[pull] main from openai:main#4
Open
pull[bot] wants to merge 41 commits into
Open
Conversation
#### Context The config layer had grown around NimbleOptions and a large getter surface. This branch moves parsing to an Ecto schema and simplifies callers to read typed nested settings directly. #### TL;DR *Replace the bespoke config access layer with an Ecto-backed schema and typed settings access.* #### Summary - Replace the old config extraction path with an Ecto embedded schema and defaults - Collapse `Config` down to `settings/0`, `settings!/0`, and a small runtime helper surface - Update callers and tests to read nested config structs directly instead of one-off getter wrappers - Keep the repo green under format, lint, coverage, and dialyzer by adding the missing schema specs and tests #### Alternatives - Keep NimbleOptions and shrink the wrapper layer incrementally, but that would preserve the custom parser shape - Keep the strict refactor without extra schema tests, but that left `make -C elixir all` red on coverage and dialyzer #### Test Plan - [x] `make -C elixir all` - [x] `cd elixir && mix test test/symphony_elixir/workspace_and_config_test.exs --warnings-as-errors`
#### Context The schema and tests now treat tracker state lists as YAML lists and only lowercase state-limit keys, but `SPEC.md` still documented older and stricter behavior. #### TL;DR *Align `SPEC.md` with the current workflow config and state normalization behavior.* #### Summary - document tracker `active_states` and `terminal_states` as YAML string lists - update the cheat sheet defaults to use list examples instead of CSV strings - remove trim-based state normalization language from the spec #### Alternatives - restore support for comma-separated tracker state strings in the schema - keep trim-based normalization in the spec and change the implementation #### Test Plan - [x] `make -C elixir all` - [x] Docs-only diff reviewed against current schema and tests
#### Context Symphony Elixir had a few correctness gaps around retry scheduling, refresh coalescing, workspace path handling, Codex turn policy forwarding, and running-issue refreshes. #### TL;DR *Stabilize Symphony Elixir orchestration, workspace safety, and Codex policy passthrough.* #### Summary - Ignore stale retry timers and coalesce superseded poll ticks in the orchestrator. - Canonicalize workspace paths and clarify last-known-good workflow reload behavior. - Pass explicit Codex turn sandbox policies through unchanged and add integration coverage. - Paginate Linear by-id issue-state refreshes so running issue reconciliation sees all IDs. #### Alternatives - Keep local validation and rewriting of explicit turn sandbox policies, but that drifted from Codex semantics and broke documented policy types. - Keep single-request by-id issue refreshes, but that truncates after 50 issues and can stop healthy workers during reconciliation. #### Test Plan - [x] `make -C elixir all` - [x] Targeted regression coverage for AppServer turn policy passthrough and Linear by-id pagination
#### Context Add a real end-to-end path for Symphony Elixir that exercises Linear and Codex together, and make it easy to invoke explicitly from one Make target. #### TL;DR *Add a real live Linear/Codex E2E test plus a `make e2e` entrypoint.* #### Summary - Add an opt-in live Elixir test that creates a real Linear project and issue. - Run a real Codex turn and verify both workspace output and Linear side effects. - Require Codex to post a Linear comment and close the issue before completion. - Add `make e2e` with clear failures for missing `LINEAR_API_KEY` or `codex`. - Document the new E2E entrypoint and behavior in the Elixir README. #### Alternatives - Keep using ad hoc `mix test` commands and environment toggles. - Keep shimming Linear or post-processing issue state locally. - Those keep the happy path less reproducible and do not prove Codex can mutate Linear itself during the turn. #### Test Plan - [x] `make -C elixir all` - [x] `env -u LINEAR_API_KEY make -C elixir e2e` - [x] `LINEAR_API_KEY=$(tr -d '\r\n' < ~/.linear_api_key) SYMPHONY_RUN_LIVE_E2E=1 mix test test/symphony_elixir/live_e2e_test.exs`
#### Context Symphony needs to run tickets on SSH workers, keep the live E2E reliable, and preserve correct remote path semantics. #### TL;DR *Add SSH workers, Docker-backed SSH live E2E coverage, per-host caps, and correct worker-side `~` resolution.* #### Summary - Add SSH worker execution, remote workspace handling, and SSH app-server launch support in Elixir. - Add live E2E coverage for both local workers and SSH workers, with Docker-backed SSH workers by default. - Add an optional shared `worker.max_concurrent_agents_per_host` cap and document the SSH extension. - Keep `workspace.root` raw so SSH workers resolve `~` on the worker, while local paths expand at local use sites. #### Alternatives - Keep expanding `workspace.root` in config and carry duplicate raw path state, but that complicates the config model. - Require only absolute remote workspace roots, but that makes real worker setup less ergonomic and less representative. #### Test Plan - [x] `make -C elixir all` - [x] `cd elixir && env -u SYMPHONY_LIVE_SSH_WORKER_HOSTS LINEAR_API_KEY="$(tr -d '\r\n' < ~/.linear_api_key)" SYMPHONY_RUN_LIVE_E2E=1 mix test test/symphony_elixir/live_e2e_test.exs:128`
#### Context The Codex app-server merges stderr into stdout (`stderr_to_stdout`). Non-JSON diagnostic lines written by Codex during healthy turns were incorrectly emitted as `:malformed` protocol events in the Symphony UI. <img width="2496" height="446" alt="Screenshot 2026-03-12 at 4 27 20 PM" src="https://github.com/user-attachments/assets/3d85fa5b-c0d9-4079-87c6-850c7ccf7ee2" /> #### TL;DR *Only emit `:malformed` events for JSON-like protocol frames (lines starting with `{`); silently log all other non-JSON stream output.* #### Summary - Gate `:malformed` event emission on a new `protocol_message_candidate?/1` check — only lines starting with `{` - Preserve full logging of all non-JSON stderr noise via `log_non_json_stream_line` - Fix existing "Capture stderr log" test to assert no `:malformed` event is emitted for stderr noise - Add regression test verifying truncated JSON-like frames still surface as `:malformed` #### Alternatives - Separate stderr from stdout with a dedicated pipe: more invasive change, unnecessary given the simple heuristic - Suppress all non-JSON output silently: would lose valuable diagnostic logging #### Test Plan - [x] `make -C elixir all` - [x] `mise exec -- mix format lib/symphony_elixir/codex/app_server.ex test/symphony_elixir/app_server_test.exs` - [x] Additional: `MIX_ENV=test mise exec -- mix run --no-start -e 'Application.put_env(:symphony_elixir, :workflow_file_path, System.fetch_env!("SYMPHONY_TEST_WORKFLOW")); Mix.Task.run("test", ["test/symphony_elixir/app_server_test.exs"])'` Co-authored-by: Codex <noreply@openai.com>
#### Context SSH failover currently happens inside `AgentRunner`, which can bypass per-host caps and rerun a ticket on a second host after the first host already started setup. #### TL;DR *Keep each worker run on one SSH host and let the orchestrator own retries.* #### Summary - Remove `AgentRunner`'s internal cross-host failover loop - Keep a worker lifetime pinned to one selected SSH host - Add a regression test proving startup failure on one host does not fall through to another #### Alternatives - Keep internal failover and classify retryable errors, but that duplicates orchestrator scheduling logic - Only patch per-host cap enforcement, but invisible cross-host reruns would still risk duplicate side effects #### Test Plan - [x] `make -C elixir all` - [x] `cd elixir && mise exec -- mix test test/symphony_elixir/core_test.exs:1167 test/symphony_elixir/core_test.exs:1237 test/symphony_elixir/core_test.exs:1337 --seed 0`
## Summary Pin floating external GitHub Actions workflow refs to immutable SHAs. ## Why See the rationale doc: https://docs.google.com/document/d/1qOURCNx2zszQ0uWx7Fj5ERu4jpiYjxLVWBWgKa2wTsA/edit?tab=t.0 ## Validation - `rg -n --pcre2 "uses:\s*(?!\./)(?!docker://)[^#\n]+@(?![0-9a-f]{40}(?:\s+#.*)?$)\S+" .github/workflows` - `git diff --check` - `git diff --stat -- .github/workflows`
#### Context SPEC.md had ambiguous conformance language and implementation details that made the service contract harder to port. #### TL;DR *Clarify SPEC.md and normalize RFC-style requirement wording.* #### Summary - Add normative language and tighten config, workspace, reload, restart, and user-input wording. - Move extension config ownership to extension sections. - Point Codex protocol details at the targeted app-server spec instead of duplicating payloads. - Run a careful RFC 2119 terminology pass after mechanical normalization. #### Alternatives - Left attempt/retry redesign and broader safety issues for follow-up spec changes. #### Test Plan - [x] `make -C elixir all` - [x] `git diff --check HEAD~1..HEAD` - [x] RFC keyword scan outside code fences --------- Co-authored-by: Codex <codex@openai.com>
Summary: - Update the default Symphony Codex command to select gpt-5.5 via --config model instead of the root --model flag. - Refresh README and tests so examples and argv assertions match the app-server-compatible command shape. Rationale: - Codex app-server ignores the root --model flag, so the previous command could silently use the default model instead of the intended one. - Passing model through --config keeps the workflow aligned with Codex app-server behavior and the verified gpt-5.5 setup. Tests: - mise exec -- mix format --check-formatted - mise exec -- mix test - mise exec -- mix lint - Isolated app-server smoke test with the updated command Co-authored-by: Codex <codex@openai.com>
#### Context Restrict the PR description lint workflow so forked PR checks run with the least token access needed. #### TL;DR *Set read-only workflow permissions and stop checkout from storing credentials.* #### Summary - Add explicit contents read permission to the PR description lint workflow. - Set checkout persist-credentials to false for the lint job. #### Alternatives - Leave defaults unchanged, but explicit permissions make the token scope easier to review. #### Test Plan - [ ] `make -C elixir all` - [x] Parsed `.github/workflows/pr-description-lint.yml` with PyYAML.
#### Context Codex app-server sessions can request operator input or MCP elicitation. These should pause visibly instead of retrying until exhausted. #### TL;DR *Show input-blocked Symphony sessions in state, API, and dashboard.* #### Summary - Treat Codex input-required and MCP elicitation events as blocked sessions. - Keep blocked issues claimed until Linear state/routing changes. - Add blocked counts and per-issue blocked details to presenter payloads. - Render blocked sessions in the dashboard. - Add regression coverage for app-server and orchestrator blocked flows. #### Alternatives - Retrying was rejected because human-input blockers are not transient failures. - Moving Linear to Done was rejected because Done is post-merge terminal state. #### Test Plan - [ ] `make -C elixir all` - [x] `mise exec -- mix format` - [x] `mise exec -- mix test test/symphony_elixir/app_server_test.exs test/symphony_elixir/extensions_test.exs test/symphony_elixir/orchestrator_status_test.exs` --------- Co-authored-by: Codex <codex@openai.com>
#### Context Smoke-test ticket SD-4 asks for an isolated doc proving Symphony picked up and handled the issue. #### TL;DR *Adds the SD-4 Symphony smoke-test note.* #### Summary - Adds `docs/symphony-smoke-test-one.md`. - Keeps the change docs-only and limited to the smoke-test note. - Mentions Jira issue key `SD-4`. #### Alternatives - Leave no repo artifact; rejected because the ticket asks for a committed smoke-test doc. #### Test Plan - [x] `make -C elixir all` via GitHub Actions `make-all` - [x] `test -f docs/symphony-smoke-test-one.md && rg "SD-4|Symphony" docs/symphony-smoke-test-one.md && git diff --check` - [x] `mix pr_body.check --file <process-substitution>`
#### Context Adds the requested SD-6 smoke-test note so the Symphony board review workflow can validate a minimal docs-only change. #### TL;DR *Add a short board review smoke-test markdown note.* #### Summary - Added docs/symphony-smoke-board-review.md with a short heading and note. - Kept the change isolated to one new docs file. #### Alternatives - No code or app behavior changes were made because the ticket scope is docs-only. #### Test Plan - [x] `make -C elixir all` via GitHub Actions `make-all` rerun - [x] `mix pr_body.check --file <(gh pr view 79 --repo openai/symphony --json body -q .body)` - [x] `git status --short` shows only `?? docs/symphony-smoke-board-review.md`
#### Context Need Symphony to keep a first-class Codex thread loop for Linear issues, including human follow-up comments and terminal cleanup. #### TL;DR *Adds Codex thread links, thread archiving, and Linear comment resume support.* #### Summary - Add Codex app-server proxy support with thread owner metadata and archive calls. - Track thread IDs, comment cursors, and blocked human-input state in the orchestrator. - Fetch Linear comments and resume blocked or continued runs with human follow-up prompts. - Document the workflow/spec updates and cover stale empty workspace repair. #### Alternatives - Keep comments entirely inside Codex workpads, but Linear replies stay invisible to Symphony. - Leave thread handling as plain dashboard text, but `codex://` links make app handoff direct. #### Test Plan - [x] `make -C elixir all` - [x] `git diff --check` - [x] `rg -n "lin_api_|ZtX3ZP" .`
#### Context Revert PR #84 after it was merged so Symphony main returns to the previous workflow and implementation. #### TL;DR *Reverts the Codex thread link and Linear comment resume changes from PR #84.* #### Summary - Revert the squash merge commit from PR #84. - Remove the added Linear comment resume and Codex thread ownership/archive behavior. - Restore the previous docs, workflow config, app-server client, and tests. #### Alternatives - Patch forward selectively, but the request was to revert the merged change. #### Test Plan - [x] `git diff --check HEAD~1..HEAD` - [x] `rg -n "lin_api_|ZtX3ZP" .` - [x] `mix pr_body.check --file /tmp/symphony_revert_pr_body.md`
#### Context Brix oaipkg installs in Symphony-launched FSS runs need DNS/network access, but the workflow turn sandbox did not enable it. #### TL;DR *Allow Symphony workflow turns to use network/DNS for package installs.* #### Summary - Add `networkAccess: true` to the workflow turn sandbox policy. - Document the setting for package-manager and external-host workflows. #### Alternatives - Leave safer code defaults unchanged and scope the allowance to this workflow. #### Test Plan - [x] `/usr/bin/env mix run -e IO.inspect(...)` before and after config change - [x] `/usr/bin/env mix specs.check` - [x] `/usr/bin/env mix test test/symphony_elixir/workspace_and_config_test.exs` - [x] `/usr/bin/env make all MIX="/usr/bin/env mix"` Co-authored-by: Codex <codex@openai.com>
#### Context Projects need an explicit opt-in signal so active issues are not dispatched only because they belong to a polled project. #### TL;DR *Allow workflows to require Linear labels before an issue is dispatched or continued.* #### Summary - Add normalized `tracker.required_labels` configuration with all-label matching - Apply the label gate to dispatch, retries, reconciliation, and continuation turns - Document the configuration and cover opt-in and label-removal behavior #### Alternatives - Prompt-only filtering happens after an issue is claimed and cannot stop active work when a label is removed. - Linear query filtering would hide removed labels from reconciliation, preventing clean agent shutdown. #### Test Plan - [x] `make -C elixir all` - [x] `mix test test/symphony_elixir/workspace_and_config_test.exs`
#### Context Dashboard rows show tracker issue identifiers as plain text, so operators must navigate to active issues manually. #### TL;DR *Link dashboard issue identifiers to their tracker-provided URLs.* #### Summary - Preserve tracker issue URLs across running, blocked, and retry snapshots - Expose issue URLs in the observability state API - Link identifiers only when the tracker URL uses `http` or `https` - Add a content digest to the dashboard stylesheet URL so long-lived browser caching does not hide updated link styling #### Alternatives - Construct tracker URLs from identifiers. This would couple the dashboard to one tracker and URL format. #### Test Plan - [x] `make -C elixir all` - [x] Browser preview with synthetic `tracker.example` issue URLs - [x] Browser computed style confirms a `1px` underline - [x] Invalid URL scheme remains plain text
#### Context Symphony Observability currently uses the browser's generic fallback icon, which makes its control-plane tabs hard to identify. #### TL;DR *Add a custom, cache-busted favicon to the Symphony Observability dashboard.* #### Summary - Add a generated 128x128 transparent PNG mark for Symphony. - Serve the favicon through the existing embedded static-asset controller. - Add a content digest to the favicon URL to avoid stale browser caches. - Verify the favicon markup, route response, content type, and binary body. #### Alternatives - Keep the generic browser icon. This leaves Symphony tabs difficult to distinguish. - Embed a data URI in the layout. A normal asset route is easier to cache, test, and replace. #### Test Plan - [x] `make -C elixir all` - [x] `mix test test/symphony_elixir/extensions_test.exs` - [x] Browser preview at `http://127.0.0.1:4022/`
#### Context Live E2E could fail on cold Codex startup, remote `~/` workspace expansion, or Docker nested sandboxing. #### TL;DR *Make local and SSH live smoke tests reliable with test-only Codex isolation.* #### Summary - Fix remote `~/` workspace expansion so SSH workers use the intended home path. - Run local live tests with an auth-only temporary `CODEX_HOME` and a 60s startup timeout. - Use full access only inside disposable Docker SSH workers and finalize projects on failures. #### Alternatives - Did not change production Codex timeout defaults; the 60s budget is test-only. - Did not make Docker privileged; the container remains the isolation boundary. #### Test Plan - [x] `make -C elixir all` - [x] `cd elixir && CODEX_HOME=<temporary auth-only home> make e2e`
#### Context A YAML-valid, typed-invalid reload replaced cached config and prompt, then made `Config.settings!` raise. #### TL;DR *Keep the last good typed workflow when a reload cannot be parsed.* #### Summary - Cache parsed settings with each workflow store state. - Reject typed-invalid reloads before config and prompt become current. - Keep preflight errors visible while runtime getters use last known good values. #### Alternatives - Did not fold semantic tracker preflight into store admission; that is a separate finding. - Did not add orchestrator rescue logic; invalid typed state no longer reaches `settings!`. #### Test Plan - [x] `mix test test/symphony_elixir/extensions_test.exs:104` - [x] `mix test --cover --seed 659305` - [x] `make -C elixir all`
#### Context Orchestrator restarts reset in-memory claims, but sibling TaskSupervisor workers could survive and be redispatched concurrently. #### TL;DR *Supervise agent workers and the orchestrator as one restart unit.* #### Summary - Add an AgentRuntimeSupervisor with TaskSupervisor and Orchestrator under `:one_for_all`. - Route agent task starts and stops through the runtime-owned task supervisor. - Make public and test restart paths operate on the runtime subtree as a unit. - Add a real memory-tracker dispatch regression for hard-kill restart recovery. #### Alternatives - Startup cleanup fixed the narrow case but encoded ownership in callbacks instead of supervision. - Durable leases are broader than Symphony's in-memory restart contract. #### Test Plan - [x] `make -C elixir all` - [x] `mise exec -- mix test --repeat-until-failure 10 test/symphony_elixir/core_test.exs:228` - [x] `mise exec -- mix test --cover --seed 155984 --max-cases 8` - [x] `mise exec -- mix test test/symphony_elixir/core_test.exs test/symphony_elixir/orchestrator_status_test.exs`
#### Context Symphony could start scheduling with semantically invalid workflow settings, while blank required values also passed validation. #### TL;DR *Validate workflow settings before they become effective or start scheduling.* #### Summary - Make WorkflowStore cache only semantically valid workflow settings. - Return startup errors before Orchestrator schedules cleanup or polling. - Reject blank Linear settings and whitespace-only Codex commands. - Keep last-good settings across invalid reloads and runtime restarts. - Add cold-start, reload, restart, and test-bootstrap coverage. #### Alternatives - Validating only in Orchestrator init was rejected because bad reloads could break ordinary OTP restarts. - Keeping validation only per tick was rejected because startup still appeared healthy with invalid settings. #### Test Plan - [x] `cd elixir && mise exec -- make all` - [x] `cd elixir && mise exec -- mix test --seed 567691 --max-failures 1`
#### Context Agent guidance did not clearly state that simplicity is a project constraint or that adversarial review should challenge complexity. #### TL;DR *Make agent guidance prefer simple designs and adversarial verification.* #### Summary - Add one-owner/invariant and lifecycle review guidance. - Prefer narrow real OTP tests and stable observable proof. - Ask agents to challenge complexity and push back early. #### Alternatives - A detailed Symphony-specific checklist was rejected because it would overfit one incident instead of providing durable guidance. #### Test Plan - [x] `cd elixir && mise exec -- make all`
#### Context Using Symphony currently requires installing and configuring an Elixir runtime. Downloadable executables make first use much simpler. #### TL;DR *Add self-contained Burrito executables for macOS and Linux.* #### Summary - Add Burrito targets for macOS and Linux on arm64 and x86_64. - Route packaged releases through the existing Symphony CLI. - Build release assets, run native smoke tests, and publish checksums from GitHub Actions. - Document release binaries and source-run examples. #### Alternatives - Escript still requires Erlang/Elixir on the user's machine. - Native macOS Burrito builds hit a Zig linker failure, so CI cross-builds on Linux. - The workflow keeps the existing acknowledgement gate but does not pass the flag itself. #### Test Plan - [x] `make -C elixir all` - [x] `mise exec -- mix test --cover` - [x] `mise exec -- mix lint` - [x] `mise exec -- mix dialyzer --format short` - [x] `actionlint .github/workflows/burrito-release.yml` - [x] Run the packaged macOS arm64 CLI on this Mac.
#### Context The v0.0.1 tag run built and smoke-tested every artifact, but release creation failed because the job had no Git checkout. #### TL;DR *Check out Git before verifying release tags.* #### Summary - Add checkout to the Burrito release job before running `gh release create --verify-tag`. #### Alternatives - Removing `--verify-tag` would hide tag mistakes instead of fixing the missing Git context. #### Test Plan - [x] `yq eval .github/workflows/burrito-release.yml` - [x] `actionlint .github/workflows/burrito-release.yml` - [x] `git diff --check`
#### Context Symphony's scheduler was coupled to Linear types, reads, and mutations, making a second ticketing system require core orchestration changes. #### TL;DR *Introduce a generic tracker boundary while keeping Linear as the first adapter.* #### Summary - Normalize scheduler inputs through `Tracker.Issue` and two read operations. - Keep Linear GraphQL mutations in a session-bound provider-native tool. - Move provider config under `tracker.provider` with legacy Linear aliases. - Make SPEC generic and document Linear's concrete adapter profile. - Harden secret isolation, bound config snapshots, and provider validation. - Use collision-resistant workspace keys as a clean cut, without migration code. #### Alternatives - A lowest-common-denominator write API was rejected because it would leak provider semantics or discard useful capabilities. - A plugin system and full multi-provider rollout were deferred until a second adapter proves the smallest useful boundary. #### Test Plan - [x] `make -C elixir all` - [x] `mise exec -- mix test test/symphony_elixir/dynamic_tool_test.exs test/symphony_elixir/extensions_test.exs test/symphony_elixir/workspace_and_config_test.exs test/symphony_elixir/app_server_test.exs` - [x] No-context SPEC probes: TypeScript 6/6, Python 6/6, and Go passed. - [x] Live Linear smoke: local daemon processed FST-5 to Done, wrote one comment, and cleaned its workspace. --------- Co-authored-by: Codex <codex@openai.com>
#### Context Symphony's generic tracker seam needs a real non-Linear stress test without adding generic mutation APIs. #### TL;DR *Add GitHub Issues reads and a host-authenticated raw GitHub tool.* #### Summary - Add project-scoped GitHub issue reads, normalization, and dispatchability. - Add raw `github_api` for provider-native mutations with host-side auth. - Add contract tests, live E2E proof, and GitHub adapter documentation. #### Alternatives - Generic CRUD was rejected because it would flatten GitHub-specific capabilities. - GraphQL was rejected for v1 because REST covers the required reads and tool flow simply. #### Test Plan - [x] `make -C elixir all` - [x] `SYMPHONY_RUN_GITHUB_LIVE_E2E=1 mix test test/symphony_elixir/github_live_e2e_test.exs` - [x] `SYMPHONY_RUN_LIVE_E2E=1 SYMPHONY_LIVE_LINEAR_TEAM_KEY=FST mix test test/symphony_elixir/live_e2e_test.exs:123`
#### Context Symphony's generic tracker seam needs a Jira Cloud implementation without adding generic mutation APIs. #### TL;DR *Add Jira Cloud reads and a host-authenticated raw Jira REST tool.* #### Summary - Add project-scoped Jira reads, ADF normalization, and status dispatchability. - Add raw `jira_rest` for provider-native mutations with host-side auth. - Add contract tests, live E2E proof, and Jira adapter documentation. #### Alternatives - Generic CRUD was rejected because it would flatten Jira transitions and ADF details. - JQL-only tooling was rejected because a raw REST tool preserves broader Jira capabilities. #### Test Plan - [x] `make -C elixir all` - [x] `SYMPHONY_RUN_JIRA_LIVE_E2E=1 mix test test/symphony_elixir/jira_live_e2e_test.exs` - [x] `SYMPHONY_RUN_LIVE_E2E=1 SYMPHONY_LIVE_LINEAR_TEAM_KEY=FST mix test test/symphony_elixir/live_e2e_test.exs:123`
#### Context Symphony's generic tracker seam needs an Asana implementation without adding generic mutation APIs. #### TL;DR *Add Asana task reads and a host-authenticated raw Asana API tool.* #### Summary - Add project-scoped Asana task reads, section-state mapping, and dispatchability. - Add raw `asana_api` for provider-native mutations with host-side auth. - Add contract tests, live E2E proof, and Asana adapter documentation. #### Alternatives - Generic CRUD was rejected because it would flatten sections, stories, and task types. - Completed-only state mapping was rejected because section names are the workflow source. #### Test Plan - [x] `make -C elixir all` - [x] `SYMPHONY_RUN_ASANA_LIVE_E2E=1 mix test test/symphony_elixir/asana_live_e2e_test.exs` - [x] `SYMPHONY_RUN_LIVE_E2E=1 SYMPHONY_LIVE_LINEAR_TEAM_KEY=FST mix test test/symphony_elixir/live_e2e_test.exs:123`
#### Context Symphony's generic tracker seam needs a GitLab Issues implementation without adding generic mutation APIs. #### TL;DR *Add GitLab Issues reads and a host-authenticated raw GitLab API tool.* #### Summary - Add project-scoped GitLab issue reads, IID normalization, and dispatchability. - Add raw `gitlab_api` for provider-native mutations with host-side auth. - Add contract tests, live E2E proof, and GitLab adapter documentation. #### Alternatives - Generic CRUD was rejected because it would flatten GitLab-specific issue capabilities. - Header pagination machinery was rejected because simple page/per-page reads are sufficient. #### Test Plan - [x] `make -C elixir all` - [x] `SYMPHONY_RUN_GITLAB_LIVE_E2E=1 mix test test/symphony_elixir/gitlab_live_e2e_test.exs` - [x] `SYMPHONY_RUN_LIVE_E2E=1 SYMPHONY_LIVE_LINEAR_TEAM_KEY=FST mix test test/symphony_elixir/live_e2e_test.exs:123`
#### Context Jira inward Blocks links were normalized as dispatchable, so Symphony could start Todo work before its blocker reached a terminal state. #### TL;DR *Jira Todo issues now wait for inward Blocks dependencies.* #### Summary - Request issuelinks in Jira candidate polling and ID refresh reads. - Normalize inward Blocks links into blocked_by. - Ignore outward Blocks links and unrelated Jira link types. - Gate only Todo/To Do work until blockers reach configured terminal states. - Test direction, custom terminals, partial payloads, and ID refresh gating. #### Alternatives - Generic scheduler blocking logic: rejected because blocker semantics remain provider-specific and dispatchable already owns eligibility. - Metadata-only links: rejected because they would preserve blockers without preventing premature dispatch. #### Test Plan - [x] HEX_HOME=/private/tmp/symphony-hex-jira-blockers make -C elixir all - [x] HEX_HOME=/private/tmp/symphony-hex-jira-blockers mix test test/symphony_elixir/jira_adapter_test.exs - [x] Live Jira Orchestrator probe created linked issues, proved no workspace while blocked, transitioned the blocker, proved workspace creation, and deleted the disposable issues. - [x] SYMPHONY_RUN_JIRA_LIVE_E2E=1 mix test test/symphony_elixir/jira_live_e2e_test.exs Co-authored-by: Codex <codex@openai.com>
#### Context Terminal reconciliation could race a live worker and could recompute cleanup from reloaded config, deleting the wrong workspace. Recorded-path cleanup also still needs the local symlink-escape guard before hooks run. #### TL;DR *Stop workers first and clean the validated workspace recorded for that run.* #### Summary - Stop terminal workers before invoking cleanup hooks or removal. - Prefer the recorded workspace path for running, retrying, and blocked issues. - Validate recorded local paths against their recorded parent before hooks or removal. - Add deterministic regressions for cleanup order, config-reload target selection, and recorded symlink escapes. #### Alternatives - A new cleanup coordinator was unnecessary; existing metadata and operations are enough. #### Test Plan - [x] `HEX_HOME=/private/tmp/symphony-hex mise exec -- make -C elixir all` - [x] `mise exec -- mix test test/symphony_elixir/core_test.exs:541` - [x] `mise exec -- mix test test/symphony_elixir/core_test.exs:618` - [x] `mise exec -- mix test test/symphony_elixir/workspace_and_config_test.exs:176`
#### Context A retry performs a fresh by-id lookup, then dispatch revalidates before starting work. If that second read missed or went stale, the popped retry could stay claimed forever; bypassing it instead could dispatch stale work. #### TL;DR *Keep dispatch-time freshness and let retries release or reschedule from its outcome.* #### Summary - Preserve dispatch-time issue revalidation for retried work. - Release the retry claim when the second refresh is missing or stale. - Reschedule rather than drop the claim when dispatch-time refresh errors. - Add a regression proving a missing second read cannot dispatch stale work or strand a claim. #### Alternatives - Reusing the first retry lookup was smaller but reopened a stale-dispatch window. #### Test Plan - [x] `HEX_HOME=/private/tmp/symphony-hex mise exec -- make -C elixir all` - [x] `mise exec -- mix test test/symphony_elixir/core_test.exs:875` - [x] `mise exec -- mix test test/symphony_elixir/core_test.exs`
#### Context Failed new-workspace bootstrap was skipped on retry, and relative local roots followed launcher cwd instead of the selected workflow file. #### TL;DR *Retry failed bootstrap cleanly and anchor local roots to WORKFLOW.md.* #### Summary - Remove newly created partial workspaces when `after_create` fails. - Resolve local relative roots from the selected workflow directory. - Keep remote roots raw and use the local root in app-server validation. - Add regressions for bootstrap retry and explicit workflow paths. #### Alternatives - Marker files and global cwd changes were unnecessary; one local root helper keeps the fix small. #### Test Plan - [x] `make -C elixir all` - [x] `mise exec -- mix test test/symphony_elixir/workspace_and_config_test.exs:60` - [x] `mise exec -- mix test test/symphony_elixir/workspace_and_config_test.exs:244`
#### Context Docs called turn timeout a total cap, while runtime uses silence. Generic tool-input prompts also received fabricated answers, and approval-looking option labels alone are not enough to identify MCP approval prompts. #### TL;DR *Document idle timeouts and block generic tool input.* #### Summary - Document `turn_timeout_ms` as a reset-on-update silence interval. - Add coverage for active stream updates and silent turns. - Keep auto-approval only for recognized MCP approval question IDs. - Block freeform and generic option-based tool input, including Allow/Deny choices. #### Alternatives - A total-runtime deadline was rejected; healthy long turns should stay alive while updates continue. - Matching approval-looking labels alone was rejected because generic prompts can use the same words. #### Test Plan - [x] `HEX_HOME=/private/tmp/symphony-hex mise exec -- make -C elixir all` - [x] `mise exec -- mix test test/symphony_elixir/app_server_test.exs:619 test/symphony_elixir/app_server_test.exs:788` - [x] `mise exec -- mix test test/symphony_elixir/app_server_test.exs`
#### Context Jira blockers only gated literal Todo states, so Open or Backlog issues could dispatch through active blockers. #### TL;DR *Gate Jira new-category issues on active blockers.* #### Summary - Read Jira `statusCategory.key` while normalizing issues. - Gate `new` category issues on inward `Blocks` links. - Preserve the Todo fallback and keep in-progress work dispatchable. - Document the adapter rule and add an Open-state regression. #### Alternatives - Shared scheduler policy was unnecessary; Jira already exposes the native category signal. #### Test Plan - [x] `make -C elixir all` - [x] `mise exec -- mix test test/symphony_elixir/jira_adapter_test.exs:166`
#### Context The v0.0.2 release tag was rejected because the committed Mix project version remained 0.0.1. #### TL;DR *Bump the committed Elixir project version to 0.0.2.* #### Summary - Set `SymphonyElixir.MixProject` version to `0.0.2`. - Align the source version with the existing `v0.0.2` release tag. #### Alternatives - Retagging as `v0.0.1` would not create the intended next release. - Removing the workflow check would allow mismatched release artifacts. #### Test Plan - [x] `make -C elixir all` - [x] Confirm the staged diff changes only `elixir/mix.exs`.
#### Context Symphony releases need a short, reusable procedure that keeps tags aligned with the committed project version. #### TL;DR *Add a concise repo-local skill for cutting Symphony releases.* #### Summary - Add `.codex/skills/release/SKILL.md`. - Cover version bumps, PR landing, annotated tags, and release verification. #### Alternatives - Relying on memory risks tagging an unmerged or version-mismatched commit. - A longer runbook would duplicate the existing commit, push, and land skills. #### Test Plan - [x] `make -C elixir all` - [x] `python3 /Users/frantic/.codex/skills/.system/skill-creator/scripts/quick_validate.py /Users/frantic/.codex/worktrees/symphony-add-release-skill/.codex/skills/release`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )