Skip to content

Commit cb3d549

Browse files
authored
Merge branch 'main' into fix/subagent-tool-heartbeat-94124
2 parents 62dcec4 + 72cf43f commit cb3d549

951 files changed

Lines changed: 52767 additions & 11788 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/autoreview/SKILL.md

Lines changed: 32 additions & 32 deletions
Large diffs are not rendered by default.

.agents/skills/openclaw-live-updater/SKILL.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ Keep `/Users/steipete/openclaw` a read-only-to-the-agent deployment mirror: clea
3030
- Every successful update sets `actions.gatewayBuild` and rebuilds exact new `main` before any restart.
3131
- Missing, invalid, or stale build output also forces a build, even when Git did not move.
3232
- A dependency-input change, absent `node_modules`, or missing/invalid build provenance first runs `pnpm install --frozen-lockfile`.
33-
- `pnpm build` must leave both canonical stamp heads and `dist/build-info.json.commit` equal to post-update `afterSha`; any missing/mismatched stamp or required artifact blocks restart.
33+
- Stop the managed Gateway immediately before `pnpm build`; never mutate the live `dist` tree while an old Gateway can dynamically import from it. `pnpm build` must leave both canonical stamp heads and `dist/build-info.json.commit` equal to post-update `afterSha`; any missing/mismatched stamp or required artifact blocks restart.
3434
- Only after exact-SHA build proof may it restart the managed Gateway and require `gateway status --deep --require-rpc --json` plus `health --verbose --json`.
35+
- After every managed restart, query Gateway logs through RPC, restrict the audit to entries emitted since that restart began, report warning summaries, and fail the pass on any error/fatal entry. If RPC verification or log retrieval fails, still inspect the local structured log for that restart window. Never accept supervisor or RPC health without this restart-window log audit.
3536

3637
Treat supervisor state alone as insufficient. If build or proof fails, leave the new mirror head intact and retry the stale/missing build on the next heartbeat; never run the old `dist` against new source.
3738

.agents/skills/openclaw-live-updater/scripts/update-main.mjs

Lines changed: 148 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,9 @@ function assertExactBuild(checkout, expectedSha) {
524524

525525
function restartGateway(runCommand, checkout, expectedSha) {
526526
assertExactBuild(checkout, expectedSha);
527+
const startedAtMs = Date.now();
527528
runCommand("pnpm", ["openclaw", "gateway", "restart"], checkout);
529+
return startedAtMs;
528530
}
529531

530532
function verifyGateway(runCommand, checkout, expectedSha) {
@@ -537,6 +539,132 @@ function verifyGateway(runCommand, checkout, expectedSha) {
537539
runCommand("pnpm", ["openclaw", "health", "--verbose", "--json"], checkout);
538540
}
539541

542+
function summarizeGatewayLogEntry(entry) {
543+
return {
544+
time: entry.time,
545+
level: entry.level,
546+
subsystem: entry.subsystem ?? null,
547+
message: String(entry.message ?? "").slice(0, 500),
548+
};
549+
}
550+
551+
export function parseGatewayLogAudit(output, sinceMs) {
552+
const entries = output
553+
.split("\n")
554+
.filter(Boolean)
555+
.flatMap((line) => {
556+
try {
557+
const raw = JSON.parse(line);
558+
const rawLevel = raw.type === "log" ? raw.level : raw._meta?.logLevelName;
559+
const level = String(rawLevel ?? "").toLowerCase();
560+
const time = raw.time ?? raw._meta?.date;
561+
const timestamp = Date.parse(time ?? "");
562+
if (!level || !Number.isFinite(timestamp) || timestamp < sinceMs) {
563+
return [];
564+
}
565+
let subsystem = raw.subsystem ?? null;
566+
if (!subsystem && typeof raw["0"] === "string") {
567+
try {
568+
subsystem = JSON.parse(raw["0"]).subsystem ?? null;
569+
} catch {
570+
subsystem = null;
571+
}
572+
}
573+
return [
574+
{
575+
time,
576+
level,
577+
subsystem,
578+
message: raw.message ?? raw["1"] ?? raw["0"] ?? "",
579+
},
580+
];
581+
} catch {
582+
return [];
583+
}
584+
});
585+
const errors = entries
586+
.filter((entry) => entry.level === "error" || entry.level === "fatal")
587+
.map(summarizeGatewayLogEntry);
588+
const warnings = entries.filter((entry) => entry.level === "warn").map(summarizeGatewayLogEntry);
589+
return {
590+
entries: entries.length,
591+
errorCount: errors.length,
592+
warningCount: warnings.length,
593+
errors: errors.slice(0, 20),
594+
warnings: warnings.slice(0, 20),
595+
};
596+
}
597+
598+
function localDateKey(date) {
599+
const year = date.getFullYear();
600+
const month = String(date.getMonth() + 1).padStart(2, "0");
601+
const day = String(date.getDate()).padStart(2, "0");
602+
return `${year}-${month}-${day}`;
603+
}
604+
605+
function readFallbackGatewayLogs(sinceMs) {
606+
const dates = new Set([localDateKey(new Date(sinceMs)), localDateKey(new Date())]);
607+
const directories = new Set(["/tmp/openclaw", path.join(tmpdir(), "openclaw")]);
608+
const contents = [];
609+
for (const directory of directories) {
610+
for (const date of dates) {
611+
const logPath = path.join(directory, `openclaw-${date}.log`);
612+
if (existsSync(logPath)) {
613+
contents.push(readFileSync(logPath, "utf8"));
614+
}
615+
}
616+
}
617+
return contents.join("\n");
618+
}
619+
620+
function defaultAuditGatewayLogs(checkout, sinceMs) {
621+
let output;
622+
try {
623+
output = execFileSync(
624+
process.execPath,
625+
[
626+
"openclaw.mjs",
627+
"logs",
628+
"--json",
629+
"--limit",
630+
"1000",
631+
"--max-bytes",
632+
"1000000",
633+
"--timeout",
634+
"10000",
635+
],
636+
{ cwd: checkout, encoding: "utf8", maxBuffer: 4 * 1024 * 1024 },
637+
);
638+
} catch (error) {
639+
output = readFallbackGatewayLogs(sinceMs);
640+
if (!output) {
641+
throw error;
642+
}
643+
}
644+
const audit = parseGatewayLogAudit(output, sinceMs);
645+
if (audit.errorCount > 0) {
646+
throw new UpdateInvariantError(
647+
"gateway_restart_log_errors",
648+
`Gateway emitted ${audit.errorCount} error/fatal log entries after restart: ${JSON.stringify(audit.errors.slice(0, 5))}`,
649+
);
650+
}
651+
return audit;
652+
}
653+
654+
function verifyAndAuditGateway({ runCommand, auditGatewayLogs, checkout, expectedSha, sinceMs }) {
655+
let verificationError;
656+
try {
657+
verifyGateway(runCommand, checkout, expectedSha);
658+
} catch (error) {
659+
verificationError = error;
660+
}
661+
const audit = auditGatewayLogs(checkout, sinceMs);
662+
if (verificationError) {
663+
throw verificationError;
664+
}
665+
return audit;
666+
}
667+
540668
export function findExactMacTarget(processes, executable) {
541669
const target = processes
542670
.split("\n")
@@ -601,6 +729,8 @@ export function maintainMain(options, dependencies = {}) {
601729
}
602730
const runCommand = dependencies.runCommand ?? defaultRunCommand;
603731
const verifyMacTarget = dependencies.verifyMacTarget ?? defaultVerifyMacTarget;
732+
const auditGatewayLogs = dependencies.auditGatewayLogs ?? defaultAuditGatewayLogs;
733+
let gatewayLogAudit = null;
604734
let queuedMacState = null;
605735
if (actions.macAppRebuild) {
606736
queuedMacState = {
@@ -617,18 +747,31 @@ export function maintainMain(options, dependencies = {}) {
617747
runCommand("pnpm", ["install", "--frozen-lockfile"], update.checkout);
618748
}
619749
if (actions.gatewayBuild) {
750+
runCommand("pnpm", ["openclaw", "gateway", "stop"], update.checkout);
620751
runCommand("pnpm", ["build"], update.checkout);
621752
assertExactBuild(update.checkout, update.afterSha);
622-
restartGateway(runCommand, update.checkout, update.afterSha);
623-
verifyGateway(runCommand, update.checkout, update.afterSha);
753+
const restartStartedAt = restartGateway(runCommand, update.checkout, update.afterSha);
754+
gatewayLogAudit = verifyAndAuditGateway({
755+
runCommand,
756+
auditGatewayLogs,
757+
checkout: update.checkout,
758+
expectedSha: update.afterSha,
759+
sinceMs: restartStartedAt,
760+
});
624761
} else {
625762
try {
626763
verifyGateway(runCommand, update.checkout, update.afterSha);
627764
} catch {
628765
actions.gatewayRestart = true;
629766
actions.gatewaySelfHeal = true;
630-
restartGateway(runCommand, update.checkout, update.afterSha);
631-
verifyGateway(runCommand, update.checkout, update.afterSha);
767+
const restartStartedAt = restartGateway(runCommand, update.checkout, update.afterSha);
768+
gatewayLogAudit = verifyAndAuditGateway({
769+
runCommand,
770+
auditGatewayLogs,
771+
checkout: update.checkout,
772+
expectedSha: update.afterSha,
773+
sinceMs: restartStartedAt,
774+
});
632775
}
633776
}
634777
if (actions.macAppRebuild) {
@@ -664,6 +807,7 @@ export function maintainMain(options, dependencies = {}) {
664807
buildBefore,
665808
buildChangedPaths,
666809
actions,
810+
...(gatewayLogAudit ? { gatewayLogAudit } : {}),
667811
...(maintenanceState.macTarget ? { macTarget: maintenanceState.macTarget } : {}),
668812
};
669813
} finally {

.agents/skills/openclaw-pr-maintainer/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ gh search issues --repo openclaw/openclaw --match title,body --limit 50 \
305305
- If bot review conversations exist on your PR, address them and resolve them yourself once fixed.
306306
- Leave a review conversation unresolved only when reviewer or maintainer judgment is still needed.
307307
- Before landing any PR with non-trivial code changes, run `$autoreview` until no accepted/actionable findings remain, unless equivalent manual review already covered it, the change is trivial/docs-only, or the user opts out.
308-
- When an agent is landing or merging a PR targeting `main`, use only the repo-native `scripts/pr` wrapper: run `scripts/pr review-init <PR>`, follow its emitted checkout/guard guidance, initialize and complete review artifacts with `scripts/pr review-artifacts-init <PR>`, validate them with `scripts/pr review-validate-artifacts <PR>`, then run `OPENCLAW_TESTBOX=1 scripts/pr prepare-run <PR>` and `scripts/pr merge-run <PR>`. The Testbox flag is mandatory for agents: it verifies exact-head hosted CI/Testbox instead of running full `pnpm` gates locally.
308+
- When an agent is landing or merging a PR targeting `main`, use only the repo-native `scripts/pr` wrapper: run `scripts/pr review-init <PR>`, follow its emitted checkout/guard guidance, initialize and complete review artifacts with `scripts/pr review-artifacts-init <PR>`, validate them with `scripts/pr review-validate-artifacts <PR>`, then run `OPENCLAW_TESTBOX=1 scripts/pr prepare-run <PR>` and `scripts/pr merge-run <PR>`. The Testbox flag is mandatory for agents: it verifies hosted CI/Testbox on the current head or reuses a patch-identical pre-rebase run green within 24 hours instead of running full `pnpm` gates locally. Do not rebase only because `main` advanced; behind-main drift is advisory unless strict drift is explicitly enabled, while GitHub still blocks conflicts.
309309
- Use `scripts/committer "<msg>" <file...>` for scoped commits instead of manual `git add` and `git commit`.
310310
- Keep commit messages concise and action-oriented.
311311
- Group related changes; avoid bundling unrelated refactors.

.agents/skills/openclaw-small-bugfix-sweep/SKILL.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Triage reviews, proves, and patches local fixes first; publishing waits for Pete
1313

1414
Peter always wants to review code before commits.
1515
Default flow:
16+
1617
1. Review each issue deeply enough to prove current behavior and root cause.
1718
2. Fix only easy, high-confidence bugs with narrow ownership and focused proof.
1819
3. Stop with the dirty diff summary, touched files, and test/gate output for Peter's manual review.

.agents/skills/openclaw-testing/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ commands.
150150
tools to require an IMDSv2 token, prove the IAM credentials endpoint returns
151151
404, and compare remote `git rev-parse HEAD` with the full reviewed head SHA.
152152
Unset all `CRABBOX_TAILSCALE*` overrides, pass `--network public
153-
--tailscale=false`, clear exit-node/LAN flags, then require `crabbox inspect`
153+
--tailscale=false`, clear exit-node/LAN flags, then require `crabbox inspect`
154154
to report `network=public` and no Tailscale state before uploading any script.
155155
Upload trusted `scripts/crabbox-untrusted-bootstrap.sh` with `--fresh-pr`; it
156156
bootstraps Node 24 and repository-pinned pnpm before executing PR code and

.github/codeql/codeql-network-runtime-boundary-critical-quality.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ paths:
1414
- src/infra/push-apns-http2.ts
1515
- src/infra/ssh-tunnel.ts
1616
- src/proxy-capture
17-
- extensions/codex-supervisor/src/json-rpc-client.ts
17+
- extensions/codex/src/app-server/transport-websocket.ts
1818
- extensions/irc/src
1919
- extensions/qa-lab/src
2020
- packages/net-policy/src

.github/codeql/codeql-process-exec-boundary-critical-security.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ paths:
2828
- extensions/codex/src/app-server/sandbox-exec-server
2929
- extensions/codex/src/app-server/transport-stdio.ts
3030
- extensions/codex/src/node-cli-sessions.ts
31-
- extensions/codex-supervisor/src/json-rpc-client.ts
3231
- extensions/file-transfer/src
3332
- extensions/google-meet/src
3433
- extensions/imessage/src

.github/codeql/openclaw-boundary/queries/raw-socket-callsite-classification.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ predicate allowedRawSocketClientCall(Expr call) {
7676
or
7777
allowedOwnerScope(call, "src/proxy-capture/proxy-server.ts", "startDebugProxyServer")
7878
or
79-
allowedOwnerScope(call, "extensions/codex-supervisor/src/json-rpc-client.ts", "connectCodexSupervisorUnixSocket")
79+
allowedOwnerScope(call, "extensions/codex/src/app-server/transport-websocket.ts", "connectCodexAppServerUnixSocket")
8080
or
8181
allowedOwnerScope(call, "extensions/irc/src/client.ts", "connectIrcClient")
8282
or

.github/labeler.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -444,12 +444,11 @@
444444
- changed-files:
445445
- any-glob-to-any-file:
446446
- "extensions/codex/**"
447-
"extensions: codex-supervisor":
448-
- changed-files:
449-
- any-glob-to-any-file:
450-
- "extensions/codex-supervisor/**"
451-
- "docs/plugins/reference/codex-supervisor.md"
452-
- "docs/specs/claw-supervisor.md"
447+
- "docs/plugins/codex-harness.md"
448+
- "docs/plugins/codex-harness-reference.md"
449+
- "docs/plugins/codex-harness-runtime.md"
450+
- "docs/plugins/codex-supervision.md"
451+
- "docs/specs/codex-supervision.md"
453452
"extensions: copilot":
454453
- changed-files:
455454
- any-glob-to-any-file:

0 commit comments

Comments
 (0)