@zq-silk/yui 0.13.9 → 0.14.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 +69 -428
- package/README.md +108 -298
- package/dist/agent/managedRuntimeEnvironment.js +2 -2
- package/dist/cli/commandCatalog.js +39 -77
- package/dist/cli/interactionCandidates.js +4 -4
- package/dist/cli/interactionPolicy.js +7 -10
- package/dist/cli/invocationRouter.js +1 -1
- package/dist/cli/updateCommand.js +6 -27
- package/dist/cli/updateOrchestrator.js +63 -484
- package/dist/cli/updatePorts.js +15 -333
- package/dist/cli/upgradeCommand.js +8 -65
- package/dist/cli.js +57 -242
- package/dist/commands/configCommands.js +11 -62
- package/dist/commands/executionAuditCommands.js +23 -23
- package/dist/commands/globalRoleCommands.js +2 -7
- package/dist/commands/jobCommands.js +1 -4
- package/dist/commands/projectCommands.js +5 -5
- package/dist/commands/releaseCommands.js +3 -10
- package/dist/commands/resourcesCommands.js +2 -2
- package/dist/commands/sessionCommands.js +2 -2
- package/dist/commands/taskActor.js +31 -39
- package/dist/commands/taskChangeSetCommands.js +5 -12
- package/dist/commands/taskCommands.js +464 -1249
- package/dist/commands/taskContextCommand.js +35 -36
- package/dist/commands/taskExecutionCommands.js +33 -46
- package/dist/commands/taskInputCommands.js +20 -42
- package/dist/commands/taskNextActionCommand.js +9 -9
- package/dist/commands/taskOverviewCommand.js +56 -95
- package/dist/commands/taskRoleRuntimeStatus.js +77 -107
- package/dist/commands/taskUpstreamCommands.js +3 -3
- package/dist/commands/taskWorkspaceCommands.js +7 -79
- package/dist/commands/telemetryCommands.js +32 -124
- package/dist/commands/workflowCommands.js +3 -3
- package/dist/completion/fileCompletionManager.js +1 -1
- package/dist/config/configCatalog.js +4 -6
- package/dist/config/yuiConfig.js +6 -43
- package/dist/context/dispatchContext.js +14 -30
- package/dist/context/roleSessionContext.js +2 -2
- package/dist/context/sessionBootstrapManifest.js +2 -2
- package/dist/context/{runContextPack.js → turnContextPack.js} +58 -73
- package/dist/context/turnInputContract.js +204 -0
- package/dist/context/wakeNotification.js +2 -2
- package/dist/controller/agentRuntimeObserver.js +18 -18
- package/dist/controller/clientRuntime.js +13 -20
- package/dist/controller/controller.js +89 -116
- package/dist/controller/fileSchedulerStoreAdapter.js +511 -742
- package/dist/controller/jobControl.js +17 -17
- package/dist/controller/resourceInventory.js +6 -6
- package/dist/controller/resourceInventoryLinux.js +38 -59
- package/dist/controller/resourceInventoryRpc.js +3 -3
- package/dist/controller/resourceInventoryWorker.js +1 -1
- package/dist/controller/runtime.js +46 -53
- package/dist/controller/runtimeEventInbox.js +23 -31
- package/dist/controller/runtimeEventProcessor.js +15 -15
- package/dist/controller/{runtimeHookRunFence.js → runtimeHookTurnFence.js} +87 -81
- package/dist/controller/runtimeLaunchCoordinator.js +3 -3
- package/dist/controller/runtimeObservationHook.js +11 -8
- package/dist/controller/sessionNotify.js +11 -11
- package/dist/controller/structuredProviderObservation.js +89 -16
- package/dist/coordination/workMailbox.js +309 -579
- package/dist/coordination/workMailboxQueue.js +5 -6
- package/dist/core/controllerClient.js +1 -91
- package/dist/core/controllerServer.js +3 -6
- package/dist/doctor/doctor.js +51 -314
- package/dist/execution/candidateConvergence.js +3 -3
- package/dist/execution/executionGroup.js +32 -33
- package/dist/execution/executionHealth.js +36 -38
- package/dist/execution/resourceBroker.js +12 -12
- package/dist/executor/agentExecutor.js +30 -265
- package/dist/executor/effectiveLaunch.js +9 -19
- package/dist/executor/executorRegistry.js +43 -17
- package/dist/executor/fileRoleLaunchPlanner.js +56 -56
- package/dist/executor/launchPlan.js +3 -3
- package/dist/executor/workspacePreflightClassification.js +16 -16
- package/dist/grant/capabilityGrant.js +20 -25
- package/dist/input/inputRequest.js +12 -12
- package/dist/integration/changeSet.js +9 -13
- package/dist/integration/changeSetManifest.js +1 -1
- package/dist/integration/gitIntegrationService.js +2 -2
- package/dist/integration/integrationQueueService.js +5 -21
- package/dist/integration/overlapDiagnostics.js +2 -2
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/job/jobRunner.js +1 -1
- package/dist/lifecycle/canonicalLifecycleEvent.js +25 -25
- package/dist/lifecycle/{exactRunTerminalization.js → exactTurnTerminalization.js} +116 -232
- package/dist/message/message.js +6 -6
- package/dist/observability/executionAudit.js +74 -86
- package/dist/observability/faultClassification.js +7 -24
- package/dist/observability/orchestrationMetrics.js +5 -5
- package/dist/observability/runtimeIdentity.js +34 -101
- package/dist/profile/agentProfile.js +1 -1
- package/dist/release/cliHomeReleaseFence.js +3 -3
- package/dist/release/releaseWorkflowEngine.js +6 -10
- package/dist/release/releaseWorkflowPorts.js +2 -2
- package/dist/release/workflowFileLock.js +1 -1
- package/dist/repository/checkoutSwap.js +1 -1
- package/dist/repository/gitWorkspace.js +0 -13
- package/dist/repository/project.js +1 -1
- package/dist/repository/projectMaintenanceLock.js +1 -2
- package/dist/repository/taskBaseFreshness.js +13 -13
- package/dist/repository/taskWorkspaceCoordinator.js +21 -25
- package/dist/repository/taskWorkspaceIdentity.js +8 -21
- package/dist/repository/taskWorkspacePreparer.js +63 -620
- package/dist/resources/autoResourceGc.js +3 -3
- package/dist/resources/liveReferences.js +1 -1
- package/dist/resources/resourceGc.js +1 -1
- package/dist/resources/sqliteResourceRegistry.js +1 -1
- package/dist/review/reviewDecision.js +7 -7
- package/dist/review/reviewFindingLedger.js +1 -1
- package/dist/review/reviewOutcomeClassifier.js +35 -50
- package/dist/review/reviewRound.js +14 -25
- package/dist/review/reviewerAvailability.js +4 -4
- package/dist/review/taskFinalReviewContractResolution.js +41 -0
- package/dist/role/role.js +6 -3
- package/dist/runtime/agentDriver.js +4 -0
- package/dist/runtime/agentHost.js +151 -36
- package/dist/runtime/builtinAgentDrivers.js +79 -2
- package/dist/runtime/codexAppServerRuntime.js +122 -0
- package/dist/runtime/continuationManager.js +3 -5
- package/dist/runtime/exactControlPlane.js +17 -42
- package/dist/runtime/firstProgressAdvisory.js +1 -1
- package/dist/runtime/index.js +2 -2
- package/dist/runtime/launchDiagnostics.js +2 -2
- package/dist/runtime/lifecycleReservation.js +4 -4
- package/dist/runtime/processExitObservation.js +1 -1
- package/dist/runtime/processExitOutbox.js +0 -32
- package/dist/runtime/promptEnvelope.js +9 -9
- package/dist/runtime/providerContinuation.js +2 -2
- package/dist/runtime/providerContinuationReconciliationService.js +2 -2
- package/dist/runtime/providerRuntimeIdentity.js +76 -24
- package/dist/runtime/recentTurnIds.js +38 -0
- package/dist/runtime/runtimeContinuationProjection.js +2 -2
- package/dist/runtime/runtimeHealthPolicy.js +1 -1
- package/dist/runtime/runtimeObservation.js +58 -21
- package/dist/runtime/runtimeProjection.js +19 -27
- package/dist/runtime/sessionLaunchRequest.js +2 -2
- package/dist/runtime/structuredProviderHost.js +177 -12
- package/dist/runtime/tmuxAdapters.js +46 -11
- package/dist/scheduler/activeRoleTurnDelivery.js +245 -0
- package/dist/scheduler/leaderWakeupProcessor.js +147 -445
- package/dist/scheduler/operatorEvent.js +4 -6
- package/dist/scheduler/resourceQueueProjection.js +71 -0
- package/dist/scheduler/{roleRunLiveness.js → roleTurnLiveness.js} +24 -28
- package/dist/scheduler/{roleRunStall.js → roleTurnStall.js} +162 -247
- package/dist/scheduler/taskExecutionProjection.js +99 -99
- package/dist/scheduler/taskObservabilityProjection.js +10 -10
- package/dist/scheduler/taskWake.js +4 -4
- package/dist/scheduler/wakeReason.js +6 -10
- package/dist/scheduler/wakeupQueue.js +0 -9
- package/dist/setup/setupCommand.js +2 -2
- package/dist/storage/currentTaskStore.js +46 -0
- package/dist/storage/persistenceWorker.js +1 -1
- package/dist/storage/sqliteSchema.js +81 -485
- package/dist/storage/sqliteStore.js +206 -365
- package/dist/storage/storageSchema.js +1 -15
- package/dist/storage/storageVersions.js +8 -9
- package/dist/storage/storeRpc.js +10 -34
- package/dist/storage/taskStore.js +63 -3415
- package/dist/storage/upgrade/recordVersions.js +55 -149
- package/dist/storage/upgrade/upgradeOrchestrator.js +89 -1752
- package/dist/task/completionReadiness.js +5 -5
- package/dist/task/deliveryGuard.js +10 -10
- package/dist/task/nextAction.js +74 -77
- package/dist/task/task.js +2 -4
- package/dist/task/taskRecordReference.js +3 -3
- package/dist/task/taskRecordRetirement.js +1 -1
- package/dist/telemetry/sqliteTelemetryStore.js +53 -53
- package/dist/telemetry/telemetryConfig.js +14 -14
- package/dist/telemetry/telemetryWiring.js +8 -14
- package/dist/turn/turn.js +356 -0
- package/dist/{run/runIdentity.js → turn/turnIdentity.js} +4 -4
- package/dist/verification/gateArtifactStore.js +2 -2
- package/dist/web/assets/client/app.js +1 -1
- package/dist/web/assets/client/components.js +29 -54
- package/dist/web/assets/client/i18n.js +17 -37
- package/dist/web/assets/client/view.js +37 -37
- package/dist/web/assets/shell.js +1 -1
- package/dist/web/assets/styles/cards.js +5 -5
- package/dist/web/assets/styles/widgets.js +1 -2
- package/dist/web/webSnapshot.js +65 -60
- package/dist/workItem/workItem.js +11 -11
- package/dist/workspace/workItemChangeSetManager.js +1 -1
- package/docs/task-local-identity.md +5 -5
- package/i18n/README.zh-CN.md +41 -54
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +85 -83
- package/skills/yui-operator/SKILL.md +16 -16
- package/skills/yui-reviewer/SKILL.md +10 -10
- package/skills/yui-runtime/SKILL.md +17 -18
- package/skills/yui-worker/SKILL.md +16 -18
- package/dist/context/runContextContract.js +0 -162
- package/dist/executor/turnCompletion.js +0 -126
- package/dist/review/taskFinalReviewContractEvent.js +0 -1
- package/dist/review/taskFinalReviewContractRebind.js +0 -367
- package/dist/run/agentRun.js +0 -356
- package/dist/run/rejectedYieldAttempt.js +0 -221
- package/dist/run/runControlRequest.js +0 -50
- package/dist/run/yieldReceipt.js +0 -65
- package/dist/runtime/turnCompletion.js +0 -3
- package/dist/scheduler/actionability.js +0 -323
- package/dist/scheduler/activeRoleRunDelivery.js +0 -868
- package/dist/scheduler/activeTaskProgress.js +0 -126
- package/dist/storage/compatibleTaskStore.js +0 -248
- package/dist/storage/migration/baseline.js +0 -78
- package/dist/storage/migration/classifier.js +0 -51
- package/dist/storage/migration/compatibleCodec.js +0 -53
- package/dist/storage/migration/engine.js +0 -147
- package/dist/storage/migration/index.js +0 -33
- package/dist/storage/migration/planner.js +0 -154
- package/dist/storage/migration/productionRegistry.js +0 -3931
- package/dist/storage/migration/registry.js +0 -169
- package/dist/storage/migration/report.js +0 -54
- package/dist/storage/migration/types.js +0 -31
- package/dist/storage/upgrade/homeClassification.js +0 -353
- package/dist/storage/upgrade/homeMigrationTarget.js +0 -595
- package/dist/storage/upgrade/migrationReceipt.js +0 -67
- package/dist/storage/upgrade/offlineUpgradeInventory.js +0 -453
- package/dist/storage/upgrade/productionMigrationRegistry.js +0 -6
- package/dist/storage/upgrade/pseudoLayoutRepair.js +0 -241
- package/dist/storage/upgrade/recordVersionScan.js +0 -176
- package/dist/storage/upgrade/sqliteFileSet.js +0 -50
- package/dist/storage/upgrade/sqliteMigrationTarget.js +0 -375
- package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +0 -305
- package/dist/storage/upgrade/sqliteStateMigration.js +0 -918
- package/dist/storage/upgrade/switchProgress.js +0 -80
- package/dist/storage/upgrade/upgradeReceipt.js +0 -161
- package/dist/storage/upgradeCoordination.js +0 -187
- package/dist/storage/upgradeFence.js +0 -366
- package/dist/telemetry/telemetryCompaction.js +0 -252
|
@@ -98,14 +98,14 @@ function collectTaskStatuses(store) {
|
|
|
98
98
|
return statuses;
|
|
99
99
|
}
|
|
100
100
|
/**
|
|
101
|
-
* Workspace paths claimed by active durable Jobs. An active
|
|
101
|
+
* Workspace paths claimed by active durable Jobs. An active Turn still
|
|
102
102
|
* holds its workspace even after the managed workspace record is gone, so
|
|
103
|
-
* those paths stay protected until the
|
|
103
|
+
* those paths stay protected until the Turn finishes.
|
|
104
104
|
*/
|
|
105
105
|
function collectActiveWorkspaceOwnerPaths(store) {
|
|
106
106
|
const paths = [];
|
|
107
107
|
for (const task of store.listTasks()) {
|
|
108
|
-
for (const run of store.
|
|
108
|
+
for (const run of store.listTurns(task.id)) {
|
|
109
109
|
if (run.status !== "active")
|
|
110
110
|
continue;
|
|
111
111
|
const workspace = run.workspace;
|
|
@@ -145,7 +145,7 @@ export async function scanLiveReferences(input) {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
|
-
// 6. Active durable workspace owners (e.g. an active
|
|
148
|
+
// 6. Active durable workspace owners (e.g. an active Turn launch).
|
|
149
149
|
const activeOwners = input.ports?.activeWorkspaceOwners !== undefined
|
|
150
150
|
? input.ports.activeWorkspaceOwners()
|
|
151
151
|
: [];
|
|
@@ -125,7 +125,7 @@ function classifyDiscoveredResources(discovered, registry, scan, input, home) {
|
|
|
125
125
|
}
|
|
126
126
|
/**
|
|
127
127
|
* Collect active workspace owner path fragments from durable state.
|
|
128
|
-
* These protect resources that an active Session, Job, or
|
|
128
|
+
* These protect resources that an active Session, Job, or Turn still
|
|
129
129
|
* references even when the Task itself is terminal.
|
|
130
130
|
*/
|
|
131
131
|
function collectActiveWorkspaceOwners(input) {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* The registry is GC's own state: it is not part of the aggregate and never
|
|
10
10
|
* participates in aggregate versioning. The `resource_registry` table is
|
|
11
|
-
* created by
|
|
11
|
+
* created by the current SQLite baseline.
|
|
12
12
|
*/
|
|
13
13
|
import { existsSync } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
@@ -3,7 +3,7 @@ import { isAcceptedTaskReviewBaseline } from "./reviewAcceptance.js";
|
|
|
3
3
|
import { projectReviewerAvailability } from "./reviewerAvailability.js";
|
|
4
4
|
/** Read-only facts for Leader judgment; this projection never blocks an action. */
|
|
5
5
|
export function projectReviewDecision(input) {
|
|
6
|
-
const { store, task, roles,
|
|
6
|
+
const { store, task, roles, turns, rounds, reviewConfig, currentCandidate } = input;
|
|
7
7
|
const taskRounds = rounds.filter((round) => (round.scope ?? "work-item") === "task");
|
|
8
8
|
const accepted = [...taskRounds]
|
|
9
9
|
.filter((round) => isAcceptedTaskReviewBaseline(store, round))
|
|
@@ -20,15 +20,15 @@ export function projectReviewDecision(input) {
|
|
|
20
20
|
const activeReviews = taskRounds
|
|
21
21
|
.filter((round) => (round.status === "pending" || round.status === "running"))
|
|
22
22
|
.map((round) => {
|
|
23
|
-
const
|
|
24
|
-
const workspaceRoot = round.workspace?.root ??
|
|
23
|
+
const activeTurn = turns.find((turn) => (turn.status === "active" && turn.reviewRoundId === round.id));
|
|
24
|
+
const workspaceRoot = round.workspace?.root ?? activeTurn?.workspace?.root;
|
|
25
25
|
return {
|
|
26
26
|
reviewRoundId: round.id,
|
|
27
27
|
reviewerRoleName: round.reviewerRoleName,
|
|
28
28
|
mode: round.deltaRecheck === undefined ? "full" : "delta-recheck",
|
|
29
29
|
status: round.status,
|
|
30
|
-
...(
|
|
31
|
-
startedAt:
|
|
30
|
+
...(activeTurn === undefined ? {} : { activeTurnId: activeTurn.id }),
|
|
31
|
+
startedAt: activeTurn?.createdAt ?? round.createdAt,
|
|
32
32
|
frozenCandidate: round.taskCandidate ?? null,
|
|
33
33
|
candidateRelation: candidateRelation(round.taskCandidate ?? null, currentCandidate),
|
|
34
34
|
...(workspaceRoot === undefined ? {} : { workspaceRoot })
|
|
@@ -62,9 +62,9 @@ export function projectReviewDecision(input) {
|
|
|
62
62
|
reviewerRoleName,
|
|
63
63
|
status: "busy",
|
|
64
64
|
phase: availability.phase,
|
|
65
|
-
...(availability.
|
|
65
|
+
...(availability.activeTurnId === undefined
|
|
66
66
|
? {}
|
|
67
|
-
: {
|
|
67
|
+
: { activeTurnId: availability.activeTurnId }),
|
|
68
68
|
...(availability.activeReviewRoundId === undefined
|
|
69
69
|
? {}
|
|
70
70
|
: { activeReviewRoundId: availability.activeReviewRoundId }),
|
|
@@ -505,7 +505,7 @@ export function buildTaskFinalReviewFindingContext(store, taskId, candidate) {
|
|
|
505
505
|
ledgerContext = renderFindingLedgerContext(summarizeFindingLedger(store, taskId));
|
|
506
506
|
}
|
|
507
507
|
catch {
|
|
508
|
-
ledgerContext = "Finding ledger: unavailable (
|
|
508
|
+
ledgerContext = "Finding ledger: unavailable (a current SQLite Home is required).";
|
|
509
509
|
}
|
|
510
510
|
const lines = [
|
|
511
511
|
"Review convergence context:",
|
|
@@ -1,27 +1,25 @@
|
|
|
1
|
-
import { matchYieldReceipt } from "../run/yieldReceipt.js";
|
|
2
1
|
import { isTaskRecordRetired, operationalTaskRecords } from "../task/taskRecordRetirement.js";
|
|
3
2
|
const INFRA_SIGNATURES = [
|
|
4
3
|
{ kind: "session-not-stopped", pattern: /session must be stopped before workspace migration/iu },
|
|
5
|
-
{ kind: "
|
|
4
|
+
{ kind: "turn-start", pattern: /role turn could not start|could not start (?:the )?(?:reviewer|role) turn/iu },
|
|
6
5
|
{ kind: "storage-lock", pattern: /\.state\.lock|state lock|lock timeout|storage lock/iu },
|
|
7
6
|
{ kind: "tmux-exit", pattern: /tmux[^\n]{0,80}(?:exited|exit|died|vanished)|pane (?:exited|died)/iu },
|
|
8
|
-
{ kind: "
|
|
9
|
-
{ kind: "run-identity", pattern: /wrong run id|unknown run id|run id (?:is )?(?:invalid|unknown|mismatch)/iu },
|
|
7
|
+
{ kind: "turn-identity", pattern: /wrong turn id|unknown turn id|turn id (?:is )?(?:invalid|unknown|mismatch)/iu },
|
|
10
8
|
{ kind: "policy", pattern: /cyber_?policy|policy denial|permission denied by policy/iu },
|
|
11
9
|
{ kind: "baseline-contamination", pattern: /cross[-\s]?baseline|baseline pollution|contaminated baseline|wrong base sha/iu },
|
|
12
|
-
{ kind: "context-load", pattern: /(?:
|
|
10
|
+
{ kind: "context-load", pattern: /(?:turn )?(?:context|context pack) load (?:failed|unavailable|unauthorized|stale|mismatched|malformed)/iu },
|
|
13
11
|
{ kind: "workspace-binding", pattern: /workspace is not the durable owner|workspace-binding failure/iu }
|
|
14
12
|
];
|
|
15
13
|
/** Classify one terminal Round without rewriting it. */
|
|
16
14
|
export function classifyReviewRoundOutcome(round, evidence) {
|
|
17
15
|
if (round.status !== "completed" && round.status !== "failed")
|
|
18
16
|
return null;
|
|
19
|
-
if (evidence !== undefined && round.
|
|
20
|
-
&& isTaskRecordRetired(evidence.listEvents(round.taskId), "
|
|
17
|
+
if (evidence !== undefined && round.reviewerTurnId !== undefined
|
|
18
|
+
&& isTaskRecordRetired(evidence.listEvents(round.taskId), "turn", round.reviewerTurnId)) {
|
|
21
19
|
return {
|
|
22
20
|
kind: "non-semantic",
|
|
23
|
-
infraKind: "
|
|
24
|
-
reason: `Reviewer
|
|
21
|
+
infraKind: "turn-identity",
|
|
22
|
+
reason: `Reviewer Turn ${round.reviewerTurnId} was retired from operational evidence.`
|
|
25
23
|
};
|
|
26
24
|
}
|
|
27
25
|
const infraKind = classifyInfraKind(`${round.summary ?? ""}\n${round.report ?? ""}`);
|
|
@@ -46,7 +44,7 @@ export function classifyReviewRoundOutcome(round, evidence) {
|
|
|
46
44
|
return {
|
|
47
45
|
kind: "ambiguous",
|
|
48
46
|
infraKind,
|
|
49
|
-
reason: "Completed Round claims an infrastructure failure but corroborating
|
|
47
|
+
reason: "Completed Round claims an infrastructure failure but corroborating Turn/Event evidence was not supplied."
|
|
50
48
|
};
|
|
51
49
|
}
|
|
52
50
|
const corroborationFailure = completedInfrastructureCorroborationFailure(round, evidence);
|
|
@@ -54,7 +52,7 @@ export function classifyReviewRoundOutcome(round, evidence) {
|
|
|
54
52
|
? {
|
|
55
53
|
kind: "non-semantic",
|
|
56
54
|
infraKind,
|
|
57
|
-
reason: "Completed Round and
|
|
55
|
+
reason: "Completed Round and Turn agree on an explicit pre-review infrastructure failure."
|
|
58
56
|
}
|
|
59
57
|
: {
|
|
60
58
|
kind: "ambiguous",
|
|
@@ -90,17 +88,17 @@ function failedRoundSemanticEvidence(round, evidence) {
|
|
|
90
88
|
|| (lane.result?.evidence ?? []).length > 0
|
|
91
89
|
|| lane.result?.evidenceCommit !== undefined
|
|
92
90
|
|| lane.result?.gitSnapshot !== undefined
|
|
93
|
-
|| lane.status === "yielded"
|
|
94
91
|
|| lane.status === "completed"));
|
|
95
92
|
if (semanticLane !== undefined)
|
|
96
93
|
return `Reviewer Lane ${semanticLane.id} delivered semantic evidence.`;
|
|
97
94
|
if (evidence !== undefined) {
|
|
98
95
|
const events = evidence.listEvents(round.taskId);
|
|
99
|
-
const reviewRun = operationalTaskRecords(evidence.
|
|
96
|
+
const reviewRun = operationalTaskRecords(evidence.listTurns(round.taskId), events, "turn").find((run) => (run.purpose === "review"
|
|
100
97
|
&& run.reviewRoundId === round.id
|
|
101
|
-
&& (run.status === "
|
|
98
|
+
&& (run.status === "completed"
|
|
99
|
+
|| runtimeFailureSummaryHasReviewerOutput(run.result?.output ?? ""))));
|
|
102
100
|
if (reviewRun !== undefined)
|
|
103
|
-
return `Reviewer
|
|
101
|
+
return `Reviewer Turn ${reviewRun.id} records Reviewer output.`;
|
|
104
102
|
const finding = evidence.listReviewFindings(round.taskId).find((entry) => (entry.firstReviewRoundId === round.id || entry.lastReviewRoundId === round.id));
|
|
105
103
|
if (finding !== undefined)
|
|
106
104
|
return `Review finding ${finding.id} references the Round.`;
|
|
@@ -140,7 +138,7 @@ function completedInfrastructureCorroborationFailure(round, store) {
|
|
|
140
138
|
|| lane.result?.gitSnapshot !== undefined) {
|
|
141
139
|
return `Reviewer Lane ${lane.id} delivered semantic evidence.`;
|
|
142
140
|
}
|
|
143
|
-
if (lane.status === "
|
|
141
|
+
if (lane.status === "completed") {
|
|
144
142
|
if (lane.result === undefined
|
|
145
143
|
|| lane.result.summary !== round.summary
|
|
146
144
|
|| lane.result.report !== round.report
|
|
@@ -153,36 +151,23 @@ function completedInfrastructureCorroborationFailure(round, store) {
|
|
|
153
151
|
}
|
|
154
152
|
}
|
|
155
153
|
const allEvents = store.listEvents(round.taskId);
|
|
156
|
-
const runs = operationalTaskRecords(store.
|
|
154
|
+
const runs = operationalTaskRecords(store.listTurns(round.taskId), allEvents, "turn").filter((run) => (run.purpose === "review" && run.reviewRoundId === round.id));
|
|
157
155
|
const active = runs.find(({ status }) => status === "active");
|
|
158
156
|
if (active !== undefined)
|
|
159
|
-
return `Reviewer
|
|
160
|
-
const output = runs.find((run) => (run.status === "failed" && runtimeFailureSummaryHasReviewerOutput(run.
|
|
157
|
+
return `Reviewer Turn ${active.id} is still active.`;
|
|
158
|
+
const output = runs.find((run) => (run.status === "failed" && runtimeFailureSummaryHasReviewerOutput(run.result?.output ?? "")));
|
|
161
159
|
if (output !== undefined)
|
|
162
|
-
return `Reviewer
|
|
163
|
-
const
|
|
164
|
-
if (round.
|
|
165
|
-
||
|
|
166
|
-
||
|
|
167
|
-
return "Completed Round lacks one exact
|
|
168
|
-
}
|
|
169
|
-
const run =
|
|
160
|
+
return `Reviewer Turn ${output.id} records Reviewer output.`;
|
|
161
|
+
const completed = runs.filter(({ status }) => status === "completed");
|
|
162
|
+
if (round.reviewerTurnId === undefined
|
|
163
|
+
|| completed.length !== 1
|
|
164
|
+
|| completed[0].id !== round.reviewerTurnId) {
|
|
165
|
+
return "Completed Round lacks one exact completed Reviewer Turn.";
|
|
166
|
+
}
|
|
167
|
+
const run = completed[0];
|
|
170
168
|
if (run.roleName !== round.reviewerRoleName
|
|
171
|
-
|| run.
|
|
172
|
-
|
|
173
|
-
return `Reviewer Run ${run.id} does not match the non-semantic Round receipt.`;
|
|
174
|
-
}
|
|
175
|
-
const receiptMatch = matchYieldReceipt(run.yieldReceipt, {
|
|
176
|
-
status: "yielded",
|
|
177
|
-
summary: round.summary ?? "",
|
|
178
|
-
reviewResult: {
|
|
179
|
-
report: round.report ?? "",
|
|
180
|
-
checks: round.checks ?? [],
|
|
181
|
-
evidenceCommit: round.reviewBaseCommit
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
if (receiptMatch?.kind !== "replayed") {
|
|
185
|
-
return `Reviewer Run ${run.id} yield receipt does not cover the Round outcome.`;
|
|
169
|
+
|| run.result?.output !== round.summary) {
|
|
170
|
+
return `Reviewer Turn ${run.id} does not match the non-semantic Round result.`;
|
|
186
171
|
}
|
|
187
172
|
const finding = store.listReviewFindings(round.taskId).find((entry) => (entry.firstReviewRoundId === round.id || entry.lastReviewRoundId === round.id));
|
|
188
173
|
if (finding !== undefined)
|
|
@@ -204,12 +189,12 @@ function explicitCompletedReviewInfrastructureFailure(summary, round) {
|
|
|
204
189
|
if (exactCompletedReviewInfrastructureFailureReport(summary))
|
|
205
190
|
return true;
|
|
206
191
|
const report = summary.trim();
|
|
207
|
-
if (report === `Role
|
|
208
|
-
|| (round.
|
|
209
|
-
&& report === `Review
|
|
192
|
+
if (report === `Role Turn workspace is not the durable owner: ${round.taskId}/${round.reviewerRoleName}.`
|
|
193
|
+
|| (round.reviewerTurnId !== undefined
|
|
194
|
+
&& report === `Review Turn workspace is not the durable owner: ${round.reviewerTurnId}.`)) {
|
|
210
195
|
return true;
|
|
211
196
|
}
|
|
212
|
-
return /^(?:
|
|
197
|
+
return /^(?:Turn )?(?:Context|Context Pack) load (?:failed|unavailable|unauthorized|stale|mismatched|malformed)(?:: (?:failure|mismatch|unavailable|unauthorized|stale|mismatched|malformed))?\.?$/iu
|
|
213
198
|
.test(report);
|
|
214
199
|
}
|
|
215
200
|
function exactCompletedReviewInfrastructureFailureReport(summary) {
|
|
@@ -217,9 +202,9 @@ function exactCompletedReviewInfrastructureFailureReport(summary) {
|
|
|
217
202
|
const envelope = [
|
|
218
203
|
/^# Review result: (?:context-load|workspace-binding) failure$/u,
|
|
219
204
|
/^$/u,
|
|
220
|
-
/^The assigned
|
|
205
|
+
/^The assigned Turn context could not be safely matched to this native session, so no candidate review was performed\.$/u,
|
|
221
206
|
/^$/u,
|
|
222
|
-
/^-
|
|
207
|
+
/^- Turn: `[^`\r\n]+`$/u,
|
|
223
208
|
/^- ReviewRound: `[^`\r\n]+`$/u,
|
|
224
209
|
/^- Review base commit: `[0-9a-f]{40}`$/u,
|
|
225
210
|
/^- Frozen target: `[^`\r\n]+`$/u,
|
|
@@ -236,14 +221,14 @@ function exactCompletedReviewInfrastructureFailureReport(summary) {
|
|
|
236
221
|
/^$/u,
|
|
237
222
|
/^## Checks actually run$/u,
|
|
238
223
|
/^$/u,
|
|
239
|
-
/^- Exact Context API load: passed for Task\/
|
|
224
|
+
/^- Exact Context API load: passed for Task\/Turn\/Role\/purpose\/subject\/snapshot\/adapter\.$/u,
|
|
240
225
|
/^- Workspace binding verification: failed\.$/u,
|
|
241
226
|
/^- Candidate build\/tests\/package checks: not run\.$/u,
|
|
242
227
|
/^- Real-provider E2E: not run and not authorized\.$/u,
|
|
243
228
|
/^$/u,
|
|
244
229
|
/^## Required next action$/u,
|
|
245
230
|
/^$/u,
|
|
246
|
-
/^Attach the native Reviewer session to the exact workspace recorded by the Context Pack, or issue a fresh internally consistent Review
|
|
231
|
+
/^Attach the native Reviewer session to the exact workspace recorded by the Context Pack, or issue a fresh internally consistent Review Turn\/Context Pack\. Then perform the complete bounded Task-final review at the frozen head\.$/u
|
|
247
232
|
];
|
|
248
233
|
return lines.length === envelope.length
|
|
249
234
|
&& envelope.every((pattern, index) => pattern.test(lines[index]));
|
|
@@ -78,7 +78,7 @@ export function attachReviewRoundWorkspace(round, workspace) {
|
|
|
78
78
|
}
|
|
79
79
|
return validateReviewRound({ ...round, workspace });
|
|
80
80
|
}
|
|
81
|
-
export function startReviewRound(round,
|
|
81
|
+
export function startReviewRound(round, reviewerTurnId) {
|
|
82
82
|
validateReviewRound(round);
|
|
83
83
|
if (round.status !== "pending") {
|
|
84
84
|
throw new Error(`ReviewRound cannot start from ${round.status}: ${round.id}.`);
|
|
@@ -88,7 +88,7 @@ export function startReviewRound(round, reviewerRunId) {
|
|
|
88
88
|
}
|
|
89
89
|
return validateReviewRound({
|
|
90
90
|
...round,
|
|
91
|
-
|
|
91
|
+
reviewerTurnId: requireIdentity(reviewerTurnId, "Reviewer Turn id"),
|
|
92
92
|
status: "running"
|
|
93
93
|
});
|
|
94
94
|
}
|
|
@@ -134,7 +134,7 @@ export function finishReviewRound(round, status, summary, now, result = {}) {
|
|
|
134
134
|
}
|
|
135
135
|
/**
|
|
136
136
|
* Issue 06: retry a failed Task-final execution attempt under the same semantic
|
|
137
|
-
* Round identity.
|
|
137
|
+
* Round identity. Turn history remains the attempt trail; the Round itself
|
|
138
138
|
* returns to pending so infrastructure retries do not manufacture a new
|
|
139
139
|
* semantic ReviewRound or duplicate findings.
|
|
140
140
|
*/
|
|
@@ -153,7 +153,6 @@ export function retryTaskReviewRound(round, requestedBy, executionLaneId) {
|
|
|
153
153
|
schemaVersion: round.schemaVersion,
|
|
154
154
|
id: round.id,
|
|
155
155
|
taskId: round.taskId,
|
|
156
|
-
...(round.legacyAnchor === undefined ? {} : { legacyAnchor: round.legacyAnchor }),
|
|
157
156
|
reviewerRoleName: round.reviewerRoleName,
|
|
158
157
|
reviewBaseCommit: round.reviewBaseCommit,
|
|
159
158
|
scope: "task",
|
|
@@ -177,7 +176,7 @@ export function retryTaskReviewRound(round, requestedBy, executionLaneId) {
|
|
|
177
176
|
deletedLines: round.deltaRecheck.deletedLines
|
|
178
177
|
})
|
|
179
178
|
}),
|
|
180
|
-
// Keep the historical attempt Group and Lane addressable from
|
|
179
|
+
// Keep the historical attempt Group and Lane addressable from Turn
|
|
181
180
|
// history while resetting the Lane for another dispatch attempt.
|
|
182
181
|
...(retryExecutionGroup === undefined ? {} : { executionGroup: retryExecutionGroup }),
|
|
183
182
|
requestedBy: validateReviewRequestSource(requestedBy),
|
|
@@ -187,15 +186,15 @@ export function retryTaskReviewRound(round, requestedBy, executionLaneId) {
|
|
|
187
186
|
});
|
|
188
187
|
}
|
|
189
188
|
/** Keep a running panel Round active while retrying only its exact failed Lane. */
|
|
190
|
-
export function retryRunningReviewExecutionLane(round, executionLaneId,
|
|
189
|
+
export function retryRunningReviewExecutionLane(round, executionLaneId, turnId, now) {
|
|
191
190
|
validateReviewRound(round);
|
|
192
191
|
if (round.status !== "running" || round.executionGroup === undefined) {
|
|
193
192
|
throw new Error(`ReviewRound ${round.id} has no running ExecutionGroup.`);
|
|
194
193
|
}
|
|
195
194
|
const lane = round.executionGroup.lanes.find(({ id }) => id === executionLaneId);
|
|
196
|
-
if (lane === undefined || lane.status !== "failed" || lane.
|
|
195
|
+
if (lane === undefined || lane.status !== "failed" || lane.turnId !== turnId) {
|
|
197
196
|
throw new Error(`Review retry does not target the current failed Lane attempt: `
|
|
198
|
-
+ `${round.executionGroup.id}/${executionLaneId}/${
|
|
197
|
+
+ `${round.executionGroup.id}/${executionLaneId}/${turnId}.`);
|
|
199
198
|
}
|
|
200
199
|
return updateReviewExecutionGroup(round, retryReviewExecutionGroup(round, executionLaneId, now));
|
|
201
200
|
}
|
|
@@ -219,7 +218,7 @@ function retryReviewExecutionGroup(round, executionLaneId, retryAt) {
|
|
|
219
218
|
});
|
|
220
219
|
}
|
|
221
220
|
/** Accepts the Reviewer's complete report and extracts only optional known evidence. */
|
|
222
|
-
export function
|
|
221
|
+
export function parseReviewResultReport(value) {
|
|
223
222
|
const report = requireText(value, "Review report");
|
|
224
223
|
let parsed;
|
|
225
224
|
try {
|
|
@@ -372,15 +371,6 @@ export function validateReviewRound(round) {
|
|
|
372
371
|
if (round.workItemId !== undefined || round.candidateId !== undefined) {
|
|
373
372
|
throw new Error(`Task ReviewRound cannot use a WorkItem Candidate anchor: ${round.id}.`);
|
|
374
373
|
}
|
|
375
|
-
if (round.legacyAnchor !== undefined) {
|
|
376
|
-
validateTaskRecordReference({
|
|
377
|
-
taskId: round.taskId,
|
|
378
|
-
localId: round.legacyAnchor.workItemId
|
|
379
|
-
}, "workItem");
|
|
380
|
-
if (!/^candidate-[1-9]\d*$/.test(round.legacyAnchor.candidateId)) {
|
|
381
|
-
throw new Error(`Legacy Candidate local id is invalid: ${round.legacyAnchor.candidateId}.`);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
374
|
if (round.taskCandidate === undefined) {
|
|
385
375
|
throw new Error(`Task ReviewRound requires a frozen Task candidate: ${round.id}.`);
|
|
386
376
|
}
|
|
@@ -407,8 +397,7 @@ export function validateReviewRound(round) {
|
|
|
407
397
|
throw new Error(`Candidate local id is invalid: ${round.candidateId}.`);
|
|
408
398
|
}
|
|
409
399
|
if (round.taskCandidate !== undefined
|
|
410
|
-
|| round.taskFinalReviewContract !== undefined
|
|
411
|
-
|| round.legacyAnchor !== undefined) {
|
|
400
|
+
|| round.taskFinalReviewContract !== undefined) {
|
|
412
401
|
throw new Error(`WorkItem ReviewRound cannot carry Task-final metadata: ${round.id}.`);
|
|
413
402
|
}
|
|
414
403
|
}
|
|
@@ -424,11 +413,11 @@ export function validateReviewRound(round) {
|
|
|
424
413
|
}
|
|
425
414
|
validateDeltaRecheckRecord(round.deltaRecheck);
|
|
426
415
|
}
|
|
427
|
-
if (round.
|
|
416
|
+
if (round.reviewerTurnId !== undefined) {
|
|
428
417
|
validateTaskRecordReference({
|
|
429
418
|
taskId: round.taskId,
|
|
430
|
-
localId: round.
|
|
431
|
-
}, "
|
|
419
|
+
localId: round.reviewerTurnId
|
|
420
|
+
}, "turn");
|
|
432
421
|
}
|
|
433
422
|
if (round.workspace !== undefined)
|
|
434
423
|
validateReviewWorkspace(round, round.workspace);
|
|
@@ -456,8 +445,8 @@ export function validateReviewRound(round) {
|
|
|
456
445
|
throw new Error("An active ReviewRound cannot have terminal metadata.");
|
|
457
446
|
}
|
|
458
447
|
if (round.status === "running"
|
|
459
|
-
&& (round.
|
|
460
|
-
throw new Error("A running ReviewRound requires a Reviewer
|
|
448
|
+
&& (round.reviewerTurnId === undefined || round.workspace === undefined)) {
|
|
449
|
+
throw new Error("A running ReviewRound requires a Reviewer Turn and workspace.");
|
|
461
450
|
}
|
|
462
451
|
if (round.workspaceDisposition !== undefined) {
|
|
463
452
|
if (!terminal || round.workspace === undefined) {
|
|
@@ -2,14 +2,14 @@ import { nextPendingBatch, mailboxHasWork } from "../coordination/workMailbox.js
|
|
|
2
2
|
import { runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
|
|
3
3
|
/** One authoritative read-only projection for a Task Reviewer Role slot. */
|
|
4
4
|
export function projectReviewerAvailability(store, taskId, reviewerRoleName) {
|
|
5
|
-
const active = store.
|
|
6
|
-
?? store.
|
|
5
|
+
const active = store.getActiveTurn(taskId, reviewerRoleName)
|
|
6
|
+
?? store.listTurns(taskId).find((run) => (run.roleName === reviewerRoleName && run.status === "active"));
|
|
7
7
|
if (active !== null && active !== undefined) {
|
|
8
8
|
return {
|
|
9
9
|
kind: "busy",
|
|
10
10
|
reviewerRoleName,
|
|
11
|
-
phase: "active-
|
|
12
|
-
|
|
11
|
+
phase: "active-turn",
|
|
12
|
+
activeTurnId: active.id,
|
|
13
13
|
...(active.reviewRoundId === undefined
|
|
14
14
|
? {}
|
|
15
15
|
: { activeReviewRoundId: active.reviewRoundId }),
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { requireIdentity } from "../domain/validation.js";
|
|
2
|
+
import { sameTaskFinalReviewContract, validateTaskFinalReviewContract } from "./taskFinalReviewContract.js";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the one Task-final Review contract recorded by current Candidate and
|
|
5
|
+
* ReviewRound evidence. The contract is immutable once established; all later
|
|
6
|
+
* observations must match it exactly.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveRecordedTaskFinalReviewContract(taskId, workItems, reviewRounds) {
|
|
9
|
+
const normalizedTaskId = requireIdentity(taskId, "Task final-review contract Task id");
|
|
10
|
+
const observations = [
|
|
11
|
+
...workItems.flatMap((item) => item.candidates.flatMap((candidate) => (candidate.taskFinalReviewContract === undefined
|
|
12
|
+
? []
|
|
13
|
+
: [{
|
|
14
|
+
contract: candidate.taskFinalReviewContract,
|
|
15
|
+
source: `Candidate ${item.id}/${candidate.id}`
|
|
16
|
+
}]))),
|
|
17
|
+
...reviewRounds.flatMap((round) => ((round.scope ?? "work-item") !== "task"
|
|
18
|
+
|| round.taskFinalReviewContract === undefined
|
|
19
|
+
? []
|
|
20
|
+
: [{
|
|
21
|
+
contract: round.taskFinalReviewContract,
|
|
22
|
+
source: `ReviewRound ${round.id}`
|
|
23
|
+
}]))
|
|
24
|
+
];
|
|
25
|
+
if (observations.length === 0)
|
|
26
|
+
return undefined;
|
|
27
|
+
const effective = validateTaskFinalReviewContract(observations[0].contract);
|
|
28
|
+
if (effective.taskId !== normalizedTaskId) {
|
|
29
|
+
throw new Error(`${observations[0].source} carries a final-review contract for another Task.`);
|
|
30
|
+
}
|
|
31
|
+
for (const observation of observations.slice(1)) {
|
|
32
|
+
const contract = validateTaskFinalReviewContract(observation.contract);
|
|
33
|
+
if (contract.taskId !== normalizedTaskId) {
|
|
34
|
+
throw new Error(`${observation.source} carries a final-review contract for another Task.`);
|
|
35
|
+
}
|
|
36
|
+
if (!sameTaskFinalReviewContract(contract, effective)) {
|
|
37
|
+
throw new Error(`${observation.source} conflicts with the Task final-review contract.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return Object.freeze({ effective });
|
|
41
|
+
}
|
package/dist/role/role.js
CHANGED
|
@@ -93,7 +93,7 @@ export function switchActiveRoleAgent(role, sessions, targetAgentId, runtime, no
|
|
|
93
93
|
: updateGlobalRole(role, { activeAgentId: normalizedTarget }, now);
|
|
94
94
|
// A running process keeps its immutable effective identity. The desired
|
|
95
95
|
// switch becomes visible only when the next launch is planned.
|
|
96
|
-
const updatedSessions = runtime.
|
|
96
|
+
const updatedSessions = runtime.activeTurn || runtime.nativeProcessRunning
|
|
97
97
|
? sessions
|
|
98
98
|
: {
|
|
99
99
|
...sessions,
|
|
@@ -126,8 +126,11 @@ export function unbindRoleAgent(role, sessions, agentId, now) {
|
|
|
126
126
|
const taskSessions = sessions.owner.scope === "task"
|
|
127
127
|
? sessions
|
|
128
128
|
: null;
|
|
129
|
-
if (taskSessions?.
|
|
130
|
-
|
|
129
|
+
if (taskSessions?.providerBinding?.turn !== null
|
|
130
|
+
&& taskSessions?.providerBinding?.turn !== undefined
|
|
131
|
+
&& taskSessions.activeAgentId === normalizedAgentId
|
|
132
|
+
&& ["submitting", "accepted", "running"].includes(taskSessions.providerBinding.turn.status)) {
|
|
133
|
+
throw new Error(`Cannot unbind Role Agent with an active Turn: ${normalizedAgentId}.`);
|
|
131
134
|
}
|
|
132
135
|
const targetSession = sessions.sessions[normalizedAgentId];
|
|
133
136
|
if (targetSession !== undefined && targetSession.status === "active") {
|
|
@@ -92,6 +92,9 @@ export function validateAgentDriverCapabilities(input) {
|
|
|
92
92
|
if (!["exact", "partial", "unavailable"].includes(observation.turnLifecycle)) {
|
|
93
93
|
throw new Error("Agent Driver turn lifecycle capability is invalid.");
|
|
94
94
|
}
|
|
95
|
+
if (!["exact", "partial", "unavailable"].includes(observation.goalLifecycle)) {
|
|
96
|
+
throw new Error("Agent Driver Goal lifecycle capability is invalid.");
|
|
97
|
+
}
|
|
95
98
|
if (!USAGE_MODES.includes(observation.usage)) {
|
|
96
99
|
throw new Error("Agent Driver usage capability is invalid.");
|
|
97
100
|
}
|
|
@@ -163,6 +166,7 @@ export function validateAgentDriverCapabilities(input) {
|
|
|
163
166
|
preInputReadiness: observation.preInputReadiness,
|
|
164
167
|
promptAcceptance: observation.promptAcceptance,
|
|
165
168
|
turnLifecycle: observation.turnLifecycle,
|
|
169
|
+
goalLifecycle: observation.goalLifecycle,
|
|
166
170
|
operations: Object.freeze(uniqueMembers(observation.operations, OPERATIONS, "Agent Driver operation")),
|
|
167
171
|
waiting: Object.freeze(uniqueMembers(observation.waiting, WAIT_REASONS, "Agent Driver wait reason")),
|
|
168
172
|
usage: observation.usage,
|