Skip to content

Commit 74f9088

Browse files
committed
fix(release): unblock beta validation
1 parent 236a0c8 commit 74f9088

9 files changed

Lines changed: 106 additions & 34 deletions

.github/workflows/openclaw-live-and-e2e-checks-reusable.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,7 +2000,7 @@ jobs:
20002000
profiles: stable full
20012001
- suite_id: native-live-src-gateway-profiles-minimax
20022002
label: Native live gateway profiles MiniMax
2003-
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M3,minimax-portal/MiniMax-M3 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
2003+
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M2.7,minimax-portal/MiniMax-M2.7 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
20042004
timeout_minutes: 60
20052005
profile_env_only: false
20062006
profiles: stable full
@@ -2303,7 +2303,7 @@ jobs:
23032303
profiles: stable full
23042304
- suite_id: live-gateway-minimax-docker
23052305
label: Docker live gateway MiniMax
2306-
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M3,minimax-portal/MiniMax-M3 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh
2306+
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M2.7,minimax-portal/MiniMax-M2.7 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh
23072307
timeout_minutes: 40
23082308
profile_env_only: false
23092309
profiles: stable full

.github/workflows/openclaw-performance.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ on:
4545
kova_ref:
4646
description: openclaw/Kova Git ref to install
4747
required: false
48-
default: b63b6f9e20efb23641df00487e982230d81a90ac
48+
default: 4f146016583018bad9e24f8e64a6af5f963bb7ee
4949
type: string
5050
dispatch_id:
5151
description: Optional parent workflow dispatch identifier
@@ -98,7 +98,7 @@ jobs:
9898
live: "true"
9999
include_filters: "scenario:agent-cold-warm-message"
100100
env:
101-
KOVA_REF: ${{ inputs.kova_ref || 'b63b6f9e20efb23641df00487e982230d81a90ac' }}
101+
KOVA_REF: ${{ inputs.kova_ref || '4f146016583018bad9e24f8e64a6af5f963bb7ee' }}
102102
KOVA_HOME: ${{ github.workspace }}/.artifacts/kova/home/${{ matrix.lane }}
103103
PERFORMANCE_HELPER_DIR: ${{ github.workspace }}/.artifacts/performance-workflow
104104
REPORT_DIR: ${{ github.workspace }}/.artifacts/kova/reports/${{ matrix.lane }}

extensions/matrix/src/matrix/thread-bindings.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import path from "node:path";
66
import type { OpenKeyedStoreOptions } from "openclaw/plugin-sdk/plugin-state-runtime";
77
import {
88
createPluginStateKeyedStoreForTests,
9+
createPluginStateSyncKeyedStoreForTests,
910
resetPluginStateStoreForTests,
1011
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
1112
import { getSessionBindingService, testing } from "openclaw/plugin-sdk/session-binding-runtime";
@@ -197,6 +198,8 @@ describe("matrix thread bindings", () => {
197198
state: {
198199
openKeyedStore: (options: OpenKeyedStoreOptions) =>
199200
createPluginStateKeyedStoreForTests("matrix", options),
201+
openSyncKeyedStore: (options: OpenKeyedStoreOptions) =>
202+
createPluginStateSyncKeyedStoreForTests("matrix", options),
200203
resolveStateDir: () => stateDir,
201204
},
202205
} as PluginRuntime);

scripts/lib/kova-report-gate.mjs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,24 @@ export function evaluateToleratedPartialKovaReport(report) {
3636
return { ok: false, reason: `blocking count was ${JSON.stringify(gate.blockingCount)}` };
3737
}
3838

39-
const baselineRegressionCount = numericCount(
40-
report?.baseline?.comparison?.regressionCount ?? report?.gate?.baseline?.regressionCount,
41-
);
42-
if (baselineRegressionCount === undefined) {
43-
return { ok: false, reason: "missing baseline regression count" };
44-
}
45-
if (baselineRegressionCount !== 0) {
46-
return {
47-
ok: false,
48-
reason: `baseline regression count was ${JSON.stringify(baselineRegressionCount)}`,
49-
};
39+
const reportBaseline = report?.baseline;
40+
const gateBaseline = report?.gate?.baseline;
41+
if (
42+
(reportBaseline !== null && reportBaseline !== undefined) ||
43+
(gateBaseline !== null && gateBaseline !== undefined)
44+
) {
45+
const baselineRegressionCount = numericCount(
46+
reportBaseline?.comparison?.regressionCount ?? gateBaseline?.regressionCount,
47+
);
48+
if (baselineRegressionCount === undefined) {
49+
return { ok: false, reason: "missing baseline regression count" };
50+
}
51+
if (baselineRegressionCount !== 0) {
52+
return {
53+
ok: false,
54+
reason: `baseline regression count was ${JSON.stringify(baselineRegressionCount)}`,
55+
};
56+
}
5057
}
5158

5259
const statuses = report?.summary?.statuses;

scripts/test-live-cli-backend-docker.sh

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,10 @@ if [[ "$CLI_PROVIDER" == "claude-cli" && "$CLI_AUTH_MODE" == "subscription" ]];
122122
CLAUDE_CREDS_FILE="$HOME/.claude/.credentials.json"
123123
CLAUDE_SUBSCRIPTION_AUTH_SOURCE=""
124124
CLAUDE_SUBSCRIPTION_TYPE=""
125-
if [[ -f "$CLAUDE_CREDS_FILE" ]]; then
125+
if [[ -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]]; then
126+
CLAUDE_SUBSCRIPTION_TYPE="oauth-token"
127+
CLAUDE_SUBSCRIPTION_AUTH_SOURCE="env-token"
128+
elif [[ -f "$CLAUDE_CREDS_FILE" ]]; then
126129
CLAUDE_SUBSCRIPTION_TYPE="$(
127130
node -e '
128131
const fs = require("node:fs");
@@ -138,9 +141,6 @@ if [[ "$CLI_PROVIDER" == "claude-cli" && "$CLI_AUTH_MODE" == "subscription" ]];
138141
exit 1
139142
}
140143
CLAUDE_SUBSCRIPTION_AUTH_SOURCE="credentials-file"
141-
elif [[ -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]]; then
142-
CLAUDE_SUBSCRIPTION_TYPE="oauth-token"
143-
CLAUDE_SUBSCRIPTION_AUTH_SOURCE="env-token"
144144
else
145145
echo "ERROR: Claude subscription auth requires either:" >&2
146146
echo " - $CLAUDE_CREDS_FILE with claudeAiOauth.subscriptionType, or" >&2
@@ -200,6 +200,16 @@ else
200200
AUTH_FILES+=("$auth_file")
201201
done < <(openclaw_live_collect_auth_files_from_csv "$CLI_PROVIDER")
202202
fi
203+
if [[ "${CLAUDE_SUBSCRIPTION_AUTH_SOURCE:-}" == "env-token" ]]; then
204+
retained_auth_files=()
205+
for auth_file in "${AUTH_FILES[@]}"; do
206+
case "$auth_file" in
207+
.claude.json | .claude/.credentials.json) ;;
208+
*) retained_auth_files+=("$auth_file") ;;
209+
esac
210+
done
211+
AUTH_FILES=("${retained_auth_files[@]}")
212+
fi
203213
AUTH_DIRS_CSV=""
204214
if ((${#AUTH_DIRS[@]} > 0)); then
205215
AUTH_DIRS_CSV="$(openclaw_live_join_csv "${AUTH_DIRS[@]}")"
@@ -327,15 +337,15 @@ if [ "$provider" = "claude-cli" ]; then
327337
node - <<'NODE'
328338
const fs = require("node:fs");
329339
const file = `${process.env.HOME}/.claude/.credentials.json`;
330-
if (fs.existsSync(file)) {
340+
if (process.env.CLAUDE_CODE_OAUTH_TOKEN?.trim()) {
341+
console.error("[claude-subscription] using CLAUDE_CODE_OAUTH_TOKEN from environment");
342+
} else if (fs.existsSync(file)) {
331343
const data = JSON.parse(fs.readFileSync(file, "utf8"));
332344
const subscriptionType = String(data?.claudeAiOauth?.subscriptionType ?? "").trim();
333345
if (!subscriptionType || subscriptionType === "unknown") {
334346
throw new Error("Claude subscription OAuth credentials are missing subscriptionType.");
335347
}
336348
console.error(`[claude-subscription] subscriptionType=${subscriptionType}`);
337-
} else if (process.env.CLAUDE_CODE_OAUTH_TOKEN?.trim()) {
338-
console.error("[claude-subscription] using CLAUDE_CODE_OAUTH_TOKEN from environment");
339349
} else {
340350
throw new Error("Claude subscription OAuth token or credentials file is required.");
341351
}
@@ -365,17 +375,30 @@ WRAP
365375
if [ "$auth_mode" = "subscription" ]; then
366376
claude --version
367377
direct_token="OPENCLAW-CLAUDE-SUBSCRIPTION-DIRECT"
368-
direct_output="$(
369-
claude \
370-
-p "Reply exactly: $direct_token" \
371-
--output-format text \
372-
--model sonnet \
373-
--permission-mode bypassPermissions \
374-
--setting-sources user \
375-
--strict-mcp-config \
376-
--mcp-config '{"mcpServers":{}}' \
377-
--no-session-persistence
378-
)"
378+
direct_probe_log="$(mktemp)"
379+
set +e
380+
claude \
381+
-p "Reply exactly: $direct_token" \
382+
--output-format text \
383+
--model sonnet \
384+
--permission-mode bypassPermissions \
385+
--setting-sources user \
386+
--strict-mcp-config \
387+
--mcp-config '{"mcpServers":{}}' \
388+
--no-session-persistence >"$direct_probe_log" 2>&1
389+
direct_probe_status=$?
390+
set -e
391+
direct_output="$(<"$direct_probe_log")"
392+
if [ "$direct_probe_status" -ne 0 ]; then
393+
echo "ERROR: direct Claude subscription probe exited with status $direct_probe_status." >&2
394+
sed -E \
395+
-e 's/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/<redacted-email>/g' \
396+
-e 's/(sk-ant-|sk-)[A-Za-z0-9_-]+/<redacted-secret>/g' \
397+
"$direct_probe_log" >&2
398+
rm -f "$direct_probe_log"
399+
exit "$direct_probe_status"
400+
fi
401+
rm -f "$direct_probe_log"
379402
if [[ "$direct_output" != *"$direct_token"* ]]; then
380403
echo "ERROR: direct Claude subscription probe did not return expected token." >&2
381404
echo "$direct_output" >&2

test/scripts/kova-report-gate.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,16 @@ describe("scripts/lib/kova-report-gate.mjs", () => {
9090
).toEqual({ ok: false, reason: "missing baseline regression count" });
9191
});
9292

93+
it("accepts partial reports without a baseline comparison", () => {
94+
expect(
95+
evaluateToleratedPartialKovaReport(
96+
partialReport({
97+
baseline: null,
98+
}),
99+
),
100+
).toEqual({ ok: true });
101+
});
102+
93103
it("rejects partial reports with malformed zero-like baseline regression counts", () => {
94104
expect(
95105
evaluateToleratedPartialKovaReport(

test/scripts/openclaw-performance-workflow.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ describe("OpenClaw performance workflow", () => {
4343
expect(workflow).toContain("Optional parent workflow dispatch identifier");
4444
});
4545

46+
it("pins the Kova evaluator that reads agent payloads", () => {
47+
const workflow = readFileSync(WORKFLOW, "utf8");
48+
const kovaRef = "4f146016583018bad9e24f8e64a6af5f963bb7ee";
49+
50+
expect(workflow).toContain(`default: ${kovaRef}`);
51+
expect(workflow).toContain(`inputs.kova_ref || '${kovaRef}'`);
52+
});
53+
4654
it("uses the clawgrit reports token for every report repo push path", () => {
4755
const prepare = findStep("Prepare clawgrit reports checkout");
4856
const publish = findStep("Publish to clawgrit reports");

test/scripts/package-acceptance-workflow.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,7 @@ describe("package artifact reuse", () => {
791791
"OPENCLAW_LIVE_GATEWAY_MODELS=google/gemini-3.1-pro-preview node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles",
792792
);
793793
expect(workflow).toContain(
794-
"OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M3,minimax-portal/MiniMax-M3 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2",
794+
"OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M2.7,minimax-portal/MiniMax-M2.7 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2",
795795
);
796796
expect(workflow).toMatch(
797797
/suite_id: native-live-src-gateway-profiles-fireworks[\s\S]*?timeout_minutes: 30[\s\S]*?advisory: true/u,
@@ -894,6 +894,9 @@ describe("package artifact reuse", () => {
894894
expect(workflow).toContain(
895895
"command: OPENCLAW_LIVE_GATEWAY_THINKING=off OPENCLAW_LIVE_GATEWAY_PROVIDERS=openai OPENCLAW_LIVE_GATEWAY_MODELS=openai/gpt-5.5 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1",
896896
);
897+
expect(workflow).toContain(
898+
"command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M2.7,minimax-portal/MiniMax-M2.7 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2",
899+
);
897900
expect(workflow).toContain(
898901
'command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 45m bash .release-harness/scripts/test-live-cli-backend-docker.sh',
899902
);

test/scripts/test-live-cli-backend-docker.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,22 @@ describe("scripts/test-live-cli-backend-docker.sh", () => {
4848
expect(result.stderr).not.toContain("Cannot find package 'tsx'");
4949
expect(result.stderr).not.toContain("docker");
5050
});
51+
52+
it("prints redacted Claude subscription probe failures", () => {
53+
const script = fs.readFileSync(SCRIPT_PATH, "utf8");
54+
55+
expect(script).toContain('direct_probe_log="$(mktemp)"');
56+
expect(script).toContain("direct Claude subscription probe exited with status");
57+
expect(script).toContain("<redacted-email>");
58+
expect(script).toContain("<redacted-secret>");
59+
});
60+
61+
it("prefers explicit Claude setup tokens over staged credentials", () => {
62+
const script = fs.readFileSync(SCRIPT_PATH, "utf8");
63+
64+
expect(script).toMatch(
65+
/if \[\[ -n "\$\{CLAUDE_CODE_OAUTH_TOKEN:-\}" \]\]; then[\s\S]*?CLAUDE_SUBSCRIPTION_AUTH_SOURCE="env-token"[\s\S]*?elif \[\[ -f "\$CLAUDE_CREDS_FILE" \]\]; then/,
66+
);
67+
expect(script).toContain(".claude.json | .claude/.credentials.json) ;;");
68+
});
5169
});

0 commit comments

Comments
 (0)