@useorgx/openclaw-plugin 0.4.9 → 0.7.2

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 (224) hide show
  1. package/README.md +77 -11
  2. package/dashboard/dist/assets/6mILZQ2a.js +1 -0
  3. package/dashboard/dist/assets/6mILZQ2a.js.br +0 -0
  4. package/dashboard/dist/assets/6mILZQ2a.js.gz +0 -0
  5. package/dashboard/dist/assets/8dksYiq4.js +2 -0
  6. package/dashboard/dist/assets/8dksYiq4.js.br +0 -0
  7. package/dashboard/dist/assets/8dksYiq4.js.gz +0 -0
  8. package/dashboard/dist/assets/B5zYRHc3.js +1 -0
  9. package/dashboard/dist/assets/B5zYRHc3.js.br +0 -0
  10. package/dashboard/dist/assets/B5zYRHc3.js.gz +0 -0
  11. package/dashboard/dist/assets/B6wPWJ35.js +1 -0
  12. package/dashboard/dist/assets/B6wPWJ35.js.br +0 -0
  13. package/dashboard/dist/assets/B6wPWJ35.js.gz +0 -0
  14. package/dashboard/dist/assets/BJgZIVUQ.js +53 -0
  15. package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
  16. package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
  17. package/dashboard/dist/assets/BWEwjt1W.js +1 -0
  18. package/dashboard/dist/assets/BWEwjt1W.js.br +0 -0
  19. package/dashboard/dist/assets/BWEwjt1W.js.gz +0 -0
  20. package/dashboard/dist/assets/BgOYB78t.js +4 -0
  21. package/dashboard/dist/assets/BgOYB78t.js.br +0 -0
  22. package/dashboard/dist/assets/BgOYB78t.js.gz +0 -0
  23. package/dashboard/dist/assets/BzRbDCAD.css +1 -0
  24. package/dashboard/dist/assets/BzRbDCAD.css.br +0 -0
  25. package/dashboard/dist/assets/BzRbDCAD.css.gz +0 -0
  26. package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
  27. package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
  28. package/dashboard/dist/assets/C8uM3AX8.js +1 -0
  29. package/dashboard/dist/assets/C8uM3AX8.js.br +0 -0
  30. package/dashboard/dist/assets/C8uM3AX8.js.gz +0 -0
  31. package/dashboard/dist/assets/C9jy61eu.js +212 -0
  32. package/dashboard/dist/assets/C9jy61eu.js.br +0 -0
  33. package/dashboard/dist/assets/C9jy61eu.js.gz +0 -0
  34. package/dashboard/dist/assets/CC63EwFD.js +1 -0
  35. package/dashboard/dist/assets/CC63EwFD.js.br +0 -0
  36. package/dashboard/dist/assets/CC63EwFD.js.gz +0 -0
  37. package/dashboard/dist/assets/CL_wXqR7.js +1 -0
  38. package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
  39. package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
  40. package/dashboard/dist/assets/CZaT3ob_.js +1 -0
  41. package/dashboard/dist/assets/CZaT3ob_.js.br +0 -0
  42. package/dashboard/dist/assets/CZaT3ob_.js.gz +0 -0
  43. package/dashboard/dist/assets/CgaottFX.js +1 -0
  44. package/dashboard/dist/assets/CgaottFX.js.br +0 -0
  45. package/dashboard/dist/assets/CgaottFX.js.gz +0 -0
  46. package/dashboard/dist/assets/{CpJsfbXo.js → CxQ08qFN.js} +2 -2
  47. package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
  48. package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
  49. package/dashboard/dist/assets/CzCxAZlW.js +1 -0
  50. package/dashboard/dist/assets/CzCxAZlW.js.br +0 -0
  51. package/dashboard/dist/assets/CzCxAZlW.js.gz +0 -0
  52. package/dashboard/dist/assets/D3iMTYEj.js +1 -0
  53. package/dashboard/dist/assets/D3iMTYEj.js.br +0 -0
  54. package/dashboard/dist/assets/D3iMTYEj.js.gz +0 -0
  55. package/dashboard/dist/assets/D8JNX8kq.js +2 -0
  56. package/dashboard/dist/assets/D8JNX8kq.js.br +0 -0
  57. package/dashboard/dist/assets/D8JNX8kq.js.gz +0 -0
  58. package/dashboard/dist/assets/DnA8dpj6.js +1 -0
  59. package/dashboard/dist/assets/DnA8dpj6.js.br +0 -0
  60. package/dashboard/dist/assets/DnA8dpj6.js.gz +0 -0
  61. package/dashboard/dist/assets/IUexzymk.js +1 -0
  62. package/dashboard/dist/assets/IUexzymk.js.br +0 -0
  63. package/dashboard/dist/assets/IUexzymk.js.gz +0 -0
  64. package/dashboard/dist/assets/cNrhgGc1.js +8 -0
  65. package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
  66. package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
  67. package/dashboard/dist/assets/ic2FaMnh.js +1 -0
  68. package/dashboard/dist/assets/ic2FaMnh.js.br +0 -0
  69. package/dashboard/dist/assets/ic2FaMnh.js.gz +0 -0
  70. package/dashboard/dist/assets/qm8xLgv-.css +1 -0
  71. package/dashboard/dist/assets/qm8xLgv-.css.br +0 -0
  72. package/dashboard/dist/assets/qm8xLgv-.css.gz +0 -0
  73. package/dashboard/dist/assets/rttbDbEx.js +1 -0
  74. package/dashboard/dist/assets/rttbDbEx.js.br +0 -0
  75. package/dashboard/dist/assets/rttbDbEx.js.gz +0 -0
  76. package/dashboard/dist/brand/anthropic-mark.svg.br +0 -0
  77. package/dashboard/dist/brand/anthropic-mark.svg.gz +0 -0
  78. package/dashboard/dist/brand/openai-mark.svg.br +0 -0
  79. package/dashboard/dist/brand/openai-mark.svg.gz +0 -0
  80. package/dashboard/dist/brand/openclaw-mark.svg.br +0 -0
  81. package/dashboard/dist/brand/openclaw-mark.svg.gz +0 -0
  82. package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
  83. package/dashboard/dist/index.html +7 -5
  84. package/dashboard/dist/index.html.br +0 -0
  85. package/dashboard/dist/index.html.gz +0 -0
  86. package/dist/activity-actor-fields.js +26 -4
  87. package/dist/activity-store.js +34 -8
  88. package/dist/agent-context-store.js +79 -17
  89. package/dist/agent-run-store.js +44 -3
  90. package/dist/agent-suite.d.ts +9 -0
  91. package/dist/agent-suite.js +149 -9
  92. package/dist/artifacts/artifact-domain-schemas.d.ts +66 -0
  93. package/dist/artifacts/artifact-domain-schemas.js +357 -0
  94. package/dist/artifacts/register-artifact.d.ts +4 -3
  95. package/dist/artifacts/register-artifact.js +170 -57
  96. package/dist/chat-store.d.ts +157 -0
  97. package/dist/chat-store.js +586 -0
  98. package/dist/cli/orgx.js +11 -0
  99. package/dist/contracts/client.d.ts +43 -3
  100. package/dist/contracts/client.js +159 -30
  101. package/dist/contracts/practice-exercise-schema.d.ts +216 -0
  102. package/dist/contracts/practice-exercise-schema.js +314 -0
  103. package/dist/contracts/retro-schema.d.ts +81 -0
  104. package/dist/contracts/retro-schema.js +80 -0
  105. package/dist/contracts/shared-types.d.ts +159 -0
  106. package/dist/contracts/shared-types.js +199 -1
  107. package/dist/contracts/skill-pack-schema.d.ts +192 -0
  108. package/dist/contracts/skill-pack-schema.js +180 -0
  109. package/dist/contracts/types.d.ts +247 -2
  110. package/dist/entities/auto-assignment.js +43 -17
  111. package/dist/event-sanitization.d.ts +11 -0
  112. package/dist/event-sanitization.js +113 -0
  113. package/dist/gateway-watchdog.d.ts +5 -0
  114. package/dist/gateway-watchdog.js +50 -0
  115. package/dist/hooks/post-reporting-event.mjs +1 -5
  116. package/dist/http/helpers/activity-headline.js +13 -132
  117. package/dist/http/helpers/auto-continue-engine.d.ts +198 -10
  118. package/dist/http/helpers/auto-continue-engine.js +3145 -186
  119. package/dist/http/helpers/autopilot-operations.d.ts +19 -0
  120. package/dist/http/helpers/autopilot-operations.js +182 -31
  121. package/dist/http/helpers/autopilot-runtime.d.ts +1 -0
  122. package/dist/http/helpers/autopilot-runtime.js +328 -25
  123. package/dist/http/helpers/autopilot-slice-utils.d.ts +18 -0
  124. package/dist/http/helpers/autopilot-slice-utils.js +514 -93
  125. package/dist/http/helpers/decision-mapper.d.ts +40 -0
  126. package/dist/http/helpers/decision-mapper.js +223 -7
  127. package/dist/http/helpers/dispatch-lifecycle.d.ts +19 -2
  128. package/dist/http/helpers/dispatch-lifecycle.js +242 -37
  129. package/dist/http/helpers/kickoff-context.js +104 -0
  130. package/dist/http/helpers/llm-client.d.ts +47 -0
  131. package/dist/http/helpers/llm-client.js +256 -0
  132. package/dist/http/helpers/mission-control.d.ts +102 -3
  133. package/dist/http/helpers/mission-control.js +498 -9
  134. package/dist/http/helpers/sentinel-catalog.d.ts +23 -0
  135. package/dist/http/helpers/sentinel-catalog.js +193 -0
  136. package/dist/http/helpers/session-classification.d.ts +9 -0
  137. package/dist/http/helpers/session-classification.js +564 -0
  138. package/dist/http/helpers/slice-experience-v2.d.ts +137 -0
  139. package/dist/http/helpers/slice-experience-v2.js +677 -0
  140. package/dist/http/helpers/slice-run-projections.d.ts +72 -0
  141. package/dist/http/helpers/slice-run-projections.js +877 -0
  142. package/dist/http/helpers/triage-mapper.d.ts +43 -0
  143. package/dist/http/helpers/triage-mapper.js +549 -0
  144. package/dist/http/helpers/value-utils.js +7 -2
  145. package/dist/http/helpers/workspace-scope.d.ts +15 -0
  146. package/dist/http/helpers/workspace-scope.js +170 -0
  147. package/dist/http/index.js +1420 -105
  148. package/dist/http/routes/agent-suite.d.ts +9 -0
  149. package/dist/http/routes/agent-suite.js +294 -8
  150. package/dist/http/routes/agents-catalog.js +64 -19
  151. package/dist/http/routes/chat.d.ts +19 -0
  152. package/dist/http/routes/chat.js +522 -0
  153. package/dist/http/routes/decision-actions.d.ts +8 -1
  154. package/dist/http/routes/decision-actions.js +42 -5
  155. package/dist/http/routes/dispatch-gateway-envelope.d.ts +25 -0
  156. package/dist/http/routes/dispatch-gateway-envelope.js +26 -0
  157. package/dist/http/routes/entities.d.ts +16 -0
  158. package/dist/http/routes/entities.js +232 -6
  159. package/dist/http/routes/live-legacy.d.ts +5 -0
  160. package/dist/http/routes/live-legacy.js +23 -509
  161. package/dist/http/routes/live-misc.d.ts +12 -0
  162. package/dist/http/routes/live-misc.js +251 -31
  163. package/dist/http/routes/live-snapshot.d.ts +49 -2
  164. package/dist/http/routes/live-snapshot.js +653 -23
  165. package/dist/http/routes/live-terminal.d.ts +11 -0
  166. package/dist/http/routes/live-terminal.js +154 -0
  167. package/dist/http/routes/live-triage.d.ts +61 -0
  168. package/dist/http/routes/live-triage.js +192 -0
  169. package/dist/http/routes/mission-control-actions.d.ts +49 -1
  170. package/dist/http/routes/mission-control-actions.js +1246 -84
  171. package/dist/http/routes/mission-control-read.d.ts +48 -3
  172. package/dist/http/routes/mission-control-read.js +1658 -20
  173. package/dist/http/routes/realtime-orchestrator.d.ts +10 -0
  174. package/dist/http/routes/realtime-orchestrator.js +74 -0
  175. package/dist/http/routes/run-control.d.ts +5 -2
  176. package/dist/http/routes/run-control.js +10 -0
  177. package/dist/http/routes/sentinels-catalog.d.ts +7 -0
  178. package/dist/http/routes/sentinels-catalog.js +24 -0
  179. package/dist/http/routes/summary.js +10 -3
  180. package/dist/http/routes/usage.d.ts +24 -0
  181. package/dist/http/routes/usage.js +362 -0
  182. package/dist/http/routes/work-artifacts.js +28 -9
  183. package/dist/index.js +165 -27
  184. package/dist/local-openclaw.js +29 -6
  185. package/dist/mcp-client-setup.js +3 -3
  186. package/dist/mcp-http-handler.d.ts +3 -0
  187. package/dist/mcp-http-handler.js +34 -60
  188. package/dist/next-up-queue-store.d.ts +16 -1
  189. package/dist/next-up-queue-store.js +89 -7
  190. package/dist/outbox.d.ts +5 -0
  191. package/dist/outbox.js +113 -9
  192. package/dist/paths.js +36 -5
  193. package/dist/reporting/rollups.d.ts +41 -0
  194. package/dist/reporting/rollups.js +113 -0
  195. package/dist/retro/domain-templates.d.ts +45 -0
  196. package/dist/retro/domain-templates.js +297 -0
  197. package/dist/retro/quality-rubric.d.ts +33 -0
  198. package/dist/retro/quality-rubric.js +213 -0
  199. package/dist/runtime-cleanup.d.ts +18 -0
  200. package/dist/runtime-cleanup.js +87 -0
  201. package/dist/services/background.d.ts +11 -0
  202. package/dist/services/background.js +22 -0
  203. package/dist/services/experiment-randomization.d.ts +21 -0
  204. package/dist/services/experiment-randomization.js +63 -0
  205. package/dist/skill-pack-state.d.ts +36 -5
  206. package/dist/skill-pack-state.js +273 -29
  207. package/dist/sync/local-agent-telemetry.d.ts +13 -0
  208. package/dist/sync/local-agent-telemetry.js +128 -0
  209. package/dist/sync/outbox-replay.js +131 -24
  210. package/dist/team-context-store.d.ts +23 -0
  211. package/dist/team-context-store.js +116 -0
  212. package/dist/telemetry/posthog.js +4 -2
  213. package/dist/tools/core-tools.d.ts +10 -14
  214. package/dist/tools/core-tools.js +1289 -24
  215. package/dist/types.d.ts +2 -0
  216. package/dist/types.js +2 -0
  217. package/dist/worker-supervisor.js +23 -0
  218. package/package.json +20 -6
  219. package/dashboard/dist/assets/B3ziCA02.js +0 -8
  220. package/dashboard/dist/assets/B5NEElEI.css +0 -1
  221. package/dashboard/dist/assets/BhapSNAs.js +0 -215
  222. package/dashboard/dist/assets/iFdvE7lx.js +0 -1
  223. package/dashboard/dist/assets/jRJsmpYM.js +0 -1
  224. package/dashboard/dist/assets/sAhvFnpk.js +0 -4
@@ -1,8 +1,150 @@
1
- import { chmodSync, createWriteStream, mkdirSync, writeFileSync, } from "node:fs";
1
+ import { chmodSync, createWriteStream, existsSync, mkdtempSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
2
2
  import { spawn } from "node:child_process";
3
- import { dirname, resolve, sep } from "node:path";
3
+ import { homedir, tmpdir } from "node:os";
4
+ import { dirname, join, resolve, sep } from "node:path";
5
+ import { getOrgxPluginConfigDir } from "../../paths.js";
4
6
  import { normalizeCodexArgs } from "./autopilot-slice-utils.js";
5
7
  export function createAutopilotRuntime(deps) {
8
+ function hasExplicitCodexSubcommand(args) {
9
+ const first = (args[0] ?? "").trim();
10
+ if (!first || first.startsWith("-"))
11
+ return false;
12
+ return true;
13
+ }
14
+ function envFlag(name, defaultValue) {
15
+ const raw = (process.env[name] ?? "").trim().toLowerCase();
16
+ if (!raw)
17
+ return defaultValue;
18
+ return !(raw === "0" || raw === "false" || raw === "no" || raw === "off");
19
+ }
20
+ function readFirstExisting(paths) {
21
+ for (const pathname of paths) {
22
+ if (!pathname)
23
+ continue;
24
+ try {
25
+ if (!existsSync(pathname))
26
+ continue;
27
+ return readFileSync(pathname, "utf8");
28
+ }
29
+ catch {
30
+ // continue
31
+ }
32
+ }
33
+ return null;
34
+ }
35
+ function extractOrgxOpenclawUrl(configToml) {
36
+ if (!configToml)
37
+ return null;
38
+ const lines = configToml.split(/\r?\n/);
39
+ let inTargetSection = false;
40
+ for (const rawLine of lines) {
41
+ const line = rawLine.trim();
42
+ if (!line)
43
+ continue;
44
+ if (/^\[mcp_servers\.(?:"orgx-openclaw"|orgx-openclaw)\]\s*$/i.test(line)) {
45
+ inTargetSection = true;
46
+ continue;
47
+ }
48
+ if (inTargetSection && line.startsWith("[")) {
49
+ break;
50
+ }
51
+ if (!inTargetSection)
52
+ continue;
53
+ const urlMatch = line.match(/^url\s*=\s*("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')\s*(?:#.*)?$/i);
54
+ if (!urlMatch)
55
+ continue;
56
+ const token = (urlMatch[1] ?? "").trim();
57
+ if (token.length < 2)
58
+ continue;
59
+ const quote = token[0];
60
+ const unescaped = token
61
+ .slice(1, -1)
62
+ .replace(quote === '"' ? /\\"/g : /\\'/g, quote)
63
+ .trim();
64
+ const rawUrl = unescaped;
65
+ if (rawUrl.length > 0)
66
+ return rawUrl;
67
+ }
68
+ return null;
69
+ }
70
+ function prepareAutopilotCodexHome() {
71
+ const configuredHome = (process.env.ORGX_AUTOPILOT_CODEX_HOME ?? "").trim();
72
+ const preferredHome = configuredHome.length > 0
73
+ ? configuredHome
74
+ : join(getOrgxPluginConfigDir(), "codex-autopilot-home");
75
+ const sourceHome = (process.env.CODEX_HOME ?? "").trim() || join(homedir(), ".codex");
76
+ const sourceConfigCandidates = [
77
+ join(sourceHome, "config.toml"),
78
+ join(homedir(), ".codex", "config.toml"),
79
+ join(homedir(), ".config", "codex", "config.toml"),
80
+ ];
81
+ const mcpModeRaw = (process.env.ORGX_AUTOPILOT_CODEX_MCP_MODE ?? "").trim().toLowerCase();
82
+ const mcpMode = mcpModeRaw.length > 0 ? mcpModeRaw : "orgx-openclaw";
83
+ const sourceConfig = readFirstExisting(sourceConfigCandidates);
84
+ const extractedOrgxOpenclawUrl = extractOrgxOpenclawUrl(sourceConfig);
85
+ const defaultOrgxOpenclawUrl = (process.env.ORGX_AUTOPILOT_ORGX_MCP_URL ?? "").trim() ||
86
+ extractedOrgxOpenclawUrl ||
87
+ "http://127.0.0.1:18789/orgx/mcp";
88
+ const configLines = [
89
+ "# Autogenerated by OrgX autopilot runtime. This isolates codex slices",
90
+ "# from broken or noisy global MCP entries in ~/.codex/config.toml.",
91
+ "",
92
+ ];
93
+ if (mcpMode === "none") {
94
+ configLines.push("mcp_servers = {}", "");
95
+ }
96
+ else {
97
+ configLines.push('[mcp_servers."orgx-openclaw"]', `url = ${JSON.stringify(defaultOrgxOpenclawUrl)}`, "");
98
+ }
99
+ const writeAutopilotHome = (targetHome) => {
100
+ try {
101
+ mkdirSync(targetHome, { recursive: true, mode: 0o700 });
102
+ try {
103
+ chmodSync(targetHome, 0o700);
104
+ }
105
+ catch {
106
+ // best effort
107
+ }
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ const sourceAuthPath = join(sourceHome, "auth.json");
113
+ const targetAuthPath = join(targetHome, "auth.json");
114
+ try {
115
+ if (existsSync(sourceAuthPath)) {
116
+ const authRaw = readFileSync(sourceAuthPath, "utf8");
117
+ writeFileSync(targetAuthPath, authRaw, { encoding: "utf8", mode: 0o600 });
118
+ }
119
+ }
120
+ catch {
121
+ // best effort
122
+ }
123
+ try {
124
+ writeFileSync(join(targetHome, "config.toml"), `${configLines.join("\n")}\n`, {
125
+ encoding: "utf8",
126
+ mode: 0o600,
127
+ });
128
+ }
129
+ catch {
130
+ return false;
131
+ }
132
+ return true;
133
+ };
134
+ if (writeAutopilotHome(preferredHome))
135
+ return preferredHome;
136
+ // Hard fallback: use an ephemeral isolated CODEX_HOME so slices do not
137
+ // inherit potentially broken global MCP config.
138
+ try {
139
+ const fallbackHome = mkdtempSync(join(tmpdir(), "orgx-autopilot-codex-home-"));
140
+ if (writeAutopilotHome(fallbackHome))
141
+ return fallbackHome;
142
+ }
143
+ catch {
144
+ // best effort
145
+ }
146
+ return null;
147
+ }
6
148
  function ensurePrivateDirForFile(pathname) {
7
149
  const dir = dirname(pathname);
8
150
  mkdirSync(dir, { recursive: true, mode: 0o700 });
@@ -13,14 +155,49 @@ export function createAutopilotRuntime(deps) {
13
155
  // best effort
14
156
  }
15
157
  }
158
+ function createSafeAppendStream(pathname) {
159
+ const stream = createWriteStream(pathname, { flags: "a" });
160
+ stream.on("error", () => {
161
+ // Best-effort logging only.
162
+ });
163
+ return stream;
164
+ }
165
+ function hasSliceOutput(pathname) {
166
+ try {
167
+ if (!existsSync(pathname))
168
+ return false;
169
+ const raw = readFileSync(pathname, "utf8");
170
+ return raw.trim().length > 0;
171
+ }
172
+ catch {
173
+ return false;
174
+ }
175
+ }
176
+ function writeFallbackSliceOutput(input) {
177
+ if (hasSliceOutput(input.outputPath))
178
+ return false;
179
+ try {
180
+ writeFileSync(input.outputPath, `${JSON.stringify({
181
+ status: "error",
182
+ summary: `Worker exited without structured output (${input.reason}; code=${String(input.code)}, signal=${String(input.signal)}).`,
183
+ workstream_id: input.workstreamId ?? "unknown",
184
+ workstream_title: input.workstreamTitle ?? null,
185
+ slice_id: input.runId,
186
+ }, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
187
+ return true;
188
+ }
189
+ catch {
190
+ return false;
191
+ }
192
+ }
16
193
  function spawnCodexSliceWorker(input) {
17
194
  ensurePrivateDirForFile(input.logPath);
18
195
  ensurePrivateDirForFile(input.outputPath);
19
196
  const workerKind = (process.env.ORGX_AUTOPILOT_WORKER_KIND ?? "").trim().toLowerCase();
20
197
  if (workerKind === "mock") {
21
198
  const scriptPath = resolve(dirname(deps.filename), "..", "..", "scripts", "mock-autopilot-slice-worker.mjs");
22
- const logStream = createWriteStream(input.logPath, { flags: "a" });
23
- const outStream = createWriteStream(input.outputPath, { flags: "a" });
199
+ const logStream = createSafeAppendStream(input.logPath);
200
+ const outStream = createSafeAppendStream(input.outputPath);
24
201
  logStream.write(`\n==== ${new Date().toISOString()} :: mock slice ${input.runId} ====\n`);
25
202
  const child = spawn("node", [scriptPath], {
26
203
  cwd: input.cwd,
@@ -64,7 +241,19 @@ export function createAutopilotRuntime(deps) {
64
241
  child.on("close", (code, signal) => {
65
242
  deps.autoContinueSliceChildren.delete(input.runId);
66
243
  const stamp = new Date().toISOString();
244
+ const wroteFallback = writeFallbackSliceOutput({
245
+ outputPath: input.outputPath,
246
+ runId: input.runId,
247
+ workstreamId: input.env.ORGX_WORKSTREAM_ID,
248
+ workstreamTitle: input.env.ORGX_WORKSTREAM_TITLE,
249
+ code,
250
+ signal,
251
+ reason: "mock worker close",
252
+ });
67
253
  try {
254
+ if (wroteFallback) {
255
+ logStream.write(`fallback output synthesized at ${input.outputPath}\n`);
256
+ }
68
257
  logStream.write(`\n==== ${stamp} :: exit code=${String(code)} signal=${String(signal)} ====\n`);
69
258
  }
70
259
  catch {
@@ -108,21 +297,91 @@ export function createAutopilotRuntime(deps) {
108
297
  return { pid: child.pid ?? null };
109
298
  }
110
299
  if (workerKind === "claude-code" || workerKind === "claude_code") {
300
+ const hasArgFlag = (args, flag) => args.includes(flag) || args.some((arg) => typeof arg === "string" && arg.startsWith(`${flag}=`));
301
+ const readArgValue = (args, flag) => {
302
+ const inline = args.find((arg) => typeof arg === "string" && arg.startsWith(`${flag}=`));
303
+ if (inline)
304
+ return inline.slice(flag.length + 1).trim() || null;
305
+ const index = args.indexOf(flag);
306
+ const next = index >= 0 ? args[index + 1] : null;
307
+ return typeof next === "string" && next.trim().length > 0 ? next.trim() : null;
308
+ };
111
309
  const claudeBin = (process.env.ORGX_CLAUDE_CODE_BIN ?? "").trim() || "claude";
112
310
  const rawArgs = (process.env.ORGX_CLAUDE_CODE_ARGS ?? "").trim();
113
311
  const args = rawArgs.length > 0 ? rawArgs.split(/\s+/).filter(Boolean) : [];
114
- const logStream = createWriteStream(input.logPath, { flags: "a" });
115
- const outStream = createWriteStream(input.outputPath, { flags: "a" });
312
+ const hasPrint = hasArgFlag(args, "--print") || args.includes("-p");
313
+ const hasOutputFormat = hasArgFlag(args, "--output-format");
314
+ const hasJsonSchema = hasArgFlag(args, "--json-schema");
315
+ const hasNoSessionPersistence = hasArgFlag(args, "--no-session-persistence");
316
+ const hasPermissionMode = hasArgFlag(args, "--permission-mode");
317
+ const hasDangerousSkipPermissions = hasArgFlag(args, "--dangerously-skip-permissions");
318
+ const hasAllowDangerousSkipPermissions = hasArgFlag(args, "--allow-dangerously-skip-permissions");
319
+ const explicitOutputFormat = readArgValue(args, "--output-format");
320
+ const explicitJsonSchemaArg = readArgValue(args, "--json-schema");
321
+ const explicitPermissionMode = readArgValue(args, "--permission-mode");
322
+ let schemaArg = null;
323
+ if (input.outputSchemaPath && !hasJsonSchema) {
324
+ try {
325
+ const schemaRaw = readFileSync(input.outputSchemaPath, "utf8").trim();
326
+ if (schemaRaw.length > 0)
327
+ schemaArg = schemaRaw;
328
+ }
329
+ catch {
330
+ schemaArg = null;
331
+ }
332
+ }
333
+ const claudeExtraArgs = [];
334
+ if (!hasPrint)
335
+ claudeExtraArgs.push("--print");
336
+ if (!hasOutputFormat)
337
+ claudeExtraArgs.push("--output-format", "json");
338
+ if (!hasNoSessionPersistence)
339
+ claudeExtraArgs.push("--no-session-persistence");
340
+ if (!hasPermissionMode)
341
+ claudeExtraArgs.push("--permission-mode", "bypassPermissions");
342
+ if (!hasDangerousSkipPermissions && !hasAllowDangerousSkipPermissions) {
343
+ claudeExtraArgs.push("--dangerously-skip-permissions");
344
+ }
345
+ if (schemaArg)
346
+ claudeExtraArgs.push("--json-schema", schemaArg);
347
+ const logStream = createSafeAppendStream(input.logPath);
348
+ const outStream = createSafeAppendStream(input.outputPath);
116
349
  logStream.write(`\n==== ${new Date().toISOString()} :: claude slice ${input.runId} ====\n`);
117
- // Claude Code invocation is environment-specific; ORGX_CLAUDE_CODE_ARGS should be set to
118
- // a headless-compatible command shape. We pass the prompt as the final argument.
119
- const child = spawn(claudeBin, [...args, input.prompt], {
350
+ logStream.write(`claude_bin: ${claudeBin}\n`);
351
+ if (claudeExtraArgs.length > 0) {
352
+ const claudeArgsForLog = claudeExtraArgs.map((arg) => {
353
+ if (schemaArg && arg === schemaArg)
354
+ return "<json-schema>";
355
+ return arg.length > 160 ? `${arg.slice(0, 157)}...` : arg;
356
+ });
357
+ logStream.write(`claude_args_injected: ${claudeArgsForLog.join(" ")}\n`);
358
+ }
359
+ if (schemaArg && input.outputSchemaPath) {
360
+ logStream.write(`claude_json_schema: ${input.outputSchemaPath}\n`);
361
+ }
362
+ else if (hasJsonSchema) {
363
+ logStream.write(`claude_json_schema: ${explicitJsonSchemaArg ?? "provided-via-args"}\n`);
364
+ }
365
+ else if (input.outputSchemaPath && !hasJsonSchema) {
366
+ logStream.write(`claude_json_schema: unavailable (${input.outputSchemaPath})\n`);
367
+ }
368
+ logStream.write(`claude_output_format: ${hasOutputFormat ? explicitOutputFormat ?? "provided" : "json"}\n`);
369
+ logStream.write(`claude_permission_mode: ${hasPermissionMode ? explicitPermissionMode ?? "provided" : "bypassPermissions"}\n`);
370
+ logStream.write(`claude_skip_permissions: ${hasDangerousSkipPermissions || hasAllowDangerousSkipPermissions ? "provided" : "dangerously-skip-permissions"}\n`);
371
+ const childEnv = {
372
+ ...process.env,
373
+ ...deps.resolveByokEnvOverrides(),
374
+ ...input.env,
375
+ };
376
+ if (claudeBin.includes(sep)) {
377
+ const binDir = dirname(claudeBin);
378
+ childEnv.PATH = childEnv.PATH ? `${binDir}:${childEnv.PATH}` : binDir;
379
+ }
380
+ // Force non-interactive structured output by default for parity with codex output-schema mode.
381
+ // If callers already pass explicit print/output/schema flags, we preserve their args unchanged.
382
+ const child = spawn(claudeBin, [...args, ...claudeExtraArgs, input.prompt], {
120
383
  cwd: input.cwd,
121
- env: {
122
- ...process.env,
123
- ...deps.resolveByokEnvOverrides(),
124
- ...input.env,
125
- },
384
+ env: childEnv,
126
385
  stdio: ["ignore", "pipe", "pipe"],
127
386
  detached: true,
128
387
  });
@@ -152,7 +411,19 @@ export function createAutopilotRuntime(deps) {
152
411
  child.on("close", (code, signal) => {
153
412
  deps.autoContinueSliceChildren.delete(input.runId);
154
413
  const stamp = new Date().toISOString();
414
+ const wroteFallback = writeFallbackSliceOutput({
415
+ outputPath: input.outputPath,
416
+ runId: input.runId,
417
+ workstreamId: input.env.ORGX_WORKSTREAM_ID,
418
+ workstreamTitle: input.env.ORGX_WORKSTREAM_TITLE,
419
+ code,
420
+ signal,
421
+ reason: "claude worker close",
422
+ });
155
423
  try {
424
+ if (wroteFallback) {
425
+ logStream.write(`fallback output synthesized at ${input.outputPath}\n`);
426
+ }
156
427
  logStream.write(`\n==== ${stamp} :: exit code=${String(code)} signal=${String(signal)} ====\n`);
157
428
  }
158
429
  catch {
@@ -199,17 +470,14 @@ export function createAutopilotRuntime(deps) {
199
470
  const codexInfo = deps.resolveCodexBinInfo();
200
471
  const codexBin = codexInfo.bin;
201
472
  const rawArgs = (process.env.ORGX_CODEX_ARGS ?? "").trim();
202
- const args = normalizeCodexArgs(rawArgs.length > 0 ? rawArgs.split(/\s+/).filter(Boolean) : ["--full-auto"]);
203
- // Autopilot slices should not fail just because an unrelated MCP server is flaky.
204
- // Default: disable firecrawl unless explicitly re-enabled.
205
- const disableFirecrawlRaw = (process.env.ORGX_AUTOPILOT_DISABLE_FIRECRAWL ?? "").trim().toLowerCase();
206
- const disableFirecrawl = disableFirecrawlRaw !== "false" && disableFirecrawlRaw !== "0" && disableFirecrawlRaw !== "no";
207
- const hasFirecrawlOverride = args.some((arg) => String(arg).includes("mcp_servers.firecrawl"));
473
+ const normalizedArgs = normalizeCodexArgs(rawArgs.length > 0
474
+ ? rawArgs.split(/\s+/).filter(Boolean)
475
+ : ["exec", "--ephemeral", "--full-auto", "--skip-git-repo-check"]);
476
+ const args = hasExplicitCodexSubcommand(normalizedArgs)
477
+ ? normalizedArgs
478
+ : ["exec", ...normalizedArgs];
208
479
  const extraArgs = [];
209
- if (disableFirecrawl && !hasFirecrawlOverride) {
210
- extraArgs.push("-c", "mcp_servers.firecrawl.enabled=false");
211
- }
212
- const logStream = createWriteStream(input.logPath, { flags: "a" });
480
+ const logStream = createSafeAppendStream(input.logPath);
213
481
  logStream.write(`\n==== ${new Date().toISOString()} :: slice ${input.runId} ====\n`);
214
482
  logStream.write(`codex_bin: ${codexBin}${codexInfo.versionString ? ` (${codexInfo.versionString})` : ""}\n`);
215
483
  const childEnv = {
@@ -217,6 +485,21 @@ export function createAutopilotRuntime(deps) {
217
485
  ...deps.resolveByokEnvOverrides(),
218
486
  ...input.env,
219
487
  };
488
+ const shouldIsolateCodexHome = envFlag("ORGX_AUTOPILOT_ISOLATE_CODEX_HOME", true);
489
+ const autopilotCodexHome = prepareAutopilotCodexHome();
490
+ if (autopilotCodexHome) {
491
+ childEnv.CODEX_HOME = autopilotCodexHome;
492
+ logStream.write(shouldIsolateCodexHome
493
+ ? `codex_home: ${autopilotCodexHome}\n`
494
+ : `codex_home: ${autopilotCodexHome} (forced-safe override while ORGX_AUTOPILOT_ISOLATE_CODEX_HOME=false)\n`);
495
+ }
496
+ else if (shouldIsolateCodexHome) {
497
+ delete childEnv.CODEX_HOME;
498
+ logStream.write("codex_home: isolation unavailable (default lookup)\n");
499
+ }
500
+ else {
501
+ logStream.write("codex_home: forced-safe override unavailable (inheriting global CODEX_HOME)\n");
502
+ }
220
503
  if (codexBin.includes(sep)) {
221
504
  const binDir = dirname(codexBin);
222
505
  childEnv.PATH = childEnv.PATH ? `${binDir}:${childEnv.PATH}` : binDir;
@@ -226,7 +509,15 @@ export function createAutopilotRuntime(deps) {
226
509
  const outputArgs = hasOutputLastMessage
227
510
  ? []
228
511
  : ["--output-last-message", input.outputPath];
229
- const child = spawn(codexBin, [...args, ...extraArgs, ...outputArgs, input.prompt], {
512
+ const hasOutputSchema = args.includes("--output-schema") ||
513
+ args.some((arg) => typeof arg === "string" && arg.startsWith("--output-schema="));
514
+ const outputSchemaArgs = input.outputSchemaPath && !hasOutputSchema
515
+ ? ["--output-schema", input.outputSchemaPath]
516
+ : [];
517
+ if (outputSchemaArgs.length > 0) {
518
+ logStream.write(`output_schema: ${input.outputSchemaPath}\n`);
519
+ }
520
+ const child = spawn(codexBin, [...args, ...extraArgs, ...outputArgs, ...outputSchemaArgs, input.prompt], {
230
521
  cwd: input.cwd,
231
522
  env: childEnv,
232
523
  stdio: ["ignore", "pipe", "pipe"],
@@ -252,7 +543,19 @@ export function createAutopilotRuntime(deps) {
252
543
  child.on("close", (code, signal) => {
253
544
  deps.autoContinueSliceChildren.delete(input.runId);
254
545
  const stamp = new Date().toISOString();
546
+ const wroteFallback = writeFallbackSliceOutput({
547
+ outputPath: input.outputPath,
548
+ runId: input.runId,
549
+ workstreamId: input.env.ORGX_WORKSTREAM_ID,
550
+ workstreamTitle: input.env.ORGX_WORKSTREAM_TITLE,
551
+ code,
552
+ signal,
553
+ reason: "codex worker close",
554
+ });
255
555
  try {
556
+ if (wroteFallback) {
557
+ logStream.write(`fallback output synthesized at ${input.outputPath}\n`);
558
+ }
256
559
  logStream.write(`\n==== ${stamp} :: exit code=${String(code)} signal=${String(signal)} ====\n`);
257
560
  }
258
561
  catch {
@@ -13,6 +13,11 @@ export declare function createCodexBinResolver(): {
13
13
  resolveCodexBinInfo: () => CodexBinInfo;
14
14
  getCachedCodexProbeSummary: () => string | null;
15
15
  };
16
+ export declare function buildSliceOutputInstructions(input: {
17
+ runId: string;
18
+ schemaPath: string;
19
+ requiredSkills: string[];
20
+ }): string;
16
21
  export declare function buildWorkstreamSlicePrompt(input: {
17
22
  initiativeTitle: string;
18
23
  initiativeId: string;
@@ -33,6 +38,19 @@ export declare function buildWorkstreamSlicePrompt(input: {
33
38
  domain: string;
34
39
  requiredSkills: string[];
35
40
  };
41
+ behaviorConfig?: {
42
+ configId?: string | null;
43
+ version?: string | null;
44
+ hash?: string | null;
45
+ policySource?: string | null;
46
+ context?: string | null;
47
+ } | null;
36
48
  runId: string;
37
49
  schemaPath: string;
38
50
  }): string;
51
+ export type BuildScopeDirectiveScope = "task" | "milestone" | "workstream";
52
+ export declare function buildScopeDirective(scope: BuildScopeDirectiveScope, meta: {
53
+ milestoneTitles?: string[];
54
+ workstreamTitle?: string;
55
+ taskCount: number;
56
+ }): string;