newmark-agent 0.6.3 → 0.6.4

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.
@@ -126970,6 +126970,23 @@ var SkillsManager = class {
126970
126970
  // src/core/agent.ts
126971
126971
  init_flow();
126972
126972
 
126973
+ // src/core/branchIdentity.ts
126974
+ var BRANCH_IDENTITY_SEPARATOR = "::branch:";
126975
+ function branchConversationIdentity(conversationId, branchNodeId) {
126976
+ const conversation = String(conversationId || "").trim() || "default";
126977
+ const branch = String(branchNodeId || "").trim();
126978
+ return branch ? `${conversation}${BRANCH_IDENTITY_SEPARATOR}${branch}` : conversation;
126979
+ }
126980
+ function assertFreshBranchIdentity(conversationId, branchNodeId, existing) {
126981
+ const branch = String(branchNodeId || "").trim();
126982
+ if (!branch) throw new Error("Branch conversation identity requires a branch node id.");
126983
+ for (const known of existing) {
126984
+ if (String(known || "") === branch) {
126985
+ throw new Error(`Branch conversation identity ${branchConversationIdentity(conversationId, branch)} is already in use.`);
126986
+ }
126987
+ }
126988
+ }
126989
+
126973
126990
  // src/core/agentKernelRunner.ts
126974
126991
  var fs19 = __toESM(require("fs"));
126975
126992
  var path21 = __toESM(require("path"));
@@ -128050,10 +128067,16 @@ var HIDDEN_LINE_PREFIXES = [
128050
128067
  ];
128051
128068
  function providerSessionIdentity(agent) {
128052
128069
  const conversationId = String(agent.activeConversationId || "default");
128070
+ let runBranchId = "";
128071
+ try {
128072
+ runBranchId = String(agent.activeWorkRunBranchId() || "");
128073
+ } catch {
128074
+ runBranchId = "";
128075
+ }
128076
+ if (runBranchId) return branchConversationIdentity(conversationId, runBranchId);
128053
128077
  try {
128054
128078
  const snapshot2 = agent.getConversationSnapshot(conversationId);
128055
- const branchId = String(snapshot2.runtimeBranchId || snapshot2.activeBranchId || "");
128056
- return branchId ? `${conversationId}::branch:${branchId}` : conversationId;
128079
+ return branchConversationIdentity(conversationId, String(snapshot2.runtimeBranchId || snapshot2.activeBranchId || ""));
128057
128080
  } catch {
128058
128081
  return conversationId;
128059
128082
  }
@@ -132801,6 +132824,22 @@ var Agent5 = class _Agent {
132801
132824
  currentWorkRunId() {
132802
132825
  return this.activeWorkRunId || this.finalizingWorkRunId || "";
132803
132826
  }
132827
+ /**
132828
+ * The branch node that owns the currently active Build. Provider session ids
132829
+ * and branch-scoped caches must use this identity instead of "the branch that
132830
+ * happens to be active", otherwise a concurrently running sibling branch
132831
+ * (branch-communication mode) or a page switched mid-Build would read another
132832
+ * branch's remote session and folded history.
132833
+ */
132834
+ activeWorkRunBranchId() {
132835
+ const runId = this.currentWorkRunId();
132836
+ const run = runId ? this.workRuns.find((item) => String(item.runId || "") === runId) : void 0;
132837
+ return String(run?.branchNodeId || "") || this.currentBranchNodeId();
132838
+ }
132839
+ /** Full conversation identity of one branch node (shared by every branch kind). */
132840
+ branchConversationIdentity(branchNodeId) {
132841
+ return branchConversationIdentity(this.activeConversationId || "default", branchNodeId);
132842
+ }
132804
132843
  activeModelConfig() {
132805
132844
  const deployment = this.activeDeployment();
132806
132845
  return deployment ? this.config.findDeployment(deployment) : this.config.findModel(this.model);
@@ -135039,6 +135078,7 @@ ${next2.body}`;
135039
135078
  });
135040
135079
  const reusableGroup = Object.values(tree.branchGroups).find((group) => group.sourceNodeId === parentNodeId && (targetGuideNodeId && group.sourceGuideId === targetGuideNodeId || !targetGuideNodeId && targetMessageId && group.sourceMessageId === targetMessageId || !group.sourceGuideId && !group.sourceMessageId && group.sourceMessageIndex === index2) || group.nodeIds.includes(parentNodeId) && group.sourceMessageIndex === index2 && (targetGuideNodeId && group.pageGuideIds?.[parentNodeId] === targetGuideNodeId || !targetGuideNodeId && targetMessageId && group.pageMessageIds?.[parentNodeId] === targetMessageId));
135041
135080
  const branchId = crypto15.randomUUID();
135081
+ assertFreshBranchIdentity(clean || this.activeConversationId || "default", branchId, Object.keys(tree.nodes));
135042
135082
  const branch = this.treeNodeFromEntry(branchId, parentNodeId, index2, text3, {
135043
135083
  ...entry,
135044
135084
  chatMessages: sourceNode.chatMessages.slice(0, index2),
@@ -135623,7 +135663,7 @@ Conversation title (a few words):`;
135623
135663
  chatMessages: [...this.chatMessages],
135624
135664
  history: [...this.history],
135625
135665
  providerUsage: this.conversationProviderUsage(),
135626
- compressionCache: [...this.compressionCache],
135666
+ compressionCache: this.mergedCompressionCacheForPersist(stored.conversations[stateKey2]),
135627
135667
  branchMailbox: [...this.branchMailbox],
135628
135668
  branchCommunication: this.branchCommunicationEnabled,
135629
135669
  plan: this.normalizeConversationPlan(this.conversationPlan),
@@ -135681,7 +135721,7 @@ Conversation title (a few words):`;
135681
135721
  if (saved) {
135682
135722
  this.restoreProviderUsage(saved.providerUsage);
135683
135723
  this.history = [...saved.history];
135684
- this.compressionCache = saved.compressionCache ? saved.compressionCache.map((entry) => ({ ...entry, messages: [...entry.messages] })) : [];
135724
+ this.compressionCache = this.compressionCacheForBranch(saved.compressionCache);
135685
135725
  this.nextCompressionCacheId = Math.max(1, ...this.compressionCache.map((entry) => Number(entry.id.replace(/^ctx-cache-/, "")) || 0)) + 1;
135686
135726
  this.branchMailbox = (saved.branchMailbox || []).map((message) => ({ ...message }));
135687
135727
  this.nextBranchMessageSequence = Math.max(1, ...this.branchMailbox.map((message) => Number(message.sequence) || 0)) + 1;
@@ -135710,7 +135750,7 @@ Conversation title (a few words):`;
135710
135750
  this.restoreProviderUsage(persisted?.providerUsage);
135711
135751
  const repairedHistory = this.repairDanglingToolCalls(persisted?.history ? [...persisted.history] : []);
135712
135752
  this.history = repairedHistory.messages;
135713
- this.compressionCache = persisted?.compressionCache ? persisted.compressionCache.map((entry) => ({ ...entry, messages: [...entry.messages] })) : [];
135753
+ this.compressionCache = this.compressionCacheForBranch(persisted?.compressionCache);
135714
135754
  this.nextCompressionCacheId = Math.max(1, ...this.compressionCache.map((entry) => Number(entry.id.replace(/^ctx-cache-/, "")) || 0)) + 1;
135715
135755
  this.branchMailbox = (persisted?.branchMailbox || []).map((message) => ({ ...message }));
135716
135756
  this.nextBranchMessageSequence = Math.max(1, ...this.branchMailbox.map((message) => Number(message.sequence) || 0)) + 1;
@@ -140562,7 +140602,36 @@ ${text3.slice(-tailChars).trimStart()}`;
140562
140602
  }
140563
140603
  compressionArchiveScopeKey() {
140564
140604
  if (this.isSubagentRuntime || !this.config.getBool("context", "compression_archive_enabled")) return null;
140565
- return this.workspaceConversationKey();
140605
+ const base = this.workspaceConversationKey();
140606
+ if (!base) return null;
140607
+ return branchConversationIdentity(base, this.currentBranchNodeId());
140608
+ }
140609
+ /**
140610
+ * The hot folded-history cache belongs to one branch node. Legacy entries
140611
+ * (created before branch scoping) belong to the root node, which is where
140612
+ * they were produced.
140613
+ */
140614
+ compressionCacheForBranch(entries) {
140615
+ const branch = String(this.currentBranchNodeId() || "");
140616
+ const root3 = String(this.conversationTree()?.rootNodeId || "");
140617
+ return (Array.isArray(entries) ? entries : []).flatMap((entry) => {
140618
+ const owner = String(entry.branchNodeId || root3 || "");
140619
+ if (branch && owner && owner !== branch) return [];
140620
+ if (branch && !owner) return [];
140621
+ return [{ ...entry, branchNodeId: owner || branch || void 0, messages: [...entry.messages] }];
140622
+ });
140623
+ }
140624
+ /**
140625
+ * Persist the union of every branch's folded history: the live in-memory
140626
+ * cache only holds the active branch, and the stored entry holds the rest.
140627
+ */
140628
+ mergedCompressionCacheForPersist(storedEntry) {
140629
+ const branch = String(this.currentBranchNodeId() || "");
140630
+ const others = (storedEntry?.compressionCache || []).filter((entry) => {
140631
+ const owner = String(entry.branchNodeId || "");
140632
+ return !!owner && owner !== branch;
140633
+ });
140634
+ return [...others, ...this.compressionCache.map((entry) => ({ ...entry, messages: [...entry.messages] }))];
140566
140635
  }
140567
140636
  coldCompressionEntries() {
140568
140637
  const scopeKey = this.compressionArchiveScopeKey();
@@ -140625,7 +140694,8 @@ ${text3.slice(-tailChars).trimStart()}`;
140625
140694
  foldedEntries: messages.length,
140626
140695
  foldedChars,
140627
140696
  model,
140628
- fallback
140697
+ fallback,
140698
+ branchNodeId: this.currentBranchNodeId() || void 0
140629
140699
  });
140630
140700
  this.nextCompressionCacheId += 1;
140631
140701
  const maxEntries = Math.max(0, Math.floor(this.config.getNum("context", "compression_cache_max") || 8));
@@ -141706,6 +141776,81 @@ var GuardedContinuationStore = class {
141706
141776
  return { ...build2, input: cloneInput(build2.input) };
141707
141777
  });
141708
141778
  }
141779
+ /**
141780
+ * dev-0.6.4 hotfix: 当某个被受理的 Build 失败/取消后,它的后继会永远无法被
141781
+ * claim(`claimBuild` 只认「父 = 已提交 frontier」),整条队列就此卡死,新提交
141782
+ * 也只是接在失败链后面。
141783
+ *
141784
+ * 这里提供一条**显式**修复通道:把被阻断的排队 Build 重新挂到当前已提交的
141785
+ * frontier 上,保持原有队列顺序,并为每一次改挂写入 `BuildQueueRepaired`
141786
+ * 审计事件(记录旧 parent / 新 parent / 原因)。它不是静默 rebase:调用方是
141787
+ * 用户的显式动作(恢复队列)或一次新的入队命令。
141788
+ */
141789
+ repairBlockedQueue(input2) {
141790
+ return this.mutate((ledger) => {
141791
+ const branch = this.requireBranch(ledger, input2);
141792
+ const frontier = branch.headBuildId || null;
141793
+ const queued = Object.values(ledger.builds).filter((build2) => build2.branchId === branch.branchId && build2.status === "QUEUED").sort((a, b) => a.queueSequence - b.queueSequence);
141794
+ const repaired = [];
141795
+ let chainParent = frontier;
141796
+ let mutated = false;
141797
+ for (const build2 of queued) {
141798
+ if ((build2.parentBuildId || null) !== (chainParent || null)) {
141799
+ const previousParentBuildId = build2.parentBuildId;
141800
+ build2.parentBuildId = chainParent;
141801
+ build2.waitingReason = void 0;
141802
+ build2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
141803
+ repaired.push(build2.buildId);
141804
+ mutated = true;
141805
+ this.appendEvent(ledger, {
141806
+ type: "BuildQueueRepaired",
141807
+ workspaceId: this.workspaceId,
141808
+ rootId: branch.rootId,
141809
+ branchId: branch.branchId,
141810
+ buildId: build2.buildId,
141811
+ attemptId: null,
141812
+ fence: null,
141813
+ payload: {
141814
+ previousParentBuildId,
141815
+ newParentBuildId: chainParent,
141816
+ reason: String(input2.reason || "committed-frontier-repair")
141817
+ }
141818
+ });
141819
+ }
141820
+ chainParent = build2.buildId;
141821
+ }
141822
+ if (mutated) {
141823
+ branch.queueRevision += 1;
141824
+ branch.lifecycleRevision += 1;
141825
+ branch.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
141826
+ }
141827
+ return { repaired, frontier };
141828
+ });
141829
+ }
141830
+ /**
141831
+ * dev-0.6.4 hotfix: 读取视角的受阻推导。
141832
+ *
141833
+ * 一个 QUEUED Build 只有在它的父正好是「已提交 frontier」或队列里位于它之前
141834
+ * 的可执行 Build 时才可能被 claim(见 `claimBuild`)。这里按队列顺序推导哪些行
141835
+ * 目前不可执行:父不是链上前驱、或父已 FAILED/CANCELLED 的行即为受阻,且受阻点
141836
+ * 之后的所有行同样受阻。
141837
+ */
141838
+ blockedQueuedBuildIds(ledger, branch) {
141839
+ const blocked = /* @__PURE__ */ new Set();
141840
+ const queued = Object.values(ledger.builds).filter((build2) => build2.branchId === branch.branchId && build2.status === "QUEUED").sort((a, b) => a.queueSequence - b.queueSequence);
141841
+ let chainParent = branch.headBuildId || null;
141842
+ for (const build2 of queued) {
141843
+ const parent2 = build2.parentBuildId ? ledger.builds[build2.parentBuildId] : null;
141844
+ const parentIsChainPredecessor = (build2.parentBuildId || null) === (chainParent || null);
141845
+ const parentFailed = !!parent2 && (parent2.status === "FAILED" || parent2.status === "CANCELLED");
141846
+ if (!parentIsChainPredecessor || parentFailed) {
141847
+ blocked.add(build2.buildId);
141848
+ continue;
141849
+ }
141850
+ chainParent = build2.buildId;
141851
+ }
141852
+ return blocked;
141853
+ }
141709
141854
  deleteQueuedBuild(input2) {
141710
141855
  this.mutate((ledger) => {
141711
141856
  const build2 = ledger.builds[input2.buildId];
@@ -142107,7 +142252,12 @@ var GuardedContinuationStore = class {
142107
142252
  }
142108
142253
  snapshotUnlocked(ledger, branch) {
142109
142254
  const guard = ledger.guards[branch.branchId] || defaultGuard(branch.branchId);
142110
- const builds = Object.values(ledger.builds).filter((build2) => build2.branchId === branch.branchId).sort((a, b) => a.queueSequence - b.queueSequence).map((build2) => ({ ...build2, input: cloneInput(build2.input) }));
142255
+ const blockedBuildIds = this.blockedQueuedBuildIds(ledger, branch);
142256
+ const builds = Object.values(ledger.builds).filter((build2) => build2.branchId === branch.branchId).sort((a, b) => a.queueSequence - b.queueSequence).map((build2) => ({
142257
+ ...build2,
142258
+ input: cloneInput(build2.input),
142259
+ waitingReason: build2.waitingReason || (blockedBuildIds.has(build2.buildId) ? "DEPENDENCY_FAILED" : void 0)
142260
+ }));
142111
142261
  return {
142112
142262
  workspaceId: this.workspaceId,
142113
142263
  rootId: branch.rootId,
@@ -142710,11 +142860,25 @@ var ConversationKernel = class {
142710
142860
  queueItems(target) {
142711
142861
  const runtime = this.findRuntime(target);
142712
142862
  if (!runtime) return [];
142863
+ let waitingByBuildId = /* @__PURE__ */ new Map();
142864
+ const continuation = this.continuationStore(runtime);
142865
+ if (continuation) {
142866
+ try {
142867
+ const snapshot2 = continuation.store.snapshot({
142868
+ workspaceId: continuation.workspaceId,
142869
+ rootId: continuation.rootId,
142870
+ branchId: continuation.branchId
142871
+ });
142872
+ waitingByBuildId = new Map(snapshot2.builds.filter((build2) => !!build2.waitingReason).map((build2) => [build2.buildId, String(build2.waitingReason)]));
142873
+ } catch {
142874
+ }
142875
+ }
142713
142876
  return runtime.pendingNextTurn.flatMap((item) => {
142714
142877
  if (item.queueMode !== "followUp") return [];
142715
142878
  if (typeof item.message === "string") return [];
142716
142879
  const id = String(item.message.clientMessageId || "");
142717
142880
  if (!id) return [];
142881
+ const buildId = String(item.message.buildId || "");
142718
142882
  return [{
142719
142883
  id,
142720
142884
  buildId: item.message.buildId,
@@ -142727,7 +142891,9 @@ var ConversationKernel = class {
142727
142891
  images: item.message.images?.map((image) => ({ ...image })),
142728
142892
  branchNodeId: item.message.branchNodeId,
142729
142893
  branchPath: item.message.branchPath?.slice(),
142730
- modelSelection: item.message.modelSelection
142894
+ modelSelection: item.message.modelSelection,
142895
+ waitingReason: waitingByBuildId.get(buildId),
142896
+ blocked: waitingByBuildId.has(buildId)
142731
142897
  }];
142732
142898
  });
142733
142899
  }
@@ -143001,6 +143167,35 @@ ${text3}`;
143001
143167
  }
143002
143168
  return runtime.queuePaused;
143003
143169
  }
143170
+ /**
143171
+ * dev-0.6.4 hotfix: 显式修复被失败前置阻断的排队行。
143172
+ *
143173
+ * 0.6.3 的合约是「失败/取消阻断后继,且不静默跳过」,所以这里不挂在恢复动作上
143174
+ * 自动执行;它必须由用户的显式动作触发(界面上的“修复受阻队列”按钮)。每一次
143175
+ * 改挂都写入 `BuildQueueRepaired` 事件并发布可见状态,触发者与原因可审计。
143176
+ */
143177
+ repairBlockedQueueNow(runtime) {
143178
+ const continuation = this.continuationStore(runtime);
143179
+ if (!continuation) return 0;
143180
+ try {
143181
+ const result = continuation.store.repairBlockedQueue({
143182
+ workspaceId: continuation.workspaceId,
143183
+ rootId: continuation.rootId,
143184
+ branchId: continuation.branchId,
143185
+ reason: "explicit-user-repair"
143186
+ });
143187
+ if (result.repaired.length) {
143188
+ runtime.runner.recordWorkStatus(
143189
+ `${result.repaired.length} queued row(s) blocked by a failed predecessor were re-anchored to the last committed build; the queue resumes in order.`
143190
+ );
143191
+ this.schedulePendingRuntimeContinuation(runtime, runtime.runId);
143192
+ }
143193
+ return result.repaired.length;
143194
+ } catch (error2) {
143195
+ runtime.runner.recordWorkStatus(`Queue repair failed: ${error2 instanceof Error ? error2.message : String(error2)}`);
143196
+ return 0;
143197
+ }
143198
+ }
143004
143199
  queueAction(target, action, input2 = {}) {
143005
143200
  const normalized = this.normalizeTarget(target);
143006
143201
  const runtime = this.findRuntime(normalized) || this.runtime(normalized, {
@@ -143035,6 +143230,8 @@ ${text3}`;
143035
143230
  this.setQueuePaused(runtime.target, !runtime.queuePaused);
143036
143231
  } else if (action === "set_pause") {
143037
143232
  this.setQueuePaused(runtime.target, input2.paused === true);
143233
+ } else if (action === "repair_blocked") {
143234
+ this.repairBlockedQueueNow(runtime);
143038
143235
  } else if (action === "guide") {
143039
143236
  if (input2.text !== void 0) this.updateQueueItem(runtime.target, String(input2.id || ""), input2.text, input2);
143040
143237
  const item = this.queueItems(runtime.target).find((entry) => entry.id === String(input2.id || ""));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "newmark-agent",
3
3
  "productName": "Newmark Agent",
4
- "version": "0.6.3",
4
+ "version": "0.6.4",
5
5
  "description": "Newmark Agent — Portable AI coding agent with rich GUI and CLI (TypeScript)",
6
6
  "homepage": "https://github.com/positer/Newmark-Agent",
7
7
  "repository": {
@@ -60,7 +60,7 @@
60
60
  "test:desktop": "npm run build && node dist/tests/conversationHistoryFirstVerify.js && npm run test:desktop:built",
61
61
  "test:deletion-safety": "npm run build && npm run test:deletion-safety:built",
62
62
  "test:deletion-safety:built": "node scripts/deletion-safety-stress.cjs",
63
- "test:desktop:built": "node dist/tests/verify.js && node dist/tests/searchMcpPoolVerify.js && node dist/tests/thinkingTierMapCacheStressVerify.js && node dist/tests/computerUseSessionVerify.js && node dist/tests/contextSystemV2Verify.js && node dist/tests/contextSystemV2StressVerify.js && node dist/tests/providerAdapterV2Verify.js && node dist/tests/providerTimeoutRecoveryVerify.js && node dist/tests/agentRuntimeV2Verify.js && node dist/tests/toolchainExposureV2Verify.js && node dist/tests/localOcrFallbackVerify.js && node dist/tests/dev018ModeSubagentStressVerify.js && npm run test:subagent-continuity:built && node dist/tests/conversationBranchStressVerify.js && node dist/tests/conversationArchiveConcurrencyVerify.js && node dist/tests/conversationArchiveRuntimeVerify.js && node dist/tests/dev040ComprehensiveStressVerify.js && node dist/tests/memoryPolicyVerify.js && node dist/tests/newmarkSelectVerify.js && node dist/tests/mcpManagerVerify.js && node dist/tests/dshCompatibilityVerify.js && node dist/tests/performanceOptimizationVerify.js && node scripts/compression-pressure-stress.cjs && node dist/tests/compressionFidelityVerify.js && node dist/tests/responseTrajectoryVerify.js && node dist/tests/normalChatRegressionVerify.js && node dist/tests/dev008-subagent.js && node dist/tests/dev009Verify.js && node dist/tests/runtimeIsolationVerify.js && node dist/tests/runtimePoolCapacityVerify.js && node dist/tests/guideWorkRunVerify.js && node dist/tests/modelSwitchBehaviorVerify.js && node scripts/test-conversation-model-binding.cjs && node scripts/test-model-response-health.cjs && node scripts/test-image-ocr-recovery.cjs && node scripts/flow-pause-stop-draft-stress.cjs && node dist/tests/guideUiReconcileVerify.js && node dist/tests/workReviewDedupVerify.js && node dist/tests/queueAttachmentIsolationVerify.js && node scripts/test-queue-continuation-identity.cjs && node dist/tests/continuationStoreVerify.js && node scripts/test-hosted-command-transport.cjs && node scripts/test-conversation-list-notifications.cjs && node scripts/test-conversation-command-state.cjs && node scripts/test-shared-conversation-commands.cjs && node scripts/test-queue-start-failure.cjs && node scripts/test-queue-acceptance-boundary.cjs && node dist/tests/queueDrainUserMessageVerify.js && node dist/tests/pcGlassMigrationVerify.js && node dist/tests/longHistoryDisplayVerify.js && node dist/tests/workspaceMenuVerify.js && node dist/tests/userImagePersistenceVerify.js && node dist/tests/displayImageVerify.js && node dist/tests/visualPreferencesVerify.js && node dist/tests/browserUseVerify.js && node dist/tests/toolProcessVerify.js && node dist/tests/toolProvisioningVerify.js && node dist/tests/taskToolsVerify.js && node dist/tests/contextCacheHitStressVerify.js && node dist/tests/buildCacheDiagnosticsVerify.js && node dist/tests/buildCacheRetryVerify.js && node dist/tests/buildProviderReuseVerify.js && node dist/tests/providerCompletionIntegrityVerify.js && node scripts/test-build-recovery-continuity.cjs && node scripts/test-build-retry-cancellation.cjs && node scripts/test-build-continuity-http.cjs && node scripts/test-build-continuity-ui.cjs && node dist/tests/workEventCoalescerVerify.js && node scripts/test-provider-request-compat.cjs && node scripts/test-provider-header-metadata.cjs && node dist/tests/providerUsageAccountingVerify.js && node dist/tests/providerUsageReportingVerify.js && node scripts/test-context-usage-ownership.cjs && node scripts/test-context-request-accounting.cjs && node scripts/test-context-inspector-accounting.cjs && node dist/tests/startupPrewarmVerify.js && node dist/tests/pdfPreviewServerVerify.js && node dist/tests/editorLifecycleVerify.js && node dist/tests/terminalTakeoverVerify.js && node dist/tests/workspaceFileRouterVerify.js && node dist/tests/screenCaptureIndependentVerify.js && node dist/tests/computerUsePerformanceVerify.js && node dist/tests/autoRouterVerify.js && node dist/tests/autoAgentIntegrationVerify.js && node dist/tests/modelRecoveryStressVerify.js && node dist/tests/autoRouteRatingVerify.js && node dist/tests/providerIdentityVerify.js && node dist/tests/modelValidationVerify.js && node dist/tests/modelValidationAgentIntegrationVerify.js && node scripts/deletion-safety-stress.cjs && node scripts/test-install-update-msi.cjs && node scripts/test-provider-usage-persistence.cjs && node scripts/test-long-conversation-ui-ordering.cjs && node scripts/test-flow-start-cancellation.cjs && node scripts/test-conversation-history-window.cjs",
63
+ "test:desktop:built": "node dist/tests/verify.js && node dist/tests/searchMcpPoolVerify.js && node dist/tests/thinkingTierMapCacheStressVerify.js && node dist/tests/computerUseSessionVerify.js && node dist/tests/contextSystemV2Verify.js && node dist/tests/contextSystemV2StressVerify.js && node dist/tests/providerAdapterV2Verify.js && node dist/tests/providerTimeoutRecoveryVerify.js && node dist/tests/agentRuntimeV2Verify.js && node dist/tests/toolchainExposureV2Verify.js && node dist/tests/localOcrFallbackVerify.js && node dist/tests/dev018ModeSubagentStressVerify.js && npm run test:subagent-continuity:built && node dist/tests/conversationBranchStressVerify.js && node dist/tests/branchPageQueueIdentityVerify.js && node dist/tests/conversationArchiveConcurrencyVerify.js && node dist/tests/conversationArchiveRuntimeVerify.js && node dist/tests/dev040ComprehensiveStressVerify.js && node dist/tests/memoryPolicyVerify.js && node dist/tests/newmarkSelectVerify.js && node dist/tests/mcpManagerVerify.js && node dist/tests/dshCompatibilityVerify.js && node dist/tests/performanceOptimizationVerify.js && node scripts/compression-pressure-stress.cjs && node dist/tests/compressionFidelityVerify.js && node dist/tests/responseTrajectoryVerify.js && node dist/tests/normalChatRegressionVerify.js && node dist/tests/dev008-subagent.js && node dist/tests/dev009Verify.js && node dist/tests/runtimeIsolationVerify.js && node dist/tests/runtimePoolCapacityVerify.js && node dist/tests/guideWorkRunVerify.js && node dist/tests/modelSwitchBehaviorVerify.js && node scripts/test-conversation-model-binding.cjs && node scripts/test-model-response-health.cjs && node scripts/test-image-ocr-recovery.cjs && node scripts/flow-pause-stop-draft-stress.cjs && node dist/tests/guideUiReconcileVerify.js && node dist/tests/workReviewDedupVerify.js && node dist/tests/queueAttachmentIsolationVerify.js && node scripts/test-queue-continuation-identity.cjs && node dist/tests/continuationStoreVerify.js && node scripts/test-hosted-command-transport.cjs && node scripts/test-conversation-list-notifications.cjs && node scripts/test-conversation-command-state.cjs && node scripts/test-shared-conversation-commands.cjs && node scripts/test-queue-start-failure.cjs && node scripts/test-queue-acceptance-boundary.cjs && node dist/tests/queueDrainUserMessageVerify.js && node dist/tests/pcGlassMigrationVerify.js && node dist/tests/longHistoryDisplayVerify.js && node dist/tests/workspaceMenuVerify.js && node dist/tests/userImagePersistenceVerify.js && node dist/tests/displayImageVerify.js && node dist/tests/visualPreferencesVerify.js && node dist/tests/browserUseVerify.js && node dist/tests/toolProcessVerify.js && node dist/tests/toolProvisioningVerify.js && node dist/tests/taskToolsVerify.js && node dist/tests/contextCacheHitStressVerify.js && node dist/tests/buildCacheDiagnosticsVerify.js && node dist/tests/buildCacheRetryVerify.js && node dist/tests/buildProviderReuseVerify.js && node dist/tests/providerCompletionIntegrityVerify.js && node scripts/test-build-recovery-continuity.cjs && node scripts/test-build-retry-cancellation.cjs && node scripts/test-build-continuity-http.cjs && node scripts/test-build-continuity-ui.cjs && node dist/tests/workEventCoalescerVerify.js && node scripts/test-provider-request-compat.cjs && node scripts/test-provider-header-metadata.cjs && node dist/tests/providerUsageAccountingVerify.js && node dist/tests/providerUsageReportingVerify.js && node scripts/test-context-usage-ownership.cjs && node scripts/test-context-request-accounting.cjs && node scripts/test-context-inspector-accounting.cjs && node dist/tests/startupPrewarmVerify.js && node dist/tests/pdfPreviewServerVerify.js && node dist/tests/editorLifecycleVerify.js && node dist/tests/terminalTakeoverVerify.js && node dist/tests/workspaceFileRouterVerify.js && node dist/tests/screenCaptureIndependentVerify.js && node dist/tests/computerUsePerformanceVerify.js && node dist/tests/autoRouterVerify.js && node dist/tests/autoAgentIntegrationVerify.js && node dist/tests/modelRecoveryStressVerify.js && node dist/tests/autoRouteRatingVerify.js && node dist/tests/providerIdentityVerify.js && node dist/tests/modelValidationVerify.js && node dist/tests/modelValidationAgentIntegrationVerify.js && node scripts/deletion-safety-stress.cjs && node scripts/test-install-update-msi.cjs && node scripts/test-provider-usage-persistence.cjs && node scripts/test-long-conversation-ui-ordering.cjs && node scripts/test-flow-start-cancellation.cjs && node scripts/test-conversation-history-window.cjs",
64
64
  "test:conversation-branch-stress": "npm run build && node dist/tests/conversationBranchStressVerify.js",
65
65
  "test:conversation-archive-concurrency": "npm run build && node dist/tests/conversationArchiveConcurrencyVerify.js",
66
66
  "test:memory-policy": "npm run build && node dist/tests/memoryPolicyVerify.js",
@@ -205,6 +205,8 @@
205
205
  "release:packaged-ocr-smoke": "node scripts/release-packaged-ocr-smoke.cjs",
206
206
  "test:stream-unlimited-timeout-stress": "npm run build && node dist/tests/streamUnlimitedTimeoutStressVerify.js",
207
207
  "test:queue-unify-stress": "npm run build && node dist/tests/queueUnifyStressVerify.js && node dist/tests/queueDrainUserMessageVerify.js",
208
+ "test:branch-page-queue-identity": "npm run build && node dist/tests/branchPageQueueIdentityVerify.js && node scripts/test-long-conversation-ui-ordering.cjs && node scripts/test-shared-conversation-commands.cjs",
209
+ "test:branch-page-queue-visual": "node scripts/dev-0.6.4-branch-page-queue-visual.cjs",
208
210
  "test:continuation-store": "npm run build && node dist/tests/continuationStoreVerify.js && node scripts/test-queue-continuation-identity.cjs",
209
211
  "test:installer": "node scripts/test-install-update-msi.cjs",
210
212
  "test:liquid-gestures": "node scripts/dev-liquid-gesture-regression.cjs",