oh-my-copilot 5.6.2 → 5.7.0
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -0
- package/bridge/__pycache__/gyoshu_bridge.cpython-312.pyc +0 -0
- package/bridge/claude-md-coordinator.cjs +2 -2
- package/bridge/cli.cjs +78578 -75769
- package/bridge/mcp-server.cjs +36510 -32259
- package/bridge/runtime-cli.cjs +95 -34
- package/bridge/team-mcp.cjs +95 -34
- package/bridge/team.js +131 -70
- package/dist/__tests__/run-cjs-fail-closed-timeout.test.d.ts +2 -0
- package/dist/__tests__/run-cjs-fail-closed-timeout.test.d.ts.map +1 -0
- package/dist/__tests__/run-cjs-fail-closed-timeout.test.js +68 -0
- package/dist/__tests__/run-cjs-fail-closed-timeout.test.js.map +1 -0
- package/dist/__tests__/session-end-process-exit.test.js +70 -2
- package/dist/__tests__/session-end-process-exit.test.js.map +1 -1
- package/dist/cli/commands/__tests__/smoke-tier2.test.d.ts +2 -0
- package/dist/cli/commands/__tests__/smoke-tier2.test.d.ts.map +1 -0
- package/dist/cli/commands/__tests__/smoke-tier2.test.js +72 -0
- package/dist/cli/commands/__tests__/smoke-tier2.test.js.map +1 -0
- package/dist/cli/commands/smoke.d.ts +36 -0
- package/dist/cli/commands/smoke.d.ts.map +1 -0
- package/dist/cli/commands/smoke.js +169 -0
- package/dist/cli/commands/smoke.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +39 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/constants/names.d.ts +1 -0
- package/dist/constants/names.d.ts.map +1 -1
- package/dist/constants/names.js +1 -0
- package/dist/constants/names.js.map +1 -1
- package/dist/hooks/session-end/index.d.ts +2 -3
- package/dist/hooks/session-end/index.d.ts.map +1 -1
- package/dist/hooks/session-end/index.js +3 -10
- package/dist/hooks/session-end/index.js.map +1 -1
- package/dist/hooks/session-end/wiki-foreground-bootstrap.d.ts +17 -0
- package/dist/hooks/session-end/wiki-foreground-bootstrap.d.ts.map +1 -0
- package/dist/hooks/session-end/wiki-foreground-bootstrap.js +20 -0
- package/dist/hooks/session-end/wiki-foreground-bootstrap.js.map +1 -0
- package/dist/lib/__tests__/atomic-write.test.js +32 -1
- package/dist/lib/__tests__/atomic-write.test.js.map +1 -1
- package/dist/lib/__tests__/mode-state-lock.test.js +121 -12
- package/dist/lib/__tests__/mode-state-lock.test.js.map +1 -1
- package/dist/lib/atomic-write.d.ts +13 -3
- package/dist/lib/atomic-write.d.ts.map +1 -1
- package/dist/lib/atomic-write.js +29 -15
- package/dist/lib/atomic-write.js.map +1 -1
- package/dist/lib/mode-state-io.d.ts +2 -2
- package/dist/lib/mode-state-io.d.ts.map +1 -1
- package/dist/lib/mode-state-io.js +16 -10
- package/dist/lib/mode-state-io.js.map +1 -1
- package/dist/mcp/__tests__/host-smoke-tool.test.d.ts +2 -0
- package/dist/mcp/__tests__/host-smoke-tool.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/host-smoke-tool.test.js +174 -0
- package/dist/mcp/__tests__/host-smoke-tool.test.js.map +1 -0
- package/dist/mcp/disable-tools.d.ts.map +1 -1
- package/dist/mcp/disable-tools.js +1 -0
- package/dist/mcp/disable-tools.js.map +1 -1
- package/dist/mcp/tool-registry.d.ts.map +1 -1
- package/dist/mcp/tool-registry.js +2 -0
- package/dist/mcp/tool-registry.js.map +1 -1
- package/dist/smoke/__tests__/copilot-sdk-driver.test.d.ts +2 -0
- package/dist/smoke/__tests__/copilot-sdk-driver.test.d.ts.map +1 -0
- package/dist/smoke/__tests__/copilot-sdk-driver.test.js +561 -0
- package/dist/smoke/__tests__/copilot-sdk-driver.test.js.map +1 -0
- package/dist/smoke/__tests__/copilot-sdk-scenarios.test.d.ts +2 -0
- package/dist/smoke/__tests__/copilot-sdk-scenarios.test.d.ts.map +1 -0
- package/dist/smoke/__tests__/copilot-sdk-scenarios.test.js +311 -0
- package/dist/smoke/__tests__/copilot-sdk-scenarios.test.js.map +1 -0
- package/dist/smoke/__tests__/copilot-session-eval.test.d.ts +2 -0
- package/dist/smoke/__tests__/copilot-session-eval.test.d.ts.map +1 -0
- package/dist/smoke/__tests__/copilot-session-eval.test.js +264 -0
- package/dist/smoke/__tests__/copilot-session-eval.test.js.map +1 -0
- package/dist/smoke/__tests__/copilot-smoke.test.d.ts +2 -0
- package/dist/smoke/__tests__/copilot-smoke.test.d.ts.map +1 -0
- package/dist/smoke/__tests__/copilot-smoke.test.js +482 -0
- package/dist/smoke/__tests__/copilot-smoke.test.js.map +1 -0
- package/dist/smoke/copilot-binary.d.ts +21 -0
- package/dist/smoke/copilot-binary.d.ts.map +1 -0
- package/dist/smoke/copilot-binary.js +46 -0
- package/dist/smoke/copilot-binary.js.map +1 -0
- package/dist/smoke/copilot-sdk-driver.d.ts +186 -0
- package/dist/smoke/copilot-sdk-driver.d.ts.map +1 -0
- package/dist/smoke/copilot-sdk-driver.js +622 -0
- package/dist/smoke/copilot-sdk-driver.js.map +1 -0
- package/dist/smoke/copilot-sdk-scenarios.d.ts +159 -0
- package/dist/smoke/copilot-sdk-scenarios.d.ts.map +1 -0
- package/dist/smoke/copilot-sdk-scenarios.js +510 -0
- package/dist/smoke/copilot-sdk-scenarios.js.map +1 -0
- package/dist/smoke/copilot-session-eval.d.ts +90 -0
- package/dist/smoke/copilot-session-eval.d.ts.map +1 -0
- package/dist/smoke/copilot-session-eval.js +323 -0
- package/dist/smoke/copilot-session-eval.js.map +1 -0
- package/dist/smoke/copilot-smoke.d.ts +228 -0
- package/dist/smoke/copilot-smoke.d.ts.map +1 -0
- package/dist/smoke/copilot-smoke.js +818 -0
- package/dist/smoke/copilot-smoke.js.map +1 -0
- package/dist/smoke/process-utils.d.ts +47 -0
- package/dist/smoke/process-utils.d.ts.map +1 -0
- package/dist/smoke/process-utils.js +99 -0
- package/dist/smoke/process-utils.js.map +1 -0
- package/dist/team/__tests__/tmux-session.pane-env.test.d.ts +2 -0
- package/dist/team/__tests__/tmux-session.pane-env.test.d.ts.map +1 -0
- package/dist/team/__tests__/tmux-session.pane-env.test.js +52 -0
- package/dist/team/__tests__/tmux-session.pane-env.test.js.map +1 -0
- package/dist/team/tmux-session.d.ts +7 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +80 -18
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/tools/host-smoke-tool.d.ts +34 -0
- package/dist/tools/host-smoke-tool.d.ts.map +1 -0
- package/dist/tools/host-smoke-tool.js +133 -0
- package/dist/tools/host-smoke-tool.js.map +1 -0
- package/docs/CLAUDE.md +1 -1
- package/docs/DEVELOPERS.md +101 -0
- package/docs/HOOKS.md +1 -1
- package/docs/MIGRATION.md +71 -0
- package/docs/REFERENCE.md +42 -1
- package/docs/TOOLS.md +32 -1
- package/package.json +11 -2
- package/plugin.json +1 -1
- package/scripts/dev/repro-state-lock.mjs +1 -1
- package/scripts/lib/atomic-write.mjs +4 -2
- package/scripts/lib/state-lock.mjs +21 -12
- package/scripts/run.cjs +13 -3
- package/scripts/wiki-session-end.mjs +2 -1
- package/templates/hooks/lib/atomic-write.mjs +4 -2
package/bridge/team.js
CHANGED
|
@@ -9197,33 +9197,33 @@ function ensureDirSync(dir) {
|
|
|
9197
9197
|
}
|
|
9198
9198
|
}
|
|
9199
9199
|
function verifyPrivateTempFile(fd, tempPath, label, operations) {
|
|
9200
|
-
const fdStats =
|
|
9200
|
+
const fdStats = descriptorStats(fd, operations);
|
|
9201
9201
|
let pathStats;
|
|
9202
9202
|
try {
|
|
9203
|
-
pathStats = (operations
|
|
9203
|
+
pathStats = pathnameStats(tempPath, operations);
|
|
9204
9204
|
} catch {
|
|
9205
9205
|
throw new Error(`${label} temporary file was replaced before rename`);
|
|
9206
9206
|
}
|
|
9207
9207
|
const isWindows = process.platform === "win32";
|
|
9208
|
-
const isPrivateRegularSingleLink = (stats) => stats.isFile() && (isWindows ? stats.nlink <= 1 : stats.nlink === 1) && (isWindows || (stats.mode & 511) === 384);
|
|
9208
|
+
const isPrivateRegularSingleLink = (stats) => stats.isFile() && (isWindows ? Number(stats.nlink) <= 1 : Number(stats.nlink) === 1) && (isWindows || (Number(stats.mode) & 511) === 384);
|
|
9209
9209
|
if (!isPrivateRegularSingleLink(fdStats) || !isPrivateRegularSingleLink(pathStats)) {
|
|
9210
9210
|
throw new Error(
|
|
9211
9211
|
`${label} temporary file must be a private regular single-link file`
|
|
9212
9212
|
);
|
|
9213
9213
|
}
|
|
9214
|
-
if (!sameFileIdentity(fdStats, pathStats)) {
|
|
9214
|
+
if (!sameFileIdentity(fileIdentityOf(fdStats), fileIdentityOf(pathStats))) {
|
|
9215
9215
|
throw new Error(`${label} temporary file was replaced before rename`);
|
|
9216
9216
|
}
|
|
9217
9217
|
}
|
|
9218
9218
|
function verifyPublishedFile(fd, filePath, label, operations) {
|
|
9219
|
-
const fdStats =
|
|
9219
|
+
const fdStats = descriptorStats(fd, operations);
|
|
9220
9220
|
let pathStats;
|
|
9221
9221
|
try {
|
|
9222
|
-
pathStats = (operations
|
|
9222
|
+
pathStats = pathnameStats(filePath, operations);
|
|
9223
9223
|
} catch {
|
|
9224
9224
|
throw new Error(`${label} target was replaced at publication`);
|
|
9225
9225
|
}
|
|
9226
|
-
if (!pathStats.isFile() || !sameFileIdentity(fdStats, pathStats)) {
|
|
9226
|
+
if (!pathStats.isFile() || !sameFileIdentity(fileIdentityOf(fdStats), fileIdentityOf(pathStats))) {
|
|
9227
9227
|
throw new Error(`${label} target was replaced at publication`);
|
|
9228
9228
|
}
|
|
9229
9229
|
}
|
|
@@ -9247,26 +9247,33 @@ function preservePriorTarget(filePath, operations) {
|
|
|
9247
9247
|
return null;
|
|
9248
9248
|
}
|
|
9249
9249
|
}
|
|
9250
|
+
function descriptorStats(fd, operations) {
|
|
9251
|
+
return operations ? fsSync.fstatSync(fd) : fsSync.fstatSync(fd, { bigint: true });
|
|
9252
|
+
}
|
|
9253
|
+
function pathnameStats(filePath, operations) {
|
|
9254
|
+
return operations ? operations.lstat(filePath) : fsSync.lstatSync(filePath, { bigint: true });
|
|
9255
|
+
}
|
|
9256
|
+
function fileIdentityOf(stats) {
|
|
9257
|
+
return { dev: BigInt(stats.dev), ino: BigInt(stats.ino) };
|
|
9258
|
+
}
|
|
9250
9259
|
function sameFileIdentity(a, b) {
|
|
9251
9260
|
if (a.ino !== b.ino) return false;
|
|
9252
9261
|
const isWindows = process.platform === "win32";
|
|
9253
|
-
if (isWindows && (a.dev ===
|
|
9262
|
+
if (isWindows && (a.dev === 0n || b.dev === 0n)) {
|
|
9254
9263
|
return true;
|
|
9255
9264
|
}
|
|
9256
9265
|
return a.dev === b.dev;
|
|
9257
9266
|
}
|
|
9258
9267
|
function currentFileIdentity(filePath, operations) {
|
|
9259
9268
|
try {
|
|
9260
|
-
|
|
9261
|
-
return { dev: stats.dev, ino: stats.ino };
|
|
9269
|
+
return fileIdentityOf(pathnameStats(filePath, operations));
|
|
9262
9270
|
} catch {
|
|
9263
9271
|
return null;
|
|
9264
9272
|
}
|
|
9265
9273
|
}
|
|
9266
|
-
function descriptorIdentity(fd) {
|
|
9274
|
+
function descriptorIdentity(fd, operations) {
|
|
9267
9275
|
try {
|
|
9268
|
-
|
|
9269
|
-
return { dev: stats.dev, ino: stats.ino };
|
|
9276
|
+
return fileIdentityOf(descriptorStats(fd, operations));
|
|
9270
9277
|
} catch {
|
|
9271
9278
|
return null;
|
|
9272
9279
|
}
|
|
@@ -11768,13 +11775,14 @@ __export(tmux_session_exports, {
|
|
|
11768
11775
|
waitForPaneReady: () => waitForPaneReady,
|
|
11769
11776
|
waitForStartupPaneReady: () => waitForStartupPaneReady,
|
|
11770
11777
|
workerPaneBelongsToOwnedProviderTarget: () => workerPaneBelongsToOwnedProviderTarget,
|
|
11771
|
-
workerPaneBelongsToProviderTarget: () => workerPaneBelongsToProviderTarget
|
|
11778
|
+
workerPaneBelongsToProviderTarget: () => workerPaneBelongsToProviderTarget,
|
|
11779
|
+
workerPaneShellCommand: () => workerPaneShellCommand
|
|
11772
11780
|
});
|
|
11773
|
-
import { existsSync as existsSync23, statSync as statSync4 } from "fs";
|
|
11781
|
+
import { existsSync as existsSync23, mkdtempSync, rmSync as rmSync2, statSync as statSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
11774
11782
|
import { createHash as createHash10, randomUUID as randomUUID14 } from "crypto";
|
|
11775
11783
|
import { execFile as execFile3 } from "child_process";
|
|
11776
11784
|
import { promisify as promisify3 } from "util";
|
|
11777
|
-
import { join as join25, basename as basename12, isAbsolute as isAbsolute7, win32 as win323 } from "path";
|
|
11785
|
+
import { join as join25, basename as basename12, dirname as dirname22, isAbsolute as isAbsolute7, win32 as win323 } from "path";
|
|
11778
11786
|
import { tmpdir as tmpdir3 } from "os";
|
|
11779
11787
|
function tmuxArgsForIdentity(identity, args) {
|
|
11780
11788
|
return ["-S", identity.socket_path, ...args];
|
|
@@ -12649,23 +12657,66 @@ async function verifyWorkerStartCommandSubmitted(paneId, startCmd, opts = {}) {
|
|
|
12649
12657
|
}
|
|
12650
12658
|
return false;
|
|
12651
12659
|
}
|
|
12660
|
+
function writePaneEnvFile(values) {
|
|
12661
|
+
const directory = mkdtempSync(join25(tmpdir3(), "omc-pane-env-"));
|
|
12662
|
+
const file = join25(directory, "env");
|
|
12663
|
+
const body = Object.entries(values).map(([key, value]) => `export ${key}=${shellQuote(value)}
|
|
12664
|
+
`).join("");
|
|
12665
|
+
writeFileSync6(file, body, { mode: 384, flag: "wx" });
|
|
12666
|
+
return file;
|
|
12667
|
+
}
|
|
12668
|
+
function discardPaneEnvFile(envFile) {
|
|
12669
|
+
if (!envFile) return;
|
|
12670
|
+
rmSync2(dirname22(envFile), { recursive: true, force: true });
|
|
12671
|
+
}
|
|
12652
12672
|
function workerPaneShellCommand() {
|
|
12653
12673
|
if (process.platform === "win32" && !isUnixLikeOnWindows()) {
|
|
12654
|
-
return [getDefaultShell()];
|
|
12674
|
+
return { args: [getDefaultShell()], envFile: null };
|
|
12655
12675
|
}
|
|
12656
|
-
if (process.platform === "win32") return [];
|
|
12676
|
+
if (process.platform === "win32") return { args: [], envFile: null };
|
|
12657
12677
|
const shell = getDefaultShell();
|
|
12658
12678
|
const baseline = buildProviderEnvironment({ SHELL: shell });
|
|
12679
|
+
const inline = buildProviderEnvironment({ SHELL: shell }, process.env, process.platform, []);
|
|
12680
|
+
const passthrough = Object.fromEntries(
|
|
12681
|
+
Object.entries(baseline).filter(([key, value]) => inline[key] !== value)
|
|
12682
|
+
);
|
|
12659
12683
|
const inheritedPaneEnvironment = ["TERM", "TMUX", "TMUX_PANE", "TMUX_TMPDIR", "LANG", "LC_ALL", "LC_CTYPE"].map((key) => `${key}="$${key}"`);
|
|
12684
|
+
const inlineAssignments = Object.entries(inline).map(([key, value]) => `${key}=${shellQuote(value)}`);
|
|
12685
|
+
if (Object.keys(passthrough).length === 0) {
|
|
12686
|
+
const command2 = [
|
|
12687
|
+
"/usr/bin/env",
|
|
12688
|
+
"-i",
|
|
12689
|
+
...inlineAssignments,
|
|
12690
|
+
...inheritedPaneEnvironment,
|
|
12691
|
+
shellQuote(shell),
|
|
12692
|
+
"-l"
|
|
12693
|
+
].join(" ");
|
|
12694
|
+
return { args: [command2], envFile: null };
|
|
12695
|
+
}
|
|
12696
|
+
const envFile = writePaneEnvFile(passthrough);
|
|
12697
|
+
const bootstrap = '. "$OMC_PANE_ENV_FILE" && rm -rf -- "${OMC_PANE_ENV_FILE%/*}" && unset OMC_PANE_ENV_FILE && exec "$SHELL" -l';
|
|
12660
12698
|
const command = [
|
|
12661
12699
|
"/usr/bin/env",
|
|
12662
12700
|
"-i",
|
|
12663
|
-
...
|
|
12701
|
+
...inlineAssignments,
|
|
12702
|
+
`OMC_PANE_ENV_FILE=${shellQuote(envFile)}`,
|
|
12664
12703
|
...inheritedPaneEnvironment,
|
|
12665
|
-
|
|
12666
|
-
"-
|
|
12704
|
+
"/bin/sh",
|
|
12705
|
+
"-c",
|
|
12706
|
+
shellQuote(bootstrap)
|
|
12667
12707
|
].join(" ");
|
|
12668
|
-
return [command];
|
|
12708
|
+
return { args: [command], envFile };
|
|
12709
|
+
}
|
|
12710
|
+
async function runPaneCreationCommand(identity, nativeCommand, paneShell) {
|
|
12711
|
+
let result;
|
|
12712
|
+
try {
|
|
12713
|
+
result = await runGuardedNativeTmuxCommand(identity, nativeCommand);
|
|
12714
|
+
} catch (error) {
|
|
12715
|
+
discardPaneEnvFile(paneShell.envFile);
|
|
12716
|
+
throw error;
|
|
12717
|
+
}
|
|
12718
|
+
if (result.outcome === "not_executed") discardPaneEnvFile(paneShell.envFile);
|
|
12719
|
+
return result;
|
|
12669
12720
|
}
|
|
12670
12721
|
function escapeForCmdSet(value) {
|
|
12671
12722
|
return value.replace(/(["%])/g, "$1$1");
|
|
@@ -12964,6 +13015,7 @@ async function splitTeamWorkerPaneWithEvidence(splitTarget, direction, cwd, prov
|
|
|
12964
13015
|
};
|
|
12965
13016
|
}
|
|
12966
13017
|
const splitType = direction === "right" ? "-h" : "-v";
|
|
13018
|
+
const splitPaneShell = workerPaneShellCommand();
|
|
12967
13019
|
const splitArgs = [
|
|
12968
13020
|
"split-window",
|
|
12969
13021
|
splitType,
|
|
@@ -12975,11 +13027,12 @@ async function splitTeamWorkerPaneWithEvidence(splitTarget, direction, cwd, prov
|
|
|
12975
13027
|
"#{pane_id} #{socket_path} #{pid}",
|
|
12976
13028
|
"-c",
|
|
12977
13029
|
cwd,
|
|
12978
|
-
...
|
|
13030
|
+
...splitPaneShell.args
|
|
12979
13031
|
];
|
|
12980
|
-
const splitResult = await
|
|
13032
|
+
const splitResult = await runPaneCreationCommand(
|
|
12981
13033
|
identity,
|
|
12982
|
-
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"])
|
|
13034
|
+
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"]),
|
|
13035
|
+
splitPaneShell
|
|
12983
13036
|
);
|
|
12984
13037
|
const parsed = splitResult.outcome === "executed" ? parseTmuxCreationRecord(
|
|
12985
13038
|
splitResult.stdout,
|
|
@@ -13081,6 +13134,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
13081
13134
|
sessionMode: "detached-session",
|
|
13082
13135
|
...tmuxServerIdentity ? { tmuxServerIdentity: { ...tmuxServerIdentity } } : {}
|
|
13083
13136
|
});
|
|
13137
|
+
const detachedPaneShell = workerPaneShellCommand();
|
|
13084
13138
|
const detachedArgs = [
|
|
13085
13139
|
"new-session",
|
|
13086
13140
|
"-d",
|
|
@@ -13091,7 +13145,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
13091
13145
|
detachedSessionName,
|
|
13092
13146
|
"-c",
|
|
13093
13147
|
cwd,
|
|
13094
|
-
...
|
|
13148
|
+
...detachedPaneShell.args
|
|
13095
13149
|
];
|
|
13096
13150
|
const cleanupFreshDetachedServer = async () => {
|
|
13097
13151
|
if (isPsmux() && freshSocketPathForEvidence) {
|
|
@@ -13120,9 +13174,10 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
13120
13174
|
if (existingDetachedIdentity) {
|
|
13121
13175
|
tmuxServerIdentity = existingDetachedIdentity;
|
|
13122
13176
|
try {
|
|
13123
|
-
detachedResult = await
|
|
13177
|
+
detachedResult = await runPaneCreationCommand(
|
|
13124
13178
|
existingDetachedIdentity,
|
|
13125
|
-
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"])
|
|
13179
|
+
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"]),
|
|
13180
|
+
detachedPaneShell
|
|
13126
13181
|
);
|
|
13127
13182
|
} catch (error) {
|
|
13128
13183
|
const cleaned = await cleanupDetachedSession();
|
|
@@ -13182,11 +13237,13 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
13182
13237
|
throw new Error("tmux_server_identity_unavailable");
|
|
13183
13238
|
}
|
|
13184
13239
|
freshDetachedServerIdentity = tmuxServerIdentity;
|
|
13185
|
-
detachedResult = await
|
|
13240
|
+
detachedResult = await runPaneCreationCommand(
|
|
13186
13241
|
tmuxServerIdentity,
|
|
13187
|
-
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"])
|
|
13242
|
+
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"]),
|
|
13243
|
+
detachedPaneShell
|
|
13188
13244
|
);
|
|
13189
13245
|
} catch (error) {
|
|
13246
|
+
discardPaneEnvFile(detachedPaneShell.envFile);
|
|
13190
13247
|
const cleaned = await cleanupDetachedSession();
|
|
13191
13248
|
if (!cleaned && freshDetachedServerStarted) {
|
|
13192
13249
|
throw new TeamSessionCreationError(
|
|
@@ -13366,6 +13423,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
13366
13423
|
if (useDedicatedWindow) {
|
|
13367
13424
|
const targetSession = sessionAndWindow.split(":")[0] ?? sessionAndWindow;
|
|
13368
13425
|
const windowName = `omc-${sanitizeName(teamName)}`.slice(0, 32);
|
|
13426
|
+
const newWindowPaneShell = workerPaneShellCommand();
|
|
13369
13427
|
const newWindowArgs = [
|
|
13370
13428
|
"new-window",
|
|
13371
13429
|
"-d",
|
|
@@ -13378,13 +13436,14 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
13378
13436
|
windowName,
|
|
13379
13437
|
"-c",
|
|
13380
13438
|
cwd,
|
|
13381
|
-
...
|
|
13439
|
+
...newWindowPaneShell.args
|
|
13382
13440
|
];
|
|
13383
13441
|
let newWindowResult;
|
|
13384
13442
|
try {
|
|
13385
|
-
newWindowResult = await
|
|
13443
|
+
newWindowResult = await runPaneCreationCommand(
|
|
13386
13444
|
tmuxServerIdentity,
|
|
13387
|
-
tmuxCommandString(newWindowArgs, ["#S:#I #{pane_id} #{socket_path} #{pid}"])
|
|
13445
|
+
tmuxCommandString(newWindowArgs, ["#S:#I #{pane_id} #{socket_path} #{pid}"]),
|
|
13446
|
+
newWindowPaneShell
|
|
13388
13447
|
);
|
|
13389
13448
|
} catch (error) {
|
|
13390
13449
|
const creationError = new TeamSessionCreationError(
|
|
@@ -13534,6 +13593,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
13534
13593
|
continue;
|
|
13535
13594
|
}
|
|
13536
13595
|
const splitType = i === 0 ? "-h" : "-v";
|
|
13596
|
+
const splitPaneShell = workerPaneShellCommand();
|
|
13537
13597
|
const splitArgs = [
|
|
13538
13598
|
"split-window",
|
|
13539
13599
|
splitType,
|
|
@@ -13545,11 +13605,12 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
13545
13605
|
"#{pane_id} #{socket_path} #{pid}",
|
|
13546
13606
|
"-c",
|
|
13547
13607
|
cwd,
|
|
13548
|
-
...
|
|
13608
|
+
...splitPaneShell.args
|
|
13549
13609
|
];
|
|
13550
|
-
const splitResult = await
|
|
13610
|
+
const splitResult = await runPaneCreationCommand(
|
|
13551
13611
|
tmuxServerIdentity,
|
|
13552
|
-
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"])
|
|
13612
|
+
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"]),
|
|
13613
|
+
splitPaneShell
|
|
13553
13614
|
);
|
|
13554
13615
|
if (splitResult.outcome !== "executed") {
|
|
13555
13616
|
const creationError = new TeamSessionCreationError(
|
|
@@ -14824,7 +14885,7 @@ var init_tmux_session = __esm({
|
|
|
14824
14885
|
|
|
14825
14886
|
// src/team/mcp-comm.ts
|
|
14826
14887
|
import { realpathSync as realpathSync4 } from "node:fs";
|
|
14827
|
-
import { basename as basename13, dirname as
|
|
14888
|
+
import { basename as basename13, dirname as dirname23, join as join26 } from "node:path";
|
|
14828
14889
|
function isConfirmedNotification(outcome) {
|
|
14829
14890
|
if (!outcome.ok) return false;
|
|
14830
14891
|
if (outcome.transport !== "hook") return true;
|
|
@@ -14850,7 +14911,7 @@ function canonicalNotificationLockIdentity(lockPath) {
|
|
|
14850
14911
|
return realpathSync4(lockPath);
|
|
14851
14912
|
} catch {
|
|
14852
14913
|
try {
|
|
14853
|
-
return join26(realpathSync4(
|
|
14914
|
+
return join26(realpathSync4(dirname23(lockPath)), basename13(lockPath));
|
|
14854
14915
|
} catch {
|
|
14855
14916
|
return lockPath;
|
|
14856
14917
|
}
|
|
@@ -15316,12 +15377,12 @@ var init_mcp_comm = __esm({
|
|
|
15316
15377
|
|
|
15317
15378
|
// src/agents/prompt-helpers.ts
|
|
15318
15379
|
import { readdirSync as readdirSync10 } from "fs";
|
|
15319
|
-
import { join as join27, dirname as
|
|
15380
|
+
import { join as join27, dirname as dirname24, basename as basename14 } from "path";
|
|
15320
15381
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
15321
15382
|
function getPackageDir3() {
|
|
15322
15383
|
if (typeof __dirname !== "undefined" && __dirname) {
|
|
15323
15384
|
const currentDirName = basename14(__dirname);
|
|
15324
|
-
const parentDirName = basename14(
|
|
15385
|
+
const parentDirName = basename14(dirname24(__dirname));
|
|
15325
15386
|
if (currentDirName === "bridge") {
|
|
15326
15387
|
return join27(__dirname, "..");
|
|
15327
15388
|
}
|
|
@@ -15331,7 +15392,7 @@ function getPackageDir3() {
|
|
|
15331
15392
|
}
|
|
15332
15393
|
try {
|
|
15333
15394
|
const __filename = fileURLToPath4(import.meta.url);
|
|
15334
|
-
const __dirname2 =
|
|
15395
|
+
const __dirname2 = dirname24(__filename);
|
|
15335
15396
|
const currentDirName = basename14(__dirname2);
|
|
15336
15397
|
if (currentDirName === "bridge") {
|
|
15337
15398
|
return join27(__dirname2, "..");
|
|
@@ -15385,7 +15446,7 @@ var init_prompt_helpers = __esm({
|
|
|
15385
15446
|
|
|
15386
15447
|
// src/team/worker-bootstrap.ts
|
|
15387
15448
|
import { mkdir as mkdir9, writeFile as writeFile7, appendFile as appendFile2 } from "fs/promises";
|
|
15388
|
-
import { join as join28, dirname as
|
|
15449
|
+
import { join as join28, dirname as dirname25 } from "path";
|
|
15389
15450
|
function buildInstructionPath(...parts) {
|
|
15390
15451
|
return join28(...parts).replaceAll("\\", "/");
|
|
15391
15452
|
}
|
|
@@ -15655,7 +15716,7 @@ ${bootstrapInstructions}
|
|
|
15655
15716
|
}
|
|
15656
15717
|
async function composeInitialInbox(teamName, workerName, content, cwd, cliOutputContract) {
|
|
15657
15718
|
const inboxPath = join28(teamStateRoot(cwd, sanitizeName(teamName)), "workers", sanitizeName(workerName), "inbox.md");
|
|
15658
|
-
await mkdir9(
|
|
15719
|
+
await mkdir9(dirname25(inboxPath), { recursive: true });
|
|
15659
15720
|
const finalContent = cliOutputContract && !content.includes(cliOutputContract) ? `${content}
|
|
15660
15721
|
${cliOutputContract}` : content;
|
|
15661
15722
|
await writeFile7(inboxPath, finalContent, "utf-8");
|
|
@@ -15665,7 +15726,7 @@ async function appendToInbox(teamName, workerName, message, cwd) {
|
|
|
15665
15726
|
const safeWorker = sanitizeName(workerName);
|
|
15666
15727
|
const inboxPath = join28(teamStateRoot(cwd, safeTeam), "workers", safeWorker, "inbox.md");
|
|
15667
15728
|
validateResolvedPath(inboxPath, teamStateRoot(cwd, safeTeam));
|
|
15668
|
-
await mkdir9(
|
|
15729
|
+
await mkdir9(dirname25(inboxPath), { recursive: true });
|
|
15669
15730
|
await appendFile2(inboxPath, `
|
|
15670
15731
|
|
|
15671
15732
|
---
|
|
@@ -15684,7 +15745,7 @@ async function writeWorkerOverlay(params) {
|
|
|
15684
15745
|
const { teamName, workerName, cwd } = params;
|
|
15685
15746
|
const overlay = generateWorkerOverlay(params);
|
|
15686
15747
|
const overlayPath = join28(teamStateRoot(cwd, sanitizeName(teamName)), "workers", sanitizeName(workerName), "AGENTS.md");
|
|
15687
|
-
await mkdir9(
|
|
15748
|
+
await mkdir9(dirname25(overlayPath), { recursive: true });
|
|
15688
15749
|
await writeFile7(overlayPath, overlay, "utf-8");
|
|
15689
15750
|
return overlayPath;
|
|
15690
15751
|
}
|
|
@@ -15884,7 +15945,7 @@ var init_mailbox_outstanding = __esm({
|
|
|
15884
15945
|
|
|
15885
15946
|
// src/team/events.ts
|
|
15886
15947
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
15887
|
-
import { dirname as
|
|
15948
|
+
import { dirname as dirname26 } from "path";
|
|
15888
15949
|
import { mkdir as mkdir10, readFile as readFile12, appendFile as appendFile3 } from "fs/promises";
|
|
15889
15950
|
import { existsSync as existsSync25 } from "fs";
|
|
15890
15951
|
async function appendTeamEvent(teamName, event, cwd) {
|
|
@@ -15895,7 +15956,7 @@ async function appendTeamEvent(teamName, event, cwd) {
|
|
|
15895
15956
|
...event
|
|
15896
15957
|
};
|
|
15897
15958
|
const p = absPath(cwd, TeamPaths.events(teamName));
|
|
15898
|
-
await mkdir10(
|
|
15959
|
+
await mkdir10(dirname26(p), { recursive: true });
|
|
15899
15960
|
await appendFile3(p, `${JSON.stringify(full)}
|
|
15900
15961
|
`, "utf8");
|
|
15901
15962
|
return full;
|
|
@@ -15938,7 +15999,7 @@ async function emitMonitorDerivedEvents(teamName, tasks, workers, previousSnapsh
|
|
|
15938
15999
|
}, cwd).catch(logDerivedEventFailure);
|
|
15939
16000
|
}
|
|
15940
16001
|
if (prevState === "working" && worker.status.state === "idle") {
|
|
15941
|
-
const mailboxDir =
|
|
16002
|
+
const mailboxDir = dirname26(absPath(cwd, TeamPaths.mailbox(teamName, worker.name)));
|
|
15942
16003
|
const outstanding = await countOutstandingForWorker(mailboxDir, worker.name);
|
|
15943
16004
|
await appendTeamEvent(teamName, {
|
|
15944
16005
|
type: "worker_idle",
|
|
@@ -16091,7 +16152,7 @@ var init_worktree_cleanup_safety = __esm({
|
|
|
16091
16152
|
});
|
|
16092
16153
|
|
|
16093
16154
|
// src/team/git-worktree.ts
|
|
16094
|
-
import { existsSync as existsSync27, realpathSync as realpathSync6, readFileSync as readFileSync18, readdirSync as readdirSync11, rmSync as
|
|
16155
|
+
import { existsSync as existsSync27, realpathSync as realpathSync6, readFileSync as readFileSync18, readdirSync as readdirSync11, rmSync as rmSync3, unlinkSync as unlinkSync9, writeFileSync as writeFileSync7 } from "node:fs";
|
|
16095
16156
|
import { join as join31, resolve as resolve10 } from "node:path";
|
|
16096
16157
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
16097
16158
|
function getWorktreePath(repoRoot, teamName, workerName) {
|
|
@@ -16240,7 +16301,7 @@ function installWorktreeRootAgents(teamName, workerName, repoRoot, worktreePath,
|
|
|
16240
16301
|
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
16241
16302
|
};
|
|
16242
16303
|
atomicWriteJson(backupPath, backup);
|
|
16243
|
-
|
|
16304
|
+
writeFileSync7(agentsPath, overlayContent, "utf-8");
|
|
16244
16305
|
}
|
|
16245
16306
|
function restoreWorktreeRootAgents(teamName, workerName, repoRoot, worktreePath) {
|
|
16246
16307
|
const omcRoot = getOmcRoot(repoRoot);
|
|
@@ -16265,7 +16326,7 @@ function restoreWorktreeRootAgents(teamName, workerName, repoRoot, worktreePath)
|
|
|
16265
16326
|
return { restored: false, reason: "agents_dirty" };
|
|
16266
16327
|
}
|
|
16267
16328
|
if (backup.hadOriginal) {
|
|
16268
|
-
|
|
16329
|
+
writeFileSync7(agentsPath, backup.originalContent ?? "", "utf-8");
|
|
16269
16330
|
} else if (existsSync27(agentsPath)) {
|
|
16270
16331
|
unlinkSync9(agentsPath);
|
|
16271
16332
|
}
|
|
@@ -16489,7 +16550,7 @@ function removeWorkerWorktree(teamName, workerName, repoRoot) {
|
|
|
16489
16550
|
expectedRoots: [join31(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "worktrees")],
|
|
16490
16551
|
mainRepoRoots: [repoRoot]
|
|
16491
16552
|
});
|
|
16492
|
-
|
|
16553
|
+
rmSync3(wtPath, { recursive: true, force: true });
|
|
16493
16554
|
}
|
|
16494
16555
|
forgetMetadataUnlocked(repoRoot, teamName, workerName);
|
|
16495
16556
|
});
|
|
@@ -17182,7 +17243,7 @@ var init_merge_coordinator = __esm({
|
|
|
17182
17243
|
// src/team/leader-inbox.ts
|
|
17183
17244
|
import { appendFile as appendFile4, mkdir as mkdir11, writeFile as writeFile8 } from "fs/promises";
|
|
17184
17245
|
import { existsSync as existsSync28 } from "fs";
|
|
17185
|
-
import { dirname as
|
|
17246
|
+
import { dirname as dirname27, join as join33 } from "path";
|
|
17186
17247
|
function leaderInboxPath(teamName, cwd) {
|
|
17187
17248
|
const safe = sanitizeName(teamName);
|
|
17188
17249
|
return join33(teamStateRoot(cwd, safe), "leader", "inbox.md");
|
|
@@ -17190,7 +17251,7 @@ function leaderInboxPath(teamName, cwd) {
|
|
|
17190
17251
|
async function ensureLeaderInbox(teamName, cwd) {
|
|
17191
17252
|
const inboxPath = leaderInboxPath(teamName, cwd);
|
|
17192
17253
|
validateResolvedPath(inboxPath, teamStateRoot(cwd, sanitizeName(teamName)));
|
|
17193
|
-
await mkdir11(
|
|
17254
|
+
await mkdir11(dirname27(inboxPath), { recursive: true });
|
|
17194
17255
|
if (!existsSync28(inboxPath)) {
|
|
17195
17256
|
await writeFile8(inboxPath, LEADER_INBOX_HEADER, "utf-8");
|
|
17196
17257
|
}
|
|
@@ -17199,7 +17260,7 @@ async function ensureLeaderInbox(teamName, cwd) {
|
|
|
17199
17260
|
async function appendToLeaderInbox(teamName, message, cwd) {
|
|
17200
17261
|
const inboxPath = leaderInboxPath(teamName, cwd);
|
|
17201
17262
|
validateResolvedPath(inboxPath, teamStateRoot(cwd, sanitizeName(teamName)));
|
|
17202
|
-
await mkdir11(
|
|
17263
|
+
await mkdir11(dirname27(inboxPath), { recursive: true });
|
|
17203
17264
|
await appendFile4(inboxPath, `
|
|
17204
17265
|
|
|
17205
17266
|
---
|
|
@@ -17289,7 +17350,7 @@ var init_conflict_mailbox = __esm({
|
|
|
17289
17350
|
// src/team/worker-commit-cadence.ts
|
|
17290
17351
|
import { existsSync as existsSync29, watch as fsWatch } from "fs";
|
|
17291
17352
|
import { readFile as readFile13, writeFile as writeFile9, mkdir as mkdir12, unlink as unlink6 } from "fs/promises";
|
|
17292
|
-
import { join as join34, dirname as
|
|
17353
|
+
import { join as join34, dirname as dirname28 } from "path";
|
|
17293
17354
|
import { exec } from "child_process";
|
|
17294
17355
|
function ownsCadence(ctx) {
|
|
17295
17356
|
const current = cadenceOwners.get(ctx.worktreePath);
|
|
@@ -17356,7 +17417,7 @@ async function installPostToolUseHook(worktreePath, workerName) {
|
|
|
17356
17417
|
}
|
|
17357
17418
|
async function pauseHookViaSentinel(worktreePath) {
|
|
17358
17419
|
const sentinelPath = join34(worktreePath, SENTINEL_FILENAME);
|
|
17359
|
-
await mkdir12(
|
|
17420
|
+
await mkdir12(dirname28(sentinelPath), { recursive: true });
|
|
17360
17421
|
await writeFile9(sentinelPath, "", "utf-8");
|
|
17361
17422
|
}
|
|
17362
17423
|
async function resumeHookViaSentinel(worktreePath) {
|
|
@@ -17467,7 +17528,7 @@ var init_worker_commit_cadence = __esm({
|
|
|
17467
17528
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
17468
17529
|
import { existsSync as existsSync30 } from "node:fs";
|
|
17469
17530
|
import { mkdir as mkdir13, appendFile as appendFile5 } from "node:fs/promises";
|
|
17470
|
-
import { dirname as
|
|
17531
|
+
import { dirname as dirname29, join as join35 } from "node:path";
|
|
17471
17532
|
function mergerWorktreePathFor(repoRoot, teamName) {
|
|
17472
17533
|
return join35(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "merger");
|
|
17473
17534
|
}
|
|
@@ -17511,7 +17572,7 @@ function assertRuntimeV2Gate() {
|
|
|
17511
17572
|
}
|
|
17512
17573
|
async function appendEvent(repoRoot, teamName, event) {
|
|
17513
17574
|
const path5 = orchestratorEventLogPath(repoRoot, teamName);
|
|
17514
|
-
await mkdir13(
|
|
17575
|
+
await mkdir13(dirname29(path5), { recursive: true });
|
|
17515
17576
|
const full = {
|
|
17516
17577
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17517
17578
|
team: teamName,
|
|
@@ -17570,7 +17631,7 @@ function isWorktreeRegistered(repoRoot, wtPath) {
|
|
|
17570
17631
|
return false;
|
|
17571
17632
|
}
|
|
17572
17633
|
function ensureMergerWorktree(repoRoot, mergerPath, leaderBranch) {
|
|
17573
|
-
ensureDirWithMode(
|
|
17634
|
+
ensureDirWithMode(dirname29(mergerPath));
|
|
17574
17635
|
if (existsSync30(mergerPath) && isWorktreeRegistered(repoRoot, mergerPath)) {
|
|
17575
17636
|
return;
|
|
17576
17637
|
}
|
|
@@ -18025,7 +18086,7 @@ ${dirtyFiles.map((f) => `- \`${f}\``).join("\n")}`;
|
|
|
18025
18086
|
} catch {
|
|
18026
18087
|
}
|
|
18027
18088
|
const auditPath = teardownAuditPath(config.repoRoot, config.teamName);
|
|
18028
|
-
await mkdir13(
|
|
18089
|
+
await mkdir13(dirname29(auditPath), { recursive: true });
|
|
18029
18090
|
for (const u of unmerged) {
|
|
18030
18091
|
const row = JSON.stringify({
|
|
18031
18092
|
type: "unmerged_at_shutdown",
|
|
@@ -23279,10 +23340,10 @@ import {
|
|
|
23279
23340
|
readFileSync as readFileSync22,
|
|
23280
23341
|
renameSync as renameSync5,
|
|
23281
23342
|
unlinkSync as unlinkSync10,
|
|
23282
|
-
writeFileSync as
|
|
23343
|
+
writeFileSync as writeFileSync8
|
|
23283
23344
|
} from "fs";
|
|
23284
23345
|
import { readFile as readFile18 } from "fs/promises";
|
|
23285
|
-
import { dirname as
|
|
23346
|
+
import { dirname as dirname31, join as join41, resolve as resolve13 } from "path";
|
|
23286
23347
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
23287
23348
|
|
|
23288
23349
|
// src/team/api-interop.ts
|
|
@@ -23302,7 +23363,7 @@ init_git_worktree();
|
|
|
23302
23363
|
init_swallowed_error();
|
|
23303
23364
|
init_types();
|
|
23304
23365
|
import { existsSync as existsSync32, readFileSync as readFileSync20 } from "node:fs";
|
|
23305
|
-
import { dirname as
|
|
23366
|
+
import { dirname as dirname30, join as join38, resolve as resolvePath } from "node:path";
|
|
23306
23367
|
var TEAM_UPDATE_TASK_MUTABLE_FIELDS = /* @__PURE__ */ new Set(["subject", "description", "blocked_by", "requires_code_change", "delegation"]);
|
|
23307
23368
|
var TEAM_UPDATE_TASK_REQUEST_FIELDS = /* @__PURE__ */ new Set(["team_name", "task_id", "workingDirectory", ...TEAM_UPDATE_TASK_MUTABLE_FIELDS]);
|
|
23308
23369
|
var RECOVER_WORKER_REQUEST_FIELDS = /* @__PURE__ */ new Set(["team_name", "worker", "request_id", "timeout_ms"]);
|
|
@@ -23536,7 +23597,7 @@ function stateRootToWorkingDirectory(stateRoot2) {
|
|
|
23536
23597
|
if (idx >= 0) {
|
|
23537
23598
|
const workspaceRoot = absolute.slice(0, idx);
|
|
23538
23599
|
if (workspaceRoot && workspaceRoot !== "/") return workspaceRoot;
|
|
23539
|
-
return
|
|
23600
|
+
return dirname30(dirname30(dirname30(dirname30(absolute))));
|
|
23540
23601
|
}
|
|
23541
23602
|
}
|
|
23542
23603
|
for (const marker of ["/.omg/state", "/.omx/state"]) {
|
|
@@ -23544,10 +23605,10 @@ function stateRootToWorkingDirectory(stateRoot2) {
|
|
|
23544
23605
|
if (idx >= 0) {
|
|
23545
23606
|
const workspaceRoot = absolute.slice(0, idx);
|
|
23546
23607
|
if (workspaceRoot && workspaceRoot !== "/") return workspaceRoot;
|
|
23547
|
-
return
|
|
23608
|
+
return dirname30(dirname30(absolute));
|
|
23548
23609
|
}
|
|
23549
23610
|
}
|
|
23550
|
-
return
|
|
23611
|
+
return dirname30(dirname30(absolute));
|
|
23551
23612
|
}
|
|
23552
23613
|
function resolveTeamWorkingDirectoryFromMetadata(teamName, candidateCwd, workerContext) {
|
|
23553
23614
|
const teamRoot = join38(getOmcRoot(candidateCwd), "state", "team", teamName);
|
|
@@ -23590,7 +23651,7 @@ function resolveTeamWorkingDirectory(teamName, preferredCwd) {
|
|
|
23590
23651
|
if (teamStateExists(normalizedTeamName, cursor)) {
|
|
23591
23652
|
return resolveTeamWorkingDirectoryFromMetadata(normalizedTeamName, cursor, workerContext) ?? cursor;
|
|
23592
23653
|
}
|
|
23593
|
-
const parent =
|
|
23654
|
+
const parent = dirname30(cursor);
|
|
23594
23655
|
if (!parent || parent === cursor) break;
|
|
23595
23656
|
cursor = parent;
|
|
23596
23657
|
}
|
|
@@ -24836,7 +24897,7 @@ function resolveRuntimeCliPath2(env = process.env) {
|
|
|
24836
24897
|
if (env.OMC_RUNTIME_CLI_PATH) {
|
|
24837
24898
|
return env.OMC_RUNTIME_CLI_PATH;
|
|
24838
24899
|
}
|
|
24839
|
-
const moduleDir =
|
|
24900
|
+
const moduleDir = dirname31(fileURLToPath5(import.meta.url));
|
|
24840
24901
|
return join41(moduleDir, "../../bridge/runtime-cli.cjs");
|
|
24841
24902
|
}
|
|
24842
24903
|
function ensureJobsDir(jobsDir) {
|
|
@@ -24961,7 +25022,7 @@ function writeJobToDiskUnlocked(jobId, job, jobsDir) {
|
|
|
24961
25022
|
const targetPath = jobPath(jobsDir, jobId);
|
|
24962
25023
|
const tempPath = `${targetPath}.tmp.${process.pid}.${randomUUID17()}`;
|
|
24963
25024
|
try {
|
|
24964
|
-
|
|
25025
|
+
writeFileSync8(tempPath, JSON.stringify(job), { encoding: "utf-8", mode: 384 });
|
|
24965
25026
|
renameSync5(tempPath, targetPath);
|
|
24966
25027
|
} finally {
|
|
24967
25028
|
try {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-cjs-fail-closed-timeout.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/run-cjs-fail-closed-timeout.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'fs';
|
|
3
|
+
import { tmpdir } from 'os';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { spawnSync } from 'child_process';
|
|
6
|
+
/**
|
|
7
|
+
* The fork's fail-closed contract in scripts/run.cjs: with OMC_HOOK_FAIL_CLOSED=1
|
|
8
|
+
* a hook timeout exits 124 (generic child, trusted Worker, and the SessionEnd
|
|
9
|
+
* foreground budget); without it the runner stays fail-open (exit 0).
|
|
10
|
+
*/
|
|
11
|
+
const RUN_CJS_PATH = join(__dirname, '..', '..', 'scripts', 'run.cjs');
|
|
12
|
+
const NODE = process.execPath;
|
|
13
|
+
const HANG = 'setTimeout(() => process.exit(0), 20000);';
|
|
14
|
+
describe('run.cjs — OMC_HOOK_FAIL_CLOSED hook timeouts', () => {
|
|
15
|
+
let tmpDir;
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
tmpDir = mkdtempSync(join(tmpdir(), 'omc-run-cjs-fail-closed-'));
|
|
18
|
+
});
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
21
|
+
});
|
|
22
|
+
function plugin(name, script, event, timeoutSec) {
|
|
23
|
+
const root = join(tmpDir, `${name}-root`);
|
|
24
|
+
mkdirSync(join(root, 'scripts'), { recursive: true });
|
|
25
|
+
mkdirSync(join(root, 'hooks'), { recursive: true });
|
|
26
|
+
writeFileSync(join(root, 'scripts', 'run.cjs'), '// plugin-root marker');
|
|
27
|
+
writeFileSync(join(root, 'scripts', name), script);
|
|
28
|
+
writeFileSync(join(root, 'hooks', 'hooks.json'), JSON.stringify({
|
|
29
|
+
hooks: {
|
|
30
|
+
[event]: [{ matcher: '', hooks: [{
|
|
31
|
+
type: 'command',
|
|
32
|
+
command: `node "$CLAUDE_PLUGIN_ROOT"/scripts/run.cjs "$CLAUDE_PLUGIN_ROOT"/scripts/${name}`,
|
|
33
|
+
timeout: timeoutSec,
|
|
34
|
+
}] }],
|
|
35
|
+
},
|
|
36
|
+
}));
|
|
37
|
+
return join(root, 'scripts', name);
|
|
38
|
+
}
|
|
39
|
+
function run(target, failClosed, extraEnv = {}) {
|
|
40
|
+
const env = { ...process.env, CLAUDE_PLUGIN_ROOT: join(target, '..', '..'), ...extraEnv };
|
|
41
|
+
delete env.OMC_HOOK_FAIL_CLOSED;
|
|
42
|
+
if (failClosed)
|
|
43
|
+
env.OMC_HOOK_FAIL_CLOSED = '1';
|
|
44
|
+
const result = spawnSync(NODE, [RUN_CJS_PATH, target], { encoding: 'utf-8', env, input: '{}', timeout: 30_000 });
|
|
45
|
+
return { status: result.status, stderr: result.stderr || '' };
|
|
46
|
+
}
|
|
47
|
+
it.each([
|
|
48
|
+
['generic child', 'slow-stop.cjs', HANG, 'Stop'],
|
|
49
|
+
['trusted Worker', 'pre-tool-enforcer.mjs', HANG, 'PreToolUse'],
|
|
50
|
+
])('%s: timeout exits 124 when fail-closed, 0 otherwise', (_label, name, script, event) => {
|
|
51
|
+
const target = plugin(name, script, event, 2);
|
|
52
|
+
const closed = run(target, true);
|
|
53
|
+
expect(closed.status, closed.stderr).toBe(124);
|
|
54
|
+
expect(closed.stderr).toContain('exiting fail-closed (124).');
|
|
55
|
+
const open = run(target, false);
|
|
56
|
+
expect(open.status, open.stderr).toBe(0);
|
|
57
|
+
expect(open.stderr).toContain('exiting fail-open.');
|
|
58
|
+
});
|
|
59
|
+
it('SessionEnd foreground budget: timeout exits 124 when fail-closed, 0 otherwise', () => {
|
|
60
|
+
const target = plugin('session-end.mjs', 'await new Promise((r) => setTimeout(r, 20000));', 'SessionEnd', 5);
|
|
61
|
+
const env = { NODE_ENV: 'test', OMC_SESSION_END_TEST_FOREGROUND_TIMEOUT_MS: '500' };
|
|
62
|
+
const closed = run(target, true, env);
|
|
63
|
+
expect(closed.status, closed.stderr).toBe(124);
|
|
64
|
+
const open = run(target, false, env);
|
|
65
|
+
expect(open.status, open.stderr).toBe(0);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=run-cjs-fail-closed-timeout.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-cjs-fail-closed-timeout.test.js","sourceRoot":"","sources":["../../src/__tests__/run-cjs-fail-closed-timeout.test.ts"],"names":[],"mappings":"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"}
|