oh-my-codex 0.21.7 → 0.21.9

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 (99) hide show
  1. package/Cargo.lock +8 -8
  2. package/Cargo.toml +1 -1
  3. package/README.md +28 -0
  4. package/dist/cli/__tests__/doctor-state-root-binding.test.js +17 -2
  5. package/dist/cli/__tests__/doctor-state-root-binding.test.js.map +1 -1
  6. package/dist/cli/__tests__/native-assets.test.js +1 -1
  7. package/dist/cli/__tests__/native-assets.test.js.map +1 -1
  8. package/dist/cli/__tests__/session-export.test.d.ts +2 -0
  9. package/dist/cli/__tests__/session-export.test.d.ts.map +1 -0
  10. package/dist/cli/__tests__/session-export.test.js +166 -0
  11. package/dist/cli/__tests__/session-export.test.js.map +1 -0
  12. package/dist/cli/__tests__/session-usage.test.d.ts +2 -0
  13. package/dist/cli/__tests__/session-usage.test.d.ts.map +1 -0
  14. package/dist/cli/__tests__/session-usage.test.js +88 -0
  15. package/dist/cli/__tests__/session-usage.test.js.map +1 -0
  16. package/dist/cli/doctor.js +1 -1
  17. package/dist/cli/doctor.js.map +1 -1
  18. package/dist/cli/index.d.ts +1 -1
  19. package/dist/cli/index.d.ts.map +1 -1
  20. package/dist/cli/index.js +1 -0
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/session-export.d.ts +9 -0
  23. package/dist/cli/session-export.d.ts.map +1 -0
  24. package/dist/cli/session-export.js +76 -0
  25. package/dist/cli/session-export.js.map +1 -0
  26. package/dist/cli/session-search.d.ts.map +1 -1
  27. package/dist/cli/session-search.js +14 -0
  28. package/dist/cli/session-search.js.map +1 -1
  29. package/dist/cli/session-usage.d.ts +8 -0
  30. package/dist/cli/session-usage.d.ts.map +1 -0
  31. package/dist/cli/session-usage.js +100 -0
  32. package/dist/cli/session-usage.js.map +1 -0
  33. package/dist/evals/astra-defaults/__tests__/collector.test.d.ts +2 -0
  34. package/dist/evals/astra-defaults/__tests__/collector.test.d.ts.map +1 -0
  35. package/dist/evals/astra-defaults/__tests__/collector.test.js +139 -0
  36. package/dist/evals/astra-defaults/__tests__/collector.test.js.map +1 -0
  37. package/dist/evals/astra-defaults/collector.d.ts +31 -0
  38. package/dist/evals/astra-defaults/collector.d.ts.map +1 -0
  39. package/dist/evals/astra-defaults/collector.js +215 -0
  40. package/dist/evals/astra-defaults/collector.js.map +1 -0
  41. package/dist/native-assets/archive.js +2 -2
  42. package/dist/native-assets/archive.js.map +1 -1
  43. package/dist/runtime/__tests__/bridge.test.js +79 -0
  44. package/dist/runtime/__tests__/bridge.test.js.map +1 -1
  45. package/dist/runtime/bridge.d.ts +1 -0
  46. package/dist/runtime/bridge.d.ts.map +1 -1
  47. package/dist/runtime/bridge.js +17 -4
  48. package/dist/runtime/bridge.js.map +1 -1
  49. package/dist/scripts/__tests__/codex-native-hook.test.js +129 -0
  50. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  51. package/dist/scripts/__tests__/ralplan-advisory-hook.test.js +39 -0
  52. package/dist/scripts/__tests__/ralplan-advisory-hook.test.js.map +1 -1
  53. package/dist/scripts/__tests__/verify-native-release-assets.test.js +1 -1
  54. package/dist/scripts/__tests__/verify-native-release-assets.test.js.map +1 -1
  55. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  56. package/dist/scripts/codex-native-hook.js +37 -4
  57. package/dist/scripts/codex-native-hook.js.map +1 -1
  58. package/dist/scripts/eval/collect-astra-defaults.d.ts +2 -0
  59. package/dist/scripts/eval/collect-astra-defaults.d.ts.map +1 -0
  60. package/dist/scripts/eval/collect-astra-defaults.js +89 -0
  61. package/dist/scripts/eval/collect-astra-defaults.js.map +1 -0
  62. package/dist/session-history/__tests__/export.test.d.ts +2 -0
  63. package/dist/session-history/__tests__/export.test.d.ts.map +1 -0
  64. package/dist/session-history/__tests__/export.test.js +225 -0
  65. package/dist/session-history/__tests__/export.test.js.map +1 -0
  66. package/dist/session-history/__tests__/usage.test.d.ts +2 -0
  67. package/dist/session-history/__tests__/usage.test.d.ts.map +1 -0
  68. package/dist/session-history/__tests__/usage.test.js +216 -0
  69. package/dist/session-history/__tests__/usage.test.js.map +1 -0
  70. package/dist/session-history/export.d.ts +31 -0
  71. package/dist/session-history/export.d.ts.map +1 -0
  72. package/dist/session-history/export.js +225 -0
  73. package/dist/session-history/export.js.map +1 -0
  74. package/dist/session-history/search.d.ts +1 -0
  75. package/dist/session-history/search.d.ts.map +1 -1
  76. package/dist/session-history/search.js +6 -2
  77. package/dist/session-history/search.js.map +1 -1
  78. package/dist/session-history/usage.d.ts +44 -0
  79. package/dist/session-history/usage.d.ts.map +1 -0
  80. package/dist/session-history/usage.js +211 -0
  81. package/dist/session-history/usage.js.map +1 -0
  82. package/dist/team/__tests__/state.test.js +33 -0
  83. package/dist/team/__tests__/state.test.js.map +1 -1
  84. package/dist/team/__tests__/worker-bootstrap.test.js +100 -1
  85. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  86. package/dist/team/state.d.ts.map +1 -1
  87. package/dist/team/state.js +3 -2
  88. package/dist/team/state.js.map +1 -1
  89. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  90. package/dist/team/worker-bootstrap.js +74 -18
  91. package/dist/team/worker-bootstrap.js.map +1 -1
  92. package/dist/verification/__tests__/native-release-manifest.test.js.map +1 -1
  93. package/package.json +3 -3
  94. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  95. package/src/scripts/__tests__/codex-native-hook.test.ts +182 -0
  96. package/src/scripts/__tests__/ralplan-advisory-hook.test.ts +40 -0
  97. package/src/scripts/__tests__/verify-native-release-assets.test.ts +3 -3
  98. package/src/scripts/codex-native-hook.ts +37 -3
  99. package/src/scripts/eval/collect-astra-defaults.ts +140 -0
@@ -23,6 +23,7 @@ import { getLegacyWikiDir, serializePage, writePage, } from "../../wiki/storage.
23
23
  import { WIKI_SCHEMA_VERSION } from "../../wiki/types.js";
24
24
  import { createUltragoalPlan, readUltragoalPlan, } from "../../ultragoal/artifacts.js";
25
25
  import { getBaseStateDir } from "../../state/paths.js";
26
+ import { recordNativeSubagentAuthorityObservation } from "../../subagents/tracker.js";
26
27
  import { maybeNudgeLeaderForAllowedWorkerStop } from "../notify-hook/team-worker-stop.js";
27
28
  import { MAX_NATIVE_STDIN_JSON_BYTES } from "../hook-payload-guard.js";
28
29
  import { injectExecFollowup, readPendingExecFollowups, } from "../../exec/followup.js";
@@ -911,6 +912,134 @@ describe("codex native hook dispatch", { concurrency: false }, () => {
911
912
  await rm(cwd, { recursive: true, force: true });
912
913
  }
913
914
  });
915
+ it("records bounded completion evidence for native subagent Stop events (#3729)", async () => {
916
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-completion-evidence-"));
917
+ try {
918
+ const stateDir = join(cwd, ".omx", "state");
919
+ const sessionId = "sess-stop-subagent";
920
+ const threadId = "thread-stop-subagent";
921
+ const leaderThreadId = "leader-thread";
922
+ await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
923
+ await writeSessionStart(cwd, sessionId, { nativeSessionId: leaderThreadId, pid: process.pid });
924
+ // Create transcript with thread_spawn metadata to make dispatcher detect as subagent
925
+ const stopTranscriptPath = join(cwd, "stop-transcript.jsonl");
926
+ await writeFile(stopTranscriptPath, JSON.stringify({
927
+ type: "session_meta",
928
+ payload: { id: threadId, source: { subagent: { thread_spawn: { parent_thread_id: leaderThreadId } } } }
929
+ }) + "\n");
930
+ // Initialize subagent tracking by recording the native subagent observation
931
+ await recordNativeSubagentAuthorityObservation(cwd, {
932
+ sessionIds: [sessionId],
933
+ childThreadId: threadId,
934
+ parentThreadId: leaderThreadId,
935
+ rootNativeSessionId: leaderThreadId,
936
+ authorityEvidence: "valid",
937
+ });
938
+ // Send Stop event from subagent thread
939
+ const result = await dispatchCodexNativeHook({
940
+ hook_event_name: "Stop",
941
+ cwd,
942
+ session_id: sessionId,
943
+ thread_id: threadId,
944
+ stop_hook_active: true,
945
+ }, { cwd, sessionOwnerPid: process.pid });
946
+ // Verify completion evidence was recorded
947
+ const tracking = JSON.parse(await readFile(join(stateDir, "subagent-tracking.json"), "utf-8"));
948
+ const thread = tracking.sessions?.[sessionId]?.threads?.[threadId];
949
+ assert.ok(thread?.completed_at, "completion evidence must record completed_at timestamp");
950
+ assert.equal(thread?.completion_source, "native_stop_event", "completion evidence must mark completionSource as native_stop_event");
951
+ }
952
+ finally {
953
+ await rm(cwd, { recursive: true, force: true });
954
+ }
955
+ });
956
+ it("records bounded delivery evidence for native subagent SessionStart events (#3729)", async () => {
957
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-sessionstart-delivery-evidence-"));
958
+ try {
959
+ const stateDir = join(cwd, ".omx", "state");
960
+ const sessionId = "sess-sessionstart-subagent";
961
+ const threadId = "thread-sessionstart-subagent";
962
+ const leaderThreadId = "leader-thread";
963
+ await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
964
+ await writeSessionStart(cwd, sessionId, { nativeSessionId: leaderThreadId, pid: process.pid });
965
+ // Create transcript with thread_spawn metadata to make dispatcher detect as subagent
966
+ const transcriptPath = join(cwd, "sessionstart-transcript.jsonl");
967
+ await writeFile(transcriptPath, JSON.stringify({
968
+ type: "session_meta",
969
+ payload: { id: threadId, source: { subagent: { thread_spawn: { parent_thread_id: leaderThreadId } } } }
970
+ }) + "\n");
971
+ // Send SessionStart event from subagent thread
972
+ // Note: session_id should be the child's thread ID, thread_id is required for evidence recording
973
+ const result = await dispatchCodexNativeHook({
974
+ hook_event_name: "SessionStart",
975
+ cwd,
976
+ session_id: threadId,
977
+ thread_id: threadId,
978
+ transcript_path: transcriptPath,
979
+ }, { cwd, sessionOwnerPid: process.pid });
980
+ // Verify delivery evidence was recorded (without completion_source)
981
+ // Note: Sessions are keyed by canonical session ID in tracking state
982
+ const canonicalFromPointer = JSON.parse(await readFile(join(stateDir, "session.json"), "utf-8"));
983
+ const canonicalSessionIdResult = canonicalFromPointer.session_id || sessionId;
984
+ const tracking = JSON.parse(await readFile(join(stateDir, "subagent-tracking.json"), "utf-8"));
985
+ const thread = tracking.sessions?.[canonicalSessionIdResult]?.threads?.[threadId];
986
+ assert.ok(thread, "thread should exist in tracking");
987
+ // SessionStart should record the turn (turn_count should be incremented to 1)
988
+ assert.equal(thread?.turn_count, 1, "SessionStart must record the turn (turn_count should be 1)");
989
+ // SessionStart should NOT set completed_at
990
+ assert.ok(!thread?.completed_at, "SessionStart must not set completed_at timestamp");
991
+ // SessionStart should NOT set completion_source
992
+ assert.ok(!thread?.completion_source, "SessionStart must not set completion_source");
993
+ }
994
+ finally {
995
+ await rm(cwd, { recursive: true, force: true });
996
+ }
997
+ });
998
+ it("does NOT record completion evidence for leader Stop events (#3729)", async () => {
999
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-leader-no-record-"));
1000
+ try {
1001
+ const stateDir = join(cwd, ".omx", "state");
1002
+ const sessionId = "sess-stop-leader";
1003
+ const leaderThreadId = "leader-thread-stop";
1004
+ await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
1005
+ // Initialize subagent tracking with only leader thread BEFORE writeSessionStart
1006
+ await writeJson(join(stateDir, "subagent-tracking.json"), {
1007
+ schemaVersion: 1,
1008
+ sessions: {
1009
+ [sessionId]: {
1010
+ session_id: sessionId,
1011
+ leader_thread_id: leaderThreadId,
1012
+ updated_at: new Date().toISOString(),
1013
+ threads: {
1014
+ [leaderThreadId]: {
1015
+ thread_id: leaderThreadId,
1016
+ kind: "leader",
1017
+ status: "available",
1018
+ first_seen_at: new Date().toISOString(),
1019
+ last_seen_at: new Date().toISOString(),
1020
+ },
1021
+ },
1022
+ },
1023
+ },
1024
+ });
1025
+ // Send Stop event from leader thread
1026
+ const result = await dispatchCodexNativeHook({
1027
+ hook_event_name: "Stop",
1028
+ cwd,
1029
+ session_id: sessionId,
1030
+ thread_id: leaderThreadId,
1031
+ stop_hook_active: true,
1032
+ }, { cwd });
1033
+ // Verify NO completion evidence was recorded for leader
1034
+ const tracking = JSON.parse(await readFile(join(stateDir, "subagent-tracking.json"), "utf-8"));
1035
+ const thread = tracking.sessions?.[sessionId]?.threads?.[leaderThreadId];
1036
+ assert.ok(!thread?.completed_at, "leader Stop must not record completed_at timestamp");
1037
+ assert.ok(!thread?.completion_source, "leader Stop must not record completion_source");
1038
+ }
1039
+ finally {
1040
+ await rm(cwd, { recursive: true, force: true });
1041
+ }
1042
+ });
914
1043
  it("emits no-op JSON for oversized Stop stdin without parsing or creating inactive state", async () => {
915
1044
  const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-cli-stop-oversized-"));
916
1045
  try {