mixdog 0.9.157 → 0.9.159

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 (135) hide show
  1. package/README.md +30 -14
  2. package/package.json +13 -8
  3. package/scripts/build-runtime-linux.sh +7 -0
  4. package/scripts/build-runtime-macos.sh +7 -0
  5. package/scripts/lib/stage-postgres-runtime-windows.ps1 +13 -2
  6. package/scripts/office-design-audit.mjs +43 -0
  7. package/scripts/release-paths.mjs +108 -0
  8. package/scripts/smoke-runtime-negative.sh +3 -2
  9. package/scripts/suite-health.mjs +102 -0
  10. package/src/defaults/skills/setup/SKILL.md +10 -11
  11. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +12 -12
  12. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +0 -4
  13. package/src/runtime/agent/orchestrator/config.mjs +8 -13
  14. package/src/runtime/agent/orchestrator/internal-tools.mjs +6 -1
  15. package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +234 -0
  16. package/src/runtime/agent/orchestrator/providers/cursor-wire-interactions.mjs +80 -0
  17. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +75 -1
  18. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +234 -93
  19. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +52 -2
  20. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +2 -2
  21. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +19 -7
  22. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +0 -9
  23. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +8 -44
  24. package/src/runtime/agent/orchestrator/session/compact/continuation.mjs +55 -0
  25. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +89 -4
  26. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +227 -767
  27. package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +4 -4
  28. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +43 -50
  29. package/src/runtime/agent/orchestrator/session/compact.mjs +7 -21
  30. package/src/runtime/agent/orchestrator/session/context-utils.mjs +75 -0
  31. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +1 -0
  32. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +113 -80
  33. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  34. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +472 -0
  35. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +6 -2
  36. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +16 -5
  37. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +66 -163
  38. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -20
  39. package/src/runtime/agent/orchestrator/session/manager/message-sanitize.mjs +8 -4
  40. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +4 -23
  41. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +3 -14
  42. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +0 -2
  43. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +17 -2
  44. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +64 -195
  45. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +60 -0
  46. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +23 -3
  47. package/src/runtime/agent/orchestrator/session/tool-batch.mjs +1 -0
  48. package/src/runtime/agent/orchestrator/session/tool-envelope.mjs +18 -6
  49. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +49 -3
  50. package/src/runtime/agent/orchestrator/tools/builtin/lib/glob-static-prefix.mjs +121 -0
  51. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +6 -14
  52. package/src/runtime/browser-bridge/action-schema.mjs +19 -2
  53. package/src/runtime/browser-bridge/client.mjs +6 -2
  54. package/src/runtime/browser-bridge/tool-defs.mjs +6 -6
  55. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +4 -5
  56. package/src/runtime/computer-bridge/action-schema.mjs +85 -365
  57. package/src/runtime/computer-bridge/client.mjs +71 -6
  58. package/src/runtime/computer-bridge/core-actions.mjs +227 -0
  59. package/src/runtime/computer-bridge/error-recovery.mjs +105 -0
  60. package/src/runtime/computer-bridge/tool-defs.mjs +13 -12
  61. package/src/runtime/memory/data/runtime-manifest.json +17 -17
  62. package/src/runtime/memory/index.mjs +2 -1
  63. package/src/runtime/memory/lib/compact-handoff.mjs +127 -0
  64. package/src/runtime/memory/lib/http-wire.mjs +1 -1
  65. package/src/runtime/memory/lib/memory-config-flags.mjs +10 -0
  66. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +5 -3
  67. package/src/runtime/memory/lib/memory-cycle3.mjs +5 -5
  68. package/src/runtime/memory/lib/query-handlers.mjs +16 -6
  69. package/src/runtime/memory/lib/recall-format.mjs +18 -41
  70. package/src/runtime/memory/lib/runtime-fetcher.mjs +16 -6
  71. package/src/runtime/memory/lib/session-ingest-runtime.mjs +4 -2
  72. package/src/runtime/memory/lib/session-ingest.mjs +37 -9
  73. package/src/runtime/office/assurance-benchmark.mjs +68 -2
  74. package/src/runtime/office/assurance.mjs +82 -0
  75. package/src/runtime/office/capabilities.mjs +9 -7
  76. package/src/runtime/office/composition-system.mjs +5 -0
  77. package/src/runtime/office/content-model.mjs +1 -1
  78. package/src/runtime/office/design-aesthetics.mjs +460 -0
  79. package/src/runtime/office/design-art-direction.mjs +283 -0
  80. package/src/runtime/office/design-creative-director.mjs +170 -0
  81. package/src/runtime/office/design-deck-diversity.mjs +115 -0
  82. package/src/runtime/office/design-docx-components.mjs +60 -1
  83. package/src/runtime/office/design-docx.mjs +31 -3
  84. package/src/runtime/office/design-frontier-review.mjs +129 -0
  85. package/src/runtime/office/design-layout-grammar.mjs +134 -0
  86. package/src/runtime/office/design-pptx-plan.mjs +236 -125
  87. package/src/runtime/office/design-pptx-semantic-flow.mjs +111 -0
  88. package/src/runtime/office/design-pptx-semantic-visuals.mjs +885 -0
  89. package/src/runtime/office/design-pptx-stack.mjs +58 -0
  90. package/src/runtime/office/design-review.mjs +4 -0
  91. package/src/runtime/office/design-system.mjs +26 -4
  92. package/src/runtime/office/design-tokens.mjs +36 -8
  93. package/src/runtime/office/design-xlsx.mjs +28 -5
  94. package/src/runtime/office/image-layout.mjs +81 -0
  95. package/src/runtime/office/index.mjs +2 -0
  96. package/src/runtime/office/office-actions.mjs +42 -3
  97. package/src/runtime/office/office-com-host.ps1 +277 -31
  98. package/src/runtime/office/office-com-session-host.ps1 +217 -7
  99. package/src/runtime/office/office-sessions.mjs +2 -0
  100. package/src/runtime/office/portable-pptx-core.mjs +11 -1
  101. package/src/runtime/office/portable-pptx-shapes.mjs +32 -6
  102. package/src/runtime/office/portable-slide-shapes.mjs +14 -1
  103. package/src/runtime/office/portable-validation.mjs +23 -4
  104. package/src/runtime/office/quality-live-benchmark.mjs +121 -67
  105. package/src/runtime/office/quality-pipeline.mjs +20 -0
  106. package/src/runtime/office/quality-score.mjs +84 -0
  107. package/src/runtime/office/text-metrics.mjs +96 -2
  108. package/src/runtime/office/tool-defs.mjs +5 -1
  109. package/src/session-runtime/builtin-features.mjs +105 -0
  110. package/src/session-runtime/config-helpers.mjs +16 -11
  111. package/src/session-runtime/config-lifecycle.mjs +6 -1
  112. package/src/session-runtime/context-status.mjs +14 -13
  113. package/src/session-runtime/goal-reminder.mjs +18 -0
  114. package/src/session-runtime/runtime-core.mjs +24 -16
  115. package/src/session-runtime/session-transcript.mjs +2 -2
  116. package/src/session-runtime/session-turn-api.mjs +5 -1
  117. package/src/session-runtime/settings-api.mjs +63 -14
  118. package/src/standalone/session-protocol.mjs +2 -0
  119. package/src/tui/App.jsx +1 -3
  120. package/src/tui/app/create-app-pickers.mjs +0 -4
  121. package/src/tui/app/extension-pickers.mjs +1 -56
  122. package/src/tui/app/input-parsers.mjs +1 -27
  123. package/src/tui/app/prompt-submit.mjs +2 -2
  124. package/src/tui/app/settings-picker.mjs +2 -43
  125. package/src/tui/app/slash-commands.mjs +0 -1
  126. package/src/tui/app/slash-dispatch.mjs +0 -4
  127. package/src/tui/app/usage-context-panels.mjs +0 -1
  128. package/src/tui/dist/index.mjs +10 -110
  129. package/src/tui/lib/voice-setup.mjs +13 -20
  130. package/src/tui/session/context-state.mjs +7 -1
  131. package/src/tui/session/session-api-ext.mjs +10 -5
  132. package/src/tui/session/session-api.mjs +20 -3
  133. package/src/tui/session/session-flow.mjs +6 -11
  134. package/src/vendor/statusline/src/gateway/route-meta.mjs +2 -3
  135. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +0 -245
package/README.md CHANGED
@@ -45,31 +45,35 @@ workflow setup.
45
45
 
46
46
  Terminal-Bench 2.1 — same model, same 89 tasks, same official verifier, with
47
47
  only the harness changed. Against the native CLI of each model family, Mixdog
48
- scores higher while spending less to get there.
48
+ delivers the same results at the same speed — on a fraction of the context,
49
+ for far less cost.
49
50
 
50
51
  ### GPT-5.6 Sol xhigh — Mixdog vs Codex CLI
51
52
 
52
53
  ![Terminal-Bench 2.1: Mixdog with GPT-5.6 Sol xhigh versus Codex CLI](https://raw.githubusercontent.com/tribgames/mixdog/main/benchmarks/terminal-bench-2.1/tb21-sol-vs-codex.svg)
53
54
 
54
- - **86.5%** (385/445) vs Codex CLI's **84.3%** (75/89)
55
- - **42%** lower priced cost$0.641 vs $1.096 per trial
56
- - **45%** smaller median final context18.5k vs 33.5k tokens
57
- - **1.11×** faster — 339s vs 378s per trial
55
+ - **39%** lower priced cost $0.476 vs $0.782 per trial
56
+ - **46%** smaller median final context 18.5k vs 34.3k tokens
57
+ - **86.5%** (385/445) vs Codex CLI's **86.1%** (383/445) full `k=5` on both
58
+ sides, pass@5 **96.6%** vs 95.5%
59
+ - Matched speed — 415s vs 437s wall time per trial
58
60
 
59
61
  ### Claude Opus 5 — Mixdog vs Claude Code
60
62
 
61
63
  ![Terminal-Bench 2.1: Mixdog with Claude Opus 5 versus Claude Code](https://raw.githubusercontent.com/tribgames/mixdog/main/benchmarks/terminal-bench-2.1/tb21-opus-vs-claude-code.svg)
62
64
 
63
- - **79/89** vs Claude Code's **77/89**
64
65
  - **19%** lower priced cost — $104.29 vs $129.21 per run
65
66
  - **28%** smaller median final context — 27.6k vs 38.2k tokens
66
- - **1.15×** faster
67
+ - **79/89** vs Claude Code's **77/89**
68
+ - **1.16×** faster — 610s vs 708s wall time per trial
67
69
 
68
- Every run uses the official Harbor verifier, fast mode off, a 272k context
69
- window, and zero retries. The Mixdog Sol run follows the protocol the official
70
- Terminal-Bench leaderboard requires all 89 tasks repeated five times (`k=5`,
71
- 445 trials); the Codex CLI baseline and both Opus-side runs are single passes
72
- (`k=1`, 89 trials each).
70
+ Every run uses the official Harbor verifier, fast mode off, and a 272k context
71
+ window; task failures and agent timeouts are never retried. The Sol comparison
72
+ follows the protocol the official Terminal-Bench leaderboard requires on both
73
+ sides all 89 tasks repeated five times (`k=5`, 445 trials each); the
74
+ Opus-side runs are single passes (`k=1`, 89 trials each). Speed is the full
75
+ trial wall clock, and cost values both sides at the same current API list
76
+ rates.
73
77
 
74
78
  The leaderboard is not accepting community submissions, so every run here ships
75
79
  its raw artifacts instead — Harbor verdicts, official verifier output, pinned
@@ -88,6 +92,13 @@ the harness, presets, and metric scripts that recompute each number above:
88
92
  MCP, skills, hooks, and plugins.
89
93
  - **Local memory** — semantic and lexical recall with project-scoped context
90
94
  and multilingual retrieval.
95
+ - **Browser Use** — a logged-in Chromium pane the agent can drive: tabs,
96
+ forms, downloads, and snapshots, with one-time Chrome profile import
97
+ including cookies and passwords.
98
+ - **Computer Use** — agent control of the Windows desktop through screen
99
+ capture, accessibility, OCR, and a strict guarded input contract.
100
+ - **Office documents** — author and edit Word, Excel, and PowerPoint files
101
+ with model-authored design plans, charts, and assurance-checked output.
91
102
  - **Encrypted remote access** — pair the installable web app with Desktop and
92
103
  use Mixdog from a browser or phone over authenticated E2EE.
93
104
  - **Desktop coding app** — agent panes, Monaco editor, Git, terminals, file
@@ -180,7 +191,6 @@ stdout; diagnostics remain on stderr.
180
191
  /mcp manage MCP servers and tools
181
192
  /skills choose a skill for the next request
182
193
  /plugins manage local plugin integrations
183
- /hooks manage before-tool hooks and events
184
194
  /setting open runtime settings
185
195
  /profile set your title and response language
186
196
  /update check for updates
@@ -202,14 +212,20 @@ Mixdog Desktop runs the same agent runtime as the CLI:
202
212
  - Git staging, commits, branches, and generated commit messages
203
213
  - File explorer with previews, thumbnails, search, and drag-and-drop
204
214
  - Integrated terminal tabs using the local system shell
215
+ - Browser Use pane with agent control and Chromium profile import
216
+ - Computer Use on Windows with guarded native input
217
+ - Office document authoring with rendered previews
205
218
  - Image and video generation Studio with a persistent local gallery
206
219
  - Visual workflow, agent, schedule, and webhook editors
207
220
  - Voice dictation with an optional local transcription runtime
221
+ - Extensions hub with guided setup for Git, Memory, Browser Use, Computer
222
+ Use, Office, and voice
208
223
  - Provider setup, usage, git identity, and remote pairing settings
209
224
 
210
225
  The paired remote web app is installable on desktop and mobile browsers. It
211
226
  uses an authenticated end-to-end encrypted connection before session state,
212
- terminal data, files, or operation requests cross the relay.
227
+ terminal data, files, or operation requests cross the relay, and adds mobile
228
+ share-target intake, push notifications, and remote Browser Use.
213
229
 
214
230
  For desktop development:
215
231
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixdog",
3
- "version": "0.9.157",
3
+ "version": "0.9.159",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Standalone mixdog coding-agent CLI/TUI workspace.",
@@ -32,6 +32,10 @@
32
32
  "!scripts/recall-bench-*.txt",
33
33
  "!scripts/*-test.mjs",
34
34
  "!scripts/*.test.mjs",
35
+ "!scripts/tool-contracts/",
36
+ "!scripts/provider-toolcall/",
37
+ "!scripts/session-transport/",
38
+ "!scripts/shellhardening/",
35
39
  "!scripts/*-smoke.mjs",
36
40
  "!scripts/smoke-loop*.mjs",
37
41
  "!scripts/*-bench.mjs",
@@ -54,25 +58,25 @@
54
58
  "smoke:all": "npm run smoke && npm run smoke:boot && npm run smoke:patch && npm run smoke:compact",
55
59
  "smoke:boot": "node scripts/boot-smoke.mjs",
56
60
  "smoke:compact": "node scripts/compact-smoke.mjs",
57
- "test:compact": "node --test scripts/suite-compact-test.mjs src/runtime/agent/orchestrator/session/token-estimate.test.mjs",
61
+ "test:compact": "node --test scripts/suite-compact-test.mjs src/runtime/agent/orchestrator/session/compact-fresh-context.test.mjs src/runtime/agent/orchestrator/session/compaction-read-reset.test.mjs src/runtime/agent/orchestrator/session/token-estimate.test.mjs",
58
62
  "test:markdown": "node --test scripts/markdown-surface-test.mjs",
59
63
  "smoke:loop": "node scripts/smoke-loop.mjs",
60
64
  "smoke:loop:final": "node scripts/smoke-loop-report.mjs --require-complete --min-elapsed 5h --min-iterations 400 --max-gap 60s --max-smoke-ms 10000 --max-avg-smoke-ms 8500 --max-step-ms smoke.mjs=4000 --max-step-ms boot-smoke.mjs=8000 --max-rss-mb 140 --max-rss-growth-mb 50",
61
65
  "smoke:loop:report": "node scripts/smoke-loop-report.mjs",
62
66
  "build:spawn:test": "cargo build --locked --manifest-path native/mixdog-spawn/Cargo.toml",
63
- "test:tool-contracts": "npm run build:spawn:test && node scripts/tool-smoke.mjs",
67
+ "test:tool-contracts": "npm run build:spawn:test && node --test --test-force-exit \"scripts/tool-contracts/*.test.mjs\"",
64
68
  "smoke:patch": "node scripts/apply-patch-edit-smoke.mjs",
65
- "test:shellhardening": "npm run build:spawn:test && node --test scripts/suite-shellhardening-test.mjs scripts/suite-shell-direct-exe-test.mjs",
66
- "test:providers": "node --test scripts/provider-toolcall-test.mjs scripts/provider-contract-test.mjs scripts/provider-stream-outcome-test.mjs scripts/cursor-provider-test.mjs src/runtime/agent/orchestrator/providers/openai-codex-identity.test.mjs src/runtime/agent/orchestrator/providers/openai-ws-delta-parity.test.mjs",
69
+ "test:shellhardening": "npm run build:spawn:test && node --test \"scripts/shellhardening/*.test.mjs\" scripts/suite-shell-direct-exe-test.mjs",
70
+ "test:providers": "node --test \"scripts/provider-toolcall/*.test.mjs\" scripts/provider-contract-test.mjs scripts/provider-stream-outcome-test.mjs scripts/cursor-provider-test.mjs src/runtime/agent/orchestrator/providers/openai-codex-identity.test.mjs src/runtime/agent/orchestrator/providers/openai-ws-delta-parity.test.mjs",
67
71
  "test:embedding-runtime:warmup": "node scripts/verify-embedding-runtime.mjs --warmup",
68
72
  "test:release-assets": "node --check scripts/verify-release-assets.mjs && node --check scripts/release-gate-test.mjs && node --check scripts/prepare-native-assets.mjs && node --test scripts/release-gate-test.mjs scripts/prepare-native-assets-test.mjs scripts/generate-voice-runtime-manifest.test.mjs",
69
73
  "test:native-edit-wire": "node scripts/native-edit-wire-test.mjs",
70
74
  "test:release-critical": "npm run test:release-assets && npm run smoke:patch && npm run test:providers",
71
75
  "test:spec-advisory": "node scripts/advisory-spec-test.mjs && npm run test:spec-advisory --prefix apps/desktop",
72
- "test:session-transport": "node --test scripts/session-transport-test.mjs scripts/daemon-bootstrap-test.mjs src/runtime/shared/child-spawn-remote.test.mjs src/standalone/session-runtime-agent-control-client.test.mjs src/standalone/session-runtime-dispatch-cancel.test.mjs src/standalone/session-runtime-host-factory.test.mjs src/standalone/session-runtime-inline-host.test.mjs src/standalone/session-runtime-provider-cooldown.test.mjs src/standalone/session-runtime-shard-host.test.mjs src/standalone/session-runtime-shard-router.test.mjs",
73
- "test:session": "node --test scripts/runtime-turn-contract-test.mjs scripts/session-save-fault-store-test.mjs scripts/turn-review-revert-test.mjs src/runtime/shared/tool-surface.test.mjs src/runtime/bridge-clients.test.mjs",
76
+ "test:session-transport": "node --test \"scripts/session-transport/*.test.mjs\" scripts/daemon-bootstrap-test.mjs src/runtime/shared/child-spawn-remote.test.mjs src/standalone/session-runtime-agent-control-client.test.mjs src/standalone/session-runtime-dispatch-cancel.test.mjs src/standalone/session-runtime-host-factory.test.mjs src/standalone/session-runtime-inline-host.test.mjs src/standalone/session-runtime-provider-cooldown.test.mjs src/standalone/session-runtime-shard-host.test.mjs src/standalone/session-runtime-shard-router.test.mjs",
77
+ "test:session": "node --test scripts/runtime-turn-contract-test.mjs scripts/session-save-fault-store-test.mjs scripts/turn-review-revert-test.mjs src/runtime/shared/tool-surface.test.mjs src/runtime/bridge-clients.test.mjs src/runtime/computer-bridge/client-semantic-error.test.mjs src/runtime/agent/orchestrator/session/tool-envelope.test.mjs src/runtime/agent/orchestrator/session/eager-dispatch.test.mjs",
74
78
  "test:quick": "npm run test:session && npm run test:session-transport && npm run test:desktop-main --prefix apps/desktop",
75
- "test:office": "node --test scripts/run-office-live-tests.test.mjs src/runtime/office/office-runtime.test.mjs src/runtime/office/office-assurance.test.mjs src/runtime/office/portable-authoring.test.mjs && npm run test:office-approval --prefix apps/desktop",
79
+ "test:office": "node --test scripts/run-office-live-tests.test.mjs src/runtime/office/office-runtime.test.mjs src/runtime/office/office-assurance.test.mjs src/runtime/office/portable-authoring.test.mjs src/runtime/office/slide-quality.test.mjs && npm run test:office-approval --prefix apps/desktop",
76
80
  "test:office:live": "node scripts/run-office-live-tests.mjs",
77
81
  "test:media": "node --test src/runtime/media/store.test.mjs src/runtime/media/renditions.test.mjs src/runtime/media/adapters/codex-image.test.mjs",
78
82
  "failures": "node scripts/tool-failures.mjs",
@@ -91,6 +95,7 @@
91
95
  "bench:recall": "node scripts/recall-bench.mjs",
92
96
  "bench:recall:strict": "node scripts/recall-bench.mjs --strict",
93
97
  "test:recall-validator": "node --test scripts/recall-bench-test.mjs",
98
+ "test:suite-health": "node --test scripts/suite-health.test.mjs",
94
99
  "bench:tui-load": "node scripts/tui-runtime-load-bench.mjs",
95
100
  "bench:output-style": "node scripts/output-style-bench.mjs",
96
101
  "bench:session-context": "node scripts/session-context-bench.mjs",
@@ -78,6 +78,7 @@ else
78
78
  make -j"$(nproc)"
79
79
  make install
80
80
  make -C contrib/pgcrypto install
81
+ make -C contrib/pg_trgm install
81
82
  fi
82
83
 
83
84
  PG_CONFIG="$STAGE_DIR/bin/pg_config"
@@ -255,6 +256,10 @@ for attempt in 1 2 3; do
255
256
  echo " vector extension version: $EXTV"
256
257
  echo " distance query result: $DIST"
257
258
  [[ "$EXTV" == "$PGVECTOR_VERSION" ]] || { echo "FAIL: extversion=$EXTV expected=$PGVECTOR_VERSION"; exit 1; }
259
+ "${RUN_AS[@]}" "$RUNTIME_DIR/bin/psql" -h 127.0.0.1 -p "$SMOKE_PORT" -U postgres -d postgres -c "CREATE EXTENSION pg_trgm;" > /dev/null
260
+ SIM="$("${RUN_AS[@]}" "$RUNTIME_DIR/bin/psql" -h 127.0.0.1 -p "$SMOKE_PORT" -U postgres -d postgres -tAc "SELECT similarity('mixdog','mixdig') > 0;")"
261
+ echo " pg_trgm similarity probe: $SIM"
262
+ [[ "$SIM" == "t" ]] || { echo "FAIL: pg_trgm similarity=$SIM"; exit 1; }
258
263
  "${RUN_AS[@]}" "$RUNTIME_DIR/bin/pg_ctl" -D "$SMOKE_DATA" -m fast stop > /dev/null
259
264
  )
260
265
  attempt_rc=$?
@@ -323,6 +328,8 @@ for attempt in 1 2 3; do
323
328
  "$EXTRACT_DIR/bin/psql" -h 127.0.0.1 -p "$EXTRACT_PORT" -U postgres -d postgres -tAc \
324
329
  "SELECT extversion FROM pg_extension WHERE extname='vector';")"
325
330
  [[ "$EXTV2" == "$PGVECTOR_VERSION" ]] || { echo "FAIL: extracted-smoke extversion=$EXTV2"; exit 1; }
331
+ "${RUN_AS[@]}" env -i HOME="$EXTRACT_DIR" PATH="/usr/bin:/bin" \
332
+ "$EXTRACT_DIR/bin/psql" -h 127.0.0.1 -p "$EXTRACT_PORT" -U postgres -d postgres -c "CREATE EXTENSION pg_trgm;" > /dev/null
326
333
  "${RUN_AS[@]}" env -i HOME="$EXTRACT_DIR" PATH="/usr/bin:/bin" \
327
334
  "$EXTRACT_DIR/bin/pg_ctl" -D "$EXTRACT_DATA" -m fast stop > /dev/null
328
335
  )
@@ -73,6 +73,7 @@ else
73
73
  make -j"$(sysctl -n hw.logicalcpu)"
74
74
  make install
75
75
  make -C contrib/pgcrypto install
76
+ make -C contrib/pg_trgm install
76
77
  fi
77
78
 
78
79
  PG_CONFIG="$STAGE_DIR/bin/pg_config"
@@ -165,6 +166,10 @@ DIST="$("$RUNTIME_DIR/bin/psql" -h 127.0.0.1 -p "$SMOKE_PORT" -U postgres -d pos
165
166
  echo " vector extension version: $EXTV"
166
167
  echo " distance query result: $DIST"
167
168
  [[ "$EXTV" == "$PGVECTOR_VERSION" ]] || { echo "FAIL: extversion=$EXTV expected=$PGVECTOR_VERSION"; exit 1; }
169
+ "$RUNTIME_DIR/bin/psql" -h 127.0.0.1 -p "$SMOKE_PORT" -U postgres -d postgres -c "CREATE EXTENSION pg_trgm;" > /dev/null
170
+ SIM="$("$RUNTIME_DIR/bin/psql" -h 127.0.0.1 -p "$SMOKE_PORT" -U postgres -d postgres -tAc "SELECT similarity('mixdog','mixdig') > 0;")"
171
+ echo " pg_trgm similarity probe: $SIM"
172
+ [[ "$SIM" == "t" ]] || { echo "FAIL: pg_trgm similarity=$SIM"; exit 1; }
168
173
  "$RUNTIME_DIR/bin/pg_ctl" -D "$SMOKE_DATA" -m fast stop > /dev/null
169
174
  trap - EXIT
170
175
  rm -rf "$SMOKE_DATA"
@@ -207,6 +212,8 @@ env -i HOME="$EXTRACT_DIR" PATH="/usr/bin:/bin" \
207
212
  "$EXTRACT_DIR/bin/psql" -h 127.0.0.1 -p "$EXTRACT_PORT" -U postgres -d postgres -c "CREATE EXTENSION vector;" > /dev/null
208
213
  EXTV2="$(env -i HOME="$EXTRACT_DIR" PATH="/usr/bin:/bin" "$EXTRACT_DIR/bin/psql" -h 127.0.0.1 -p "$EXTRACT_PORT" -U postgres -d postgres -tAc "SELECT extversion FROM pg_extension WHERE extname='vector';")"
209
214
  [[ "$EXTV2" == "$PGVECTOR_VERSION" ]] || { echo "FAIL: extracted-smoke extversion=$EXTV2"; exit 1; }
215
+ env -i HOME="$EXTRACT_DIR" PATH="/usr/bin:/bin" \
216
+ "$EXTRACT_DIR/bin/psql" -h 127.0.0.1 -p "$EXTRACT_PORT" -U postgres -d postgres -c "CREATE EXTENSION pg_trgm;" > /dev/null
210
217
  env -i HOME="$EXTRACT_DIR" PATH="/usr/bin:/bin" \
211
218
  "$EXTRACT_DIR/bin/pg_ctl" -D "$EXTRACT_DATA" -m fast stop > /dev/null
212
219
  trap - EXIT
@@ -64,6 +64,7 @@ function Stage-MixdogWindowsPgRuntime {
64
64
  )
65
65
  $ModuleSources = [ordered]@{
66
66
  'dict_snowball.dll' = Join-Path $PgRoot 'lib\dict_snowball.dll'
67
+ 'pg_trgm.dll' = Join-Path $PgRoot 'lib\pg_trgm.dll'
67
68
  'plpgsql.dll' = Join-Path $PgRoot 'lib\plpgsql.dll'
68
69
  'vector.dll' = $VectorDll
69
70
  }
@@ -137,6 +138,15 @@ function Stage-MixdogWindowsPgRuntime {
137
138
  }
138
139
  $PlpgsqlAssets | Copy-Item -Destination $RuntimeExtensionDir -Force
139
140
 
141
+ # pg_trgm ships with the runtime: memory recall's hybrid trigram CTEs and
142
+ # transcript inserts depend on it (runtime-v0.4.0 omitted it and every
143
+ # memory write/recall failed with 'could not access file "$libdir/pg_trgm"').
144
+ $PgTrgmAssets = @(Get-ChildItem -Path "$SourceShare\extension\pg_trgm*" -File)
145
+ if ($PgTrgmAssets.Count -eq 0) {
146
+ throw "Required pg_trgm extension assets not found under $SourceShare\extension"
147
+ }
148
+ $PgTrgmAssets | Copy-Item -Destination $RuntimeExtensionDir -Force
149
+
140
150
  $RuntimeBytes = (
141
151
  Get-ChildItem -LiteralPath $RuntimeDir -File -Recurse |
142
152
  Measure-Object -Property Length -Sum
@@ -174,7 +184,7 @@ function Assert-MixdogWindowsPgRuntime {
174
184
  throw "Unexpected PostgreSQL executable set: $($ActualExecutables -join ', ')"
175
185
  }
176
186
 
177
- $ExpectedModules = @('dict_snowball.dll', 'plpgsql.dll', 'vector.dll')
187
+ $ExpectedModules = @('dict_snowball.dll', 'pg_trgm.dll', 'plpgsql.dll', 'vector.dll')
178
188
  $ActualModules = @(
179
189
  Get-ChildItem -LiteralPath "$RuntimeDir\lib" -File -Filter '*.dll' |
180
190
  ForEach-Object Name |
@@ -195,7 +205,7 @@ function Assert-MixdogWindowsPgRuntime {
195
205
 
196
206
  $UnexpectedExtensionAssets = @(
197
207
  Get-ChildItem -LiteralPath "$RuntimeDir\share\extension" -Force |
198
- Where-Object { $_.Name -notlike 'plpgsql*' -and $_.Name -notlike 'vector*' }
208
+ Where-Object { $_.Name -notlike 'pg_trgm*' -and $_.Name -notlike 'plpgsql*' -and $_.Name -notlike 'vector*' }
199
209
  )
200
210
  if ($UnexpectedExtensionAssets.Count -gt 0) {
201
211
  throw "Unexpected extension assets leaked into runtime: $($UnexpectedExtensionAssets.Count)"
@@ -205,6 +215,7 @@ function Assert-MixdogWindowsPgRuntime {
205
215
  "$RuntimeDir\share\extension\vector.control",
206
216
  "$RuntimeDir\share\extension\vector--$PgVectorVersion.sql",
207
217
  "$RuntimeDir\share\extension\plpgsql.control",
218
+ "$RuntimeDir\share\extension\pg_trgm.control",
208
219
  "$RuntimeDir\share\postgres.bki"
209
220
  )
210
221
  foreach ($Path in $RequiredPaths) {
@@ -0,0 +1,43 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { basename, resolve } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+
5
+ import { reviewRenderedOfficePages } from '../src/runtime/office/assurance.mjs';
6
+
7
+ function argumentValue(name) {
8
+ const index = process.argv.indexOf(name);
9
+ return index >= 0 ? process.argv[index + 1] : '';
10
+ }
11
+
12
+ function pageFromPath(path, fallback) {
13
+ const match = basename(path).match(/(?:page|slide)[-_ ]?(\d+)/i);
14
+ return match ? Number(match[1]) : fallback;
15
+ }
16
+
17
+ export async function auditOfficeDesignImages(paths, {
18
+ format = 'pptx',
19
+ } = {}) {
20
+ const images = await Promise.all(paths.map(async (path, index) => {
21
+ const absolute = resolve(path);
22
+ const data = await readFile(absolute);
23
+ return {
24
+ page: pageFromPath(absolute, index + 1),
25
+ path: absolute,
26
+ mimeType: 'image/png',
27
+ data: data.toString('base64'),
28
+ };
29
+ }));
30
+ images.sort((left, right) => left.page - right.page);
31
+ return reviewRenderedOfficePages(images, { format });
32
+ }
33
+
34
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
35
+ const format = argumentValue('--format') || 'pptx';
36
+ const paths = process.argv.slice(2).filter((entry, index, values) => (
37
+ entry !== '--format' && values[index - 1] !== '--format'
38
+ ));
39
+ if (!paths.length) throw new Error('Pass rendered page image paths to audit.');
40
+ const report = await auditOfficeDesignImages(paths, { format });
41
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
42
+ if (!report.ok) process.exitCode = 1;
43
+ }
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ // Single source of truth for CI/CD path selection.
3
+ //
4
+ // Consumers:
5
+ // - .github/workflows/release-gate.yml → `node scripts/release-paths.mjs desktop-regex|runtime-regex`
6
+ // (grep -E patterns selecting which incremental gates a change requires)
7
+ // - .github/workflows/deploy.yml → `import { RELEASE_CRITICAL_PATHS }`
8
+ // (git diff paths whose change invalidates the previous release's
9
+ // critical verification)
10
+ //
11
+ // Adding or renaming a release-relevant script means editing THIS file only;
12
+ // the workflows derive their patterns from it at run time.
13
+
14
+ export const PACKAGE_MANIFESTS = ['package.json', 'package-lock.json'];
15
+
16
+ // This module governs gate selection itself, so changing it must re-run
17
+ // every gate it feeds.
18
+ const GATE_SELECTION_SOURCES = ['scripts/release-paths.mjs'];
19
+
20
+ // Prefixes whose changes require the desktop bundle gate.
21
+ export const DESKTOP_GATE_PREFIXES = ['apps/desktop/', 'src/', 'vendor/', 'LICENSES/'];
22
+ export const DESKTOP_GATE_FILES = ['README.md', 'NOTICE.md', ...PACKAGE_MANIFESTS];
23
+ // Desktop packaging/postinstall scripts; `.test` companions ride along.
24
+ export const DESKTOP_GATE_SCRIPT_BASES = [
25
+ 'scripts/prune-embedding-runtime',
26
+ 'scripts/native-binary-arch',
27
+ 'scripts/native-tool-download',
28
+ 'scripts/runtime-dependency-cache-key',
29
+ ];
30
+
31
+ // Prefixes whose changes require the runtime gate (the release-critical lane
32
+ // plus the tool-contract suites the gate also executes).
33
+ export const RUNTIME_GATE_PREFIXES = [
34
+ '.github/workflows/',
35
+ 'native/',
36
+ 'scripts/tool-contracts/',
37
+ 'src/runtime/agent/orchestrator/',
38
+ 'src/runtime/shared/',
39
+ ];
40
+
41
+ // Everything `npm run test:release-critical` executes
42
+ // (test:release-assets + smoke:patch + test:providers).
43
+ export const RELEASE_CRITICAL_SCRIPTS = [
44
+ 'scripts/verify-release-assets.mjs',
45
+ 'scripts/release-gate-test.mjs',
46
+ 'scripts/prepare-native-assets.mjs',
47
+ 'scripts/prepare-native-assets-test.mjs',
48
+ 'scripts/generate-voice-runtime-manifest.mjs',
49
+ 'scripts/generate-voice-runtime-manifest.test.mjs',
50
+ 'scripts/apply-patch-edit-smoke.mjs',
51
+ 'scripts/provider-contract-test.mjs',
52
+ 'scripts/provider-stream-outcome-test.mjs',
53
+ 'scripts/cursor-provider-test.mjs',
54
+ ];
55
+
56
+ // Directory-shaped suites the critical lane executes (test:providers runs
57
+ // scripts/provider-toolcall/*.test.mjs): deploy consumes these as git
58
+ // pathspecs, the gate regex as path prefixes.
59
+ export const RELEASE_CRITICAL_SUITE_DIRS = ['scripts/provider-toolcall'];
60
+
61
+ // Gate-only suite files the runtime job executes beyond the critical lane
62
+ // (test:compact); editing one must re-run the gate that executes it.
63
+ export const RUNTIME_GATE_SUITE_FILES = ['scripts/suite-compact-test.mjs'];
64
+
65
+ // deploy.yml plan: paths whose change since the published release tag marks
66
+ // the critical lane as unverified.
67
+ export const RELEASE_CRITICAL_PATHS = [
68
+ 'native',
69
+ 'src/runtime/agent/orchestrator',
70
+ 'src/runtime/shared',
71
+ ...RELEASE_CRITICAL_SCRIPTS,
72
+ ...RELEASE_CRITICAL_SUITE_DIRS,
73
+ ...PACKAGE_MANIFESTS,
74
+ ];
75
+
76
+ const escapeRegex = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
77
+
78
+ export function desktopGateRegex() {
79
+ return `^(${[
80
+ ...DESKTOP_GATE_PREFIXES.map(escapeRegex),
81
+ ...DESKTOP_GATE_FILES.map((file) => `${escapeRegex(file)}$`),
82
+ ...DESKTOP_GATE_SCRIPT_BASES.map((base) => `${escapeRegex(base)}(\\.test)?\\.mjs$`),
83
+ ...GATE_SELECTION_SOURCES.map((file) => `${escapeRegex(file)}$`),
84
+ ].join('|')})`;
85
+ }
86
+
87
+ export function runtimeGateRegex() {
88
+ return `^(${[
89
+ ...RUNTIME_GATE_PREFIXES.map(escapeRegex),
90
+ ...RELEASE_CRITICAL_SCRIPTS.map((file) => `${escapeRegex(file)}$`),
91
+ ...RELEASE_CRITICAL_SUITE_DIRS.map((dir) => `${escapeRegex(dir)}/`),
92
+ ...RUNTIME_GATE_SUITE_FILES.map((file) => `${escapeRegex(file)}$`),
93
+ ...DESKTOP_GATE_SCRIPT_BASES.map((base) => `${escapeRegex(base)}(\\.test)?\\.mjs$`),
94
+ ...PACKAGE_MANIFESTS.map((file) => `${escapeRegex(file)}$`),
95
+ ...GATE_SELECTION_SOURCES.map((file) => `${escapeRegex(file)}$`),
96
+ ].join('|')})`;
97
+ }
98
+
99
+ const mode = process.argv[2];
100
+ if (mode) {
101
+ if (mode === 'desktop-regex') process.stdout.write(`${desktopGateRegex()}\n`);
102
+ else if (mode === 'runtime-regex') process.stdout.write(`${runtimeGateRegex()}\n`);
103
+ else if (mode === 'critical-paths') process.stdout.write(`${RELEASE_CRITICAL_PATHS.join('\n')}\n`);
104
+ else {
105
+ process.stderr.write(`unknown mode: ${mode} (expected desktop-regex|runtime-regex|critical-paths)\n`);
106
+ process.exit(1);
107
+ }
108
+ }
@@ -9,7 +9,7 @@
9
9
 
10
10
  set -euo pipefail
11
11
 
12
- TAG="${TAG:-runtime-v0.4.0}"
12
+ TAG="${TAG:-runtime-v0.4.1}"
13
13
  OS="${OS:-$(uname -s | tr '[:upper:]' '[:lower:]')}"
14
14
  ARCH="${ARCH:-$(uname -m | sed 's/x86_64/x64/')}"
15
15
  PG_VER="16.4"
@@ -76,7 +76,8 @@ echo "==> ldd vector.so (under env -i):"
76
76
  "${RUN_AS[@]}" env -i HOME="$WORK/fresh" PATH=/usr/bin:/bin "$PG_BIN/psql" -h 127.0.0.1 -p "$PORT" -U postgres -d postgres -c "CREATE EXTENSION vector;" > /dev/null
77
77
  EXTV="$("${RUN_AS[@]}" env -i HOME="$WORK/fresh" PATH=/usr/bin:/bin "$PG_BIN/psql" -h 127.0.0.1 -p "$PORT" -U postgres -d postgres -tAc "SELECT extversion FROM pg_extension WHERE extname='vector';")"
78
78
  [[ "$EXTV" == "$PGVECTOR_VER" ]] || { echo "FAIL: extversion=$EXTV"; exit 1; }
79
- echo " PASS: fresh-extract boot + vector extension"
79
+ "${RUN_AS[@]}" env -i HOME="$WORK/fresh" PATH=/usr/bin:/bin "$PG_BIN/psql" -h 127.0.0.1 -p "$PORT" -U postgres -d postgres -c "CREATE EXTENSION pg_trgm;" > /dev/null
80
+ echo " PASS: fresh-extract boot + vector + pg_trgm extensions"
80
81
 
81
82
  echo "==> Test 5: same tarball extracted twice → second initdb refuses (data-dir already initialized)"
82
83
  mkdir -p "$WORK/twice"
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ // Weekly opt-out sweep: run every test:*/smoke:* npm script in the repository
3
+ // so no locally-registered suite can rot silently (docs/testing.md, "A
4
+ // contract suite runs in CI or it drifts"). New scripts join automatically;
5
+ // exclusions are explicit, reasoned, and fail closed when they go stale.
6
+ import { readFileSync, writeFileSync } from 'node:fs';
7
+ import { join } from 'node:path';
8
+ import { pathToFileURL } from 'node:url';
9
+ import { spawnSync } from 'node:child_process';
10
+
11
+ export const WORKSPACES = [
12
+ {
13
+ dir: '.',
14
+ exclusions: {
15
+ 'smoke:all': 'aggregate; its components run individually',
16
+ 'smoke:loop': 'long-running local endurance harness',
17
+ 'smoke:loop:final': 'endurance-harness gate, needs hours of loop data',
18
+ 'smoke:loop:report': 'report reader, not a suite',
19
+ 'test:release-critical': 'aggregate; the release gate owns it',
20
+ 'test:quick': 'aggregate; its components run individually',
21
+ 'test:office:live': 'drives real Office COM on a desktop machine',
22
+ 'test:embedding-runtime:warmup': 'downloads the embedding runtime',
23
+ 'test:spec-advisory': 'advisory by design (MIXDOG_TEST_ADVISORY)',
24
+ },
25
+ },
26
+ {
27
+ dir: 'apps/desktop',
28
+ exclusions: {
29
+ 'test:renderer:full': 'aggregate; its components run individually',
30
+ 'test:fast-direct': 'dev-only deploy tool; real deploys are its verification',
31
+ 'test:office-approval': 'runs through the root test:office chain',
32
+ 'test:spec-advisory': 'advisory by design (MIXDOG_TEST_ADVISORY)',
33
+ 'test:browser-host:integration': 'live desktop integration harness',
34
+ 'test:browser-profile-import:integration': 'live desktop integration harness',
35
+ 'test:computer-host:integration': 'live desktop integration harness',
36
+ 'test:computer-host:scenarios': 'live desktop scenario harness',
37
+ 'test:computer-host:repeats': 'live desktop scenario harness',
38
+ },
39
+ },
40
+ ];
41
+
42
+ export function selectSuiteScripts(scripts, exclusions) {
43
+ const names = Object.keys(scripts).filter((name) => /^(test|smoke)(:|$)/.test(name));
44
+ const stale = Object.keys(exclusions).filter((name) => !names.includes(name));
45
+ if (stale.length) {
46
+ throw new Error(`stale exclusions (script no longer exists): ${stale.join(', ')}`);
47
+ }
48
+ return names.filter((name) => !(name in exclusions));
49
+ }
50
+
51
+ function runSweep() {
52
+ const failures = [];
53
+ const reportLines = [];
54
+ for (const ws of WORKSPACES) {
55
+ const pkg = JSON.parse(readFileSync(join(ws.dir, 'package.json'), 'utf8'));
56
+ const names = selectSuiteScripts(pkg.scripts || {}, ws.exclusions);
57
+ for (const name of names) {
58
+ const label = ws.dir === '.' ? name : `${ws.dir} ${name}`;
59
+ const started = Date.now();
60
+ const args = ['run', name, ...(ws.dir === '.' ? [] : ['--prefix', ws.dir])];
61
+ const child = spawnSync(process.platform === 'win32' ? 'npm.cmd' : 'npm', args, {
62
+ encoding: 'utf8',
63
+ shell: process.platform === 'win32',
64
+ maxBuffer: 64 * 1024 * 1024,
65
+ });
66
+ const seconds = ((Date.now() - started) / 1000).toFixed(1);
67
+ if (child.status === 0) {
68
+ reportLines.push(`- ${label}: OK (${seconds}s)`);
69
+ console.log(`${label}: OK (${seconds}s)`);
70
+ } else {
71
+ const tail = `${child.stdout || ''}\n${child.stderr || ''}`
72
+ .trim().split('\n').slice(-25).join('\n');
73
+ failures.push(`- ${label}: FAILED (${seconds}s)\n\n\`\`\`\n${tail}\n\`\`\``);
74
+ reportLines.push(`- ${label}: FAILED (${seconds}s)`);
75
+ console.error(`${label}: FAILED (${seconds}s)\n${tail}`);
76
+ }
77
+ }
78
+ }
79
+ console.log(`\n${reportLines.join('\n')}`);
80
+ if (failures.length > 0) {
81
+ const runUrl = process.env.GITHUB_RUN_ID
82
+ ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`
83
+ : '(local run)';
84
+ const report = [
85
+ '# Weekly suite health sweep failed',
86
+ '',
87
+ `Checked: ${new Date().toISOString()}`,
88
+ `Workflow run: ${runUrl}`,
89
+ '',
90
+ ...reportLines,
91
+ '',
92
+ ...failures,
93
+ '',
94
+ ].join('\n');
95
+ writeFileSync('suite-health-report.md', report);
96
+ process.exitCode = 1;
97
+ }
98
+ }
99
+
100
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
101
+ runSweep();
102
+ }
@@ -18,7 +18,7 @@ description: Use this skill only to inspect or modify a Mixdog user's persisted
18
18
  - 프로젝트 config: `<cwd>/.mixdog/hooks.json`
19
19
  - TUI 명령 목록: `src/tui/app/slash-commands.mjs`
20
20
  - TUI 설정 허브: `/setting` (별칭 `/settings`, `/config`) → `src/tui/app/settings-picker.mjs`
21
- - Desktop 설정: `Ctrl+,` → General / Context / Output style / Providers / Git / Skills / MCP / Plugins / Hooks / Connection / System / Shortcuts / About
21
+ - Desktop 설정: `Ctrl+,` → General / Context / Output style / Providers / Git / Skills / MCP / Plugins / Connection / System / Shortcuts / About
22
22
  - Desktop rail: **Projects / Workflows / Schedules / Webhooks / Utilities**
23
23
 
24
24
  사용자 경로와 지원 여부는 **현재 Desktop 구현을 최신 기준**으로 판정한다. TUI는 Desktop에 없는 고급 경로를 보완할 때만 사용하며, 저장만 왕복되고 실제 소비되지 않는 key는 사용자 옵션으로 설명하지 않는다.
@@ -219,7 +219,7 @@ API 키·토큰·OAuth 자격은 config에 쓰지 않는다.
219
219
 
220
220
  1. **확인**: `/setting → Auto-compact`, Desktop **Settings → Context**, 디스크 `agent.compaction`.
221
221
  2. **변경**: Auto-compact toggle → `setCompactionSettings({ auto })`.
222
- 3. **고정 계약**: Compact type`Fast-track (fixed)`이며 UI 변경 불가. memory recap이 꺼져도 recall-fasttrack은 유지된다.
222
+ 3. **고정 계약**: 모든 session하나의 fresh-context Compact를 사용한다. Main은 Memory handoff, Agent는 session-local handoff를 사용하며 type 선택 UI는 없다.
223
223
 
224
224
  ### Memory / Recap / Core Memory
225
225
 
@@ -260,7 +260,7 @@ TUI·Desktop interval 편집 UI는 없다.
260
260
 
261
261
  ---
262
262
 
263
- ## 4. MCP·Skills·Plugins·Hooks
263
+ ## 4. MCP·Skills·Plugins·Hooks(내부)
264
264
 
265
265
  ### MCP 추가
266
266
 
@@ -319,14 +319,13 @@ UI 생성 액션은 없다.
319
319
 
320
320
  Plugin toggle은 해당 Plugin의 Skills와 MCP를 전역으로 함께 활성화/비활성화한다. 개별 MCP와 Skill은 각 화면에서도 관리할 수 있다.
321
321
 
322
- ### Hooks
322
+ ### Hooks (사용자 설정 UI 없음)
323
323
 
324
- 1. **확인**: `/hooks` 또는 Desktop **Settings Hooks**, `hooksStatus()`.
325
- 2. **UI 범위**: 기존 rule의 Enable/Disable만 지원한다. UI에서 add/delete/edit은 하지 않는다.
326
- 3. **추가·수정·삭제**: hook config 파일을 편집하거나 runtime `addHookRule()` / `deleteHookRule()`을 사용한다.
327
- 4. **검색 경로**: `MIXDOG_HOOKS_FILE` 프로젝트 `.mixdog/hooks.json`·`.mixdog/hooks/hooks.json` 글로벌 `<mixdogData>/hooks.json`·`hooks/hooks.json` plugin hooks.
328
- 5. **형식**: 표준 `{ "hooks": { "<Event>": [{ "matcher": "...", "hooks": [...] }] } }`; 레거시 before-tool 배열도 읽는다.
329
- 6. **검증**: mtime 기반 자동 reload 후 Hooks 목록과 대상 event 발동을 확인한다.
324
+ 1. **범위**: hook은 plugin·내부 연동 전용이다. Desktop 설정 화면과 `/hooks` 슬래시 명령은 제공하지 않으므로 사용자 옵션으로 안내하지 않는다.
325
+ 2. **구성**: hook config 파일을 직접 편집하거나 runtime `addHookRule()` / `setHookRuleEnabled()` / `deleteHookRule()`을 사용한다.
326
+ 3. **검색 경로**: `MIXDOG_HOOKS_FILE` 프로젝트 `.mixdog/hooks.json`·`.mixdog/hooks/hooks.json` → 글로벌 `<mixdogData>/hooks.json`·`hooks/hooks.json` → plugin hooks.
327
+ 4. **형식**: 표준 `{ "hooks": { "<Event>": [{ "matcher": "...", "hooks": [...] }] } }`; 레거시 before-tool 배열도 읽는다.
328
+ 5. **검증**: mtime 기반 자동 reload `/doctor`의 hooks 행과 대상 event 발동을 확인한다.
330
329
 
331
330
  ---
332
331
 
@@ -415,7 +414,7 @@ Desktop과 현재 runtime에서 소비되지 않는 아래 key는 사용자 옵
415
414
  | `channels.webhook.ngrokDomain`, `channels.webhook.respectQuiet` | 제거; endpoint URL은 Desktop Webhooks가 발급 |
416
415
  | `agent.outputStyle` | 제거 (이관 없음; 루트 `outputStyle`만 유효) |
417
416
 
418
- 다음 항목은 레거시처럼 보여도 현행이므로 유지한다: 루트 `outputStyle`, `agent.shell`, `agent.modules`, compaction의 `type/compactType`과 recall tuning fields.
417
+ 다음 항목은 레거시처럼 보여도 현행이므로 유지한다: 루트 `outputStyle`, `agent.shell`, `agent.modules`, compaction의 `auto`, `summaryModel`, `timeoutMs`, `memoryTimeoutMs`, buffer/target fields.
419
418
 
420
419
  ---
421
420
 
@@ -23,22 +23,22 @@ import { resolveAgentSessionPermission } from '../internal-agents.mjs';
23
23
  import { loadConfig } from '../config.mjs';
24
24
  import { AGENT_OWNER } from '../agent-owner.mjs';
25
25
 
26
- import {
27
- COMPACT_TYPE_SEMANTIC,
28
- normalizeCompactType,
29
- } from '../session/compact.mjs';
30
-
31
26
  function normalizeAgentCompactionConfig(value = {}) {
32
27
  const raw = value && typeof value === 'object' ? value : {};
33
- const compactType = normalizeCompactType(
34
- raw.compactType ?? raw.compact_type ?? raw.type,
35
- COMPACT_TYPE_SEMANTIC,
36
- );
28
+ const next = { ...raw };
29
+ if (!next.summaryModel && raw.semanticModel) next.summaryModel = raw.semanticModel;
30
+ if (!next.memoryTimeoutMs && raw.recallMemoryTimeoutMs) next.memoryTimeoutMs = raw.recallMemoryTimeoutMs;
31
+ for (const key of [
32
+ 'type', 'compactType', 'compact_type', 'semantic', 'semanticModel', 'prune', 'tailTurns',
33
+ 'recallMemoryTimeoutMs', 'recallIngestLimit', 'recallChunkLimit', 'recallLimit',
34
+ 'recallCycle1BatchSize', 'recallRowsPerSession', 'recallWindowSize',
35
+ 'recallConcurrency', 'recallCycle1DeadlineMs',
36
+ ]) {
37
+ delete next[key];
38
+ }
37
39
  return {
38
- ...raw,
40
+ ...next,
39
41
  auto: raw.auto !== false && raw.enabled !== false,
40
- type: compactType,
41
- compactType,
42
42
  };
43
43
  }
44
44