From 0b4905af3d246bfe26ba86d6ae9b8575eef7c6bb Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 15 Apr 2026 04:08:04 +0000 Subject: [PATCH] chore: gardener housekeeping 2026-04-15 --- AGENTS.md | 2 +- architect/AGENTS.md | 2 +- dev/AGENTS.md | 2 +- gardener/AGENTS.md | 2 +- gardener/pending-actions.json | 23 +---------------------- lib/AGENTS.md | 2 +- planner/AGENTS.md | 2 +- predictor/AGENTS.md | 2 +- review/AGENTS.md | 2 +- supervisor/AGENTS.md | 2 +- 10 files changed, 10 insertions(+), 31 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 211afed..85d1b6a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ - + # Disinto — Agent Instructions ## What this repo is diff --git a/architect/AGENTS.md b/architect/AGENTS.md index 955acd6..49d32b3 100644 --- a/architect/AGENTS.md +++ b/architect/AGENTS.md @@ -1,4 +1,4 @@ - + # Architect — Agent Instructions ## What this agent is diff --git a/dev/AGENTS.md b/dev/AGENTS.md index 22186d5..abeb619 100644 --- a/dev/AGENTS.md +++ b/dev/AGENTS.md @@ -1,4 +1,4 @@ - + # Dev Agent **Role**: Implement issues autonomously — write code, push branches, address diff --git a/gardener/AGENTS.md b/gardener/AGENTS.md index 8ea9c86..8d4c3af 100644 --- a/gardener/AGENTS.md +++ b/gardener/AGENTS.md @@ -1,4 +1,4 @@ - + # Gardener Agent **Role**: Backlog grooming — detect duplicate issues, missing acceptance diff --git a/gardener/pending-actions.json b/gardener/pending-actions.json index 9c26bae..fe51488 100644 --- a/gardener/pending-actions.json +++ b/gardener/pending-actions.json @@ -1,22 +1 @@ -[ - { - "action": "edit_body", - "issue": 745, - "body": "## Problem / motivation\n\ndisinto.ai is an addressable but not an observable — no engagement data flows back to the factory. The planner has no evidence to assess whether the landing page communicates the value proposition.\n\nParent vision issue: #426\nSprint: `website-observability-wire-up` (ops PR #10)\nDesign choices: Q1=A (fetch raw log, process locally), Q2=A (direct cron in edge container), Q3=B (dedicated purpose-limited SSH key)\n\n## Proposed solution\n\nCreate `formulas/collect-engagement.toml` with steps:\n1. SSH into Caddy host using dedicated key (`CADDY_SSH_KEY` from `.env.vault.enc`) — fetch today's access log segment via `scp` or `rsync`\n2. Run `site/collect-engagement.sh` inside the container against the local copy\n3. Commit evidence JSON to ops repo via Forgejo API (`evidence/engagement/YYYY-MM-DD.json`)\n\nAdd a daily cron entry to the edge container entrypoint (like supervisor/planner cron pattern).\n\n## Affected files\n- `formulas/collect-engagement.toml` (new)\n- `docker/edge/entrypoint.sh` or equivalent (cron entry)\n- `site/collect-engagement.sh` (may need minor adaptation for container context)\n\n## Acceptance criteria\n- [ ] `collect-engagement.toml` formula exists with SSH fetch + local parse + API commit steps\n- [ ] Edge container has daily cron entry that triggers the formula\n- [ ] Evidence JSON lands in `evidence/engagement/YYYY-MM-DD.json` on the ops repo\n- [ ] SSH key is read from `.env.vault.enc` (`CADDY_SSH_KEY`), never hardcoded\n- [ ] ShellCheck passes on all new/modified scripts\n\n## Dependencies\n- Sub-issue 3 (evidence directory setup) should land first or concurrently\n\n## Related\n- #426 (parent vision issue — open vision issue, not a blocker)" - }, - { - "action": "edit_body", - "issue": 712, - "body": "## Goal\n\nLet `disinto-chat` perform scoped write actions against the factory — specifically: trigger a Woodpecker CI run, create a Forgejo issue, create a Forgejo PR — via explicit backend endpoints. The UI surfaces these as buttons the user clicks from a chat turn that proposes an action. The model never holds API tokens directly.\n\n## Why\n\n- #623 lists these escalations as the difference between \"chat that talks about the project\" and \"chat that moves the project forward\".\n- Routing through explicit backend endpoints (instead of giving the sandboxed claude process API tokens) keeps the trust model tight: the *user* authorises each action, not the model.\n\n## Scope\n\n### Files to touch\n\n- `docker/chat/server.{py,go}` — new authenticated endpoints (reuse #708 / #709 session check):\n - `POST /chat/action/ci-run` — body `{repo, branch}` → calls Woodpecker API with `WOODPECKER_TOKEN` (already in `.env` from existing factory setup) to trigger a pipeline.\n - `POST /chat/action/issue-create` — body `{title, body, labels}` → calls Forgejo API `/repos///issues` with `FORGE_TOKEN`.\n - `POST /chat/action/pr-create` — body `{head, base, title, body}` → calls `/repos///pulls`.\n - All actions record to #710's NDJSON history as `{role: \"action\", ...}` lines.\n- `docker/chat/ui/index.html` — small HTMX pattern: when claude's response contains a marker like `{...}`, render a clickable button below the message; clicking POSTs to `/chat/action/` with the payload.\n- `lib/generators.sh` chat env: pass `WOODPECKER_TOKEN`, `FORGE_TOKEN`, `FORGE_URL`, `FORGE_OWNER`, `FORGE_REPO`.\n\n### Out of scope\n\n- Destructive actions (branch delete, force push, secret rotation) — deliberately excluded.\n- Multi-step workflows / approval chains.\n- Arbitrary code execution in the chat container (that is what the agents exist for).\n\n## Affected files\n- `docker/chat/server.py` (or `server.go`) — new action endpoints\n- `docker/chat/ui/index.html` — action button rendering\n- `lib/generators.sh` — pass additional env vars to chat container\n\n## Acceptance\n\n- [ ] A chat turn that emits an `{...}` block renders a button; clicking it creates an issue on Forgejo, visible via the API.\n- [ ] CI-trigger action creates a Woodpecker pipeline that can be seen in the CI UI.\n- [ ] PR-create action produces a Forgejo PR with the specified head / base.\n- [ ] All three actions are logged into the #710 history file with role `action` and the response from the API call.\n- [ ] Unauthenticated requests to `/chat/action/*` return 401 (inherits #708 gate).\n\n## Depends on\n\n- #708 (OAuth gate — actions are authorised by the logged-in user).\n- #742 (CI smoke test fix — #712 fails CI until agent-smoke.sh lib sourcing is stabilised)\n- #710 (history — actions need to be logged alongside chat turns).\n\n## Notes\n\n- Forgejo API auth: the factory's `FORGE_TOKEN` is a long-lived admin token. For MVP, reuse it; a follow-up issue can scope it down to per-user Forgejo tokens derived from the OAuth flow.\n- Woodpecker API is at `http://woodpecker:8000/api/...`, reachable via the compose network — no need to go through the edge container.\n- The `` marker is deliberately simple markup the model can emit in its response text. Do not implement tool-calling protocol; do not spin up an MCP server.\n\n## Boundaries for dev-agent\n\n- Do not give the claude subprocess direct API tokens. The chat backend holds them; the model only emits action markers the user clicks.\n- Do not add destructive actions (delete, force-push). Additive only.\n- Do not invent a new markup format beyond `{JSON}`.\n- Parent vision: #623." - }, - { - "action": "edit_body", - "issue": 707, - "body": "## Goal\n\nGive `disinto-chat` its own Claude identity mount so its OAuth refresh races cannot corrupt the factory agents' shared `~/.claude` credentials. Default to a separate `~/.claude-chat/` on the host; support `ANTHROPIC_API_KEY` as a fallback that skips OAuth entirely.\n\n## Why\n\n- #623 root-caused this: Claude Code's internal refresh lock in `~/.claude.lock` operates outside bind-mounted directories, so two containers sharing `~/.claude` can race during token refresh and invalidate each other. The factory has already had OAuth expiry incidents traced to multiple agents sharing credentials.\n- Scoping chat to its own identity dir means chat can be logged in as a different Anthropic account, or pinned to an API key, without touching agent credentials.\n\n## Scope\n\n### Files to touch\n\n- `lib/generators.sh` chat service block (from #705):\n - Replace the throwaway named volume with `${CHAT_CLAUDE_DIR:-${HOME}/.claude-chat}:/home/chat/.claude-chat`.\n - Env: `CLAUDE_CONFIG_DIR=/home/chat/.claude-chat/config`, `CLAUDE_CREDENTIALS_DIR=/home/chat/.claude-chat/config/credentials`.\n - Conditional: if `ANTHROPIC_API_KEY` is set in `.env`, pass it through and **do not** mount `~/.claude-chat` at all (no credentials on disk in that mode).\n- `bin/disinto disinto_init()` — after #620's admin password prompt, add an optional prompt: `Use separate Anthropic identity for chat? (y/N)`. On yes, create `~/.claude-chat/` and invoke `claude login` in a subshell with `CLAUDE_CONFIG_DIR=~/.claude-chat/config`.\n- `lib/claude-config.sh` — factor out the existing `~/.claude` setup logic so a non-default `CLAUDE_CONFIG_DIR` is a first-class parameter. If it is already parameterised, just document it; if not, extract a helper `setup_claude_dir ` and have the existing path call it with the default dir.\n- `docker/chat/Dockerfile` — declare `VOLUME /home/chat/.claude-chat`, set owner to the non-root chat user introduced in #706.\n\n### Out of scope\n\n- Cross-session lock coherence for multiple concurrent chat containers (single-chat-container assumption is fine for MVP).\n- Anthropic team / workspace support — single identity is enough.\n\n## Affected files\n- `lib/generators.sh` — chat service block credential mount\n- `bin/disinto` — init flow: separate chat identity prompt\n- `lib/claude-config.sh` — extract parameterised setup_claude_dir helper\n- `docker/chat/Dockerfile` — declare VOLUME for chat Claude dir\n\n## Acceptance\n\n- [ ] Fresh `disinto init` with \"use separate chat identity\" answered yes creates `~/.claude-chat/` and logs in successfully.\n- [ ] With `ANTHROPIC_API_KEY=sk-ant-...` set in `.env`, chat starts without any `~/.claude-chat` mount (verified via `docker inspect disinto-chat`) and successfully completes a test prompt.\n- [ ] Running the factory agents AND chat simultaneously for 24h does not produce any OAuth refresh failures on either side (manual soak test — document result in PR).\n- [ ] `CLAUDE_CONFIG_DIR` and `CLAUDE_CREDENTIALS_DIR` inside the chat container resolve to `/home/chat/.claude-chat/config*`, not the shared factory path.\n\n## Depends on\n\n- #705 (chat scaffold).\n- #742 (CI smoke test fix — #707 fails CI until agent-smoke.sh lib sourcing is stabilised)\n- #620 (admin password prompt — same init flow this adds a step to).\n\n## Notes\n\n- The factory's existing shared mount is `/var/lib/disinto/claude-shared` (see `lib/generators.sh:113,327,381,426`). Chat must NOT use this path.\n- `flock(\"${HOME}/.claude/session.lock\")` logic mentioned in #623 is load-bearing, not redundant — do not \"simplify\" it.\n- Prefer the API-key path for anyone running the factory on shared hardware; call this out in README updates.\n\n## Boundaries for dev-agent\n\n- Do not try to make chat share `~/.claude` with the agents \"just for convenience\". The whole point of this chunk is the opposite.\n- Do not add a third claude config dir. One for agents, one for chat, done.\n- Do not refactor `lib/claude-config.sh` beyond extracting a parameterised helper if needed.\n- Parent vision: #623." - }, - { - "action": "comment", - "issue": 758, - "body": "Gardener review: this issue requires admin-level Forgejo configuration that no agent can perform autonomously.\n\n**Recommended action (human):** In the ops repo branch protection settings, either:\n1. Add `planner-bot` to the push/merge allowlist, OR\n2. Remove branch protection from `disinto-ops` `main` (agents are the primary writers, human review is informal), OR\n3. Provision an admin service token in `.env.vault.enc` as `FORGE_ADMIN_TOKEN`\n\nUntil one of these options is implemented, all ops repo writes (prerequisites.md, vault items, sprint artifacts) will be lost on container restart.\n\nIssue remains `blocked` — no gardener action can unblock this without operator intervention." - } -] +[] diff --git a/lib/AGENTS.md b/lib/AGENTS.md index b94b8f4..0f53ef8 100644 --- a/lib/AGENTS.md +++ b/lib/AGENTS.md @@ -1,4 +1,4 @@ - + # Shared Helpers (`lib/`) All agents source `lib/env.sh` as their first action. Additional helpers are diff --git a/planner/AGENTS.md b/planner/AGENTS.md index f06ac57..5168eb4 100644 --- a/planner/AGENTS.md +++ b/planner/AGENTS.md @@ -1,4 +1,4 @@ - + # Planner Agent **Role**: Strategic planning using a Prerequisite Tree (Theory of Constraints), diff --git a/predictor/AGENTS.md b/predictor/AGENTS.md index 0e5a21f..b5391fe 100644 --- a/predictor/AGENTS.md +++ b/predictor/AGENTS.md @@ -1,4 +1,4 @@ - + # Predictor Agent **Role**: Abstract adversary (the "goblin"). Runs a 2-step formula diff --git a/review/AGENTS.md b/review/AGENTS.md index f9bf5df..a3eb4c5 100644 --- a/review/AGENTS.md +++ b/review/AGENTS.md @@ -1,4 +1,4 @@ - + # Review Agent **Role**: AI-powered PR review — post structured findings and formal diff --git a/supervisor/AGENTS.md b/supervisor/AGENTS.md index 1ab5dc7..46d7335 100644 --- a/supervisor/AGENTS.md +++ b/supervisor/AGENTS.md @@ -1,4 +1,4 @@ - + # Supervisor Agent **Role**: Health monitoring and auto-remediation, executed as a formula-driven