Skip to content
Merged
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
298 changes: 206 additions & 92 deletions internal/examples/self_development_test.go

Large diffs are not rendered by default.

53 changes: 24 additions & 29 deletions self-development/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ directory and its nested Agora and Kanon directories references
[`gjkim42/kanon-repo`'s `instructions/AGENTS.md`](https://github.com/gjkim42/kanon-repo/blob/main/instructions/AGENTS.md)
and installs all skills from that repository through `spec.skills`.
Tasks and TaskSpawners add a second role-specific AgentConfig when they need
local identity, conventions, or workflow instructions. The `kelos-workers`
SessionSpawner and Sessions created with `cs` use only `base-agent`.
local identity, conventions, or workflow instructions. The issue and PR
pick-up SessionSpawners for Kelos, Agora, and Kanon, plus Sessions created with
`cs`, use only `base-agent`.

Apply the shared AgentConfig before deploying any self-development resource:

Expand All @@ -48,13 +49,13 @@ while a worker or PR responder is handling an explicitly requested issue or PR.

| Spawner | Trigger | Agent | Description |
|---|---|---|---|
| **kelos-workers** | Webhook: every new issue/PR conversation comment | Codex | Responds in a durable Session, creates or updates PRs when needed, self-reviews, and ensures CI passes |
| **kelos-workers** | Webhook: issue comment `/kelos pick-up` | Codex | Picks up an open issue in a durable Session, creates or updates its PR, self-reviews, and ensures CI passes |
| **kelos-planner** | Webhook: issue comment `/kelos plan` | Codex | Investigates an issue and posts a structured implementation plan — advisory only, no code changes |
| **kelos-reviewer** | Webhook: PR comment `/kelos review` | Codex | Reviews PRs on demand — analyzes code, checks conventions, and updates a sticky review comment |
| **kelos-glm-reviewer** | Webhook: PR comment `/kelos glm-review` | GLM-5.2 | Runs a second code review path with Z.AI GLM-5.2 through OpenCode and updates a sticky review comment |
| **kelos-api-reviewer** | Webhook: issue/PR comment `/kelos api-review` | Codex | Reviews Kubernetes API design on issues or PRs — naming, compatibility, CRD validation |
| **kelos-glm-api-reviewer** | Webhook: issue/PR comment `/kelos glm-api-review` | GLM-5.2 | Runs a second Kubernetes API design review path with Z.AI GLM-5.2 through OpenCode and updates sticky PR comments |
| **kelos-pr-responder** | Webhook: PR review/comment on `generated-by-kelos` PRs | Codex | Re-engages on PR review feedback and updates the existing branch incrementally |
| **kelos-pr-responder** | Webhook: PR comment/review `/kelos pick-up` | Codex | Picks up an open PR in a durable Session and updates its existing branch incrementally |
| **kelos-triage** | Webhook: issue opened/labeled/reopened (`needs-actor`) | Codex | Classifies issues by kind/priority, detects duplicates, and recommends an actor |
| **kelos-fake-user** | Cron (daily 09:00 UTC) | Codex | Tests DX as a new user and maintains one unassigned issue slot for the highest-impact problem found |
| **kelos-fake-strategist** | Cron (every 12 hours) | Codex | Explores new use cases, integrations, and API ideas while maintaining one unassigned strategic issue slot |
Expand All @@ -65,41 +66,34 @@ while a worker or PR responder is handling an explicitly requested issue or PR.

### kelos-workers.yaml

Creates a durable Session for every new non-bot comment in an issue or pull
request conversation. The triggering comment is the immediate request;
`/kelos pick-up` tells the worker to take ownership of the complete issue or PR.
Follow-ups can continue through the Session's web or terminal clients after the
initial turn.
Creates a durable Session when the maintainer posts `/kelos pick-up` on an open
issue. Follow-ups continue through the Session's web or terminal clients after
the initial turn.

| | |
|---|---|
| **Trigger** | Every GitHub `issue_comment` webhook with action `created`, on issues and PRs |
| **Trigger** | GitHub `issue_comment` webhook with an exact `/kelos pick-up` command from `gjkim42` on an open issue |
| **Agent** | Codex |
| **Storage** | 10 GiB persistent volume per created Session |

**Key features:**
- Automatically checks for existing PRs and updates them incrementally
- Uses the PR head branch for PR comments and `kelos-task-<number>` for issue comments
- Uses `kelos-task-<number>` for the issue branch
- Self-reviews PRs before requesting human review
- Ensures CI passes before completion
- Treats `/kelos pick-up` as a request to handle the complete issue or PR
- Requires `/kelos pick-up` from the maintainer before starting work
- Excludes comments from `kelos-bot[bot]` to prevent self-trigger loops
- Keeps the Session available for later web or terminal follow-ups
- Hands off PR review feedback to `kelos-pr-responder`
- May create separate follow-up issues for out-of-scope discoveries; those
follow-ups are exempt from the per-TaskSpawner issue slot cap
follow-ups are exempt from autonomous discovery issue slot caps

**Deploy:**
```bash
kubectl delete taskspawner kelos-workers --ignore-not-found
kubectl apply -f self-development/base-agent.yaml
kubectl apply -f self-development/kelos-workers.yaml
```

The delete is required when migrating an existing installation because
`TaskSpawner/kelos-workers` and `SessionSpawner/kelos-workers` are distinct
Kubernetes objects. Leaving both installed would run both worker flows.

### kelos-planner.yaml

Reacts to `/kelos plan` comments on open issues. Investigates the issue, inspects the codebase, and posts a structured implementation plan — advisory only, no code changes.
Expand Down Expand Up @@ -237,24 +231,26 @@ kubectl apply -f self-development/kelos-glm-api-reviewer.yaml

### kelos-pr-responder.yaml

Picks up open GitHub pull requests labeled `generated-by-kelos` when a reviewer requests changes.
Creates a durable Session when the maintainer posts an exact `/kelos pick-up`
PR comment or review on an open pull request.

| | |
|---|---|
| **Trigger** | GitHub PR review/comment webhooks on `generated-by-kelos` pull requests |
| **Trigger** | GitHub PR comment or review webhook with an exact `/kelos pick-up` command from `gjkim42` on an open PR; review events also exclude drafts |
| **Agent** | Codex |
| **Concurrency** | 8 |
| **Storage** | 10 GiB persistent volume per created Session |

**Key features:**
- Reuses the existing PR branch instead of starting over
- Reads review comments and PR conversation before making incremental changes
- Lets the maintainer stay on the PR page for the common review-feedback loop
- Keeps the Session available for later web or terminal follow-ups
- Requires `/kelos pick-up` PR comment or review body to be picked up
- May create separate follow-up issues for out-of-scope discoveries; those
follow-ups are exempt from the per-TaskSpawner issue slot cap
follow-ups are exempt from autonomous discovery issue slot caps

**Deploy:**
```bash
kubectl apply -f self-development/base-agent.yaml
kubectl apply -f self-development/kelos-pr-responder.yaml
```

Expand Down Expand Up @@ -573,7 +569,7 @@ To adapt these examples for your own repository:
| `bodyPattern` | `TaskSpawner.spec.when.githubWebhook.filters[]` | Go re2 regex match against the comment/review body — the modern replacement for substring-only matching. |
| `excludeBodyPatterns` | `TaskSpawner.spec.when.githubWebhook.filters[]` | Companion to `bodyPattern`: a list of regexes that, if any match, drop the event. Use to carve out bot-echo replies that would otherwise match `bodyPattern`. |
| `commentOn` | `TaskSpawner.spec.when.githubWebhook.filters[]` | Scopes `issue_comment` events to `Issue` or `PullRequest`. GitHub fires `issue_comment` for both, so set this to keep issue-only spawners off PRs (and vice versa). |
| `author` | `TaskSpawner.spec.when.githubWebhook.filters[]` | Restrict matches to a single sender's username. Omit it to accept every sender not listed in top-level `excludeAuthors`, as `kelos-workers` does. |
| `author` | `TaskSpawner.spec.when.githubWebhook.filters[]` | Restrict matches to a single sender's username. Omit it to accept every sender not listed in top-level `excludeAuthors`; `kelos-workers` sets it to the maintainer as an approval gate. |
| `draft` | `TaskSpawner.spec.when.githubWebhook.filters[]` | Match by PR draft status. Set `false` to skip drafts; omit to match both. |

See [docs/reference.md](../docs/reference.md#taskspawner) for the full
Expand Down Expand Up @@ -630,10 +626,10 @@ To adapt these examples for your own repository:
The key pattern in these examples is webhook-triggered handoff plus runtime re-validation:

1. GitHub delivers an `issue_comment`, `issues`, or `pull_request_review` webhook
2. The matching TaskSpawner creates a Task, or `kelos-workers` creates a Session
2. The matching TaskSpawner creates a Task, while the issue and PR pick-up spawners for Kelos, Agora, and Kanon create Sessions
3. The agent re-reads the latest issue or PR state with `gh` before acting, so asynchronous label updates are respected
4. If the agent needs human input, it posts a plain-English status comment describing what happened
5. Every fresh issue or PR conversation comment creates a `kelos-workers` Session; explicit commands or relabel events retrigger the other matching automation
5. An exact `/kelos pick-up` command creates a Session for an open issue or PR; explicit commands or relabel events retrigger the other matching automation

Each matching webhook delivery creates a discrete Task or Session. A created
Session remains available for interactive follow-ups through Session clients.
Expand All @@ -653,9 +649,8 @@ spawners when those spawners include a matching bot-author filter.
- If the issue or PR matched before you deployed the webhook server, retrigger it with a new comment or relabel

**SessionSpawner not creating a Session:**
- Check the SessionSpawner status: `kubectl get sessionspawner kelos-workers -o yaml`
- Check created Sessions: `SPAWNER_UID=$(kubectl get sessionspawner kelos-workers -o jsonpath='{.metadata.uid}'); kubectl get sessions -l kelos.dev/sessionspawner="$SPAWNER_UID"`
- Ensure the old `TaskSpawner/kelos-workers` was removed during migration
- Check the SessionSpawner status: `kubectl get sessionspawner <name> -o yaml`
- Check created Sessions: `SPAWNER_UID=$(kubectl get sessionspawner <name> -o jsonpath='{.metadata.uid}'); kubectl get sessions -l kelos.dev/sessionspawner="$SPAWNER_UID"`
- Check the same Workspace, credentials, webhook server, and recent-delivery details listed above

**Tasks failing immediately:**
Expand Down
69 changes: 36 additions & 33 deletions self-development/agora/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ the Agora repository.

## How It Works

Each TaskSpawner references the root [`base-agent`](../base-agent.yaml) first
for shared instructions and skills. It then references an AgentConfig with
repository- or role-specific instructions: pr-responder, triage, and
squash-commits share `agentconfig.yaml` (`agora-dev-agent`), while workers,
planner, reviewer, fake-user, and fake-strategist define their own AgentConfig
inline.
Every spawner references the root [`base-agent`](../base-agent.yaml) for shared
instructions and skills. The issue and PR pick-up SessionSpawners reference
only `base-agent`. The remaining TaskSpawners add repository- or role-specific
instructions where needed: triage and squash-commits share `agentconfig.yaml`
(`agora-dev-agent`), while planner, reviewer, fake-user, and fake-strategist
define their own AgentConfig inline.

Autonomous discovery agents that publish GitHub issues maintain at most one
open `generated-by-kelos` issue slot per TaskSpawner. The issue body includes a
Expand All @@ -35,14 +35,14 @@ maintain (`self-development/agora/*`) live in *this* repository, so they use the
`self-development/`, and they read Agora's activity cross-repo with
`gh ... --repo kelos-dev/agora`.

## TaskSpawners
## Spawners

| TaskSpawner | Trigger | Agent | Description |
| Spawner | Trigger | Agent | Description |
|---|---|---|---|
| **agora-workers** | Webhook: issue comment `/kelos pick-up` | Codex | Picks up issues, creates or updates PRs, self-reviews, and ensures CI passes |
| **agora-workers** | Webhook: issue comment `/kelos pick-up` | Codex | Creates durable Sessions for issue work, including PR creation or updates |
| **agora-planner** | Webhook: issue comment `/kelos plan` | Codex | Investigates an issue and posts a structured implementation plan — advisory only, no code changes |
| **agora-reviewer** | Webhook: PR comment `/kelos review` | Codex | Reviews PRs on demand — analyzes code, checks conventions, and updates a sticky review comment |
| **agora-pr-responder** | Webhook: PR review/comment with `/kelos pick-up` | Codex | Re-engages on PR review feedback and updates the existing branch incrementally |
| **agora-pr-responder** | Webhook: PR review/comment with `/kelos pick-up` | Codex | Creates durable Sessions for PR review feedback on the existing branch |
| **agora-triage** | Webhook: issue opened/reopened (untriaged) | Codex | Classifies issues by kind/priority, detects duplicates, and recommends an actor |
| **agora-fake-user** | Cron (daily 09:00 UTC) | Codex | Tests DX as a new user and maintains one unassigned issue slot for the highest-impact problem found |
| **agora-fake-strategist** | Cron (every 12 hours) | Codex | Explores new use cases, integrations, and API/UI/deployment capabilities while maintaining one unassigned strategic issue slot |
Expand All @@ -56,8 +56,7 @@ maintain (`self-development/agora/*`) live in *this* repository, so they use the

Apply the root `base-agent` first, then the whole directory. The directory
includes `agentconfig.yaml`, which defines the `agora-dev-agent` role
instructions referenced by the pr-responder, triage, and squash-commits
spawners:
instructions referenced by the triage and squash-commits spawners:

```bash
kubectl apply -f self-development/base-agent.yaml
Expand All @@ -69,22 +68,24 @@ individual spawner after `base-agent` is installed.

### agora-workers.yaml

Picks up open GitHub issues when a maintainer posts `/kelos pick-up` and creates autonomous agent tasks to fix them.
Picks up open GitHub issues when a maintainer posts `/kelos pick-up` and
creates a durable Session to fix them.

| | |
|---|---|
| **Trigger** | GitHub `issue_comment` webhook with `/kelos pick-up` |
| **Agent** | Codex |
| **Concurrency** | 8 |
| **Storage** | 10 Gi PVC |

**Key features:**
- Automatically checks for existing PRs and updates them incrementally
- Self-reviews PRs before requesting human review
- Ensures CI passes before completion
- Requires a `/kelos pick-up` comment to pick up an issue (maintainer approval gate)
- Hands off PR review feedback to `agora-pr-responder`
- Keeps the workspace across Session follow-ups and pod restarts
- Supports routine follow-ups through the Session's web or terminal clients
- May create separate follow-up issues for out-of-scope discoveries; those
follow-ups are exempt from the per-TaskSpawner issue slot cap
follow-ups are exempt from autonomous discovery issue slot caps

**Deploy:**
```bash
Expand Down Expand Up @@ -147,15 +148,17 @@ Picks up open GitHub pull requests when a reviewer requests changes with `/kelos
|---|---|
| **Trigger** | GitHub PR comment with `/kelos pick-up`, or a PR review whose body contains `/kelos pick-up` |
| **Agent** | Codex |
| **Concurrency** | 8 |
| **Storage** | 10 Gi PVC |

**Key features:**
- Reuses the existing PR branch instead of starting over
- Reads review comments and PR conversation before making incremental changes
- Lets the maintainer stay on the PR page for the common review-feedback loop
- Requires a `/kelos pick-up` PR comment or review body to be picked up
- Keeps the workspace across Session follow-ups and pod restarts
- Supports routine follow-ups through the Session's web or terminal clients
- May create separate follow-up issues for out-of-scope discoveries; those
follow-ups are exempt from the per-TaskSpawner issue slot cap
follow-ups are exempt from autonomous discovery issue slot caps

**Deploy:**
```bash
Expand Down Expand Up @@ -372,17 +375,16 @@ The token needs `repo` (full control) and `workflow` (if your repo uses GitHub A

### 4. GitHub Webhook Secret and Delivery

The issue and pull request TaskSpawners are webhook-driven. Reuse the
`github-webhook-secret` from your existing deployment, then configure a
repository webhook on `kelos-dev/agora`:
The issue and PR pick-up SessionSpawners and the remaining webhook
TaskSpawners are event-driven. Reuse the `github-webhook-secret` from your
existing deployment, then configure a repository webhook on `kelos-dev/agora`:

- Point it at the same `https://<your-domain>/webhook/github` endpoint
- Use the same shared secret
- Subscribe to `issues`, `issue_comment`, and `pull_request_review`

Webhook TaskSpawners only react to **new** events after deployment. Retrigger an
existing issue or PR with a fresh comment or relabel if it was already in a
matching state.
Webhook spawners only react to **new** events after deployment. Retrigger an
existing issue or PR with a fresh matching event if needed.

### 5. Agent Credentials Secret

Expand All @@ -394,32 +396,33 @@ kubectl create secret generic kelos-credentials \
--from-file=CODEX_AUTH_JSON=$HOME/.codex/auth.json
```

For API-key auth, change the task template credential type to `api-key` and use
For API-key auth, change the worker credential type to `api-key` and use
`--from-literal=CODEX_API_KEY=<your-openai-api-key>`.

## Customizing

The `TaskSpawner.spec.when.githubWebhook` filters and template variables work
exactly as in `self-development/`. See
The `spec.when.githubWebhook` filters and template variables work the same for
TaskSpawner and SessionSpawner resources. See
[`self-development/README.md`](../README.md#customizing-for-your-repository)
for the webhook filter field reference and the full
[template variable table](../README.md), and
[docs/reference.md](../../docs/reference.md#taskspawner) for the authoritative
`TaskSpawner` field reference.
[docs/reference.md](../../docs/reference.md) for the authoritative field
references.

## Troubleshooting

**TaskSpawner not creating tasks:**
- Check the TaskSpawner status: `kubectl get taskspawner <name> -o yaml`
**Webhook spawner not creating work:**
- For pick-up, check the SessionSpawner status: `kubectl get sessionspawner <name> -o yaml`
- For other automation, check the TaskSpawner status: `kubectl get taskspawner <name> -o yaml`
- Verify the Workspaces exist: `kubectl get workspace agora-agent kelos-agent`
- Ensure credentials are configured: `kubectl get secret kelos-credentials`
- Ensure the GitHub webhook server is enabled and the `github-webhook-secret` exists
- Review the `kelos-dev/agora` repository webhook's recent deliveries in GitHub

**Tasks failing immediately:**
**Sessions or tasks failing immediately:**
- Verify the agent credentials are valid
- Check the Workspace repository is accessible and the token has push access to it
- Review task logs: `kubectl logs -l job-name=<job-name>`
- Review the corresponding Session or Task status and pod logs

**Triage or PR/issue creation failing on labels:**
- Confirm the labels from [Repository labels](#2-repository-labels) exist on `kelos-dev/agora` — `gh` errors when adding or creating with a label that does not exist
Expand Down
Loading
Loading