chore(ci): establish PR governance for agent collaboration (#177)
* chore(ci): establish PR governance for agent collaboration * docs: add AGENTS playbook and strengthen agent collaboration workflow --------- Co-authored-by: chumyin <183474434+chumyin@users.noreply.github.com>
This commit is contained in:
parent
dca95cac7a
commit
dfe648d5ae
14 changed files with 1020 additions and 19 deletions
10
.github/CODEOWNERS
vendored
Normal file
10
.github/CODEOWNERS
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Default owner for all files
|
||||
* @theonlyhennygod
|
||||
|
||||
# High-risk surfaces
|
||||
/src/security/** @theonlyhennygod
|
||||
/src/runtime/** @theonlyhennygod
|
||||
/src/memory/** @theonlyhennygod
|
||||
/.github/** @theonlyhennygod
|
||||
/Cargo.toml @theonlyhennygod
|
||||
/Cargo.lock @theonlyhennygod
|
||||
93
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
93
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
name: Bug Report
|
||||
description: Report a reproducible defect in ZeroClaw
|
||||
title: "[Bug]: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report a bug.
|
||||
Please provide a minimal reproducible case so maintainers can triage quickly.
|
||||
|
||||
- type: input
|
||||
id: summary
|
||||
attributes:
|
||||
label: Summary
|
||||
description: One-line description of the problem.
|
||||
placeholder: zeroclaw daemon exits immediately when ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: current
|
||||
attributes:
|
||||
label: Current behavior
|
||||
description: What is happening now?
|
||||
placeholder: The process exits with ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: What should happen instead?
|
||||
placeholder: The daemon should stay alive and ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduce
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Please provide exact commands/config.
|
||||
placeholder: |
|
||||
1. zeroclaw onboard --interactive
|
||||
2. zeroclaw daemon
|
||||
3. Observe crash in logs
|
||||
render: bash
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs / stack traces
|
||||
description: Paste relevant logs (redact secrets).
|
||||
render: text
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: ZeroClaw version
|
||||
placeholder: v0.1.0 / commit SHA
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: rust
|
||||
attributes:
|
||||
label: Rust version
|
||||
placeholder: rustc 1.xx.x
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating system
|
||||
placeholder: Ubuntu 24.04 / macOS 15 / Windows 11
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: regression
|
||||
attributes:
|
||||
label: Regression?
|
||||
options:
|
||||
- Unknown
|
||||
- Yes, it worked before
|
||||
- No, first-time setup
|
||||
validations:
|
||||
required: true
|
||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Security vulnerability report
|
||||
url: https://github.com/theonlyhennygod/zeroclaw/security/policy
|
||||
about: Please report security vulnerabilities privately via SECURITY.md policy.
|
||||
- name: Contribution guide
|
||||
url: https://github.com/theonlyhennygod/zeroclaw/blob/main/CONTRIBUTING.md
|
||||
about: Please read contribution and PR requirements before opening an issue.
|
||||
64
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
64
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
name: Feature Request
|
||||
description: Propose an improvement or new capability
|
||||
title: "[Feature]: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for sharing your idea.
|
||||
Please focus on user value, constraints, and rollout safety.
|
||||
|
||||
- type: input
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem statement
|
||||
description: What user problem are you trying to solve?
|
||||
placeholder: Teams need a way to ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: proposal
|
||||
attributes:
|
||||
label: Proposed solution
|
||||
description: Describe the preferred solution.
|
||||
placeholder: Add a new subcommand / trait implementation ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives considered
|
||||
description: What alternatives did you evaluate?
|
||||
placeholder: Keep current behavior, use external tool, etc.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: architecture
|
||||
attributes:
|
||||
label: Architecture impact
|
||||
description: Which subsystem(s) are affected?
|
||||
placeholder: providers/, channels/, memory/, runtime/, security/ ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: risk
|
||||
attributes:
|
||||
label: Risk and rollback
|
||||
description: Main risk + how to disable/revert quickly.
|
||||
placeholder: Risk is ... rollback is ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: breaking
|
||||
attributes:
|
||||
label: Breaking change?
|
||||
options:
|
||||
- No
|
||||
- Yes
|
||||
validations:
|
||||
required: true
|
||||
59
.github/labeler.yml
vendored
Normal file
59
.github/labeler.yml
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
"type: docs":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "docs/**"
|
||||
- "**/*.md"
|
||||
- "LICENSE"
|
||||
|
||||
"type: dependencies":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "deny.toml"
|
||||
|
||||
"type: ci":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- ".github/**"
|
||||
- ".githooks/**"
|
||||
|
||||
"area: providers":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/**"
|
||||
|
||||
"area: channels":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/**"
|
||||
|
||||
"area: memory":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/memory/**"
|
||||
|
||||
"area: security":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/security/**"
|
||||
|
||||
"area: runtime":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/runtime/**"
|
||||
|
||||
"area: tools":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/**"
|
||||
|
||||
"area: observability":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/observability/**"
|
||||
|
||||
"area: tests":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "tests/**"
|
||||
70
.github/pull_request_template.md
vendored
Normal file
70
.github/pull_request_template.md
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
## Summary
|
||||
|
||||
Describe this PR in 2-5 bullets:
|
||||
|
||||
- Problem:
|
||||
- Why it matters:
|
||||
- What changed:
|
||||
- What did **not** change (scope boundary):
|
||||
|
||||
## Change Type
|
||||
|
||||
- [ ] Bug fix
|
||||
- [ ] Feature
|
||||
- [ ] Refactor
|
||||
- [ ] Docs
|
||||
- [ ] Security hardening
|
||||
- [ ] Chore / infra
|
||||
|
||||
## Scope
|
||||
|
||||
- [ ] Core runtime / daemon
|
||||
- [ ] Provider integration
|
||||
- [ ] Channel integration
|
||||
- [ ] Memory / storage
|
||||
- [ ] Security / sandbox
|
||||
- [ ] CI / release / tooling
|
||||
- [ ] Documentation
|
||||
|
||||
## Linked Issue
|
||||
|
||||
- Closes #
|
||||
- Related #
|
||||
|
||||
## Testing
|
||||
|
||||
Commands and result summary (required):
|
||||
|
||||
```bash
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
cargo test
|
||||
```
|
||||
|
||||
If any command is intentionally skipped, explain why.
|
||||
|
||||
## Security Impact
|
||||
|
||||
- New permissions/capabilities? (`Yes/No`)
|
||||
- New external network calls? (`Yes/No`)
|
||||
- Secrets/tokens handling changed? (`Yes/No`)
|
||||
- File system access scope changed? (`Yes/No`)
|
||||
- If any `Yes`, describe risk and mitigation:
|
||||
|
||||
## Agent Collaboration Notes (recommended)
|
||||
|
||||
- [ ] If agent/automation tools were used, I added brief workflow notes.
|
||||
- [ ] I included concrete validation evidence for this change.
|
||||
- [ ] I can explain design choices and rollback steps.
|
||||
|
||||
If agent tools were used, optional context:
|
||||
|
||||
- Tool(s):
|
||||
- Prompt/plan summary:
|
||||
- Verification focus:
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
- Fast rollback command/path:
|
||||
- Feature flags or config toggles (if any):
|
||||
- Observable failure symptoms:
|
||||
40
.github/workflows/auto-response.yml
vendored
Normal file
40
.github/workflows/auto-response.yml
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
name: Auto Response
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
first-interaction:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Greet first-time contributors
|
||||
uses: actions/first-interaction@v1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-message: |
|
||||
Thanks for opening this issue.
|
||||
|
||||
Before maintainers triage it, please confirm:
|
||||
- Repro steps are complete and run on latest `main`
|
||||
- Environment details are included (OS, Rust version, ZeroClaw version)
|
||||
- Sensitive values are redacted
|
||||
|
||||
This helps us keep issue throughput high and response latency low.
|
||||
pr-message: |
|
||||
Thanks for contributing to ZeroClaw.
|
||||
|
||||
For faster review, please ensure:
|
||||
- PR template sections are fully completed
|
||||
- `cargo fmt --all -- --check`, `cargo clippy --all-targets -- -D warnings`, and `cargo test` are included
|
||||
- If automation/agents were used heavily, add brief workflow notes
|
||||
- Scope is focused (prefer one concern per PR)
|
||||
|
||||
See `CONTRIBUTING.md` and `docs/pr-workflow.md` for full collaboration rules.
|
||||
137
.github/workflows/ci.yml
vendored
137
.github/workflows/ci.yml
vendored
|
|
@ -6,14 +6,86 @@ on:
|
|||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
name: Detect Change Scope
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
docs_only: ${{ steps.scope.outputs.docs_only }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Detect docs-only changes
|
||||
id: scope
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||
BASE="${{ github.event.pull_request.base.sha }}"
|
||||
else
|
||||
BASE="${{ github.event.before }}"
|
||||
fi
|
||||
|
||||
if [ -z "$BASE" ] || ! git cat-file -e "$BASE^{commit}" 2>/dev/null; then
|
||||
echo "docs_only=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
CHANGED="$(git diff --name-only "$BASE" HEAD || true)"
|
||||
if [ -z "$CHANGED" ]; then
|
||||
echo "docs_only=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
docs_only=true
|
||||
while IFS= read -r file; do
|
||||
[ -z "$file" ] && continue
|
||||
case "$file" in
|
||||
docs/*|*.md|*.mdx|LICENSE|.github/ISSUE_TEMPLATE/*|.github/pull_request_template.md)
|
||||
;;
|
||||
*)
|
||||
docs_only=false
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done <<< "$CHANGED"
|
||||
|
||||
echo "docs_only=$docs_only" >> "$GITHUB_OUTPUT"
|
||||
|
||||
lint:
|
||||
name: Format & Lint
|
||||
needs: [changes]
|
||||
if: needs.changes.outputs.docs_only != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: Run rustfmt
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Run clippy
|
||||
run: cargo clippy --all-targets -- -D warnings
|
||||
|
||||
test:
|
||||
name: Test
|
||||
needs: [changes]
|
||||
if: needs.changes.outputs.docs_only != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true # Don't block PRs
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
|
|
@ -22,24 +94,55 @@ jobs:
|
|||
run: cargo test --verbose
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: true # Don't block PRs on build failures
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
- os: macos-latest
|
||||
target: aarch64-apple-darwin
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
name: Build (Smoke)
|
||||
needs: [changes]
|
||||
if: needs.changes.outputs.docs_only != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: Build
|
||||
run: cargo build --release --verbose
|
||||
- name: Build release binary
|
||||
run: cargo build --release --locked --verbose
|
||||
|
||||
docs-only:
|
||||
name: Docs-Only Fast Path
|
||||
needs: [changes]
|
||||
if: needs.changes.outputs.docs_only == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Skip heavy jobs for docs-only change
|
||||
run: echo "Docs-only change detected. Rust lint/test/build skipped."
|
||||
|
||||
ci-required:
|
||||
name: CI Required Gate
|
||||
if: always()
|
||||
needs: [changes, lint, test, build, docs-only]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Enforce required status
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ "${{ needs.changes.outputs.docs_only }}" = "true" ]; then
|
||||
echo "Docs-only fast path passed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
lint_result="${{ needs.lint.result }}"
|
||||
test_result="${{ needs.test.result }}"
|
||||
build_result="${{ needs.build.result }}"
|
||||
|
||||
echo "lint=${lint_result}"
|
||||
echo "test=${test_result}"
|
||||
echo "build=${build_result}"
|
||||
|
||||
if [ "$lint_result" != "success" ] || [ "$test_result" != "success" ] || [ "$build_result" != "success" ]; then
|
||||
echo "Required CI jobs did not pass."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "All required CI jobs passed."
|
||||
|
|
|
|||
70
.github/workflows/labeler.yml
vendored
Normal file
70
.github/workflows/labeler.yml
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
name: PR Labeler
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened, synchronize, edited]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Apply path labels
|
||||
uses: actions/labeler@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Apply size label
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const sizeLabels = ["size: XS", "size: S", "size: M", "size: L", "size: XL"];
|
||||
const labelColor = "BFDADC";
|
||||
const changedLines = (pr.additions || 0) + (pr.deletions || 0);
|
||||
|
||||
let sizeLabel = "size: XL";
|
||||
if (changedLines <= 80) sizeLabel = "size: XS";
|
||||
else if (changedLines <= 250) sizeLabel = "size: S";
|
||||
else if (changedLines <= 500) sizeLabel = "size: M";
|
||||
else if (changedLines <= 1000) sizeLabel = "size: L";
|
||||
|
||||
for (const label of sizeLabels) {
|
||||
try {
|
||||
await github.rest.issues.getLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: label,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error.status !== 404) throw error;
|
||||
await github.rest.issues.createLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: label,
|
||||
color: labelColor,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
});
|
||||
|
||||
const keepLabels = currentLabels
|
||||
.map((label) => label.name)
|
||||
.filter((label) => !sizeLabels.includes(label));
|
||||
|
||||
const nextLabels = [...new Set([...keepLabels, sizeLabel])];
|
||||
await github.rest.issues.setLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
labels: nextLabels,
|
||||
});
|
||||
44
.github/workflows/stale.yml
vendored
Normal file
44
.github/workflows/stale.yml
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
name: Stale
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "20 2 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Mark stale issues and pull requests
|
||||
uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-issue-stale: 21
|
||||
days-before-issue-close: 7
|
||||
days-before-pr-stale: 14
|
||||
days-before-pr-close: 7
|
||||
stale-issue-label: stale
|
||||
stale-pr-label: stale
|
||||
exempt-issue-labels: security,pinned,no-stale,maintainer
|
||||
exempt-pr-labels: no-stale,maintainer
|
||||
remove-stale-when-updated: true
|
||||
exempt-all-assignees: true
|
||||
operations-per-run: 300
|
||||
stale-issue-message: |
|
||||
This issue was automatically marked as stale due to inactivity.
|
||||
Please provide an update, reproduction details, or current status to keep it open.
|
||||
close-issue-message: |
|
||||
Closing this issue due to inactivity.
|
||||
If the problem still exists on the latest `main`, please open a new issue with fresh repro steps.
|
||||
close-issue-reason: not_planned
|
||||
stale-pr-message: |
|
||||
This PR was automatically marked as stale due to inactivity.
|
||||
Please rebase/update and post the latest validation results.
|
||||
close-pr-message: |
|
||||
Closing this PR due to inactivity.
|
||||
Maintainers can reopen once the branch is updated and validation is provided.
|
||||
63
.github/workflows/workflow-sanity.yml
vendored
Normal file
63
.github/workflows/workflow-sanity.yml
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
name: Workflow Sanity
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/**"
|
||||
- ".github/*.yml"
|
||||
- ".github/*.yaml"
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- ".github/workflows/**"
|
||||
- ".github/*.yml"
|
||||
- ".github/*.yaml"
|
||||
|
||||
concurrency:
|
||||
group: workflow-sanity-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
no-tabs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Fail on tabs in workflow files
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python - <<'PY'
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
root = pathlib.Path(".github/workflows")
|
||||
bad: list[str] = []
|
||||
for path in sorted(root.rglob("*.yml")):
|
||||
if b"\t" in path.read_bytes():
|
||||
bad.append(str(path))
|
||||
for path in sorted(root.rglob("*.yaml")):
|
||||
if b"\t" in path.read_bytes():
|
||||
bad.append(str(path))
|
||||
|
||||
if bad:
|
||||
print("Tabs found in workflow file(s):")
|
||||
for path in bad:
|
||||
print(f"- {path}")
|
||||
sys.exit(1)
|
||||
PY
|
||||
|
||||
actionlint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Lint GitHub workflows
|
||||
uses: rhysd/actionlint@v1
|
||||
158
AGENTS.md
Normal file
158
AGENTS.md
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# AGENTS.md — ZeroClaw Agent Coding Guide
|
||||
|
||||
This file defines the default working protocol for coding agents in this repository.
|
||||
Scope: entire repository.
|
||||
|
||||
## 1) Project Snapshot (Read First)
|
||||
|
||||
ZeroClaw is a Rust-first autonomous agent runtime optimized for:
|
||||
|
||||
- high performance
|
||||
- high efficiency
|
||||
- high stability
|
||||
- high extensibility
|
||||
- high sustainability
|
||||
- high security
|
||||
|
||||
Core architecture is trait-driven and modular. Most extension work should be done by implementing traits and registering in factory modules.
|
||||
|
||||
Key extension points:
|
||||
|
||||
- `src/providers/traits.rs` (`Provider`)
|
||||
- `src/channels/traits.rs` (`Channel`)
|
||||
- `src/tools/traits.rs` (`Tool`)
|
||||
- `src/memory/traits.rs` (`Memory`)
|
||||
- `src/observability/traits.rs` (`Observer`)
|
||||
- `src/runtime/traits.rs` (`RuntimeAdapter`)
|
||||
|
||||
## 2) Repository Map (High-Level)
|
||||
|
||||
- `src/main.rs` — CLI entrypoint and command routing
|
||||
- `src/lib.rs` — module exports and shared command enums
|
||||
- `src/config/` — schema + config loading/merging
|
||||
- `src/agent/` — orchestration loop
|
||||
- `src/gateway/` — webhook/gateway server
|
||||
- `src/security/` — policy, pairing, secret store
|
||||
- `src/memory/` — markdown/sqlite memory backends + embeddings/vector merge
|
||||
- `src/providers/` — model providers and resilient wrapper
|
||||
- `src/channels/` — Telegram/Discord/Slack/etc channels
|
||||
- `src/tools/` — tool execution surface (shell, file, memory, browser)
|
||||
- `src/runtime/` — runtime adapters (currently native)
|
||||
- `docs/` — architecture + process docs
|
||||
- `.github/` — CI, templates, automation workflows
|
||||
|
||||
## 3) Non-Negotiable Engineering Constraints
|
||||
|
||||
### 3.1 Performance and Footprint
|
||||
|
||||
- Prefer minimal dependencies; avoid adding crates unless clearly justified.
|
||||
- Preserve release-size profile assumptions in `Cargo.toml`.
|
||||
- Avoid unnecessary allocations, clones, and blocking operations.
|
||||
- Keep startup path lean; avoid heavy initialization in command parsing flow.
|
||||
|
||||
### 3.2 Security and Safety
|
||||
|
||||
- Treat `src/security/`, `src/gateway/`, `src/tools/` as high-risk surfaces.
|
||||
- Never broaden filesystem/network execution scope without explicit policy checks.
|
||||
- Never log secrets, tokens, raw credentials, or sensitive payloads.
|
||||
- Keep default behavior secure-by-default (deny-by-default where applicable).
|
||||
|
||||
### 3.3 Stability and Compatibility
|
||||
|
||||
- Preserve CLI contract unless change is intentional and documented.
|
||||
- Prefer explicit errors over silent fallback for unsupported critical paths.
|
||||
- Keep changes local; avoid cross-module refactors in unrelated tasks.
|
||||
|
||||
## 4) Agent Workflow (Required)
|
||||
|
||||
1. **Read before write**
|
||||
- Inspect existing module and adjacent tests before editing.
|
||||
2. **Define scope boundary**
|
||||
- One concern per PR; avoid mixed feature+refactor+infra patches.
|
||||
3. **Implement minimal patch**
|
||||
- Follow KISS/YAGNI/DRY; no speculative abstractions.
|
||||
4. **Validate by risk**
|
||||
- Docs-only: keep checks lightweight.
|
||||
- Code changes: run relevant checks and tests.
|
||||
5. **Document impact**
|
||||
- Update docs/PR notes for behavior, risk, rollback.
|
||||
|
||||
## 5) Change Playbooks
|
||||
|
||||
### 5.1 Adding a Provider
|
||||
|
||||
- Implement `Provider` in `src/providers/`.
|
||||
- Register in `src/providers/mod.rs` factory.
|
||||
- Add focused tests for factory wiring and error paths.
|
||||
|
||||
### 5.2 Adding a Channel
|
||||
|
||||
- Implement `Channel` in `src/channels/`.
|
||||
- Ensure `send`, `listen`, and `health_check` semantics are consistent.
|
||||
- Cover auth/allowlist/health behavior with tests.
|
||||
|
||||
### 5.3 Adding a Tool
|
||||
|
||||
- Implement `Tool` in `src/tools/` with strict parameter schema.
|
||||
- Validate and sanitize all inputs.
|
||||
- Return structured `ToolResult`; avoid panics in runtime path.
|
||||
|
||||
### 5.4 Security / Runtime / Gateway Changes
|
||||
|
||||
- Include threat/risk notes and rollback strategy.
|
||||
- Add or update tests for boundary checks and failure modes.
|
||||
- Keep observability useful but non-sensitive.
|
||||
|
||||
## 6) Validation Matrix
|
||||
|
||||
Default local checks for code changes:
|
||||
|
||||
```bash
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
cargo test
|
||||
```
|
||||
|
||||
If full checks are impractical, run the most relevant subset and document what was skipped and why.
|
||||
|
||||
For workflow/template-only changes, at least ensure YAML/template syntax validity.
|
||||
|
||||
## 7) Collaboration and PR Discipline
|
||||
|
||||
- Follow `.github/pull_request_template.md`.
|
||||
- Keep PR descriptions concrete: problem, change, non-goals, risk, rollback.
|
||||
- Use conventional commit titles.
|
||||
- Prefer small PRs (`size: XS/S/M`) when possible.
|
||||
|
||||
Reference docs:
|
||||
|
||||
- `CONTRIBUTING.md`
|
||||
- `docs/pr-workflow.md`
|
||||
|
||||
## 8) Anti-Patterns (Do Not)
|
||||
|
||||
- Do not add heavy dependencies for minor convenience.
|
||||
- Do not silently weaken security policy or access constraints.
|
||||
- Do not mix massive formatting-only changes with functional changes.
|
||||
- Do not modify unrelated modules "while here".
|
||||
- Do not bypass failing checks without explicit explanation.
|
||||
|
||||
## 9) Handoff Template (Agent -> Agent / Maintainer)
|
||||
|
||||
When handing off work, include:
|
||||
|
||||
1. What changed
|
||||
2. What did not change
|
||||
3. Validation run and results
|
||||
4. Remaining risks / unknowns
|
||||
5. Next recommended action
|
||||
|
||||
## 10) Vibe Coding Guardrails
|
||||
|
||||
When working in a fast iterative "vibe coding" style:
|
||||
|
||||
- Keep each iteration reversible (small commits, clear rollback).
|
||||
- Validate assumptions with code search before implementing.
|
||||
- Prefer deterministic behavior over clever shortcuts.
|
||||
- Do not "ship and hope" on security-sensitive paths.
|
||||
- If uncertain, leave a concrete TODO with verification context, not a hidden guess.
|
||||
|
|
@ -37,6 +37,33 @@ git push --no-verify
|
|||
|
||||
> **Note:** CI runs the same checks, so skipped hooks will be caught on the PR.
|
||||
|
||||
## High-Volume Collaboration Rules
|
||||
|
||||
When PR traffic is high (especially with AI-assisted contributions), these rules keep quality and throughput stable:
|
||||
|
||||
- **One concern per PR**: avoid mixing refactor + feature + infra in one change.
|
||||
- **Small PRs first**: prefer PR size `XS/S/M`; split large work into stacked PRs.
|
||||
- **Template is mandatory**: complete every section in `.github/pull_request_template.md`.
|
||||
- **Explicit rollback**: every PR must include a fast rollback path.
|
||||
- **Security-first review**: changes in `src/security/`, runtime, and CI need stricter validation.
|
||||
|
||||
Full maintainer workflow: [`docs/pr-workflow.md`](docs/pr-workflow.md).
|
||||
|
||||
## Agent Collaboration Guidance
|
||||
|
||||
Agent-assisted contributions are welcome and treated as first-class contributions.
|
||||
|
||||
For smoother agent-to-agent and human-to-agent review:
|
||||
|
||||
- Keep PR summaries concrete (problem, change, non-goals).
|
||||
- Include reproducible validation evidence (`fmt`, `clippy`, `test`, scenario checks).
|
||||
- Add brief workflow notes when automation materially influenced design/code.
|
||||
- Call out uncertainty and risky edges explicitly.
|
||||
|
||||
We do **not** require PRs to declare an AI-vs-human line ratio.
|
||||
|
||||
Agent implementation playbook lives in [`AGENTS.md`](AGENTS.md).
|
||||
|
||||
## Architecture: Trait-Based Pluggability
|
||||
|
||||
ZeroClaw's architecture is built on **traits** — every subsystem is swappable. This means contributing a new integration is as simple as implementing a trait and registering it in the factory function.
|
||||
|
|
@ -184,8 +211,9 @@ impl Tool for YourTool {
|
|||
|
||||
## Pull Request Checklist
|
||||
|
||||
- [ ] `cargo fmt` — code is formatted
|
||||
- [ ] `cargo clippy -- -D warnings` — no warnings
|
||||
- [ ] PR template sections are completed (including security + rollback)
|
||||
- [ ] `cargo fmt --all -- --check` — code is formatted
|
||||
- [ ] `cargo clippy --all-targets -- -D warnings` — no warnings
|
||||
- [ ] `cargo test` — all 129+ tests pass
|
||||
- [ ] New code has inline `#[cfg(test)]` tests
|
||||
- [ ] No new dependencies unless absolutely necessary (we optimize for binary size)
|
||||
|
|
@ -198,6 +226,7 @@ We use [Conventional Commits](https://www.conventionalcommits.org/):
|
|||
|
||||
```
|
||||
feat: add Anthropic provider
|
||||
feat(provider): add Anthropic provider
|
||||
fix: path traversal edge case with symlinks
|
||||
docs: update contributing guide
|
||||
test: add heartbeat unicode parsing tests
|
||||
|
|
@ -205,6 +234,10 @@ refactor: extract common security checks
|
|||
chore: bump tokio to 1.43
|
||||
```
|
||||
|
||||
Recommended scope keys in commit titles:
|
||||
|
||||
- `provider`, `channel`, `memory`, `security`, `runtime`, `ci`, `docs`, `tests`
|
||||
|
||||
## Code Style
|
||||
|
||||
- **Minimal dependencies** — every crate adds to binary size
|
||||
|
|
@ -219,6 +252,14 @@ chore: bump tokio to 1.43
|
|||
- **Features**: Describe the use case, propose which trait to extend
|
||||
- **Security**: See [SECURITY.md](SECURITY.md) for responsible disclosure
|
||||
|
||||
## Maintainer Merge Policy
|
||||
|
||||
- Require passing `CI Required Gate` before merge.
|
||||
- Require review approval for non-trivial changes.
|
||||
- Require CODEOWNERS review for protected paths.
|
||||
- Prefer squash merge with conventional commit title.
|
||||
- Revert fast on regressions; re-land with tests.
|
||||
|
||||
## License
|
||||
|
||||
By contributing, you agree that your contributions will be licensed under the MIT License.
|
||||
|
|
|
|||
178
docs/pr-workflow.md
Normal file
178
docs/pr-workflow.md
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
# ZeroClaw PR Workflow (High-Volume Collaboration)
|
||||
|
||||
This document defines how ZeroClaw handles high PR volume while maintaining:
|
||||
|
||||
- High performance
|
||||
- High efficiency
|
||||
- High stability
|
||||
- High extensibility
|
||||
- High sustainability
|
||||
- High security
|
||||
|
||||
## 1) Governance Goals
|
||||
|
||||
1. Keep merge throughput predictable under heavy PR load.
|
||||
2. Keep CI signal quality high (fast feedback, low false positives).
|
||||
3. Keep security review explicit for risky surfaces.
|
||||
4. Keep changes easy to reason about and easy to revert.
|
||||
|
||||
## 2) Required Repository Settings
|
||||
|
||||
Maintain these branch protection rules on `main`:
|
||||
|
||||
- Require status checks before merge.
|
||||
- Require check `CI Required Gate`.
|
||||
- Require pull request reviews before merge.
|
||||
- Require CODEOWNERS review for protected paths.
|
||||
- Dismiss stale approvals when new commits are pushed.
|
||||
- Restrict force-push on protected branches.
|
||||
|
||||
## 3) PR Lifecycle
|
||||
|
||||
### Step A: Intake
|
||||
|
||||
- Contributor opens PR with full `.github/pull_request_template.md`.
|
||||
- `PR Labeler` applies path labels + size labels.
|
||||
- `Auto Response` posts first-time contributor guidance.
|
||||
|
||||
### Step B: Validation
|
||||
|
||||
- `CI Required Gate` is the merge gate.
|
||||
- Docs-only PRs use fast-path and skip heavy Rust jobs.
|
||||
- Non-doc PRs must pass lint, tests, and release build smoke check.
|
||||
|
||||
### Step C: Review
|
||||
|
||||
- Reviewers prioritize by risk and size labels.
|
||||
- Security-sensitive paths (`src/security`, runtime, CI) require maintainer attention.
|
||||
- Large PRs (`size: L`/`size: XL`) should be split unless strongly justified.
|
||||
|
||||
### Step D: Merge
|
||||
|
||||
- Prefer **squash merge** to keep history compact.
|
||||
- PR title should follow Conventional Commit style.
|
||||
- Merge only when rollback path is documented.
|
||||
|
||||
## 4) PR Size Policy
|
||||
|
||||
- `size: XS` <= 80 changed lines
|
||||
- `size: S` <= 250 changed lines
|
||||
- `size: M` <= 500 changed lines
|
||||
- `size: L` <= 1000 changed lines
|
||||
- `size: XL` > 1000 changed lines
|
||||
|
||||
Policy:
|
||||
|
||||
- Target `XS/S/M` by default.
|
||||
- `L/XL` PRs need explicit justification and tighter test evidence.
|
||||
- If a large feature is unavoidable, split into stacked PRs.
|
||||
|
||||
## 5) AI/Agent Contribution Policy
|
||||
|
||||
AI-assisted PRs are welcome, and review can also be agent-assisted.
|
||||
|
||||
Required:
|
||||
|
||||
1. Clear PR summary with scope boundary.
|
||||
2. Explicit test/validation evidence.
|
||||
3. Security impact and rollback notes for risky changes.
|
||||
|
||||
Recommended:
|
||||
|
||||
1. Brief tool/workflow notes when automation materially influenced the change.
|
||||
2. Optional prompt/plan snippets for reproducibility.
|
||||
|
||||
We do **not** require contributors to quantify AI-vs-human line ownership.
|
||||
|
||||
Review emphasis for AI-heavy PRs:
|
||||
|
||||
- Contract compatibility
|
||||
- Security boundaries
|
||||
- Error handling and fallback behavior
|
||||
- Performance and memory regressions
|
||||
|
||||
## 6) Review SLA and Queue Discipline
|
||||
|
||||
- First maintainer triage target: within 48 hours.
|
||||
- If PR is blocked, maintainer leaves one actionable checklist.
|
||||
- `stale` automation is used to keep queue healthy; maintainers can apply `no-stale` when needed.
|
||||
|
||||
## 7) Security and Stability Rules
|
||||
|
||||
Changes in these areas require stricter review and stronger test evidence:
|
||||
|
||||
- `src/security/**`
|
||||
- runtime process management
|
||||
- filesystem access boundaries
|
||||
- network/authentication behavior
|
||||
- GitHub workflows and release pipeline
|
||||
|
||||
Minimum for risky PRs:
|
||||
|
||||
- threat/risk statement
|
||||
- mitigation notes
|
||||
- rollback steps
|
||||
|
||||
## 8) Failure Recovery
|
||||
|
||||
If a merged PR causes regressions:
|
||||
|
||||
1. Revert PR immediately on `main`.
|
||||
2. Open a follow-up issue with root-cause analysis.
|
||||
3. Re-introduce fix only with regression tests.
|
||||
|
||||
Prefer fast restore of service quality over delayed perfect fixes.
|
||||
|
||||
## 9) Maintainer Checklist (Merge-Ready)
|
||||
|
||||
- Scope is focused and understandable.
|
||||
- CI gate is green.
|
||||
- Security impact fields are complete.
|
||||
- Agent workflow notes are sufficient for reproducibility (if automation was used).
|
||||
- Rollback plan is explicit.
|
||||
- Commit title follows Conventional Commits.
|
||||
|
||||
## 10) Agent Review Operating Model
|
||||
|
||||
To keep review quality stable under high PR volume, we use a two-lane review model:
|
||||
|
||||
### Lane A: Fast triage (agent-friendly)
|
||||
|
||||
- Confirm PR template completeness.
|
||||
- Confirm CI gate signal (`CI Required Gate`).
|
||||
- Confirm risk class via labels and touched paths.
|
||||
- Confirm rollback statement exists.
|
||||
|
||||
### Lane B: Deep review (risk-based)
|
||||
|
||||
Required for high-risk changes (security/runtime/gateway/CI):
|
||||
|
||||
- Validate threat model assumptions.
|
||||
- Validate failure mode and degradation behavior.
|
||||
- Validate backward compatibility and migration impact.
|
||||
- Validate observability/logging impact.
|
||||
|
||||
## 11) Queue Priority and Label Discipline
|
||||
|
||||
Triage order recommendation:
|
||||
|
||||
1. `size: XS`/`size: S` + bug/security fixes
|
||||
2. `size: M` focused changes
|
||||
3. `size: L`/`size: XL` split requests or staged review
|
||||
|
||||
Label discipline:
|
||||
|
||||
- Path labels identify subsystem ownership quickly.
|
||||
- Size labels drive batching strategy.
|
||||
- `no-stale` is reserved for accepted-but-blocked work.
|
||||
|
||||
## 12) Agent Handoff Contract
|
||||
|
||||
When one agent hands off to another (or to a maintainer), include:
|
||||
|
||||
1. Scope boundary (what changed / what did not).
|
||||
2. Validation evidence.
|
||||
3. Open risks and unknowns.
|
||||
4. Suggested next action.
|
||||
|
||||
This keeps context loss low and avoids repeated deep dives.
|
||||
Loading…
Add table
Add a link
Reference in a new issue