Skip to content

refactor(workspaces): standardize launcher injection (AI-config + MCP/persona/skills + commit)#245

Merged
luokerenx4 merged 3 commits into
masterfrom
harness-issue
Jun 1, 2026
Merged

refactor(workspaces): standardize launcher injection (AI-config + MCP/persona/skills + commit)#245
luokerenx4 merged 3 commits into
masterfrom
harness-issue

Conversation

@luokerenx4
Copy link
Copy Markdown
Contributor

Summary

Per-template bootstrap.sh scripts each hand-rolled their own context injection and initial commit, and per-CLI AI-config write logic lived in the webui routes. This standardizes both behind the launcher, so what gets injected is uniform and centrally owned — and hardens a credential leak along the way. Three independent, behavior-preserving commits:

  • 53a0185 security: setup_git_excludes only guarded .claude/settings.local.json + .codex/auth.json, but per-workspace Codex config writes the API key to .codex/env.json and a base_url to .codex/config.toml — neither excluded. auto-quant workspaces were clones of the public Auto-Quant repo on a pushable branch, so a custom Codex provider + push would leak the key. Added both to the default exclude block.
  • 7420909 AI-config unification: moved the four CLI-specific config writers out of webui/routes/workspaces.ts into CliAdapter.writeAiConfig/readAiConfig (claude/codex), behind a shared WorkspaceAiCred. Routes now dispatch via svc.adapters; response shape unchanged. This is the seam a future config-push builds on.
  • 286ab83 launcher-owned injection + uniform commit: context-injector.ts writes the standard .mcp.json (placeholder kept for spawn-time URL resolution), composes Alice persona + the template's CLAUDE.md into CLAUDE.md/AGENTS.md, and copies bundled skills from default/skills/ into both discovery paths — gated by new template.json flags (injectMcp/injectPersona/bundledSkills). The launcher now makes the initial commit for every template (no per-template exemption). "Harness rule": every workspace is a fresh-git repo with one clean initial commit, no inherited history, no pushable remote — auto-quant conforms by scrubbing its clone (rm -rf .git && git init), which also removes the Phase-0 leak's remaining vector.

bootstrap.sh shrinks to harness-unique materialization; the duplicated template files/mcp.json and the now-dead _common.sh helpers are removed.

Test plan

  • tsc --noEmit clean
  • Full suite 1718 passed
  • Golden specs assert byte-identical AI-config output (x-api-key / bearer / model-only / reset / chat / responses) and injection output (MCP / persona composition / skills)
  • End-to-end specs (chat / auto-quant / finance-research): real bootstrap → inject → commit yields one clean launcher@local commit, clean tree; auto-quant's clone history + remote are scrubbed
  • Live: a real claude/codex session in a created workspace connects /mcp and discovers scan-value-chain (standard CLI discovery; files verified in place)

Boundary touch

Touches AI-provider credential handling (per-workspace agent config moved into adapters) and a security hardening (Codex key git-excludes). No broker/trading code, no migrations.

🤖 Generated with Claude Code

Ame and others added 3 commits June 1, 2026 17:27
setup_git_excludes only guarded .claude/settings.local.json and
.codex/auth.json, but OpenAlice's per-workspace Codex config
(writeCodexConfig) writes the API key to .codex/env.json
(OPENALICE_WORKSPACE_KEY) and a possibly-private base_url to
.codex/config.toml — neither was excluded.

auto-quant workspaces are clones of the public TraderAlice/Auto-Quant on
a pushable autoresearch/<tag> branch; the bootstrap comment explicitly
says the excludes exist to keep secrets "out of any push to upstream
Auto-Quant" — but it missed the file that actually holds the key. A user
who set a custom Codex provider on an auto-quant workspace and pushed the
branch would have leaked their key.

Add both files to the default block in _common.sh:setup_git_excludes —
one place, covers chat/finance/auto-quant and any future template.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per-workspace AI-provider config (key/endpoint/model) was written by
four CLI-specific functions living in the webui route file
(readClaudeConfig/writeClaudeConfig/readCodexConfig/writeCodexConfig),
dispatched ad-hoc from the route handlers. That put per-CLI file-format
logic in the wrong layer and duplicated the dispatch.

Standardize the contract, keep the per-CLI format behind it:

- New WorkspaceAiCred (superset shape: authMode is Claude-only, wireApi
  Codex-only) + optional writeAiConfig/readAiConfig on the CliAdapter
  interface (cli-adapter.ts).
- Move the four function bodies verbatim into claudeAdapter / codexAdapter
  (+ the tomlString helper and path/env-name constants). shell has none.
- Thin GET/PUT /:id/agent-config to dispatch via svc.adapters.get(agent)
  — response shape unchanged.

Behavior-preserving: a golden spec (ai-config.spec.ts) asserts the exact
bytes the pre-move writers produced for both CLIs across the full input
matrix (x-api-key / bearer / model-only / reset / chat / responses) plus
read round-trips. tsc --noEmit clean; full suite 1713 passed.

This is the seam a future config-push (apply-profile-to-workspaces) will
build on.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ial commit

Each template's bootstrap.sh hand-rolled its own context injection (MCP
config, persona, skills) and initial commit. Standardize: the launcher
now injects and commits uniformly, gated by template.json manifest flags;
bootstrap.sh shrinks to harness-unique materialization.

- Manifest flags injectMcp / injectPersona / bundledSkills (defaults
  preserve each template's behavior): chat = all three, finance = mcp +
  persona, auto-quant = none.
- context-injector.ts: launcher writes the standard .mcp.json (URL
  placeholder kept for spawn-time resolution), composes Alice persona +
  the template's CLAUDE.md into CLAUDE.md/AGENTS.md, and copies bundled
  skills from default/skills/ into both discovery paths. Byte-identical to
  the old _common.sh bash (golden spec asserts it).
- workspace-creator.ts: after bootstrap → inject → commit. The launcher
  owns the initial commit for EVERY template (no launcherCommits
  exemption); failure cleans up the dir and returns injection_failed.
- "Harness rule": every workspace is a fresh-git repo with one clean
  initial commit, no inherited history, no pushable remote. auto-quant
  conforms by scrubbing its clone (rm -rf .git && git init), which also
  removes the public-remote key-leak vector Phase 0 hardened.
- Moved the scan-value-chain skill (chat-bundled stopgap) → default/skills/.
- Deleted the duplicated template files/mcp.json; removed the now-dead
  _common.sh helpers (write_mcp_config / compose_persona_claude_md /
  commit_initial).

Verified: tsc --noEmit clean; injector golden (MCP bytes + persona
composition + skills into both paths); e2e (real bootstrap → inject →
commit = one clean launcher commit, clean tree); full suite 1718 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openalice-demo Building Building Preview Jun 1, 2026 10:37am

Request Review

@luokerenx4 luokerenx4 merged commit bd1dd83 into master Jun 1, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant