Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -367,27 +367,50 @@ jobs:
NODE_OPTIONS: --max-old-space-size=4096
run: pnpm test

- name: Detect Swift-relevant changes
id: swift_changes
shell: bash
run: |
set -euo pipefail
if [ "${{ github.event_name }}" != "pull_request" ]; then
echo "present=true" >> "$GITHUB_OUTPUT"
exit 0
fi
git fetch --no-tags --prune --depth=50 origin "${{ github.base_ref }}"
git diff --name-only "origin/${{ github.base_ref }}...HEAD" > /tmp/openclaw-changed-files.txt
cat /tmp/openclaw-changed-files.txt
if grep -E '(^|/)(Package\.swift|\.swiftlint\.yml|\.swiftformat|Brewfile)$|\.swift$|\.xcodeproj/|\.xcworkspace/|^apps/macos/' /tmp/openclaw-changed-files.txt; then
echo "present=true" >> "$GITHUB_OUTPUT"
else
echo "present=false" >> "$GITHUB_OUTPUT"
fi

# --- Xcode/Swift setup ---
- name: Select Xcode 26.1
if: steps.swift_changes.outputs.present == 'true'
run: |
sudo xcode-select -s /Applications/Xcode_26.1.app
xcodebuild -version

- name: Install XcodeGen / SwiftLint / SwiftFormat
if: steps.swift_changes.outputs.present == 'true'
run: brew install xcodegen swiftlint swiftformat

- name: Show toolchain
if: steps.swift_changes.outputs.present == 'true'
run: |
sw_vers
xcodebuild -version
swift --version

- name: Swift lint
if: steps.swift_changes.outputs.present == 'true'
run: |
swiftlint --config .swiftlint.yml
swiftformat --lint apps/macos/Sources --config .swiftformat

- name: Swift build (release)
if: steps.swift_changes.outputs.present == 'true'
run: |
set -euo pipefail
for attempt in 1 2 3; do
Expand All @@ -400,6 +423,7 @@ jobs:
exit 1

- name: Swift test
if: steps.swift_changes.outputs.present == 'true'
run: |
set -euo pipefail
for attempt in 1 2 3; do
Expand Down
39 changes: 39 additions & 0 deletions .github/workflows/prophet-workspace-plugin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Prophet Workspace Plugin

on:
pull_request:
paths:
- 'extensions/prophet-workspace/**'
- '.github/workflows/prophet-workspace-plugin.yml'
push:
branches:
- main
paths:
- 'extensions/prophet-workspace/**'
- '.github/workflows/prophet-workspace-plugin.yml'

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Validate registered hook RPC methods
run: |
set -euo pipefail
grep -q 'prophetWorkspace.status' extensions/prophet-workspace/index.ts
grep -q 'prophetWorkspace.emitCarrier' extensions/prophet-workspace/index.ts
grep -q 'prophetWorkspace.evaluateMembraneDecision' extensions/prophet-workspace/index.ts
grep -q 'prophetWorkspace.appendLedgerEvent' extensions/prophet-workspace/index.ts
grep -q 'prophetWorkspace.resolveConnectedAppGrant' extensions/prophet-workspace/index.ts
- name: Validate no-op safety posture
run: |
set -euo pipefail
grep -q 'reason: "not-wired"' extensions/prophet-workspace/src/hooks.ts
grep -q 'accepted: false' extensions/prophet-workspace/src/hooks.ts
grep -q 'allow: false' extensions/prophet-workspace/src/hooks.ts
grep -q 'ok: false' extensions/prophet-workspace/src/hooks.ts
grep -q 'granted: false' extensions/prophet-workspace/src/hooks.ts
73 changes: 69 additions & 4 deletions extensions/prophet-workspace/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { createNoopProphetWorkspaceHooks } from "./src/hooks.js";

const prophetWorkspacePlugin = {
id: "prophet-workspace",
name: "Prophet Workspace",
Expand Down Expand Up @@ -30,6 +32,7 @@ const prophetWorkspacePlugin = {
},
register(api: any) {
const config = this.configSchema.parse(api.pluginConfig);
const hooks = createNoopProphetWorkspaceHooks(api);

api.registerGatewayMethod("prophetWorkspace.status", ({ respond }: any) => {
respond(true, {
Expand All @@ -39,15 +42,77 @@ const prophetWorkspacePlugin = {
endpoint: config.endpoint ?? null,
authMode: config.authMode,
workspaceScope: config.workspaceScope ?? null,
phase: "skeleton",
phase: "hook-rpc",
hooks: [
"emitCarrier",
"evaluateMembraneDecision",
"appendLedgerEvent",
"resolveConnectedAppGrant",
],
});
});

api.registerGatewayMethod("prophetWorkspace.emitCarrier", async ({ params, respond }: any) => {
try {
const result = await hooks.emitCarrier({
kind: typeof params?.kind === "string" ? params.kind : "unknown",
scope: typeof params?.scope === "string" ? params.scope : undefined,
payload: params?.payload ?? {},
});
respond(true, result);
} catch (err) {
respond(false, { error: err instanceof Error ? err.message : String(err) });
}
});

api.registerGatewayMethod(
"prophetWorkspace.evaluateMembraneDecision",
async ({ params, respond }: any) => {
try {
const result = await hooks.evaluateMembraneDecision({
action: typeof params?.action === "string" ? params.action : "unknown",
resource: typeof params?.resource === "string" ? params.resource : undefined,
scope: typeof params?.scope === "string" ? params.scope : undefined,
payload: params?.payload,
});
respond(true, result);
} catch (err) {
respond(false, { error: err instanceof Error ? err.message : String(err) });
}
},
);

api.registerGatewayMethod("prophetWorkspace.appendLedgerEvent", async ({ params, respond }: any) => {
try {
const result = await hooks.appendLedgerEvent({
kind: typeof params?.kind === "string" ? params.kind : "unknown",
scope: typeof params?.scope === "string" ? params.scope : undefined,
payload: params?.payload ?? {},
});
respond(true, result);
} catch (err) {
respond(false, { error: err instanceof Error ? err.message : String(err) });
}
});

api.registerGatewayMethod(
"prophetWorkspace.resolveConnectedAppGrant",
async ({ params, respond }: any) => {
try {
const scope = typeof params?.scope === "string" ? params.scope : "default";
const result = await hooks.resolveConnectedAppGrant(scope);
respond(true, result);
} catch (err) {
respond(false, { error: err instanceof Error ? err.message : String(err) });
}
},
);

api.registerCli(
({ program }: any) => {
program
.command("prophet-workspace-status")
.description("Show Prophet workspace plugin skeleton status")
.description("Show Prophet workspace plugin status")
.action(() => {
api.logger.info(
`[prophet-workspace] enabled=${String(config.enabled)} endpoint=${config.endpoint ?? "unset"} auth=${config.authMode}`,
Expand All @@ -60,10 +125,10 @@ const prophetWorkspacePlugin = {
api.registerService({
id: "prophet-workspace",
start: async () => {
api.logger.info("[prophet-workspace] skeleton plugin ready");
api.logger.info("[prophet-workspace] hook-rpc plugin ready");
},
stop: async () => {
api.logger.info("[prophet-workspace] skeleton plugin stopped");
api.logger.info("[prophet-workspace] hook-rpc plugin stopped");
},
});
},
Expand Down
9 changes: 5 additions & 4 deletions scripts/docker/install-sh-nonroot/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,16 @@ if [[ -z "$CMD_PATH" ]]; then
exit 1
fi
echo "==> Verify CLI installed: $CLI_NAME"
INSTALLED_VERSION="$("$CMD_PATH" --version 2>/dev/null | head -n 1 | tr -d '\r')"
INSTALLED_RAW="$("$CMD_PATH" --version 2>/dev/null | head -n 1 | tr -d '\r')"
INSTALLED_VERSION="$(printf '%s\n' "$INSTALLED_RAW" | grep -Eo '[0-9]{4}\.[0-9]+\.[0-9]+([-.][A-Za-z0-9.]+)?' | head -n 1)"

echo "cli=$CLI_NAME installed=$INSTALLED_VERSION expected=$LATEST_VERSION"
echo "cli=$CLI_NAME installed=$INSTALLED_RAW parsed=$INSTALLED_VERSION expected=$LATEST_VERSION"
if [[ "$INSTALLED_VERSION" != "$LATEST_VERSION" ]]; then
echo "ERROR: expected ${CLI_NAME}@${LATEST_VERSION}, got ${CLI_NAME}@${INSTALLED_VERSION}" >&2
echo "ERROR: expected ${CLI_NAME}@${LATEST_VERSION}, got ${CLI_NAME}@${INSTALLED_RAW}" >&2
exit 1
fi

echo "==> Sanity: CLI runs"
"$CMD_PATH" --help >/dev/null

echo "OK"
echo "OK"
9 changes: 5 additions & 4 deletions scripts/docker/install-sh-smoke/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,16 @@ fi
if [[ -n "${OPENCLAW_INSTALL_LATEST_OUT:-}" ]]; then
printf "%s" "$LATEST_VERSION" > "${OPENCLAW_INSTALL_LATEST_OUT:-}"
fi
INSTALLED_VERSION="$("$CLI_NAME" --version 2>/dev/null | head -n 1 | tr -d '\r')"
echo "cli=$CLI_NAME installed=$INSTALLED_VERSION expected=$LATEST_VERSION"
INSTALLED_RAW="$("$CLI_NAME" --version 2>/dev/null | head -n 1 | tr -d '\r')"
INSTALLED_VERSION="$(printf '%s\n' "$INSTALLED_RAW" | grep -Eo '[0-9]{4}\.[0-9]+\.[0-9]+([-.][A-Za-z0-9.]+)?' | head -n 1)"
echo "cli=$CLI_NAME installed=$INSTALLED_RAW parsed=$INSTALLED_VERSION expected=$LATEST_VERSION"

if [[ "$INSTALLED_VERSION" != "$LATEST_VERSION" ]]; then
echo "ERROR: expected ${CLI_NAME}@${LATEST_VERSION}, got ${CLI_NAME}@${INSTALLED_VERSION}" >&2
echo "ERROR: expected ${CLI_NAME}@${LATEST_VERSION}, got ${CLI_NAME}@${INSTALLED_RAW}" >&2
exit 1
fi

echo "==> Sanity: CLI runs"
"$CLI_NAME" --help >/dev/null

echo "OK"
echo "OK"
Loading