Both chore/eco-watch-2026-04-17-b and chore/eco-watch-2026-04-17-c added
entries at the end of ecosystem-watch.md. Kept both entries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
vLLM (and Nous Hermes portal) only accept a single system message.
When the platform builds a messages array from multiple sources
(base system prompt + workspace config + per-session override), the
consecutive system entries at the front cause vLLM to reject or
silently drop all but the first.
Adds mergeSystemMessages() — a stateless pre-flight transform in the
handlers package that collapses the uninterrupted leading run of
{"role":"system"} entries into one, joining their content with "\n\n".
Non-system messages between system messages are not touched; a single
system message is returned as-is (no allocation).
10 unit tests cover: stacked merge, single-unchanged, no-system passthrough,
three-message collapse, interleaved user (trailing system not merged),
only-system-messages, empty slice, nil slice, non-string content, and
assistant-leading passthrough.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
vLLM (and Nous Hermes portal) only accept a single system message.
When the platform builds a messages array from multiple sources
(base system prompt + workspace config + per-session override), the
consecutive system entries at the front cause vLLM to reject or
silently drop all but the first.
Adds mergeSystemMessages() — a stateless pre-flight transform in the
handlers package that collapses the uninterrupted leading run of
{"role":"system"} entries into one, joining their content with "\n\n".
Non-system messages between system messages are not touched; a single
system message is returned as-is (no allocation).
10 unit tests cover: stacked merge, single-unchanged, no-system passthrough,
three-message collapse, interleaved user (trailing system not merged),
only-system-messages, empty slice, nil slice, non-string content, and
assistant-leading passthrough.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
24.1k-star Apache-2.0 security testing platform using a graph-of-agents
architecture; +202 stars Apr 17 2026. Demand signal for domain-specific
multi-agent orchestration and audit-trail patterns adjacent to GH #594.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
24.1k-star Apache-2.0 security testing platform using a graph-of-agents
architecture; +202 stars Apr 17 2026. Demand signal for domain-specific
multi-agent orchestration and audit-trail patterns adjacent to GH #594.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Standalone adapter images (langgraph, claude-code, etc.) use
ENTRYPOINT ["molecule-runtime"] which bypasses entrypoint.sh. PR #640's
entrypoint.sh fix therefore never runs in adapter images. The correct fix
is to bake git config --system into the image at build time.
This script:
1. Rebuilds workspace-template:base from the monorepo Dockerfile (which
has the fixed entrypoint.sh and molecule-git-token-helper.sh)
2. For each of the 6 runtime adapters: clones the standalone repo, patches
its Dockerfile to COPY the credential helper and run git config --system,
then builds the final image tagged as workspace-template:<runtime>
Usage (run on the host machine, not inside a workspace container):
bash workspace-template/rebuild-runtime-images.sh # all 6
bash workspace-template/rebuild-runtime-images.sh claude-code # one
See issue #658 for the architectural explanation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Standalone adapter images (langgraph, claude-code, etc.) use
ENTRYPOINT ["molecule-runtime"] which bypasses entrypoint.sh. PR #640's
entrypoint.sh fix therefore never runs in adapter images. The correct fix
is to bake git config --system into the image at build time.
This script:
1. Rebuilds workspace-template:base from the monorepo Dockerfile (which
has the fixed entrypoint.sh and molecule-git-token-helper.sh)
2. For each of the 6 runtime adapters: clones the standalone repo, patches
its Dockerfile to COPY the credential helper and run git config --system,
then builds the final image tagged as workspace-template:<runtime>
Usage (run on the host machine, not inside a workspace container):
bash workspace-template/rebuild-runtime-images.sh # all 6
bash workspace-template/rebuild-runtime-images.sh claude-code # one
See issue #658 for the architectural explanation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both PRs restructured the same chat.completions.create() call to use a
create_kwargs dict. Resolved by keeping both __init__ params and both
conditionals in the create_kwargs block.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both PRs restructured the same chat.completions.create() call to use a
create_kwargs dict. Resolved by keeping both __init__ params and both
conditionals in the create_kwargs block.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a fifth option to the effort <select> in the Claude Settings section:
<option value="max">max — absolute ceiling</option>
The dropdown now offers: low / medium / high / xhigh / max.
effort is typed as string? so no interface update required.
Test updated: source-assertion count "four" → "five", new toYaml
serialization test for effort: max.
641/641 tests pass. Build clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a fifth option to the effort <select> in the Claude Settings section:
<option value="max">max — absolute ceiling</option>
The dropdown now offers: low / medium / high / xhigh / max.
effort is typed as string? so no interface update required.
Test updated: source-assertion count "four" → "five", new toYaml
serialization test for effort: max.
641/641 tests pass. Build clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New LOW entry: virattt/ai-hedge-fund (55.7k⭐, +763 today) — 19-agent
financial-analysis reference implementation. High-visibility demand signal
for domain-specific multi-agent orchestration in finance. Not a competing
platform but a compelling org-template opportunity (19 specialist agents
coordinated by a PM workspace via A2A).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New LOW entry: virattt/ai-hedge-fund (55.7k⭐, +763 today) — 19-agent
financial-analysis reference implementation. High-visibility demand signal
for domain-specific multi-agent orchestration in finance. Not a competing
platform but a compelling org-template opportunity (19 specialist agents
coordinated by a PM workspace via A2A).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrations 025 + 026 declared workspace_id/org_id as TEXT but
workspaces.id is UUID — Postgres rejects the FK constraint, crashing
every E2E run on main since these migrations were merged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Migrations 025 + 026 declared workspace_id/org_id as TEXT but
workspaces.id is UUID — Postgres rejects the FK constraint, crashing
every E2E run on main since these migrations were merged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Four findings from the security audit on PR #641:
FIX 1 (MEDIUM): import_url scheme validation
- Reject non-HTTPS import URLs with 400 before forwarding to CF API.
Prevents SSRF via http://, git://, ssh://, file:// etc.
FIX 2 (MEDIUM): CF 5xx error leakage
- Add cfErrMessage() helper: returns "upstream service error" for CF 5xx
responses and non-CF errors, passes through 4xx messages.
- Applied at all four CF-error response sites (Create, Get, Fork, Token).
FIX 3 (LOW): repo name validation
- Add package-level repoNameRE = ^[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}$
- Validate in Create and Fork handlers when caller supplies an explicit name.
Auto-generated names ("molecule-ws-<id>") are always safe and skip validation.
FIX 4 (LOW): response body size limit in CF client
- Wrap resp.Body with io.LimitReader(1 MB) before json.NewDecoder in do().
Prevents memory exhaustion from a runaway/malicious CF response.
Tests: 16 new tests covering all four fixes (cfErrMessage 4xx/5xx/non-API,
import_url non-HTTPS cases, invalid repo names in Create and Fork).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four findings from the security audit on PR #641:
FIX 1 (MEDIUM): import_url scheme validation
- Reject non-HTTPS import URLs with 400 before forwarding to CF API.
Prevents SSRF via http://, git://, ssh://, file:// etc.
FIX 2 (MEDIUM): CF 5xx error leakage
- Add cfErrMessage() helper: returns "upstream service error" for CF 5xx
responses and non-CF errors, passes through 4xx messages.
- Applied at all four CF-error response sites (Create, Get, Fork, Token).
FIX 3 (LOW): repo name validation
- Add package-level repoNameRE = ^[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}$
- Validate in Create and Fork handlers when caller supplies an explicit name.
Auto-generated names ("molecule-ws-<id>") are always safe and skip validation.
FIX 4 (LOW): response body size limit in CF client
- Wrap resp.Body with io.LimitReader(1 MB) before json.NewDecoder in do().
Prevents memory exhaustion from a runaway/malicious CF response.
Tests: 16 new tests covering all four fixes (cfErrMessage 4xx/5xx/non-API,
import_url non-HTTPS cases, invalid repo names in Create and Fork).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a minimal but complete integration with the Cloudflare Artifacts API
(private beta Apr 2026, public beta May 2026) — "Git for agents" versioned
workspace-snapshot storage.
## What's included
**`platform/internal/artifacts/client.go`** — typed Go HTTP client for the
CF Artifacts REST API:
- CreateRepo, GetRepo, ForkRepo, ImportRepo, DeleteRepo
- CreateToken, RevokeToken
- CF v4 response-envelope decoding; *APIError with StatusCode + Message
**`platform/internal/handlers/artifacts.go`** — four workspace-scoped
Gin handlers (all behind WorkspaceAuth middleware):
- POST /workspaces/:id/artifacts — attach or import a CF Artifacts repo
- GET /workspaces/:id/artifacts — get linked repo info (DB + live CF)
- POST /workspaces/:id/artifacts/fork — fork the workspace's repo
- POST /workspaces/:id/artifacts/token — mint a short-lived git credential
**`platform/migrations/028_workspace_artifacts.up.sql`** — `workspace_artifacts`
table: one-to-one link between a workspace and its CF Artifacts repo.
Credentials are never stored; only the credential-stripped remote URL.
**`platform/internal/router/router.go`** — wire the four routes into the
existing wsAuth group.
## Configuration
Two env vars gate the feature (returns 503 when either is absent):
- CF_ARTIFACTS_API_TOKEN — Cloudflare API token with Artifacts write perms
- CF_ARTIFACTS_NAMESPACE — Cloudflare Artifacts namespace name
## Tests
- 10 client-level tests (httptest.Server + CF v4 envelope mocks)
- 14 handler-level tests (sqlmock DB + mock CF server)
- Helper unit tests for stripCredentials, cfErrToHTTP
All 21 packages pass (go test ./...).
Closes#595
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a minimal but complete integration with the Cloudflare Artifacts API
(private beta Apr 2026, public beta May 2026) — "Git for agents" versioned
workspace-snapshot storage.
## What's included
**`platform/internal/artifacts/client.go`** — typed Go HTTP client for the
CF Artifacts REST API:
- CreateRepo, GetRepo, ForkRepo, ImportRepo, DeleteRepo
- CreateToken, RevokeToken
- CF v4 response-envelope decoding; *APIError with StatusCode + Message
**`platform/internal/handlers/artifacts.go`** — four workspace-scoped
Gin handlers (all behind WorkspaceAuth middleware):
- POST /workspaces/:id/artifacts — attach or import a CF Artifacts repo
- GET /workspaces/:id/artifacts — get linked repo info (DB + live CF)
- POST /workspaces/:id/artifacts/fork — fork the workspace's repo
- POST /workspaces/:id/artifacts/token — mint a short-lived git credential
**`platform/migrations/028_workspace_artifacts.up.sql`** — `workspace_artifacts`
table: one-to-one link between a workspace and its CF Artifacts repo.
Credentials are never stored; only the credential-stripped remote URL.
**`platform/internal/router/router.go`** — wire the four routes into the
existing wsAuth group.
## Configuration
Two env vars gate the feature (returns 503 when either is absent):
- CF_ARTIFACTS_API_TOKEN — Cloudflare API token with Artifacts write perms
- CF_ARTIFACTS_NAMESPACE — Cloudflare Artifacts namespace name
## Tests
- 10 client-level tests (httptest.Server + CF v4 envelope mocks)
- 14 handler-level tests (sqlmock DB + mock CF server)
- Helper unit tests for stripCredentials, cfErrToHTTP
All 21 packages pass (go test ./...).
Closes#595
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both conflicts were comment-only — identical logic on both sides:
- registry.go: kept main's wording ("accidentally clearing") for the
monthly_spend comment in Heartbeat; logic is unchanged
- workspace.go: kept HEAD's comment (describes PR #634's clamping
behaviour: [0, maxMonthlySpend]); logic is unchanged
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both conflicts were comment-only — identical logic on both sides:
- registry.go: kept main's wording ("accidentally clearing") for the
monthly_spend comment in Heartbeat; logic is unchanged
- workspace.go: kept HEAD's comment (describes PR #634's clamping
behaviour: [0, maxMonthlySpend]); logic is unchanged
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two bugs prevented the git credential helper (merged in #567) from ever
running at workspace boot:
1. Dockerfile never COPY'd scripts/molecule-git-token-helper.sh into the
image — only gh-wrapper.sh was copied from scripts/. Result: the helper
binary did not exist in any built container image.
2. entrypoint.sh looked for the helper at /workspace-template/scripts/...
but /workspace-template/ is not a path that exists inside the container
(WORKDIR is /app, no /workspace-template mount). The `if [ -f ... ]`
guard silently fell through to the WARNING branch on every boot since
#567 merged — the helper was never registered.
Fix:
- Add `COPY scripts/molecule-git-token-helper.sh ./scripts/` to Dockerfile
so the script lands at /app/scripts/ in the image (matching WORKDIR /app)
- Update HELPER_SCRIPT path in entrypoint.sh from
/workspace-template/scripts/... to /app/scripts/...
After this fix, every workspace container registers the helper at boot via:
git config --global credential.https://github.com.helper \
"!/app/scripts/molecule-git-token-helper.sh"
Closes#613.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two bugs prevented the git credential helper (merged in #567) from ever
running at workspace boot:
1. Dockerfile never COPY'd scripts/molecule-git-token-helper.sh into the
image — only gh-wrapper.sh was copied from scripts/. Result: the helper
binary did not exist in any built container image.
2. entrypoint.sh looked for the helper at /workspace-template/scripts/...
but /workspace-template/ is not a path that exists inside the container
(WORKDIR is /app, no /workspace-template mount). The `if [ -f ... ]`
guard silently fell through to the WARNING branch on every boot since
#567 merged — the helper was never registered.
Fix:
- Add `COPY scripts/molecule-git-token-helper.sh ./scripts/` to Dockerfile
so the script lands at /app/scripts/ in the image (matching WORKDIR /app)
- Update HELPER_SCRIPT path in entrypoint.sh from
/workspace-template/scripts/... to /app/scripts/...
After this fix, every workspace container registers the helper at boot via:
git config --global credential.https://github.com.helper \
"!/app/scripts/molecule-git-token-helper.sh"
Closes#613.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Merge gate passed (all 7 gates). Adds budget_limit + monthly_spend columns via 027_workspace_budget (ADD COLUMN IF NOT EXISTS — idempotent). A2A budget enforcement is fail-open on DB errors. WorkspaceAuth on all budget routes. Schema migration — CEO explicit authorization in chat. Merging before #634 which writes to monthly_spend.
Merge gate passed (all 7 gates). Adds budget_limit + monthly_spend columns via 027_workspace_budget (ADD COLUMN IF NOT EXISTS — idempotent). A2A budget enforcement is fail-open on DB errors. WorkspaceAuth on all budget routes. Schema migration — CEO explicit authorization in chat. Merging before #634 which writes to monthly_spend.