Compare commits
12 Commits
claw-code/
...
claude/iss
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e83e7183e8 | ||
| e07c3bcf00 | |||
| fcdbdd9f50 | |||
| 87209a933f | |||
| 61d137798e | |||
| 5009f972c1 | |||
| 0438120402 | |||
| b580ed71bf | |||
|
|
8abd0ac01e | ||
| 3fc47a0e2e | |||
| 9b4fcc5ee4 | |||
| cbe1b79fbb |
2
.claw/sessions/session-1775533542734-0.jsonl
Normal file
2
.claw/sessions/session-1775533542734-0.jsonl
Normal file
@@ -0,0 +1,2 @@
|
||||
{"created_at_ms":1775533542734,"session_id":"session-1775533542734-0","type":"session_meta","updated_at_ms":1775533542734,"version":1}
|
||||
{"message":{"blocks":[{"text":"You are Code Claw running as the Gitea user claw-code.\n\nRepository: Timmy_Foundation/hermes-agent\nIssue: #126 — P2: Validate Documentation Audit & Apply to Our Fork\nBranch: claw-code/issue-126\n\nRead the issue and recent comments, then implement the smallest correct change.\nYou are in a git repo checkout already.\n\nIssue body:\n## Context\n\nCommit `43d468ce` is a comprehensive documentation audit — fixes stale info, expands thin pages, adds depth across all docs.\n\n## Acceptance Criteria\n\n- [ ] **Catalog all doc changes**: Run `git show 43d468ce --stat` to list all files changed, then review each for what was fixed/expanded\n- [ ] **Verify key docs are accurate**: Pick 3 docs that were previously thin (setup, deployment, plugin development), confirm they now have comprehensive content\n- [ ] **Identify stale info that was corrected**: Note at least 3 pieces of stale information that were removed or updated\n- [ ] **Apply fixes to our fork if needed**: Check if any of the doc fixes apply to our `Timmy_Foundation/hermes-agent` fork (Timmy-specific references, custom config sections)\n\n## Why This Matters\n\nAccurate documentation is critical for onboarding new agents and maintaining the fleet. Stale docs cost more debugging time than writing them initially.\n\n## Hints\n\n- Run `cd ~/.hermes/hermes-agent && git show 43d468ce --stat` to see the full scope\n- The docs likely cover: setup, plugins, deployment, MCP configuration, and tool integrations\n\n\nParent: #111\n\nRecent comments:\n## 🏷️ Automated Triage Check\n\n**Timestamp:** 2026-04-06T15:30:12.449023 \n**Agent:** Allegro Heartbeat\n\nThis issue has been identified as needing triage:\n\n### Checklist\n- [ ] Clear acceptance criteria defined\n- [ ] Priority label assigned (p0-critical / p1-important / p2-backlog)\n- [ ] Size estimate added (quick-fix / day / week / epic)\n- [ ] Owner assigned\n- [ ] Related issues linked\n\n### Context\n- No comments yet — needs engagement\n- No labels — needs categorization\n- Part of automated backlog maintenance\n\n---\n*Automated triage from Allegro 15-minute heartbeat*\n\n[BURN-DOWN] Dispatched to Code Claw (claw-code worker) as part of nightly burn-down cycle. Heartbeat active.\n\n🟠 Code Claw (OpenRouter qwen/qwen3.6-plus:free) picking up this issue via 15-minute heartbeat.\n\nTimestamp: 2026-04-07T03:45:37Z\n\nRules:\n- Make focused code/config/doc changes only if they directly address the issue.\n- Prefer the smallest proof-oriented fix.\n- Run relevant verification commands if obvious.\n- Do NOT create PRs yourself; the outer worker handles commit/push/PR.\n- If the task is too large or not code-fit, leave the tree unchanged.\n","type":"text"}],"role":"user"},"type":"message"}
|
||||
2
.claw/sessions/session-1775534636684-0.jsonl
Normal file
2
.claw/sessions/session-1775534636684-0.jsonl
Normal file
@@ -0,0 +1,2 @@
|
||||
{"created_at_ms":1775534636684,"session_id":"session-1775534636684-0","type":"session_meta","updated_at_ms":1775534636684,"version":1}
|
||||
{"message":{"blocks":[{"text":"You are Code Claw running as the Gitea user claw-code.\n\nRepository: Timmy_Foundation/hermes-agent\nIssue: #151 — [CONFIG] Add Kimi model to fallback chain for Allegro and Bezalel\nBranch: claw-code/issue-151\n\nRead the issue and recent comments, then implement the smallest correct change.\nYou are in a git repo checkout already.\n\nIssue body:\n## Problem\nAllegro and Bezalel are choking because the Kimi model code is not on their fallback chain. When primary models fail or rate-limit, Kimi should be available as a fallback option but is currently missing.\n\n## Expected Behavior\nKimi model code should be at the front of the fallback chain for both Allegro and Bezalel, so they can remain responsive when primary models are unavailable.\n\n## Context\nThis was reported in Telegram by Alexander Whitestone after observing both agents becoming unresponsive. Ezra was asked to investigate the fallback chain configuration.\n\n## Related\n- timmy-config #302: [ARCH] Fallback Portfolio Runtime Wiring (general fallback framework)\n- hermes-agent #150: [BEZALEL][AUDIT] Telegram Request-to-Gitea Tracking Audit\n\n## Acceptance Criteria\n- [ ] Kimi model code is added to Allegro fallback chain\n- [ ] Kimi model code is added to Bezalel fallback chain\n- [ ] Fallback ordering places Kimi appropriately (front of chain as requested)\n- [ ] Test and confirm both agents can successfully fall back to Kimi\n- [ ] Document the fallback chain configuration for both agents\n\n/assign @ezra\n\nRecent comments:\n[BURN-DOWN] Dispatched to Code Claw (claw-code worker) as part of nightly burn-down cycle. Heartbeat active.\n\n🟠 Code Claw (OpenRouter qwen/qwen3.6-plus:free) picking up this issue via 15-minute heartbeat.\n\nTimestamp: 2026-04-07T04:03:49Z\n\nRules:\n- Make focused code/config/doc changes only if they directly address the issue.\n- Prefer the smallest proof-oriented fix.\n- Run relevant verification commands if obvious.\n- Do NOT create PRs yourself; the outer worker handles commit/push/PR.\n- If the task is too large or not code-fit, leave the tree unchanged.\n","type":"text"}],"role":"user"},"type":"message"}
|
||||
@@ -13,6 +13,7 @@ concurrency:
|
||||
jobs:
|
||||
smoke-and-build:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-22.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -20,6 +21,9 @@ jobs:
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "uv.lock"
|
||||
|
||||
- name: Set up Python 3.11
|
||||
run: uv python install 3.11
|
||||
|
||||
@@ -11,6 +11,7 @@ on:
|
||||
jobs:
|
||||
notebook-smoke:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
1
.github/workflows/dependency-audit.yml
vendored
1
.github/workflows/dependency-audit.yml
vendored
@@ -19,6 +19,7 @@ jobs:
|
||||
audit:
|
||||
name: Audit Python dependencies
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: astral-sh/setup-uv@v5
|
||||
|
||||
1
.github/workflows/docs-site-checks.yml
vendored
1
.github/workflows/docs-site-checks.yml
vendored
@@ -10,6 +10,7 @@ on:
|
||||
jobs:
|
||||
docs-site-checks:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ jobs:
|
||||
create-audit-issue:
|
||||
name: Create quarterly security audit issue
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
1
.github/workflows/secret-scan.yml
vendored
1
.github/workflows/secret-scan.yml
vendored
@@ -12,6 +12,7 @@ jobs:
|
||||
scan:
|
||||
name: Scan for secrets
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
||||
1
.github/workflows/supply-chain-audit.yml
vendored
1
.github/workflows/supply-chain-audit.yml
vendored
@@ -12,6 +12,7 @@ jobs:
|
||||
scan:
|
||||
name: Scan PR for supply chain risks
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
1
.github/workflows/tests.yml
vendored
1
.github/workflows/tests.yml
vendored
@@ -14,6 +14,7 @@ concurrency:
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
||||
91
RELEASE_v0.5.1.md
Normal file
91
RELEASE_v0.5.1.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Hermes Agent v0.5.1 (v2026.4.7)
|
||||
|
||||
**Release Date:** April 7, 2026
|
||||
|
||||
> The Forge hardening release — CI pipeline with syntax guard, health check false-positive elimination, Ezra model fallback chain, and Gitea workflow automation skill.
|
||||
|
||||
---
|
||||
|
||||
## ✨ Highlights
|
||||
|
||||
- **Syntax Guard CI** — New `scripts/syntax_guard.py` compiles all `*.py` files pre-merge, preventing broken Python from ever reaching `main`. Integrated as a required step in `.gitea/workflows/ci.yml`.
|
||||
|
||||
- **Forge Health Check — 13,449 false positives eliminated** — Added `EXCLUDED_PATH_SEGMENTS` to skip `.cache`, `__pycache__`, `.venv`, `node_modules`, `.git`, `.tox` in sensitive-file scans. Reduced noise from 13,449 false positives to 3 real findings.
|
||||
|
||||
- **Ezra resurrected with fallback chain** — Switched Ezra primary from `kimi-for-coding` (terminated 403) to `kimi-k2.5`. Added fallback chain: Kimi → Anthropic → OpenRouter.
|
||||
|
||||
- **Gitea Workflow Automation Skill** — New `skills/devops/gitea-workflow-automation/SKILL.md` gives all wizards step-by-step API workflows for creating issues, PRs, comments, and status checks.
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ CI / Infrastructure
|
||||
|
||||
### Syntax Guard (#167)
|
||||
- Added `scripts/syntax_guard.py` — compiles all `*.py` files to catch syntax errors before merge
|
||||
- Integrated into `.gitea/workflows/ci.yml` as a required step
|
||||
|
||||
### CI uv Caching (#187)
|
||||
- Enabled `enable-cache: true` with `cache-dependency-glob: "uv.lock"` in all CI workflows
|
||||
- Faster CI runs, less redundant dependency resolution
|
||||
|
||||
### CI Runner Container Pinning (#180 / #174)
|
||||
- Pinned all workflow jobs to `container: catthehacker/ubuntu:act-22.04`
|
||||
- Fixes act runner failures (Node.js missing in default container)
|
||||
- Gitea Actions now compatible with local act runners
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
### Forge Health Check False Positives (#175)
|
||||
- Added `EXCLUDED_PATH_SEGMENTS` to skip `.cache`, `__pycache__`, `.venv`, `node_modules`, `.git`, `.tox`, `site-packages`
|
||||
- Excluded `.css` files and `secret_scan*.py` tooling from sensitive-file scan
|
||||
|
||||
### Syntax Error Fix (#188)
|
||||
- Fixed indentation error in `tests/agent/test_skill_name_traversal.py` line 282
|
||||
- Unblocked CI — all tests can run again
|
||||
|
||||
### Ezra Model Fallback Fix
|
||||
- Switched Ezra primary from `kimi-for-coding` (403 terminated) to `kimi-k2.5`
|
||||
- Added fallback chain: Kimi → Anthropic → OpenRouter
|
||||
- Ezra is operational again with robust failover
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ New Skills
|
||||
|
||||
### Gitea Workflow Automation (#181)
|
||||
- `skills/devops/gitea-workflow-automation/SKILL.md`
|
||||
- Provides step-by-step API workflows for: listing issues, creating issues, opening PRs, merging PRs, adding comments, creating releases, checking CI status
|
||||
- Prerequisites: `GITEA_URL`, `GITEA_TOKEN`, `GITEA_USER` env vars + `curl` and `jq`
|
||||
|
||||
---
|
||||
|
||||
## Files Changed
|
||||
|
||||
```
|
||||
.gitea/workflows/ci.yml | 9 ++
|
||||
.gitea/workflows/notebook-ci.yml | 1 +
|
||||
.github/workflows/*.yml | 6 +
|
||||
config/ezra-kimi-primary.yaml | 64 +++++++---------
|
||||
scripts/forge_health_check.py | 22 +++++
|
||||
scripts/syntax_guard.py | 20 +++++
|
||||
skills/devops/gitea-workflow-automation/ | 100 +++++++++++++++++++++++
|
||||
tests/agent/test_skill_name_traversal.py | 2 +-
|
||||
15 files changed, 190 insertions(+), 38 deletions(-)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verification
|
||||
|
||||
- [x] Syntax guard passes: `python3 scripts/syntax_guard.py` → "All Python files compile successfully"
|
||||
- [x] `EXCLUDED_PATH_SEGMENTS` present in `scripts/forge_health_check.py`
|
||||
- [x] `skills/devops/gitea-workflow-automation/SKILL.md` present
|
||||
- [x] Ezra config: `kimi-k2.5` primary with Anthropic + OpenRouter fallback chain
|
||||
- [x] Fast-forward merge completed successfully
|
||||
- [x] No dependency changes (`pyproject.toml`, `requirements.txt` unchanged)
|
||||
|
||||
---
|
||||
|
||||
*Compiled by Claude — reviewing Bezalel's upgrade report (issue #192)*
|
||||
@@ -98,9 +98,23 @@ class HealthReport:
|
||||
self.passed = False
|
||||
|
||||
|
||||
EXCLUDED_PATH_SEGMENTS = frozenset({
|
||||
".cache", "__pycache__", ".venv", "venv", "site-packages",
|
||||
".local/share/uv", "node_modules", ".git", ".tox",
|
||||
})
|
||||
|
||||
|
||||
def _is_excluded_path(path: Path) -> bool:
|
||||
"""Skip cache, venv, and package-manager directories."""
|
||||
parts = set(path.parts)
|
||||
return not parts.isdisjoint(EXCLUDED_PATH_SEGMENTS)
|
||||
|
||||
|
||||
def scan_orphaned_bytecode(root: Path, report: HealthReport) -> None:
|
||||
"""Detect .pyc files without corresponding .py source files."""
|
||||
for pyc in root.rglob("*.pyc"):
|
||||
if _is_excluded_path(pyc):
|
||||
continue
|
||||
py = pyc.with_suffix(".py")
|
||||
if not py.exists():
|
||||
# Also check __pycache__ naming convention
|
||||
@@ -142,6 +156,12 @@ def _is_sensitive_filename(name: str) -> bool:
|
||||
lower = name.lower()
|
||||
if lower == ".env.example":
|
||||
return False
|
||||
# Skip stylesheet and documentation artifacts
|
||||
if lower.endswith(".css"):
|
||||
return False
|
||||
# Skip scanner tooling — these are detectors, not secrets
|
||||
if lower in {"secret_scan.py", "secret_scanner.py"}:
|
||||
return False
|
||||
if any(pat in lower for pat in SENSITIVE_FILE_PATTERNS):
|
||||
return True
|
||||
if any(lower.startswith(pref) for pref in SENSITIVE_NAME_PREFIXES):
|
||||
@@ -156,6 +176,8 @@ def scan_sensitive_file_permissions(root: Path, report: HealthReport, fix: bool
|
||||
for fpath in root.rglob("*"):
|
||||
if not fpath.is_file():
|
||||
continue
|
||||
if _is_excluded_path(fpath):
|
||||
continue
|
||||
# Skip test files — real secrets should never live in tests/
|
||||
if "/tests/" in str(fpath) or str(fpath).startswith(str(root / "tests")):
|
||||
continue
|
||||
|
||||
100
skills/devops/gitea-workflow-automation/SKILL.md
Normal file
100
skills/devops/gitea-workflow-automation/SKILL.md
Normal file
@@ -0,0 +1,100 @@
|
||||
---
|
||||
name: gitea-workflow-automation
|
||||
title: Gitea Workflow Automation
|
||||
description: Automate Gitea issues, PRs, and repository workflows via the API for forge CI and backlog tracking.
|
||||
trigger: When creating Gitea issues, pull requests, or automating forge repository workflows.
|
||||
---
|
||||
|
||||
# Gitea Workflow Automation
|
||||
|
||||
## Trigger
|
||||
Use this skill when automating Gitea operations: creating issues, opening PRs, checking repository state, or integrating Gitea into CI/backlog workflows.
|
||||
|
||||
## Prerequisites
|
||||
- `GITEA_URL` environment variable set (e.g., `https://forge.alexanderwhitestone.com`)
|
||||
- `GITEA_TOKEN` environment variable with a valid API token
|
||||
- `GITEA_USER` or explicit owner/org name
|
||||
- `curl` and `jq` available in the environment
|
||||
|
||||
## Step-by-Step Workflow
|
||||
|
||||
### 1. Verify Environment
|
||||
```bash
|
||||
: "${GITEA_URL?}" "${GITEA_TOKEN?}" "${GITEA_USER?}"
|
||||
echo "Gitea env OK"
|
||||
```
|
||||
|
||||
### 2. List Issues in a Repository
|
||||
```bash
|
||||
curl -s -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}/issues?state=open&limit=50" | jq '.[] | {number, title, state}'
|
||||
```
|
||||
|
||||
### 3. Create an Issue
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}/issues" \
|
||||
-d "{\"title\":\"${TITLE}\",\"body\":\"${BODY}\",\"assignees\":[\"${ASSIGNEE}\"]}
|
||||
```
|
||||
- Escape newlines in `BODY` if passing inline; prefer a JSON file for multi-line bodies.
|
||||
|
||||
### 4. Create a Pull Request
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}/pulls" \
|
||||
-d "{\"title\":\"${TITLE}\",\"body\":\"${BODY}\",\"head\":\"${BRANCH}\",\"base\":\"${BASE_BRANCH}\"}"
|
||||
```
|
||||
|
||||
### 5. Check PR Status / Diff
|
||||
```bash
|
||||
curl -s -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}/pulls/${PR_NUMBER}" | jq '{number, title, state, mergeable}'
|
||||
```
|
||||
|
||||
### 6. Push Code Before Opening PR
|
||||
```bash
|
||||
git checkout -b "${BRANCH}"
|
||||
git add .
|
||||
git commit -m "${COMMIT_MSG}"
|
||||
git push origin "${BRANCH}"
|
||||
```
|
||||
|
||||
### 7. Add Comments to Issues/PRs
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}/issues/${NUMBER}/comments" \
|
||||
-d "{\"body\":\"${COMMENT_BODY}\"}"
|
||||
```
|
||||
|
||||
## Verification Checklist
|
||||
- [ ] Environment variables are exported and non-empty
|
||||
- [ ] API responses are parsed with `jq` to confirm success
|
||||
- [ ] Issue/PR numbers are captured from the JSON response for cross-linking
|
||||
- [ ] Branch exists on remote before creating a PR
|
||||
- [ ] Multi-line bodies are written to a temp JSON file to avoid escaping hell
|
||||
|
||||
## Pitfalls
|
||||
- **Trailing slashes in `GITEA_URL`:** Ensure `GITEA_URL` does not end with `/` or double slashes break URLs.
|
||||
- **Branch not pushed:** Creating a PR for a local-only branch returns 422.
|
||||
- **Escape hell:** For multi-line issue/PR bodies, write JSON to a file with `cat <<EOF > /tmp/payload.json` and pass `@/tmp/payload.json` to curl instead of inline strings.
|
||||
- **Token scope:** If operations fail with 403, verify the token has `repo` or `write:issue` scope.
|
||||
- **Pagination:** Default limit is 30 issues; use `?limit=100` or paginate with `page=` for large backlogs.
|
||||
|
||||
## Example: Full Issue Creation with File Body
|
||||
```bash
|
||||
cat <<'EOF' > /tmp/issue.json
|
||||
{
|
||||
"title": "[Bezalel] Forge Health Check",
|
||||
"body": "Build a diagnostic scanner for artifact integrity and permissions.\n\n- Detect .pyc without .py source\n- Detect world-readable sensitive files\n- Output JSON for CI consumption",
|
||||
"assignees": ["bezalel"],
|
||||
"labels": ["enhancement", "security"]
|
||||
}
|
||||
EOF
|
||||
curl -s -X POST -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_URL}/api/v1/repos/Timmy_Foundation/hermes-agent/issues" \
|
||||
-d @/tmp/issue.json | jq '.number'
|
||||
```
|
||||
@@ -279,7 +279,7 @@ class TestSkillViewFilePathSecurity:
|
||||
"""Tests for file_path parameter security in skill_view."""
|
||||
|
||||
@pytest.fixture
|
||||
def setup_skill_with_files(self, tmp_path):
|
||||
def setup_skill_with_files(self, tmp_path):
|
||||
"""Create a skill with supporting files."""
|
||||
skills_dir = tmp_path / "skills"
|
||||
skills_dir.mkdir()
|
||||
|
||||
Reference in New Issue
Block a user