open-research-protocol 0.4.29 → 0.4.30

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/CHANGELOG.md CHANGED
@@ -6,6 +6,19 @@ There was no prior in-repo changelog file, so the first formal entry starts
6
6
  with the currently shipped `v0.4.4` release and summarizes the full release
7
7
  delta reflected in this repo.
8
8
 
9
+ ## v0.4.30 - 2026-04-25
10
+
11
+ This release tightens ORP-managed Codex session tracking so short-lived
12
+ `codex exec` runs, including Clawdad summary and planning work, do not replace
13
+ the saved interactive workspace thread.
14
+
15
+ ### Changed
16
+
17
+ - `orp codex status` and `orp codex reconcile` now ignore local Codex exec
18
+ sessions by default, alongside the existing delegated/subagent filtering.
19
+ - Added `--include-exec` to the ORP/Codex status and reconcile flows for
20
+ explicit diagnostics when exec sessions need to be inspected.
21
+
9
22
  ## v0.4.29 - 2026-04-25
10
23
 
11
24
  This release adds ORP-managed Codex session tracking so starting a Codex thread
package/README.md CHANGED
@@ -473,10 +473,11 @@ orp schedule add codex --name morning-summary --prompt "Summarize this repo" --j
473
473
  aligned with Codex sessions. `status` compares the current repo against the
474
474
  latest local Codex session metadata, `reconcile` refreshes stale saved sessions,
475
475
  and bare `orp codex` launches Codex from the repo root while watching for the new
476
- session id. Delegated/subagent sessions are ignored by default, and
477
- artifact-output repos should be left untracked when a separate lab repo is the
478
- source of truth. Use `--` before Codex args that conflict with ORP wrapper
479
- options. The manual fallback from inside Codex is still:
476
+ session id. Codex exec and delegated/subagent sessions are ignored by default,
477
+ and artifact-output repos should be left untracked when a separate lab repo is
478
+ the source of truth. Use `--include-exec` only when diagnosing short-lived exec
479
+ sessions, and use `--` before Codex args that conflict with ORP wrapper options.
480
+ The manual fallback from inside Codex is still:
480
481
 
481
482
  ```bash
482
483
  orp workspace add-tab main --here --current-codex
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-research-protocol",
3
- "version": "0.4.29",
3
+ "version": "0.4.30",
4
4
  "description": "ORP CLI (Open Research Protocol): workspace ledgers, secrets, scheduling, governed execution, and agent-friendly research workflows.",
5
5
  "license": "MIT",
6
6
  "author": "Fractal Research Group <cody@frg.earth>",
@@ -77,6 +77,22 @@ export function isDelegatedCodexSession(session) {
77
77
  return sourceText.includes("subagent") || sourceText.includes("delegate");
78
78
  }
79
79
 
80
+ export function isCodexExecSession(session) {
81
+ const originator = normalizeOptionalString(session?.originator)?.toLowerCase();
82
+ if (originator === "codex_exec" || originator === "codex-exec") {
83
+ return true;
84
+ }
85
+ const source = session?.source;
86
+ if (typeof source === "string") {
87
+ return source.trim().toLowerCase() === "exec";
88
+ }
89
+ if (!source || typeof source !== "object" || Array.isArray(source)) {
90
+ return false;
91
+ }
92
+ const sourceKind = normalizeOptionalString(source.kind ?? source.type ?? source.source)?.toLowerCase();
93
+ return sourceKind === "exec";
94
+ }
95
+
80
96
  export function parseCodexSessionMetaLine(line, filePath, stat = {}) {
81
97
  let row;
82
98
  try {
@@ -97,6 +113,12 @@ export function parseCodexSessionMetaLine(line, filePath, stat = {}) {
97
113
 
98
114
  const timestamp = normalizeOptionalString(payload.timestamp) || normalizeOptionalString(row.timestamp);
99
115
  const timestampMs = timestamp ? Date.parse(timestamp) : 0;
116
+ const source =
117
+ typeof payload.source === "string"
118
+ ? normalizeOptionalString(payload.source)
119
+ : payload.source && typeof payload.source === "object" && !Array.isArray(payload.source)
120
+ ? payload.source
121
+ : null;
100
122
  return {
101
123
  sessionId,
102
124
  cwd: path.resolve(cwd),
@@ -106,7 +128,7 @@ export function parseCodexSessionMetaLine(line, filePath, stat = {}) {
106
128
  filePath,
107
129
  originator: normalizeOptionalString(payload.originator),
108
130
  cliVersion: normalizeOptionalString(payload.cli_version ?? payload.cliVersion),
109
- source: payload.source && typeof payload.source === "object" && !Array.isArray(payload.source) ? payload.source : null,
131
+ source,
110
132
  };
111
133
  }
112
134
 
@@ -171,6 +193,7 @@ export async function scanCodexSessions(options = {}) {
171
193
  const sessionsDir = path.join(codexHome, "sessions");
172
194
  const sinceMs = typeof options.sinceMs === "number" ? options.sinceMs : 0;
173
195
  const includeDelegated = Boolean(options.includeDelegated || options.includeSubagents);
196
+ const includeExec = Boolean(options.includeExec || options.includeCodexExec);
174
197
  const files = await walkSessionFiles(sessionsDir, options);
175
198
  const sessions = [];
176
199
 
@@ -192,6 +215,9 @@ export async function scanCodexSessions(options = {}) {
192
215
  if (!session) {
193
216
  continue;
194
217
  }
218
+ if (!includeExec && isCodexExecSession(session)) {
219
+ continue;
220
+ }
195
221
  if (!includeDelegated && isDelegatedCodexSession(session)) {
196
222
  continue;
197
223
  }
@@ -287,6 +313,7 @@ function sessionSummary(session) {
287
313
  updatedAt: session.updatedMs ? new Date(session.updatedMs).toISOString() : null,
288
314
  originator: session.originator || null,
289
315
  cliVersion: session.cliVersion || null,
316
+ source: session.source || null,
290
317
  filePath: session.filePath || null,
291
318
  };
292
319
  }
@@ -563,6 +590,10 @@ function parseCommonOptions(argv = [], defaults = {}, parseOptions = {}) {
563
590
  options.includeDelegated = true;
564
591
  continue;
565
592
  }
593
+ if (arg === "--include-exec") {
594
+ options.includeExec = true;
595
+ continue;
596
+ }
566
597
  if (arg === "--include-artifacts") {
567
598
  options.includeArtifactRepos = true;
568
599
  continue;
@@ -658,6 +689,7 @@ Commands:
658
689
  start Launch Codex in the repo root and save the new session when metadata appears
659
690
 
660
691
  Notes:
692
+ - Codex exec sessions are ignored by default.
661
693
  - Delegated/subagent sessions are ignored by default.
662
694
  - Broad roots and artifact-output repos are refused unless explicitly overridden.
663
695
  - Use -- before Codex args that conflict with ORP wrapper options.
@@ -669,7 +701,7 @@ function printStatusHelp() {
669
701
  console.log(`ORP Codex status
670
702
 
671
703
  Usage:
672
- orp codex status [--workspace main] [--path <repo-or-subdir>] [--codex-home <path>] [--json]
704
+ orp codex status [--workspace main] [--path <repo-or-subdir>] [--codex-home <path>] [--include-exec] [--json]
673
705
  `);
674
706
  }
675
707
 
@@ -677,7 +709,7 @@ function printReconcileHelp() {
677
709
  console.log(`ORP Codex reconcile
678
710
 
679
711
  Usage:
680
- orp codex reconcile [--workspace main] [--dry-run] [--add-missing] [--since-days <n>] [--json]
712
+ orp codex reconcile [--workspace main] [--dry-run] [--add-missing] [--since-days <n>] [--include-exec] [--json]
681
713
  `);
682
714
  }
683
715
 
@@ -129,6 +129,38 @@ test("scanCodexSessions ignores delegated sessions by default", async () => {
129
129
  );
130
130
  });
131
131
 
132
+ test("scanCodexSessions ignores exec sessions by default", async () => {
133
+ const tempDir = await makeTempDir();
134
+ const codexHome = path.join(tempDir, "codex-home");
135
+ const repoRoot = path.join(tempDir, "repo");
136
+ await writeSession(
137
+ codexHome,
138
+ "019dc2cb-d435-7072-bbfd-4ae4280474d1",
139
+ repoRoot,
140
+ "2026-04-25T12:00:00Z",
141
+ );
142
+ await writeSession(
143
+ codexHome,
144
+ "019dc2cb-d435-7072-bbfd-4ae4280474d2",
145
+ repoRoot,
146
+ "2026-04-25T12:01:00Z",
147
+ { originator: "codex_exec", source: "exec" },
148
+ );
149
+
150
+ const defaultSessions = await scanCodexSessions({ codexHome, sinceMs: 0 });
151
+ assert.deepEqual(
152
+ defaultSessions.map((session) => session.sessionId),
153
+ ["019dc2cb-d435-7072-bbfd-4ae4280474d1"],
154
+ );
155
+
156
+ const withExecSessions = await scanCodexSessions({ codexHome, sinceMs: 0, includeExec: true });
157
+ assert.deepEqual(
158
+ withExecSessions.map((session) => session.sessionId),
159
+ ["019dc2cb-d435-7072-bbfd-4ae4280474d2", "019dc2cb-d435-7072-bbfd-4ae4280474d1"],
160
+ );
161
+ assert.equal(withExecSessions[0].source, "exec");
162
+ });
163
+
132
164
  test("scanCodexSessions finds session metadata near the start of a rollout file", async () => {
133
165
  const tempDir = await makeTempDir();
134
166
  const codexHome = path.join(tempDir, "codex-home");