mixdog 0.9.17 → 0.9.19

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.
Files changed (129) hide show
  1. package/package.json +3 -2
  2. package/scripts/build-runtime-windows.ps1 +242 -242
  3. package/scripts/output-style-smoke.mjs +2 -2
  4. package/scripts/recall-bench-cases.json +11 -0
  5. package/scripts/recall-bench.mjs +91 -2
  6. package/scripts/recall-usecase-cases.json +1 -1
  7. package/scripts/smoke-runtime-negative.ps1 +106 -106
  8. package/scripts/tool-efficiency-diag.mjs +5 -2
  9. package/scripts/tool-smoke.mjs +101 -27
  10. package/src/agents/debugger/AGENT.md +3 -3
  11. package/src/agents/heavy-worker/AGENT.md +7 -10
  12. package/src/agents/maintainer/AGENT.md +1 -2
  13. package/src/agents/reviewer/AGENT.md +1 -2
  14. package/src/agents/worker/AGENT.md +5 -8
  15. package/src/defaults/agents.json +3 -0
  16. package/src/mixdog-session-runtime.mjs +23 -6
  17. package/src/rules/agent/00-core.md +4 -3
  18. package/src/rules/agent/30-explorer.md +53 -22
  19. package/src/rules/lead/02-channels.md +3 -3
  20. package/src/rules/lead/lead-tool.md +3 -2
  21. package/src/rules/shared/01-tool.md +24 -29
  22. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +1 -1
  23. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +1 -1
  24. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +24 -3
  25. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +3 -3
  26. package/src/runtime/agent/orchestrator/session/context-utils.mjs +2 -2
  27. package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +250 -35
  28. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +6 -4
  29. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +198 -6
  30. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +10 -2
  31. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +13 -15
  32. package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +6 -1
  33. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +45 -3
  34. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +5 -2
  35. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +195 -3
  36. package/src/runtime/agent/orchestrator/tools/builtin.mjs +17 -1
  37. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +38 -0
  38. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +4 -4
  39. package/src/runtime/agent/orchestrator/tools/shell-state.mjs +1 -1
  40. package/src/runtime/channels/backends/discord-attachments.mjs +2 -2
  41. package/src/runtime/channels/backends/discord-gateway.mjs +26 -3
  42. package/src/runtime/channels/backends/discord.mjs +139 -7
  43. package/src/runtime/channels/index.mjs +290 -76
  44. package/src/runtime/channels/lib/crash-log.mjs +21 -3
  45. package/src/runtime/channels/lib/inbound-routing.mjs +19 -12
  46. package/src/runtime/channels/lib/memory-client.mjs +32 -14
  47. package/src/runtime/channels/lib/output-forwarder.mjs +156 -14
  48. package/src/runtime/channels/lib/owner-heartbeat.mjs +13 -4
  49. package/src/runtime/channels/lib/runtime-paths.mjs +48 -1
  50. package/src/runtime/channels/lib/tool-dispatch.mjs +17 -7
  51. package/src/runtime/channels/lib/voice-transcription.mjs +4 -2
  52. package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +8 -2
  53. package/src/runtime/memory/lib/memory-recall-store.mjs +182 -9
  54. package/src/runtime/memory/lib/query-handlers.mjs +36 -4
  55. package/src/runtime/memory/lib/recall-format.mjs +106 -6
  56. package/src/runtime/memory/lib/session-ingest.mjs +1 -1
  57. package/src/runtime/shared/atomic-file.mjs +10 -4
  58. package/src/runtime/shared/background-tasks.mjs +4 -2
  59. package/src/runtime/shared/tool-execution-contract.mjs +1 -1
  60. package/src/runtime/shared/tool-result-summary.mjs +1 -1
  61. package/src/runtime/shared/tool-surface.mjs +30 -1
  62. package/src/session-runtime/config-lifecycle.mjs +1 -1
  63. package/src/session-runtime/cwd-plugins.mjs +46 -3
  64. package/src/session-runtime/mcp-glue.mjs +24 -3
  65. package/src/session-runtime/output-styles.mjs +44 -10
  66. package/src/session-runtime/workflow.mjs +16 -1
  67. package/src/standalone/channel-worker.mjs +88 -7
  68. package/src/standalone/explore-tool.mjs +1 -1
  69. package/src/tui/App.jsx +57 -77
  70. package/src/tui/app/channel-pickers.mjs +45 -0
  71. package/src/tui/app/slash-commands.mjs +0 -1
  72. package/src/tui/app/slash-dispatch.mjs +0 -16
  73. package/src/tui/app/transcript-window.mjs +66 -1
  74. package/src/tui/app/use-mouse-input.mjs +9 -2
  75. package/src/tui/app/use-prompt-handlers.mjs +7 -94
  76. package/src/tui/app/use-transcript-scroll.mjs +5 -1
  77. package/src/tui/app/use-transcript-window.mjs +74 -8
  78. package/src/tui/components/PromptInput.jsx +33 -64
  79. package/src/tui/components/ToolExecution.jsx +2 -2
  80. package/src/tui/dist/index.mjs +4744 -4806
  81. package/src/tui/engine.mjs +109 -20
  82. package/src/tui/lib/voice-setup.mjs +166 -0
  83. package/src/tui/paste-attachments.mjs +12 -5
  84. package/src/tui/prompt-history-store.mjs +125 -12
  85. package/scripts/bench/cache-probe-tasks.json +0 -8
  86. package/scripts/bench/lead-review-tasks-r3.json +0 -20
  87. package/scripts/bench/lead-review-tasks.json +0 -20
  88. package/scripts/bench/r4-mixed-tasks.json +0 -20
  89. package/scripts/bench/r5-orchestrated-task.json +0 -7
  90. package/scripts/bench/review-tasks.json +0 -20
  91. package/scripts/bench/round-codex.json +0 -114
  92. package/scripts/bench/round-mixdog-lead-r3.json +0 -269
  93. package/scripts/bench/round-mixdog-lead.json +0 -269
  94. package/scripts/bench/round-mixdog.json +0 -126
  95. package/scripts/bench/round-r10-bigsample.json +0 -679
  96. package/scripts/bench/round-r11-codexalign.json +0 -257
  97. package/scripts/bench/round-r13-clientmeta.json +0 -464
  98. package/scripts/bench/round-r14-betafeatures.json +0 -466
  99. package/scripts/bench/round-r15-fulldefault.json +0 -462
  100. package/scripts/bench/round-r16-sessionid.json +0 -466
  101. package/scripts/bench/round-r17-wirebytes.json +0 -456
  102. package/scripts/bench/round-r18-prewarm.json +0 -468
  103. package/scripts/bench/round-r19-clean.json +0 -472
  104. package/scripts/bench/round-r20-prewarm-clean.json +0 -475
  105. package/scripts/bench/round-r21-delta-retry.json +0 -473
  106. package/scripts/bench/round-r22-full-probe.json +0 -693
  107. package/scripts/bench/round-r23-itemprobe.json +0 -701
  108. package/scripts/bench/round-r24-shapefix.json +0 -677
  109. package/scripts/bench/round-r25-serial.json +0 -464
  110. package/scripts/bench/round-r26-parallel3.json +0 -671
  111. package/scripts/bench/round-r27-parallel10.json +0 -894
  112. package/scripts/bench/round-r28-parallel10-stagger.json +0 -882
  113. package/scripts/bench/round-r29-parallel10-stagger166.json +0 -886
  114. package/scripts/bench/round-r30-instid.json +0 -253
  115. package/scripts/bench/round-r31-upgradeprobe.json +0 -256
  116. package/scripts/bench/round-r32-vs-codex-lead.json +0 -254
  117. package/scripts/bench/round-r33-vs-codex-codex.json +0 -115
  118. package/scripts/bench/round-r34-orchestrated.json +0 -120
  119. package/scripts/bench/round-r35-orchestrated-codex.json +0 -61
  120. package/scripts/bench/round-r36-orchestrated-capped.json +0 -128
  121. package/scripts/bench/round-r4-codex.json +0 -114
  122. package/scripts/bench/round-r4-mixed.json +0 -225
  123. package/scripts/bench/round-r5-gpt-lead.json +0 -259
  124. package/scripts/bench/round-r6-codex.json +0 -114
  125. package/scripts/bench/round-r6-solo.json +0 -257
  126. package/scripts/bench/round-r7-full.json +0 -254
  127. package/scripts/bench/round-r8-fulldefault.json +0 -255
  128. package/src/tui/components/prompt-input/voice-indicator.mjs +0 -39
  129. package/src/tui/lib/voice-recorder.mjs +0 -469
@@ -1,255 +0,0 @@
1
- {
2
- "round": "8",
3
- "runner": "lead",
4
- "opts": {
5
- "provider": null,
6
- "model": null,
7
- "effort": null,
8
- "fast": false,
9
- "env": {
10
- "MIXDOG_DATA_DIR": "C:\\Users\\tempe\\.mixdog\\bench-data"
11
- }
12
- },
13
- "tasks": 3,
14
- "completed": 3,
15
- "completion_rate": 100,
16
- "sessions": [
17
- "sess_51468_1783039949771_1783039950019_986225c84c3411f10ae399d9084cae21",
18
- "sess_51564_1783039949781_1783039950027_596c0770872549478e285dccd2390597",
19
- "sess_19712_1783039949794_1783039950038_d4b96a9272d27d7f810e51341f8c58b7"
20
- ],
21
- "results": [
22
- {
23
- "id": "r4-debug-forwarding-gap",
24
- "agent": "reviewer",
25
- "ok": true,
26
- "ms": 144598,
27
- "sessionId": "sess_51468_1783039949771_1783039950019_986225c84c3411f10ae399d9084cae21",
28
- "output": "sessionId: sess_51468_1783039949771_1783039950019_986225c84c3411f10ae399d9084cae21\n조사 완료: 활성화 직후 경로에는 “지연 후 복구”가 대부분이지만, 새 transcript가 이미 존재하는 상태로 잡히면 첫 출력이 실제로 조용히 스킵될 수 있습니다.\n\n**경로**: `start()`가 `channelBridgeActive=true`와 `bridge-state.json`을 먼저 씁니다(`src/runtime/channels/index.mjs:1734`), 이후 ownership/connect/bind를 거쳐 `forwarder.forwardNewText()`가 `extractNewText()`→queue→`backend.sendMessage()`로 첫 전송합니다(`index.mjs:801`, `lib/output-forwarder.mjs:351`, `index.mjs:284`).\n\n**최대 영향 — 새 transcript 기존 파일을 EOF로 바인딩**: `catchUpFromPersisted`가 켜져도 persisted path가 다르면 cursor를 `currentSize`로 둡니다(`lib/output-forwarder.mjs:117`), 그리고 그 값을 즉시 상태에 저장합니다(`index.mjs:326`); 바인딩 전에 이미 쓰인 assistant 출력은 backlog catch-up으로 복구되지 않습니다.\n\n**높은 영향 — discovery polling 중 파일이 생겨 이미 내용이 있는 경우**: `discoverSessionBoundTranscript()` 루프가 `exists`를 잡으면 초기 activate 경로는 `catchUpFromPersisted:true`만 넘기고 `replayFromStart`는 거의 false입니다(`index.mjs:433`, `index.mjs:441`, `index.mjs:625`); persisted가 같은 transcript일 때만 복구되고, 아니면 위 EOF 스킵으로 유실됩니다.\n\n**중간 영향 — not-yet-created transcript watch 실패**: `startWatch()`는 없는 파일에서 catch 후 watcher를 닫습니다(`lib/output-forwarder.mjs:647`, `lib/output-forwarder.mjs:667`); pending re-arm이 250ms polling으로 파일 생성 후 `startWatch()`와 `forwardNewText()`를 실행해 60초 안에는 backlog가 복구됩니다(`index.mjs:357`, `index.mjs:376`), 60초 timeout 후에는 자동 복구가 없습니다(`index.mjs:384`).\n\n**중간 영향 — bridge-state 이후 connect/ownership 전 flush**: watch flush가 먼저 떠도 `_isOwner()`는 `bridgeRuntimeConnected && currentOwnerState().owned`라서 false이면 읽지 않고 반환합니다(`index.mjs:316`, `lib/output-forwarder.mjs:351`); cursor가 전진하지 않아 post-connect `forwardNewText()` 또는 re-arm이 backlog를 복구합니다(`index.mjs:776`, `index.mjs:801`).\n\n**낮은 영향 — ownership probe 예외/일시 false**: `_isOwner()`는 예외를 non-owner로 처리합니다(`lib/output-forwarder.mjs:36`), 해당 flush는 재시도 예약 없이 끝납니다; bytes는 소비되지 않아 다음 fs.watch/turn-end/post-connect flush가 있으면 복구되지만, 추가 트리거가 없으면 지연될 수 있습니다.\n\n**낮은 영향 — 바인딩 전 channelId 없음**: persisted status나 main channel fallback이 없으면 바인딩 자체를 중단합니다(`index.mjs:610`, `index.mjs:624`), 이후 channel bind가 생길 때까지 전송은 지연되며, 그때 새 transcript를 EOF로 잡으면 위 유실 조건을 다시 탑니다.\n\nVerdict: not-yet-created 파일과 pre-connect ownership 창은 대체로 backlog로 복구되지만, “이미 존재하는 새 transcript를 persisted mismatch 상태로 바인딩”하는 경로는 첫 assistant 출력을 조용히 유실할 수 있습니다.",
29
- "card": {
30
- "session": "sess_51468_1783039949771_1783039950019_986225c84c3411f10ae399d9084cae21",
31
- "provider": "openai-oauth",
32
- "model": "gpt-5.5",
33
- "wall_ms": 134065,
34
- "turns": 9,
35
- "tool_calls": 8,
36
- "tools_per_turn": 0.9,
37
- "total_tool_ms": 497,
38
- "llm_stream_ms": 133367,
39
- "cache_ratio": 0.8301802744876187,
40
- "cached_tokens": 186368,
41
- "prompt_tokens": 224491,
42
- "uncached_tokens": 38123,
43
- "output_tokens": 13835,
44
- "cache_weighted_input_10": 56759.8,
45
- "cache_weighted_input_25": 84715,
46
- "prompt_growth": 35644,
47
- "antipatterns": 1,
48
- "issues": 15,
49
- "issue_types": [
50
- "cache",
51
- "cache_break",
52
- "readonly_stall",
53
- "broad_tool_result",
54
- "service_tier",
55
- "missed_parallelism",
56
- "tool_churn_cluster"
57
- ],
58
- "read_fragmentation_paths": [],
59
- "grep_sweep_count": 0
60
- }
61
- },
62
- {
63
- "id": "r4-impl-usage-summary",
64
- "agent": "worker",
65
- "ok": true,
66
- "ms": 90877,
67
- "sessionId": "sess_51564_1783039949781_1783039950027_596c0770872549478e285dccd2390597",
68
- "output": "sessionId: sess_51564_1783039949781_1783039950027_596c0770872549478e285dccd2390597\n요청 범위가 작고 실행 승인이 포함되어 있어 바로 확인·수정·검증까지 진행하겠습니다.구현 파일과 npm script가 이미 작업트리에 있어 요구사항 대비 검증하고 필요한 보정만 하겠습니다.출력이 비어 있는 날에도 `GRAND TOTAL`이 보이도록 보정하겠습니다.패치 도구가 환경 문제로 실패해 PowerShell로 동일 변경을 적용하겠습니다.검증을 실행하겠습니다.차이 요약을 확인하겠습니다.새 스크립트가 untracked라 `git diff`에 빠져 상태까지 확인합니다.재영님, 완료했습니다.\n\n- **추가 기능** `usage:today` npm script와 `scripts/usage-today.mjs`를 추가해 오늘 0시 이후 usage를 모델별로 집계합니다.\n- **집계 내용** calls, input/cached/output tokens, costUsd와 `GRAND TOTAL` 라인을 출력하며 `MIXDOG_DATA_DIR`와 `--trace`, `--json`을 지원합니다.\n- **검증** `node --check scripts/usage-today.mjs` 통과, `npm run usage:today` 실행 성공.\n- **Diff 요약** `package.json` 1줄 추가, `scripts/usage-today.mjs` 신규 파일 추가.",
69
- "card": {
70
- "session": "sess_51564_1783039949781_1783039950027_596c0770872549478e285dccd2390597",
71
- "provider": "openai-oauth",
72
- "model": "gpt-5.5",
73
- "wall_ms": 80356,
74
- "turns": 11,
75
- "tool_calls": 16,
76
- "tools_per_turn": 1.5,
77
- "total_tool_ms": 3261,
78
- "llm_stream_ms": 76951,
79
- "cache_ratio": 0.7513836864762118,
80
- "cached_tokens": 161280,
81
- "prompt_tokens": 214644,
82
- "uncached_tokens": 53364,
83
- "output_tokens": 5943,
84
- "cache_weighted_input_10": 69492,
85
- "cache_weighted_input_25": 93684,
86
- "prompt_growth": 23910,
87
- "antipatterns": 1,
88
- "issues": 15,
89
- "issue_types": [
90
- "cache",
91
- "cache_break",
92
- "tool_error",
93
- "service_tier",
94
- "missed_parallelism",
95
- "tool_churn_cluster"
96
- ],
97
- "read_fragmentation_paths": [],
98
- "grep_sweep_count": 0
99
- }
100
- },
101
- {
102
- "id": "r4-explain-compact-engine",
103
- "agent": "explore",
104
- "ok": true,
105
- "ms": 74444,
106
- "sessionId": "sess_19712_1783039949794_1783039950038_d4b96a9272d27d7f810e51341f8c58b7",
107
- "output": "op.mjs:329`), then fires if `shouldCompactForSession(...)` is true (`src/runtime/agent/orchestrator/session/loop.mjs:353`).\n\n- **Trigger logic**: `shouldCompactForSession` returns false without `auto`/boundary, true on reactive overflow, true on unknown token estimate, otherwise compares `messageTokens + reserveTokens` to `triggerTokens || boundaryTokens` (`src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:170`).\n\n- **Reactive path**: provider context overflow sets `reactiveOverflowRetryPending = true`, causing the next loop to force compaction with trigger `reactive` (`src/runtime/agent/orchestrator/session/loop.mjs:996`, `src/runtime/agent/orchestrator/session/loop.mjs:1002`, `src/runtime/agent/orchestrator/session/loop.mjs:352`).\n\n- **Budgeting**: compact target is capped to the boundary and includes reserve (`src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:163`); manual runner uses the same boundary/trigger/reserve concepts and skips when not forced and below threshold (`src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:150`, `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:176`).\n\n- **Semantic flow**: `semanticCompactMessages` no-ops if sanitized messages already fit and not forced, otherwise redacts, selects a head/tail window, summarizes the head with provider.send, then emits `system + summary + tail` (`src/runtime/agent/orchestrator/session/compact/engine.mjs:278`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:289`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:312`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:367`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:392`).\n\n- **Semantic tail selection**: `selectCompactionWindow` splits protected context from live history, uses user-anchored recent turns when users exist, otherwise valid non-tool cut points, then sanitizes/reconciles the preserved tail (`src/runtime/agent/orchestrator/session/compact/engine.mjs:235`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:240`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:250`).\n\n- **User-tail policy**: user-anchored mode keeps up to `tailTurns` recent turns within `preserveRecentBudget`; if the newest turn alone is too large it keeps a fitting suffix or moves everything into the head (`src/runtime/agent/orchestrator/session/compact/engine.mjs:134`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:141`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:151`).\n\n- **No-user tail policy**: cut-point mode never starts a tail on a `tool` result, grows the newest valid suffix while it fits, and falls back to minimal/empty tail so there is still a compactable head (`src/runtime/agent/orchestrator/session/compact/engine.mjs:121`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:193`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:207`).\n\n- **Recall-fasttrack flow**: loop first builds bounded recall text, then calls `recallFastTrackCompactMessages` with force and tail options (`src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs:148`, `src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs:161`).\n\n- **Recall tail policy**: recall preserves newest structured turns verbatim, default max 2 user turns and 8k token cap, dropping oldest turns then truncating oldest surviving content while preserving newest content (`src/runtime/agent/orchestrator/session/compact/engine.mjs:449`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:467`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:601`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:610`).\n\n- **Recall assembly**: recall path redacts after no-op check, splits protected/live/previous summary, selects recall tail/head, requires compactable prior history or recall/prior text, then emits `system + recall summary + recallTail` (`src/runtime/agent/orchestrator/session/compact/engine.mjs:625`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:644`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:646`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:651`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:653`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:695`).\n\n- **Redaction hook**: sensitive tool-call argument values are redacted only when compaction proceeds, before window selection, so preserved system/tail are measured and emitted redacted; no-op returns sanitized but unredacted messages (`src/runtime/agent/orchestrator/session/compact/engine.mjs:286`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:306`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:312`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:389`).\n\n- **Budget fallback**: both semantic and recall raise budget to fit mandatory `system + tail` plus minimum summary room instead of failing when preserved content exceeds target (`src/runtime/agent/orchestrator/session/compact/engine.mjs:319`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:328`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:658`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:661`).\n\n- **Semantic failures**: provider missing, empty live window, no compactable head, prompt/summary fit failure, empty provider summary, or final budget overflow throw from `engine.mjs` (`src/runtime/agent/orchestrator/session/compact/engine.mjs:279`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:254`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:315`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:335`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:372`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:395`).\n\n- **Recall failures**: recall path throws on no compactable prior history, empty recall text when not explicitly allowed, summary fit failure, or final budget overflow (`src/runtime/agent/orchestrator/session/compact/engine.mjs:653`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:666`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:691`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:698`).\n\n- **Loop fallback**: semantic auto failure can recover via `pruneToolOutputsUnanchored` if the pruned transcript fits; recall-fasttrack failure deliberately skips this prune and escalates overflow (`src/runtime/agent/orchestrator/session/loop.mjs:501`, `src/runtime/agent/orchestrator/session/loop.mjs:517`, `src/runtime/agent/orchestrator/session/loop.mjs:527`, `src/runtime/agent/orchestrator/session/loop.mjs:618`).\n\n- **Manual fallback**: `runSessionCompaction` falls back from recall-fasttrack to semantic when enabled/provider exists; if non-recall still fails, it tries the same unanchored prune, otherwise records `manual_failed`/`post_turn_failed` without replacing history (`src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:237`, `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:245`, `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:322`, `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:348`).\n\n- **Success side effects**: successful loop compaction mutates in-memory messages, clears provider state, resets iterations, and records compact telemetry/events (`src/runtime/agent/orchestrator/session/loop.mjs:630`, `src/runtime/agent/orchestrator/session/loop.mjs:639`, `src/runtime/agent/orchestrator/session/loop.mjs:644`, `src/runtime/agent/orchestrator/session/loop.mjs:651`); manual runner writes `session.messages`, clears provider state, and stores compaction metadata (`src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:410`, `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:411`, `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:412`).",
108
- "card": {
109
- "session": "sess_19712_1783039949794_1783039950038_d4b96a9272d27d7f810e51341f8c58b7",
110
- "provider": "openai-oauth",
111
- "model": "gpt-5.5",
112
- "wall_ms": 63903,
113
- "turns": 8,
114
- "tool_calls": 12,
115
- "tools_per_turn": 1.5,
116
- "total_tool_ms": 1254,
117
- "llm_stream_ms": 62907,
118
- "cache_ratio": 0.5888853058153284,
119
- "cached_tokens": 109568,
120
- "prompt_tokens": 186060,
121
- "uncached_tokens": 76492,
122
- "output_tokens": 4420,
123
- "cache_weighted_input_10": 87448.8,
124
- "cache_weighted_input_25": 103884,
125
- "prompt_growth": 36532,
126
- "antipatterns": 0,
127
- "issues": 10,
128
- "issue_types": [
129
- "cache",
130
- "cache_break",
131
- "service_tier"
132
- ],
133
- "read_fragmentation_paths": [],
134
- "grep_sweep_count": 0
135
- }
136
- }
137
- ],
138
- "task_complete": true,
139
- "task_errors": [],
140
- "score_complete": true,
141
- "score_errors": [],
142
- "group": {
143
- "n": 3,
144
- "wall_ms": 92774.7,
145
- "turns": 9.3,
146
- "tool_calls": 12,
147
- "tools_per_turn": 1.3,
148
- "total_tool_ms": 1670.7,
149
- "llm_stream_ms": 91075,
150
- "cache_ratio": 0.7,
151
- "cached_tokens": 152405.3,
152
- "prompt_tokens": 208398.3,
153
- "uncached_tokens": 55993,
154
- "output_tokens": 8066,
155
- "cache_weighted_input_10": 71233.5,
156
- "cache_weighted_input_25": 94094.3,
157
- "prompt_growth": 32028.7,
158
- "antipatterns": 0.7,
159
- "issues": 13.3,
160
- "grep_sweep_count": 0
161
- },
162
- "cards": [
163
- {
164
- "session": "sess_51468_1783039949771_1783039950019_986225c84c3411f10ae399d9084cae21",
165
- "provider": "openai-oauth",
166
- "model": "gpt-5.5",
167
- "wall_ms": 134065,
168
- "turns": 9,
169
- "tool_calls": 8,
170
- "tools_per_turn": 0.9,
171
- "total_tool_ms": 497,
172
- "llm_stream_ms": 133367,
173
- "cache_ratio": 0.8301802744876187,
174
- "cached_tokens": 186368,
175
- "prompt_tokens": 224491,
176
- "uncached_tokens": 38123,
177
- "output_tokens": 13835,
178
- "cache_weighted_input_10": 56759.8,
179
- "cache_weighted_input_25": 84715,
180
- "prompt_growth": 35644,
181
- "antipatterns": 1,
182
- "issues": 15,
183
- "issue_types": [
184
- "cache",
185
- "cache_break",
186
- "readonly_stall",
187
- "broad_tool_result",
188
- "service_tier",
189
- "missed_parallelism",
190
- "tool_churn_cluster"
191
- ],
192
- "read_fragmentation_paths": [],
193
- "grep_sweep_count": 0
194
- },
195
- {
196
- "session": "sess_51564_1783039949781_1783039950027_596c0770872549478e285dccd2390597",
197
- "provider": "openai-oauth",
198
- "model": "gpt-5.5",
199
- "wall_ms": 80356,
200
- "turns": 11,
201
- "tool_calls": 16,
202
- "tools_per_turn": 1.5,
203
- "total_tool_ms": 3261,
204
- "llm_stream_ms": 76951,
205
- "cache_ratio": 0.7513836864762118,
206
- "cached_tokens": 161280,
207
- "prompt_tokens": 214644,
208
- "uncached_tokens": 53364,
209
- "output_tokens": 5943,
210
- "cache_weighted_input_10": 69492,
211
- "cache_weighted_input_25": 93684,
212
- "prompt_growth": 23910,
213
- "antipatterns": 1,
214
- "issues": 15,
215
- "issue_types": [
216
- "cache",
217
- "cache_break",
218
- "tool_error",
219
- "service_tier",
220
- "missed_parallelism",
221
- "tool_churn_cluster"
222
- ],
223
- "read_fragmentation_paths": [],
224
- "grep_sweep_count": 0
225
- },
226
- {
227
- "session": "sess_19712_1783039949794_1783039950038_d4b96a9272d27d7f810e51341f8c58b7",
228
- "provider": "openai-oauth",
229
- "model": "gpt-5.5",
230
- "wall_ms": 63903,
231
- "turns": 8,
232
- "tool_calls": 12,
233
- "tools_per_turn": 1.5,
234
- "total_tool_ms": 1254,
235
- "llm_stream_ms": 62907,
236
- "cache_ratio": 0.5888853058153284,
237
- "cached_tokens": 109568,
238
- "prompt_tokens": 186060,
239
- "uncached_tokens": 76492,
240
- "output_tokens": 4420,
241
- "cache_weighted_input_10": 87448.8,
242
- "cache_weighted_input_25": 103884,
243
- "prompt_growth": 36532,
244
- "antipatterns": 0,
245
- "issues": 10,
246
- "issue_types": [
247
- "cache",
248
- "cache_break",
249
- "service_tier"
250
- ],
251
- "read_fragmentation_paths": [],
252
- "grep_sweep_count": 0
253
- }
254
- ]
255
- }
@@ -1,39 +0,0 @@
1
- /**
2
- * components/prompt-input/voice-indicator.mjs — voice-indicator glyph frames,
3
- * timing constants, and frame-selection helper for the prompt box right edge.
4
- * Pure (no React). Extracted verbatim from PromptInput.jsx — behavior unchanged.
5
- */
6
-
7
- // Monotone voice indicator glyphs — right end of the prompt box. All frames
8
- // are 1-cell-wide (no emoji, no string-width special-casing needed). Modes:
9
- // 'off' — voice disabled and no install in flight: renders nothing,
10
- // zero reserved columns.
11
- // 'installing' — voice-runtime download in progress (progressHint active):
12
- // braille spinner only.
13
- // 'idle' — voice enabled, recorder idle: a STATIC ○ glyph. No
14
- // animation — an animated idle reads as "something is
15
- // running" when nothing is, and the old pulse frames
16
- // (◎ ◍ ◉ ◍) rendered as tofu/odd-width glyphs in common
17
- // Windows Terminal fonts (◍ U+25CD especially).
18
- // 'recording' — steady ● + a braille spinner riding next to it (2 cells).
19
- // 'transcribing' — braille spinner only (recording just stopped, awaiting
20
- // the whisper-server round-trip).
21
- // A single ~120ms interval drives the braille cycle, and it only exists
22
- // while an ANIMATED mode is active (installing/recording/transcribing) —
23
- // 'idle' and 'off' need no timer at all.
24
- export const VOICE_BRAILLE_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧'];
25
- export const VOICE_IDLE_GLYPH = '○';
26
- export const VOICE_TICK_MS = 120;
27
-
28
- // Resolve the indicator glyph text for a given mode + animation tick. Returns
29
- // '' (rendered as null / zero reserved columns) when the indicator is hidden.
30
- export function voiceIndicatorTextFor(mode, tick) {
31
- const voiceBrailleFrame = VOICE_BRAILLE_FRAMES[tick % VOICE_BRAILLE_FRAMES.length];
32
- return mode === 'installing' || mode === 'transcribing'
33
- ? voiceBrailleFrame
34
- : mode === 'recording'
35
- ? `●${voiceBrailleFrame}`
36
- : mode === 'idle'
37
- ? VOICE_IDLE_GLYPH
38
- : '';
39
- }