mixdog 0.9.4 → 0.9.5

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 +126 -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 +440 -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,466 @@
1
+ {
2
+ "round": "14",
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": 6,
14
+ "completed": 6,
15
+ "completion_rate": 100,
16
+ "sessions": [
17
+ "sess_45552_1783058338359_1783058338607_a015a1cdab90e4a2d1f531080d1c286b",
18
+ "sess_40340_1783058338374_1783058338625_09d691094df16330e45e10c7a25fca4b",
19
+ "sess_41232_1783058338395_1783058338643_9c39c68d28de50be18441725abb6f037",
20
+ "sess_25396_1783058424363_1783058424619_5963443d3a6c9851961f027db3819c54",
21
+ "sess_22136_1783058427761_1783058427997_8ea3b1019cb8865372862f9df6344d43",
22
+ "sess_59476_1783058430062_1783058430294_c496f72ecc8cb5c98b93240b9e9ded45"
23
+ ],
24
+ "results": [
25
+ {
26
+ "id": "r4-debug-forwarding-gap#1",
27
+ "agent": "reviewer",
28
+ "ok": true,
29
+ "ms": 89407,
30
+ "sessionId": "sess_45552_1783058338359_1783058338607_a015a1cdab90e4a2d1f531080d1c286b",
31
+ "output": "sessionId: sess_45552_1783058338359_1783058338607_a015a1cdab90e4a2d1f531080d1c286b\n관련 경로를 직접 추적해 첫 전달까지의 손실/지연 구간만 확인하겠습니다.Found real activation windows: two can silently lose first output; the rest delay and are usually recovered.\n\n**Activation path**: `start()` sets `channelBridgeActive` and writes `bridge-state.json` before ownership/backend/binding are ready (`src/runtime/channels/index.mjs:1735-1744`), then `startOwnedRuntime()` binds/restores transcript around backend connect (`src/runtime/channels/index.mjs:758-813`), `applyTranscriptBinding()` installs context/watch (`src/runtime/channels/index.mjs:317-337`), and `OutputForwarder` forwards via `fs.watch → forwardNewText → deliverQueueItem` (`src/runtime/channels/lib/output-forwarder.mjs:646-731`, `351-410`, `283-340`).\n\n**Highest impact — wrong/stale transcript binding on first inbound**: if an old binding exists and self-session discovery is not active within the 500ms steal poll, inbound is delivered while the forwarder still tails the old transcript (`src/runtime/channels/index.mjs:1506-1531`, `1571-1617`, `1623-1628`). Backlog catch-up does **not reliably recover**: a later steal to an already-existing correct transcript calls `setContext()` without replay/catch-up, so it seeks to EOF and skips the missed first reply (`src/runtime/channels/lib/output-forwarder.mjs:102-129`).\n\n**High impact — existing transcript with no matching persisted cursor**: activation restore uses `catchUpFromPersisted`, but if the discovered transcript already exists and persisted state does not match it, `setContext()` starts at `currentSize`, dropping all output already written before binding (`src/runtime/channels/index.mjs:625-629`, `441-449`; `src/runtime/channels/lib/output-forwarder.mjs:117-127`). Backlog catch-up: **no**, because the cursor is initialized at EOF.\n\n**Medium impact — not-yet-created transcript**: `fs.watch()` cannot attach, `startWatch()` catches/closes, and re-arm polls until the file appears, then installs watch and calls `forwardNewText()` (`src/runtime/channels/lib/output-forwarder.mjs:646-670`; `src/runtime/channels/index.mjs:339-393`, `469-499`). Backlog catch-up: **yes within the re-arm window** and post-connect compensation (`src/runtime/channels/index.mjs:801-812`); **no automatic recovery after the 60s timeout** unless a later rebind happens.\n\n**Lower impact — ownership/backend gate after bridge-state**: before `bridgeRuntimeConnected && currentOwnerState().owned`, `forwardNewText()` returns without reading or advancing the cursor (`src/runtime/channels/index.mjs:316`, `776-781`; `src/runtime/channels/lib/output-forwarder.mjs:351-354`). Backlog catch-up: **yes**, because unread bytes remain and post-connect `forwardNewText()` runs, unless a prior EOF-seeking bind already skipped them.\n\n**Verdict**: the bridge has bounded-delay recovery for missing-file and pre-connect windows, but first-output loss is still possible when binding chooses an existing wrong/unpersisted transcript and initializes the cursor at EOF.",
32
+ "card": {
33
+ "session": "sess_45552_1783058338359_1783058338607_a015a1cdab90e4a2d1f531080d1c286b",
34
+ "provider": "openai-oauth",
35
+ "model": "gpt-5.5",
36
+ "wall_ms": 78893,
37
+ "turns": 4,
38
+ "tool_calls": 3,
39
+ "tools_per_turn": 0.8,
40
+ "total_tool_ms": 20,
41
+ "llm_stream_ms": 78392,
42
+ "cache_ratio": 0.11257956255063072,
43
+ "cached_tokens": 9728,
44
+ "prompt_tokens": 86410,
45
+ "uncached_tokens": 76682,
46
+ "output_tokens": 7512,
47
+ "cache_weighted_input_10": 77654.8,
48
+ "cache_weighted_input_25": 79114,
49
+ "prompt_growth": 34226,
50
+ "antipatterns": 1,
51
+ "issues": 6,
52
+ "issue_types": [
53
+ "cache",
54
+ "cache_miss",
55
+ "broad_tool_result",
56
+ "service_tier",
57
+ "tool_churn_cluster"
58
+ ],
59
+ "read_fragmentation_paths": [],
60
+ "grep_sweep_count": 0
61
+ }
62
+ },
63
+ {
64
+ "id": "r4-impl-usage-summary#1",
65
+ "agent": "worker",
66
+ "ok": true,
67
+ "ms": 85967,
68
+ "sessionId": "sess_40340_1783058338374_1783058338625_09d691094df16330e45e10c7a25fca4b",
69
+ "output": "sessionId: sess_40340_1783058338374_1783058338625_09d691094df16330e45e10c7a25fca4b\n요청 범위가 명확해서 바로 구현하고 검증까지 진행하겠습니다.구현 파일과 npm script가 준비된 상태라 문법 검사와 실제 실행을 확인하겠습니다.완료됐습니다. `usage:today` 스크립트와 `scripts/usage-today.mjs`가 추가되어 오늘 로컬 자정 이후 usage를 모델별로 집계합니다.\n\n- **Diff 요약**: `package.json`에 `usage:today` 추가, `scripts/usage-today.mjs` 신규 추가.\n- **동작**: `MIXDOG_DATA_DIR` 우선, 기본값은 `~/.mixdog/data/history/agent-trace.jsonl`; 모델별 calls/input/cached/output/costUsd와 `GRAND TOTAL` 출력.\n- **검증**: `node --check scripts/usage-today.mjs` 통과, `npm run usage:today` 실행 완료.\n- **참고**: 작업 전부터 `src/runtime/channels/lib/event-queue.mjs`, `src/runtime/channels/lib/output-forwarder.mjs`에 별도 수정 상태가 있었습니다.",
70
+ "card": {
71
+ "session": "sess_40340_1783058338374_1783058338625_09d691094df16330e45e10c7a25fca4b",
72
+ "provider": "openai-oauth",
73
+ "model": "gpt-5.5",
74
+ "wall_ms": 75469,
75
+ "turns": 10,
76
+ "tool_calls": 13,
77
+ "tools_per_turn": 1.3,
78
+ "total_tool_ms": 2431,
79
+ "llm_stream_ms": 70209,
80
+ "cache_ratio": 0.6937749383029269,
81
+ "cached_tokens": 120320,
82
+ "prompt_tokens": 173428,
83
+ "uncached_tokens": 53108,
84
+ "output_tokens": 5186,
85
+ "cache_weighted_input_10": 65140,
86
+ "cache_weighted_input_25": 83188,
87
+ "prompt_growth": 21498,
88
+ "antipatterns": 1,
89
+ "issues": 5,
90
+ "issue_types": [
91
+ "cache_miss",
92
+ "cache",
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#1",
103
+ "agent": "explore",
104
+ "ok": true,
105
+ "ms": 91674,
106
+ "sessionId": "sess_41232_1783058338395_1783058338643_9c39c68d28de50be18441725abb6f037",
107
+ "output": "sessionId: sess_41232_1783058338395_1783058338643_9c39c68d28de50be18441725abb6f037\nMapped; concise architecture brief follows.\n\n- **Public surface:** `src/runtime/agent/orchestrator/session/compact.mjs:52-55` re-exports `semanticCompactMessages` and `recallFastTrackCompactMessages` from `compact/engine.mjs`.\n\n- **Callers:** normal turns enter through `askSession → agentLoop` at `src/runtime/agent/orchestrator/session/manager.mjs:1379-1380`; manual compact and clear paths call `runSessionCompaction` at `src/runtime/agent/orchestrator/session/manager.mjs:1849` and `src/runtime/agent/orchestrator/session/manager.mjs:1950-1957`.\n\n- **Policy gate:** loop compaction is enabled by `resolveWorkerCompactPolicy`, which derives `auto`, boundary, trigger, reserve, type, and tail settings from session/env config at `src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:89-148`.\n\n- **Fire decision:** before provider send, the loop drains queued steering, estimates transcript tokens, then calls `shouldCompactForSession`; compaction fires on reactive retry, null estimate, or pressure ≥ trigger at `src/runtime/agent/orchestrator/session/loop.mjs:324-364` and `src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:170-174`.\n\n- **Target budget:** the compact target is bounded by policy boundary and adds reserve back to the effective target at `src/runtime/agent/orchestrator/session/loop/compact-policy.mjs:163-168`; loop uses that target when `shouldCompact` is true at `src/runtime/agent/orchestrator/session/loop.mjs:362-364`.\n\n- **Path choice:** loop optionally prunes tool outputs first, then runs recall-fasttrack when configured, semantic otherwise, and rejects unavailable types at `src/runtime/agent/orchestrator/session/loop.mjs:405-498`.\n\n- **Session/manual gate:** `runSessionCompaction` skips closed sessions, disabled auto, too-few messages, missing boundary, or below-threshold pressure unless forced/manual at `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:143-198`.\n\n- **Semantic window split:** `splitLiveCompactionContext` repairs tool pairs, separates protected prefix, finds prior summary, and removes summary messages from live history at `src/runtime/agent/orchestrator/session/compact/engine.mjs:100-111`.\n\n- **Protected prefix:** system messages plus leading `<system-reminder>` user messages and their `.` acknowledgements are preserved outside the compactable conversation at `src/runtime/agent/orchestrator/session/compact/messages.mjs:56-80`.\n\n- **Semantic tail budget:** `selectCompactionWindow` computes recent-budget via `preserveRecentBudget`, then chooses user-turn or cut-point selection at `src/runtime/agent/orchestrator/session/compact/engine.mjs:235-250` and `src/runtime/agent/orchestrator/session/compact/budget.mjs:274-287`.\n\n- **User-tail policy:** with user turns, semantic compaction keeps up to `tailTurns` newest turns within budget and can split the newest oversized turn suffix at `src/runtime/agent/orchestrator/session/compact/engine.mjs:134-185`.\n\n- **No-user policy:** without user turns, semantic compaction cuts only at non-`tool` messages, grows the newest fitting suffix, and keeps a head to summarize when possible at `src/runtime/agent/orchestrator/session/compact/engine.mjs:121-127` and `src/runtime/agent/orchestrator/session/compact/engine.mjs:193-232`.\n\n- **Recall tail policy:** recall-fasttrack keeps the newest structured turns, drops oldest kept turns until under cap, truncates the newest turn if needed, and allows no-user tails at `src/runtime/agent/orchestrator/session/compact/engine.mjs:593-619`.\n\n- **Recall pipeline:** recall-fasttrack ingests session memory, dumps roots/raw rows, optionally drains cycle1, combines recall text, caps recall injection to context share, then calls `recallFastTrackCompactMessages` at `src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs:61-172`.\n\n- **Redaction hook:** semantic redacts after base sanitation and before window selection, so preserved system/tail are measured and emitted redacted at `src/runtime/agent/orchestrator/session/compact/engine.mjs:306-314` and `src/runtime/agent/orchestrator/session/compact/engine.mjs:389-392`.\n\n- **Recall redaction:** recall-fasttrack applies the same pre-window redaction before splitting protected context and choosing the preserved tail at `src/runtime/agent/orchestrator/session/compact/engine.mjs:622-651`.\n\n- **Redaction scope:** `redactToolCallSecretsInMessages` only changes assistant `toolCalls` argument values, preserving role/content/tool IDs/order/pairing at `src/runtime/agent/orchestrator/session/compact/text-utils.mjs:291-325`.\n\n- **Prompt-side scrub:** compaction prompt tool metadata and preserved facts also redact raw secret strings/tool-call args before summarization at `src/runtime/agent/orchestrator/session/compact/text-utils.mjs:151-154`, `src/runtime/agent/orchestrator/session/compact/summary.mjs:85-90`, and `src/runtime/agent/orchestrator/session/compact/budget.mjs:151-162`.\n\n- **Semantic hard failures:** missing provider, empty compactable head without prior summary, unfit prompt/summary, empty provider summary, or final budget overflow throw from `src/runtime/agent/orchestrator/session/compact/engine.mjs:278-281`, `src/runtime/agent/orchestrator/session/compact/engine.mjs:315-337`, and `src/runtime/agent/orchestrator/session/compact/engine.mjs:371-397`.\n\n- **Semantic soft repair:** malformed non-empty semantic summaries are schema-repaired before insertion, not injected blindly, at `src/runtime/agent/orchestrator/session/compact/summary.mjs:302-312`.\n\n- **Mandatory-cost fallback:** both semantic and recall raise the effective budget when preserved system+tail plus minimum summary room cannot fit, instead of refusing immediately at `src/runtime/agent/orchestrator/session/compact/engine.mjs:319-331` and `src/runtime/agent/orchestrator/session/compact/engine.mjs:658-664`.\n\n- **Recall hard failures:** recall-fasttrack throws on no compactable prior+empty recall, empty recall text when not allowed, unfit summary, or final budget overflow at `src/runtime/agent/orchestrator/session/compact/engine.mjs:653-699`.\n\n- **Loop fallback:** semantic failures can be salvaged by anchor-independent tool-output pruning if the pruned transcript fits effective budget; recall failures skip this silent prune and escalate at `src/runtime/agent/orchestrator/session/loop.mjs:500-537`.\n\n- **Loop escalation:** unrecovered compact failure records telemetry/events and throws `agentContextOverflowError` at `src/runtime/agent/orchestrator/session/loop.mjs:546-626`.\n\n- **Session fallback:** manual/clear recall-fasttrack failure can degrade to semantic compaction, then non-recall failures can use unanchored prune before recording failure at `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:237-347`.\n\n- **State mutation:** on success, loop replaces `messages`, clears `providerState`, resets iteration/usage epoch, and emits compact telemetry at `src/runtime/agent/orchestrator/session/loop.mjs:630-716`; session/manual paths replace `session.messages`, clear `providerState`, and persist compaction metadata at `src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs:399-470`.",
108
+ "card": {
109
+ "session": "sess_41232_1783058338395_1783058338643_9c39c68d28de50be18441725abb6f037",
110
+ "provider": "openai-oauth",
111
+ "model": "gpt-5.5",
112
+ "wall_ms": 81153,
113
+ "turns": 7,
114
+ "tool_calls": 9,
115
+ "tools_per_turn": 1.3,
116
+ "total_tool_ms": 697,
117
+ "llm_stream_ms": 80277,
118
+ "cache_ratio": 0.6459696986035477,
119
+ "cached_tokens": 119808,
120
+ "prompt_tokens": 185470,
121
+ "uncached_tokens": 65662,
122
+ "output_tokens": 6640,
123
+ "cache_weighted_input_10": 77642.8,
124
+ "cache_weighted_input_25": 95614,
125
+ "prompt_growth": 52898,
126
+ "antipatterns": 1,
127
+ "issues": 4,
128
+ "issue_types": [
129
+ "cache",
130
+ "broad_tool_result",
131
+ "service_tier",
132
+ "tool_churn_cluster"
133
+ ],
134
+ "read_fragmentation_paths": [],
135
+ "grep_sweep_count": 0
136
+ }
137
+ },
138
+ {
139
+ "id": "r4-debug-forwarding-gap#2",
140
+ "agent": "reviewer",
141
+ "ok": true,
142
+ "ms": 129661,
143
+ "sessionId": "sess_25396_1783058424363_1783058424619_5963443d3a6c9851961f027db3819c54",
144
+ "output": "sessionId: sess_25396_1783058424363_1783058424619_5963443d3a6c9851961f027db3819c54\n관련 경로를 직접 추적해 누락/지연 지점을 확인하겠습니다.I found several real activation-window gaps; most are delayed-and-caught-up, but two can still silently skip output.\n\n**Highest impact — EOF bind can drop early output:** `bindPersistedTranscriptIfAny()` calls rebind with `catchUpFromPersisted` only, and `setContext()` starts at EOF when the persisted path does not match, so assistant bytes already written before binding are skipped; backlog catch-up does **not** recover this. Anchors: `src/runtime/channels/index.mjs:625-629`, `src/runtime/channels/index.mjs:441-448`, `src/runtime/channels/lib/output-forwarder.mjs:117-126`.\n\n**High impact — no transcript path found:** if discovery never yields a pending/existing path and no previous path is usable, activation ends with no binding/watch, so output is delayed indefinitely until a later rebind trigger; backlog catch-up is **not automatic**. Anchors: `src/runtime/channels/index.mjs:431-460`, `src/runtime/channels/index.mjs:515-516`.\n\n**Medium impact — missing file watch:** binding a known-but-not-created transcript makes `fs.watch()` fail, but the re-arm poll installs the watch and calls `forwardNewText()` when the file appears; backlog catch-up **recovers within 60s**, otherwise it waits for a later trigger. Anchors: `src/runtime/channels/index.mjs:340-349`, `src/runtime/channels/index.mjs:469-498`, `src/runtime/channels/lib/output-forwarder.mjs:647-670`.\n\n**Medium impact — ownership/backend gate:** `bridge-state.json` is written before `backend.connect()` and before `bridgeRuntimeConnected`, so watcher flushes return before reading; backlog catch-up **recovers after connect** via post-connect `forwardNewText()`/re-arm. Anchors: `src/runtime/channels/index.mjs:1734-1744`, `src/runtime/channels/index.mjs:759-812`, `src/runtime/channels/lib/output-forwarder.mjs:36-42`, `src/runtime/channels/lib/output-forwarder.mjs:351-354`.\n\n**Low impact — stat-to-watch and partial-line windows:** bytes written between `setContext()` stat and watch install are covered by an immediate scheduled flush, and partial JSON lines are re-read after newline; backlog catch-up **recovers** both. Anchors: `src/runtime/channels/lib/output-forwarder.mjs:111-129`, `src/runtime/channels/lib/output-forwarder.mjs:665-666`, `src/runtime/channels/lib/output-forwarder.mjs:172-179`.\n\nVerdict: the bridge is mostly catch-up safe after ownership/connect, but first-output loss is still possible when activation binds an already-existing transcript without a matching persisted cursor.",
145
+ "card": {
146
+ "session": "sess_25396_1783058424363_1783058424619_5963443d3a6c9851961f027db3819c54",
147
+ "provider": "openai-oauth",
148
+ "model": "gpt-5.5",
149
+ "wall_ms": 119136,
150
+ "turns": 10,
151
+ "tool_calls": 9,
152
+ "tools_per_turn": 0.9,
153
+ "total_tool_ms": 508,
154
+ "llm_stream_ms": 118332,
155
+ "cache_ratio": 0.6560918574934662,
156
+ "cached_tokens": 181248,
157
+ "prompt_tokens": 276254,
158
+ "uncached_tokens": 95006,
159
+ "output_tokens": 10229,
160
+ "cache_weighted_input_10": 113130.8,
161
+ "cache_weighted_input_25": 140318,
162
+ "prompt_growth": 42817,
163
+ "antipatterns": 1,
164
+ "issues": 9,
165
+ "issue_types": [
166
+ "cache_miss",
167
+ "readonly_stall",
168
+ "cache",
169
+ "broad_tool_result",
170
+ "service_tier",
171
+ "missed_parallelism",
172
+ "tool_churn_cluster"
173
+ ],
174
+ "read_fragmentation_paths": [],
175
+ "grep_sweep_count": 0
176
+ }
177
+ },
178
+ {
179
+ "id": "r4-impl-usage-summary#2",
180
+ "agent": "worker",
181
+ "ok": true,
182
+ "ms": 90912,
183
+ "sessionId": "sess_22136_1783058427761_1783058427997_8ea3b1019cb8865372862f9df6344d43",
184
+ "output": "sessionId: sess_22136_1783058427761_1783058427997_8ea3b1019cb8865372862f9df6344d43\n요청 범위가 명확해서 바로 구현하고 검증까지 진행하겠습니다.구현 파일이 이미 작업 트리에 준비되어 있어 검증을 진행합니다.완료했습니다, 재영님. `usage:today` 스크립트와 `scripts/usage-today.mjs`가 추가되었습니다.\n\n- **바뀐 점** `package.json`에 `usage:today`를 추가했고, 새 스크립트가 `MIXDOG_DATA_DIR` 또는 기본 `~/.mixdog/data/history/agent-trace.jsonl`을 읽어 오늘 사용량을 모델별/총합으로 출력합니다.\n\n- **집계 내용** 모델별 `calls`, `input`, `cached`, `output`, `costUsd`와 `GRAND TOTAL` 라인을 출력하며 `--trace`, `--json`도 지원합니다.\n\n- **검증** `node --check scripts/usage-today.mjs` 통과, `npm run usage:today` 실행 완료: `GRAND TOTAL 1318 calls, 48.23M input, 47.96M cached, 1.57M output, 85.4306 costUsd`.\n\n- **참고** 작업 대상 외 기존 수정 파일 `src/runtime/channels/lib/event-queue.mjs`, `src/runtime/channels/lib/output-forwarder.mjs`는 건드리지 않았습니다.",
185
+ "card": {
186
+ "session": "sess_22136_1783058427761_1783058427997_8ea3b1019cb8865372862f9df6344d43",
187
+ "provider": "openai-oauth",
188
+ "model": "gpt-5.5",
189
+ "wall_ms": 80417,
190
+ "turns": 12,
191
+ "tool_calls": 13,
192
+ "tools_per_turn": 1.1,
193
+ "total_tool_ms": 3259,
194
+ "llm_stream_ms": 77037,
195
+ "cache_ratio": 0.6162420476577276,
196
+ "cached_tokens": 103936,
197
+ "prompt_tokens": 168661,
198
+ "uncached_tokens": 64725,
199
+ "output_tokens": 3898,
200
+ "cache_weighted_input_10": 75118.6,
201
+ "cache_weighted_input_25": 90709,
202
+ "prompt_growth": 13620,
203
+ "antipatterns": 1,
204
+ "issues": 7,
205
+ "issue_types": [
206
+ "cache_miss",
207
+ "cache",
208
+ "service_tier",
209
+ "missed_parallelism",
210
+ "tool_churn_cluster"
211
+ ],
212
+ "read_fragmentation_paths": [],
213
+ "grep_sweep_count": 0
214
+ }
215
+ },
216
+ {
217
+ "id": "r4-explain-compact-engine#2",
218
+ "agent": "explore",
219
+ "ok": true,
220
+ "ms": 78464,
221
+ "sessionId": "sess_59476_1783058430062_1783058430294_c496f72ecc8cb5c98b93240b9e9ded45",
222
+ "output": "sessionId: sess_59476_1783058430062_1783058430294_c496f72ecc8cb5c98b93240b9e9ded45\n- **Entry points/callers:** `compact.mjs` re-exports `semanticCompactMessages` and `recallFastTrackCompactMessages`; live loop calls semantic at pre-send and recall via `runRecallFastTrackCompact`, while manager/manual paths call both through `runSessionCompaction` (`compact.mjs:52-55`, `engine.mjs:278`, `engine.mjs:445`, `loop.mjs:414-459`, `compaction-runner.mjs:207-318`).\n\n- **Fire decision:** live compaction runs before provider send after queued steering is drained, only when policy auto is enabled and `shouldCompactForSession` says pressure meets trigger, estimate is unknown, or reactive overflow forced it (`loop.mjs:324-354`, `compact-policy.mjs:89-93`, `compact-policy.mjs:170-174`).\n\n- **Budget/trigger:** pressure is transcript tokens plus reserve; trigger is explicit sub-boundary auto limit or `boundary - buffer`, with default buffer ratio `0.1` capped by `0.25`; target budget is compact target plus reserve capped at boundary (`compact-policy.mjs:150-168`, `compact-policy.mjs:101-117`, `context-utils.mjs:94-96`, `context-utils.mjs:206-228`).\n\n- **Type routing:** policy chooses `semantic` by default, forces agent-owned sessions to semantic, and routes recall-fasttrack vs semantic accordingly (`constants.mjs:42-44`, `compact-policy.mjs:39-51`, `compact-policy.mjs:123-140`, `loop.mjs:414-459`).\n\n- **Semantic window:** engine first sanitizes, separates protected system/reminder prefix from conversation, finds prior compact summary, excludes summaries from live history, then splits into head/tail (`engine.mjs:100-112`, `messages.mjs:56-81`).\n\n- **Semantic tail:** with user turns, it keeps up to `tailTurns` recent turns within `preserveRecentBudget`, splitting the newest turn suffix if needed; without user turns, it cuts only at non-tool messages so assistant/tool pairs stay together (`engine.mjs:130-185`, `engine.mjs:188-233`, `engine.mjs:235-250`).\n\n- **Recall tail:** recall-fasttrack keeps newest user-anchored turns, drops oldest kept turns until under cap, then truncates the oldest surviving message if still oversized; no-user tails keep newest fitting messages and repair tool pairs (`engine.mjs:449-467`, `engine.mjs:525-575`, `engine.mjs:593-619`).\n\n- **Redaction hook:** no-op fit returns sanitized transcript unchanged; once compaction proceeds, `redactToolCallSecretsInMessages` runs before window selection so preserved system/tail are measured and emitted redacted, while prompt-side tool summaries also redact/truncate args (`engine.mjs:284-312`, `engine.mjs:389-393`, `text-utils.mjs:219-326`, `summary.mjs:85-90`).\n\n- **Summary construction:** semantic sends a compact prompt to provider, repairs malformed summary schema, fits summary into remaining budget, then emits `[system, summary, tail]`; recall-fasttrack injects memory recall/prior summary into a fitted summary without an LLM call (`engine.mjs:333-386`, `summary.mjs:302-386`, `engine.mjs:666-695`, `summary.mjs:412-450`).\n\n- **Failure/fallback:** semantic throws on missing provider, empty live/window, no compactable head, prompt/summary fit failures, empty provider output, or final budget overflow; recall throws on no compactable history, empty recall, summary fit failure, or overflow (`engine.mjs:278-280`, `engine.mjs:252-256`, `engine.mjs:315-317`, `engine.mjs:333-337`, `engine.mjs:371-397`, `engine.mjs:653-699`).\n\n- **Recovery paths:** loop semantic failures can fall back to anchor-independent tool-output prune, but recall-fasttrack failures do not silently prune; manager recall-fasttrack failure first tries semantic fallback, then non-recall failures may prune, otherwise records failed stage/error (`loop.mjs:500-618`, `compaction-runner.mjs:237-347`, `compaction-runner.mjs:348-397`).",
223
+ "card": {
224
+ "session": "sess_59476_1783058430062_1783058430294_c496f72ecc8cb5c98b93240b9e9ded45",
225
+ "provider": "openai-oauth",
226
+ "model": "gpt-5.5",
227
+ "wall_ms": 67975,
228
+ "turns": 13,
229
+ "tool_calls": 16,
230
+ "tools_per_turn": 1.2,
231
+ "total_tool_ms": 920,
232
+ "llm_stream_ms": 66801,
233
+ "cache_ratio": 0.563987246794594,
234
+ "cached_tokens": 247296,
235
+ "prompt_tokens": 438478,
236
+ "uncached_tokens": 191182,
237
+ "output_tokens": 4369,
238
+ "cache_weighted_input_10": 215911.6,
239
+ "cache_weighted_input_25": 253006,
240
+ "prompt_growth": 75759,
241
+ "antipatterns": 1,
242
+ "issues": 11,
243
+ "issue_types": [
244
+ "cache_miss",
245
+ "readonly_stall",
246
+ "cache",
247
+ "broad_tool_result",
248
+ "service_tier",
249
+ "missed_parallelism",
250
+ "tool_churn_cluster"
251
+ ],
252
+ "read_fragmentation_paths": [],
253
+ "grep_sweep_count": 0
254
+ }
255
+ }
256
+ ],
257
+ "task_complete": true,
258
+ "task_errors": [],
259
+ "score_complete": true,
260
+ "score_errors": [],
261
+ "group": {
262
+ "n": 6,
263
+ "wall_ms": 83840.5,
264
+ "turns": 9.3,
265
+ "tool_calls": 10.5,
266
+ "tools_per_turn": 1.1,
267
+ "total_tool_ms": 1305.8,
268
+ "llm_stream_ms": 81841.3,
269
+ "cache_ratio": 0.5,
270
+ "cached_tokens": 130389.3,
271
+ "prompt_tokens": 221450.2,
272
+ "uncached_tokens": 91060.8,
273
+ "output_tokens": 6305.7,
274
+ "cache_weighted_input_10": 104099.8,
275
+ "cache_weighted_input_25": 123658.2,
276
+ "prompt_growth": 40136.3,
277
+ "antipatterns": 1,
278
+ "issues": 7,
279
+ "grep_sweep_count": 0
280
+ },
281
+ "cards": [
282
+ {
283
+ "session": "sess_45552_1783058338359_1783058338607_a015a1cdab90e4a2d1f531080d1c286b",
284
+ "provider": "openai-oauth",
285
+ "model": "gpt-5.5",
286
+ "wall_ms": 78893,
287
+ "turns": 4,
288
+ "tool_calls": 3,
289
+ "tools_per_turn": 0.8,
290
+ "total_tool_ms": 20,
291
+ "llm_stream_ms": 78392,
292
+ "cache_ratio": 0.11257956255063072,
293
+ "cached_tokens": 9728,
294
+ "prompt_tokens": 86410,
295
+ "uncached_tokens": 76682,
296
+ "output_tokens": 7512,
297
+ "cache_weighted_input_10": 77654.8,
298
+ "cache_weighted_input_25": 79114,
299
+ "prompt_growth": 34226,
300
+ "antipatterns": 1,
301
+ "issues": 6,
302
+ "issue_types": [
303
+ "cache",
304
+ "cache_miss",
305
+ "broad_tool_result",
306
+ "service_tier",
307
+ "tool_churn_cluster"
308
+ ],
309
+ "read_fragmentation_paths": [],
310
+ "grep_sweep_count": 0
311
+ },
312
+ {
313
+ "session": "sess_40340_1783058338374_1783058338625_09d691094df16330e45e10c7a25fca4b",
314
+ "provider": "openai-oauth",
315
+ "model": "gpt-5.5",
316
+ "wall_ms": 75469,
317
+ "turns": 10,
318
+ "tool_calls": 13,
319
+ "tools_per_turn": 1.3,
320
+ "total_tool_ms": 2431,
321
+ "llm_stream_ms": 70209,
322
+ "cache_ratio": 0.6937749383029269,
323
+ "cached_tokens": 120320,
324
+ "prompt_tokens": 173428,
325
+ "uncached_tokens": 53108,
326
+ "output_tokens": 5186,
327
+ "cache_weighted_input_10": 65140,
328
+ "cache_weighted_input_25": 83188,
329
+ "prompt_growth": 21498,
330
+ "antipatterns": 1,
331
+ "issues": 5,
332
+ "issue_types": [
333
+ "cache_miss",
334
+ "cache",
335
+ "service_tier",
336
+ "missed_parallelism",
337
+ "tool_churn_cluster"
338
+ ],
339
+ "read_fragmentation_paths": [],
340
+ "grep_sweep_count": 0
341
+ },
342
+ {
343
+ "session": "sess_41232_1783058338395_1783058338643_9c39c68d28de50be18441725abb6f037",
344
+ "provider": "openai-oauth",
345
+ "model": "gpt-5.5",
346
+ "wall_ms": 81153,
347
+ "turns": 7,
348
+ "tool_calls": 9,
349
+ "tools_per_turn": 1.3,
350
+ "total_tool_ms": 697,
351
+ "llm_stream_ms": 80277,
352
+ "cache_ratio": 0.6459696986035477,
353
+ "cached_tokens": 119808,
354
+ "prompt_tokens": 185470,
355
+ "uncached_tokens": 65662,
356
+ "output_tokens": 6640,
357
+ "cache_weighted_input_10": 77642.8,
358
+ "cache_weighted_input_25": 95614,
359
+ "prompt_growth": 52898,
360
+ "antipatterns": 1,
361
+ "issues": 4,
362
+ "issue_types": [
363
+ "cache",
364
+ "broad_tool_result",
365
+ "service_tier",
366
+ "tool_churn_cluster"
367
+ ],
368
+ "read_fragmentation_paths": [],
369
+ "grep_sweep_count": 0
370
+ },
371
+ {
372
+ "session": "sess_25396_1783058424363_1783058424619_5963443d3a6c9851961f027db3819c54",
373
+ "provider": "openai-oauth",
374
+ "model": "gpt-5.5",
375
+ "wall_ms": 119136,
376
+ "turns": 10,
377
+ "tool_calls": 9,
378
+ "tools_per_turn": 0.9,
379
+ "total_tool_ms": 508,
380
+ "llm_stream_ms": 118332,
381
+ "cache_ratio": 0.6560918574934662,
382
+ "cached_tokens": 181248,
383
+ "prompt_tokens": 276254,
384
+ "uncached_tokens": 95006,
385
+ "output_tokens": 10229,
386
+ "cache_weighted_input_10": 113130.8,
387
+ "cache_weighted_input_25": 140318,
388
+ "prompt_growth": 42817,
389
+ "antipatterns": 1,
390
+ "issues": 9,
391
+ "issue_types": [
392
+ "cache_miss",
393
+ "readonly_stall",
394
+ "cache",
395
+ "broad_tool_result",
396
+ "service_tier",
397
+ "missed_parallelism",
398
+ "tool_churn_cluster"
399
+ ],
400
+ "read_fragmentation_paths": [],
401
+ "grep_sweep_count": 0
402
+ },
403
+ {
404
+ "session": "sess_22136_1783058427761_1783058427997_8ea3b1019cb8865372862f9df6344d43",
405
+ "provider": "openai-oauth",
406
+ "model": "gpt-5.5",
407
+ "wall_ms": 80417,
408
+ "turns": 12,
409
+ "tool_calls": 13,
410
+ "tools_per_turn": 1.1,
411
+ "total_tool_ms": 3259,
412
+ "llm_stream_ms": 77037,
413
+ "cache_ratio": 0.6162420476577276,
414
+ "cached_tokens": 103936,
415
+ "prompt_tokens": 168661,
416
+ "uncached_tokens": 64725,
417
+ "output_tokens": 3898,
418
+ "cache_weighted_input_10": 75118.6,
419
+ "cache_weighted_input_25": 90709,
420
+ "prompt_growth": 13620,
421
+ "antipatterns": 1,
422
+ "issues": 7,
423
+ "issue_types": [
424
+ "cache_miss",
425
+ "cache",
426
+ "service_tier",
427
+ "missed_parallelism",
428
+ "tool_churn_cluster"
429
+ ],
430
+ "read_fragmentation_paths": [],
431
+ "grep_sweep_count": 0
432
+ },
433
+ {
434
+ "session": "sess_59476_1783058430062_1783058430294_c496f72ecc8cb5c98b93240b9e9ded45",
435
+ "provider": "openai-oauth",
436
+ "model": "gpt-5.5",
437
+ "wall_ms": 67975,
438
+ "turns": 13,
439
+ "tool_calls": 16,
440
+ "tools_per_turn": 1.2,
441
+ "total_tool_ms": 920,
442
+ "llm_stream_ms": 66801,
443
+ "cache_ratio": 0.563987246794594,
444
+ "cached_tokens": 247296,
445
+ "prompt_tokens": 438478,
446
+ "uncached_tokens": 191182,
447
+ "output_tokens": 4369,
448
+ "cache_weighted_input_10": 215911.6,
449
+ "cache_weighted_input_25": 253006,
450
+ "prompt_growth": 75759,
451
+ "antipatterns": 1,
452
+ "issues": 11,
453
+ "issue_types": [
454
+ "cache_miss",
455
+ "readonly_stall",
456
+ "cache",
457
+ "broad_tool_result",
458
+ "service_tier",
459
+ "missed_parallelism",
460
+ "tool_churn_cluster"
461
+ ],
462
+ "read_fragmentation_paths": [],
463
+ "grep_sweep_count": 0
464
+ }
465
+ ]
466
+ }