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
45 changes: 45 additions & 0 deletions .github/workflows/release-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: release-build

on:
push:
tags:
- 'v*'

permissions:
contents: write

jobs:
build-release:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up mise tools
uses: jdx/mise-action@v3
with:
install: true
cache: true
working_directory: elixir

- name: Install Mix dependencies
working-directory: elixir
run: |
mix local.hex --force
mix local.rebar --force
mix deps.get

- name: Package release artifacts
run: ./scripts/package-release.sh Linux x86_64

- name: Publish GitHub release assets
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
run: |
if gh release view "$TAG" >/dev/null 2>&1; then
gh release upload "$TAG" dist/* --clobber
else
gh release create "$TAG" dist/* --title "$TAG" --generate-notes
fi
55 changes: 55 additions & 0 deletions .github/workflows/release-tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: release-tag

on:
push:
branches:
- main

permissions:
contents: write

jobs:
create-tag:
runs-on: ubuntu-latest
defaults:
run:
working-directory: elixir

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up mise tools
uses: jdx/mise-action@v3
with:
install: true
cache: true
working_directory: elixir

- name: Install Mix dependencies
run: |
mix local.hex --force
mix local.rebar --force
mix deps.get

- name: Resolve release version
id: version
run: |
version=$(sed -n 's/.*version: "\([^"]*\)".*/\1/p' mix.exs | head -n 1)
echo "version=$version" >> "$GITHUB_OUTPUT"

- name: Create tag when version is new
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
tag="v$VERSION"

if git show-ref --tags --verify --quiet "refs/tags/$tag"; then
echo "Tag $tag already exists; skipping."
exit 0
fi

git tag "$tag" "$GITHUB_SHA"
git push origin "$tag"
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ _In this [demo video](.github/media/symphony-demo.mp4), Symphony monitors a GitH
> [!WARNING]
> Symphony is a low-key engineering preview for testing in trusted environments.

## Quick install

On Linux x86_64, install the latest packaged Symphony release into your user profile with:

```bash
curl -fsSL https://raw.githubusercontent.com/BetterAndBetterII/symphony/main/scripts/install.sh | sh
```

After installation, run `symphony` from any project directory. It will create `WORKFLOW.md` when
missing and then boot the service from that directory.

To pin a specific release, export `SYMPHONY_VERSION` before invoking the installer.

## Running Symphony

### Requirements
Expand All @@ -23,7 +36,7 @@ moving from managing coding agents to managing work that needs to get done.
Tell your favorite coding agent to build Symphony in a programming language of your choice:

> Implement Symphony according to the following spec:
> https://github.com/openai/symphony/blob/main/SPEC.md
> https://github.com/BetterAndBetterII/symphony/blob/main/SPEC.md

### Option 2. Use our experimental reference implementation

Expand All @@ -32,7 +45,7 @@ and run the Elixir-based Symphony implementation. You can also ask your favorite
help with the setup:

> Set up Symphony for my repository based on
> https://github.com/openai/symphony/blob/main/elixir/README.md
> https://github.com/BetterAndBetterII/symphony/blob/main/elixir/README.md

---

Expand Down
115 changes: 115 additions & 0 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -2105,6 +2105,9 @@ Use the same validation profiles as Section 17:
exposes the baseline endpoints/error semantics in Section 13.7 if shipped.
- Optional `github_graphql` client-side tool extension exposes raw GitHub GraphQL access through the
app-server session using configured Symphony auth.
- Recommended distribution profile: ship a self-contained release artifact plus a user-level
installer script so that end users can install and run Symphony without language toolchains
installed (see Section 19).
- TODO: Persist retry queue and session metadata across process restarts.
- TODO: Make observability settings configurable in workflow front matter without prescribing UI
implementation details.
Expand All @@ -2118,3 +2121,115 @@ Use the same validation profiles as Section 17:
- Verify hook execution and workflow path resolution on the target host OS/shell environment.
- If the optional HTTP server is shipped, verify the configured port behavior and loopback/default
bind expectations on the target environment.

## 19. Distribution and Installation Profile (Recommended)

This section defines a recommended "single artifact you can run" distribution profile for Symphony
implementations.

This profile is intended to:

- Avoid requiring end users to install language toolchains (for example Elixir/Mix).
- Provide a stable, versioned download surface (GitHub Releases).
- Provide a one-line installer suitable for automation (`curl | sh`), without requiring root.

### 19.1 Release Artifact Contract

An implementation that ships this profile SHOULD publish a release artifact per supported platform.

Recommended contract:

- Archive format: `.tar.gz`
- Asset naming: `<app>-v<version>-<os>-<arch>.tar.gz`
- Example: `symphony-v0.1.0-linux-amd64.tar.gz`
- Archive contents: a self-contained runtime directory that can be extracted and executed directly.
- The extracted payload MUST include everything required to run Symphony on that platform, except:
- an issue tracker token (provided via `WORKFLOW.md` or environment variables), and
- the coding-agent executable itself (for example `codex`).

### 19.2 Installer Script Contract

An implementation that ships this profile SHOULD provide a user-level installer script that:

- Can be executed via a single command line, for example:
- `curl -fsSL <install-script-url> | sh`
- Installs into user-writable directories (no `sudo`).
- Installs an executable named `symphony` into a directory intended for user binaries.
- Recommended default: `${XDG_BIN_HOME:-$HOME/.local/bin}`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve the user experience, especially for users whose systems don't have $HOME/.local/bin in their PATH by default, it would be beneficial for the installer script to check for this. The specification could recommend that the script prints a warning and provides instructions on how to add the directory to the PATH if it's not already present. This would prevent confusion when the symphony command is not found after installation.

Suggested change
- Recommended default: `${XDG_BIN_HOME:-$HOME/.local/bin}`
- Recommended default: `${XDG_BIN_HOME:-$HOME/.local/bin}`. The script SHOULD also warn the user if this directory is not in their `PATH`.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in scripts/install.sh: the installer now warns when the chosen bin directory is not on PATH, so users get an actionable hint after installation.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[codex] accept: this is already implemented in scripts/install.sh; the installer now warns when the chosen bin directory is not on PATH so users get an actionable follow-up after install.

- Installs the runtime payload into a versioned directory intended for user data.
- Recommended default: `${XDG_DATA_HOME:-$HOME/.local/share}/symphony/<version>/`
- Supports selecting a specific version via an environment variable (for example `SYMPHONY_VERSION`),
defaulting to the latest GitHub Release when unset.
- Detects platform + architecture (`uname -s`, `uname -m`) and selects the correct asset name.
- Fails with an actionable error message when the platform is unsupported or download/extract fails.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里如果失败了 要提供清晰的友好的指引

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in this implementation. The installer now fails with explicit Error: messages for unsupported platforms, missing tools, download failures, and broken payloads, and it prints a friendly success/walkthrough message after install.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[codex] accept: handled in this branch. scripts/install.sh now fails with explicit, user-facing Error: guidance for unsupported platforms, missing tools, download failures, and broken payloads.


Security and safety recommendations:

- Prefer downloading from `releases/latest/download/<asset>` to avoid JSON parsing dependencies.
- Optionally publish a `sha256` checksum file per release and verify downloads in the installer when
`sha256sum` is available.

### 19.3 Default WORKFLOW.md Bootstrap Contract

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

默认 的 WORKFLOW.md 创建 用一个选择与填写的 TUI 交互,用户可以填写自己的 GitHub project等,选择codex的权限。其他部分照搬现在的仓库里的WORKFLOW.md

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept this PR focused on the baseline requested in #6: packaged release + install script + automatic WORKFLOW.md bootstrap. The interactive TUI/bootstrap flow is a larger follow-up, so I split it into backlog issue #13 and marked it blocked by #6.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[codex] push back: I am keeping PR #9 scoped to the baseline requirement in #6 (packaged release, installer, automatic WORKFLOW.md bootstrap). The interactive bootstrap/TUI flow is tracked separately in backlog issue #13 because it expands into GitHub project discovery/creation and permissions setup.


To support quick starts, an implementation that ships this profile SHOULD make `symphony` runnable
from any directory:

- If `./WORKFLOW.md` exists: start Symphony using that workflow.
- If `./WORKFLOW.md` is missing: create a default `WORKFLOW.md` in the current directory, then
start Symphony using that newly created file.

The default `WORKFLOW.md` SHOULD:

- Include valid YAML front matter with a complete baseline configuration.
- Default to environment-backed tokens (for example `tracker.api_key: $GITHUB_TOKEN`).
- Use conservative defaults for sandboxing/approvals where applicable.
- Include clear inline comments or prompt text that indicates where to customize project-specific
settings (project owner/number, clone URL, etc).

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

添加一个Boostrap步骤,创建默认 Workflow.md 的时候,列出用户的所有 Poroject,支持TUI选择绑定到一个project,并且支持创建一个 Project,创建的时候直接帮用户配置好所有的必要的 status,支持用户命名这个 project。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same follow-up as #13: project discovery/creation plus status bootstrapping is larger than the non-interactive baseline in #6, so I tracked it separately in backlog issue #13 (blocked by #6) to keep this release/install PR reviewable.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[codex] push back: same scope decision as #13. Project listing/creation plus status bootstrapping is a larger interactive workflow, so I deferred it to backlog issue #13 (blocked by #6) to keep this PR focused on the approved release/install path.

### 19.4 GitHub Release Automation

For GitHub-hosted repos, the recommended automation is:

- On each push to `main`, read the repo version (for example from a version constant).
- If the corresponding tag `v<version>` does not exist, create:
- a Git tag `v<version>` pointing at that commit, and
- a GitHub Release for that tag.
- Build a release artifact for each supported platform and upload it to that GitHub Release.

Implementation note (Elixir reference implementation):

- Use `mix release` with `include_erts: true` so the target host does not need Elixir/Mix installed.

### 19.5 Milestones and Validation (Suggested)

Suggested implementation milestones for this profile:

1. Build a self-contained release artifact
- Add a release definition (for example `mix release`) that bundles the runtime for the target
platform.
- Produce `.tar.gz` assets using the naming contract in Section 19.1.
2. Provide a stable installer entrypoint
- Add an install script (for example `scripts/install.sh`) that installs the runtime payload into
user-writable locations and exposes the `symphony` executable in `${XDG_BIN_HOME:-$HOME/.local/bin}`.
3. Provide a first-run bootstrap for `WORKFLOW.md`
- Ensure `symphony` creates `./WORKFLOW.md` if missing, using a default template that is valid
and runnable once required credentials are present.
4. Automate releases on GitHub Actions
- Add workflows that create `v<version>` tags and publish GitHub Releases with the built assets
attached.
5. Update documentation
- Document the installer, supported platforms, and required runtime dependencies (token, `git`,
`curl`, `tar`, and the coding-agent executable).

Suggested validation for this profile:

- Local validation:
- Build the release artifact and start `symphony` in a clean directory that does not contain a
`WORKFLOW.md`; verify that it creates the file and starts the service.
- Verify that the installed `symphony` works when Elixir/Mix are not present on `$PATH` (for
example by running in a minimal container/VM).
- CI validation:
- Ensure the release workflow builds at least one target and uploads an asset to a GitHub Release.
- Failure-mode validation:
- Run the installer on an unsupported `uname -s` / `uname -m` combination and confirm it fails
with a clear error message.
29 changes: 23 additions & 6 deletions elixir/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Symphony stops the active agent for that issue and cleans up matching workspaces
- Configure the Project field used as "status" (default: `Status`).
- Ensure the Project field values match your expected states (for example: `Todo`, `In Progress`,
`In Review`, `Merging`, `Done`, `Rework`).
6. Follow the instructions below to install the required runtime dependencies and start the service.
6. Either install the packaged release (no Elixir/Mix required on the target host) or use the source workflow below for local development.

## Prerequisites

Expand All @@ -52,16 +52,33 @@ mise install
mise exec -- elixir --version
```

## Run
## Install packaged release

For Linux x86_64 hosts, install the latest release into your user profile without Elixir or Mix:

```bash
curl -fsSL https://raw.githubusercontent.com/BetterAndBetterII/symphony/main/scripts/install.sh | sh
```

To install a specific version instead of the latest release:

```bash
SYMPHONY_VERSION=0.1.0 curl -fsSL https://raw.githubusercontent.com/BetterAndBetterII/symphony/main/scripts/install.sh | sh
```

The installer places the user-facing `symphony` command in `${XDG_BIN_HOME:-$HOME/.local/bin}` and
keeps the versioned runtime payload under `${XDG_DATA_HOME:-$HOME/.local/share}/symphony/`.

## Run from source

```bash
git clone https://github.com/openai/symphony
git clone https://github.com/BetterAndBetterII/symphony
cd symphony/elixir
mise trust -y
mise install
mise exec -- mix setup
mise exec -- mix build
mise exec -- ./bin/symphony --i-understand-that-this-will-be-running-without-the-usual-guardrails ./WORKFLOW.md
mise exec -- ./bin/symphony
```

## Configuration
Expand All @@ -72,7 +89,7 @@ Pass a custom workflow file path to `./bin/symphony` when starting the service:
./bin/symphony /path/to/custom/WORKFLOW.md
```

If no path is passed, Symphony defaults to `./WORKFLOW.md`.
If no path is passed, Symphony defaults to `./WORKFLOW.md` and creates a default template there when the file is missing. Passing an explicit path still requires that file to exist.

Optional flags:

Expand Down Expand Up @@ -145,7 +162,7 @@ codex:
command: "$CODEX_BIN app-server --model gpt-5.3-codex"
```

- If `WORKFLOW.md` is missing or has invalid YAML, startup and scheduling are halted until fixed.
- If the default `./WORKFLOW.md` is missing, Symphony creates a starter template on first run. Missing explicit workflow paths or invalid YAML still halt startup until fixed.
- `server.port` or CLI `--port` enables the optional Phoenix LiveView dashboard and JSON API at
`/`, `/api/v1/state`, `/api/v1/<issue_identifier>`, and `/api/v1/refresh`.

Expand Down
Loading
Loading