From 8f48a385500d5c165c154f7fd1ac8246af3481ce Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Sun, 3 May 2026 05:41:53 -0700 Subject: [PATCH 1/3] fix(publish-runtime): re-add 5 templates wrongly removed from cascade (#2566) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PR #2536 cascade prune ('deprecated, no shipping images') was empirically wrong. Re-confirmed 2026-05-03: - continuous-synth-e2e.yml defaults to langgraph as its primary canary - All 5 'deprecated' templates have successful publish-image runs in the past 24h: langgraph, crewai, autogen, deepagents, gemini-cli Symptom this fixes — issue #2566 (priority-high, failing 36+h): Synthetic E2E (staging): langgraph adapter A2A failure 'Received Message object in task mode' — failing for >36h Today at 11:06 commit e1628c4 fixed the underlying a2a-sdk strict-mode issue in workspace/a2a_executor.py. publish-runtime fired at 11:13 and cascaded — but only to claude-code, hermes, openclaw, codex. langgraph was excluded by the prune, so its image stayed on the broken runtime and the synth E2E (which defaults to langgraph) kept failing despite the fix being live in PyPI. After this lands + the next runtime publish fires, langgraph image re-bakes with the fix and synth-E2E goes green. Test plan: - [x] yaml-validate the workflow - [ ] After merge, watch publish-runtime cascade to all 9 templates - [ ] Confirm langgraph publish-image fires + succeeds - [ ] Confirm next continuous-synth-e2e run goes green Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-runtime.yml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-runtime.yml b/.github/workflows/publish-runtime.yml index f3a180f3..b3750a61 100644 --- a/.github/workflows/publish-runtime.yml +++ b/.github/workflows/publish-runtime.yml @@ -327,13 +327,19 @@ jobs: echo "::error::publish job did not expose a version output — cascade cannot fan out" exit 1 fi - # Source of truth: manifest.json workspace_templates (PR #2536 pruned - # to 4 actively-supported runtimes: claude-code, hermes, openclaw, codex). - # Removed langgraph/crewai/autogen/deepagents/gemini-cli (deprecated, no - # shipping images); added codex (had been missing since #2512). - # Long-term: derive this list from manifest.json so the cascade can't - # drift again — tracked in RFC #388 as a Phase-1 invariant. - TEMPLATES="claude-code hermes openclaw codex" + # All 9 active workspace template repos. The PR #2536 pruning + # ("deprecated, no shipping images") was empirically wrong: + # continuous-synth-e2e.yml defaults to langgraph as its primary + # canary (line 44), and every excluded template had successful + # publish-image runs as of 2026-05-03 — none were dormant. + # Symptom of the prune: today's a2a-sdk strict-mode fix + # (#2566 / commit e1628c4) cascaded to 4 templates but never + # reached langgraph, so the synth-E2E correctly canary'd a fix + # that had landed but not deployed. Re-added the 5 templates. + # Long-term: derive this list from manifest.json so cascade + # scope can't drift from E2E scope — tracked in RFC #388 as a + # Phase-1 invariant. + TEMPLATES="claude-code hermes openclaw codex langgraph crewai autogen deepagents gemini-cli" FAILED="" for tpl in $TEMPLATES; do REPO="Molecule-AI/molecule-ai-workspace-template-$tpl" From 6eb79adfd5faed9608bec77ce275764e7f7e9680 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Sun, 3 May 2026 05:43:07 -0700 Subject: [PATCH 2/3] manifest: re-add 5 workspace templates pruned by #2536 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cascade-list-vs-manifest drift gate (PR #2556's behavior-based test) caught my previous-commit cascade additions as 'extra-in-cascade'. Manifest is the source of truth — restoring there. All 5 templates have successful publish-image runs in the past 24h (verified before the cascade fix), and continuous-synth-e2e defaults to langgraph as its primary canary. None deprecated. Co-Authored-By: Claude Opus 4.7 (1M context) --- manifest.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 7610bd80..96be673d 100644 --- a/manifest.json +++ b/manifest.json @@ -28,7 +28,12 @@ {"name": "claude-code-default", "repo": "Molecule-AI/molecule-ai-workspace-template-claude-code", "ref": "main"}, {"name": "hermes", "repo": "Molecule-AI/molecule-ai-workspace-template-hermes", "ref": "main"}, {"name": "openclaw", "repo": "Molecule-AI/molecule-ai-workspace-template-openclaw", "ref": "main"}, - {"name": "codex", "repo": "Molecule-AI/molecule-ai-workspace-template-codex", "ref": "main"} + {"name": "codex", "repo": "Molecule-AI/molecule-ai-workspace-template-codex", "ref": "main"}, + {"name": "langgraph", "repo": "Molecule-AI/molecule-ai-workspace-template-langgraph", "ref": "main"}, + {"name": "crewai", "repo": "Molecule-AI/molecule-ai-workspace-template-crewai", "ref": "main"}, + {"name": "autogen", "repo": "Molecule-AI/molecule-ai-workspace-template-autogen", "ref": "main"}, + {"name": "deepagents", "repo": "Molecule-AI/molecule-ai-workspace-template-deepagents", "ref": "main"}, + {"name": "gemini-cli", "repo": "Molecule-AI/molecule-ai-workspace-template-gemini-cli", "ref": "main"} ], "org_templates": [ {"name": "molecule-dev", "repo": "Molecule-AI/molecule-ai-org-template-molecule-dev", "ref": "main"}, From 7abb94dab8f8946f313399a9d88a2dd49702dc93 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Sun, 3 May 2026 05:56:18 -0700 Subject: [PATCH 3/3] fix(canvas): align tier text contracts with 4-tier reality (T1/T2/T3/T4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tier system in CreateWorkspaceDialog and design-tokens has been T1 Sandboxed / T2 Standard / T3 Privileged / T4 Full Access, but two chrome surfaces still showed the older 3-tier mapping with T3 as "Full Access": - Legend (bottom-left chrome on every canvas page) listed only T1/T2/T3 and called T3 "Full Access". On a SaaS tenant the actual workspace badges render T4 (in amber/warm) — there was no T4 entry in the legend at all, so the user sees an undocumented orange badge. - ConfigTab tier dropdown (per-workspace settings → Sandboxing) had no T4 option at all and called T3 "Full Access". So an existing T4 workspace would show "T3 — Full Access" as the selected option, silently downgrading the displayed tier on the settings panel. - tenant.ts isSaaSTenant() doc comment claimed SaaS workspaces are "inherently T3 Full Access" — wrong on both the number and the lock rationale (SaaS hides T1/T2/T3, not just T1/T2). Fix: - Legend now imports TIER_CONFIG and renders all four tiers (Sandboxed/Standard/Privileged/Full Access) using the same color swatches as the badges on workspace cards. Eliminates the previous drift where Legend's hardcoded sky/violet/warm chips didn't match the gray/sky/violet/amber actually rendered on nodes. - ConfigTab adds the missing T4 — Full Access option and renames T3 to Privileged. - tenant.ts comment updated to match the picker's actual hide list. Co-Authored-By: Claude Opus 4.7 (1M context) --- canvas/src/components/Legend.tsx | 20 ++++++++++++++++---- canvas/src/components/tabs/ConfigTab.tsx | 3 ++- canvas/src/lib/tenant.ts | 4 ++-- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/canvas/src/components/Legend.tsx b/canvas/src/components/Legend.tsx index 647479ef..c6d67365 100644 --- a/canvas/src/components/Legend.tsx +++ b/canvas/src/components/Legend.tsx @@ -1,11 +1,23 @@ "use client"; import { useEffect, useState } from "react"; -import { STATUS_CONFIG } from "@/lib/design-tokens"; +import { STATUS_CONFIG, TIER_CONFIG } from "@/lib/design-tokens"; import { useCanvasStore } from "@/store/canvas"; const LEGEND_STATUSES = ["online", "provisioning", "degraded", "failed", "paused", "offline"] as const; +// Tier descriptions kept in sync with CreateWorkspaceDialog.tsx (the +// source of truth for what each tier means semantically). Colors come +// from TIER_CONFIG so the legend swatch matches the badge actually +// rendered on every WorkspaceNode — drift here misled users into +// thinking the legend documented a different tier than the one shown. +const LEGEND_TIERS: ReadonlyArray<{ tier: number; label: string }> = [ + { tier: 1, label: "Sandboxed" }, + { tier: 2, label: "Standard" }, + { tier: 3, label: "Privileged" }, + { tier: 4, label: "Full Access" }, +]; + // Persist the user's choice across sessions. Default is "open" so // first-time users still see the symbol key; once dismissed we // respect that until they explicitly reopen via the floating pill. @@ -102,9 +114,9 @@ export function Legend() {
Tier
- - - + {LEGEND_TIERS.map(({ tier, label }) => ( + + ))}
diff --git a/canvas/src/components/tabs/ConfigTab.tsx b/canvas/src/components/tabs/ConfigTab.tsx index da2eb206..8682073b 100644 --- a/canvas/src/components/tabs/ConfigTab.tsx +++ b/canvas/src/components/tabs/ConfigTab.tsx @@ -655,7 +655,8 @@ export function ConfigTab({ workspaceId }: Props) { > - + + diff --git a/canvas/src/lib/tenant.ts b/canvas/src/lib/tenant.ts index 13881037..095b1391 100644 --- a/canvas/src/lib/tenant.ts +++ b/canvas/src/lib/tenant.ts @@ -59,8 +59,8 @@ export function getTenantSlug(): string { * isSaaSTenant reports whether the canvas is running as the UI for a * SaaS tenant (served at .moleculesai.app). Use for client-side * UX branches that should behave differently on SaaS vs self-hosted — - * e.g. the workspace tier picker hides T1/T2 sandbox tiers because every - * SaaS workspace gets its own EC2 VM (inherently T3 Full Access). + * e.g. the workspace tier picker hides T1/T2/T3 sandbox tiers because + * every SaaS workspace gets its own EC2 VM (inherently T4 Full Access). * * SSR-safe: returns false on the server to avoid hydration drift; call * sites should tolerate a flip from false→true on first client render.