feat: migrate missing harnesses, templates, and workflows from agent-runtimes
Brings the framework CRS repo up to date with all content that was living in agent-runtimes (local-dev fallback) but hadn't been promoted. New composites: feature-delivery-loop, integration-direct, scaffolding-repo, sonnet-impl-narrow, sonnet-manager, test-writing-repo New contexts: integration/v1, scaffolding/v1, sonnet-manager/v1, z-ai/v1, airouter/v1/bin (anthropic-compat-wrapper.sh), cp-harness/v1/init.sh New task-templates: sonnet-integrator.yaml, workflow/* (17 typed workflow task templates for the Epic 1 pipeline) Updated: agent-repo/v1/finalize.sh — adds AR-38/F97 empty-deliverable audit (SKIP_BRANCH_PUSH support, boilerplate-path filtering, ci_metadata.json flag) Also adds MEMORY.md index and memory/ topic files for the framework repo.
This commit is contained in:
21
memory/decisions.md
Normal file
21
memory/decisions.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Decisions
|
||||
|
||||
## Weekly fork cleanup workflow on `agent-runtimes-agents`
|
||||
|
||||
A weekly cron in the fork's `.gitea/workflows/cleanup.yaml` deletes `task-*` branches that have been inactive for 7+ days, and resets `main` to an orphan commit if there have been no commits for 7+ days. Supports a dry-run via `workflow_dispatch`. Runs on the fork (not the parent) because Gitea Actions is per-repo and the fork enables Actions independently. Merged 2026-05-04 (PR #1, opened by ai_enablement, merged by admin).
|
||||
|
||||
## Shallow clones (`--depth 1`) for task branches in fork cleanup
|
||||
|
||||
The fork-cleanup workflow uses `--depth 1` when cloning individual task branches it is about to delete — no history is needed beyond the tip. Keeps the runner cheap. The exception is the cleanup job itself, which uses `fetch-depth: 0` so it can inspect commit dates across `main`.
|
||||
|
||||
## Workspace pre-test hook reverts agent test edits before each test run
|
||||
|
||||
`pre_test.sh` at the harness level reverts any agent modifications to test folders before each test run. The hook writes `{"reverted": N}` to `/workspace/.agent-output/.pre-test-result.json` atomically (mktemp + mv). Exit non-zero → that test attempt is skipped. Closes BUG-5 (`.agent-output/` silent drops) and prevents agents from tampering with the tests they are being judged against.
|
||||
|
||||
## Workflow nodes declare `output: {path, min_bytes}` for validation
|
||||
|
||||
All 17 nodes in the spec-planning workflow now carry an `output:` block. The finalize step validates that the declared file exists and meets the minimum size before declaring the node successful. Pairs with wrong-path detection: if the agent writes the right content to the wrong path, a `.correction-prompt.txt` sentinel is written and the entrypoint re-invokes the agent with the correction prompt. Closes BUG-20 (MiniMax finalize no-push).
|
||||
|
||||
## Push retry with debug tracing in finalize
|
||||
|
||||
`finalize.sh` now runs with `set -x` tracing and retries the final git push up to `AGENT_PUSH_RETRIES` times. Output validation gates the push: if `AGENT_EXPECTED_OUTPUT` is set and the file is missing or under-sized, the finalize fails loudly rather than silently pushing an empty branch.
|
||||
25
memory/gotchas-gitea.md
Normal file
25
memory/gotchas-gitea.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Gitea Gotchas
|
||||
|
||||
## `/login` returns 404 — use Basic Auth or `/users/<username>/access_tokens`
|
||||
|
||||
Symptom: hitting `/api/v1/login` (or any `/login`-style endpoint) returns `404 Not Found`. Easy to mistake for a misconfigured Gitea instance.
|
||||
|
||||
Fix: Gitea has no session-login API endpoint. Either (a) use HTTP Basic Auth directly against any `/api/v1/` endpoint with `auth=("user","pass")` in `httpx`/`requests`, or (b) create an access token by POSTing to `/api/v1/users/<username>/access_tokens` (also Basic-Auth'd). Bearer token auth is supported on subsequent calls *after* you have a token.
|
||||
|
||||
## API access tokens require HTTP Basic Auth, not Bearer
|
||||
|
||||
Symptom: Bearer token auth (`Authorization: Bearer <token>`) returns `401 Unauthorized` even with a valid access token against Gitea API endpoints used for token creation.
|
||||
|
||||
Fix: use `httpx.get(url, auth=("user","pass"))` (Basic Auth) for token-creation calls. Once you hold a personal access token, subsequent API calls accept it as the `password` half of Basic Auth (with the username as the user) — still NOT Bearer-style. Encode this in any helper library wrapping the Gitea API.
|
||||
|
||||
## PR state `closed` with `merged: true` means merged, not abandoned
|
||||
|
||||
Symptom: PR appears `state: closed` in the API response; easy to assume the PR was cancelled.
|
||||
|
||||
Fix: always check `merged` alongside `state`. Gitea encodes merged PRs as `state: closed, merged: true`. Parse both fields. When verifying a PR's outcome programmatically, dump the full JSON (`json.dumps(..., indent=2)`) and read both rather than asserting on `state` alone.
|
||||
|
||||
## Fork actions run on the fork, not the parent
|
||||
|
||||
Symptom: A workflow file lives on a fork repo and you expect the parent repo's Actions runner to see it — or vice versa. The workflow never fires (or fires on the wrong runner).
|
||||
|
||||
Fix: Gitea Actions is enabled per-repo. `has_actions=true` on the parent does NOT propagate to forks — forks must enable Actions independently. Fork-cleanup workflows must be committed to the fork's own `.gitea/workflows/` and run on the fork. Parent-repo workflows ignore fork branches entirely.
|
||||
7
memory/gotchas-tokens.md
Normal file
7
memory/gotchas-tokens.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Token Gotchas
|
||||
|
||||
## `~/.config/agent-runtimes/tokens.json` uses flat structure
|
||||
|
||||
Symptom: code expecting a nested `{provider: {access_token, expires_at}}` shape fails to find the token.
|
||||
|
||||
Fix: the file is flat — `{"access_token": "...", "expires_at": <unix_seconds>}`. There is no provider key. Read it as a flat dict. When debugging "is my token expired?", compare `expires_at` against `int(time.time())` directly — both are Unix epoch seconds.
|
||||
27
memory/log/2026-05-04.225112.md
Normal file
27
memory/log/2026-05-04.225112.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Session Log -- 2026-05-04
|
||||
|
||||
## Summary
|
||||
Implemented 5 planned fixes for BUG-5 (`.agent-output/` silent drops) and BUG-20 (MiniMax finalize no-push): pre_test.sh harness hook, output validation in finalize, push retry with debug tracing, spec-planning workflow output tags, and wrong-path detection with agent correction re-invoke. Fork cleanup PR merged, agent-monitor PR #44 merged.
|
||||
|
||||
## Decisions
|
||||
- Fork cleanup workflow (PR #1 on agent-runtimes-agents): weekly cron deletes `task-*` branches inactive for 7+ days; main reset to orphan commit if no commits for 7+ days. Supports dry-run via workflow_dispatch. **Merged** (2026-05-04 10:39 UTC by admin).
|
||||
- Gitea API token auth requires HTTP Basic Auth (`auth=("user","pass")`) not Bearer token — Bearer returns 401 even with valid access token. Use `httpx.get(..., auth=("user","pass"))` pattern.
|
||||
- Shallow clone (`--depth 1`) for task branches in fork cleanup to avoid bloating with full history.
|
||||
|
||||
## Gotchas Discovered
|
||||
- **[Gitea Gotchas]** Gitea API endpoint `/login` is `404 Not Found` — use `/users/<username>/access_tokens` to create tokens, or use HTTP Basic Auth directly against any `/api/v1/` endpoint with `auth=("user","pass")`.
|
||||
- **[Gitea Gotchas]** PR state `closed` with `merged: true` means the PR was merged (not just closed). Gitea distinguishes merged vs closed states.
|
||||
- **[Gitea Gotchas]** Fork PRs use the parent repo's Actions (has_actions=true on parent, `has_actions: false` on fork). Fork cleanup workflow runs on the fork's GHA because fork enables Actions independently.
|
||||
- **[tokens]** Token file at `~/.config/agent-runtimes/tokens.json` uses flat structure: `{"access_token": "...", "expires_at": N}`. Token was valid (not expired at session continuation time: now 1777891716 vs expiry 1777891804).
|
||||
|
||||
## Key Context
|
||||
- **agent-runtime-framework** `8bbf6cb`: pre_test.sh created (harness-level test folder revert), finalize.sh gains `set -x` tracing, push retry (`AGENT_PUSH_RETRIES`), output validation (`AGENT_EXPECTED_OUTPUT`), wrong-path detection + `.correction-prompt.txt` sentinel for entrypoint re-invoke. All 17 spec-planning workflow nodes tagged with `output: {path, min_bytes}`.
|
||||
- **agent-runtimes-agents** fork: `fork-cleanup` branch merged to main (PR #1 by ai_enablement, merged by admin 2026-05-04). Workflow file at `.gitea/workflows/cleanup.yaml`.
|
||||
- **agent-runtimes** `148d9d3`: PR #44 merged — `scripts/agent-monitor` gains `provider` and `model_full` columns.
|
||||
- **agent-runtimes** local uncommitted: M22 Phase 3 manifests work (`controlplane/api/manifests.py`, `controlplane/db/manifest_store.py`, migration `20260504_0017_m16_phase3_manifests.py`, `controlplane/manifests/`). Not related to this session's focus.
|
||||
- Two ops gates pending before M22 Phase 9 live cutover: CI build `agent-runtimes-init:1.0.0` image; `agent-session` Role deployed via `homelab/agent-runtimes-deploy` + ArgoCD sync.
|
||||
|
||||
## Process Notes
|
||||
- When verifying PR state via Gitea API: parse JSON directly (don't assume specific keys — use `json.dumps(..., indent=2)` to inspect full structure).
|
||||
- Fork cleanup workflow commits to `agent-runtimes-agents` fork main; parent `agent-runtimes` main unchanged. Fork's main tracked via `agent-runtimes-agents` remote in local `agent-runtime-framework` checkout.
|
||||
- Fork cleanup's `fetch-depth: 0` is needed for commit date inspection even with shallow clones elsewhere.
|
||||
17
memory/process-lessons.md
Normal file
17
memory/process-lessons.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Process Lessons
|
||||
|
||||
## When verifying PR state via the Gitea API, dump the full JSON
|
||||
|
||||
Do not assert on a single key like `state`. Dump the response (`json.dumps(..., indent=2)`) and read `state`, `merged`, `merged_at`, and `merge_commit_sha` together. PRs that look "closed" may have been merged; PRs that look "open" may have a stale `head` SHA pointing at a deleted branch.
|
||||
|
||||
## Fork-cleanup workflows must live on the fork, not the parent
|
||||
|
||||
When the goal is "clean up branches on a fork", commit the workflow to the fork's `.gitea/workflows/`. The parent repo's Actions runner does not see fork branches. Verify Gitea Actions is enabled on the fork (`has_actions: true` in the fork's repo metadata).
|
||||
|
||||
## Use `fetch-depth: 0` in cleanup jobs that inspect commit dates
|
||||
|
||||
Shallow clones omit the timestamps needed to decide "this branch has been inactive for 7 days". The cleanup job itself must use `fetch-depth: 0` even if every other clone in the workflow is shallow.
|
||||
|
||||
## Test the wrong-path detection by writing to the wrong path on purpose
|
||||
|
||||
When adding output validation + correction prompt, do a smoke test that deliberately writes the expected content to the wrong path. Confirm the sentinel `.correction-prompt.txt` is written and the entrypoint re-invokes the agent. Don't rely on accidental coverage.
|
||||
Reference in New Issue
Block a user