@cortexkit/opencode-magic-context 0.42.3 → 0.42.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 (134) hide show
  1. package/README.md +3 -1
  2. package/dist/{announcement-3c1vertn.js → announcement-8mgn61fw.js} +1 -1
  3. package/dist/{conflict-warning-hook-aedp084d.js → conflict-warning-hook-jyj54gbe.js} +4 -4
  4. package/dist/{derive-budgets-s2pgnnm4.js → derive-budgets-v1fkhjjr.js} +2 -2
  5. package/dist/features/magic-context/context-authority.d.ts +13 -0
  6. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  7. package/dist/features/magic-context/dreamer/classify.d.ts +3 -1
  8. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  9. package/dist/features/magic-context/dreamer/curate-category-rotation.d.ts +26 -0
  10. package/dist/features/magic-context/dreamer/curate-category-rotation.d.ts.map +1 -0
  11. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts +7 -5
  12. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/task-executor.d.ts +6 -2
  14. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  15. package/dist/features/magic-context/dreamer/task-gates.d.ts +1 -0
  16. package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
  17. package/dist/features/magic-context/dreamer/task-prompts.d.ts +3 -0
  18. package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
  19. package/dist/features/magic-context/dreamer/task-registry.d.ts +9 -0
  20. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  21. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +5 -1
  22. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  23. package/dist/features/magic-context/memory/embedding-local.d.ts +11 -0
  24. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  25. package/dist/features/magic-context/mural/compress-cues.d.ts +3 -1
  26. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  27. package/dist/features/magic-context/transform-decision-log.d.ts +4 -0
  28. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/apply-operations.d.ts +4 -1
  30. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/caveman-cleanup.d.ts +4 -0
  32. package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/compartment-runner-historian.d.ts +5 -2
  34. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +2 -2
  36. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/compartment-runner-types.d.ts +61 -2
  38. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/compartment-runner.d.ts +2 -2
  40. package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
  41. package/dist/hooks/magic-context/dropped-token-estimate.d.ts +20 -0
  42. package/dist/hooks/magic-context/dropped-token-estimate.d.ts.map +1 -0
  43. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +2 -0
  44. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  45. package/dist/hooks/magic-context/hook.d.ts +2 -2
  46. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  47. package/dist/hooks/magic-context/module-transport.d.ts +4 -1
  48. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  49. package/dist/hooks/magic-context/rust-mode-transform.d.ts +2 -0
  50. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  51. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  52. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -0
  53. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  54. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +8 -0
  55. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  56. package/dist/hooks/magic-context/transform.d.ts +21 -0
  57. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  58. package/dist/{index-sf6x1ga9.js → index-1ar7b3e9.js} +3 -3
  59. package/dist/{index-wde5446v.js → index-3wbd8sdq.js} +225 -67
  60. package/dist/{index-3fe78beq.js → index-4ftb5hcq.js} +9 -1
  61. package/dist/{index-may8skc8.js → index-4wwr6cz0.js} +18 -1
  62. package/dist/{index-ecz14qke.js → index-d8mgqezq.js} +2 -2
  63. package/dist/{index-xdtge3y2.js → index-f9gem5cr.js} +2 -2
  64. package/dist/{index-z8552w7e.js → index-jkrqhc7y.js} +1 -1
  65. package/dist/{index-3wzdwt6p.js → index-ntbmt6rq.js} +1 -1
  66. package/dist/{index-gynz8qdc.js → index-p474rw9p.js} +3 -3
  67. package/dist/{index-dkv2dn46.js → index-qp20p2py.js} +1 -1
  68. package/dist/index.d.ts +4 -1
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +1625 -148
  71. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  72. package/dist/plugin/rpc-handlers.d.ts +18 -0
  73. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  74. package/dist/plugin/rust-tool-backends.d.ts +3 -1
  75. package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
  76. package/dist/{recomp-orchestrator-447vycpt.js → recomp-orchestrator-k20sfpm2.js} +6 -6
  77. package/dist/{safe-notification-target-q9z81zt3.js → safe-notification-target-fepvcbsj.js} +1 -1
  78. package/dist/{send-session-notification-2mzgd3zf.js → send-session-notification-xnypkxpx.js} +3 -3
  79. package/dist/shared/harness.d.ts +2 -1
  80. package/dist/shared/harness.d.ts.map +1 -1
  81. package/dist/shared/model-suggestion-retry.d.ts +5 -1
  82. package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
  83. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  84. package/dist/shared/rpc-types.d.ts +13 -0
  85. package/dist/shared/rpc-types.d.ts.map +1 -1
  86. package/dist/shared/status-detail-text.d.ts.map +1 -1
  87. package/dist/shared/status-summary.d.ts.map +1 -1
  88. package/dist/shared/user-facing-codes.d.ts +10 -0
  89. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  90. package/dist/{storage-meta-session-fkmfhswa.js → storage-meta-session-x3j0q9qy.js} +3 -3
  91. package/dist/{task-config-hnv93r7p.js → task-config-cv8k9y8r.js} +1 -1
  92. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  93. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  94. package/dist/v2/fold/markers.d.ts +7 -0
  95. package/dist/v2/fold/markers.d.ts.map +1 -0
  96. package/dist/v2/fold/owner.d.ts +40 -0
  97. package/dist/v2/fold/owner.d.ts.map +1 -0
  98. package/dist/v2/fold/restore.d.ts +11 -0
  99. package/dist/v2/fold/restore.d.ts.map +1 -0
  100. package/dist/v2/hidden-completion.d.ts +20 -0
  101. package/dist/v2/hidden-completion.d.ts.map +1 -0
  102. package/dist/v2/hooks/channel2.d.ts +8 -0
  103. package/dist/v2/hooks/channel2.d.ts.map +1 -0
  104. package/dist/v2/hooks/context.d.ts +7 -0
  105. package/dist/v2/hooks/context.d.ts.map +1 -0
  106. package/dist/v2/hooks/dream-trigger.d.ts +19 -0
  107. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -0
  108. package/dist/v2/hooks/payload.d.ts +12 -0
  109. package/dist/v2/hooks/payload.d.ts.map +1 -0
  110. package/dist/v2/hooks/refusal.d.ts +7 -0
  111. package/dist/v2/hooks/refusal.d.ts.map +1 -0
  112. package/dist/v2/hooks/store.d.ts +6 -0
  113. package/dist/v2/hooks/store.d.ts.map +1 -0
  114. package/dist/v2/hooks/types.d.ts +90 -0
  115. package/dist/v2/hooks/types.d.ts.map +1 -0
  116. package/dist/v2/hooks/update-check.d.ts +10 -0
  117. package/dist/v2/hooks/update-check.d.ts.map +1 -0
  118. package/dist/v2/server.d.ts +3 -1
  119. package/dist/v2/server.d.ts.map +1 -1
  120. package/dist/v2/server.js +116641 -4
  121. package/dist/v2/store-reader.d.ts +2 -0
  122. package/dist/v2/store-reader.d.ts.map +1 -1
  123. package/index.js +1 -0
  124. package/package.json +5 -4
  125. package/src/features/magic-context/dreamer/task-registry.ts +29 -0
  126. package/src/shared/harness.ts +2 -1
  127. package/src/shared/model-suggestion-retry.ts +66 -14
  128. package/src/shared/prompt-surface-runtime.ts +5 -1
  129. package/src/shared/rpc-types.ts +13 -0
  130. package/src/shared/status-detail-text.test.ts +26 -0
  131. package/src/shared/status-detail-text.ts +11 -0
  132. package/src/shared/status-summary.ts +2 -0
  133. package/src/shared/user-facing-codes.test.ts +1 -1
  134. package/src/shared/user-facing-codes.ts +10 -0
@@ -58,6 +58,8 @@ export declare class V2StoreReader {
58
58
  idleRows(sessionID: string, after?: number): StoreRow<"idle">[];
59
59
  /** Include the completed checkpoint itself, matching the host history cut. */
60
60
  window(sessionID: string): StoreRow[];
61
+ /** Full retained source is needed to restore unarchived rows hidden by a host cut. */
62
+ history(sessionID: string): StoreRow[];
61
63
  private all;
62
64
  }
63
65
  //# sourceMappingURL=store-reader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store-reader.d.ts","sourceRoot":"","sources":["../../src/v2/store-reader.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,MAAM,EACf,GAAG,GAAE,MAAM,CAAC,UAAwB,GACrC,MAAM,CASR;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,SAAW,EAClB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACrC,MAAM,CAGR;AAGD,MAAM,MAAM,WAAW,GACjB,gBAAgB,GAChB,gBAAgB,GAChB,mBAAmB,GACnB,MAAM,GACN,WAAW,GACX,QAAQ,GACR,OAAO,GACP,OAAO,GACP,WAAW,GACX,YAAY,GACZ,MAAM,CAAC;AACb,MAAM,WAAW,WAAW;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAC1C,CAAC;IACF,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE;AACD,MAAM,WAAW,QAAS,SAAQ,WAAW;IACzC,OAAO,EAAE,WAAW,GAAG,QAAQ,GAAG,aAAa,CAAC;CACnD;AACD,MAAM,WAAW,cAAe,SAAQ,WAAW;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IACzD,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,CAAC,CAAC;IACR,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,CAAC,SAAS,MAAM,GAAG,QAAQ,GAAG,CAAC,SAAS,YAAY,GAAG,cAAc,GAAG,WAAW,CAAC;CAC7F;AAmBD,0GAA0G;AAC1G,qBAAa,aAAa;IACtB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAW;gBAClB,IAAI,EAAE,MAAM;IAGxB,KAAK,IAAI,IAAI;IAIb,kFAAkF;IAClF,IAAI,CACA,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,WAAW,CAAA;KAAO,GACrE;QAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE;IAoBnD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,GAAG,SAAS;IAQvE,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE;IAG3D,8EAA8E;IAC9E,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE;IAMrC,OAAO,CAAC,GAAG;CASd"}
1
+ {"version":3,"file":"store-reader.d.ts","sourceRoot":"","sources":["../../src/v2/store-reader.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,MAAM,EACf,GAAG,GAAE,MAAM,CAAC,UAAwB,GACrC,MAAM,CASR;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,SAAW,EAClB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACrC,MAAM,CAGR;AAGD,MAAM,MAAM,WAAW,GACjB,gBAAgB,GAChB,gBAAgB,GAChB,mBAAmB,GACnB,MAAM,GACN,WAAW,GACX,QAAQ,GACR,OAAO,GACP,OAAO,GACP,WAAW,GACX,YAAY,GACZ,MAAM,CAAC;AACb,MAAM,WAAW,WAAW;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAC1C,CAAC;IACF,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE;AACD,MAAM,WAAW,QAAS,SAAQ,WAAW;IACzC,OAAO,EAAE,WAAW,GAAG,QAAQ,GAAG,aAAa,CAAC;CACnD;AACD,MAAM,WAAW,cAAe,SAAQ,WAAW;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IACzD,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,CAAC,CAAC;IACR,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,CAAC,SAAS,MAAM,GAAG,QAAQ,GAAG,CAAC,SAAS,YAAY,GAAG,cAAc,GAAG,WAAW,CAAC;CAC7F;AAmBD,0GAA0G;AAC1G,qBAAa,aAAa;IACtB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAW;gBAClB,IAAI,EAAE,MAAM;IAGxB,KAAK,IAAI,IAAI;IAIb,kFAAkF;IAClF,IAAI,CACA,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,WAAW,CAAA;KAAO,GACrE;QAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE;IAoBnD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,GAAG,SAAS;IAQvE,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE;IAG3D,8EAA8E;IAC9E,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE;IAMrC,sFAAsF;IACtF,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE;IAGtC,OAAO,CAAC,GAAG;CASd"}
package/index.js ADDED
@@ -0,0 +1 @@
1
+ export { default } from "./dist/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.42.3",
3
+ "version": "0.42.5",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",
@@ -24,6 +24,7 @@
24
24
  },
25
25
  "files": [
26
26
  "dist",
27
+ "index.js",
27
28
  "src/tui",
28
29
  "src/tui-compiled",
29
30
  "src/shared",
@@ -34,16 +35,16 @@
34
35
  "README.md"
35
36
  ],
36
37
  "scripts": {
37
- "build": "tsc -p ../retina-local-fs/tsconfig.build.json && bun run build:tui && rm -f dist/index.js dist/transformers-web.js dist/transformers-node-wasm.js dist/*-*.js && bun build src/features/magic-context/memory/transformers-web-entry.ts --outfile dist/transformers-web.js --target browser --format esm --external onnxruntime-web && bun scripts/build-transformers-node-wasm.ts dist && bun build src/index.ts --outdir dist --target node --format esm --splitting --external @opencode-ai/plugin --external onnxruntime-node --external onnxruntime-web --external sharp --external bun:sqlite --external node:sqlite && bun run build:v2 && tsc --emitDeclarationOnly",
38
+ "build": "bun ../../scripts/check-bun.mjs && tsc -p ../retina-local-fs/tsconfig.build.json && bun run build:tui && rm -f dist/index.js dist/transformers-web.js dist/transformers-node-wasm.js dist/*-*.js && bun build src/features/magic-context/memory/transformers-web-entry.ts --outfile dist/transformers-web.js --target browser --format esm --external onnxruntime-web && bun scripts/build-transformers-node-wasm.ts dist && bun build src/index.ts --outdir dist --target node --format esm --splitting --external @opencode-ai/plugin --external onnxruntime-node --external onnxruntime-web --external sharp --external bun:sqlite --external node:sqlite && bun run build:v2 && tsc --emitDeclarationOnly",
38
39
  "build:v2": "bun build src/v2/server.ts --outfile dist/v2/server.js --target node --format esm --external @opencode/plugin && bun test src/v2/server.test.ts",
39
40
  "build:tui": "bun scripts/build-tui.ts",
40
41
  "check:tui-compiled": "bun run build:tui && git diff --exit-code -- src/tui-compiled && test -z \"$(git status --porcelain -- src/tui-compiled)\"",
41
42
  "check:transformers-node-wasm": "bun scripts/verify-transformers-node-wasm.ts",
42
43
  "typecheck": "tsc -p ../retina-local-fs/tsconfig.build.json && tsc --noEmit && tsc -p tsconfig.scripts.json",
43
- "test": "bun install --frozen-lockfile && bun test --parallel --timeout 30000",
44
+ "test": "bun ../../scripts/check-bun.mjs && bun install --frozen-lockfile && bun test --parallel --timeout 30000",
44
45
  "test:serial": "bun install --frozen-lockfile && bun test --timeout 30000",
45
46
  "test:parallel:probe": "bun scripts/verify-parallel-db-isolation.ts",
46
- "lint": "biome check .",
47
+ "lint": "bun ../../scripts/check-bun.mjs && biome check .",
47
48
  "lint:fix": "biome check --write .",
48
49
  "format": "biome format --write .",
49
50
  "format:check": "biome format .",
@@ -8,6 +8,8 @@
8
8
  * concurrently while memory-mutating tasks serialize. See lease.ts + the A+B spec.
9
9
  */
10
10
 
11
+ import type { CurateMemoryCategory } from "./curate-category-rotation";
12
+
11
13
  export const CANONICAL_DREAM_TASKS = [
12
14
  // map-memories runs BEFORE verify (it records the file mappings verify gates
13
15
  // on) and shares the memory lease, so it leads the canonical order.
@@ -27,12 +29,33 @@ export const CANONICAL_DREAM_TASKS = [
27
29
 
28
30
  export type DreamTaskName = (typeof CANONICAL_DREAM_TASKS)[number];
29
31
 
32
+ export const DREAM_TASK_CAPABILITIES: Record<DreamTaskName, { requiresTools: boolean }> = {
33
+ // A single manifest is not a tool-free task: mapping and verification need
34
+ // read-only tools to inspect backing code before they can change memory state.
35
+ "map-memories": { requiresTools: true },
36
+ verify: { requiresTools: true },
37
+ "verify-broad": { requiresTools: true },
38
+ curate: { requiresTools: true },
39
+ // mural/compress-cues.ts is a zero-tool transform; its child transport
40
+ // still needs substitution before the generate executor can dispatch it.
41
+ "compress-cues": { requiresTools: false },
42
+ "classify-memories": { requiresTools: false },
43
+ retrospective: { requiresTools: true },
44
+ "maintain-docs": { requiresTools: true },
45
+ "evaluate-smart-notes": { requiresTools: true },
46
+ "review-user-memories": { requiresTools: true },
47
+ "promote-primers": { requiresTools: true },
48
+ "refresh-primers": { requiresTools: true },
49
+ };
50
+
30
51
  /** Cheap, read-only work counts for one Dreamer task. */
31
52
  export interface DreamTaskBacklog {
32
53
  /** Items selected by the task's current backlog predicate. */
33
54
  pending: number;
34
55
  /** Total items in the task's candidate pool. */
35
56
  total: number;
57
+ /** Curate's one-category scope for this run/window. */
58
+ category?: CurateMemoryCategory;
36
59
  }
37
60
 
38
61
  /** Backlog counts keyed by canonical task name. */
@@ -47,6 +70,9 @@ export function formatDreamTaskBacklogs(
47
70
  .filter((task) => backlogs[task] !== undefined)
48
71
  .map((task) => {
49
72
  const backlog = backlogs[task];
73
+ if (task === "curate" && backlog?.category) {
74
+ return `- curate: ${backlog.category} (${backlog.pending})`;
75
+ }
50
76
  return `- ${task}: ${backlog?.pending ?? 0} pending / ${backlog?.total ?? 0} total`;
51
77
  })
52
78
  .join("\n");
@@ -58,6 +84,8 @@ export interface DreamTaskProgress {
58
84
  processed: number;
59
85
  total: number;
60
86
  startedAt: number;
87
+ /** Curate's one-category scope. */
88
+ category?: CurateMemoryCategory;
61
89
  /** Update/archive verdicts refused by host-side verification safety gates during the current run. */
62
90
  refused?: number;
63
91
  }
@@ -69,6 +97,7 @@ export interface DreamTaskRunBacklog {
69
97
  pendingAtEnd: number;
70
98
  totalAtEnd: number;
71
99
  processed: number;
100
+ category?: CurateMemoryCategory;
72
101
  }
73
102
 
74
103
  /** Use the decrease in the persisted backlog between the start and end snapshots as the per-run progress count, clamped to zero when the backlog does not decrease. */
@@ -13,13 +13,14 @@
13
13
  * happens:
14
14
  * - OpenCode plugin: relies on the default ("opencode") — no setHarness call
15
15
  * needed
16
+ * - OpenCode 2 plugin: calls `setHarness("opencode2")` before opening the database
16
17
  * - Pi-compatible plugin: resolves the host and calls `setHarness("pi" | "omp")` before opening the database
17
18
  *
18
19
  * NEVER read this from configuration or session state — it is a
19
20
  * boot-time constant per plugin instance. Cross-harness leakage is a
20
21
  * correctness bug, not a feature.
21
22
  */
22
- export type HarnessId = "opencode" | "pi" | "omp";
23
+ export type HarnessId = "opencode" | "opencode2" | "pi" | "omp";
23
24
 
24
25
  let currentHarness: HarnessId = "opencode";
25
26
  let harnessLocked = false;
@@ -6,7 +6,11 @@ import type { ModelInput } from "./model-resolution";
6
6
  import { sanitizeDiagnosticText } from "./redaction";
7
7
  import { parseProviderModel, toModelEntry } from "./resolve-fallbacks";
8
8
 
9
- type Client = ReturnType<typeof createOpencodeClient>;
9
+ type Client = ReturnType<typeof createOpencodeClient> | undefined;
10
+
11
+ export type PromptTransport = ((args: PromptArgs) => Promise<void>) & {
12
+ readonly childSessionId?: string;
13
+ };
10
14
 
11
15
  /** Max time to wait for the best-effort child-session abort HTTP call before
12
16
  * giving up on its response (the abort still proceeds server-side). Keeps a
@@ -50,6 +54,7 @@ export interface PromptAttemptInfo {
50
54
  }
51
55
 
52
56
  export interface PromptRetryOptions {
57
+ transport?: PromptTransport;
53
58
  timeoutMs?: number;
54
59
  /** External abort signal — cancels the in-flight LLM prompt immediately when aborted */
55
60
  signal?: AbortSignal;
@@ -200,6 +205,7 @@ async function promptWithTimeout(
200
205
  args: PromptArgs,
201
206
  timeoutMs: number,
202
207
  signal?: AbortSignal,
208
+ transport?: PromptTransport,
203
209
  ): Promise<void> {
204
210
  // Bail immediately if the caller's signal is already aborted (e.g.
205
211
  // lease loss before this attempt was scheduled). Per spec
@@ -218,23 +224,29 @@ async function promptWithTimeout(
218
224
  signal?.addEventListener("abort", onExternalAbort);
219
225
 
220
226
  try {
221
- await client.session.prompt({
222
- ...args,
223
- signal: controller.signal,
224
- } as Parameters<typeof client.session.prompt>[0]);
227
+ const request = { ...args, signal: controller.signal };
228
+ if (transport) await transport(request);
229
+ else {
230
+ if (!client) throw new Error("Hidden completion transport is unavailable");
231
+ await client.session.prompt(request as Parameters<typeof client.session.prompt>[0]);
232
+ }
225
233
  } catch (error) {
226
234
  if (signal?.aborted) {
227
235
  // External abort (e.g. dreamer lease loss): the child run loop is an
228
236
  // independent SERVER-SIDE fiber — cancelling our client fetch alone
229
237
  // leaves it looping the LLM forever (issue #154). Force-stop it.
230
- await abortChildRun(client, args.path.id);
238
+ if (!transport || transport.childSessionId) {
239
+ await abortChildRun(client, transport?.childSessionId ?? args.path.id);
240
+ }
231
241
  throw new Error("prompt aborted by external signal");
232
242
  }
233
243
  if (controller.signal.aborted) {
234
244
  // Our timeout fired. Same problem: abort the server-side run loop, not
235
245
  // just our fetch, or the child keeps re-calling the LLM past the
236
246
  // timeout (uncancellable by the user's ESC — issue #154).
237
- await abortChildRun(client, args.path.id);
247
+ if (!transport || transport.childSessionId) {
248
+ await abortChildRun(client, transport?.childSessionId ?? args.path.id);
249
+ }
238
250
  throw new Error(`prompt timed out after ${timeoutMs}ms`);
239
251
  }
240
252
  throw error;
@@ -251,6 +263,7 @@ async function promptWithTimeout(
251
263
  * a failure here must not mask the original timeout/abort error.
252
264
  */
253
265
  async function abortChildRun(client: Client, sessionId: string): Promise<void> {
266
+ if (!client) return;
254
267
  try {
255
268
  // Bound the abort call: it's best-effort cleanup, and if the abort
256
269
  // endpoint itself stalls (the runner is wedged) an unbounded await here
@@ -342,6 +355,7 @@ function throwWithPromptFailure(
342
355
  failedAttempts: FailedAttempt[],
343
356
  args: PromptArgs,
344
357
  timeoutMs: number,
358
+ transport?: PromptTransport,
345
359
  ): never {
346
360
  const error =
347
361
  legacyError instanceof Error ? legacyError : new Error(extractMessage(legacyError));
@@ -357,7 +371,7 @@ function throwWithPromptFailure(
357
371
  modelsTried: failedAttempts.map((failure) => failure.attempt.label),
358
372
  providerError,
359
373
  timeoutMs: failureClass === "provider_timeout" ? timeoutMs : null,
360
- childSessionId: args.path.id || null,
374
+ childSessionId: transport ? (transport.childSessionId ?? null) : args.path.id || null,
361
375
  });
362
376
  throw error;
363
377
  }
@@ -374,6 +388,7 @@ async function attemptOnce(
374
388
  signal: AbortSignal | undefined,
375
389
  callContext: string,
376
390
  label: string,
391
+ transport?: PromptTransport,
377
392
  ): Promise<void> {
378
393
  // Keep this snapshot separate from the object passed to the client. A
379
394
  // failed prompt facade may rewrite its request body before rejecting; the
@@ -381,7 +396,7 @@ async function attemptOnce(
381
396
  const originalBody = { ...args.body };
382
397
  const attemptArgs = copyPromptArgs(args, originalBody);
383
398
  try {
384
- await promptWithTimeout(client, attemptArgs, timeoutMs, signal);
399
+ await promptWithTimeout(client, attemptArgs, timeoutMs, signal, transport);
385
400
  return;
386
401
  } catch (error) {
387
402
  // If non-retryable (abort, overflow, timeout), bubble up immediately.
@@ -411,6 +426,7 @@ async function attemptOnce(
411
426
  }),
412
427
  timeoutMs,
413
428
  signal,
429
+ transport,
414
430
  );
415
431
  }
416
432
  }
@@ -460,6 +476,7 @@ export async function promptSyncWithModelSuggestionRetry(
460
476
  options.signal,
461
477
  callContext,
462
478
  explicitPrimaryLabel,
479
+ options.transport,
463
480
  );
464
481
  return;
465
482
  } catch (error) {
@@ -496,7 +513,15 @@ export async function promptSyncWithModelSuggestionRetry(
496
513
  });
497
514
 
498
515
  try {
499
- await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label);
516
+ await attemptOnce(
517
+ client,
518
+ attemptArgs,
519
+ timeoutMs,
520
+ options.signal,
521
+ callContext,
522
+ label,
523
+ options.transport,
524
+ );
500
525
  log(
501
526
  `[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`,
502
527
  );
@@ -533,7 +558,15 @@ async function attemptAndValidate<TOutput, TValidated>(
533
558
  options: ValidatedPromptRetryOptions<TOutput, TValidated>,
534
559
  ): Promise<ValidatedPromptRetryResult<TOutput, TValidated>> {
535
560
  try {
536
- await attemptOnce(client, args, timeoutMs, signal, callContext, attempt.label);
561
+ await attemptOnce(
562
+ client,
563
+ args,
564
+ timeoutMs,
565
+ signal,
566
+ callContext,
567
+ attempt.label,
568
+ options.transport,
569
+ );
537
570
  } catch (error) {
538
571
  throw {
539
572
  error,
@@ -615,11 +648,23 @@ export async function promptSyncWithValidatedOutputRetry<TOutput, TValidated = T
615
648
  firstError = failure.error;
616
649
  lastError = failure.error;
617
650
  if (isNonRetryable(failure.error, options.signal)) {
618
- throwWithPromptFailure(failure.error, failedAttempts, args, timeoutMs);
651
+ throwWithPromptFailure(
652
+ failure.error,
653
+ failedAttempts,
654
+ args,
655
+ timeoutMs,
656
+ options.transport,
657
+ );
619
658
  }
620
659
 
621
660
  if (fallbacks.length === 0) {
622
- throwWithPromptFailure(failure.error, failedAttempts, args, timeoutMs);
661
+ throwWithPromptFailure(
662
+ failure.error,
663
+ failedAttempts,
664
+ args,
665
+ timeoutMs,
666
+ options.transport,
667
+ );
623
668
  }
624
669
 
625
670
  log(
@@ -669,7 +714,13 @@ export async function promptSyncWithValidatedOutputRetry<TOutput, TValidated = T
669
714
  failedAttempts.push(failure);
670
715
  lastError = failure.error;
671
716
  if (isNonRetryable(failure.error, options.signal)) {
672
- throwWithPromptFailure(failure.error, failedAttempts, args, timeoutMs);
717
+ throwWithPromptFailure(
718
+ failure.error,
719
+ failedAttempts,
720
+ args,
721
+ timeoutMs,
722
+ options.transport,
723
+ );
673
724
  }
674
725
 
675
726
  const remaining = fallbacks.length - i - 1;
@@ -689,5 +740,6 @@ export async function promptSyncWithValidatedOutputRetry<TOutput, TValidated = T
689
740
  failedAttempts,
690
741
  args,
691
742
  timeoutMs,
743
+ options.transport,
692
744
  );
693
745
  }
@@ -105,7 +105,11 @@ function resolveUserConfigDirectory(options: CreatePromptSurfaceRuntimeOptions):
105
105
  if (options.harness) {
106
106
  const legacy = resolveLegacyConfigSourcesForHarness(
107
107
  options.directory ?? process.cwd(),
108
- options.harness === "omp" ? "pi" : options.harness,
108
+ options.harness === "omp"
109
+ ? "pi"
110
+ : options.harness === "opencode2"
111
+ ? "opencode"
112
+ : options.harness,
109
113
  ).user.find((source) => existsSync(source.path));
110
114
  if (legacy) return dirname(legacy.path);
111
115
  }
@@ -149,6 +149,19 @@ export interface SidebarSnapshot {
149
149
  export interface StatusDetail extends SidebarSnapshot {
150
150
  /** True when Rust authority has rerouted host tool and historian paths to the module. */
151
151
  hostBackendsModuleSide?: boolean;
152
+ /** Host cursor compared with the module changefeed frontier. */
153
+ memoryMirror?: {
154
+ cursor: number;
155
+ cursorUpdatedAt: number | null;
156
+ cursorAgeMs: number | null;
157
+ liveRows: number;
158
+ feedHead: number | null;
159
+ pendingRows: number | null;
160
+ stalled: boolean;
161
+ code: "MC-M01" | null;
162
+ };
163
+ /** A durable host marker whose live module status no longer reports module ownership. */
164
+ memoryAuthorityMismatch?: boolean;
152
165
  /** User-owned model profile selected for this project, or null for the base config. */
153
166
  activeProfile: string | null;
154
167
  tagCounter: number;
@@ -157,6 +157,32 @@ describe("status detail text", () => {
157
157
  expect(summary).toContain("(MC-H01)");
158
158
  });
159
159
 
160
+ test("shows stalled mirror and authority mismatch codes in summary and diagnostics", () => {
161
+ const detail = {
162
+ ...STATUS_FIXTURE,
163
+ hostBackendsModuleSide: true,
164
+ memoryMirror: {
165
+ cursor: 3726,
166
+ cursorUpdatedAt: 1,
167
+ cursorAgeMs: 40_000,
168
+ liveRows: 275,
169
+ feedHead: 4850,
170
+ pendingRows: 1124,
171
+ stalled: true,
172
+ code: "MC-M01" as const,
173
+ },
174
+ memoryAuthorityMismatch: true,
175
+ };
176
+ const summary = formatStatusDetailMarkdown(detail);
177
+ const diagnostics = formatStatusDiagnosticsMarkdown(detail);
178
+
179
+ expect(summary).toContain("(MC-M01)");
180
+ expect(summary).toContain("(MC-M02)");
181
+ expect(diagnostics).toContain("cursor 3,726 / 4,850");
182
+ expect(diagnostics).toContain("stalled (MC-M01)");
183
+ expect(diagnostics).toContain("(MC-M02)");
184
+ });
185
+
160
186
  test("does not expose module routing in the summary", () => {
161
187
  const rustStatus = formatStatusDetailMarkdown({
162
188
  ...STATUS_FIXTURE,
@@ -67,6 +67,11 @@ export function formatStatusDiagnosticsMarkdown(detail: StatusDetail): string {
67
67
  `- **${formatCacheTtlDisplay({ value: detail.cacheTtl, source: detail.cacheTtlSource ?? "session", modelKey: detail.cacheTtlModelKey })}**; ${formatCacheLane(detail)}`,
68
68
  `- **Historian:** ${[historianState, ...historianDetails].join("; ")}`,
69
69
  ...(detail.hostBackendsModuleSide ? [`- ${RUST_MODE_HOST_PATHS_LINE}`] : []),
70
+ ...(detail.memoryMirror
71
+ ? [
72
+ `- **Memory mirror:** cursor ${formatCount(detail.memoryMirror.cursor)} / ${detail.memoryMirror.feedHead === null ? "unknown" : formatCount(detail.memoryMirror.feedHead)}; ${formatCount(detail.memoryMirror.liveRows)} live rows; ${detail.memoryMirror.stalled ? `stalled (${detail.memoryMirror.code})` : "advancing or caught up"}`,
73
+ ]
74
+ : []),
70
75
  `- **Memory:** ${formatCount(detail.memoryCount)} active; ${formatCount(detail.memoryBlockCount)} injected`,
71
76
  `- **Tags:** ${formatCount(detail.activeTags)} active, ${formatCount(detail.droppedTags)} dropped; ${formatCount(detail.pendingOpsCount)} pending drops`,
72
77
  `- **Execute threshold:** ${detail.executeThreshold.toFixed(1)}%${detail.executeThresholdClamped ? " (clamped)" : ""}`,
@@ -80,6 +85,12 @@ export function formatStatusDiagnosticsMarkdown(detail: StatusDetail): string {
80
85
  if (detail.lastTransformError) {
81
86
  lines.push(`- **Warning:** ${renderUserFacingFailure("transform_update_failed")}`);
82
87
  }
88
+ if (detail.memoryMirror?.stalled) {
89
+ lines.push(`- **Warning:** ${renderUserFacingFailure("memory_mirror_stalled")}`);
90
+ }
91
+ if (detail.memoryAuthorityMismatch) {
92
+ lines.push(`- **Warning:** ${renderUserFacingFailure("memory_authority_mismatch")}`);
93
+ }
83
94
 
84
95
  return lines.join("\n");
85
96
  }
@@ -49,6 +49,8 @@ export function statusSummaryFromDetail(detail: StatusDetail): UserStatusSummary
49
49
  if ((detail.loggerDiagnostics?.swallowedWriteCount ?? 0) > 0) {
50
50
  warnings.push("status_log_unavailable");
51
51
  }
52
+ if (detail.memoryMirror?.stalled) warnings.push("memory_mirror_stalled");
53
+ if (detail.memoryAuthorityMismatch) warnings.push("memory_authority_mismatch");
52
54
 
53
55
  return {
54
56
  inputTokens: detail.inputTokens,
@@ -43,7 +43,7 @@ describe("user-facing failure codes", () => {
43
43
  const entries = Object.values(USER_FACING_FAILURES);
44
44
  expect(new Set(entries.map((entry) => entry.code)).size).toBe(entries.length);
45
45
  for (const [key, entry] of Object.entries(USER_FACING_FAILURES)) {
46
- expect(entry.code).toMatch(/^MC-[CHDERS]\d{2}$/);
46
+ expect(entry.code).toMatch(/^MC-[CHDERSM]\d{2}$/);
47
47
  expect(entry.sentence).toEndWith(".");
48
48
  expect(entry.action).toEndWith(".");
49
49
  expect(renderUserFacingFailure(key as keyof typeof USER_FACING_FAILURES)).toBe(
@@ -177,6 +177,16 @@ export const USER_FACING_FAILURES = {
177
177
  sentence: "Magic Context is temporarily unavailable.",
178
178
  action: "Retry in a moment.",
179
179
  },
180
+ memory_mirror_stalled: {
181
+ code: "MC-M01",
182
+ sentence: "Memory synchronization stopped before the host mirror caught up.",
183
+ action: "Send another message to resume it, or run `ck doctor drain-authority`.",
184
+ },
185
+ memory_authority_mismatch: {
186
+ code: "MC-M02",
187
+ sentence: "Memory authority is inconsistent between the host and module.",
188
+ action: "Run `ck doctor drain-authority` before changing Rust mode.",
189
+ },
180
190
  } as const;
181
191
 
182
192
  export type UserFacingFailureKey = keyof typeof USER_FACING_FAILURES;