oh-my-codex 0.21.24 → 0.21.25

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.
package/Cargo.lock CHANGED
@@ -32,7 +32,7 @@ checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
32
32
 
33
33
  [[package]]
34
34
  name = "omx-api"
35
- version = "0.21.24"
35
+ version = "0.21.25"
36
36
  dependencies = [
37
37
  "serde",
38
38
  "serde_json",
@@ -40,14 +40,14 @@ dependencies = [
40
40
 
41
41
  [[package]]
42
42
  name = "omx-explore-harness"
43
- version = "0.21.24"
43
+ version = "0.21.25"
44
44
  dependencies = [
45
45
  "libc",
46
46
  ]
47
47
 
48
48
  [[package]]
49
49
  name = "omx-mux"
50
- version = "0.21.24"
50
+ version = "0.21.25"
51
51
  dependencies = [
52
52
  "serde",
53
53
  "serde_json",
@@ -55,7 +55,7 @@ dependencies = [
55
55
 
56
56
  [[package]]
57
57
  name = "omx-runtime"
58
- version = "0.21.24"
58
+ version = "0.21.25"
59
59
  dependencies = [
60
60
  "fs2",
61
61
  "libc",
@@ -67,7 +67,7 @@ dependencies = [
67
67
 
68
68
  [[package]]
69
69
  name = "omx-runtime-core"
70
- version = "0.21.24"
70
+ version = "0.21.25"
71
71
  dependencies = [
72
72
  "fs2",
73
73
  "serde",
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "omx-sparkshell"
79
- version = "0.21.24"
79
+ version = "0.21.25"
80
80
  dependencies = [
81
81
  "omx-mux",
82
82
  ]
package/Cargo.toml CHANGED
@@ -11,7 +11,7 @@ resolver = "2"
11
11
 
12
12
  [workspace.package]
13
13
 
14
- version = "0.21.24"
14
+ version = "0.21.25"
15
15
 
16
16
  edition = "2021"
17
17
  rust-version = "1.73"
@@ -2619,6 +2619,166 @@ exit 1
2619
2619
  await rm(cwd, { recursive: true, force: true });
2620
2620
  }
2621
2621
  });
2622
+ it('rejects mailbox creation failures without publishing a successful fallback', async () => {
2623
+ const cwd = await mkdtemp(join(tmpdir(), 'omx-mailbox-create-failure-'));
2624
+ const previousBinary = process.env.OMX_RUNTIME_BINARY;
2625
+ const previousBridge = process.env.OMX_RUNTIME_BRIDGE;
2626
+ try {
2627
+ const runtime = join(cwd, 'runtime');
2628
+ process.env.OMX_RUNTIME_BINARY = runtime;
2629
+ process.env.OMX_RUNTIME_BRIDGE = '1';
2630
+ await initTeamState('alpha', 'task', 'executor', 1, cwd);
2631
+ for (const failure of [
2632
+ "process.stderr.write('failed to load authoritative runtime state'); process.exit(1);",
2633
+ "process.stdout.write('truncated response'); process.exit(0);",
2634
+ "process.stdout.write('{}'); process.exit(0);",
2635
+ "process.stdout.write('null'); process.exit(0);",
2636
+ "process.stdout.write('[]'); process.exit(0);",
2637
+ "process.stdout.write(JSON.stringify({event:'SnapshotCaptured'})); process.exit(0);",
2638
+ "process.stdout.write(JSON.stringify({event:'MailboxMessageCreated',message_id:'wrong-id',from_worker:command.from_worker,to_worker:command.to_worker})); process.exit(0);",
2639
+ "process.stdout.write(JSON.stringify({event:'MailboxMessageCreated',message_id:command.message_id,from_worker:'other',to_worker:command.to_worker})); process.exit(0);",
2640
+ "process.stdout.write(JSON.stringify({event:'MailboxMessageCreated',message_id:command.message_id,from_worker:command.from_worker,to_worker:'other'})); process.exit(0);",
2641
+ "process.stdout.write(JSON.stringify({event:'MailboxMessageCreated',message_id:command.message_id,from_worker:command.from_worker,to_worker:command.to_worker,team_name:'other'})); process.exit(0);",
2642
+ "process.stdout.write(JSON.stringify({event:'MailboxMessageCreated',message_id:command.message_id,from_worker:command.from_worker,to_worker:command.to_worker,body:'other'})); process.exit(0);",
2643
+ ]) {
2644
+ await writeCompatRuntimeFixture(runtime, join(cwd, 'runtime.log'));
2645
+ const fixture = await readFile(runtime, 'utf8');
2646
+ await writeFile(runtime, fixture.replace("const dir = stateDir();", `if (command.command === 'CreateMailboxMessage') { ${failure} }\nconst dir = stateDir();`));
2647
+ await assert.rejects(() => sendDirectMessage('alpha', 'leader-fixed', 'worker-1', failure, cwd), /failed to load authoritative runtime state|non-JSON output|invalid mailbox creation acknowledgement/);
2648
+ assert.deepEqual(await listMailboxMessages('alpha', 'worker-1', cwd), []);
2649
+ const shadow = JSON.parse(await readFile(join(cwd, '.omx/state/team/alpha/mailbox/worker-1.json'), 'utf8'));
2650
+ assert.deepEqual(shadow.messages, []);
2651
+ assert.doesNotMatch(await readFile(join(cwd, '.omx/state/team/alpha/events/events.ndjson'), 'utf8').catch(() => ''), /message_received/);
2652
+ }
2653
+ process.env.OMX_RUNTIME_BINARY = join(cwd, 'missing-runtime');
2654
+ const fallback = await sendDirectMessage('alpha', 'leader-fixed', 'worker-1', 'offline fallback', cwd);
2655
+ assert.equal((await listMailboxMessages('alpha', 'worker-1', cwd))[0]?.message_id, fallback.message_id);
2656
+ process.env.OMX_RUNTIME_BINARY = runtime;
2657
+ await writeCompatRuntimeFixture(runtime, join(cwd, 'runtime.log'));
2658
+ const native = await sendDirectMessage('alpha', 'leader-fixed', 'worker-1', 'runtime restored', cwd);
2659
+ assert.ok((await listMailboxMessages('alpha', 'worker-1', cwd)).some((message) => message.message_id === native.message_id));
2660
+ }
2661
+ finally {
2662
+ if (previousBinary === undefined)
2663
+ delete process.env.OMX_RUNTIME_BINARY;
2664
+ else
2665
+ process.env.OMX_RUNTIME_BINARY = previousBinary;
2666
+ if (previousBridge === undefined)
2667
+ delete process.env.OMX_RUNTIME_BRIDGE;
2668
+ else
2669
+ process.env.OMX_RUNTIME_BRIDGE = previousBridge;
2670
+ await rm(cwd, { recursive: true, force: true });
2671
+ }
2672
+ });
2673
+ it('recovers a partially persisted mailbox creation before allowing a retry', async () => {
2674
+ const cwd = await mkdtemp(join(tmpdir(), 'omx-mailbox-partial-persist-'));
2675
+ const keys = ['OMX_RUNTIME_BINARY', 'OMX_RUNTIME_BRIDGE', 'OMX_TEST_MATERIALIZE_MAILBOX_ON_CAPTURE'];
2676
+ const previous = Object.fromEntries(keys.map(key => [key, process.env[key]]));
2677
+ try {
2678
+ const runtime = join(cwd, 'runtime');
2679
+ const log = join(cwd, 'runtime.log');
2680
+ process.env.OMX_RUNTIME_BINARY = runtime;
2681
+ process.env.OMX_RUNTIME_BRIDGE = '1';
2682
+ process.env.OMX_TEST_MATERIALIZE_MAILBOX_ON_CAPTURE = '1';
2683
+ await initTeamState('alpha', 'task', 'executor', 1, cwd);
2684
+ await writeCompatRuntimeFixture(runtime, log);
2685
+ const fixture = await readFile(runtime, 'utf8');
2686
+ await writeFile(runtime, fixture.replace(" case 'CreateMailboxMessage': {", ` case 'CreateMailboxMessage': {
2687
+ writeJson(path.join(dir, 'events.json'), [{ ...command, event: 'MailboxMessageCreated' }]);
2688
+ process.stderr.write('persist failed: mailbox snapshot is read-only'); process.exit(1);`));
2689
+ const send = () => sendDirectMessage('alpha', 'leader-fixed', 'worker-1', 'partial creation', cwd);
2690
+ await assert.rejects(send, /persist failed/);
2691
+ const stateDir = join(cwd, '.omx/state');
2692
+ const eventsPath = join(stateDir, 'events.json');
2693
+ const committed = await readFile(eventsPath, 'utf8');
2694
+ const originalId = JSON.parse(committed)[0].message_id;
2695
+ assert.deepEqual(await listMailboxMessages('alpha', 'worker-1', cwd), []);
2696
+ await writeFile(join(stateDir, 'mailbox.json'), JSON.stringify({ records: [] }));
2697
+ for (const response of [
2698
+ "process.stderr.write('recovery unavailable'); process.exit(1);",
2699
+ "process.stdout.write('{}'); process.exit(0);",
2700
+ "process.stdout.write(JSON.stringify({event:'SnapshotCaptured'})); process.exit(0);",
2701
+ ]) {
2702
+ await writeFile(runtime, fixture.replace(" case 'CaptureSnapshot': {", ` case 'CaptureSnapshot': { ${response}`));
2703
+ await assert.rejects(send, /recovery unavailable|mailbox creation recovery/);
2704
+ assert.equal(await readFile(eventsPath, 'utf8'), committed);
2705
+ }
2706
+ process.env.OMX_RUNTIME_BINARY = join(cwd, 'missing-runtime');
2707
+ await assert.rejects(send, /omx-runtime/);
2708
+ process.env.OMX_RUNTIME_BINARY = runtime;
2709
+ await writeFile(eventsPath, '{}');
2710
+ await assert.rejects(send, /invalid runtime mailbox event log/);
2711
+ await writeFile(eventsPath, committed);
2712
+ await writeFile(runtime, fixture);
2713
+ const retried = await Promise.all(Array.from({ length: 4 }, send));
2714
+ assert.ok(retried.every(message => message.message_id === originalId));
2715
+ assert.equal((await listMailboxMessages('alpha', 'worker-1', cwd)).length, 1);
2716
+ assert.equal(await readFile(eventsPath, 'utf8'), committed);
2717
+ assert.equal((await readFile(log, 'utf8')).split('"command":"CreateMailboxMessage"').length - 1, 1);
2718
+ assert.equal(await markMessageDelivered('alpha', 'worker-1', originalId, cwd), true);
2719
+ process.env.OMX_RUNTIME_BINARY = join(cwd, 'missing-runtime');
2720
+ const offline = await send();
2721
+ assert.notEqual(offline.message_id, originalId, 'a confirmed delivered message must not block normal offline fallback');
2722
+ assert.ok((await listMailboxMessages('alpha', 'worker-1', cwd)).some(message => message.message_id === offline.message_id));
2723
+ }
2724
+ finally {
2725
+ for (const key of keys) {
2726
+ if (previous[key] === undefined)
2727
+ delete process.env[key];
2728
+ else
2729
+ process.env[key] = previous[key];
2730
+ }
2731
+ await rm(cwd, { recursive: true, force: true });
2732
+ }
2733
+ });
2734
+ it('deduplicates against the verified projection when another reader refreshes it', async () => {
2735
+ const cwd = await mkdtemp(join(tmpdir(), 'omx-mailbox-refresh-race-'));
2736
+ const previousBinary = process.env.OMX_RUNTIME_BINARY;
2737
+ const previousBridge = process.env.OMX_RUNTIME_BRIDGE;
2738
+ try {
2739
+ process.env.OMX_RUNTIME_BINARY = join(cwd, 'missing-runtime');
2740
+ process.env.OMX_RUNTIME_BRIDGE = '1';
2741
+ const stateDir = join(cwd, '.omx/state');
2742
+ await mkdir(stateDir, { recursive: true });
2743
+ const message = {
2744
+ message_id: 'committed', from_worker: 'leader-fixed', to_worker: 'worker-1',
2745
+ body: 'retry', created_at: new Date().toISOString(),
2746
+ };
2747
+ await writeFile(join(stateDir, 'events.json'), JSON.stringify([{
2748
+ ...message, event: 'MailboxMessageCreated', team_name: 'alpha',
2749
+ }]));
2750
+ let reads = 0;
2751
+ const result = await sendDirectMessageWithDeps('leader-fixed', 'worker-1', 'retry', {
2752
+ teamName: 'alpha', cwd,
2753
+ withMailboxLock: async (_team, _worker, _cwd, fn) => await fn(),
2754
+ readMailbox: async () => {
2755
+ assert.equal(++reads, 1, 'deduplication must use the same projection that was verified');
2756
+ await writeFile(join(stateDir, 'mailbox.json'), JSON.stringify({ records: [{
2757
+ ...message, team_name: 'foreign', message_id: 'foreign', notified_at: null, delivered_at: null,
2758
+ }, {
2759
+ ...message, team_name: 'alpha', notified_at: null, delivered_at: null,
2760
+ }] }));
2761
+ return { worker: 'worker-1', messages: [] };
2762
+ },
2763
+ readLegacyMailbox: async () => ({ worker: 'worker-1', messages: [] }),
2764
+ writeMailbox: async () => assert.fail('must not create a second provisional message'),
2765
+ appendTeamEvent: async () => assert.fail('must not publish a second creation'),
2766
+ readTeamConfig: async () => null,
2767
+ });
2768
+ assert.equal(result.message_id, message.message_id);
2769
+ }
2770
+ finally {
2771
+ if (previousBinary === undefined)
2772
+ delete process.env.OMX_RUNTIME_BINARY;
2773
+ else
2774
+ process.env.OMX_RUNTIME_BINARY = previousBinary;
2775
+ if (previousBridge === undefined)
2776
+ delete process.env.OMX_RUNTIME_BRIDGE;
2777
+ else
2778
+ process.env.OMX_RUNTIME_BRIDGE = previousBridge;
2779
+ await rm(cwd, { recursive: true, force: true });
2780
+ }
2781
+ });
2622
2782
  it('rejects QueueDispatch schema failures without polluting existing runtime state', async () => {
2623
2783
  const cwd = await mkdtemp(join(tmpdir(), 'omx-queue-schema-'));
2624
2784
  const previousBinary = process.env.OMX_RUNTIME_BINARY;