@cortexkit/opencode-magic-context 0.41.2 → 0.41.3

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 (138) hide show
  1. package/README.md +9 -3
  2. package/dist/announcement-3c1vertn.js +14 -0
  3. package/dist/config/project-security.d.ts.map +1 -1
  4. package/dist/config/schema/magic-context.d.ts +756 -4
  5. package/dist/config/schema/magic-context.d.ts.map +1 -1
  6. package/dist/conflict-warning-hook-z5sd697e.js +16 -0
  7. package/dist/derive-budgets-901a0pk0.js +11 -0
  8. package/dist/features/magic-context/compartment-lease.d.ts +6 -0
  9. package/dist/features/magic-context/compartment-lease.d.ts.map +1 -1
  10. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  11. package/dist/features/magic-context/storage-db.d.ts +18 -1
  12. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  13. package/dist/features/magic-context/storage-meta-persisted.d.ts +11 -12
  14. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  15. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  16. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  17. package/dist/features/magic-context/storage-subagent-invocations.d.ts +3 -2
  18. package/dist/features/magic-context/storage-subagent-invocations.d.ts.map +1 -1
  19. package/dist/features/magic-context/storage-tags.d.ts +6 -0
  20. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  21. package/dist/features/magic-context/storage.d.ts +2 -2
  22. package/dist/features/magic-context/storage.d.ts.map +1 -1
  23. package/dist/features/magic-context/subagent-token-capture.d.ts +2 -1
  24. package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/compaction-marker-manager.d.ts +6 -1
  26. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/compartment-runner.d.ts +2 -1
  28. package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/hook.d.ts +4 -3
  30. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/inject-compartments.d.ts +6 -0
  32. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/module-state-sync.d.ts +2 -1
  34. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/module-transport.d.ts +11 -4
  36. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/module-wire.d.ts +6 -1
  38. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/read-session-db.d.ts +15 -0
  40. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  41. package/dist/hooks/magic-context/rust-mode-transform.d.ts +10 -0
  42. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  43. package/dist/hooks/magic-context/send-session-notification.d.ts +6 -0
  44. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  45. package/dist/hooks/magic-context/sentinel.d.ts +5 -16
  46. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  47. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  48. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +32 -0
  49. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  50. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  51. package/dist/{index-y1yr57fw.js → index-0bycg0np.js} +18 -18
  52. package/dist/{index-1yh8g550.js → index-22jkk6wg.js} +2 -15
  53. package/dist/{index-dmvy29z0.js → index-3wzdwt6p.js} +11 -15
  54. package/dist/{index-d1mxrd3p.js → index-7k55qm8a.js} +17 -12
  55. package/dist/{index-4x691bz5.js → index-dkv2dn46.js} +5 -2
  56. package/dist/{index-cvda5jb3.js → index-dn1rwpd8.js} +11 -11
  57. package/dist/{index-rgdqj8nj.js → index-e7vx3byk.js} +1 -1
  58. package/dist/{index-szf8w1p5.js → index-fmsr7v69.js} +2 -2
  59. package/dist/{index-d62ypazr.js → index-jdxxq8cz.js} +6 -11
  60. package/dist/{index-9j3tx8hy.js → index-may8skc8.js} +6 -25
  61. package/dist/{index-eq9wr75c.js → index-npx8vhmy.js} +57 -108
  62. package/dist/{index-zwjhba2r.js → index-q264erdp.js} +122 -41
  63. package/dist/{index-b9j85d29.js → index-raatkvw5.js} +49 -11
  64. package/dist/{index-9xexf8s7.js → index-rn7gafjr.js} +1 -9
  65. package/dist/index-v6t0tg85.js +13 -0
  66. package/dist/{index-j8r0ejb3.js → index-vmmjdpc0.js} +1694 -11167
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +2149 -1799
  69. package/dist/model-resolution-dxatzjde.js +12 -0
  70. package/dist/{index-dynqfgx1.js → module-asyncify-2EFITU5U-rkqjhjxd.js} +69 -8
  71. package/dist/plugin/boot-deadline.d.ts +47 -0
  72. package/dist/plugin/boot-deadline.d.ts.map +1 -0
  73. package/dist/plugin/conflict-warning-hook.d.ts +10 -0
  74. package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
  75. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -0
  76. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  77. package/dist/plugin/messages-transform.d.ts.map +1 -1
  78. package/dist/prompt-context-5y5ms8f9.js +6 -0
  79. package/dist/recomp-orchestrator-f5m2wk74.js +19 -0
  80. package/dist/rpc-notifications-4amf6mf4.js +14 -0
  81. package/dist/{index-vnz6jvdc.js → safe-notification-target-q9z81zt3.js} +4 -3
  82. package/dist/send-session-notification-hdh02wy9.js +16 -0
  83. package/dist/shared/conflict-detector.d.ts +3 -1
  84. package/dist/shared/conflict-detector.d.ts.map +1 -1
  85. package/dist/shared/harness.d.ts +3 -3
  86. package/dist/shared/harness.d.ts.map +1 -1
  87. package/dist/shared/model-resolution.d.ts +3 -3
  88. package/dist/shared/model-resolution.d.ts.map +1 -1
  89. package/dist/shared/prompt-surface-runtime.d.ts +2 -2
  90. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  91. package/dist/shared/tag-transcript.d.ts.map +1 -1
  92. package/dist/shared/transcript.d.ts +2 -1
  93. package/dist/shared/transcript.d.ts.map +1 -1
  94. package/dist/storage-meta-session-3rxx9ekm.js +20 -0
  95. package/dist/task-config-hnv93r7p.js +9 -0
  96. package/dist/transformers-node-wasm.js +328 -328
  97. package/dist/transformers-web.js +72 -72
  98. package/dist/{transformers.node-b1wa0hgx.js → transformers.node-dpmf3wpx.js} +74 -74
  99. package/package.json +1 -1
  100. package/src/config/index.test.ts +28 -0
  101. package/src/config/project-security.hostile-matrix.test.ts +78 -9
  102. package/src/config/project-security.ts +4 -3
  103. package/src/config/schema/magic-context.test.ts +64 -0
  104. package/src/config/schema/magic-context.ts +100 -6
  105. package/src/shared/conflict-detector.test.ts +24 -0
  106. package/src/shared/conflict-detector.ts +25 -7
  107. package/src/shared/harness.ts +3 -3
  108. package/src/shared/model-resolution.test.ts +61 -0
  109. package/src/shared/model-resolution.ts +14 -5
  110. package/src/shared/prompt-surface-runtime.ts +3 -3
  111. package/src/shared/tag-transcript.ts +11 -0
  112. package/src/shared/transcript.ts +3 -1
  113. package/dist/announcement-3g9xg433.js +0 -18
  114. package/dist/conflict-warning-hook-rf17b6et.js +0 -17
  115. package/dist/derive-budgets-9q2d3r93.js +0 -14
  116. package/dist/emscripten-module-49k43zfy.js +0 -507
  117. package/dist/emscripten-module-ex4v0x4z.js +0 -606
  118. package/dist/emscripten-module-jfs3d1dq.js +0 -1536
  119. package/dist/emscripten-module-ss4g4spn.js +0 -4563
  120. package/dist/ffi-bbm9vkfa.js +0 -92
  121. package/dist/ffi-kb5r0x1j.js +0 -92
  122. package/dist/ffi-qnrt0y78.js +0 -80
  123. package/dist/ffi-yx2hpf4p.js +0 -80
  124. package/dist/index-8sseka65.js +0 -251
  125. package/dist/index-ss632za9.js +0 -77
  126. package/dist/model-resolution-6w6wzw18.js +0 -17
  127. package/dist/module-ES6BEMUI-1yjdz59c.js +0 -14
  128. package/dist/module-asyncify-2EFITU5U-fdkx4fhy.js +0 -9
  129. package/dist/prompt-context-29qkb28f.js +0 -7
  130. package/dist/recomp-orchestrator-m37p3fq6.js +0 -34
  131. package/dist/rpc-notifications-1ffm755w.js +0 -17
  132. package/dist/safe-notification-target-2a8py95v.js +0 -11
  133. package/dist/send-session-notification-bw7eex6w.js +0 -20
  134. package/dist/storage-meta-session-dse3qv6s.js +0 -23
  135. package/dist/task-config-gv6s04fp.js +0 -18
  136. /package/dist/{index-37yzyeca.js → index-3fe78beq.js} +0 -0
  137. /package/dist/{index-8mtsfhyg.js → index-jfpk81yt.js} +0 -0
  138. /package/dist/{index-2wchnyk6.js → index-kby1sng5.js} +0 -0
@@ -307,6 +307,19 @@ describe("MagicContextConfigSchema", () => {
307
307
  },
308
308
  thinking_level: "high",
309
309
  },
310
+ omp: {
311
+ model: {
312
+ model: "opencode/work-historian",
313
+ thinking_level: "auto",
314
+ },
315
+ fallback_models: [
316
+ {
317
+ model: "opencode/work-historian-fallback",
318
+ thinking_level: "inherit",
319
+ },
320
+ ],
321
+ thinking_level: "max",
322
+ },
310
323
  },
311
324
  dreamer: {
312
325
  opencode: {
@@ -329,6 +342,16 @@ describe("MagicContextConfigSchema", () => {
329
342
  ],
330
343
  thinking_level: "high",
331
344
  },
345
+ omp: {
346
+ model: "opencode/work-dreamer",
347
+ fallback_models: [
348
+ {
349
+ model: "opencode/work-dreamer-fallback",
350
+ thinking_level: "auto",
351
+ },
352
+ ],
353
+ thinking_level: "inherit",
354
+ },
332
355
  },
333
356
  sidekick: {
334
357
  model: "anthropic/work-sidekick",
@@ -349,6 +372,10 @@ describe("MagicContextConfigSchema", () => {
349
372
  expect(result.profiles?.work?.dreamer?.pi?.fallback_models).toEqual([
350
373
  { model: "openai/work-dreamer-fallback", thinking_level: "minimal" },
351
374
  ]);
375
+ expect(result.profiles?.work?.historian?.omp?.fallback_models).toEqual([
376
+ { model: "opencode/work-historian-fallback", thinking_level: "inherit" },
377
+ ]);
378
+ expect(result.profiles?.work?.dreamer?.omp?.thinking_level).toBe("inherit");
352
379
  expect(result.profiles?.work?.sidekick?.model).toBe("anthropic/work-sidekick");
353
380
  });
354
381
 
@@ -484,6 +511,14 @@ describe("MagicContextConfigSchema", () => {
484
511
  fallback_models: ["openai/gpt-5.4"],
485
512
  thinking_level: "medium",
486
513
  },
514
+ omp: {
515
+ model: {
516
+ model: "opencode/gpt-5.4",
517
+ thinking_level: "auto",
518
+ },
519
+ fallback_models: [{ model: "openai/gpt-5.4", thinking_level: "inherit" }],
520
+ thinking_level: "max",
521
+ },
487
522
  },
488
523
  dreamer: {
489
524
  disable: false,
@@ -518,6 +553,29 @@ describe("MagicContextConfigSchema", () => {
518
553
  },
519
554
  },
520
555
  },
556
+ omp: {
557
+ model: "opencode/gpt-5.4",
558
+ fallback_models: [
559
+ { model: "opencode/gpt-5.4-mini", thinking_level: "auto" },
560
+ ],
561
+ thinking_level: "inherit",
562
+ tasks: {
563
+ verify: {
564
+ model: {
565
+ model: "opencode/gpt-5.4",
566
+ thinking_level: "max",
567
+ },
568
+ fallback_models: [
569
+ {
570
+ model: "opencode/gpt-5.4-mini",
571
+ thinking_level: "off",
572
+ },
573
+ ],
574
+ thinking_level: "auto",
575
+ timeout_minutes: 30,
576
+ },
577
+ },
578
+ },
521
579
  },
522
580
  });
523
581
 
@@ -527,12 +585,18 @@ describe("MagicContextConfigSchema", () => {
527
585
  promotion_threshold: 4,
528
586
  });
529
587
  expect(result.dreamer?.opencode?.tasks?.verify?.timeout_minutes).toBe(30);
588
+ expect(result.historian?.omp?.model).toEqual({
589
+ model: "opencode/gpt-5.4",
590
+ thinking_level: "auto",
591
+ });
592
+ expect(result.dreamer?.omp?.tasks?.verify?.thinking_level).toBe("auto");
530
593
  });
531
594
 
532
595
  it("rejects cross-harness vocabulary, non-array fallbacks, and execution fields at metadata depth", () => {
533
596
  const invalidConfigs = [
534
597
  { historian: { opencode: { thinking_level: "high" } } },
535
598
  { historian: { pi: { variant: "high" } } },
599
+ { historian: { omp: { variant: "high" } } },
536
600
  {
537
601
  dreamer: {
538
602
  opencode: { tasks: { verify: { thinking_level: "high" } } },
@@ -36,6 +36,12 @@ export const PiThinkingLevelSchema = z
36
36
  .optional();
37
37
  export type PiThinkingLevel = z.infer<typeof PiThinkingLevelSchema>;
38
38
 
39
+ /** OMP accepts Pi's thinking levels plus host-managed inheritance and automatic selection. */
40
+ export const OmpThinkingLevelSchema = z
41
+ .enum(["off", "minimal", "low", "medium", "high", "xhigh", "max", "inherit", "auto"])
42
+ .optional();
43
+ export type OmpThinkingLevel = z.infer<typeof OmpThinkingLevelSchema>;
44
+
39
45
  /** Pi-only child-process controls. This block is intentionally optional so an
40
46
  * absent allowlist preserves Pi's normal extension discovery behavior. */
41
47
  export const PiConfigSchema = z
@@ -157,6 +163,9 @@ export const PER_HARNESS_MIGRATION_INVENTORY = {
157
163
  },
158
164
  } as const;
159
165
 
166
+ /** Harness keys that own independent hidden-agent model-selection blocks. */
167
+ export const PER_HARNESS_MODEL_KEYS = ["opencode", "pi", "omp"] as const;
168
+
160
169
  /** OpenCode entry objects permit `variant` and reject Pi-only `thinking_level`. */
161
170
  const OcEntryObjectSchema = z
162
171
  .object({
@@ -177,6 +186,16 @@ const PiEntryObjectSchema = z
177
186
  export const PiEntrySchema = z.union([z.string(), PiEntryObjectSchema]);
178
187
  export type PiEntry = z.infer<typeof PiEntrySchema>;
179
188
 
189
+ /** OMP entry objects use Pi's qualifier vocabulary, including OMP-only auto/inherit. */
190
+ const OmpEntryObjectSchema = z
191
+ .object({
192
+ model: z.string().describe("OMP model ID (for example, provider/model)."),
193
+ thinking_level: OmpThinkingLevelSchema.describe("OMP thinking level for this entry."),
194
+ })
195
+ .strict();
196
+ export const OmpEntrySchema = z.union([z.string(), OmpEntryObjectSchema]);
197
+ export type OmpEntry = z.infer<typeof OmpEntrySchema>;
198
+
180
199
  /** Strict model-resolution block used by historian.opencode. */
181
200
  export const OpenCodeHarnessBlockSchema = z
182
201
  .object({
@@ -216,6 +235,22 @@ export const PiHarnessBlockSchema = z
216
235
  .describe("Strict Pi model-resolution block. It accepts no OpenCode vocabulary.");
217
236
  export type PiHarnessBlock = z.infer<typeof PiHarnessBlockSchema>;
218
237
 
238
+ /** Strict model-resolution block used by historian.omp. */
239
+ export const OmpHarnessBlockSchema = z
240
+ .object({
241
+ model: OmpEntrySchema.optional().describe("Primary OMP model entry."),
242
+ fallback_models: z
243
+ .array(OmpEntrySchema)
244
+ .optional()
245
+ .describe("Ordered fallback OMP entries."),
246
+ thinking_level: OmpThinkingLevelSchema.describe(
247
+ "OMP thinking level for the primary entry when it declares none. Fallback entries declare thinking levels per-entry.",
248
+ ),
249
+ })
250
+ .strict()
251
+ .describe("Strict OMP model-resolution block. It accepts no OpenCode vocabulary.");
252
+ export type OmpHarnessBlock = z.infer<typeof OmpHarnessBlockSchema>;
253
+
219
254
  /** Strict OpenCode-only execution override for one dreamer task. */
220
255
  export const OpenCodeTaskExecutionSchema = z
221
256
  .object({
@@ -259,6 +294,26 @@ export const PiTaskExecutionSchema = z
259
294
  .strict();
260
295
  export type PiTaskExecution = z.infer<typeof PiTaskExecutionSchema>;
261
296
 
297
+ /** Strict OMP-only execution override for one dreamer task. */
298
+ export const OmpTaskExecutionSchema = z
299
+ .object({
300
+ model: OmpEntrySchema.optional().describe("OMP model entry for this task."),
301
+ fallback_models: z
302
+ .array(OmpEntrySchema)
303
+ .optional()
304
+ .describe("Ordered OMP fallback entries for this task."),
305
+ thinking_level: OmpThinkingLevelSchema.describe(
306
+ "OMP thinking level for this task's primary entry when it declares none. Fallback entries declare thinking levels per-entry.",
307
+ ),
308
+ timeout_minutes: z
309
+ .number()
310
+ .min(5)
311
+ .optional()
312
+ .describe("Minutes allowed for this task before it is aborted."),
313
+ })
314
+ .strict();
315
+ export type OmpTaskExecution = z.infer<typeof OmpTaskExecutionSchema>;
316
+
262
317
  /** Strict OpenCode harness block for dreamer execution and task overrides. */
263
318
  export const DreamerOpenCodeHarnessBlockSchema = z
264
319
  .object({
@@ -310,6 +365,28 @@ export const DreamerPiHarnessBlockSchema = z
310
365
  .describe("Strict Pi dreamer model-resolution block. It accepts no OpenCode vocabulary.");
311
366
  export type DreamerPiHarnessBlock = z.infer<typeof DreamerPiHarnessBlockSchema>;
312
367
 
368
+ /** Strict OMP harness block for dreamer execution and task overrides. */
369
+ export const DreamerOmpHarnessBlockSchema = z
370
+ .object({
371
+ model: OmpEntrySchema.optional().describe("Primary OMP model entry."),
372
+ fallback_models: z
373
+ .array(OmpEntrySchema)
374
+ .optional()
375
+ .describe("Ordered fallback OMP entries."),
376
+ thinking_level: OmpThinkingLevelSchema.describe(
377
+ "OMP thinking level for the primary entry when it declares none. Fallback entries declare thinking levels per-entry.",
378
+ ),
379
+ tasks: z
380
+ .record(z.string(), OmpTaskExecutionSchema)
381
+ .optional()
382
+ .describe(
383
+ "OMP task execution overrides. Each named task accepts only model, fallback_models, thinking_level, and timeout_minutes.",
384
+ ),
385
+ })
386
+ .strict()
387
+ .describe("Strict OMP dreamer model-resolution block. It accepts no OpenCode vocabulary.");
388
+ export type DreamerOmpHarnessBlock = z.infer<typeof DreamerOmpHarnessBlockSchema>;
389
+
313
390
  /**
314
391
  * A profile may select models but must not alter execution policy. Keep this
315
392
  * separate from the full harness schemas, whose dreamer blocks also admit task
@@ -342,16 +419,31 @@ const ProfilePiModelBlockSchema = z
342
419
  })
343
420
  .strict()
344
421
  .describe("Strict profile-only Pi model-selection block.");
422
+ const ProfileOmpModelBlockSchema = z
423
+ .object({
424
+ model: OmpEntrySchema.optional().describe("Primary OMP model entry."),
425
+ fallback_models: z
426
+ .array(OmpEntrySchema)
427
+ .optional()
428
+ .describe("Ordered fallback OMP model entries."),
429
+ thinking_level: OmpThinkingLevelSchema.describe(
430
+ "OMP thinking level for the primary model entry.",
431
+ ),
432
+ })
433
+ .strict()
434
+ .describe("Strict profile-only OMP model-selection block.");
345
435
  const ProfileHistorianSchema = z
346
436
  .object({
347
437
  opencode: ProfileOpenCodeModelBlockSchema.optional(),
348
438
  pi: ProfilePiModelBlockSchema.optional(),
439
+ omp: ProfileOmpModelBlockSchema.optional(),
349
440
  })
350
441
  .strict();
351
442
  const ProfileDreamerSchema = z
352
443
  .object({
353
444
  opencode: ProfileOpenCodeModelBlockSchema.optional(),
354
445
  pi: ProfilePiModelBlockSchema.optional(),
446
+ omp: ProfileOmpModelBlockSchema.optional(),
355
447
  })
356
448
  .strict();
357
449
  const ProfileSidekickSchema = AgentOverrideConfigSchema.pick({
@@ -502,7 +594,7 @@ export const DreamTasksSchema = z
502
594
  ),
503
595
  })
504
596
  .describe(
505
- "Harness-independent task metadata. schedule, promotion_threshold, and other task metadata remain here; execution settings live under dreamer.opencode.tasks or dreamer.pi.tasks.",
597
+ "Harness-independent task metadata. schedule, promotion_threshold, and other task metadata remain here; execution settings live under dreamer.opencode.tasks, dreamer.pi.tasks, or dreamer.omp.tasks.",
506
598
  );
507
599
 
508
600
  const AgentMetadataSchema = AgentOverrideConfigSchema.pick({
@@ -519,10 +611,11 @@ const AgentMetadataSchema = AgentOverrideConfigSchema.pick({
519
611
  maxTokens: true,
520
612
  });
521
613
 
522
- /** Combined dreamer metadata plus two independent strict execution blocks. */
614
+ /** Combined dreamer metadata plus independent strict execution blocks. */
523
615
  export const DreamerConfigSchema = AgentMetadataSchema.extend({
524
616
  opencode: DreamerOpenCodeHarnessBlockSchema.optional(),
525
617
  pi: DreamerPiHarnessBlockSchema.optional(),
618
+ omp: DreamerOmpHarnessBlockSchema.optional(),
526
619
  tasks: DreamTasksSchema.default(() => DreamTasksSchema.parse({})),
527
620
  inject_docs: z
528
621
  .boolean()
@@ -544,11 +637,12 @@ export type SidekickConfig = NonNullable<z.infer<typeof SidekickConfigSchema>>;
544
637
 
545
638
  /**
546
639
  * Historian metadata remains harness-independent. Only model resolution moves to
547
- * the strict opencode and pi blocks; two_pass and disallowed_tools stay here.
640
+ * the strict opencode, pi, and omp blocks; two_pass and disallowed_tools stay here.
548
641
  */
549
642
  export const HistorianConfigSchema = AgentMetadataSchema.extend({
550
643
  opencode: OpenCodeHarnessBlockSchema.optional(),
551
644
  pi: PiHarnessBlockSchema.optional(),
645
+ omp: OmpHarnessBlockSchema.optional(),
552
646
  two_pass: z
553
647
  .boolean()
554
648
  .default(false)
@@ -986,13 +1080,13 @@ export const MagicContextConfigSchema = z
986
1080
  "Select a named user-owned model profile. A valid project name overrides this user default; an empty string, null, or other non-string project value is ignored with a warning so the user selection still applies. Unknown names warn and use the base configuration.",
987
1081
  ),
988
1082
  profiles: ConfigProfilesSchema.optional().describe(
989
- "User-level named model profiles. A profile may contain only historian/dreamer model, fallback_models, OpenCode variant, and Pi thinking_level fields plus sidekick model-selection fields; task execution policy (including timeout_minutes) is excluded. Project configs may select a name but cannot define profiles.",
1083
+ "User-level named model profiles. A profile may contain only historian/dreamer model, fallback_models, OpenCode variant, and Pi/OMP thinking_level fields plus sidekick model-selection fields; task execution policy (including timeout_minutes) is excluded. Project configs may select a name but cannot define profiles.",
990
1084
  ),
991
1085
  historian: HistorianConfigSchema.describe(
992
- "Historian metadata plus independent strict OpenCode and Pi execution blocks. Retained metadata stays at historian; model, fallback_models, variant, and thinking_level belong only in historian.opencode or historian.pi.",
1086
+ "Historian metadata plus independent strict OpenCode, Pi, and OMP execution blocks. Retained metadata stays at historian; model, fallback_models, variant, and thinking_level belong only in historian.opencode, historian.pi, or historian.omp.",
993
1087
  ),
994
1088
  dreamer: DreamerConfigSchema.optional().describe(
995
- "Dreamer metadata and scheduling plus independent strict OpenCode and Pi execution blocks. schedule and promotion_threshold stay at dreamer.tasks; model, fallback_models, variant, thinking_level, and timeout_minutes belong only in the matching harness block.",
1089
+ "Dreamer metadata and scheduling plus independent strict OpenCode, Pi, and OMP execution blocks. schedule and promotion_threshold stay at dreamer.tasks; model, fallback_models, variant, thinking_level, and timeout_minutes belong only in the matching harness block.",
996
1090
  ),
997
1091
  smart_notes: z
998
1092
  .object({
@@ -653,5 +653,29 @@ describe("detectConflicts", () => {
653
653
  const result = await resolveCompactionForBoot(client, 20);
654
654
  expect(result).toBeNull();
655
655
  });
656
+
657
+ it("aborts the host request when its boot timeout expires", async () => {
658
+ let requestSignal: AbortSignal | undefined;
659
+ const client = {
660
+ config: {
661
+ get: (options?: { signal?: AbortSignal }) => {
662
+ requestSignal = options?.signal;
663
+ return new Promise<{ data?: unknown }>((_resolve, reject) => {
664
+ options?.signal?.addEventListener(
665
+ "abort",
666
+ () => reject(options.signal?.reason ?? new Error("aborted")),
667
+ { once: true },
668
+ );
669
+ });
670
+ },
671
+ },
672
+ };
673
+
674
+ const result = await resolveCompactionForBoot(client, 20);
675
+
676
+ expect(result).toBeNull();
677
+ expect(requestSignal).toBeDefined();
678
+ expect(requestSignal?.aborted).toBe(true);
679
+ });
656
680
  });
657
681
  });
@@ -209,7 +209,7 @@ export function detectConflicts(
209
209
  */
210
210
  export interface OpencodeConfigClientLike {
211
211
  config: {
212
- get: () => Promise<{ data?: unknown }>;
212
+ get: (options?: { signal?: AbortSignal }) => Promise<{ data?: unknown }>;
213
213
  };
214
214
  }
215
215
 
@@ -250,13 +250,29 @@ export async function resolveCompactionForBoot(
250
250
  client: OpencodeConfigClientLike,
251
251
  timeoutMs = 2_000,
252
252
  ): Promise<ResolvedCompaction | null> {
253
+ const controller = new AbortController();
254
+ let timer: ReturnType<typeof setTimeout> | undefined;
253
255
  try {
254
- const result = await Promise.race([
255
- client.config.get(),
256
- new Promise<never>((_, reject) =>
257
- setTimeout(() => reject(new Error("config.get() timed out")), timeoutMs),
258
- ),
259
- ]);
256
+ // Install the deadline before invoking the generated SDK method. During
257
+ // OpenCode bootstrap, /config can recursively wait for the same project
258
+ // instance that is currently loading this plugin. Deferring invocation
259
+ // ensures the deadline exists before any synchronous SDK/fetch prefix runs.
260
+ const timeout = new Promise<null>((resolve) => {
261
+ timer = setTimeout(
262
+ () => {
263
+ controller.abort(new Error("config.get() timed out"));
264
+ resolve(null);
265
+ },
266
+ Math.max(0, timeoutMs),
267
+ );
268
+ (timer as { unref?: () => void }).unref?.();
269
+ });
270
+ const request = Promise.resolve().then(() =>
271
+ client.config.get({ signal: controller.signal }),
272
+ );
273
+ const result = await Promise.race([request, timeout]);
274
+ if (result === null) return null;
275
+
260
276
  // The SDK's generated `Config` type has no `compaction` key, so read it
261
277
  // defensively from the runtime response.
262
278
  const compaction = (result?.data as ResolvedCompactionBlock | undefined)?.compaction;
@@ -272,6 +288,8 @@ export async function resolveCompactionForBoot(
272
288
  return { auto: compaction.auto, prune: compaction.prune };
273
289
  } catch {
274
290
  return null;
291
+ } finally {
292
+ if (timer) clearTimeout(timer);
275
293
  }
276
294
  }
277
295
 
@@ -2,7 +2,7 @@
2
2
  * Identifier for the host harness this plugin is running inside.
3
3
  *
4
4
  * Magic Context's SQLite database lives at a vendor-scoped path
5
- * (`~/.local/share/cortexkit/magic-context/`) so OpenCode and Pi can share
5
+ * (`~/.local/share/cortexkit/magic-context/`) so OpenCode, Pi, and OMP can share
6
6
  * project memories, embedding cache, dreamer runs, and other project-scoped
7
7
  * state. Session-scoped tables carry a `harness` column populated from this
8
8
  * module so we can disambiguate which harness wrote each session row,
@@ -13,13 +13,13 @@
13
13
  * happens:
14
14
  * - OpenCode plugin: relies on the default ("opencode") — no setHarness call
15
15
  * needed
16
- * - Pi plugin: calls `setHarness("pi")` before opening the database
16
+ * - Pi-compatible plugin: resolves the host and calls `setHarness("pi" | "omp")` before opening the database
17
17
  *
18
18
  * NEVER read this from configuration or session state — it is a
19
19
  * boot-time constant per plugin instance. Cross-harness leakage is a
20
20
  * correctness bug, not a feature.
21
21
  */
22
- export type HarnessId = "opencode" | "pi";
22
+ export type HarnessId = "opencode" | "pi" | "omp";
23
23
 
24
24
  let currentHarness: HarnessId = "opencode";
25
25
  let harnessLocked = false;
@@ -130,6 +130,67 @@ describe("model-resolution", () => {
130
130
  });
131
131
  });
132
132
 
133
+ test("uses OMP blocks first, falls back to Pi blocks, then preserves existing defaults", () => {
134
+ const configured = {
135
+ historian: {
136
+ pi: {
137
+ model: { model: "pi/historian", thinking_level: "high" },
138
+ fallback_models: ["pi/historian-fallback"],
139
+ },
140
+ omp: {
141
+ model: { model: "omp/historian", thinking_level: "auto" },
142
+ fallback_models: [{ model: "omp/historian-fallback", thinking_level: "max" }],
143
+ },
144
+ },
145
+ dreamer: {
146
+ tasks: { verify: { schedule: "0 3 * * *" } },
147
+ pi: {
148
+ model: "pi/dreamer",
149
+ tasks: { verify: { model: "pi/verify" } },
150
+ },
151
+ omp: {
152
+ model: "omp/dreamer",
153
+ tasks: {
154
+ verify: {
155
+ model: { model: "omp/verify", thinking_level: "inherit" },
156
+ },
157
+ },
158
+ },
159
+ },
160
+ };
161
+
162
+ expect(resolveHistorianModel(configured, "omp")).toEqual({
163
+ primary: { model: "omp/historian", qualifier: "auto" },
164
+ fallbacks: [{ model: "omp/historian-fallback", qualifier: "max" }],
165
+ });
166
+ expect(
167
+ resolveDreamerTaskModel({ config: configured, harness: "omp", task: "verify" }),
168
+ ).toMatchObject({ primary: { model: "omp/verify", qualifier: "inherit" } });
169
+
170
+ const piFallback = {
171
+ historian: configured.historian,
172
+ dreamer: { ...configured.dreamer, omp: undefined },
173
+ };
174
+ delete (piFallback.historian as { omp?: unknown }).omp;
175
+ expect(resolveHistorianModel(piFallback, "omp")?.primary).toEqual({
176
+ model: "pi/historian",
177
+ qualifier: "high",
178
+ });
179
+ expect(
180
+ resolveDreamerTaskModel({ config: piFallback, harness: "omp", task: "verify" }),
181
+ ).toMatchObject({ primary: { model: "pi/verify" } });
182
+
183
+ expect(resolveHistorianModel({}, "omp")).toEqual({ fallbacks: [] });
184
+ const existingDefaults = resolveDreamerTaskModel({
185
+ config: { dreamer: { tasks: { verify: { schedule: "0 3 * * *" } } } },
186
+ harness: "omp",
187
+ task: "verify",
188
+ });
189
+ expect(existingDefaults.primary).toBeUndefined();
190
+ expect(existingDefaults.fallbacks).toEqual([]);
191
+ expect(existingDefaults.schedule).toBe("0 3 * * *");
192
+ });
193
+
133
194
  test("resolves ordinary task model and scheduling without crossing harnesses", () => {
134
195
  const config = {
135
196
  dreamer: {
@@ -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. */
@@ -27,6 +27,14 @@ function hasOwn(record: ConfigRecord, key: string): boolean {
27
27
  return Object.hasOwn(record, key);
28
28
  }
29
29
 
30
+ function resolveHarnessBlock(
31
+ container: ConfigRecord | undefined,
32
+ harness: ModelHarness,
33
+ ): ConfigRecord | undefined {
34
+ const selected = harness === "omp" ? (container?.omp ?? container?.pi) : container?.[harness];
35
+ return asRecord(selected);
36
+ }
37
+
30
38
  /**
31
39
  * Collapses the string and object spellings of a harness model entry into the
32
40
  * same model identity. Qualifiers stay separate because they alter an attempt,
@@ -98,15 +106,15 @@ export interface ResolvedHistorianModel {
98
106
  }
99
107
 
100
108
  /**
101
- * Resolve historian model attempts from exactly one harness block. Flat keys
102
- * and the other harness are deliberately never consulted after cutover.
109
+ * Resolve historian model attempts from the selected harness block. OMP uses
110
+ * its own block when present and falls back to Pi when it is absent.
103
111
  */
104
112
  export function resolveHistorianModel(
105
113
  config: unknown,
106
114
  harness: ModelHarness,
107
115
  ): ResolvedHistorianModel {
108
116
  const historian = asRecord(asRecord(config)?.historian);
109
- const block = asRecord(historian?.[harness]);
117
+ const block = resolveHarnessBlock(historian, harness);
110
118
  if (!block) return { fallbacks: [] };
111
119
 
112
120
  return {
@@ -139,7 +147,7 @@ export function resolveDreamerTaskModel(args: {
139
147
  muralModel?: unknown;
140
148
  }): ResolvedDreamerTaskModel {
141
149
  const dreamer = asRecord(asRecord(args.config)?.dreamer);
142
- const harnessBlock = asRecord(dreamer?.[args.harness]);
150
+ const harnessBlock = resolveHarnessBlock(dreamer, args.harness);
143
151
  const taskBlock = asRecord(asRecord(harnessBlock?.tasks)?.[args.task]);
144
152
  const schedulingTask = asRecord(asRecord(dreamer?.tasks)?.[args.task]);
145
153
  if (!harnessBlock) {
@@ -211,6 +219,7 @@ export function resolveOpenCodeAgentOverrides(agent: unknown): Record<string, un
211
219
  thinking_level: _thinking,
212
220
  opencode,
213
221
  pi,
222
+ omp,
214
223
  tasks,
215
224
  ...rest
216
225
  } = source;
@@ -2,7 +2,6 @@ import { existsSync, readFileSync, statSync } from "node:fs";
2
2
  import { dirname, isAbsolute, resolve } from "node:path";
3
3
 
4
4
  import {
5
- type ConfigHarness,
6
5
  cortexKitUserConfigBasePath,
7
6
  resolveLegacyConfigSourcesForHarness,
8
7
  } from "../config/migrate-config-location";
@@ -13,6 +12,7 @@ import {
13
12
  CTX_REDUCE_LIGHT_DESCRIPTION,
14
13
  CTX_SEARCH_LIGHT_DESCRIPTION,
15
14
  } from "../tools/light-descriptions";
15
+ import type { HarnessId } from "./harness";
16
16
  import { piModelRefToCanonical } from "./harness-provider-map";
17
17
  import { detectConfigFile } from "./jsonc-parser";
18
18
  import {
@@ -88,7 +88,7 @@ export interface PromptSurfaceRuntime {
88
88
  }
89
89
 
90
90
  export interface CreatePromptSurfaceRuntimeOptions {
91
- harness?: ConfigHarness;
91
+ harness?: HarnessId;
92
92
  directory?: string;
93
93
  /** Explicit test/integration seam; production derives the USER config directory. */
94
94
  userConfigDirectory?: string;
@@ -105,7 +105,7 @@ function resolveUserConfigDirectory(options: CreatePromptSurfaceRuntimeOptions):
105
105
  if (options.harness) {
106
106
  const legacy = resolveLegacyConfigSourcesForHarness(
107
107
  options.directory ?? process.cwd(),
108
- options.harness,
108
+ options.harness === "omp" ? "pi" : options.harness,
109
109
  ).user.find((source) => existsSync(source.path));
110
110
  if (legacy) return dirname(legacy.path);
111
111
  }
@@ -62,6 +62,7 @@ import {
62
62
  byteSize,
63
63
  prependTag,
64
64
  stripTagPrefix,
65
+ stripWellFormedLeadingTagPrefix,
65
66
  } from "../hooks/magic-context/tag-content-primitives";
66
67
  import type { TagTarget } from "../hooks/magic-context/tag-messages";
67
68
  import type { Transcript, TranscriptPart } from "./transcript";
@@ -814,6 +815,16 @@ interface TagTextPartArgs {
814
815
  function tagTextPart(args: TagTextPartArgs): void {
815
816
  const identityStart = args.timing ? performance.now() : 0;
816
817
  const text = args.part.getText() ?? "";
818
+ // Pi and OMP can expose provider framing as assistant text blocks. Treat a
819
+ // previously prefixed blank as blank too, so MC never turns inert framing
820
+ // into a tag-bearing part that later strip logic could mistake for content.
821
+ if (
822
+ args.message.info.role === "assistant" &&
823
+ stripWellFormedLeadingTagPrefix(text).trim().length === 0
824
+ ) {
825
+ if (args.timing) args.timing.identity += performance.now() - identityStart;
826
+ return;
827
+ }
817
828
  const contentId = args.contentId;
818
829
  const reusableTagId = args.reuseIdentity
819
830
  ? args.tagger.getTag(args.sessionId, contentId, "message")
@@ -1,3 +1,5 @@
1
+ import type { HarnessId } from "./harness";
2
+
1
3
  /**
2
4
  * Harness-agnostic transcript interface.
3
5
  *
@@ -229,7 +231,7 @@ export interface Transcript {
229
231
  * compaction marker injection).
230
232
  * - Test assertions confirming the right adapter ran.
231
233
  */
232
- readonly harness: "opencode" | "pi";
234
+ readonly harness: HarnessId;
233
235
 
234
236
  /**
235
237
  * Commit accumulated mutations to the underlying source array.
@@ -1,18 +0,0 @@
1
- import {
2
- ANNOUNCEMENT_FEATURES,
3
- ANNOUNCEMENT_FOOTER,
4
- ANNOUNCEMENT_VERSION,
5
- markAnnouncementSeen,
6
- readLastAnnouncedVersion,
7
- shouldShowAnnouncement
8
- } from "./index-dmvy29z0.js";
9
- import"./index-37yzyeca.js";
10
- import"./index-1yh8g550.js";
11
- export {
12
- ANNOUNCEMENT_FEATURES,
13
- ANNOUNCEMENT_FOOTER,
14
- ANNOUNCEMENT_VERSION,
15
- markAnnouncementSeen,
16
- readLastAnnouncedVersion,
17
- shouldShowAnnouncement
18
- };
@@ -1,17 +0,0 @@
1
- import {
2
- cleanupConflictWarnings,
3
- sendConflictWarning,
4
- sendSchemaFenceWarning,
5
- sendStartupAnnouncement
6
- } from "./index-eq9wr75c.js";
7
- import"./index-8mtsfhyg.js";
8
- import"./index-vnz6jvdc.js";
9
- import"./index-4x691bz5.js";
10
- import"./index-37yzyeca.js";
11
- import"./index-1yh8g550.js";
12
- export {
13
- cleanupConflictWarnings,
14
- sendConflictWarning,
15
- sendSchemaFenceWarning,
16
- sendStartupAnnouncement
17
- };