Skip to content
Open
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
1 change: 1 addition & 0 deletions .github/workflows/commit-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ jobs:
name: Skip disabled target commit review
if: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.target_repo == 'openclaw/clawhub' && vars.CLAWSWEEPER_ENABLE_CLAWHUB != '1' }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Explain skipped commit review
run: |
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/repair-comment-router.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
CLAWSWEEPER_APP_CLIENT_ID: Iv23liOECG0slfuhz093

concurrency:
group: repair-comment-router-${{ github.event.inputs.target_repo || github.event.client_payload.target_repo || 'openclaw/openclaw' }}
cancel-in-progress: false

jobs:
route-comments:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/repair-commit-finding-intake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ jobs:
name: Skip disabled target commit finding
if: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.target_repo == 'openclaw/clawhub' && vars.CLAWSWEEPER_ENABLE_CLAWHUB != '1' }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Explain skipped commit finding
run: |
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/repair-finalize-open-prs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
CLAWSWEEPER_APP_CLIENT_ID: Iv23liOECG0slfuhz093

concurrency:
group: clawsweeper-repair-finalize-open-prs
cancel-in-progress: false

jobs:
finalize:
runs-on: ${{ inputs.runner }}
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/repair-self-heal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
CLAWSWEEPER_APP_CLIENT_ID: Iv23liOECG0slfuhz093

concurrency:
group: clawsweeper-repair-self-heal
cancel-in-progress: false

jobs:
self-heal:
runs-on: ${{ github.event_name == 'workflow_dispatch' && inputs.runner || vars.CLAWSWEEPER_WORKER_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/sweep.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ jobs:
name: Skip disabled target event
if: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.target_repo == 'openclaw/clawhub' && vars.CLAWSWEEPER_ENABLE_CLAWHUB != '1' }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Explain skipped event
run: |
Expand Down
77 changes: 77 additions & 0 deletions .github/workflows/sync-from-upstream.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Sync fork from upstream

on:
schedule:
- cron: "17 * * * *"
workflow_dispatch:

permissions:
contents: write

concurrency:
group: sync-from-upstream-${{ github.repository }}
cancel-in-progress: false

jobs:
replay:
name: Replay fork patches on upstream main
if: github.repository == 'ds4psb-ai/clawsweeper'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- uses: ./.github/actions/setup-pnpm

- name: Replay fork-only commits on latest upstream/main
shell: bash
run: |
set -euo pipefail
git config user.name "ds4psb-ai fork sync"
git config user.email "ted.taeeun.kim@gmail.com"

git remote add upstream https://github.com/openclaw/clawsweeper.git 2>/dev/null || true
git fetch --no-tags origin main
git fetch --no-tags upstream main

old_fork="$(git rev-parse origin/main)"
upstream_head="$(git rev-parse upstream/main)"
mapfile -t patch_stack < <(git rev-list --reverse --no-merges "${upstream_head}..${old_fork}")

echo "upstream/main: ${upstream_head}"
echo "fork main: ${old_fork}"
echo "fork-only commits to replay: ${#patch_stack[@]}"

git checkout -B fork-sync "${upstream_head}"
for commit in "${patch_stack[@]}"; do
subject="$(git log -1 --format=%s "${commit}")"
echo "::group::replay ${commit} ${subject}"
if git cherry-pick -x "${commit}"; then
echo "replayed ${commit}"
else
if git diff --quiet && git diff --cached --quiet; then
echo "${commit} is already represented on upstream/main; skipping empty cherry-pick"
git cherry-pick --skip
else
echo "Conflict while replaying ${commit}: ${subject}" >&2
git status --short >&2
exit 1
fi
fi
echo "::endgroup::"
done

- name: Verify canonical fork state
run: pnpm run check

- name: Force-update fork main after successful verification
shell: bash
run: |
set -euo pipefail
if [ "$(git rev-parse HEAD^{tree})" = "$(git rev-parse origin/main^{tree})" ]; then
echo "Fork main already matches the verified replay tree."
exit 0
fi
git push --force-with-lease=main:$(git rev-parse origin/main) origin HEAD:main
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ pnpm run check

Use `pnpm run check` before handoff for code/test/workflow changes.

`engines.node` is `>=24`. Node 22 will install (no `engine-strict`) but the
notifier tests' 5-second retry paths surface as `cancelledByParent` under the
old `node:test` runner. Run on Node 24 or newer before reporting test
failures.

## GitHub Checks

Useful live probes:
Expand Down
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ checkpoint, and status-only commits are intentionally omitted.

### Added

- Added the proposal-only Policy RFC Engine for mining durable ClawSweeper
records into maintainer-reviewable draft policy proposals. Thanks @Freeak88
(#39).
- Added a fork-only `sync-from-upstream` verifier that replays the launch-ready
fork patch stack on the latest upstream `main`, runs `pnpm run check`, and
updates `ds4psb-ai/clawsweeper@main` only after the replayed tree is green.
- Added a light privacy reminder and stronger screenshot-or-video nudge to real behavior proof review guidance.
- Added agent-led real behavior proof judgement so ClawSweeper can inspect linked screenshots, videos, logs, and terminal output with a read-only GitHub token, explain the proof verdict in the review comment, tell contributors how to trigger a fresh review after adding proof, and sync `proof: sufficient` when the evidence is convincing.
- Added a real behavior proof assessment to PR reviews so missing, mock-only, or insufficient contributor proof blocks pass/automerge markers and asks for screenshots, terminal output, redacted logs, recordings, linked artifacts, or copied live output instead.
Expand All @@ -24,6 +30,23 @@ checkpoint, and status-only commits are intentionally omitted.

### Fixed

- Guarded likely-owner commit links so public review comments no longer render
PR numbers, PR URLs, or other non-SHA provenance as broken `/commit/...`
links. Thanks @samzong (#52).
- Kept Policy RFC output deterministic by deriving default timestamps from
evidence instead of wall-clock time and preserving item numbers for archived
`closed/` records. Thanks @Freeak88 (#39).
- Preserved Policy RFC recency scoring by sharing one deterministic evidence
reference date across scored patterns instead of resetting each pattern's age
to zero. Thanks @Freeak88 (#39).
- Cleared stale generated Policy RFC proposal files before each run writes the
current proposal set, while preserving non-generated operator notes. Thanks
@Freeak88 (#39).
- Documented that Node 22 notifier-test `cancelledByParent` failures are
environmental because the repository requires Node 24+. Thanks @ds4psb-ai
(#54).
- Hardened CI by adding explicit timeouts to disabled-target echo jobs and
concurrency groups to write-side repair workflows. Thanks @ds4psb-ai (#55).
- Gave manual exact-item review dispatches their own concurrency group so
targeted maintainer reviews no longer wait behind broad normal backfill runs.
- Downgraded screenshot-only browser runtime proof so ClawSweeper no longer accepts "no visible console/CSP violation" screenshots as sufficient real behavior proof. Thanks @BunsDev.
Expand Down Expand Up @@ -52,6 +75,8 @@ checkpoint, and status-only commits are intentionally omitted.
immediate duplicate capacity probe in the dispatch loop.
- Cached comment-router open-label issue lookups per run so repair-loop comment
discovery and command synthesis do not repeat identical GitHub searches.
- Cached comment-router issue comment lookups per run so targeted command routing
and replay/status checks do not repeat identical comment pagination.
- Retried Codex edit workers after TPM/rate-limit exits and collapsed JSONL failure transcripts into concise repair status reasons.
- Added deterministic merged closing-PR provenance to issue close reports and
public close comments when GitHub exposes a high-confidence closing PR.
Expand Down Expand Up @@ -120,6 +145,14 @@ checkpoint, and status-only commits are intentionally omitted.
tokens exist, keeping untargeted fix prompts cheaper to build.
- Requested 100-item REST pages for paginated GitHub list calls, reducing
review and repair API page fan-out on large issues and pull requests.
- Bounded repair cluster PR file and commit hydration to the context carried
into generated plans, avoiding full pagination for very large pull requests.
- Validated repair cluster hydration limit environment overrides so malformed
values fall back to safe defaults and multi-page bounded hydration stays
covered. Thanks @stainlu (#49).
- Clamped review-context tail hydration to GitHub's retrievable PR endpoint
windows so very large PRs keep the newest available file and commit context
instead of requesting pages beyond the API caps. Thanks @stainlu (#53).
- Compacted review prompt context lazily so large comment, timeline, file, and
commit lists no longer process entries that are omitted from Codex input.
- Scoped every sweep workflow status write to the active target repository so
Expand Down
67 changes: 67 additions & 0 deletions docs/policy-rfc-engine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Policy RFC Engine

The Policy RFC Engine turns repeated ClawSweeper review and repair patterns into structured, reviewable policy proposals. It is an additive, manual tool: it reads durable local records and writes generated documentation/state under `results/policy-rfc/`. It does not mutate GitHub, dispatch repairs, close issues, change labels, or alter scheduler behavior.

## Usage

Build the project, then run:

```sh
pnpm run policy-rfc -- --target-repo openclaw/openclaw --min-occurrences 5
```

Useful options:

- `--target-repo`: repository profile to scan, such as `openclaw/openclaw`.
- `--records-root`: local durable record root. Defaults to `records`.
- `--output-root`: generated proposal root. Defaults to `results/policy-rfc`.
- `--min-occurrences`: minimum repeated observations before an RFC is emitted. Defaults to `5`.

## What It Reads

The collector scans existing markdown and JSON records below `records/<repo-slug>/`. It tolerates missing directories, unreadable files, older markdown shapes, and malformed partial records by skipping what it cannot safely parse.

The first version extracts repeated examples of:

- file conflict types
- labels
- repair markers
- review verdict markers
- safe-close reasons
- automerge repair causes

## What It Writes

For each eligible pattern, the engine writes:

- `results/policy-rfc/<repo-slug>/<proposal-id>.md`
- `results/policy-rfc/<repo-slug>/<proposal-id>.json`

Markdown RFCs contain:

- Title
- Status: Draft
- Summary
- Observed Pattern
- Evidence
- Proposed Policy
- Safety Constraints
- Non-Goals
- Rollout Plan
- Metrics
- Reversion Plan

JSON proposals include the stable machine-readable fields needed for review automation or later dashboards: `id`, `title`, `status`, `pattern_type`, `evidence_items`, `confidence_score`, `proposed_conditions`, `proposed_action`, `safety_constraints`, `created_at`, and `source_records`.

## Proposal-Only Boundary

The engine intentionally stops at documentation/state. A generated RFC is evidence that a pattern may deserve a formal policy; it is not an executable rule. Any accepted proposal must be implemented separately, reviewed as normal code, and routed through ClawSweeper's existing conservative apply paths.

This keeps the feature out of hot scheduler paths:

- no GitHub mutation
- no automatic policy execution
- no changes to close/apply/automerge logic
- no extra review shard work
- no live GitHub scans in the scheduler critical path

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"audit": "node dist/clawsweeper.js audit",
"reconcile": "node dist/clawsweeper.js reconcile",
"status": "node dist/clawsweeper.js status",
"policy-rfc": "node dist/policy-rfc/index.js",
"commit-review": "node dist/commit-sweeper.js",
"commit-reports": "node dist/commit-sweeper.js reports",
"repair:validate": "node dist/repair/validate-all.js",
Expand Down
Loading