@retaw106/mmc-oc 2.0.0 → 2.1.1

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 (108) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/config/live-run-config.d.ts.map +1 -1
  3. package/dist/config-init.js +1 -1
  4. package/dist/{context-95zkksn3.js → context-cx3y8abt.js} +2602 -1594
  5. package/dist/features/magic-context/memory/types.d.ts +1 -0
  6. package/dist/features/magic-context/memory/types.d.ts.map +1 -1
  7. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  8. package/dist/features/magic-context/session-project-storage.d.ts +8 -2
  9. package/dist/features/magic-context/session-project-storage.d.ts.map +1 -1
  10. package/dist/features/magic-context/storage-meta-persisted.d.ts +12 -0
  11. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  12. package/dist/features/magic-context/storage-meta-session.d.ts +6 -0
  13. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  14. package/dist/features/magic-context/storage-tags.d.ts +2 -2
  15. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  16. package/dist/features/magic-context/transform-decision-log.d.ts +3 -1
  17. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  18. package/dist/hooks/magic-context/compartment-runner-types.d.ts +3 -5
  19. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  20. package/dist/hooks/magic-context/compartment-runner.d.ts +2 -1
  21. package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
  22. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  23. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
  24. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  26. package/dist/hooks/magic-context/historian-drain-gate.d.ts +11 -0
  27. package/dist/hooks/magic-context/historian-drain-gate.d.ts.map +1 -0
  28. package/dist/hooks/magic-context/lkg-replay-fit.d.ts +118 -0
  29. package/dist/hooks/magic-context/lkg-replay-fit.d.ts.map +1 -0
  30. package/dist/hooks/magic-context/lkg-replay.d.ts +2 -0
  31. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  32. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  34. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -28
  35. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  36. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  37. package/dist/{index-fg34g6a5.js → index-1j34a56j.js} +49 -8
  38. package/dist/{index-5pg0acf7.js → index-amycb7b1.js} +1 -1
  39. package/dist/{index-1mjhzqq7.js → index-dr0gepzw.js} +86 -23
  40. package/dist/{index-xt7y10x6.js → index-n0vnzz6h.js} +1 -1
  41. package/dist/{index-977gxfz0.js → index-ramz5kkm.js} +1 -1
  42. package/dist/{index-bdt9my9y.js → index-wtb9hzk6.js} +130 -50
  43. package/dist/index.js +1 -1
  44. package/dist/{message-time-backfill-zfernxbw.js → message-time-backfill-phrwp2fz.js} +1 -1
  45. package/dist/{read-session-chunk-hp464g13.js → read-session-chunk-82rkqa8j.js} +3 -3
  46. package/dist/{recomp-orchestrator-3qxeqwb9.js → recomp-orchestrator-vc5dkzy2.js} +6 -6
  47. package/dist/{send-session-notification-y29y9fsr.js → send-session-notification-rnc4nrsr.js} +3 -3
  48. package/dist/shared/harness.d.ts +1 -1
  49. package/dist/shared/harness.d.ts.map +1 -1
  50. package/dist/shared/historian-tool-expansions.d.ts +1 -1
  51. package/dist/shared/historian-tool-expansions.d.ts.map +1 -1
  52. package/dist/shared/historian-tool-template.d.ts +2 -2
  53. package/dist/shared/historian-tool-template.d.ts.map +1 -1
  54. package/dist/shared/model-resolution.d.ts +1 -1
  55. package/dist/shared/model-resolution.d.ts.map +1 -1
  56. package/dist/shared/sqlite.d.ts +14 -1
  57. package/dist/shared/sqlite.d.ts.map +1 -1
  58. package/dist/tools/ctx-expand/constants.d.ts +1 -1
  59. package/dist/tools/ctx-expand/constants.d.ts.map +1 -1
  60. package/dist/tools/ctx-expand/render.d.ts +3 -2
  61. package/dist/tools/ctx-expand/render.d.ts.map +1 -1
  62. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  63. package/dist/v2/fold/host-media.d.ts +4 -0
  64. package/dist/v2/fold/host-media.d.ts.map +1 -1
  65. package/dist/v2/fold/memory-cache.d.ts +70 -0
  66. package/dist/v2/fold/memory-cache.d.ts.map +1 -0
  67. package/dist/v2/fold/native-codec.d.ts +10 -0
  68. package/dist/v2/fold/native-codec.d.ts.map +1 -0
  69. package/dist/v2/fold/native-replay.d.ts +58 -0
  70. package/dist/v2/fold/native-replay.d.ts.map +1 -0
  71. package/dist/v2/fold/policy.d.ts +24 -0
  72. package/dist/v2/fold/policy.d.ts.map +1 -0
  73. package/dist/v2/hidden-child-record.d.ts +6 -0
  74. package/dist/v2/hidden-child-record.d.ts.map +1 -1
  75. package/dist/v2/hidden-completion.d.ts.map +1 -1
  76. package/dist/v2/hooks/context.d.ts.map +1 -1
  77. package/dist/v2/hooks/types.d.ts +6 -0
  78. package/dist/v2/hooks/types.d.ts.map +1 -1
  79. package/dist/v2/server.js +1819 -574
  80. package/dist/v2/store-reader.d.ts +16 -0
  81. package/dist/v2/store-reader.d.ts.map +1 -1
  82. package/dist/web/api.d.ts.map +1 -1
  83. package/dist/web/context-store.d.ts +2 -0
  84. package/dist/web/context-store.d.ts.map +1 -1
  85. package/dist/web/fixtures.d.ts +41 -0
  86. package/dist/web/fixtures.d.ts.map +1 -1
  87. package/dist/web/host-opencode.d.ts +9 -0
  88. package/dist/web/host-opencode.d.ts.map +1 -1
  89. package/dist/web/main.js +873 -64
  90. package/dist/web/memories.d.ts +18 -2
  91. package/dist/web/memories.d.ts.map +1 -1
  92. package/dist/web/ui/panel.css +3 -0
  93. package/dist/web/ui/panel.js +151 -80
  94. package/dist/web/views.d.ts +71 -9
  95. package/dist/web/views.d.ts.map +1 -1
  96. package/dist/{wrapup-orchestrator-wgb2nd19.js → wrapup-orchestrator-x9xamts2.js} +6 -6
  97. package/package.json +1 -1
  98. package/src/config/live-run-config.ts +28 -0
  99. package/src/shared/harness.ts +1 -1
  100. package/src/shared/historian-tool-defaults.json +6 -6
  101. package/src/shared/historian-tool-expansions.ts +65 -8
  102. package/src/shared/historian-tool-preview-defaults.json +13 -0
  103. package/src/shared/historian-tool-template.ts +48 -14
  104. package/src/shared/model-resolution.ts +1 -1
  105. package/src/shared/prompt-surface-a1-golden.md +2 -2
  106. package/src/shared/sqlite-acquisition-routing.test.ts +18 -0
  107. package/src/shared/sqlite.ts +100 -15
  108. package/src/shared/write-transaction-attribution.test.ts +2 -2
@@ -41,20 +41,51 @@ export declare function openContextFor(sources: PanelSources): OpenContextStoreR
41
41
  export declare function openOc2For(sources: PanelSources): OpenOc2HostResult;
42
42
  export declare function resolvePiRootFor(sources: PanelSources): string;
43
43
  export declare function listPiBranchGroups(sources: PanelSources): PiSessionBranchGroup[];
44
- export type DerivedKind = "historian" | "child" | null;
45
- export declare function classifyDerived(input: {
46
- title: string | null;
47
- parentId: string | null;
48
- }): DerivedKind;
49
- export interface PanelSession {
44
+ export type LatestMessageTimeQuality = "normal" | "no-messages" | "unreadable" | "partial-unreadable";
45
+ export interface LatestMessageTime {
46
+ quality: LatestMessageTimeQuality;
47
+ /**
48
+ * Latest user/assistant message creation time (epoch ms). A known LOWER
49
+ * bound only when partially unreadable (Q8); null otherwise.
50
+ */
51
+ value: number | null;
52
+ detail: string | null;
53
+ }
54
+ export type SessionRelationState = "root" | "child" | "orphan";
55
+ export type SessionRelationReason = null | "missing-parent" | "cross-project" | "duplicate" | "cycle" | "maintenance-parent-hidden";
56
+ export interface SessionRelation {
57
+ state: SessionRelationState;
58
+ reason: SessionRelationReason;
59
+ }
60
+ export type MaintenanceKind = "historian" | "maintainer-a" | "maintainer-b";
61
+ /**
62
+ * Maintenance classification by EXACT title equality against the standard
63
+ * hidden-child titles (`HIDDEN_CHILD_ROLE_TITLES` — the same persistent source
64
+ * `roleTitle` writes). Similar-but-not-exact titles are never classified.
65
+ */
66
+ export declare function classifyMaintenance(title: string | null): MaintenanceKind | null;
67
+ export interface PanelSessionNode {
50
68
  sessionId: string;
51
69
  harness: "opencode2" | "pi";
52
70
  title: string | null;
53
71
  hostTimeCreated: number | null;
54
72
  hostTimeUpdated: number | null;
55
- lastActivityAt: number | null;
73
+ latestMessageTime: LatestMessageTime;
74
+ /** Host parent id (OC2 `session_v2.parent_id`); always null for Pi (message-level relation). */
75
+ parentId: string | null;
76
+ relation: SessionRelation;
77
+ maintenance: MaintenanceKind | null;
78
+ /** Source provenance only — never a parent relation (plan 15: fork ≠ parent). */
79
+ forkSessionId: string | null;
80
+ /** The registration is the only identity fact guaranteed by this list. */
81
+ registered: true;
82
+ /** Host/session metadata only; never a health verdict. */
83
+ childIdentity: "root" | "child" | "unknown";
84
+ /** Persisted/default eligibility, not proof of current use or health. */
85
+ processingEligibility: "primary" | "reduced-subagent" | "unknown";
86
+ /** Children counted within THIS pruned response, not globally. */
87
+ childCount: number;
56
88
  compartmentCount: number;
57
- derived: DerivedKind;
58
89
  /** Present on Pi sessions only (D13): branch files, never merged. */
59
90
  piBranches?: Array<{
60
91
  fileName: string;
@@ -62,7 +93,23 @@ export interface PanelSession {
62
93
  headerTimestamp: string | null;
63
94
  }>;
64
95
  }
65
- export declare function listProjectSessionViews(sources: PanelSources, projectPath: string): PanelSession[];
96
+ export interface ProjectSessionTree {
97
+ projectPath: string;
98
+ includeMaintenance: boolean;
99
+ /** Raw registration rows (listProjectSessions) BEFORE maintenance pruning. */
100
+ registeredCount: number;
101
+ /** Maintenance nodes pruned from `sessions` this response (0 when includeMaintenance). */
102
+ maintenanceHiddenCount: number;
103
+ /**
104
+ * The project's full safe candidate set. The server does not sort by
105
+ * activity — the registration query's stable order is preserved; all
106
+ * tree-aware filtering/sorting/expanding is frontend work (plan 15 Q10).
107
+ */
108
+ sessions: PanelSessionNode[];
109
+ }
110
+ export declare function listProjectSessionViews(sources: PanelSources, projectPath: string, options?: {
111
+ includeMaintenance?: boolean;
112
+ }): ProjectSessionTree;
66
113
  export interface PanelMessageRow {
67
114
  /** Keyset cursor value: OC2 host seq, or Pi projected ordinal. */
68
115
  key: number;
@@ -70,6 +117,14 @@ export interface PanelMessageRow {
70
117
  role: string;
71
118
  timeCreated: number | null;
72
119
  parts: unknown[];
120
+ /** Separate coordinate spaces; null means this projection cannot prove one. */
121
+ coordinates: PanelMessageCoordinates;
122
+ }
123
+ export interface PanelMessageCoordinates {
124
+ hostSeq: number | null;
125
+ rawOrdinal: number | null;
126
+ /** All tag numbers attached to this raw row's content; null means unknown. */
127
+ tagNumbers: number[] | null;
73
128
  }
74
129
  export interface PanelMessagePage {
75
130
  source: "oc2-host" | "pi-jsonl";
@@ -95,13 +150,20 @@ export type PanelBoundary = {
95
150
  } | {
96
151
  state: "resolved";
97
152
  anchor: number;
153
+ coordinates: PanelBoundaryCoordinates;
98
154
  } | {
99
155
  state: "synth-resolved";
100
156
  anchor: number;
101
157
  aliasedTo: string;
158
+ coordinates: PanelBoundaryCoordinates;
102
159
  } | {
103
160
  state: "unresolved";
104
161
  };
162
+ export interface PanelBoundaryCoordinates {
163
+ hostSeq: number | null;
164
+ rawOrdinal: number | null;
165
+ tagNumbers: number[] | null;
166
+ }
105
167
  export type PanelCompartmentRenderTier = "full" | "decayed";
106
168
  export interface PanelCompartment {
107
169
  id: number;
@@ -1 +1 @@
1
- {"version":3,"file":"views.d.ts","sourceRoot":"","sources":["../../src/web/views.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"views.d.ts","sourceRoot":"","sources":["../../src/web/views.ts"],"names":[],"mappings":"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"}
@@ -21,11 +21,11 @@ import {
21
21
  getActiveCompartmentRun,
22
22
  markActiveCompartmentRunPublished,
23
23
  registerActiveCompartmentRun
24
- } from "./index-bdt9my9y.js";
25
- import"./index-fg34g6a5.js";
24
+ } from "./index-wtb9hzk6.js";
25
+ import"./index-1j34a56j.js";
26
26
  import"./index-x37vg474.js";
27
- import"./index-1mjhzqq7.js";
28
- import"./index-977gxfz0.js";
27
+ import"./index-dr0gepzw.js";
28
+ import"./index-ramz5kkm.js";
29
29
  import {
30
30
  pushNotification2
31
31
  } from "./index-jdxxq8cz.js";
@@ -33,11 +33,11 @@ import"./index-5cep2r9n.js";
33
33
  import"./index-53g38ggt.js";
34
34
  import {
35
35
  sendStatusNotification2
36
- } from "./index-5pg0acf7.js";
36
+ } from "./index-amycb7b1.js";
37
37
  import {
38
38
  setRecompStarting2,
39
39
  setRecompTerminal2
40
- } from "./index-xt7y10x6.js";
40
+ } from "./index-n0vnzz6h.js";
41
41
  import"./index-33gprt9g.js";
42
42
 
43
43
  // src/hooks/magic-context/wrapup-orchestrator.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retaw106/mmc-oc",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",
@@ -11,6 +11,14 @@ export function sampleLiveConfig<T extends MagicContextConfig>(boot: T, fresh: T
11
11
  const parts = path.split(".");
12
12
  let value: unknown = fresh;
13
13
  for (const part of parts) value = (value as Record<string, unknown> | undefined)?.[part];
14
+ if (value === undefined) {
15
+ // An unset live path must not create its parent objects. An empty `omp`
16
+ // block, for example, shadows the `pi` block it would otherwise fall back
17
+ // to, and the historian and dreamer lose their configured model. Only
18
+ // clear a leaf the boot config actually has, so removing a key live works.
19
+ removeLeaf(result, parts);
20
+ continue;
21
+ }
14
22
  let target = result;
15
23
  for (const part of parts.slice(0, -1)) {
16
24
  const child = target[part];
@@ -27,6 +35,26 @@ export function sampleLiveConfig<T extends MagicContextConfig>(boot: T, fresh: T
27
35
  return result as T;
28
36
  }
29
37
 
38
+ function removeLeaf(root: Record<string, unknown>, parts: string[]): void {
39
+ const parents = parts.slice(0, -1);
40
+ let node: Record<string, unknown> = root;
41
+ for (const part of parents) {
42
+ const child = node[part];
43
+ if (!child || typeof child !== "object" || Array.isArray(child)) return;
44
+ node = child as Record<string, unknown>;
45
+ }
46
+ const leaf = parts.at(-1);
47
+ if (leaf === undefined || !Object.hasOwn(node, leaf)) return;
48
+ // Copy the parent chain before deleting so the boot config object is never mutated.
49
+ let target = root;
50
+ for (const part of parents) {
51
+ const copy = { ...(target[part] as Record<string, unknown>) };
52
+ target[part] = copy;
53
+ target = copy;
54
+ }
55
+ delete target[leaf];
56
+ }
57
+
30
58
  export function changedLiveKeys(previous: MagicContextConfig, next: MagicContextConfig): string[] {
31
59
  const at = (config: MagicContextConfig, path: string): unknown =>
32
60
  path
@@ -20,7 +20,7 @@
20
20
  * boot-time constant per plugin instance. Cross-harness leakage is a
21
21
  * correctness bug, not a feature.
22
22
  */
23
- export type HarnessId = "opencode" | "opencode2" | "pi";
23
+ export type HarnessId = "opencode" | "opencode2" | "pi" | "omp";
24
24
 
25
25
  let currentHarness: HarnessId = "opencode";
26
26
  let harnessLocked = false;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "todowrite": "Todos (${input.todos.count}): ${input.todos.each(\"${status}: ${content}\")}",
3
3
  "question": "Asked user: ${input.questions[*].question.join(\" / \")} → ${output}",
4
- "task": "Task ${input.subagent_type}: ${input.prompt} → ${output.truncate(200)}",
5
- "ask": "Asked: ${input.question.truncate(250)} [options: ${input.options.join(\" / \")}] ${input.resolution} → ${output.truncate(300)}",
6
- "peer_send": "PM to ${input.agent}${input.agent_id}: ${input.message.truncate(400)}",
7
- "board": "Board ${input.verb}: ${input.ops.each(\"${op} ${item}${lane.title} ${state}${lane.status}${props.text} ${lane.items[*].text}\")}",
8
- "room": "Room ${input.action} ${input.room_id}: ${input.text.truncate(400)}",
9
- "work": "Work ${input.action} ${input.id}: ${input.prompt_file}${input.prompt.truncate(200)}${input.notes.truncate(200)} → ${output.truncate(160)}",
4
+ "task": "Task ${input.subagent_type}: ${input.prompt.truncate(600)} → ${output.truncate(200)}",
5
+ "ask": "Asked: ${input.question} [options: ${input.options.join(\" / \")}] ${input.text}${input.resolution} → ${output.truncate(300)}",
6
+ "peer_send": "PM ${input.recipient}: ${input.message}",
7
+ "board": "Board ${input.verb}${input.board_lane}: ${input.ops.each(\"${op} ${lane_label} ${item}${props.text}${lane.items} ${state}${props.state}${lane.status}${id}${title}\")}",
8
+ "room": "Room ${input.action} ${input.room_label}: ${input.room_detail}",
9
+ "work": "Work ${input.action} ${input.title}${input.id}: ${input.prompt.truncate(600)}${input.notes.truncate(600)} → ${output.truncate(160)}",
10
10
  "knowhow": "Looked up how-to: ${input.query}${input.id}",
11
11
  "mmc_note": "Note ${input.action} ${input.note_ids}: ${input.content} → ${output.truncate(160)}",
12
12
  "mmc_memory": "Memory ${input.action} ${input.category} ${input.ids}: ${input.content} → ${output.truncate(160)}"
@@ -1,18 +1,75 @@
1
1
  import defaults from "./historian-tool-defaults.json";
2
+ import previewDefaults from "./historian-tool-preview-defaults.json";
2
3
  import { renderToolTemplate, type ToolExpansionMap } from "./historian-tool-template";
3
4
 
4
5
  export { defaults as DEFAULT_TOOL_EXPANSIONS };
5
- export function expandToolPart(part: unknown, overrides?: ToolExpansionMap): string | null {
6
+
7
+ // Room actions, private-message addresses and board lanes have multiple input
8
+ // shapes. Derive readable labels only for built-ins; configured template overrides
9
+ // keep the unmodified tool input.
10
+ function builtinInput(tool: string, input: unknown): unknown {
11
+ if (!input || typeof input !== "object") return input;
12
+ const i = input as Record<string, unknown>;
13
+ if (tool === "peer_send") {
14
+ const external = i.external as Record<string, unknown> | undefined;
15
+ const recipient = i.reply_to_pmid
16
+ ? `reply to ${i.reply_to_pmid}`
17
+ : i.agent || i.agent_id
18
+ ? `to ${i.agent || i.agent_id}`
19
+ : external?.session_id || i.session_id
20
+ ? `to session ${external?.session_id || i.session_id}`
21
+ : "to unknown recipient";
22
+ return { ...i, recipient };
23
+ }
24
+ if (tool === "room") {
25
+ return {
26
+ ...i,
27
+ room_label: i.room_id || i.title,
28
+ room_detail:
29
+ i.action === "create" || i.action === "invite"
30
+ ? `invitees: ${renderToolTemplate("${input.invitees}", i)}`
31
+ : i.text,
32
+ };
33
+ }
34
+ if (tool === "board") {
35
+ return {
36
+ ...i,
37
+ board_lane: i.lane ? ` ${i.lane}` : "",
38
+ ops: Array.isArray(i.ops)
39
+ ? i.ops.map((op) =>
40
+ op && typeof op === "object"
41
+ ? {
42
+ ...op,
43
+ lane_label:
44
+ typeof op.lane === "string"
45
+ ? op.lane
46
+ : op.lane?.title || op.lane?.id,
47
+ }
48
+ : op,
49
+ )
50
+ : i.ops,
51
+ };
52
+ }
53
+ return input;
54
+ }
55
+
56
+ export function expandToolPart(
57
+ part: unknown,
58
+ overrides?: ToolExpansionMap,
59
+ legacyPreview = false,
60
+ ): string | null {
6
61
  if (!part || typeof part !== "object") return null;
7
62
  const p = part as Record<string, unknown>;
8
63
  if (p.type !== "tool" || typeof p.tool !== "string") return null;
9
- const template =
10
- overrides && Object.hasOwn(overrides, p.tool)
11
- ? overrides[p.tool]
12
- : Object.hasOwn(defaults, p.tool)
13
- ? defaults[p.tool as keyof typeof defaults]
14
- : undefined;
64
+ const builtinDefaults = legacyPreview ? previewDefaults : defaults;
65
+ const overridden = overrides && Object.hasOwn(overrides, p.tool);
66
+ const template = overridden
67
+ ? overrides[p.tool]
68
+ : Object.hasOwn(builtinDefaults, p.tool)
69
+ ? builtinDefaults[p.tool as keyof typeof defaults]
70
+ : undefined;
15
71
  if (typeof template !== "string") return null;
16
72
  const state = p.state as Record<string, unknown> | undefined;
17
- return renderToolTemplate(template, state?.input, state?.output ?? state?.error);
73
+ const input = overridden || legacyPreview ? state?.input : builtinInput(p.tool, state?.input);
74
+ return renderToolTemplate(template, input, state?.output ?? state?.error, legacyPreview);
18
75
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "todowrite": "Todos (${input.todos.count}): ${input.todos.each(\"${status}: ${content}\")}",
3
+ "question": "Asked user: ${input.questions[*].question.join(\" / \")} → ${output}",
4
+ "task": "Task ${input.subagent_type}: ${input.prompt} → ${output.truncate(200)}",
5
+ "ask": "Asked: ${input.question.truncate(250)} [options: ${input.options.join(\" / \")}] ${input.resolution} → ${output.truncate(300)}",
6
+ "peer_send": "PM to ${input.agent}${input.agent_id}: ${input.message.truncate(400)}",
7
+ "board": "Board ${input.verb}: ${input.ops.each(\"${op} ${item}${lane.title} ${state}${lane.status}${props.text} ${lane.items[*].text}\")}",
8
+ "room": "Room ${input.action} ${input.room_id}: ${input.text.truncate(400)}",
9
+ "work": "Work ${input.action} ${input.id}: ${input.prompt_file}${input.prompt.truncate(200)}${input.notes.truncate(200)} → ${output.truncate(160)}",
10
+ "knowhow": "Looked up how-to: ${input.query}${input.id}",
11
+ "mmc_note": "Note ${input.action} ${input.note_ids}: ${input.content} → ${output.truncate(160)}",
12
+ "mmc_memory": "Memory ${input.action} ${input.category} ${input.ids}: ${input.content} → ${output.truncate(160)}"
13
+ }
@@ -1,4 +1,4 @@
1
- /** A deliberately non-executable language for readable, bounded historian tool lines. */
1
+ /** A deliberately non-executable language for readable historian tool lines. */
2
2
  export type ToolExpansionMap = Record<string, string | false>;
3
3
  type Step = { field: string } | { index: number } | { project: string };
4
4
  type Expression = {
@@ -6,7 +6,7 @@ type Expression = {
6
6
  each?: Template;
7
7
  join?: string;
8
8
  count?: boolean;
9
- cap: number;
9
+ cap?: number;
10
10
  };
11
11
  type Template = Array<string | Expression>;
12
12
 
@@ -78,7 +78,7 @@ class Parser {
78
78
  if (this.source[this.pos] === "(") return this.error();
79
79
  } else break;
80
80
  }
81
- const expression: Expression = { steps, cap: 300 };
81
+ const expression: Expression = { steps };
82
82
  if (this.take(".each(")) {
83
83
  if (relative) return this.error();
84
84
  expression.each = parseTemplate(this.quoted(), true);
@@ -145,9 +145,24 @@ function compiled(source: string): Template | null {
145
145
  function oneLine(value: string): string {
146
146
  return value.replace(/[\r\n\u2028\u2029]+/g, " ");
147
147
  }
148
- function truncate(value: string, cap: number): string {
148
+ function truncate(value: string, cap?: number, legacyPreview = false): string {
149
149
  const chars = Array.from(oneLine(value));
150
- return chars.length > cap ? `${chars.slice(0, cap).join("")}…` : chars.join("");
150
+ if (cap === undefined || chars.length <= cap) return chars.join("");
151
+ if (legacyPreview) return `${chars.slice(0, cap).join("")}…`;
152
+ // Explicit caps stop after sentence-ending punctuation so a cut is not
153
+ // mistaken for an intact tool message. If no sentence fits, show only the marker.
154
+ let end = 0;
155
+ for (let i = 0; i < Math.min(cap, chars.length); i++) {
156
+ if (!".!?。!?".includes(chars[i])) continue;
157
+ let next = i + 1;
158
+ while (next < chars.length && "\"'”’)]".includes(chars[next])) next++;
159
+ if (
160
+ next <= cap &&
161
+ ("。!?".includes(chars[i]) || next === chars.length || /[ \t]/.test(chars[next]))
162
+ )
163
+ end = next;
164
+ }
165
+ return `${end ? `${chars.slice(0, end).join("")} ` : ""}[… ${chars.length - end} more characters]`;
151
166
  }
152
167
  function scalar(value: unknown): string {
153
168
  if (value === undefined) return "";
@@ -174,10 +189,11 @@ function field(value: unknown, key: string): unknown {
174
189
  ? (value as Record<string, unknown>)[key]
175
190
  : undefined;
176
191
  }
177
- function render(nodes: Template, root: unknown): string {
192
+ function render(nodes: Template, root: unknown, legacyPreview: boolean): string {
178
193
  return nodes
179
194
  .map((node) => {
180
195
  if (typeof node === "string") return node;
196
+ const cap = node.cap ?? (legacyPreview ? 300 : undefined);
181
197
  let value = root;
182
198
  let list = false;
183
199
  for (const step of node.steps) {
@@ -196,18 +212,31 @@ function render(nodes: Template, root: unknown): string {
196
212
  }
197
213
  }
198
214
  if (node.count)
199
- return truncate(Array.isArray(value) ? String(value.length) : "", node.cap);
215
+ return truncate(
216
+ Array.isArray(value) ? String(value.length) : "",
217
+ cap,
218
+ legacyPreview,
219
+ );
200
220
  if (node.each || list || node.join !== undefined) {
201
221
  if (!Array.isArray(value)) return "";
202
222
  const elements = value
203
- .slice(0, 10)
223
+ .slice(0, legacyPreview ? 10 : undefined)
204
224
  .map((item) =>
205
- truncate(node.each ? render(node.each, item) : scalar(item), 300),
225
+ truncate(
226
+ node.each ? render(node.each, item, legacyPreview) : scalar(item),
227
+ legacyPreview ? 300 : undefined,
228
+ legacyPreview,
229
+ ),
206
230
  );
207
- if (value.length > 10) elements.push(`… +${value.length - 10} more`);
208
- return truncate(elements.join(node.join ?? (node.each ? "; " : ", ")), node.cap);
231
+ if (legacyPreview && value.length > 10)
232
+ elements.push(`… +${value.length - 10} more`);
233
+ return truncate(
234
+ elements.join(node.join ?? (node.each ? "; " : ", ")),
235
+ cap,
236
+ legacyPreview,
237
+ );
209
238
  }
210
- return truncate(scalar(value), node.cap);
239
+ return truncate(scalar(value), cap, legacyPreview);
211
240
  })
212
241
  .join("");
213
242
  }
@@ -216,6 +245,7 @@ export function renderToolTemplate(
216
245
  source: string,
217
246
  input: unknown,
218
247
  output?: unknown,
248
+ legacyPreview = false,
219
249
  ): string | null {
220
250
  const nodes = compiled(source);
221
251
  if (!nodes) return null;
@@ -241,8 +271,12 @@ export function renderToolTemplate(
241
271
  !node.each &&
242
272
  !node.count &&
243
273
  node.join === undefined
244
- ? truncate(text ?? "", node.cap)
274
+ ? truncate(text ?? "", node.cap ?? (legacyPreview ? 300 : undefined), legacyPreview)
245
275
  : node,
246
276
  );
247
- return truncate(render(bareOutputNodes, root), 1000);
277
+ return truncate(
278
+ render(bareOutputNodes, root, legacyPreview),
279
+ legacyPreview ? 1000 : undefined,
280
+ legacyPreview,
281
+ );
248
282
  }
@@ -1,4 +1,4 @@
1
- export type ModelHarness = "opencode" | "pi";
1
+ export type ModelHarness = "opencode" | "pi" | "omp";
2
2
 
3
3
  export interface ResolvedModelEntry {
4
4
  /** Canonical provider/model reference used for identity and model selection. */
@@ -149,7 +149,7 @@ Look at each tag before stamping it; never blanket-stamp a range like "1-50". Ma
149
149
  }
150
150
  ```
151
151
 
152
- ### mmc_expand — description ~391 tokens, params ~189 tokens (total ~580)
152
+ ### mmc_expand — description ~393 tokens, params ~189 tokens (total ~582)
153
153
 
154
154
  **Description:**
155
155
 
@@ -164,7 +164,7 @@ Returns the raw transcript as [N] U:/A: lines, capped at ~15K tokens; an oversiz
164
164
 
165
165
  Finer recovery:
166
166
  - verbose=true lists each message separately with its ordinal and a per-part preview (tool calls with output sizes) so you can pick one.
167
- - message=N returns that one message in full — every text part and every tool call's complete input and output — from stored history. This is the way back to a tool output you released with mmc_reduce; if the message was deleted from history it says so.
167
+ - message=N returns that one message in full — every text part and every tool call's complete input and output — from stored history. This is the way back to a tool output you released with mmc_reduce; if the message is no longer in stored history it says so.
168
168
  ```
169
169
 
170
170
  **Parameters (JSON Schema per parameter, as serialized to the provider):**
@@ -4,6 +4,7 @@ import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import {
6
6
  Database,
7
+ SqliteAcquisitionBusyError,
7
8
  withAsyncPrivilegedWriter,
8
9
  withPrivilegedWriter,
9
10
  withSqliteTransformPass,
@@ -11,6 +12,23 @@ import {
11
12
  import { startSqliteWriteLocker } from "./sqlite-write-locker-test-support";
12
13
  import { createTestTempDirFromPath } from "./test-temp-dir";
13
14
 
15
+ test("async writer never retries callback acquisition errors after work began", async () => {
16
+ const db = new Database(":memory:");
17
+ db.exec("CREATE TABLE context_privilege_state(id INTEGER PRIMARY KEY, enabled INTEGER)");
18
+ let calls = 0;
19
+ try {
20
+ await expect(
21
+ withAsyncPrivilegedWriter(db, () => {
22
+ calls++;
23
+ throw new SqliteAcquisitionBusyError(new Error("nested BEGIN"));
24
+ }),
25
+ ).rejects.toThrow("acquisition remained busy");
26
+ expect(calls).toBe(1);
27
+ } finally {
28
+ db.close();
29
+ }
30
+ });
31
+
14
32
  for (const mode of ["default", "immediate", "exclusive", "literal"] as const) {
15
33
  test(`shared SQLite retries ${mode} acquisition before running any writes`, async () => {
16
34
  const dir = createTestTempDirFromPath(join(tmpdir(), "mc-routed-acquisition-"));