Skip to content
Open
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
31 changes: 31 additions & 0 deletions .agent/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Changelog

## 0.2.0 - 2026-05-19

### Added

- Opt-in self-approval and self-merge workflows with reviewed-head provenance, PR-author blocks, status comments, and orchestrator handoffs.
- Repository skill setup hooks through `setup.sh` and a shared skill setup action.
- Upload-only track-only session bundles for debugging one-shot runs without treating them as resumable continuity state.

### Changed

- Dispatch and orchestration now recognize orchestrate starts from triage, derive implement tracking metadata from issue context, and carry stacked `base_pr` metadata through router dispatch.
- Onboarding and installation docs now emphasize hosted App prerequisites, reused setup issue status, and simpler first-run guidance.
- Daily summary scheduling and orchestration defaults are more conservative; the packaged daily summary cron remains disabled by default.
- GitHub memory artifacts are namespaced by owner and repo, with legacy artifact cleanup kept explicit.
- Sepo release notes now live in `.agent/CHANGELOG.md` alongside the canonical runtime version in `.agent/package.json`.

### Fixed

- Normalized weak GitHub mention associations across triggers and added regression coverage for weak association handling.
- Hardened auto-merge eligibility, self-approval status upserts, and review handoff behavior for current reviewed heads.

## 0.1.0 - 2026-05-11

### Added

Initial public pre-release of Sepo, a GitHub-native agent harness for orchestrating long-running coding tasks with repository memory through GitHub Actions. It features the following:
- Git-native memory and rubrics layout: code-related memory and induced user/team rubrics live alongside the repository on the `agent/memory` and `agent/rubrics` branches.
- GitHub Actions workflows that can propose code changes, run verification, and execute computational experiments without requiring a separate always-on server.
- Agent orchestration for long-horizon tasks — including task breakdown, review/fix loops, and iterative self-improvement workflows.
114 changes: 114 additions & 0 deletions .agent/action-templates/agent-action-template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Template for generated scheduled agent-action workflows.
# Copy this file to .github/workflows/agent-action-<short-slug>.yml and
# replace the placeholder name, cron, expiration, lane, request text, and
# optional issue-report target.

name: Agent Action / Example

on:
schedule:
- cron: "17 * * * *"
workflow_dispatch:

permissions:
actions: read
contents: read
# If enabling REPORT_ISSUE_NUMBER below, add issue write permission.
id-token: write

concurrency:
group: agent-action-example-${{ github.repository }}
cancel-in-progress: false

env:
ACTION_EXPIRES_AT: "YYYY-MM-DD"
REPORT_ISSUE_NUMBER: ""

jobs:
run:
runs-on: ${{ fromJson(vars.AGENT_RUNS_ON || '["ubuntu-latest"]') }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
token: ${{ github.token }}

- name: Check expiration
id: expiration
uses: ./.github/actions/check-agent-action-expiration
with:
expires_at: ${{ env.ACTION_EXPIRES_AT }}

- name: Resolve GitHub auth
if: steps.expiration.outputs.expired != 'true'
id: auth
uses: ./.github/actions/resolve-github-auth
with:
app_id: ${{ secrets.AGENT_APP_ID }}
app_private_key: ${{ secrets.AGENT_APP_PRIVATE_KEY }}
pat: ${{ secrets.AGENT_PAT }}
fallback_token: ${{ github.token }}

- name: Resolve provider
if: steps.expiration.outputs.expired != 'true'
id: provider
uses: ./.github/actions/resolve-agent-provider
with:
route: answer
default_provider: ${{ vars.AGENT_DEFAULT_PROVIDER || 'auto' }}
openai_api_key: ${{ secrets.OPENAI_API_KEY }}
claude_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

- name: Setup agent runtime
if: steps.expiration.outputs.expired != 'true'
uses: ./.github/actions/setup-agent-runtime
with:
install_codex: ${{ steps.provider.outputs.install_codex }}
install_claude: ${{ steps.provider.outputs.install_claude }}

- name: Resolve task timeout
if: steps.expiration.outputs.expired != 'true'
id: task_timeout
env:
AGENT_TASK_TIMEOUT_POLICY: ${{ vars.AGENT_TASK_TIMEOUT_POLICY || '' }}
ROUTE: answer
run: node .agent/dist/cli/resolve-task-timeout.js

- name: Run scheduled agent task
if: steps.expiration.outputs.expired != 'true'
id: agent
timeout-minutes: ${{ fromJson(steps.task_timeout.outputs.minutes || '30') }}
uses: ./.github/actions/run-agent-task
with:
agent: ${{ steps.provider.outputs.provider }}
github_token: ${{ steps.auth.outputs.token }}
openai_api_key: ${{ secrets.OPENAI_API_KEY }}
claude_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
permission_mode: approve-all
prompt: answer
route: answer
lane: agent-action-example
memory_mode_override: read-only
session_policy: track-only
request_text: |
Describe the bounded recurring task here.
requested_by: ${{ github.actor }}
source_kind: workflow_dispatch
target_kind: repository
target_number: "0"
target_url: ${{ github.server_url }}/${{ github.repository }}
workflow: agent-action-example.yml

# Optional: set REPORT_ISSUE_NUMBER and add issue write permission only when the workflow should report to an issue.
- name: Post report to issue
if: >-
steps.expiration.outputs.expired != 'true' &&
steps.agent.outcome == 'success' &&
env.REPORT_ISSUE_NUMBER != ''
env:
BODY_FILE: ${{ steps.agent.outputs.response_file }}
GH_TOKEN: ${{ steps.auth.outputs.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
RESPONSE_KIND: issue_comment
TARGET_NUMBER: ${{ env.REPORT_ISSUE_NUMBER }}
run: node .agent/dist/cli/post-response.js
44 changes: 44 additions & 0 deletions .agent/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# `.agent` docs

## Overview

- [What is a self-evolving repository?](overview/what-is-self-evolving-repo.md)
- [Quick start](overview/quick-start.md)

## Architecture

- [Overall design](architecture/overall-design.md)
- [Repository memory](architecture/memory.md)
- [User/team rubrics](architecture/rubrics.md)
- [The life cycle of an agent request](architecture/request-lifecycle.md)
- [Supported workflows](architecture/supported-workflows.md)

## Technical details

- [Key concepts](technical-details/key-concepts.md)
- [Session continuity](technical-details/session-continuity.md)
- [Agent orchestrator](technical-details/agent-orchestrator.md)
- [Sepo versioning](technical-details/versioning.md)
- [Developer notes](technical-details/developer-notes.md)

## Actions

- [Actions overview](actions/README.md)
- [Internal actions](actions/internal-actions.md)
- [Agent actions](actions/agent-actions.md)

## Customization

- [Configurations list](customization/configuration-list.md)
- [Repository skills](customization/skills.md)
- [Trigger access policy](access-policy.md)
- [Creating your own actions](customization/creating-your-own-actions.md)
- [Creating your own workflows](customization/creating-your-own-workflows.md)

## Deployment

- [Deployment overview](deployment/README.md)
- [Setup guide](deployment/setup-guide.md)
- [Install into an existing repository](deployment/install-existing-repository.md)
- [Self-hosted GitHub Action runner](deployment/self-hosted-github-action-runner.md)
- [Using your own GitHub App](deployment/using-your-own-github-app.md)
84 changes: 84 additions & 0 deletions .agent/docs/access-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Trigger access policy

`AGENT_ACCESS_POLICY` is an optional repository variable that controls which GitHub author associations can trigger the agent.

## Policy shape

Use `allowed_associations` as the default allowlist for routes without a more specific rule:

```json
{
"allowed_associations": ["OWNER", "MEMBER", "COLLABORATOR"]
}
```

Add `route_overrides` only when a route needs a narrower or wider allowlist than the default:

```json
{
"allowed_associations": ["OWNER", "MEMBER", "COLLABORATOR", "CONTRIBUTOR"],
"route_overrides": {
"implement": ["OWNER", "MEMBER"]
}
}
```

Both keys are optional:

- `allowed_associations`: fallback allowlist for routes without an override
- `route_overrides`: map of route name to route-specific allowlist

Route override keys are matched after route resolution, so future routes can use the same policy shape without changing this schema. If a route has no override, it uses `allowed_associations`; if `allowed_associations` is also unset, it uses the repository visibility default below.

## Example

This policy lets contributors ask questions through the default `answer` behavior, while keeping implementation work limited to owners and organization members:

```json
{
"allowed_associations": ["OWNER", "MEMBER", "COLLABORATOR", "CONTRIBUTOR"],
"route_overrides": {
"implement": ["OWNER", "MEMBER"]
}
}
```

## GitHub author associations

The values match GitHub's [`CommentAuthorAssociation`](https://docs.github.com/graphql/reference/enums#commentauthorassociation) enum:

- `OWNER`
- `MEMBER`
- `COLLABORATOR`
- `CONTRIBUTOR`
- `FIRST_TIME_CONTRIBUTOR`
- `FIRST_TIMER`
- `MANNEQUIN`
- `NONE`

## Default behavior

If `AGENT_ACCESS_POLICY` is unset:

- private repositories allow `OWNER`, `MEMBER`, `COLLABORATOR`, and `CONTRIBUTOR`
- public repositories also allow `OWNER`, `MEMBER`, `COLLABORATOR`, and `CONTRIBUTOR`

Known limitation: GitHub can report private organization members as `CONTRIBUTOR` in public repository issue payloads when the token or payload cannot see private membership. Sepo therefore includes `CONTRIBUTOR` in the public default allowlist as a pragmatic compatibility choice. Repositories that need stricter public access should set `AGENT_ACCESS_POLICY`, for example `{"allowed_associations":["OWNER","MEMBER","COLLABORATOR"]}`.

## Enforcement model

For mention and label triggers, trigger extraction validates the event, resolves explicit routes or labels when present, and records the caller association. Route authorization happens during dispatch resolution after explicit routes are normalized locally or implicit mentions are triaged into a concrete route.

That means `route_overrides` also apply to plain implicit mentions such as `@sepo-agent can you help?`. If the resolved route is not allowed, the router posts an inline unsupported reply instead of silently dropping the request.

Approval comments use the same policy after the pending request is found. The approval check uses the route stored in the pending request marker.

Label triggers authorize the label applier rather than the issue or pull request author. Personal-repository owners map to `OWNER`; visible organization members map to `MEMBER`; repository collaborators with label permission map to `COLLABORATOR`. After a label-triggered request is accepted by the router, `agent-label.yml` removes the triggering `agent/*` label even when the route is denied, so unauthorized queue labels do not linger.

Organization membership detection depends on what the agent's GitHub token can see. With a repo-scoped installation token, only **public** org memberships are visible, so private org members who apply a label resolve as `COLLABORATOR` rather than `MEMBER`. Policies that restrict a route to `MEMBER` only (e.g. `route_overrides.implement: ["OWNER", "MEMBER"]`) may therefore reject private org members unless `COLLABORATOR` is also included.

## Weak association normalization

For mention triggers, the runtime trusts strong `author_association` values (`OWNER`, `MEMBER`, and `COLLABORATOR`) without another lookup. When GitHub reports a weaker value such as `NONE`, `CONTRIBUTOR`, `FIRST_TIMER`, or `FIRST_TIME_CONTRIBUTOR`, Sepo checks the triggering actor with `GET /repos/{owner}/{repo}/collaborators/{username}` and treats a `204` response as `COLLABORATOR` before route authorization. This applies to all supported mention surfaces, including issue and pull request bodies, discussion bodies and comments, issue comments, pull request review comments, and pull request reviews.

Issue-body mentions from `issues` events also refresh `author_association` from the live issue API before the collaborator fallback. These checks cover cases where repo-scoped tokens cannot see private org membership through webhook `author_association`, but GitHub author association remains token- and visibility-dependent. The public default allowlist therefore still includes `CONTRIBUTOR` unless a repository configures a stricter `AGENT_ACCESS_POLICY`.
20 changes: 20 additions & 0 deletions .agent/docs/actions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Actions

This section documents the action layer inside the `.agent` backend.

The docs use three terms consistently:

- **Workflows** are GitHub workflow files in `.github/workflows/`. They define triggers, jobs, permissions, and dispatch boundaries. See [Supported workflows](../architecture/supported-workflows.md).
- **Internal actions** are shared composite GitHub Actions in `.github/actions/`. They scaffold the runtime, resolve GitHub auth, and run agent tasks for workflows.
- **Agent actions** are route-level behaviors such as `answer`, `implement`, `fix-pr`, and `review`. They are selected by mention, label, approval, or workflow dispatch, and are implemented through workflow wiring plus prompts.

## Documentation model

These pages are hand-written for now. The desired long-term pattern is to keep small `agent-doc` metadata blocks near the YAML workflows, composite actions, and prompt files, then render this section from that metadata.

Until that renderer exists:

- [Internal actions](internal-actions.md) is the canonical place for `.github/actions/*` details.
- [Agent actions](agent-actions.md) is the canonical place for route behavior, prompt consumption, session policy, and generated-doc metadata conventions.

Avoid duplicating internal action details in setup or architecture pages. Those pages should explain user-facing behavior and link here for implementation details.
Loading