mixdog 0.9.4 → 0.9.6

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 (121) hide show
  1. package/README.md +112 -38
  2. package/package.json +4 -1
  3. package/scripts/bench/r5-orchestrated-task.json +7 -0
  4. package/scripts/bench/round-r13-clientmeta.json +464 -0
  5. package/scripts/bench/round-r14-betafeatures.json +466 -0
  6. package/scripts/bench/round-r15-fulldefault.json +462 -0
  7. package/scripts/bench/round-r16-sessionid.json +466 -0
  8. package/scripts/bench/round-r17-wirebytes.json +456 -0
  9. package/scripts/bench/round-r18-prewarm.json +468 -0
  10. package/scripts/bench/round-r19-clean.json +472 -0
  11. package/scripts/bench/round-r20-prewarm-clean.json +475 -0
  12. package/scripts/bench/round-r21-delta-retry.json +473 -0
  13. package/scripts/bench/round-r22-full-probe.json +693 -0
  14. package/scripts/bench/round-r23-itemprobe.json +701 -0
  15. package/scripts/bench/round-r24-shapefix.json +677 -0
  16. package/scripts/bench/round-r25-serial.json +464 -0
  17. package/scripts/bench/round-r26-parallel3.json +671 -0
  18. package/scripts/bench/round-r27-parallel10.json +894 -0
  19. package/scripts/bench/round-r28-parallel10-stagger.json +882 -0
  20. package/scripts/bench/round-r29-parallel10-stagger166.json +886 -0
  21. package/scripts/bench/round-r30-instid.json +253 -0
  22. package/scripts/bench/round-r31-upgradeprobe.json +256 -0
  23. package/scripts/bench/round-r32-vs-codex-lead.json +254 -0
  24. package/scripts/bench/round-r33-vs-codex-codex.json +115 -0
  25. package/scripts/bench/round-r34-orchestrated.json +120 -0
  26. package/scripts/bench/round-r35-orchestrated-codex.json +61 -0
  27. package/scripts/bench/round-r36-orchestrated-capped.json +128 -0
  28. package/scripts/bench-run.mjs +40 -7
  29. package/scripts/internal-comms-bench.mjs +2 -4
  30. package/scripts/model-catalog-audit.mjs +209 -0
  31. package/scripts/model-list-sanitize-test.mjs +37 -0
  32. package/scripts/recall-bench.mjs +76 -13
  33. package/scripts/recall-quality-cases.json +12 -0
  34. package/scripts/tool-smoke.mjs +2 -2
  35. package/src/agents/heavy-worker/AGENT.md +7 -7
  36. package/src/agents/scheduler-task/AGENT.md +2 -3
  37. package/src/agents/webhook-handler/AGENT.md +2 -3
  38. package/src/agents/worker/AGENT.md +9 -10
  39. package/src/app.mjs +12 -1
  40. package/src/headless-role.mjs +7 -1
  41. package/src/mixdog-session-runtime.mjs +15 -14
  42. package/src/output-styles/default.md +14 -18
  43. package/src/output-styles/minimal.md +4 -5
  44. package/src/output-styles/simple.md +7 -8
  45. package/src/rules/agent/00-common.md +6 -5
  46. package/src/rules/agent/30-explorer.md +16 -5
  47. package/src/rules/lead/01-general.md +5 -5
  48. package/src/rules/lead/lead-brief.md +6 -3
  49. package/src/rules/lead/lead-tool.md +6 -4
  50. package/src/rules/shared/01-tool.md +17 -21
  51. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +8 -3
  52. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +19 -0
  53. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +11 -3
  54. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +9 -1
  55. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +53 -9
  56. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +23 -10
  57. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +11 -9
  58. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +33 -4
  59. package/src/runtime/agent/orchestrator/providers/provider-catalog-cache.mjs +80 -0
  60. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +93 -0
  61. package/src/runtime/agent/orchestrator/session/loop.mjs +27 -5
  62. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +1 -1
  63. package/src/runtime/agent/orchestrator/stall-policy.mjs +20 -1
  64. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -7
  65. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  66. package/src/runtime/channels/backends/discord-gateway.mjs +2 -2
  67. package/src/runtime/channels/backends/discord.mjs +15 -26
  68. package/src/runtime/channels/backends/telegram.mjs +8 -12
  69. package/src/runtime/channels/index.mjs +23 -43
  70. package/src/runtime/channels/lib/backend-dispatch.mjs +5 -3
  71. package/src/runtime/channels/lib/config.mjs +37 -149
  72. package/src/runtime/channels/lib/event-pipeline.mjs +4 -4
  73. package/src/runtime/channels/lib/event-queue.mjs +15 -9
  74. package/src/runtime/channels/lib/inbound-routing.mjs +2 -39
  75. package/src/runtime/channels/lib/interaction-workflows.mjs +5 -113
  76. package/src/runtime/channels/lib/scheduler.mjs +27 -113
  77. package/src/runtime/channels/lib/webhook/deliveries.mjs +3 -2
  78. package/src/runtime/channels/lib/webhook.mjs +8 -47
  79. package/src/runtime/memory/index.mjs +9 -0
  80. package/src/runtime/memory/lib/core-memory-store.mjs +5 -1
  81. package/src/runtime/memory/lib/ko-morph.mjs +195 -0
  82. package/src/runtime/memory/lib/memory-recall-store.mjs +47 -10
  83. package/src/runtime/memory/lib/memory-text-utils.mjs +46 -0
  84. package/src/runtime/memory/lib/query-handlers.mjs +27 -5
  85. package/src/runtime/memory/tool-defs.mjs +2 -2
  86. package/src/runtime/shared/config.mjs +14 -4
  87. package/src/runtime/shared/markdown-frontmatter.mjs +19 -0
  88. package/src/runtime/shared/schedules-store.mjs +13 -3
  89. package/src/runtime/shared/tool-execution-contract.mjs +2 -2
  90. package/src/session-runtime/config-helpers.mjs +45 -10
  91. package/src/session-runtime/quick-model-rows.mjs +46 -11
  92. package/src/session-runtime/quick-search-models.mjs +28 -27
  93. package/src/session-runtime/settings-api.mjs +34 -1
  94. package/src/session-runtime/tool-defs.mjs +1 -1
  95. package/src/session-runtime/workflow.mjs +1 -1
  96. package/src/standalone/agent-tool/tool-def.mjs +1 -1
  97. package/src/standalone/agent-tool.mjs +30 -0
  98. package/src/standalone/channel-admin.mjs +102 -90
  99. package/src/standalone/explore-tool.mjs +39 -10
  100. package/src/tui/App.jsx +131 -28
  101. package/src/tui/app/app-format.mjs +11 -4
  102. package/src/tui/app/channel-pickers.mjs +2 -4
  103. package/src/tui/app/maintenance-pickers.mjs +60 -28
  104. package/src/tui/app/model-options.mjs +5 -1
  105. package/src/tui/app/settings-picker.mjs +0 -1
  106. package/src/tui/app/transcript-window.mjs +8 -2
  107. package/src/tui/app/use-transcript-scroll.mjs +3 -1
  108. package/src/tui/app/use-transcript-window.mjs +19 -1
  109. package/src/tui/components/ConfirmBar.jsx +10 -7
  110. package/src/tui/components/Picker.jsx +32 -11
  111. package/src/tui/components/PromptInput.jsx +10 -1
  112. package/src/tui/components/StatusLine.jsx +6 -3
  113. package/src/tui/dist/index.mjs +441 -293
  114. package/src/tui/engine.mjs +48 -12
  115. package/src/tui/index.jsx +11 -52
  116. package/src/ui/statusline.mjs +10 -0
  117. package/src/workflows/default/WORKFLOW.md +15 -17
  118. package/src/workflows/sequential/WORKFLOW.md +15 -17
  119. package/vendor/ink/build/ink.js +9 -1
  120. package/scripts/recall-usecase-probe.json +0 -6
  121. package/src/runtime/channels/lib/holidays.mjs +0 -138
@@ -0,0 +1,693 @@
1
+ {
2
+ "round": "22",
3
+ "runner": "lead",
4
+ "opts": {
5
+ "provider": "openai-oauth",
6
+ "model": "gpt-5.5",
7
+ "effort": null,
8
+ "fast": false,
9
+ "env": {
10
+ "MIXDOG_DATA_DIR": "C:\\Users\\tempe\\.mixdog\\bench-data"
11
+ }
12
+ },
13
+ "tasks": 9,
14
+ "completed": 9,
15
+ "completion_rate": 100,
16
+ "sessions": [
17
+ "sess_50448_1783061989422_1783061989666_f0a35e862535fbe68ff8c8c88c0d0809",
18
+ "sess_54180_1783061989438_1783061989675_e5514174e89fb92cbd4273d0e62a4b28",
19
+ "sess_32300_1783061989501_1783061989741_99cf7ec8354cf28ea3a700342eb2e6a7",
20
+ "sess_20344_1783062068465_1783062068692_1d6b26b6f2a3a0133357d26b5a5a8151",
21
+ "sess_15120_1783062104167_1783062104412_1fe19d7b1f20a61f3bc3a86a27ae6713",
22
+ "sess_33656_1783062173100_1783062173332_b75ff8b22e9c0931d849dac0a24ebc93",
23
+ "sess_6000_1783062197414_1783062197644_1864f3a1d11748a3ab64e6eae8f1b872",
24
+ "sess_56856_1783062226636_1783062226867_eced60ea81dbd87ee9c6ce2ee94d3ece",
25
+ "sess_38168_1783062254169_1783062254416_be5f77906fddddcb7543086ee03b0585"
26
+ ],
27
+ "results": [
28
+ {
29
+ "id": "r4-debug-forwarding-gap#1",
30
+ "agent": "reviewer",
31
+ "ok": true,
32
+ "ms": 114750,
33
+ "sessionId": "sess_50448_1783061989422_1783061989666_f0a35e862535fbe68ff8c8c88c0d0809",
34
+ "output": "sessionId: sess_50448_1783061989422_1783061989666_f0a35e862535fbe68ff8c8c88c0d0809\nTrace: activation writes `bridge-state.json` before ownership, backend connect, transcript binding, and `fs.watch` are all ready (`src/runtime/channels/lib/tool-dispatch.mjs:45`, `src/runtime/channels/index.mjs:1734`, `src/runtime/channels/index.mjs:710`, `src/runtime/channels/index.mjs:801`).\n\nFindings ordered by impact:\n\n1. **Existing transcript can be skipped at initial bind** — if the transcript already exists and no matching persisted cursor exists, `setContext()` starts at current EOF, so assistant text written before binding is silently dropped; backlog catch-up does **not** recover it. Anchors: `src/runtime/channels/index.mjs:625`, `src/runtime/channels/index.mjs:441`, `src/runtime/channels/lib/output-forwarder.mjs:117`.\n\n2. **No channel target means no binding** — if persisted status and configured `main` channel cannot provide `channelId`, `bindPersistedTranscriptIfAny()` returns without binding or watching; later binding may start at EOF and miss prior output. Backlog catch-up: **not automatic**. Anchor: `src/runtime/channels/index.mjs:610`.\n\n3. **Bridge active before owner/backend ready** — `forwardNewText()` fails closed while `bridgeRuntimeConnected` is false or ownership is not confirmed, so output is delayed, not read; initial activation usually recovers via post-connect `forwardNewText()`/rearm. Anchors: `src/runtime/channels/index.mjs:316`, `src/runtime/channels/lib/output-forwarder.mjs:351`, `src/runtime/channels/index.mjs:769`, `src/runtime/channels/index.mjs:809`.\n\n4. **Missing transcript file cannot be watched** — `fs.watch()` fails on a not-yet-created transcript, but pending rearm polls and forwards from the saved cursor when the file appears; backlog catch-up **recovers within the 60s rearm window**. Anchors: `src/runtime/channels/lib/output-forwarder.mjs:647`, `src/runtime/channels/index.mjs:357`, `src/runtime/channels/index.mjs:486`.\n\n5. **Pending rearm can expire** — if the transcript appears after `PENDING_REARM_MAX_MS`, no watch is installed and no automatic catch-up runs until another rebind/activation/inbound path. Backlog catch-up: **recoverable only by a later explicit bind**. Anchor: `src/runtime/channels/index.mjs:384`.\n\n6. **Watch-install race is covered** — bytes written between `setContext()` stat and successful watch install are flushed by `scheduleWatchFlush()`, so backlog catch-up **does recover** this narrow race. Anchor: `src/runtime/channels/lib/output-forwarder.mjs:665`.\n\nVerdict: the main real loss is binding an already-existing transcript at EOF without a matching persisted cursor; missing-file and pre-owner windows are mostly delayed and catch up unless rearm times out.",
35
+ "card": {
36
+ "session": "sess_50448_1783061989422_1783061989666_f0a35e862535fbe68ff8c8c88c0d0809",
37
+ "provider": "openai-oauth",
38
+ "model": "gpt-5.5",
39
+ "wall_ms": 104256,
40
+ "turns": 8,
41
+ "tool_calls": 10,
42
+ "tools_per_turn": 1.3,
43
+ "total_tool_ms": 674,
44
+ "llm_stream_ms": 103106,
45
+ "cache_ratio": 0.7904302327731247,
46
+ "cached_tokens": 171008,
47
+ "prompt_tokens": 216348,
48
+ "uncached_tokens": 45340,
49
+ "output_tokens": 10532,
50
+ "cache_weighted_input_10": 62440.8,
51
+ "cache_weighted_input_25": 88092,
52
+ "prompt_growth": 35331,
53
+ "antipatterns": 1,
54
+ "issues": 11,
55
+ "issue_types": [
56
+ "cache",
57
+ "cache_break",
58
+ "service_tier",
59
+ "tool_churn_cluster"
60
+ ],
61
+ "read_fragmentation_paths": [],
62
+ "grep_sweep_count": 0
63
+ }
64
+ },
65
+ {
66
+ "id": "r4-impl-usage-summary#1",
67
+ "agent": "worker",
68
+ "ok": true,
69
+ "ms": 237204,
70
+ "sessionId": "sess_54180_1783061989438_1783061989675_e5514174e89fb92cbd4273d0e62a4b28",
71
+ "output": "sessionId: sess_54180_1783061989438_1783061989675_e5514174e89fb92cbd4273d0e62a4b28\n구현 범위를 확인한 뒤 바로 반영하고 검증하겠습니다.`package.json`에는 이미 `usage:today` 항목이 있어 새 스크립트만 추가합니다.스크립트를 추가했으며 문법 검사와 1회 실행으로 확인하겠습니다.검증은 통과했고, 최종 변경 범위만 확인하겠습니다.재영님, 구현과 검증 완료했습니다.\n\n- **추가됨** `scripts/usage-today.mjs`: `MIXDOG_DATA_DIR` 우선, 로컬 자정 이후 usage row를 모델별/총합으로 집계합니다.\n- **스크립트** `package.json`: `usage:today` → `node scripts/usage-today.mjs`.\n- **검증** `node --check scripts/usage-today.mjs` 통과, `npm run usage:today` 실행 완료; grand total은 `$109.912145`로 출력됐습니다.\n- **참고** 기존 수정 파일 `src/runtime/channels/...` 2개는 건드리지 않았습니다.",
72
+ "card": {
73
+ "session": "sess_54180_1783061989438_1783061989675_e5514174e89fb92cbd4273d0e62a4b28",
74
+ "provider": "openai-oauth",
75
+ "model": "gpt-5.5",
76
+ "wall_ms": 226698,
77
+ "turns": 16,
78
+ "tool_calls": 19,
79
+ "tools_per_turn": 1.2,
80
+ "total_tool_ms": 3570,
81
+ "llm_stream_ms": 222784,
82
+ "cache_ratio": 0.7806373224374972,
83
+ "cached_tokens": 297472,
84
+ "prompt_tokens": 381063,
85
+ "uncached_tokens": 83591,
86
+ "output_tokens": 13736,
87
+ "cache_weighted_input_10": 113338.2,
88
+ "cache_weighted_input_25": 157959,
89
+ "prompt_growth": 29409,
90
+ "antipatterns": 2,
91
+ "issues": 16,
92
+ "issue_types": [
93
+ "cache",
94
+ "cache_break",
95
+ "readonly_stall",
96
+ "tool_error",
97
+ "service_tier",
98
+ "missed_parallelism",
99
+ "tool_churn_cluster"
100
+ ],
101
+ "read_fragmentation_paths": [],
102
+ "grep_sweep_count": 0
103
+ }
104
+ },
105
+ {
106
+ "id": "r4-explain-compact-engine#1",
107
+ "agent": "explore",
108
+ "ok": true,
109
+ "ms": 79013,
110
+ "sessionId": "sess_32300_1783061989501_1783061989741_99cf7ec8354cf28ea3a700342eb2e6a7",
111
+ "output": "sessionId: sess_32300_1783061989501_1783061989741_99cf7ec8354cf28ea3a700342eb2e6a7\n완료했습니다 — `engine.mjs` 기준 compaction 흐름은 아래처럼 정리됩니다.\n\n- **공개 진입점**: `compact.mjs`가 `semanticCompactMessages`와 `recallFastTrackCompactMessages`를 re-export하고, 실제 구현은 `engine.mjs`에 있다 (`src/runtime/agent/orchestrator/session/compact.mjs:52-55`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:278`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:445`).\n\n- **주요 호출자**: live turn은 `agentLoop`의 pre-send auto compact에서 호출하고, manual/auto-clear는 `runSessionCompaction`을 통해 호출된다 (`src/runtime/agent/orchestrator/session/loop.mjs:329-365`, `src/runtime/agent/orchestrator/session/loop.mjs:414-459`, `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:143-210`, `src/runtime/agent/orchestrator/session/manager.mjs:1849`, `src/runtime/agent/orchestrator/session/manager.mjs:1950`).\n\n- **발화 조건**: policy는 auto/type/boundary/trigger/reserve/tail budget을 만들고, token 추정 실패 또는 `pressure >= trigger`이거나 reactive retry면 compact를 실행한다 (`src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:89-148`, `src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:170-175`, `src/runtime/agent/orchestrator/session/loop.mjs:351-365`).\n\n- **경로 선택**: recall-fasttrack type이면 memory ingest/dump/cycle1 recall을 만든 뒤 type-2 compact를 실행하고, 아니면 semantic provider summary를 실행한다 (`src/runtime/agent/orchestrator/session/loop.mjs:414-459`, `src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs:25-88`, `src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs:103-172`).\n\n- **semantic tail 선택**: system/protected prefix와 previous summary를 분리하고 summary 메시지를 live에서 제외한 뒤, user turn이 있으면 최근 `tailTurns`를 budget 안에서 보존하고 없으면 tool-result로 시작하지 않는 cut point를 고른다 (`src/runtime/agent/orchestrator/session/compact/engine.mjs:100-111`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:134-185`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:193-242`).\n\n- **tool pairing 보존**: tail boundary는 `tool` 메시지로 시작하지 않게 하고, cut 이후에도 `sanitizeToolPairs`/`dedupToolResultBodies`/`reconcileDedupStubs`로 provider-valid 구조를 복구한다 (`src/runtime/agent/orchestrator/session/compact/engine.mjs:121-127`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:246-250`).\n\n- **recall tail 선택**: recall-fasttrack은 최신 user-anchored turn 최대 2개를 보존하고 cap을 넘으면 오래된 turn을 버리거나 마지막 turn을 truncate하며, no-user tail도 유효하게 유지한다 (`src/runtime/agent/orchestrator/session/compact/engine.mjs:449-466`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:593-619`).\n\n- **redaction 위치**: fits-budget no-op은 원래 sanitized transcript를 그대로 반환하지만, 실제 compact가 진행되면 window 선택 전에 tool-call argument 값을 redaction해서 preserved system/tail에도 반영한다 (`src/runtime/agent/orchestrator/session/compact/engine.mjs:286-314`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:644-646`, `src/runtime/agent/orchestrator/session/compact/text-utils.mjs:291-326`).\n\n- **prompt-side redaction**: summary prompt의 tool-call metadata와 preserved facts도 raw secret string/key 기반 redaction을 통과한다 (`src/runtime/agent/orchestrator/session/compact/text-utils.mjs:121-159`, `src/runtime/agent/orchestrator/session/compact/summary.mjs:85-90`, `src/runtime/agent/orchestrator/session/compact/budget.mjs:119-153`).\n\n- **fit/fallback**: mandatory system+tail 비용이 target budget을 넘으면 budget을 summary room만큼 올리고, prompt/summary fitting은 prior summary 축소·facts 제거·head count 축소·schema repair를 시도한다 (`src/runtime/agent/orchestrator/session/compact/engine.mjs:319-337`, `src/runtime/agent/orchestrator/session/compact/summary.mjs:199-281`, `src/runtime/agent/orchestrator/session/compact/summary.mjs:302-385`).\n\n- **실패 경로**: semantic/recall은 compactable history 없음, empty recall, empty provider summary, fit 실패, final budget 초과에서 throw하고, loop는 non-recall에 한해 unanchored prune fallback 후 실패 telemetry를 남긴다 (`src/runtime/agent/orchestrator/session/compact/engine.mjs:315-317`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:653-700`, `src/runtime/agent/orchestrator/session/loop.mjs:500-537`, `src/runtime/agent/orchestrator/session/loop.mjs:546-601`).\n\n- **manual/clear fallback**: session-level recall-fasttrack 실패는 semantic fallback을 한 번 시도하고, non-recall 실패는 prune fallback을 시도하며, 그래도 실패하면 session compaction metadata에 실패를 기록한다 (`src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:231-278`, `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:319-380`).",
112
+ "card": {
113
+ "session": "sess_32300_1783061989501_1783061989741_99cf7ec8354cf28ea3a700342eb2e6a7",
114
+ "provider": "openai-oauth",
115
+ "model": "gpt-5.5",
116
+ "wall_ms": 68462,
117
+ "turns": 8,
118
+ "tool_calls": 7,
119
+ "tools_per_turn": 0.9,
120
+ "total_tool_ms": 911,
121
+ "llm_stream_ms": 67095,
122
+ "cache_ratio": 0.6492341421503274,
123
+ "cached_tokens": 109568,
124
+ "prompt_tokens": 168765,
125
+ "uncached_tokens": 59197,
126
+ "output_tokens": 5191,
127
+ "cache_weighted_input_10": 70153.8,
128
+ "cache_weighted_input_25": 86589,
129
+ "prompt_growth": 44771,
130
+ "antipatterns": 1,
131
+ "issues": 14,
132
+ "issue_types": [
133
+ "cache",
134
+ "cache_break",
135
+ "broad_tool_result",
136
+ "service_tier",
137
+ "missed_parallelism",
138
+ "tool_churn_cluster"
139
+ ],
140
+ "read_fragmentation_paths": [],
141
+ "grep_sweep_count": 0
142
+ }
143
+ },
144
+ {
145
+ "id": "r4-debug-forwarding-gap#2",
146
+ "agent": "reviewer",
147
+ "ok": true,
148
+ "ms": 104639,
149
+ "sessionId": "sess_20344_1783062068465_1783062068692_1d6b26b6f2a3a0133357d26b5a5a8151",
150
+ "output": "sessionId: sess_20344_1783062068465_1783062068692_1d6b26b6f2a3a0133357d26b5a5a8151\n조사 완료: 활성화 후 첫 전달 경로는 `start()` → ownership/connect → transcript bind/watch → `forwardNewText()` → queue drain → `backend.sendMessage()`입니다.\n\n- **최대 손실: fresh existing transcript** — 새 transcript가 이미 존재하지만 persisted cursor가 없으면 `setContext()`가 EOF에서 시작해 기존 출력은 건너뜁니다; backlog catch-up 없음. `src/runtime/channels/lib/output-forwarder.mjs:117`, `src/runtime/channels/index.mjs:435`\n\n- **라우팅 미확정** — `channelId`가 없고 main fallback도 없으면 bind 자체가 중단되며, 이후 첫 inbound가 기존 transcript를 EOF로 bind할 수 있어 이전 출력은 복구되지 않습니다. `src/runtime/channels/index.mjs:610`, `src/runtime/channels/index.mjs:624`, `src/runtime/channels/index.mjs:1597`\n\n- **not-yet-created transcript** — `fs.watch()` 실패는 re-arm poll이 파일 생성 후 watch 설치와 `forwardNewText()`로 backlog를 읽어 복구합니다; 단 60초 timeout 이후 자동 복구는 없습니다. `src/runtime/channels/index.mjs:357`, `src/runtime/channels/index.mjs:376`, `src/runtime/channels/index.mjs:384`\n\n- **pre-connect ownership gate** — bridge-state는 먼저 쓰이지만 `bridgeRuntimeConnected` 전에는 `_isOwner()`가 false라 flush가 조용히 no-op입니다; cursor를 전진하지 않아 post-connect `forwardNewText()`가 복구합니다. `src/runtime/channels/index.mjs:1735`, `src/runtime/channels/lib/output-forwarder.mjs:351`, `src/runtime/channels/index.mjs:801`\n\n- **ownership handoff/loss** — owner probe가 false면 이 프로세스는 읽지도 보내지도 않으므로 지연됩니다; 새 owner가 같은 transcript를 bind해야 복구되며, 아니면 이 프로세스에서는 복구되지 않습니다. `src/runtime/channels/index.mjs:316`, `src/runtime/channels/index.mjs:897`\n\nVerdict: persisted cursor나 pending-transcript rearm 경로는 대부분 복구하지만, “이미 생성된 fresh transcript를 처음 bind”하는 경우가 실제 무손실 보장의 핵심 구멍입니다.",
151
+ "card": {
152
+ "session": "sess_20344_1783062068465_1783062068692_1d6b26b6f2a3a0133357d26b5a5a8151",
153
+ "provider": "openai-oauth",
154
+ "model": "gpt-5.5",
155
+ "wall_ms": 94151,
156
+ "turns": 11,
157
+ "tool_calls": 10,
158
+ "tools_per_turn": 0.9,
159
+ "total_tool_ms": 950,
160
+ "llm_stream_ms": 92568,
161
+ "cache_ratio": 0.8255604379235868,
162
+ "cached_tokens": 221696,
163
+ "prompt_tokens": 268540,
164
+ "uncached_tokens": 46844,
165
+ "output_tokens": 7366,
166
+ "cache_weighted_input_10": 69013.6,
167
+ "cache_weighted_input_25": 102268,
168
+ "prompt_growth": 33077,
169
+ "antipatterns": 1,
170
+ "issues": 15,
171
+ "issue_types": [
172
+ "cache",
173
+ "cache_break",
174
+ "readonly_stall",
175
+ "service_tier",
176
+ "missed_parallelism",
177
+ "tool_churn_cluster"
178
+ ],
179
+ "read_fragmentation_paths": [],
180
+ "grep_sweep_count": 0
181
+ }
182
+ },
183
+ {
184
+ "id": "r4-impl-usage-summary#2",
185
+ "agent": "worker",
186
+ "ok": true,
187
+ "ms": 93245,
188
+ "sessionId": "sess_15120_1783062104167_1783062104412_1fe19d7b1f20a61f3bc3a86a27ae6713",
189
+ "output": "sessionId: sess_15120_1783062104167_1783062104412_1fe19d7b1f20a61f3bc3a86a27ae6713\n요청 범위가 작고 실행까지 명시되어 있어 바로 반영하겠습니다.구현 파일과 npm script가 이미 변경된 상태로 보이며, 현재 내용 기준으로 검증을 진행하겠습니다.구현 및 검증 완료했습니다.\n\n- **Diff 요약**: `package.json`에 `usage:today` script 추가, `scripts/usage-today.mjs` 신규 추가.\n- **동작**: `MIXDOG_DATA_DIR`를 반영해 `history/agent-trace.jsonl`을 읽고, 로컬 자정 이후 `usage`/`usage_raw`를 모델별로 집계합니다.\n- **검증**: `node --check scripts/usage-today.mjs` 통과, `npm run usage:today` 실행 완료.\n- **참고**: 기존에 수정돼 있던 `src/runtime/channels/lib/*` 변경은 건드리지 않았습니다.",
190
+ "card": {
191
+ "session": "sess_15120_1783062104167_1783062104412_1fe19d7b1f20a61f3bc3a86a27ae6713",
192
+ "provider": "openai-oauth",
193
+ "model": "gpt-5.5",
194
+ "wall_ms": 82749,
195
+ "turns": 13,
196
+ "tool_calls": 14,
197
+ "tools_per_turn": 1.1,
198
+ "total_tool_ms": 2816,
199
+ "llm_stream_ms": 79913,
200
+ "cache_ratio": 0.8312670927877303,
201
+ "cached_tokens": 210944,
202
+ "prompt_tokens": 253762,
203
+ "uncached_tokens": 42818,
204
+ "output_tokens": 7230,
205
+ "cache_weighted_input_10": 63912.4,
206
+ "cache_weighted_input_25": 95554,
207
+ "prompt_growth": 25448,
208
+ "antipatterns": 2,
209
+ "issues": 15,
210
+ "issue_types": [
211
+ "cache",
212
+ "cache_break",
213
+ "readonly_stall",
214
+ "service_tier",
215
+ "missed_parallelism",
216
+ "tool_churn_cluster"
217
+ ],
218
+ "read_fragmentation_paths": [],
219
+ "grep_sweep_count": 0
220
+ }
221
+ },
222
+ {
223
+ "id": "r4-explain-compact-engine#2",
224
+ "agent": "explore",
225
+ "ok": true,
226
+ "ms": 81074,
227
+ "sessionId": "sess_33656_1783062173100_1783062173332_b75ff8b22e9c0931d849dac0a24ebc93",
228
+ "output": "sessionId: sess_33656_1783062173100_1783062173332_b75ff8b22e9c0931d849dac0a24ebc93\nArchitecture brief:\n\n- Entry points: `semanticCompactMessages` and `recallFastTrackCompactMessages` are re-exported from `compact.mjs` and implemented in `engine.mjs`. `src/runtime/agent/orchestrator/session/compact.mjs:52`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:278`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:445`\n\n- Callers: live turns go through `askSession → agentLoop`, while manual clear/compact calls use `runSessionCompaction`. `src/runtime/agent/orchestrator/session/manager.mjs:1379`, `src/runtime/agent/orchestrator/session/loop.mjs:414`, `src/runtime/agent/orchestrator/session/manager.mjs:1849`, `src/runtime/agent/orchestrator/session/manager.mjs:1950`\n\n- Fire decision: loop compaction is enabled by `resolveWorkerCompactPolicy`, estimates message tokens, then fires when pressure reaches trigger or a reactive retry is pending. `src/runtime/agent/orchestrator/session/loop.mjs:329`, `src/runtime/agent/orchestrator/session/loop.mjs:351`, `src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:170`\n\n- Budget/trigger: policy derives boundary, trigger, reserve, type, timeout, tail turns, and keep tokens from session/env/tool reserve. `src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:89`, `src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:117`, `src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:123`, `src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:141`\n\n- Reactive path: provider context overflow marks `reactiveOverflowRetryPending`, loops back, and forces the next pre-send compact pass. `src/runtime/agent/orchestrator/session/loop.mjs:982`, `src/runtime/agent/orchestrator/session/loop.mjs:995`, `src/runtime/agent/orchestrator/session/loop.mjs:1002`\n\n- Tail selection: semantic compaction sanitizes, splits protected system context from live messages, finds prior summary, and selects a head/tail window. `src/runtime/agent/orchestrator/session/compact/engine.mjs:100`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:235`\n\n- User-tail path: with user turns, it keeps up to `tailTurns` recent turns within `preserveRecentBudget`, splitting the newest turn suffix if needed. `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 path: without user turns, it cuts only at non-`tool` indices so tool results never start the preserved tail. `src/runtime/agent/orchestrator/session/compact/engine.mjs:121`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:193`\n\n- Recall tail: recall fast-track keeps the newest structured turns, drops oldest kept turns until under cap, then truncates the oldest surviving content if needed. `src/runtime/agent/orchestrator/session/compact/engine.mjs:593`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:601`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:610`\n\n- Redaction hook: if compaction proceeds, both semantic and recall redact tool-call secret argument values before window selection, so preserved system/tail are measured and emitted redacted. `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:644`\n\n- Redaction behavior: sensitive keys and embedded raw secret pairs become `[redacted]`, while tool-call structure/order/pairing is preserved. `src/runtime/agent/orchestrator/session/compact/text-utils.mjs:230`, `src/runtime/agent/orchestrator/session/compact/text-utils.mjs:261`, `src/runtime/agent/orchestrator/session/compact/text-utils.mjs:319`\n\n- Semantic output: semantic compaction sends a fitted prompt to the provider, schema-repairs malformed summaries, fits the summary beside mandatory system+tail, and rejects over-budget output. `src/runtime/agent/orchestrator/session/compact/engine.mjs:333`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:367`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:376`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:384`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:395`\n\n- Recall output: recall fast-track requires recall/prior text unless explicitly allowed empty, caps recall injection room, fits a recall summary, and preserves the recall tail. `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:679`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:684`\n\n- Fallbacks: loop semantic failures can recover via unanchored tool-output prune; recall-fasttrack failures skip that prune and escalate. `src/runtime/agent/orchestrator/session/loop.mjs:500`, `src/runtime/agent/orchestrator/session/loop.mjs:517`, `src/runtime/agent/orchestrator/session/loop.mjs:527`, `src/runtime/agent/orchestrator/session/loop.mjs:546`\n\n- Manual fallback: session runner falls back from recall-fasttrack to semantic once, then tries unanchored prune for non-recall failures before recording failure. `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- Hard failure: unresolved loop failures emit compact telemetry/events and throw `AgentContextOverflowError`; manual failures persist `lastStage`/errors and return `changed:false`. `src/runtime/agent/orchestrator/session/loop.mjs:552`, `src/runtime/agent/orchestrator/session/loop.mjs:597`, `src/runtime/agent/orchestrator/session/loop.mjs:618`, `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:349`",
229
+ "card": {
230
+ "session": "sess_33656_1783062173100_1783062173332_b75ff8b22e9c0931d849dac0a24ebc93",
231
+ "provider": "openai-oauth",
232
+ "model": "gpt-5.5",
233
+ "wall_ms": 70584,
234
+ "turns": 10,
235
+ "tool_calls": 12,
236
+ "tools_per_turn": 1.2,
237
+ "total_tool_ms": 844,
238
+ "llm_stream_ms": 69391,
239
+ "cache_ratio": 0.6072081141273244,
240
+ "cached_tokens": 176128,
241
+ "prompt_tokens": 290062,
242
+ "uncached_tokens": 113934,
243
+ "output_tokens": 4768,
244
+ "cache_weighted_input_10": 131546.8,
245
+ "cache_weighted_input_25": 157966,
246
+ "prompt_growth": 48996,
247
+ "antipatterns": 1,
248
+ "issues": 17,
249
+ "issue_types": [
250
+ "cache",
251
+ "cache_break",
252
+ "cache_miss",
253
+ "readonly_stall",
254
+ "service_tier",
255
+ "missed_parallelism",
256
+ "tool_churn_cluster"
257
+ ],
258
+ "read_fragmentation_paths": [],
259
+ "grep_sweep_count": 0
260
+ }
261
+ },
262
+ {
263
+ "id": "r4-debug-forwarding-gap#3",
264
+ "agent": "reviewer",
265
+ "ok": true,
266
+ "ms": 113617,
267
+ "sessionId": "sess_6000_1783062197414_1783062197644_1864f3a1d11748a3ab64e6eae8f1b872",
268
+ "output": "sessionId: sess_6000_1783062197414_1783062197644_1864f3a1d11748a3ab64e6eae8f1b872\n요청 범위가 명확해 바로 추적하겠습니다.Found the activation-to-first-send path and the reliability gaps.\n\n**Path:** activation sets `channelBridgeActive`, writes `bridge-state.json`, claims ownership, then binds/restores transcript before `forwardNewText()` reads transcript bytes and sends them (`src/runtime/channels/index.mjs:1735`, `src/runtime/channels/index.mjs:218`, `src/runtime/channels/index.mjs:759`, `src/runtime/channels/index.mjs:801`, `src/runtime/channels/lib/output-forwarder.mjs:351`).\n\n**Highest impact — bind-at-EOF can permanently skip early output:** `setContext()` starts at current file size unless `replayFromStart` or same-transcript `catchUpFromPersisted` applies, so output already written before first binding is silently skipped when there is no matching persisted cursor (`src/runtime/channels/lib/output-forwarder.mjs:115`). Backlog catch-up recovers only for same persisted transcript (`lastFileSize`) or explicit pending-session replay; otherwise no.\n\n**Missing transcript file delays, then may become permanent:** `fs.watch()` fails on a not-yet-created file, and recovery depends on `schedulePendingTranscriptRearm()` polling until creation (`src/runtime/channels/lib/output-forwarder.mjs:647`, `src/runtime/channels/index.mjs:340`). Backlog is recovered if the file appears within the 60s re-arm window or post-connect re-arm runs; after timeout it is delayed indefinitely until another rebind path fires (`src/runtime/channels/index.mjs:384`).\n\n**Ownership/backend-ready window delays but usually recovers:** binding can start before `backend.connect()` completes, but `_isOwner()` blocks forwarding until `bridgeRuntimeConnected && currentOwnerState().owned` (`src/runtime/channels/index.mjs:316`, `src/runtime/channels/lib/output-forwarder.mjs:36`). Because the read cursor is not committed, post-connect `forwardNewText()` catches up (`src/runtime/channels/index.mjs:809`).\n\n**No channel binding means no forwarding target:** if no persisted/main channel is available, activation returns without binding (`src/runtime/channels/index.mjs:624`). Backlog recovery is not guaranteed; a later inbound can bind, but already-existing transcript bytes may still hit the bind-at-EOF skip.\n\n**Watch/flush latency delays first visible output:** installed watchers debounce 100ms and read only complete newline-delimited JSONL (`src/runtime/channels/lib/output-forwarder.mjs:703`, `src/runtime/channels/lib/output-forwarder.mjs:172`). Backlog is recovered on the next flush/newline because `readFileSize` is not advanced past partial lines.\n\nVerdict: the main real loss risk is not the pre-connect owner gate but binding an already-written transcript at EOF; missing-file rearm mostly recovers, but only within its bounded poll window.",
269
+ "card": {
270
+ "session": "sess_6000_1783062197414_1783062197644_1864f3a1d11748a3ab64e6eae8f1b872",
271
+ "provider": "openai-oauth",
272
+ "model": "gpt-5.5",
273
+ "wall_ms": 103119,
274
+ "turns": 10,
275
+ "tool_calls": 12,
276
+ "tools_per_turn": 1.2,
277
+ "total_tool_ms": 1063,
278
+ "llm_stream_ms": 101611,
279
+ "cache_ratio": 0.5503817764812559,
280
+ "cached_tokens": 134144,
281
+ "prompt_tokens": 243729,
282
+ "uncached_tokens": 109585,
283
+ "output_tokens": 8420,
284
+ "cache_weighted_input_10": 122999.4,
285
+ "cache_weighted_input_25": 143121,
286
+ "prompt_growth": 46223,
287
+ "antipatterns": 1,
288
+ "issues": 17,
289
+ "issue_types": [
290
+ "cache",
291
+ "cache_break",
292
+ "cache_miss",
293
+ "readonly_stall",
294
+ "service_tier",
295
+ "missed_parallelism",
296
+ "tool_churn_cluster"
297
+ ],
298
+ "read_fragmentation_paths": [],
299
+ "grep_sweep_count": 0
300
+ }
301
+ },
302
+ {
303
+ "id": "r4-impl-usage-summary#3",
304
+ "agent": "worker",
305
+ "ok": true,
306
+ "ms": 252047,
307
+ "sessionId": "sess_56856_1783062226636_1783062226867_eced60ea81dbd87ee9c6ce2ee94d3ece",
308
+ "output": "sessionId: sess_56856_1783062226636_1783062226867_eced60ea81dbd87ee9c6ce2ee94d3ece\n구현 범위를 확인한 뒤 바로 반영하고 검증하겠습니다.현재 작업트리에 이미 관련 변경이 일부 있어, 요청 범위와 겹치는 부분만 확인해 반영하겠습니다.스크립트 동작 보강 후 `node --check`와 npm 스크립트 실행까지 확인하겠습니다.검증은 통과했고, 최종 diff 범위만 확인하겠습니다.재영님, 완료했습니다.\n\n- **변경 요약**: `package.json`에 `usage:today` 추가, `scripts/usage-today.mjs` 신규 작성.\n- **동작**: `MIXDOG_DATA_DIR` 또는 `~/.mixdog/data/history/agent-trace.jsonl`을 읽고, 로컬 자정 이후 usage를 모델별/총합으로 집계합니다.\n- **검증**: `node --check scripts/usage-today.mjs` 통과, `npm run usage:today` 실행 성공.\n- **참고**: 작업 전부터 있던 `src/runtime/channels/lib/*` 수정은 건드리지 않았습니다.",
309
+ "card": {
310
+ "session": "sess_56856_1783062226636_1783062226867_eced60ea81dbd87ee9c6ce2ee94d3ece",
311
+ "provider": "openai-oauth",
312
+ "model": "gpt-5.5",
313
+ "wall_ms": 241567,
314
+ "turns": 23,
315
+ "tool_calls": 31,
316
+ "tools_per_turn": 1.3,
317
+ "total_tool_ms": 4694,
318
+ "llm_stream_ms": 237239,
319
+ "cache_ratio": 0.8463148050041583,
320
+ "cached_tokens": 571904,
321
+ "prompt_tokens": 675758,
322
+ "uncached_tokens": 103854,
323
+ "output_tokens": 22518,
324
+ "cache_weighted_input_10": 161044.4,
325
+ "cache_weighted_input_25": 246830,
326
+ "prompt_growth": 42843,
327
+ "antipatterns": 1,
328
+ "issues": 17,
329
+ "issue_types": [
330
+ "cache",
331
+ "cache_break",
332
+ "cache_miss",
333
+ "tool_error",
334
+ "service_tier",
335
+ "missed_parallelism",
336
+ "tool_churn_cluster"
337
+ ],
338
+ "read_fragmentation_paths": [],
339
+ "grep_sweep_count": 0
340
+ }
341
+ },
342
+ {
343
+ "id": "r4-explain-compact-engine#3",
344
+ "agent": "explore",
345
+ "ok": true,
346
+ "ms": 80924,
347
+ "sessionId": "sess_38168_1783062254169_1783062254416_be5f77906fddddcb7543086ee03b0585",
348
+ "output": "sessionId: sess_38168_1783062254169_1783062254416_be5f77906fddddcb7543086ee03b0585\n- **Entry points/callers**: `semanticCompactMessages` and `recallFastTrackCompactMessages` are the engine exports, re-exported by `compact.mjs`; loop auto-compaction calls them pre-send, while manual/auto-clear goes through `runSessionCompaction`. `engine.mjs:278`, `engine.mjs:445`, `compact.mjs:52`, `loop.mjs:329`, `loop.mjs:441`, `manager/compaction-runner.mjs:143`, `manager.mjs:1849`, `manager.mjs:1950`.\n\n- **Fire decision**: auto policy requires `auto !== false`, a boundary from explicit/context/limit, trigger = explicit sub-boundary limit or boundary minus buffer, then fires on reactive overflow, unknown token estimate, or pressure ≥ trigger. `compact-policy.mjs:89`, `compact-policy.mjs:97`, `compact-policy.mjs:113`, `compact-policy.mjs:170`, `loop.mjs:351`.\n\n- **Execution path**: loop drains queued messages before checking, computes target budget, optionally prunes, then chooses recall-fasttrack or semantic; manual runner uses `force` for manual and skips auto only when below threshold. `loop.mjs:324`, `loop.mjs:362`, `loop.mjs:405`, `loop.mjs:414`, `loop.mjs:439`, `manager/compaction-runner.mjs:145`, `manager/compaction-runner.mjs:176`.\n\n- **Preserved tail**: engine first sanitizes/pairs/dedups, splits protected system context from live history, finds prior summary, then semantic keeps recent user-anchored turns within `preserveRecentBudget` or falls back to non-tool cut points when no user turn exists. `engine.mjs:100`, `engine.mjs:235`, `engine.mjs:240`, `engine.mjs:134`, `engine.mjs:193`.\n\n- **Recall tail**: recall-fasttrack keeps the newest `RECALL_TAIL_USER_MAX` turns, drops oldest turns until under cap, truncates the surviving oversized turn/message, and accepts no-user assistant/tool tails. `engine.mjs:467`, `engine.mjs:593`, `engine.mjs:601`, `engine.mjs:602`, `engine.mjs:610`, `engine.mjs:613`.\n\n- **Redaction hook**: compaction no-op returns sanitized history unchanged; real semantic/recall compaction redacts tool-call argument secrets before window selection so preserved system/tail are emitted redacted, using shape-preserving argument redaction. `engine.mjs:286`, `engine.mjs:306`, `engine.mjs:312`, `engine.mjs:644`, `text-utils.mjs:219`, `text-utils.mjs:323`.\n\n- **Failure/fallbacks**: engine throws on missing provider, empty compactable history, prompt/summary/final-budget failures; loop records `overflow_failed`, tries non-recall unanchored prune fallback, otherwise raises context overflow. `engine.mjs:279`, `engine.mjs:315`, `engine.mjs:335`, `engine.mjs:385`, `engine.mjs:395`, `loop.mjs:500`, `loop.mjs:517`, `loop.mjs:552`, `loop.mjs:618`.\n\n- **Manager fallback/persistence**: recall-fasttrack failure may degrade to semantic, semantic failure may degrade to unanchored prune, hard failure records `manual_failed`/`post_turn_failed`, and successful compaction replaces messages and clears provider state. `manager/compaction-runner.mjs:231`, `manager/compaction-runner.mjs:242`, `manager/compaction-runner.mjs:327`, `manager/compaction-runner.mjs:348`, `manager/compaction-runner.mjs:410`.",
349
+ "card": {
350
+ "session": "sess_38168_1783062254169_1783062254416_be5f77906fddddcb7543086ee03b0585",
351
+ "provider": "openai-oauth",
352
+ "model": "gpt-5.5",
353
+ "wall_ms": 70424,
354
+ "turns": 11,
355
+ "tool_calls": 14,
356
+ "tools_per_turn": 1.3,
357
+ "total_tool_ms": 1255,
358
+ "llm_stream_ms": 68585,
359
+ "cache_ratio": 0.7573455254487999,
360
+ "cached_tokens": 247808,
361
+ "prompt_tokens": 327206,
362
+ "uncached_tokens": 79398,
363
+ "output_tokens": 4272,
364
+ "cache_weighted_input_10": 104178.8,
365
+ "cache_weighted_input_25": 141350,
366
+ "prompt_growth": 62021,
367
+ "antipatterns": 2,
368
+ "issues": 19,
369
+ "issue_types": [
370
+ "cache",
371
+ "cache_break",
372
+ "cache_miss",
373
+ "readonly_stall",
374
+ "broad_tool_result",
375
+ "service_tier",
376
+ "missed_parallelism",
377
+ "tool_churn_cluster"
378
+ ],
379
+ "read_fragmentation_paths": [],
380
+ "grep_sweep_count": 0
381
+ }
382
+ }
383
+ ],
384
+ "task_complete": true,
385
+ "task_errors": [],
386
+ "score_complete": true,
387
+ "score_errors": [],
388
+ "group": {
389
+ "n": 9,
390
+ "wall_ms": 118001.1,
391
+ "turns": 12.2,
392
+ "tool_calls": 14.3,
393
+ "tools_per_turn": 1.2,
394
+ "total_tool_ms": 1864.1,
395
+ "llm_stream_ms": 115810.2,
396
+ "cache_ratio": 0.7,
397
+ "cached_tokens": 237852.4,
398
+ "prompt_tokens": 313914.8,
399
+ "uncached_tokens": 76062.3,
400
+ "output_tokens": 9337,
401
+ "cache_weighted_input_10": 99847.6,
402
+ "cache_weighted_input_25": 135525.4,
403
+ "prompt_growth": 40902.1,
404
+ "antipatterns": 1.3,
405
+ "issues": 15.7,
406
+ "grep_sweep_count": 0
407
+ },
408
+ "cards": [
409
+ {
410
+ "session": "sess_50448_1783061989422_1783061989666_f0a35e862535fbe68ff8c8c88c0d0809",
411
+ "provider": "openai-oauth",
412
+ "model": "gpt-5.5",
413
+ "wall_ms": 104256,
414
+ "turns": 8,
415
+ "tool_calls": 10,
416
+ "tools_per_turn": 1.3,
417
+ "total_tool_ms": 674,
418
+ "llm_stream_ms": 103106,
419
+ "cache_ratio": 0.7904302327731247,
420
+ "cached_tokens": 171008,
421
+ "prompt_tokens": 216348,
422
+ "uncached_tokens": 45340,
423
+ "output_tokens": 10532,
424
+ "cache_weighted_input_10": 62440.8,
425
+ "cache_weighted_input_25": 88092,
426
+ "prompt_growth": 35331,
427
+ "antipatterns": 1,
428
+ "issues": 11,
429
+ "issue_types": [
430
+ "cache",
431
+ "cache_break",
432
+ "service_tier",
433
+ "tool_churn_cluster"
434
+ ],
435
+ "read_fragmentation_paths": [],
436
+ "grep_sweep_count": 0
437
+ },
438
+ {
439
+ "session": "sess_54180_1783061989438_1783061989675_e5514174e89fb92cbd4273d0e62a4b28",
440
+ "provider": "openai-oauth",
441
+ "model": "gpt-5.5",
442
+ "wall_ms": 226698,
443
+ "turns": 16,
444
+ "tool_calls": 19,
445
+ "tools_per_turn": 1.2,
446
+ "total_tool_ms": 3570,
447
+ "llm_stream_ms": 222784,
448
+ "cache_ratio": 0.7806373224374972,
449
+ "cached_tokens": 297472,
450
+ "prompt_tokens": 381063,
451
+ "uncached_tokens": 83591,
452
+ "output_tokens": 13736,
453
+ "cache_weighted_input_10": 113338.2,
454
+ "cache_weighted_input_25": 157959,
455
+ "prompt_growth": 29409,
456
+ "antipatterns": 2,
457
+ "issues": 16,
458
+ "issue_types": [
459
+ "cache",
460
+ "cache_break",
461
+ "readonly_stall",
462
+ "tool_error",
463
+ "service_tier",
464
+ "missed_parallelism",
465
+ "tool_churn_cluster"
466
+ ],
467
+ "read_fragmentation_paths": [],
468
+ "grep_sweep_count": 0
469
+ },
470
+ {
471
+ "session": "sess_32300_1783061989501_1783061989741_99cf7ec8354cf28ea3a700342eb2e6a7",
472
+ "provider": "openai-oauth",
473
+ "model": "gpt-5.5",
474
+ "wall_ms": 68462,
475
+ "turns": 8,
476
+ "tool_calls": 7,
477
+ "tools_per_turn": 0.9,
478
+ "total_tool_ms": 911,
479
+ "llm_stream_ms": 67095,
480
+ "cache_ratio": 0.6492341421503274,
481
+ "cached_tokens": 109568,
482
+ "prompt_tokens": 168765,
483
+ "uncached_tokens": 59197,
484
+ "output_tokens": 5191,
485
+ "cache_weighted_input_10": 70153.8,
486
+ "cache_weighted_input_25": 86589,
487
+ "prompt_growth": 44771,
488
+ "antipatterns": 1,
489
+ "issues": 14,
490
+ "issue_types": [
491
+ "cache",
492
+ "cache_break",
493
+ "broad_tool_result",
494
+ "service_tier",
495
+ "missed_parallelism",
496
+ "tool_churn_cluster"
497
+ ],
498
+ "read_fragmentation_paths": [],
499
+ "grep_sweep_count": 0
500
+ },
501
+ {
502
+ "session": "sess_20344_1783062068465_1783062068692_1d6b26b6f2a3a0133357d26b5a5a8151",
503
+ "provider": "openai-oauth",
504
+ "model": "gpt-5.5",
505
+ "wall_ms": 94151,
506
+ "turns": 11,
507
+ "tool_calls": 10,
508
+ "tools_per_turn": 0.9,
509
+ "total_tool_ms": 950,
510
+ "llm_stream_ms": 92568,
511
+ "cache_ratio": 0.8255604379235868,
512
+ "cached_tokens": 221696,
513
+ "prompt_tokens": 268540,
514
+ "uncached_tokens": 46844,
515
+ "output_tokens": 7366,
516
+ "cache_weighted_input_10": 69013.6,
517
+ "cache_weighted_input_25": 102268,
518
+ "prompt_growth": 33077,
519
+ "antipatterns": 1,
520
+ "issues": 15,
521
+ "issue_types": [
522
+ "cache",
523
+ "cache_break",
524
+ "readonly_stall",
525
+ "service_tier",
526
+ "missed_parallelism",
527
+ "tool_churn_cluster"
528
+ ],
529
+ "read_fragmentation_paths": [],
530
+ "grep_sweep_count": 0
531
+ },
532
+ {
533
+ "session": "sess_15120_1783062104167_1783062104412_1fe19d7b1f20a61f3bc3a86a27ae6713",
534
+ "provider": "openai-oauth",
535
+ "model": "gpt-5.5",
536
+ "wall_ms": 82749,
537
+ "turns": 13,
538
+ "tool_calls": 14,
539
+ "tools_per_turn": 1.1,
540
+ "total_tool_ms": 2816,
541
+ "llm_stream_ms": 79913,
542
+ "cache_ratio": 0.8312670927877303,
543
+ "cached_tokens": 210944,
544
+ "prompt_tokens": 253762,
545
+ "uncached_tokens": 42818,
546
+ "output_tokens": 7230,
547
+ "cache_weighted_input_10": 63912.4,
548
+ "cache_weighted_input_25": 95554,
549
+ "prompt_growth": 25448,
550
+ "antipatterns": 2,
551
+ "issues": 15,
552
+ "issue_types": [
553
+ "cache",
554
+ "cache_break",
555
+ "readonly_stall",
556
+ "service_tier",
557
+ "missed_parallelism",
558
+ "tool_churn_cluster"
559
+ ],
560
+ "read_fragmentation_paths": [],
561
+ "grep_sweep_count": 0
562
+ },
563
+ {
564
+ "session": "sess_33656_1783062173100_1783062173332_b75ff8b22e9c0931d849dac0a24ebc93",
565
+ "provider": "openai-oauth",
566
+ "model": "gpt-5.5",
567
+ "wall_ms": 70584,
568
+ "turns": 10,
569
+ "tool_calls": 12,
570
+ "tools_per_turn": 1.2,
571
+ "total_tool_ms": 844,
572
+ "llm_stream_ms": 69391,
573
+ "cache_ratio": 0.6072081141273244,
574
+ "cached_tokens": 176128,
575
+ "prompt_tokens": 290062,
576
+ "uncached_tokens": 113934,
577
+ "output_tokens": 4768,
578
+ "cache_weighted_input_10": 131546.8,
579
+ "cache_weighted_input_25": 157966,
580
+ "prompt_growth": 48996,
581
+ "antipatterns": 1,
582
+ "issues": 17,
583
+ "issue_types": [
584
+ "cache",
585
+ "cache_break",
586
+ "cache_miss",
587
+ "readonly_stall",
588
+ "service_tier",
589
+ "missed_parallelism",
590
+ "tool_churn_cluster"
591
+ ],
592
+ "read_fragmentation_paths": [],
593
+ "grep_sweep_count": 0
594
+ },
595
+ {
596
+ "session": "sess_6000_1783062197414_1783062197644_1864f3a1d11748a3ab64e6eae8f1b872",
597
+ "provider": "openai-oauth",
598
+ "model": "gpt-5.5",
599
+ "wall_ms": 103119,
600
+ "turns": 10,
601
+ "tool_calls": 12,
602
+ "tools_per_turn": 1.2,
603
+ "total_tool_ms": 1063,
604
+ "llm_stream_ms": 101611,
605
+ "cache_ratio": 0.5503817764812559,
606
+ "cached_tokens": 134144,
607
+ "prompt_tokens": 243729,
608
+ "uncached_tokens": 109585,
609
+ "output_tokens": 8420,
610
+ "cache_weighted_input_10": 122999.4,
611
+ "cache_weighted_input_25": 143121,
612
+ "prompt_growth": 46223,
613
+ "antipatterns": 1,
614
+ "issues": 17,
615
+ "issue_types": [
616
+ "cache",
617
+ "cache_break",
618
+ "cache_miss",
619
+ "readonly_stall",
620
+ "service_tier",
621
+ "missed_parallelism",
622
+ "tool_churn_cluster"
623
+ ],
624
+ "read_fragmentation_paths": [],
625
+ "grep_sweep_count": 0
626
+ },
627
+ {
628
+ "session": "sess_56856_1783062226636_1783062226867_eced60ea81dbd87ee9c6ce2ee94d3ece",
629
+ "provider": "openai-oauth",
630
+ "model": "gpt-5.5",
631
+ "wall_ms": 241567,
632
+ "turns": 23,
633
+ "tool_calls": 31,
634
+ "tools_per_turn": 1.3,
635
+ "total_tool_ms": 4694,
636
+ "llm_stream_ms": 237239,
637
+ "cache_ratio": 0.8463148050041583,
638
+ "cached_tokens": 571904,
639
+ "prompt_tokens": 675758,
640
+ "uncached_tokens": 103854,
641
+ "output_tokens": 22518,
642
+ "cache_weighted_input_10": 161044.4,
643
+ "cache_weighted_input_25": 246830,
644
+ "prompt_growth": 42843,
645
+ "antipatterns": 1,
646
+ "issues": 17,
647
+ "issue_types": [
648
+ "cache",
649
+ "cache_break",
650
+ "cache_miss",
651
+ "tool_error",
652
+ "service_tier",
653
+ "missed_parallelism",
654
+ "tool_churn_cluster"
655
+ ],
656
+ "read_fragmentation_paths": [],
657
+ "grep_sweep_count": 0
658
+ },
659
+ {
660
+ "session": "sess_38168_1783062254169_1783062254416_be5f77906fddddcb7543086ee03b0585",
661
+ "provider": "openai-oauth",
662
+ "model": "gpt-5.5",
663
+ "wall_ms": 70424,
664
+ "turns": 11,
665
+ "tool_calls": 14,
666
+ "tools_per_turn": 1.3,
667
+ "total_tool_ms": 1255,
668
+ "llm_stream_ms": 68585,
669
+ "cache_ratio": 0.7573455254487999,
670
+ "cached_tokens": 247808,
671
+ "prompt_tokens": 327206,
672
+ "uncached_tokens": 79398,
673
+ "output_tokens": 4272,
674
+ "cache_weighted_input_10": 104178.8,
675
+ "cache_weighted_input_25": 141350,
676
+ "prompt_growth": 62021,
677
+ "antipatterns": 2,
678
+ "issues": 19,
679
+ "issue_types": [
680
+ "cache",
681
+ "cache_break",
682
+ "cache_miss",
683
+ "readonly_stall",
684
+ "broad_tool_result",
685
+ "service_tier",
686
+ "missed_parallelism",
687
+ "tool_churn_cluster"
688
+ ],
689
+ "read_fragmentation_paths": [],
690
+ "grep_sweep_count": 0
691
+ }
692
+ ]
693
+ }