@sema-agent/client-core 0.77.1 → 0.77.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/CHANGELOG.md +13 -1
- package/README.md +5 -4
- package/dist/abortableSleep.d.ts +0 -28
- package/dist/abortableSleep.js +0 -28
- package/dist/adapt/arms.d.ts +0 -46
- package/dist/adapt/arms.js +9 -544
- package/dist/adapt/ids.d.ts +0 -58
- package/dist/adapt/ids.js +0 -63
- package/dist/adapt/instanceLedger.d.ts +0 -25
- package/dist/adapt/instanceLedger.js +0 -20
- package/dist/adapt/panelTasks.d.ts +0 -69
- package/dist/adapt/panelTasks.js +0 -95
- package/dist/adapt/textSegmentAuthority.d.ts +1 -137
- package/dist/adapt/textSegmentAuthority.js +0 -54
- package/dist/adapt/textStream.d.ts +0 -252
- package/dist/adapt/textStream.js +2 -281
- package/dist/adapt/toolCards.d.ts +0 -46
- package/dist/adapt/toolCards.js +0 -23
- package/dist/adapt/turnFlags.d.ts +0 -54
- package/dist/adapt/turnFlags.js +1 -17
- package/dist/adapt/wireShapes.d.ts +0 -92
- package/dist/adapt/wireShapes.js +0 -83
- package/dist/adapt.d.ts +0 -55
- package/dist/adapt.js +1 -120
- package/dist/adapter/activeRunSelfHeal.d.ts +22 -515
- package/dist/adapter/activeRunSelfHeal.js +10 -625
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -305
- package/dist/adapter/downstream/eventToSdkMessage.js +2 -867
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +2 -314
- package/dist/adapter/downstream/terminalToSdkResult.js +13 -560
- package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +0 -95
- package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -31
- package/dist/adapter/runStream.d.ts +0 -206
- package/dist/adapter/runStream.js +6 -596
- package/dist/adapter/types.d.ts +0 -111
- package/dist/adapter/types.js +0 -29
- package/dist/agentSession/backgroundView.d.ts +0 -106
- package/dist/agentSession/backgroundView.js +3 -49
- package/dist/agentSession/contract.d.ts +0 -98
- package/dist/agentSession/contract.js +0 -12
- package/dist/agentsWireCaps.d.ts +0 -72
- package/dist/agentsWireCaps.js +4 -72
- package/dist/approvalsStreamLiveCapability.d.ts +0 -25
- package/dist/approvalsStreamLiveCapability.js +0 -31
- package/dist/argvFlagValue.d.ts +0 -33
- package/dist/argvFlagValue.js +3 -35
- package/dist/attachmentsWireCaps.d.ts +0 -127
- package/dist/attachmentsWireCaps.js +0 -144
- package/dist/autoModeUnavailable.d.ts +0 -120
- package/dist/autoModeUnavailable.js +0 -144
- package/dist/classifierStatus.d.ts +0 -72
- package/dist/classifierStatus.js +0 -167
- package/dist/classifierVerdictWire.d.ts +0 -54
- package/dist/classifierVerdictWire.js +0 -133
- package/dist/clientContextWireCaps.d.ts +0 -37
- package/dist/clientContextWireCaps.js +0 -36
- package/dist/clientSlice.d.ts +0 -63
- package/dist/clientSlice.js +0 -45
- package/dist/cloudConfigWireCaps.d.ts +0 -86
- package/dist/cloudConfigWireCaps.js +2 -65
- package/dist/compensations.d.ts +0 -52
- package/dist/compensations.js +2 -63
- package/dist/controlRouter.d.ts +2 -208
- package/dist/controlRouter.js +1 -129
- package/dist/coreValuePorts.d.ts +0 -84
- package/dist/coreValuePorts.js +0 -29
- package/dist/decideReceipt.d.ts +0 -110
- package/dist/decideReceipt.js +0 -84
- package/dist/detachWire.d.ts +0 -130
- package/dist/detachWire.js +1 -130
- package/dist/deviceExecutorManagementCapability.d.ts +2 -35
- package/dist/deviceExecutorManagementCapability.js +1 -37
- package/dist/diagnostics.d.ts +0 -8
- package/dist/diagnostics.js +0 -8
- package/dist/diff/patch.d.ts +0 -17
- package/dist/diff/patch.js +0 -19
- package/dist/effectiveFacts.d.ts +0 -40
- package/dist/effectiveFacts.js +0 -22
- package/dist/effortWire.d.ts +0 -11
- package/dist/effortWire.js +0 -12
- package/dist/engineAgentPanelStore.d.ts +0 -169
- package/dist/engineAgentPanelStore.js +13 -293
- package/dist/engineCapReader.d.ts +0 -62
- package/dist/engineCapReader.js +1 -43
- package/dist/engineCapsCache.d.ts +0 -177
- package/dist/engineCapsCache.js +0 -199
- package/dist/engineCapsGenerationGuard.d.ts +0 -2
- package/dist/engineCapsGenerationGuard.js +0 -11
- package/dist/engineErrorCodes.d.ts +1 -316
- package/dist/engineErrorCodes.js +0 -427
- package/dist/engineHttpTools.d.ts +0 -29
- package/dist/engineHttpTools.js +0 -29
- package/dist/engineIdentity.d.ts +0 -83
- package/dist/engineIdentity.js +0 -88
- package/dist/engineInlineTaskStats.d.ts +0 -57
- package/dist/engineInlineTaskStats.js +1 -42
- package/dist/engineNoticeCodes.d.ts +0 -190
- package/dist/engineNoticeCodes.js +0 -182
- package/dist/engineSessionParam.d.ts +0 -30
- package/dist/engineSessionParam.js +0 -52
- package/dist/engineToolLabelStore.d.ts +0 -29
- package/dist/engineToolLabelStore.js +0 -31
- package/dist/engineWireSdk.d.ts +0 -90
- package/dist/engineWireSdk.js +0 -74
- package/dist/engineWireTarget.d.ts +0 -14
- package/dist/engineWireTarget.js +0 -39
- package/dist/env/localeGeo.d.ts +0 -12
- package/dist/env/localeGeo.js +2 -77
- package/dist/env/localeTag.d.ts +0 -34
- package/dist/env/localeTag.js +0 -32
- package/dist/env/uiLanguage.d.ts +0 -13
- package/dist/env/uiLanguage.js +0 -25
- package/dist/envFlag.d.ts +0 -37
- package/dist/envFlag.js +0 -40
- package/dist/executionLaneCapability.d.ts +0 -48
- package/dist/executionLaneCapability.js +0 -54
- package/dist/finalVerifyWire.d.ts +0 -67
- package/dist/finalVerifyWire.js +3 -43
- package/dist/fleet/fleetLedger.d.ts +0 -308
- package/dist/fleet/fleetLedger.js +10 -429
- package/dist/fleet/fleetProjection.d.ts +0 -240
- package/dist/fleet/fleetProjection.js +0 -189
- package/dist/fleet/fleetRowAgentType.d.ts +0 -6
- package/dist/fleet/fleetRowAgentType.js +1 -32
- package/dist/fleet/workflowSizeWarning.d.ts +0 -47
- package/dist/fleet/workflowSizeWarning.js +1 -46
- package/dist/fleetAgentPanelProjection.d.ts +0 -48
- package/dist/fleetAgentPanelProjection.js +8 -173
- package/dist/fleetTaskDesc.d.ts +0 -39
- package/dist/fleetTaskDesc.js +0 -69
- package/dist/forkWireCaps.d.ts +0 -23
- package/dist/forkWireCaps.js +1 -24
- package/dist/gateOutcome.d.ts +0 -140
- package/dist/gateOutcome.js +0 -85
- package/dist/gateVocabulary.d.ts +0 -114
- package/dist/gateVocabulary.js +1 -161
- package/dist/goalStopHook.d.ts +0 -127
- package/dist/goalStopHook.js +0 -178
- package/dist/headlessPermissionModeWire.d.ts +0 -76
- package/dist/headlessPermissionModeWire.js +1 -155
- package/dist/headlessReconnectWire.d.ts +0 -84
- package/dist/headlessReconnectWire.js +13 -67
- package/dist/hitl/approvalDecisionNoteAudit.d.ts +0 -49
- package/dist/hitl/approvalDecisionNoteAudit.js +0 -56
- package/dist/hitl/approvalOutcomeNote.d.ts +0 -2
- package/dist/hitl/approvalOutcomeNote.js +0 -20
- package/dist/hitl/approvalResolution.d.ts +0 -113
- package/dist/hitl/approvalResolution.js +0 -66
- package/dist/hitl/approvalsFeed.d.ts +0 -183
- package/dist/hitl/approvalsFeed.js +12 -243
- package/dist/hitl/armedGateRegistry.d.ts +0 -55
- package/dist/hitl/armedGateRegistry.js +0 -146
- package/dist/hitl/askGateWire.d.ts +0 -86
- package/dist/hitl/askGateWire.js +1 -95
- package/dist/hitl/askParkRowRouting.d.ts +0 -123
- package/dist/hitl/askParkRowRouting.js +1 -89
- package/dist/hitl/crashConverged.d.ts +0 -148
- package/dist/hitl/crashConverged.js +0 -214
- package/dist/hitl/editedRuleTextPrecheck.d.ts +0 -109
- package/dist/hitl/editedRuleTextPrecheck.js +0 -71
- package/dist/hitl/frameRouter.d.ts +0 -134
- package/dist/hitl/frameRouter.js +6 -378
- package/dist/hitl/gateIdentity.d.ts +0 -39
- package/dist/hitl/gateIdentity.js +0 -41
- package/dist/hitl/gateLedger.d.ts +0 -267
- package/dist/hitl/gateLedger.js +0 -121
- package/dist/hitl/hitlBridge.d.ts +7 -431
- package/dist/hitl/hitlBridge.js +7 -476
- package/dist/hitl/hitlHostSurface.d.ts +0 -150
- package/dist/hitl/hitlHostSurface.js +0 -169
- package/dist/hitl/livePendingAsk.d.ts +0 -91
- package/dist/hitl/livePendingAsk.js +0 -74
- package/dist/hitl/localAllowRule.d.ts +0 -62
- package/dist/hitl/localAllowRule.js +1 -33
- package/dist/hitl/parkOwnership.d.ts +0 -56
- package/dist/hitl/parkOwnership.js +0 -22
- package/dist/hitl/parkResolver.d.ts +3 -88
- package/dist/hitl/parkResolver.js +8 -349
- package/dist/hitl/parkRowBirthWait.d.ts +2 -26
- package/dist/hitl/parkRowBirthWait.js +3 -93
- package/dist/hitl/persistedRulesWire.d.ts +13 -358
- package/dist/hitl/persistedRulesWire.js +0 -310
- package/dist/hitl/planReviewWire.d.ts +4 -176
- package/dist/hitl/planReviewWire.js +9 -312
- package/dist/hitl/resumeRunningCard.d.ts +0 -105
- package/dist/hitl/resumeRunningCard.js +0 -105
- package/dist/hitl/sessionPolicyWire.d.ts +11 -191
- package/dist/hitl/sessionPolicyWire.js +0 -149
- package/dist/hitl/suspendedReopen.d.ts +3 -24
- package/dist/hitl/suspendedReopen.js +0 -14
- package/dist/hitl/toolApprovalWire.d.ts +5 -1308
- package/dist/hitl/toolApprovalWire.js +5 -945
- package/dist/hooksWireCaps.d.ts +0 -38
- package/dist/hooksWireCaps.js +0 -190
- package/dist/host.d.ts +0 -105
- package/dist/host.js +0 -33
- package/dist/hostEnv.d.ts +0 -14
- package/dist/hostEnv.js +0 -13
- package/dist/imagesWireCaps.d.ts +0 -21
- package/dist/imagesWireCaps.js +0 -22
- package/dist/index.d.ts +0 -134
- package/dist/index.js +0 -476
- package/dist/interactiveHalt.d.ts +5 -153
- package/dist/interactiveHalt.js +0 -111
- package/dist/interactiveToolsWire.d.ts +0 -62
- package/dist/interactiveToolsWire.js +1 -67
- package/dist/leaderConflict.d.ts +0 -59
- package/dist/leaderConflict.js +0 -48
- package/dist/limitsWire.d.ts +0 -125
- package/dist/limitsWire.js +2 -120
- package/dist/liveInitToolFace.d.ts +0 -77
- package/dist/liveInitToolFace.js +1 -109
- package/dist/liveModelCatalog.d.ts +0 -52
- package/dist/liveModelCatalog.js +0 -48
- package/dist/liveQuestionStore.d.ts +0 -87
- package/dist/liveQuestionStore.js +1 -56
- package/dist/mcpLiveness.d.ts +0 -151
- package/dist/mcpLiveness.js +0 -122
- package/dist/mcpPanel.d.ts +0 -104
- package/dist/mcpPanel.js +0 -49
- package/dist/mcpReconnect.d.ts +0 -58
- package/dist/mcpReconnect.js +0 -69
- package/dist/mcpWireCaps.d.ts +0 -55
- package/dist/mcpWireCaps.js +1 -13
- package/dist/memoryComplianceCapability.d.ts +3 -57
- package/dist/memoryComplianceCapability.js +0 -57
- package/dist/memoryEntriesWire.d.ts +6 -198
- package/dist/memoryEntriesWire.js +0 -144
- package/dist/memoryOriginCapability.d.ts +3 -53
- package/dist/memoryOriginCapability.js +0 -50
- package/dist/memorySpecWire.d.ts +0 -116
- package/dist/memorySpecWire.js +0 -150
- package/dist/model/catalog.d.ts +0 -111
- package/dist/model/catalog.js +0 -87
- package/dist/model/catalogLoader.d.ts +0 -114
- package/dist/model/catalogLoader.js +2 -139
- package/dist/model/modelSupplyRules.d.ts +1 -55
- package/dist/model/modelSupplyRules.js +0 -62
- package/dist/model/providerAuth.d.ts +0 -103
- package/dist/model/providerAuth.js +2 -38
- package/dist/model/providerCatalog.d.ts +0 -45
- package/dist/model/providerCatalog.js +0 -37
- package/dist/model/providerPresets.d.ts +0 -33
- package/dist/model/providerPresets.js +2 -91
- package/dist/model/tierVocabulary.d.ts +0 -31
- package/dist/model/tierVocabulary.js +0 -27
- package/dist/modelBudgetRule.d.ts +0 -39
- package/dist/modelBudgetRule.js +0 -39
- package/dist/modelCapabilityProbe.d.ts +0 -175
- package/dist/modelCapabilityProbe.js +0 -147
- package/dist/modelWireCaps.d.ts +0 -13
- package/dist/modelWireCaps.js +0 -13
- package/dist/notifications.d.ts +0 -233
- package/dist/notifications.js +14 -492
- package/dist/oneShotWireCaps.d.ts +0 -34
- package/dist/oneShotWireCaps.js +0 -35
- package/dist/ownKey.d.ts +0 -33
- package/dist/ownKey.js +0 -33
- package/dist/panelRunningHistory.d.ts +0 -28
- package/dist/panelRunningHistory.js +0 -43
- package/dist/peerFrames.d.ts +0 -71
- package/dist/peerFrames.js +0 -168
- package/dist/peerLaneCapability.d.ts +0 -44
- package/dist/peerLaneCapability.js +0 -52
- package/dist/permissionRuleIssue.d.ts +0 -30
- package/dist/permissionRuleIssue.js +0 -78
- package/dist/permissionRulesWriteCapability.d.ts +0 -46
- package/dist/permissionRulesWriteCapability.js +0 -54
- package/dist/permissionWireCaps.d.ts +0 -37
- package/dist/permissionWireCaps.js +0 -37
- package/dist/postureKnob.d.ts +0 -71
- package/dist/postureKnob.js +0 -86
- package/dist/principalWire.d.ts +0 -17
- package/dist/principalWire.js +0 -17
- package/dist/printToolResultFrame.d.ts +0 -100
- package/dist/printToolResultFrame.js +0 -33
- package/dist/promptProfileWireCaps.d.ts +0 -13
- package/dist/promptProfileWireCaps.js +0 -13
- package/dist/readFacePosture.d.ts +0 -43
- package/dist/readFacePosture.js +0 -46
- package/dist/request/printNotification.d.ts +0 -20
- package/dist/request/printNotification.js +0 -55
- package/dist/request/taskRequest.d.ts +0 -249
- package/dist/request/taskRequest.js +6 -498
- package/dist/resumeRefusalCopy.d.ts +0 -136
- package/dist/resumeRefusalCopy.js +1 -117
- package/dist/retainBackgroundWireCaps.d.ts +0 -48
- package/dist/retainBackgroundWireCaps.js +0 -48
- package/dist/retryStatus.d.ts +2 -221
- package/dist/retryStatus.js +0 -107
- package/dist/rewindWireCaps.d.ts +0 -27
- package/dist/rewindWireCaps.js +0 -24
- package/dist/runCancelContext.d.ts +1 -20
- package/dist/runCancelContext.js +0 -34
- package/dist/runTerminal.d.ts +0 -273
- package/dist/runTerminal.js +0 -177
- package/dist/sandboxWire.d.ts +0 -38
- package/dist/sandboxWire.js +0 -82
- package/dist/scenarioWire.d.ts +0 -60
- package/dist/scenarioWire.js +0 -68
- package/dist/scratchpadWireCaps.d.ts +0 -11
- package/dist/scratchpadWireCaps.js +0 -32
- package/dist/sdkWireTransit.d.ts +0 -38
- package/dist/sdkWireTransit.js +0 -30
- package/dist/seam.d.ts +18 -853
- package/dist/seam.js +0 -52
- package/dist/seatContract.d.ts +0 -555
- package/dist/seatContract.js +5 -304
- package/dist/selfOrchestrationDenial.d.ts +0 -189
- package/dist/selfOrchestrationDenial.js +0 -162
- package/dist/selfOrchestrationWireCaps.d.ts +0 -38
- package/dist/selfOrchestrationWireCaps.js +0 -38
- package/dist/sessionMap.d.ts +0 -60
- package/dist/sessionMap.js +0 -37
- package/dist/sessionMemoryStatus.d.ts +11 -114
- package/dist/sessionMemoryStatus.js +0 -112
- package/dist/sessionModelLatch.d.ts +0 -29
- package/dist/sessionModelLatch.js +0 -40
- package/dist/sessionPolicyCapability.d.ts +3 -53
- package/dist/sessionPolicyCapability.js +0 -52
- package/dist/sessionSlot.d.ts +0 -26
- package/dist/sessionSlot.js +0 -17
- package/dist/skillsWireCaps.d.ts +0 -87
- package/dist/skillsWireCaps.js +0 -38
- package/dist/sqlEngineCapability.d.ts +0 -118
- package/dist/sqlEngineCapability.js +0 -134
- package/dist/sseIdleTriage.d.ts +0 -79
- package/dist/sseIdleTriage.js +1 -80
- package/dist/steering.d.ts +0 -54
- package/dist/steering.js +0 -63
- package/dist/subagent/engineCompactWire.d.ts +0 -34
- package/dist/subagent/engineCompactWire.js +4 -134
- package/dist/subagent/engineDelegatedPrompt.d.ts +0 -31
- package/dist/subagent/engineDelegatedPrompt.js +1 -103
- package/dist/subagent/engineRowStopGate.d.ts +0 -20
- package/dist/subagent/engineRowStopGate.js +0 -49
- package/dist/subagent/engineSubagentOutput.d.ts +0 -7
- package/dist/subagent/engineSubagentOutput.js +1 -51
- package/dist/subagent/engineSubagentResume.d.ts +2 -279
- package/dist/subagent/engineSubagentResume.js +2 -129
- package/dist/subagent/engineSubagentSteer.d.ts +0 -26
- package/dist/subagent/engineSubagentSteer.js +0 -63
- package/dist/subagent/engineSubagentTail.d.ts +0 -38
- package/dist/subagent/engineSubagentTail.js +2 -110
- package/dist/subagent/engineTaskHandleWire.d.ts +6 -67
- package/dist/subagent/engineTaskHandleWire.js +0 -126
- package/dist/subagent/subagentOwnerAbsence.d.ts +0 -2
- package/dist/subagent/subagentOwnerAbsence.js +0 -25
- package/dist/subagentContentStore.d.ts +3 -260
- package/dist/subagentContentStore.js +7 -540
- package/dist/systemReminderTag.d.ts +0 -49
- package/dist/systemReminderTag.js +0 -61
- package/dist/toolResult.d.ts +1 -211
- package/dist/toolResult.js +1 -358
- package/dist/toolRoster.d.ts +0 -140
- package/dist/toolRoster.js +0 -66
- package/dist/typePins.d.ts +0 -46
- package/dist/types/engineState.d.ts +0 -71
- package/dist/types/engineState.js +0 -16
- package/dist/ultracodeWireCaps.d.ts +0 -75
- package/dist/ultracodeWireCaps.js +0 -92
- package/dist/unrefTimer.d.ts +0 -27
- package/dist/webSearchBackendCapability.d.ts +0 -72
- package/dist/webSearchBackendCapability.js +0 -79
- package/dist/webSearchWireCaps.d.ts +0 -37
- package/dist/webSearchWireCaps.js +0 -34
- package/dist/websearch/searchProviderPresets.d.ts +0 -81
- package/dist/websearch/searchProviderPresets.js +0 -27
- package/dist/wireErrorTriage.d.ts +4 -160
- package/dist/wireErrorTriage.js +0 -171
- package/dist/wireRefusalCopy.d.ts +0 -28
- package/dist/wireRefusalCopy.js +0 -28
- package/dist/workflow.d.ts +0 -40
- package/dist/workflow.js +0 -52
- package/dist/workflowClient.d.ts +0 -122
- package/dist/workflowClient.js +8 -360
- package/dist/workflowMonitor.d.ts +2 -72
- package/dist/workflowMonitor.js +0 -26
- package/dist/writeProtectionCapability.d.ts +0 -112
- package/dist/writeProtectionCapability.js +0 -109
- package/docs/INTEGRATION-CLIENTS.md +30 -1
- package/package.json +1 -1
|
@@ -1,45 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ⇄ B1 批搬迁(2026-07-27,多端改造设计稿 §2.4.1-B):cli src/sema/engineAgentPanelStore.ts 逐字搬入(零 import;壳侧改 re-export)。
|
|
3
|
-
* 🔴 同 subagentContentStore:buffer/listener/residentTaskIds 是单实例语义,发布侧(bridge/fleet
|
|
4
|
-
* 投影)与订阅侧(chrome-agentprogress 的面板 hook)必须同实例,否则事件发进一个副本、面板订另一个。
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* engineAgentPanelStore — dep-free side-channel store bridging ENGINE-side subagent progress
|
|
8
|
-
* (`task_progress` ticks, design/99 MF-10) to CC's CoordinatorTaskPanel (the footer live-agent panel).
|
|
9
|
-
*
|
|
10
|
-
* WHY A STORE (the retryStatusStore / liveQuestionStore pattern): the upstream bridge is a plain
|
|
11
|
-
* generator with no React/AppState access, while the panel reads `AppState.tasks` — so the bridge
|
|
12
|
-
* PUBLISHES neutral events here and a sema-owned hook inside chrome-agentprogress.tsx (already mounted
|
|
13
|
-
* under the footer) SUBSCRIBES and applies them to AppState via registerTask/updateTaskState. CC files
|
|
14
|
-
* stay verbatim; the AppState write side lives in the sema override that owns the panel.
|
|
15
|
-
*
|
|
16
|
-
* WHY THE PANEL (CC-187 parity): a local sync AgentTool renders an inline progress TRAIL from the
|
|
17
|
-
* subagent's real messages. An engine tick carries ONLY rollup numbers ({toolUses, totalTokens}) — the
|
|
18
|
-
* exact shape of CC's `AgentProgress` — and CC's own precedent for out-of-process agents (remote agent
|
|
19
|
-
* tasks) is the TASK PANEL + task-notification, not a synthetic inline trail. Faithful mapping, no
|
|
20
|
-
* fabricated subagent messages.
|
|
21
|
-
*
|
|
22
|
-
* Buffering: ticks published before the panel mounts are buffered (bounded) and replayed to the first
|
|
23
|
-
* subscriber, so early frames in a fast turn aren't lost to mount timing.
|
|
24
|
-
*/
|
|
25
1
|
import { retirePanelRowRunning, notePanelRowEnded, panelRowEndedIdentity, peekHeldNewbornTerminalRow, takeHeldNewbornTerminalRow, dropHeldNewbornTerminalRow, heldNewbornTerminalRefs } from './panelRunningHistory.js';
|
|
26
2
|
const _panelToolUsesLanePins = [true, true];
|
|
27
3
|
void _panelToolUsesLanePins;
|
|
28
|
-
/**
|
|
29
|
-
* 两条 lane 对 `toolUses` 的口径(运行期读面,给门用;上面的编译钉保证它没在撒谎)。
|
|
30
|
-
* `required-engine-always-emits` = 缺席不可达 ⇒ 兜底值合法;
|
|
31
|
-
* `optional-tolerate-absent` = 缺席即「不知道」⇒ 必须传播缺席(键不落)。
|
|
32
|
-
*/
|
|
33
4
|
export const PANEL_TOOLUSES_LANE_POLICY = {
|
|
34
5
|
tick: 'required-engine-always-emits',
|
|
35
6
|
'fleet-row': 'optional-tolerate-absent',
|
|
36
7
|
};
|
|
37
|
-
// ── #6(frame-lane-matrix)session 常驻行台账 ─────────────────────────────────────────────────
|
|
38
|
-
// 行寿命 ≠ turn 寿命:跨 turn 存活的 bg 子代行(tick 绑不到本 turn 开着的卡 = inert/unbound)不该被
|
|
39
|
-
// turn 末防御 sweep(bridge settlePanelTasks(null) / seamQuery 'sweep' 事件)结成假 completed——一旦
|
|
40
|
-
// 假结,消费端 tick 门(status!=='running' ⇒ return prev)会把后续真 tick 全丢,真终态(failed)也
|
|
41
|
-
// 改不动(冻死)。台账 module-level(publisher=bridge 按绑定活性写;两个 sweep 消费点按它跳过;
|
|
42
|
-
// 真终态通知(task_notification 帧 / enqueueBgChildNotification 合成)settle 时摘除)。
|
|
43
8
|
const residentTaskIds = new Set();
|
|
44
9
|
export function markEnginePanelTaskResident(taskId) {
|
|
45
10
|
residentTaskIds.add(taskId);
|
|
@@ -53,19 +18,11 @@ export function isEnginePanelTaskResident(taskId) {
|
|
|
53
18
|
const MAX_BUFFER = 200;
|
|
54
19
|
let listener = null;
|
|
55
20
|
const buffer = [];
|
|
56
|
-
/** 两条 fleet-row 都带同一种周期身份(launch 锚 / 代际号)且不相等 ⇒ 新周期(任一条没带 = 这一帧没说,不算变化)。 */
|
|
57
21
|
function launchAnchorChanged(prev, next) {
|
|
58
22
|
if (prev.kind !== 'fleet-row' || next.kind !== 'fleet-row')
|
|
59
23
|
return false;
|
|
60
24
|
return isNewEngineAgentPanelCycle(prev, next);
|
|
61
25
|
}
|
|
62
|
-
/**
|
|
63
|
-
* 0.74.5 CC-87 —— 「这一帧是不是**新周期**」的单源判据(`isStaleEngineAgentPanelEnd` 的对偶,壳侧此前各拼一份):
|
|
64
|
-
* · 两边都带 `cycleSeq` ⇒ **只**比它:不等 ⇒ 新周期;
|
|
65
|
-
* · 否则两边都带 `startedAt` ⇒ 不等 ⇒ 新周期;
|
|
66
|
-
* · 任一边判不出 ⇒ **不是**新周期(这一帧没说,不算变化 —— 方向与陈旧判据相同:缺席不制造周期)。
|
|
67
|
-
* 与缓冲合并屏障(`launchAnchorChanged`)同一条规则;消费端在 `fleet-row` 到时拿行上记的身份与帧上的身份调它。
|
|
68
|
-
*/
|
|
69
26
|
export function isNewEngineAgentPanelCycle(prev, next) {
|
|
70
27
|
const pc = cycleSeqOf(prev);
|
|
71
28
|
const nc = cycleSeqOf(next);
|
|
@@ -83,15 +40,6 @@ function startedAtOf(v) {
|
|
|
83
40
|
const n = v?.startedAt;
|
|
84
41
|
return typeof n === 'number' && Number.isFinite(n) && n > 0 ? n : undefined;
|
|
85
42
|
}
|
|
86
|
-
/**
|
|
87
|
-
* 0.74.0 —— 这条 `end` 是不是**上一周期迟到的**(单源判据,三端共用)。`current` = 消费端记在行上的当前周期
|
|
88
|
-
* (取自最近一条 `fleet-row` 的 `cycleSeq` / `startedAt`)。
|
|
89
|
-
* · 两边都有 `cycleSeq` ⇒ **只**比它:`end` 更小 ⇒ 陈旧;
|
|
90
|
-
* · 否则两边都有 `startedAt` ⇒ `end` 更早 ⇒ 陈旧;
|
|
91
|
-
* · 任一边判不出(流内 close 臂的 `end` / 没有代际概念的行 / 老引擎 / 坏形)⇒ **不陈旧** —— 按现行为 settle。
|
|
92
|
-
* 方向是宁可照旧也不因为缺席丢掉一条真终态。
|
|
93
|
-
* 陈旧的 `end`:忽略(不 settle、不写 report、不摘所有权)。
|
|
94
|
-
*/
|
|
95
43
|
export function isStaleEngineAgentPanelEnd(end, current) {
|
|
96
44
|
const ec = cycleSeqOf(end);
|
|
97
45
|
const cc = cycleSeqOf(current);
|
|
@@ -103,51 +51,16 @@ export function isStaleEngineAgentPanelEnd(end, current) {
|
|
|
103
51
|
return es < cs;
|
|
104
52
|
return false;
|
|
105
53
|
}
|
|
106
|
-
// ── 0.74.3 CC-70:子代身份归一(所有 lane 的唯一漏斗)────────────────────────────────────────
|
|
107
|
-
//
|
|
108
|
-
// 病(cli L-407 / test 定谳,三端同撞):同一个后台子代在 wire 上有**两把身份** —— fleet 行 id 尾段(17 位,= 注册表 task_id
|
|
109
|
-
// = 壳本地 agentId,core #948 按构造)与主流 `task_progress.taskId`(引擎 UUIDv7 = transcriptId = childSessionId)。本包的
|
|
110
|
-
// `fleet-row` / 通知 `end` 用前者,tick / 流内 close 臂的 `end` 用后者 ⇒ 壳面板按 `ev.taskId` 落 Map 长成两行;包内常驻标也是
|
|
111
|
-
// 「UUID 记、17 位清」永不清。修法 = 在这一只漏斗里把 tick / end 的 `taskId` 归一到 fleet 尾段(消费端零改):
|
|
112
|
-
// · 钥匙两把,fleet-row 一到就登记:`transcriptId → 尾段`(主)、`parentToolCallId → 尾段`(退路);
|
|
113
|
-
// · 查得到 ⇒ 改写 `taskId`,原词进 `wireTaskId`,`taskIdOrigin:'fleet-row'`;常驻标若记在 UUID 下随之迁移;
|
|
114
|
-
// · 查不到:绑卡的 tick(同步委派,`cardBound`)直发;未绑的 tick **缓一拍**等 fleet-row(常态 fleet-row 先到几十秒,但非保证)——
|
|
115
|
-
// 触发 = 同 UUID 的 fleet-row 到(归一发)/ 同 UUID 第二条 tick(新的原样发,旧的丢)/ 同 UUID `end`(先 tick 后 end 原样发)/
|
|
116
|
-
// 缓冲满(最旧的原样发);原样发的带 `taskIdOrigin:'wire'`。🔴 `sweep` **不放**缓着的 tick:那条 tick 还没有行,sweep 没有东西可结;
|
|
117
|
-
// 在「tick 先到、父 turn 先结、行帧后到」的窗里放出去反而把 UUID 行造出来、接着行帧再造第二行 —— 正是要修的病。
|
|
118
|
-
// · 两张钥匙表与缓一拍都有界(常量),溢出先进先出 —— 上限是内存约束不是语义,超出只退化成「原样发」;
|
|
119
|
-
// · 缓一拍还按**节拍**有界(异源复审 R1 [medium]):别的 fleet-row / end / sweep 每过一条算一拍(别的 tick 不算 —— 它说明不了行帧车道
|
|
120
|
-
// 活不活,一阵子代同时起步时也不该互相挤),过 MAX_HELD_WIRE_TICK_BEATS 拍还没等到自己的行帧 ⇒ 原样放(store 无计时器,拍是唯一可数的时间);
|
|
121
|
-
// · 钥匙带**周期身份**(复审 R1 [high]):行帧登记时连 cycleSeq / startedAt 一起记,归一后的 end 若自己不带周期就借钥匙上的
|
|
122
|
-
// (流内 close 臂的 end 恒不带)—— 复活后旧 transcriptId 的钥匙仍在,迟到的 end{旧 UUID} 归一后带着旧代际,
|
|
123
|
-
// isStaleEngineAgentPanelEnd 才判得出它是前代;
|
|
124
|
-
// · tick 经退路键(parentToolCallId)归一时,顺手把 UUID → 尾段 记进主表(复审 R1 [high]):随后的 end{UUID} 不带 parentToolCallId,
|
|
125
|
-
// 没有这一步它永远归不了一。
|
|
126
|
-
// · 🔴 **先发布的键为准**(0.74.4 CC-83;test [7702] N-3 证伪「零改」:tick 归不了一而原样发出之后,行帧再按尾段发 = 消费端仍两行):
|
|
127
|
-
// 一条 tick 已按 UUID 原样发出(第二拍 / 拍数耗尽 / 绑卡),这个子代在消费端的键就是 UUID —— 之后到的 fleet-row / fleet 侧 end
|
|
128
|
-
// 改写成 UUID(原词进 wireTaskId,taskIdOrigin:'wire'),不再把尾段当第二把键发出去。消费端从此在任何到达序上都只见一把键;
|
|
129
|
-
// 常态序(行帧先到)仍归一到尾段。
|
|
130
|
-
// · 🔴 前代 UUID 的迟到 tick **丢弃**(0.74.4 CC-84;test [7702] W2 tick 腿):钥匙上的周期比最近行帧旧 ⇒ 这条 progress 属已结束的
|
|
131
|
-
// 周期,归一发出去会把前代的累计数写进复活行;end 有陈旧判据(消费端按周期挡),tick 没有 ⇒ 在漏斗里挡。
|
|
132
|
-
/** 钥匙表上限(LRU:命中即续命,真在飞的子代不会被一阵新登记挤掉;超出只退化成「原样发」)。 */
|
|
133
54
|
const MAX_IDENTITY_KEYS = 2048;
|
|
134
55
|
const MAX_HELD_WIRE_TICKS = 64;
|
|
135
|
-
/** 缓一拍的节拍上限:别的 fleet-row / end / sweep 每过一条算一拍(别的 tick 不算)。 */
|
|
136
56
|
export const MAX_HELD_WIRE_TICK_BEATS = 16;
|
|
137
57
|
const fleetIdByTranscriptId = new Map();
|
|
138
58
|
const fleetIdByParentToolCallId = new Map();
|
|
139
59
|
const heldWireTicks = new Map();
|
|
140
|
-
/** 每个 fleet 尾段最近一条行帧带的周期身份(在场才记):清常驻标时用它判「这条终态是不是前代的」(异源复审 R3 [high])。 */
|
|
141
60
|
const latestCycleByFleetId = new Map();
|
|
142
|
-
/**
|
|
143
|
-
* 已按 UUID 原样发出过 tick 的子代(先发布的键为准,CC-83):transcriptId(= UUID)与 parentToolCallId 两把钥匙都记。
|
|
144
|
-
* 🔴 所有权表**按生命周期退役、不按容量改写**(异源复审 0.74.4 R1 [medium]):一把已发布的键在消费端就是一行,容量到了把它忘掉 =
|
|
145
|
-
* 同一子代重新长成两行。所以 `retired`(收到 end)的条目先让位;都没退役时才让最旧的(上限 MAX_OWNERSHIP_KEYS,远大于同时在飞的子代数)。
|
|
146
|
-
*/
|
|
147
61
|
const MAX_OWNERSHIP_KEYS = 8192;
|
|
148
62
|
const publishedWireIds = new Map();
|
|
149
63
|
const publishedWireByParent = new Map();
|
|
150
|
-
/** 尾段 → 已发布的 UUID(CC-83):fleet 侧的 fleet-row / end / 缺席 到时改写成 UUID;带登记时行帧的周期,复活的新周期不继承。 */
|
|
151
64
|
const wireIdByFleetId = new Map();
|
|
152
65
|
function bounded(map, key, value) {
|
|
153
66
|
map.delete(key);
|
|
@@ -158,7 +71,6 @@ function bounded(map, key, value) {
|
|
|
158
71
|
map.delete(oldest);
|
|
159
72
|
}
|
|
160
73
|
}
|
|
161
|
-
/** 所有权表的有界:退役的先让位,都没退役才让最旧的。 */
|
|
162
74
|
function boundedOwnership(map, key, value) {
|
|
163
75
|
map.delete(key);
|
|
164
76
|
map.set(key, value);
|
|
@@ -174,14 +86,11 @@ function boundedOwnership(map, key, value) {
|
|
|
174
86
|
if (oldest !== undefined)
|
|
175
87
|
map.delete(oldest);
|
|
176
88
|
}
|
|
177
|
-
/** 一条 tick 按 UUID 原样发出去了:从此这个子代的键 = UUID。 */
|
|
178
89
|
function notePublishedWire(ev) {
|
|
179
|
-
// 已退役的键不因一条迟到 tick 复活(异源复审 R3 [high]):退役 = 它的行已结,迟到帧落在它自己的行上,所有权不回来
|
|
180
90
|
boundedOwnership(publishedWireIds, ev.taskId, { retired: publishedWireIds.get(ev.taskId)?.retired ?? false });
|
|
181
91
|
if (ev.parentToolCallId !== undefined && ev.parentToolCallId.length > 0)
|
|
182
92
|
bounded(publishedWireByParent, ev.parentToolCallId, ev.taskId);
|
|
183
93
|
}
|
|
184
|
-
/** 这把 UUID 的子代收到了终态:所有权可退役(容量满时先让位;不删 —— 迟到的同周期行帧 / end 仍要改写到它)。 */
|
|
185
94
|
function retireWire(wireId) {
|
|
186
95
|
const w = publishedWireIds.get(wireId);
|
|
187
96
|
if (w !== undefined)
|
|
@@ -190,7 +99,6 @@ function retireWire(wireId) {
|
|
|
190
99
|
if (o.wireId === wireId)
|
|
191
100
|
o.retired = true;
|
|
192
101
|
}
|
|
193
|
-
/** fleet-row 对应的子代是否已经按 UUID 发布过;transcriptId 命中不看退役(同一子代的迟到行帧),parentToolCallId 只认未退役(复活会沿用同一张卡)。 */
|
|
194
102
|
function publishedWireFor(ev) {
|
|
195
103
|
if (ev.transcriptId !== undefined && publishedWireIds.has(ev.transcriptId))
|
|
196
104
|
return ev.transcriptId;
|
|
@@ -201,16 +109,14 @@ function publishedWireFor(ev) {
|
|
|
201
109
|
}
|
|
202
110
|
return undefined;
|
|
203
111
|
}
|
|
204
|
-
/** 尾段今天归哪把 UUID(在场 = 这个子代已按 UUID 上屏;复活的新周期不算)。 */
|
|
205
112
|
function wireOwnerOf(fleetId, current, transcriptId) {
|
|
206
113
|
const o = wireIdByFleetId.get(fleetId);
|
|
207
114
|
if (o === undefined)
|
|
208
115
|
return undefined;
|
|
209
|
-
|
|
210
|
-
const newTranscript = transcriptId !== undefined && transcriptId !== (o.transcriptId ?? o.wireId); // 父键登记没记 transcriptId 时,wireId 本身就是那一代的转录身份(复审 R3)
|
|
116
|
+
const newTranscript = transcriptId !== undefined && transcriptId !== (o.transcriptId ?? o.wireId);
|
|
211
117
|
if (newTranscript || (current !== undefined && isStaleEngineAgentPanelEnd(o, current))) {
|
|
212
|
-
wireIdByFleetId.delete(fleetId);
|
|
213
|
-
retireWire(o.wireId);
|
|
118
|
+
wireIdByFleetId.delete(fleetId);
|
|
119
|
+
retireWire(o.wireId);
|
|
214
120
|
return undefined;
|
|
215
121
|
}
|
|
216
122
|
return o.wireId;
|
|
@@ -224,14 +130,10 @@ function remember(map, key, alias) {
|
|
|
224
130
|
map.delete(oldest);
|
|
225
131
|
}
|
|
226
132
|
}
|
|
227
|
-
/**
|
|
228
|
-
* 0.74.3 CC-70:把 wire 上的子代 id(task_progress 的 UUID)反查成 fleet 行 id 尾段;`transcriptId` 表优先,退 `parentToolCallId` 表;
|
|
229
|
-
* 都查不到 ⇒ 原样(`origin:'wire'`)。fleet 尾段本身传进来也原样(它就是目标键)。
|
|
230
|
-
*/
|
|
231
133
|
export function resolveEnginePanelTaskId(wireTaskId, parentToolCallId) {
|
|
232
134
|
const byTranscript = fleetIdByTranscriptId.get(wireTaskId);
|
|
233
135
|
if (byTranscript !== undefined) {
|
|
234
|
-
remember(fleetIdByTranscriptId, wireTaskId, byTranscript);
|
|
136
|
+
remember(fleetIdByTranscriptId, wireTaskId, byTranscript);
|
|
235
137
|
return identityOf(byTranscript);
|
|
236
138
|
}
|
|
237
139
|
const byParent = parentToolCallId !== undefined ? fleetIdByParentToolCallId.get(parentToolCallId) : undefined;
|
|
@@ -249,7 +151,6 @@ function identityOf(alias) {
|
|
|
249
151
|
...(alias.startedAt !== undefined ? { startedAt: alias.startedAt } : {}),
|
|
250
152
|
};
|
|
251
153
|
}
|
|
252
|
-
/** 经退路键归一的 tick:把 UUID → 尾段 记进主表,随后不带 parentToolCallId 的 end{UUID} 才归得了一。 */
|
|
253
154
|
function rememberResolvedWire(wireTaskId, id) {
|
|
254
155
|
if (fleetIdByTranscriptId.has(wireTaskId))
|
|
255
156
|
return;
|
|
@@ -259,7 +160,6 @@ function rememberResolvedWire(wireTaskId, id) {
|
|
|
259
160
|
...(id.startedAt !== undefined ? { startedAt: id.startedAt } : {}),
|
|
260
161
|
});
|
|
261
162
|
}
|
|
262
|
-
/** 别的事件过了一拍:缓着的 tick 各记一拍,过上限的原样放出(先进先出)。 */
|
|
263
163
|
function ageHeld(except) {
|
|
264
164
|
for (const [wireId, held] of [...heldWireTicks]) {
|
|
265
165
|
if (wireId === except)
|
|
@@ -289,7 +189,6 @@ function asIsTick(ev) {
|
|
|
289
189
|
notePublishedWire(ev);
|
|
290
190
|
return { ...rest, taskIdOrigin: 'wire' };
|
|
291
191
|
}
|
|
292
|
-
/** 钥匙上的周期比最近行帧旧 = 这条 tick 属已结束的周期(CC-84);判不出 ⇒ 不算陈旧。 */
|
|
293
192
|
function staleWireTick(id) {
|
|
294
193
|
return isStaleEngineAgentPanelEnd(id, latestCycleByFleetId.get(id.taskId));
|
|
295
194
|
}
|
|
@@ -305,23 +204,16 @@ function flushHeld(wireTaskId) {
|
|
|
305
204
|
const id = resolveEnginePanelTaskId(held.ev.taskId, held.ev.parentToolCallId);
|
|
306
205
|
if (id.origin === 'fleet-row') {
|
|
307
206
|
if (staleWireTick(id))
|
|
308
|
-
return;
|
|
207
|
+
return;
|
|
309
208
|
rememberResolvedWire(held.ev.taskId, id);
|
|
310
209
|
deliverEngineAgentPanelEvent(normalizedTick(held.ev, id.taskId));
|
|
311
210
|
return;
|
|
312
211
|
}
|
|
313
212
|
deliverEngineAgentPanelEvent(asIsTick(held.ev));
|
|
314
213
|
}
|
|
315
|
-
/**
|
|
316
|
-
* 0.74.3 CC-70(异源复审 R3 [high]):按 wire 上的子代 id 清常驻标 —— 原键照清;归一到 fleet 尾段的那把键**只在这条终态属当代时**才清:
|
|
317
|
-
* 复活后迟到的前代终态(旧 UUID 的流内 close / 终态 tick)归一后带旧代际,清了尾段键 = 撤掉复活行的 sweep 保护 ⇒ 下一次 sweep 假结它。
|
|
318
|
-
* 判据与 `end` 的陈旧判据同一只(`isStaleEngineAgentPanelEnd`,拿钥匙上的周期对最近一条行帧的周期);判不出 ⇒ 照清(不因缺席留下永久常驻)。
|
|
319
|
-
* `cycle`(0.74.4):调用方(通知车道)带得出这条终态的周期时传进来 —— 尾段归某把 UUID 所有而通知比所有权旧 ⇒ 不清那把 UUID 的常驻标。
|
|
320
|
-
*/
|
|
321
214
|
export function clearEnginePanelTaskResidentByWire(wireTaskId, cycle) {
|
|
322
215
|
residentTaskIds.delete(wireTaskId);
|
|
323
|
-
const owner = wireIdByFleetId.get(wireTaskId);
|
|
324
|
-
// 通知带周期(seq)且比所有权登记时的周期旧 = 前代的终态 ⇒ 不清当代 UUID 的常驻标(异源复审 R3 [high])
|
|
216
|
+
const owner = wireIdByFleetId.get(wireTaskId);
|
|
325
217
|
if (owner !== undefined && !(cycle !== undefined && isStaleEngineAgentPanelEnd(cycle, owner)))
|
|
326
218
|
residentTaskIds.delete(owner.wireId);
|
|
327
219
|
const id = resolveEnginePanelTaskId(wireTaskId);
|
|
@@ -331,12 +223,6 @@ export function clearEnginePanelTaskResidentByWire(wireTaskId, cycle) {
|
|
|
331
223
|
return;
|
|
332
224
|
residentTaskIds.delete(id.taskId);
|
|
333
225
|
}
|
|
334
|
-
/**
|
|
335
|
-
* 测试钩。逐表清单(每加一张表同批更新这里):① 转录钥匙表(UUID → 行尾段)② 父调用钥匙表(parentToolCallId → 行尾段)
|
|
336
|
-
* ③ 缓着的未绑卡 tick ④ 每行最近一次行帧的周期水位 ⑤ 「先发布的键」集合(UUID)⑥ 同上按父调用记的那一份 ⑦ 反向所有权表(行尾段 → UUID)。
|
|
337
|
-
* 🔴 不清:订阅者 / 回放缓冲、常驻标、running 历史(那一本由 `__resetPanelRunningHistoryForTests` 清)。
|
|
338
|
-
* 🔴 连续场景(同一只子代跨多步的用例)**中途别调**:清掉 ④–⑦ 之后,陈旧判据与「先发布的键为准」都会从零开始,前后两半不再是同一段历史。
|
|
339
|
-
*/
|
|
340
226
|
export function __resetEngineAgentPanelIdentityForTests() {
|
|
341
227
|
fleetIdByTranscriptId.clear();
|
|
342
228
|
fleetIdByParentToolCallId.clear();
|
|
@@ -346,30 +232,12 @@ export function __resetEngineAgentPanelIdentityForTests() {
|
|
|
346
232
|
publishedWireByParent.clear();
|
|
347
233
|
wireIdByFleetId.clear();
|
|
348
234
|
}
|
|
349
|
-
/**
|
|
350
|
-
* 0.75.0 W2:一条 end 递达之前,先把投影缓着的「首见即终态」行放出来(它带这一行唯一的一份最终用量),经漏斗原路发布(身份归一照走);
|
|
351
|
-
* 递达之后记「本进程结过这一行」—— 投影据此把之后到的终态行当成短命子代的收尾(照发用量)而不是历史行。两步都只对当代 end(陈旧判据与销 running 历史同一只)。
|
|
352
|
-
*/
|
|
353
|
-
/**
|
|
354
|
-
* 这一条缓行**放出去会落在哪把消费端键上**(纯读口,不动表;与 fleet-row 臂的改写次序同序:
|
|
355
|
-
* 反向所有权 → 已发布的 wire 键 → 自己的行尾段)。第四条腿据它核「行与 end 是否同键」。
|
|
356
|
-
* 🔴 保守方向:所有权在表里就按它答(`wireOwnerOf` 遇到新一代会把它删掉再落到下一档 —— 那一档答错只会让本腿
|
|
357
|
-
* **少放**一次,不会让一只子代分成两行)。
|
|
358
|
-
*/
|
|
359
235
|
function heldRowConsumerKey(tail, held) {
|
|
360
236
|
const owner = wireIdByFleetId.get(tail);
|
|
361
237
|
if (owner !== undefined)
|
|
362
238
|
return owner.wireId;
|
|
363
239
|
return publishedWireFor(held) ?? tail;
|
|
364
240
|
}
|
|
365
|
-
/**
|
|
366
|
-
* 这一条 end 对那一行缓着的终态行的**代际三向**(纯读口,不动表)。先 peek 再决定:先 take 会让前代
|
|
367
|
-
* end 把当代唯一的缓行取走丢掉;
|
|
368
|
-
* · `'keep'` = end 可证比缓行**旧** ⇒ 缓行留着(等当代的那条 end);
|
|
369
|
-
* · `'drop'` = end 可证比缓行**新** ⇒ 缓行作废(前代的用量不许盖当代行);
|
|
370
|
-
* · `'release'` = 同代 / 判不出 ⇒ 可以放出;
|
|
371
|
-
* · `'none'` = 这一行没有缓着的终态行。
|
|
372
|
-
*/
|
|
373
241
|
function heldNewbornTerminalVerdict(taskId, endCycle) {
|
|
374
242
|
const held = peekHeldNewbornTerminalRow(taskId);
|
|
375
243
|
if (held === undefined || held.kind !== 'fleet-row')
|
|
@@ -381,19 +249,6 @@ function heldNewbornTerminalVerdict(taskId, endCycle) {
|
|
|
381
249
|
return 'drop';
|
|
382
250
|
return 'release';
|
|
383
251
|
}
|
|
384
|
-
/**
|
|
385
|
-
* 🔴 放行前的**同键核**:这一条缓行放出去,行帧与随后那条 end 会不会落在**同一把消费端键**上?
|
|
386
|
-
*
|
|
387
|
-
* 反例(实测):一只子代的委派卡被复用 —— `tick{V, 卡 P}` 已按 V 上过屏;缓着的终态行是
|
|
388
|
-
* `{尾段 X, 转录锚 U, 卡 P}`;来的是 `end{U}`。第四条腿按转录锚找到唯一候选 X,可它一放行就被
|
|
389
|
-
* 「先发布的键为准」经卡 P 改写到 **V** 上,而这条 `end{U}` 在主路上谁也不命中、原样落在 **U**:
|
|
390
|
-
* 用量记到了 V,X 的终态却发给了 U,消费端还可能凭 `end{U}` 另开一行。
|
|
391
|
-
*
|
|
392
|
-
* 所以只在两种形下放行(其余留着缓行,等真正属于它的那条 end —— 宁可晚交一份用量,不让一只子代分成两行):
|
|
393
|
-
* ① 行会被改写到**这条 end 自己那把键**上(随后主路也落在同一把键,`ownedFleetIds` 连带结账);
|
|
394
|
-
* ② 行按**自己的尾段**上屏,而这条 end 的键正是它的转录锚且那把键没被发布过 —— 放行登记了转录钥匙,
|
|
395
|
-
* 主路随即经钥匙表归一到同一条尾段。
|
|
396
|
-
*/
|
|
397
252
|
function heldRowReleasesOntoSameKey(tail, end) {
|
|
398
253
|
const held = peekHeldNewbornTerminalRow(tail);
|
|
399
254
|
if (held === undefined || held.kind !== 'fleet-row')
|
|
@@ -401,9 +256,6 @@ function heldRowReleasesOntoSameKey(tail, end) {
|
|
|
401
256
|
const rowKey = heldRowConsumerKey(tail, held);
|
|
402
257
|
if (rowKey === end.taskId)
|
|
403
258
|
return true;
|
|
404
|
-
// 末一项 `!publishedWireIds.has(...)` 是**可证冗余**的写方守卫(删掉行为不变:若这把键发布过,
|
|
405
|
-
// 上面的 `heldRowConsumerKey` 就会把 rowKey 算成它、第一档已经返回 true,走不到这里)。留着是把
|
|
406
|
-
// 「② 只成立于那把键没上过屏」这句话钉在代码里,别当成活判据去删第一档。
|
|
407
259
|
return rowKey === tail && held.transcriptId === end.taskId && !publishedWireIds.has(end.taskId);
|
|
408
260
|
}
|
|
409
261
|
function releaseHeldNewbornTerminal(taskId, endCycle) {
|
|
@@ -418,24 +270,18 @@ function releaseHeldNewbornTerminal(taskId, endCycle) {
|
|
|
418
270
|
if (held !== undefined)
|
|
419
271
|
publishEngineAgentPanelEvent(held);
|
|
420
272
|
}
|
|
421
|
-
/** 结算(end 已递达):running 历史销、ended 账单调写(可证比已结周期旧的 end 不倒写)。 */
|
|
422
273
|
function settleRowHistory(taskId, cycle) {
|
|
423
274
|
retirePanelRowRunning(taskId);
|
|
424
275
|
notePanelRowEnded(taskId, cycle, isStaleEngineAgentPanelEnd(cycle, panelRowEndedIdentity(taskId)));
|
|
425
276
|
}
|
|
426
|
-
/** end 的陈旧判据同时参考行帧水位与 ended 账(短命子代常常没有行帧水位 —— 异源复审 R3 [high])。 */
|
|
427
277
|
function endOlderThanKnown(end, taskId, rowCycle) {
|
|
428
278
|
return isStaleEngineAgentPanelEnd(end, rowCycle) || isStaleEngineAgentPanelEnd(end, panelRowEndedIdentity(taskId));
|
|
429
279
|
}
|
|
430
|
-
/** 宿主的唯一发布口(三条 lane 都经这里):先归一身份,再进主通道(订阅者 / 缓冲)。 */
|
|
431
280
|
export function publishEngineAgentPanelEvent(ev) {
|
|
432
|
-
// 行帧先登记、先放自己匹配的 tick,再给别的缓着的 tick 记拍(异源复审 R2 [high]:先记拍会让第 16 拍那条正好是自己行帧的 tick 过期);
|
|
433
|
-
// end / sweep 没有「自己的」匹配 ⇒ 先记拍。
|
|
434
281
|
if (ev.kind === 'end' || ev.kind === 'sweep')
|
|
435
282
|
ageHeld(ev.kind === 'sweep' ? undefined : ev.taskId);
|
|
436
283
|
switch (ev.kind) {
|
|
437
284
|
case 'fleet-row': {
|
|
438
|
-
// 先发布的键为准(CC-83):这个子代已经按 UUID 上过屏 ⇒ 行帧改写成 UUID 发,并记 尾段 → UUID 供 fleet 侧 end 改写;不登记尾段钥匙。
|
|
439
285
|
const rowCycle = { ...(ev.cycleSeq !== undefined ? { cycleSeq: ev.cycleSeq } : {}), ...(ev.startedAt !== undefined ? { startedAt: ev.startedAt } : {}) };
|
|
440
286
|
const published = wireOwnerOf(ev.taskId, rowCycle, ev.transcriptId) ?? publishedWireFor(ev);
|
|
441
287
|
if (published !== undefined && published !== ev.taskId) {
|
|
@@ -463,7 +309,6 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
463
309
|
remember(fleetIdByTranscriptId, ev.transcriptId, alias);
|
|
464
310
|
if (ev.parentToolCallId !== undefined && ev.parentToolCallId.length > 0)
|
|
465
311
|
remember(fleetIdByParentToolCallId, ev.parentToolCallId, alias);
|
|
466
|
-
// 先发行帧再放缓着的 tick:tick 一到 fleet lane 就永久让位,行帧说的话(transcriptId / startedAt)得先落在行上。
|
|
467
312
|
deliverEngineAgentPanelEvent(ev);
|
|
468
313
|
for (const [wireId, held] of [...heldWireTicks]) {
|
|
469
314
|
if (wireId === ev.transcriptId || (held.ev.parentToolCallId !== undefined && held.ev.parentToolCallId === ev.parentToolCallId))
|
|
@@ -473,8 +318,6 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
473
318
|
return;
|
|
474
319
|
}
|
|
475
320
|
case 'tick': {
|
|
476
|
-
// 先发布的键为准也管 tick 自己(异源复审 R2 [high]):这把 UUID 已经是消费端的键,之后的 tick 不再经退路键归一到尾段
|
|
477
|
-
//(否则复活后同一张卡的退路键把前代 UUID 的迟到 tick 拉进新周期的行)。
|
|
478
321
|
if (publishedWireIds.has(ev.taskId)) {
|
|
479
322
|
heldWireTicks.delete(ev.taskId);
|
|
480
323
|
deliverEngineAgentPanelEvent(asIsTick(ev));
|
|
@@ -484,7 +327,7 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
484
327
|
if (id.origin === 'fleet-row') {
|
|
485
328
|
heldWireTicks.delete(ev.taskId);
|
|
486
329
|
if (staleWireTick(id))
|
|
487
|
-
return;
|
|
330
|
+
return;
|
|
488
331
|
rememberResolvedWire(ev.taskId, id);
|
|
489
332
|
deliverEngineAgentPanelEvent(normalizedTick(ev, id.taskId));
|
|
490
333
|
return;
|
|
@@ -494,7 +337,6 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
494
337
|
return;
|
|
495
338
|
}
|
|
496
339
|
if (heldWireTicks.has(ev.taskId)) {
|
|
497
|
-
// 第二拍还没等到 fleet-row ⇒ 不再等:新的原样发,旧的丢(progress 合并语义,旧拍没有信息)。
|
|
498
340
|
heldWireTicks.delete(ev.taskId);
|
|
499
341
|
deliverEngineAgentPanelEvent(asIsTick(ev));
|
|
500
342
|
return;
|
|
@@ -508,11 +350,6 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
508
350
|
return;
|
|
509
351
|
}
|
|
510
352
|
case 'end': {
|
|
511
|
-
// 0.75.0 W2:缓着的「首见即终态」行**先于一切归一**放出(异源复审 R3 [high]:放出的行帧会登记钥匙 / 所有权,之后的 end 归一必须看到它,
|
|
512
|
-
// 否则同一子代长成 UUID 行 + 尾段行两行)。
|
|
513
|
-
// 🔴 0.75.1 —— 前三把键的**真实射程**(实测反例):尾段本身 / UUID 经钥匙解析到的尾段 / 这把 UUID 名下的反向所有权尾段,
|
|
514
|
-
// 后两把**只在行帧真发布过时才登记**,而缓行的定义就是「还没发布」⇒ `tick{UUID}` 先上屏、终态行 `{尾段, transcriptId: UUID}`
|
|
515
|
-
// 被缓住时,这三把全查不到,缓行永远放不出。所以有第四条腿:按缓行**自带的** wire 侧键(transcriptId / 退路键)反查。
|
|
516
353
|
releaseHeldNewbornTerminal(ev.taskId, ev);
|
|
517
354
|
{
|
|
518
355
|
const pre = resolveEnginePanelTaskId(ev.taskId);
|
|
@@ -525,13 +362,10 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
525
362
|
for (const [fleetId, o] of wireIdByFleetId)
|
|
526
363
|
if (o.wireId === ev.taskId && !o.retired)
|
|
527
364
|
releaseHeldNewbornTerminal(fleetId, ev);
|
|
528
|
-
// 第四条腿:缓着的行自带 `transcriptId`(主键)与委派卡 id(退路键)—— 两把与 `publishedWireFor` 的**同一条律**:
|
|
529
|
-
// 转录键命中不看退役(同一子代的迟到终态);退路键只认**未退役**的那把 wire 键(复活沿用同一张卡)。
|
|
530
|
-
// 放行仍走 `releaseHeldNewbornTerminal`(代际三向 peek + 经原漏斗归一),所以前代的缓行会被当代终态作废而不是盖上去。
|
|
531
365
|
const heldMatches = [];
|
|
532
366
|
for (const ref of heldNewbornTerminalRefs()) {
|
|
533
367
|
if (ref.taskId === ev.taskId)
|
|
534
|
-
continue;
|
|
368
|
+
continue;
|
|
535
369
|
const byTranscript = ref.transcriptId !== undefined && ref.transcriptId === ev.taskId;
|
|
536
370
|
const byParent = ref.parentToolCallId !== undefined &&
|
|
537
371
|
publishedWireByParent.get(ref.parentToolCallId) === ev.taskId &&
|
|
@@ -539,30 +373,6 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
539
373
|
if (byTranscript || byParent)
|
|
540
374
|
heldMatches.push(ref.taskId);
|
|
541
375
|
}
|
|
542
|
-
// 命中之后**先逐条按代际三向判、不动表**,再决定放谁:
|
|
543
|
-
// · 可证更旧的缓行(前代那一行)⇒ 当场作废(它的用量不许盖当代);
|
|
544
|
-
// · end 可证更旧 ⇒ 那条缓行留着,等属于它自己的那条 end;
|
|
545
|
-
// · 剩下的「可放行」候选**恰一条** ⇒ 放行 —— 它一上屏就登记了自己的钥匙 / 所有权,本条 end 随后在主路上
|
|
546
|
-
// 归一到同一把键,所以仍是「一行一条 end」。
|
|
547
|
-
// · 🔴 候选 **≥2**(两个行尾段自称同一个转录锚 / 同一张委派卡)= **身份两义 ⇒ 一条都不放**:转录钥匙表是
|
|
548
|
-
// **单值**的(后写覆盖先写),放两条就会各自上屏成两行而主路只归一到最后那一条 ⇒ 前面那些行永远收不到结算;
|
|
549
|
-
// 换成「每行各自补一条 end」则要在这里替主路决定消费端键,会吞掉原 wire 键那一行自己的终态。身份对不上就
|
|
550
|
-
// **一帧都不摘**是本包扣留表的既有律(见 `hitl/gateLedger.ts` 的「判不出 ⇒ 一条都不摘」)。代价 = 这种形下
|
|
551
|
-
// 那几条行的用量仍缺席(与本件修之前同),换来的是绝不凭空多长一行、绝不替谁编一条终态。
|
|
552
|
-
// 🔴 **理由更正(0.76.0;外部验收方 [7764] 逐条回一级源码亲核后证伪了本句旧版)**:旧注释写的是「两个行尾段共享一个
|
|
553
|
-
// **转录锚**不成立(转录锚按代际唯一),所以这一支是防御面」—— 那句话**只论证了转录钥匙那条腿**,而 `heldMatches`
|
|
554
|
-
// 是**转录锚腿 ∪ 委派卡腿**的并集,两条腿异质:
|
|
555
|
-
// · 委派卡那条腿的前提**为假** —— workflow 扇出下一张卡整跑冻结成常量、尾段逐 callKey 不同,**最多 50 个**
|
|
556
|
-
// 尾段共享同一张卡且可同时在飞(上游坐标:core `workflow.ts` 的 `bceParentToolCall` 与 `waIdOf(callKey)`;
|
|
557
|
-
// 默认 `maxAgents` 50)。这正是本包 lane 判据里 `workflow-card-parent` 那一支的上游本体。
|
|
558
|
-
// 🔴 上游当事方 09-20 直讯确认了这一形:**一次扇出的全部子代共享同一张 `parentToolCallId`**(那次 workflow
|
|
559
|
-
// 工具调用自己的卡),逐子代能区分的键**只有 `taskId`**(`wa*` 形)—— 也就是说委派卡这条腿在扇出下**天然多对一**。
|
|
560
|
-
// · 更要紧:**凑够 ≥2 根本不需要两行共享任何一个键** —— 一行只经转录锚命中、另一行只经委派卡命中即可。
|
|
561
|
-
// ⇒ 今天这一支之所以罕见,**靠的不是上面那条律**,而是「workflow 子代的 tick 被 lane 门拦掉 ⇒ 委派卡那条腿的
|
|
562
|
-
// `publishedWireByParent` 没有写入」这条**更脆**的保证 —— 它历史上塌过(上游投影白名单曾把 `workflowRunId` 整个剥掉)。
|
|
563
|
-
// **失效条件**:workflow 子代的 tick 一旦上屏(白名单变宽 / lane 门放行),这一支立刻变成常态路径。
|
|
564
|
-
// 所以本分支**不是**「理论上才会走到的防御面」,它是**有真上游机制**的一支,只是今天被一条脆保证挡着。
|
|
565
|
-
// 🔴 无论放没放,**主路照走**:原 wire 键那一行(它可能早就上过屏)自己的 end 绝不能被这条腿吞掉。
|
|
566
376
|
const releasable = [];
|
|
567
377
|
for (const tail of heldMatches) {
|
|
568
378
|
const verdict = heldNewbornTerminalVerdict(tail, ev);
|
|
@@ -574,13 +384,11 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
574
384
|
if (releasable.length === 1)
|
|
575
385
|
releaseHeldNewbornTerminal(releasable[0], ev);
|
|
576
386
|
}
|
|
577
|
-
// 先发布的键为准(CC-83):尾段已被改写成 UUID 的子代,fleet 侧(投影 / 通知)的 end{尾段} 也改写成 UUID
|
|
578
387
|
const wireOwner = wireOwnerOf(ev.taskId, ev);
|
|
579
388
|
if (wireOwner !== undefined) {
|
|
580
389
|
const ownerRec = wireIdByFleetId.get(ev.taskId);
|
|
581
390
|
const staleA = endOlderThanKnown(ev, ev.taskId, ownerRec) || isStaleEngineAgentPanelEnd(ev, panelRowEndedIdentity(wireOwner));
|
|
582
391
|
deliverEngineAgentPanelEvent({ ...ev, taskId: wireOwner, wireTaskId: ev.taskId, taskIdOrigin: 'wire' });
|
|
583
|
-
// 前代迟到的 end(比所有权登记时的周期旧)只过境让消费端判陈旧,不退役当代所有权(异源复审 R3)、不销当代 running 历史
|
|
584
392
|
if (!staleA) {
|
|
585
393
|
retireWire(wireOwner);
|
|
586
394
|
settleRowHistory(ev.taskId, ev);
|
|
@@ -589,9 +397,7 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
589
397
|
return;
|
|
590
398
|
}
|
|
591
399
|
if (publishedWireIds.has(ev.taskId)) {
|
|
592
|
-
// 这把 UUID 是先发布的键 ⇒ 它的 end 落在它自己的行上(不归一;一把已发布的键永远不改写)
|
|
593
400
|
flushHeld(ev.taskId);
|
|
594
|
-
// 这把 UUID 名下的尾段(反向所有权 / 转录别名)在投影里以尾段记账(复审 R3 [medium]),各自带周期守卫:先放缓着的终态行,end 之后再销
|
|
595
401
|
const ownedFleetIds = [];
|
|
596
402
|
for (const [fleetId, o] of wireIdByFleetId) {
|
|
597
403
|
if (o.wireId === ev.taskId && !endOlderThanKnown(ev, fleetId, o))
|
|
@@ -602,7 +408,6 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
602
408
|
ownedFleetIds.push(alias.fleetId);
|
|
603
409
|
deliverEngineAgentPanelEvent(ev);
|
|
604
410
|
retireWire(ev.taskId);
|
|
605
|
-
// UUID 自己的 ended 账也带守卫(end(U,2) 之后的 end(U,1) 不倒写)
|
|
606
411
|
if (!isStaleEngineAgentPanelEnd(ev, panelRowEndedIdentity(ev.taskId)))
|
|
607
412
|
settleRowHistory(ev.taskId, ev);
|
|
608
413
|
for (const fleetId of ownedFleetIds)
|
|
@@ -611,10 +416,8 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
611
416
|
}
|
|
612
417
|
const id = resolveEnginePanelTaskId(ev.taskId);
|
|
613
418
|
if (id.origin === 'fleet-row' && id.taskId !== ev.taskId) {
|
|
614
|
-
flushHeld(ev.taskId);
|
|
419
|
+
flushHeld(ev.taskId);
|
|
615
420
|
migrateResidency(ev.taskId, id.taskId);
|
|
616
|
-
// 任何 lane 的 end 到漏斗 = 这一行结了 ⇒ running 历史销账(只销当代:前代迟到的 end 不擦新一代;异源复审 0.74.5 R2)
|
|
617
|
-
// 🔴 用与递达**同一个**有效身份判(事件自带的周期优先、缺席才借钥匙;复审 R3 [high]:按钥匙判会把 end{cycle 1} 当成当代)
|
|
618
421
|
const effectiveEnd = {
|
|
619
422
|
...(ev.cycleSeq !== undefined ? { cycleSeq: ev.cycleSeq } : id.cycleSeq !== undefined ? { cycleSeq: id.cycleSeq } : {}),
|
|
620
423
|
...(ev.startedAt !== undefined ? { startedAt: ev.startedAt } : id.startedAt !== undefined ? { startedAt: id.startedAt } : {}),
|
|
@@ -625,7 +428,6 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
625
428
|
taskId: id.taskId,
|
|
626
429
|
wireTaskId: ev.taskId,
|
|
627
430
|
taskIdOrigin: 'fleet-row',
|
|
628
|
-
// end 自己不带周期身份(流内 close 臂恒不带)⇒ 借钥匙上的:复活后迟到的 end{旧 UUID} 由此带着旧代际,消费端按 isStaleEngineAgentPanelEnd 挡掉
|
|
629
431
|
...(ev.cycleSeq === undefined && id.cycleSeq !== undefined ? { cycleSeq: id.cycleSeq } : {}),
|
|
630
432
|
...(ev.startedAt === undefined && id.startedAt !== undefined ? { startedAt: id.startedAt } : {}),
|
|
631
433
|
});
|
|
@@ -633,23 +435,19 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
633
435
|
settleRowHistory(id.taskId, effectiveEnd);
|
|
634
436
|
return;
|
|
635
437
|
}
|
|
636
|
-
flushHeld(ev.taskId);
|
|
637
|
-
// 通知车道 / fleet 投影铸的 end(尾段键):只对当代(前代迟到的 end 带旧 seq / cycleSeq ⇒ 不擦历史、不放缓着的行)
|
|
438
|
+
flushHeld(ev.taskId);
|
|
638
439
|
const staleD = endOlderThanKnown(ev, ev.taskId, latestCycleByFleetId.get(ev.taskId));
|
|
639
440
|
deliverEngineAgentPanelEvent(ev);
|
|
640
|
-
retireWire(ev.taskId);
|
|
441
|
+
retireWire(ev.taskId);
|
|
641
442
|
if (!staleD)
|
|
642
443
|
settleRowHistory(ev.taskId, ev);
|
|
643
444
|
return;
|
|
644
445
|
}
|
|
645
446
|
default:
|
|
646
|
-
// sweep:缓着的 tick 不放(见头注)—— 原样进主通道。
|
|
647
447
|
deliverEngineAgentPanelEvent(ev);
|
|
648
448
|
}
|
|
649
449
|
}
|
|
650
450
|
function deliverEngineAgentPanelEvent(ev) {
|
|
651
|
-
// 同 taskId 的任何主通道事实(tick / fleet-row = 行在场;end = 真终态)都让**缓冲里**那条缺席过期 —— 迟订阅的消费者
|
|
652
|
-
// 不许先恢复了行、再被一条旧缺席标成 unknown(已递达订阅者的缺席由订阅者按契约在这些事件上撤标)。
|
|
653
451
|
if (ev.kind !== 'sweep')
|
|
654
452
|
absenceBuffer.delete(ev.taskId);
|
|
655
453
|
if (listener) {
|
|
@@ -657,53 +455,15 @@ function deliverEngineAgentPanelEvent(ev) {
|
|
|
657
455
|
listener(ev);
|
|
658
456
|
}
|
|
659
457
|
catch {
|
|
660
|
-
// A consumer render error must never tear down the bridge's stream drain.
|
|
661
458
|
}
|
|
662
459
|
return;
|
|
663
460
|
}
|
|
664
|
-
// Buffered (panel not mounted yet / temporarily unmounted).
|
|
665
|
-
//
|
|
666
|
-
// Two event CLASSES, and every buffering rule below keys off the class (not off one kind):
|
|
667
|
-
// · PROGRESS ('tick' / 'fleet-row') — cumulative rollups off the two live lanes. Only the latest
|
|
668
|
-
// one per taskId carries information, so they COALESCE per (kind, taskId) and they are the ones
|
|
669
|
-
// that yield when the buffer is full.
|
|
670
|
-
// · LIFECYCLE ('end' / 'sweep') — each one is a distinct fact that settles a row. They are never
|
|
671
|
-
// the ones squeezed out by a long unmount (adversarial review w0zwpa251 #4: dropping a buffered
|
|
672
|
-
// 'end' left a row running forever).
|
|
673
|
-
//
|
|
674
|
-
// 🔴 [F4957-2] (0.41.0) the full-buffer arm used to look ONLY for a 'tick' to evict and then pushed
|
|
675
|
-
// UNCONDITIONALLY even when it found none — so a stream carrying no ticks at all (the 'fleet-row'
|
|
676
|
-
// lane is exactly that: background subagents never reach the panel through 'task_progress', see the
|
|
677
|
-
// fleet-row arm's own header) grew the buffer without bound. MAX_BUFFER is a memory bound on
|
|
678
|
-
// UNTRUSTED wire volume; it has to hold for every kind mix, not just the one the first version had
|
|
679
|
-
// in mind.
|
|
680
|
-
// Adjacent 'sweep' dedup. A sweep settles every row the consumer still has running and its own doc
|
|
681
|
-
// calls it idempotent, so a sweep whose immediate predecessor is a sweep is a strict no-op — nothing
|
|
682
|
-
// happened in between that it could settle differently. Dropping it is not a micro-optimisation: a
|
|
683
|
-
// long unmount publishes one sweep per turn, and 200 of them fill the buffer with pure lifecycle
|
|
684
|
-
// events, after which every post-barrier progress event has to yield (that is the other half of the
|
|
685
|
-
// bounded policy) — a subagent that starts at that point would replay as "still settled", forever.
|
|
686
461
|
if (ev.kind === 'sweep' && buffer.length > 0 && buffer[buffer.length - 1]?.kind === 'sweep')
|
|
687
462
|
return;
|
|
688
463
|
const progress = ev.kind === 'tick' || ev.kind === 'fleet-row';
|
|
689
464
|
if (progress) {
|
|
690
465
|
const kind = ev.kind;
|
|
691
466
|
const taskId = ev.taskId;
|
|
692
|
-
// Search BACKWARDS for a merge target and STOP at the first barrier. The bar for the whole buffer
|
|
693
|
-
// is "replaying it leaves the consumer in the same state as if the panel had been mounted all
|
|
694
|
-
// along", and each barrier below is a place where the consumer's state machine changes what a
|
|
695
|
-
// later event means — so an event on the far side of one cannot be folded into an event on this
|
|
696
|
-
// side (0.41.0 adversarial review #5 and #6):
|
|
697
|
-
// · 'sweep' (global) and 'end' for this taskId — they SETTLE the row, and the consumer ignores
|
|
698
|
-
// progress for a settled row. Live: `tick(v1) → sweep → tick(v2)` builds the row, settles it,
|
|
699
|
-
// then drops v2 → the row ends settled. Folded into `sweep → tick(v2)` the replay sweeps an
|
|
700
|
-
// empty table and then v2 BUILDS a running row — a ghost that live delivery never produces.
|
|
701
|
-
// · the OTHER progress lane for this taskId — the fleet-row arm's own header states that a
|
|
702
|
-
// 'tick' makes the fleet lane hand the row over PERMANENTLY, so what the fleet lane said
|
|
703
|
-
// BEFORE the handover (transcriptId / startedAt, often carried by exactly one frame) would
|
|
704
|
-
// land after it and never be applied.
|
|
705
|
-
// Barriers cost buffer slots, and that is the right trade: the bound is still enforced by the
|
|
706
|
-
// eviction policy below, while a wrong fold is silently wrong forever.
|
|
707
467
|
let i = -1;
|
|
708
468
|
for (let at = buffer.length - 1; at >= 0; at--) {
|
|
709
469
|
const b = buffer[at];
|
|
@@ -717,29 +477,13 @@ function deliverEngineAgentPanelEvent(ev) {
|
|
|
717
477
|
continue;
|
|
718
478
|
}
|
|
719
479
|
if (b.taskId !== taskId)
|
|
720
|
-
continue;
|
|
721
|
-
// 0.73.0:launch 锚变了 = 同一个 taskId 的**新周期**,也是一道屏障。逐键合并的「省略的键沿用旧值」只在同一周期内
|
|
722
|
-
// 成立;跨周期合并会把上一周期的 totalTokens / toolUses 继承进新周期(投影层刻意省略的键被缓冲层补了回来)。
|
|
480
|
+
continue;
|
|
723
481
|
if (b.kind === kind && !launchAnchorChanged(b, ev))
|
|
724
482
|
i = at;
|
|
725
|
-
break;
|
|
483
|
+
break;
|
|
726
484
|
}
|
|
727
485
|
if (i >= 0) {
|
|
728
|
-
// 🔴 Coalescing must not DROP sticky keys either (0.41.0 adversarial review #4). Both progress
|
|
729
|
-
// lanes are published as PARTIAL frames — the projection emits `...(toolUses !== undefined ?
|
|
730
|
-
// { toolUses } : {})` and friends, and an absent key means "this frame didn't say, keep what the
|
|
731
|
-
// row already has" (the three-state rule on the fleet-row arm above). A mounted panel therefore
|
|
732
|
-
// still shows the `toolUses` that arrived on v1 after a v2 that only moved `totalTokens`; a
|
|
733
|
-
// replay that kept only v2 would lose it for good. So the surviving copy is a per-key merge
|
|
734
|
-
// (later frame wins per key, keys it omits are inherited), not a wholesale replacement.
|
|
735
486
|
const merged = { ...buffer[i], ...ev };
|
|
736
|
-
// 🔴 Coalescing must not REORDER across a lifecycle barrier (0.41.0 adversarial review #2).
|
|
737
|
-
// Overwriting in place rewrites `progress(A,v1) → end(A) → progress(A,v2)` into
|
|
738
|
-
// `progress(A,v2) → end(A)` — the post-settle rollup is moved BEFORE the settle, so a row that
|
|
739
|
-
// was revived (the fleet projection explicitly allows a settled row to run again) gets settled
|
|
740
|
-
// by the replay again, with the revived progress applied to the dead cycle. The bar for a
|
|
741
|
-
// buffered replay is "same result as if the panel had been mounted the whole time", so the
|
|
742
|
-
// surviving copy has to keep the LATEST event's arrival position: drop the old one, append.
|
|
743
487
|
buffer.splice(i, 1);
|
|
744
488
|
buffer.push(merged);
|
|
745
489
|
return;
|
|
@@ -749,31 +493,15 @@ function deliverEngineAgentPanelEvent(ev) {
|
|
|
749
493
|
buffer.push(ev);
|
|
750
494
|
return;
|
|
751
495
|
}
|
|
752
|
-
// Full: the oldest PROGRESS event yields (its taskId's next rollup supersedes it anyway).
|
|
753
496
|
const evictAt = buffer.findIndex(b => b.kind === 'tick' || b.kind === 'fleet-row');
|
|
754
497
|
if (evictAt >= 0) {
|
|
755
498
|
buffer.splice(evictAt, 1);
|
|
756
499
|
buffer.push(ev);
|
|
757
500
|
return;
|
|
758
501
|
}
|
|
759
|
-
// Nothing but lifecycle events in a full buffer (MAX_BUFFER rows settled while the panel stayed
|
|
760
|
-
// unmounted — 200 distinct 'end's is the realistic way there, the adjacent-sweep dedup above having
|
|
761
|
-
// removed the cheap one). At a finite bound something must give, and the rule is NEWEST-WINS for
|
|
762
|
-
// every kind: the oldest event yields, whatever it is.
|
|
763
|
-
//
|
|
764
|
-
// 🔴 Why not "progress yields here too" (which is what this arm used to do — adversarial review
|
|
765
|
-
// round 7, finding #4): a progress event arriving at this point is the ONLY word the panel will
|
|
766
|
-
// ever get about a row that was created or revived after the barrier — `projectFleetAgentRows`
|
|
767
|
-
// emits on CHANGE, so a row that then goes quiet never speaks again. Dropping it makes that row
|
|
768
|
-
// permanently invisible after a remount, which is a strictly worse loss than dropping the OLDEST
|
|
769
|
-
// lifecycle event: that one settles a row that finished ~MAX_BUFFER events ago, and the sweep that
|
|
770
|
-
// every turn publishes (newest ⇒ always survives) settles whatever is still running anyway.
|
|
771
|
-
// The residual — an old 'end' can be dropped, taking its `report`/`isError` with it — is the honest
|
|
772
|
-
// price of a bounded buffer and is registered in CHANGELOG 0.41.0 "已知局限".
|
|
773
502
|
buffer.shift();
|
|
774
503
|
buffer.push(ev);
|
|
775
504
|
}
|
|
776
|
-
/** Single consumer (the panel hook). Replays any buffered events, returns an unsubscribe. */
|
|
777
505
|
export function subscribeEngineAgentPanel(fn) {
|
|
778
506
|
listener = fn;
|
|
779
507
|
if (buffer.length > 0) {
|
|
@@ -783,7 +511,6 @@ export function subscribeEngineAgentPanel(fn) {
|
|
|
783
511
|
fn(ev);
|
|
784
512
|
}
|
|
785
513
|
catch {
|
|
786
|
-
// ignore — same guard as publish
|
|
787
514
|
}
|
|
788
515
|
}
|
|
789
516
|
}
|
|
@@ -794,11 +521,8 @@ export function subscribeEngineAgentPanel(fn) {
|
|
|
794
521
|
}
|
|
795
522
|
const MAX_ABSENCE_BUFFER = 200;
|
|
796
523
|
let absenceListener = null;
|
|
797
|
-
/** 未订阅时的缓冲:按 taskId 留最新一条(同一行只有最新一次缺席有信息),有上界(最旧的先让位)。 */
|
|
798
524
|
const absenceBuffer = new Map();
|
|
799
|
-
/** 发布一条缺席上报(由 `projectFleetAgentRows` 的缺席路径调;消费者抛错不反噬投影)。 */
|
|
800
525
|
export function publishEngineAgentPanelAbsence(ev) {
|
|
801
|
-
// 0.74.4 CC-83(异源复审 R1 [medium]):尾段已归先发布的 UUID 所有 ⇒ 缺席也按那把键发(主通道与侧信道同一把键),原尾段进 wireTaskId
|
|
802
526
|
const owner = wireOwnerOf(ev.taskId);
|
|
803
527
|
if (owner !== undefined)
|
|
804
528
|
ev = { ...ev, taskId: owner, wireTaskId: ev.taskId };
|
|
@@ -807,7 +531,6 @@ export function publishEngineAgentPanelAbsence(ev) {
|
|
|
807
531
|
absenceListener(ev);
|
|
808
532
|
}
|
|
809
533
|
catch {
|
|
810
|
-
// A consumer render error must never tear down the projection.
|
|
811
534
|
}
|
|
812
535
|
return;
|
|
813
536
|
}
|
|
@@ -819,7 +542,6 @@ export function publishEngineAgentPanelAbsence(ev) {
|
|
|
819
542
|
absenceBuffer.delete(oldest);
|
|
820
543
|
}
|
|
821
544
|
}
|
|
822
|
-
/** 单消费者(面板 hook)。订阅即回放缓冲,返回取消订阅。不订阅 = 行为与 0.72.11 的壳完全相同(行停在最后已知态)。 */
|
|
823
545
|
export function subscribeEngineAgentPanelAbsence(fn) {
|
|
824
546
|
absenceListener = fn;
|
|
825
547
|
if (absenceBuffer.size > 0) {
|
|
@@ -830,7 +552,6 @@ export function subscribeEngineAgentPanelAbsence(fn) {
|
|
|
830
552
|
fn(ev);
|
|
831
553
|
}
|
|
832
554
|
catch {
|
|
833
|
-
// ignore — same guard as publish
|
|
834
555
|
}
|
|
835
556
|
}
|
|
836
557
|
}
|
|
@@ -839,7 +560,6 @@ export function subscribeEngineAgentPanelAbsence(fn) {
|
|
|
839
560
|
absenceListener = null;
|
|
840
561
|
};
|
|
841
562
|
}
|
|
842
|
-
/** 测试钩:清缺席口的订阅与缓冲。 */
|
|
843
563
|
export function __resetEngineAgentPanelAbsenceForTests() {
|
|
844
564
|
absenceListener = null;
|
|
845
565
|
absenceBuffer.clear();
|