Skip to content

feat(task-ledger): add ownership escalation and restore green checks#18

Merged
StreamDemon merged 5 commits into
mm/live-ethos-task-activation-basefrom
work/landing-pr-prep-20260329T011020
Mar 29, 2026
Merged

feat(task-ledger): add ownership escalation and restore green checks#18
StreamDemon merged 5 commits into
mm/live-ethos-task-activation-basefrom
work/landing-pr-prep-20260329T011020

Conversation

@StreamDemon
Copy link
Copy Markdown

@StreamDemon StreamDemon commented Mar 28, 2026

Summary

  • add ownership escalation and reassignment rules for stalled task ownership in the task ledger
  • land the formatter-only cleanup and pnpm-check type-drift fixes needed to restore a clean repo-wide pnpm check on mm/live-ethos
  • reconcile the integrated landing branch so the escalation slice and type-fix slice validate together

Included commits

  • 7c433f666cstyle(repo): normalize formatter drift on mm/live-ethos
  • 395c1dbbecfix(task-ledger): resolve pnpm check type drift
  • 9c06d23e1afeat(task-ledger): add ownership escalation reassignment rules
  • 598e1af716fix(task-ledger): reconcile landing branch integration

Validation

  • pnpm tsgo
  • pnpm lint
  • pnpm vitest run src/infra/task-ledger.test.ts src/infra/task-lifecycle-publisher.test.ts
  • pnpm check

Notes

  • The landing branch was built from mm/live-ethos and validated as a combined branch, not just as individually green lane commits.

Summary by cubic

Add ownership escalation and reassignment to the task ledger so stalled tasks move to active owners. Emit recall trace records via the ledger and restore green checks by fixing type drift, formatting, and CI routing.

  • New Features

    • Task ledger: auto-escalation with reassignment when owners stall; adds ownershipEscalation metadata and expands tests.
    • Ethos: publish entity: "recall", kind: "trace" records from ethos-context and ethos-ingest with compacted headers and no PII.
    • Runtime: add allowModelOverride for embedded runs; WhatsApp internal hook payload now includes agentId, cfg, and timestamp.
  • CI/Infra

    • Restore a clean pnpm check by aligning types (notably trimming src/commands/agent/types.ts) and normalizing formatter drift.
    • Fix CI routing and retrigger checks after base retarget; minor hygiene (import order, safer header construction).

Written for commit 9fae969. Summary will update on new commits.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

12 issues found across 3000 files

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/auto-response.yml">

<violation number="1" location=".github/workflows/auto-response.yml:40">
P1: Pin GitHub Actions to full commit SHAs instead of mutable major tags to prevent unreviewed upstream code from running in this write-capable workflow.</violation>
</file>

<file name=".github/workflows/labeler.yml">

<violation number="1" location=".github/workflows/labeler.yml:35">
P0: This `pull_request_target` workflow was changed from SHA-pinned actions to mutable version tags (`@v2/@v6/@v8`). In a secrets-backed, write-permission workflow, that increases supply-chain risk because action code can change without a PR in this repo.</violation>
</file>

<file name="Dockerfile.sandbox">

<violation number="1" location="Dockerfile.sandbox:10">
P2: Avoid `apt-get upgrade` in this Docker build; it breaks reproducibility against the pinned base image. Prefer updating the base image digest instead.</violation>
</file>

<file name=".gitignore">

<violation number="1" location=".gitignore:130">
P2: Remove `.gitignore` from ignore patterns; it unintentionally ignores future `.gitignore` files across the repo.</violation>
</file>

<file name="apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt">

<violation number="1" location="apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt:614">
P1: Security regression: `resolvePreferredGatewayEndpoint()` drops the TLS/fingerprint guards for manual gateways that the old inline auto-connect code enforced. The old code refused to auto-connect when `manualTls` was false or when no stored TLS fingerprint existed (the comments explicitly said "Security: autoconnect only to previously trusted gateways"). The new code returns the endpoint unconditionally, allowing auto-connect over plaintext to never-trusted gateways.</violation>
</file>

<file name=".agents/skills/openclaw-ghsa-maintainer/SKILL.md">

<violation number="1" location=".agents/skills/openclaw-ghsa-maintainer/SKILL.md:21">
P2: The refetch verification example reads `/tmp/ghsa.refetch.json` without ever writing the `gh api` output to that file.</violation>
</file>

<file name="Dockerfile.sandbox-common">

<violation number="1" location="Dockerfile.sandbox-common:27">
P2: Avoid `apt-get upgrade` in this image build; it makes builds non-deterministic and can unexpectedly mutate the base image package set.</violation>
</file>

<file name=".github/workflows/docker-release.yml">

<violation number="1" location=".github/workflows/docker-release.yml:162">
P2: Default and slim builds share the same GHA cache scope (`docker-release-amd64`), so the slim build's `cache-to: mode=max` overwrites the default build's cached layers on every run. Use distinct scopes (e.g., `docker-release-amd64` and `docker-release-amd64-slim`) so each variant retains its own layer cache across runs.</violation>

<violation number="2" location=".github/workflows/docker-release.yml:279">
P2: Same cache-scope collision as the amd64 job: the arm64 slim build overwrites the arm64 default build's cache. Use a separate scope like `docker-release-arm64-slim`.</violation>
</file>

<file name="Dockerfile.sandbox-browser">

<violation number="1" location="Dockerfile.sandbox-browser:10">
P2: Avoid `apt-get upgrade` in this image build; it breaks deterministic builds despite the pinned base digest.</violation>
</file>

<file name="apps/android/app/build.gradle.kts">

<violation number="1" location="apps/android/app/build.gradle.kts:246">
P1: The strip task targets a hardcoded non-flavor `release` intermediates path, so it won’t find the jar for `playRelease`/`thirdPartyRelease` builds.</violation>

<violation number="2" location="apps/android/app/build.gradle.kts:280">
P1: The dependency hook only matches `minifyReleaseWithR8`, so it misses flavor-specific release R8 tasks and the strip step won’t run for real release variants.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
- uses: actions/create-github-app-token@v2
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0: This pull_request_target workflow was changed from SHA-pinned actions to mutable version tags (@v2/@v6/@v8). In a secrets-backed, write-permission workflow, that increases supply-chain risk because action code can change without a PR in this repo.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/labeler.yml, line 35:

<comment>This `pull_request_target` workflow was changed from SHA-pinned actions to mutable version tags (`@v2/@v6/@v8`). In a secrets-backed, write-permission workflow, that increases supply-chain risk because action code can change without a PR in this repo.</comment>

<file context>
@@ -25,25 +32,25 @@ jobs:
     runs-on: blacksmith-16vcpu-ubuntu-2404
     steps:
-      - uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
+      - uses: actions/create-github-app-token@v2
         id: app-token
         continue-on-error: true
</file context>
Fix with Cubic

private-key: ${{ secrets.GH_APP_PRIVATE_KEY_FALLBACK }}
- name: Handle labeled items
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
uses: actions/github-script@v8
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Pin GitHub Actions to full commit SHAs instead of mutable major tags to prevent unreviewed upstream code from running in this write-capable workflow.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/auto-response.yml, line 40:

<comment>Pin GitHub Actions to full commit SHAs instead of mutable major tags to prevent unreviewed upstream code from running in this write-capable workflow.</comment>

<file context>
@@ -17,20 +24,20 @@ jobs:
           private-key: ${{ secrets.GH_APP_PRIVATE_KEY_FALLBACK }}
       - name: Handle labeled items
-        uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
+        uses: actions/github-script@v8
         with:
           github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
</file context>
Fix with Cubic

prefs.setLastDiscoveredStableId(list.first().stableId)
}

private fun resolvePreferredGatewayEndpoint(): GatewayEndpoint? {
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Security regression: resolvePreferredGatewayEndpoint() drops the TLS/fingerprint guards for manual gateways that the old inline auto-connect code enforced. The old code refused to auto-connect when manualTls was false or when no stored TLS fingerprint existed (the comments explicitly said "Security: autoconnect only to previously trusted gateways"). The new code returns the endpoint unconditionally, allowing auto-connect over plaintext to never-trusted gateways.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt, line 614:

<comment>Security regression: `resolvePreferredGatewayEndpoint()` drops the TLS/fingerprint guards for manual gateways that the old inline auto-connect code enforced. The old code refused to auto-connect when `manualTls` was false or when no stored TLS fingerprint existed (the comments explicitly said "Security: autoconnect only to previously trusted gateways"). The new code returns the endpoint unconditionally, allowing auto-connect over plaintext to never-trusted gateways.</comment>

<file context>
@@ -601,15 +592,59 @@ class NodeRuntime(context: Context) {
+    prefs.setLastDiscoveredStableId(list.first().stableId)
+  }
+
+  private fun resolvePreferredGatewayEndpoint(): GatewayEndpoint? {
+    if (manualEnabled.value) {
+      val host = manualHost.value.trim()
</file context>
Fix with Cubic

tasks.register("stripReleaseDnsjavaServiceDescriptor") {
val mergedJar =
layout.buildDirectory.file(
"intermediates/merged_java_res/release/mergeReleaseJavaResource/base.jar",
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The strip task targets a hardcoded non-flavor release intermediates path, so it won’t find the jar for playRelease/thirdPartyRelease builds.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/android/app/build.gradle.kts, line 246:

<comment>The strip task targets a hardcoded non-flavor `release` intermediates path, so it won’t find the jar for `playRelease`/`thirdPartyRelease` builds.</comment>

<file context>
@@ -211,3 +238,45 @@ dependencies {
+    tasks.register("stripReleaseDnsjavaServiceDescriptor") {
+        val mergedJar =
+            layout.buildDirectory.file(
+                "intermediates/merged_java_res/release/mergeReleaseJavaResource/base.jar",
+            )
+
</file context>
Fix with Cubic

dependsOn("mergeReleaseJavaResource")
}

tasks.matching { it.name == "minifyReleaseWithR8" }.configureEach {
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The dependency hook only matches minifyReleaseWithR8, so it misses flavor-specific release R8 tasks and the strip step won’t run for real release variants.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/android/app/build.gradle.kts, line 280:

<comment>The dependency hook only matches `minifyReleaseWithR8`, so it misses flavor-specific release R8 tasks and the strip step won’t run for real release variants.</comment>

<file context>
@@ -211,3 +238,45 @@ dependencies {
+    dependsOn("mergeReleaseJavaResource")
+}
+
+tasks.matching { it.name == "minifyReleaseWithR8" }.configureEach {
+    dependsOn(stripReleaseDnsjavaServiceDescriptor)
+}
</file context>
Suggested change
tasks.matching { it.name == "minifyReleaseWithR8" }.configureEach {
tasks.matching { it.name.endsWith("ReleaseWithR8") }.configureEach {
Fix with Cubic

Fetch the current advisory and the latest published npm version:

```bash
gh api /repos/openclaw/openclaw/security-advisories/<GHSA>
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The refetch verification example reads /tmp/ghsa.refetch.json without ever writing the gh api output to that file.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .agents/skills/openclaw-ghsa-maintainer/SKILL.md, line 21:

<comment>The refetch verification example reads `/tmp/ghsa.refetch.json` without ever writing the `gh api` output to that file.</comment>

<file context>
@@ -0,0 +1,87 @@
+Fetch the current advisory and the latest published npm version:
+
+```bash
+gh api /repos/openclaw/openclaw/security-advisories/<GHSA>
+npm view openclaw version --userconfig "$(mktemp)"
+```
</file context>
Fix with Cubic

Comment thread Dockerfile.sandbox-common
Comment on lines +27 to 28
&& apt-get upgrade -y --no-install-recommends \
&& apt-get install -y --no-install-recommends ${PACKAGES}
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Avoid apt-get upgrade in this image build; it makes builds non-deterministic and can unexpectedly mutate the base image package set.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Dockerfile.sandbox-common, line 27:

<comment>Avoid `apt-get upgrade` in this image build; it makes builds non-deterministic and can unexpectedly mutate the base image package set.</comment>

<file context>
@@ -24,6 +24,7 @@ ENV PATH=${BUN_INSTALL_DIR}/bin:${BREW_INSTALL_DIR}/bin:${BREW_INSTALL_DIR}/sbin
 RUN --mount=type=cache,id=openclaw-sandbox-common-apt-cache,target=/var/cache/apt,sharing=locked \
   --mount=type=cache,id=openclaw-sandbox-common-apt-lists,target=/var/lib/apt,sharing=locked \
   apt-get update \
+  && apt-get upgrade -y --no-install-recommends \
   && apt-get install -y --no-install-recommends ${PACKAGES}
 
</file context>
Suggested change
&& apt-get upgrade -y --no-install-recommends \
&& apt-get install -y --no-install-recommends ${PACKAGES}
&& apt-get install -y --no-install-recommends ${PACKAGES}
Fix with Cubic

Comment on lines +279 to +280
cache-from: type=gha,scope=docker-release-arm64
cache-to: type=gha,mode=max,scope=docker-release-arm64
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Same cache-scope collision as the amd64 job: the arm64 slim build overwrites the arm64 default build's cache. Use a separate scope like docker-release-arm64-slim.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/docker-release.yml, line 279:

<comment>Same cache-scope collision as the amd64 job: the arm64 slim build overwrites the arm64 default build's cache. Use a separate scope like `docker-release-arm64-slim`.</comment>

<file context>
@@ -182,41 +248,50 @@ jobs:
         with:
           context: .
           platforms: linux/arm64
+          cache-from: type=gha,scope=docker-release-arm64
+          cache-to: type=gha,mode=max,scope=docker-release-arm64
           tags: ${{ steps.tags.outputs.value }}
</file context>
Suggested change
cache-from: type=gha,scope=docker-release-arm64
cache-to: type=gha,mode=max,scope=docker-release-arm64
cache-from: type=gha,scope=docker-release-arm64-slim
cache-to: type=gha,mode=max,scope=docker-release-arm64-slim
Fix with Cubic

Comment on lines +162 to +163
cache-from: type=gha,scope=docker-release-amd64
cache-to: type=gha,mode=max,scope=docker-release-amd64
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Default and slim builds share the same GHA cache scope (docker-release-amd64), so the slim build's cache-to: mode=max overwrites the default build's cached layers on every run. Use distinct scopes (e.g., docker-release-amd64 and docker-release-amd64-slim) so each variant retains its own layer cache across runs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/docker-release.yml, line 162:

<comment>Default and slim builds share the same GHA cache scope (`docker-release-amd64`), so the slim build's `cache-to: mode=max` overwrites the default build's cached layers on every run. Use distinct scopes (e.g., `docker-release-amd64` and `docker-release-amd64-slim`) so each variant retains its own layer cache across runs.</comment>

<file context>
@@ -81,41 +131,50 @@ jobs:
         with:
           context: .
           platforms: linux/amd64
+          cache-from: type=gha,scope=docker-release-amd64
+          cache-to: type=gha,mode=max,scope=docker-release-amd64
           tags: ${{ steps.tags.outputs.value }}
</file context>
Suggested change
cache-from: type=gha,scope=docker-release-amd64
cache-to: type=gha,mode=max,scope=docker-release-amd64
cache-from: type=gha,scope=docker-release-amd64-slim
cache-to: type=gha,mode=max,scope=docker-release-amd64-slim
Fix with Cubic

Comment on lines +10 to 11
&& apt-get upgrade -y --no-install-recommends \
&& apt-get install -y --no-install-recommends \
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Avoid apt-get upgrade in this image build; it breaks deterministic builds despite the pinned base digest.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Dockerfile.sandbox-browser, line 10:

<comment>Avoid `apt-get upgrade` in this image build; it breaks deterministic builds despite the pinned base digest.</comment>

<file context>
@@ -7,6 +7,7 @@ ENV DEBIAN_FRONTEND=noninteractive
 RUN --mount=type=cache,id=openclaw-sandbox-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
   --mount=type=cache,id=openclaw-sandbox-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
   apt-get update \
+  && apt-get upgrade -y --no-install-recommends \
   && apt-get install -y --no-install-recommends \
     bash \
</file context>
Suggested change
&& apt-get upgrade -y --no-install-recommends \
&& apt-get install -y --no-install-recommends \
&& apt-get install -y --no-install-recommends \
Fix with Cubic

@StreamDemon StreamDemon changed the base branch from mm/live-ethos to mm/live-ethos-task-activation-base March 29, 2026 03:06
@StreamDemon
Copy link
Copy Markdown
Author

@cubic-dev-ai base was corrected to mm/live-ethos-task-activation-base. Please re-review this PR on the current 17-file / 4-commit diff.

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented Mar 29, 2026

@cubic-dev-ai base was corrected to mm/live-ethos-task-activation-base. Please re-review this PR on the current 17-file / 4-commit diff.

@StreamDemon I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 17 files

@StreamDemon
Copy link
Copy Markdown
Author

@cubic-dev-ai Please run a full code review on this PR and check for the same issues that you previously commented on. Re-comment if those issues still exist.

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented Mar 29, 2026

@cubic-dev-ai Please run a full code review on this PR and check for the same issues that you previously commented on. Re-comment if those issues still exist.

@StreamDemon I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 17 files

@StreamDemon
Copy link
Copy Markdown
Author

Local merge-gate note from Neko:

GitHub Actions remained queued because the repo is out of Actions minutes on the free tier, so I ran the relevant gate locally on the PR head (9fae969fbe) in /tmp/openclaw-pr18-refresh-20260329 instead.

Validated locally:

  • pnpm vitest run src/infra/task-ledger.test.ts src/infra/task-lifecycle-publisher.test.ts ✅ (38 tests passed)
  • pnpm check

Cubic also reran on the corrected 17-file diff and posted No issues found.

Proceeding with merge on the basis of local validation + current Cubic review.

@StreamDemon StreamDemon merged commit 9267162 into mm/live-ethos-task-activation-base Mar 29, 2026
3 of 10 checks passed
@StreamDemon StreamDemon deleted the work/landing-pr-prep-20260329T011020 branch March 29, 2026 04:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant