Commit Graph

5385 Commits

Author SHA1 Message Date
Hongming Wang
fad03b7db3 Merge pull request #48 from Molecule-AI/fix/issue-17-rogue-restart-loop
fix(provisioner): stop rogue config-missing restart loop (#17)
2026-04-14 08:12:30 -07:00
Hongming Wang
cc9f181e8d
Merge pull request #48 from Molecule-AI/fix/issue-17-rogue-restart-loop
fix(provisioner): stop rogue config-missing restart loop (#17)
2026-04-14 08:12:30 -07:00
Hongming Wang
9255ba2ada docs(hermes): document HERMES_API_KEY env var and runtime-table row
Adds HERMES_API_KEY to .env.example with a cross-reference to the
OPENROUTER_API_KEY fallback, and adds the hermes runtime row to the
CLAUDE.md runtime table so the new adapter is discoverable alongside
its siblings (langgraph, claude-code, openclaw, crewai, autogen,
deepagents).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 08:11:37 -07:00
Hongming Wang
56068a7698 docs(hermes): document HERMES_API_KEY env var and runtime-table row
Adds HERMES_API_KEY to .env.example with a cross-reference to the
OPENROUTER_API_KEY fallback, and adds the hermes runtime row to the
CLAUDE.md runtime table so the new adapter is discoverable alongside
its siblings (langgraph, claude-code, openclaw, crewai, autogen,
deepagents).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 08:11:37 -07:00
Hongming Wang
41c4d0a2ac Merge pull request #47 from Molecule-AI/fix/issue-13-workspace-chown
fix(workspace): chown /workspace when root-owned bind mount (#13)
2026-04-14 08:10:58 -07:00
Hongming Wang
af54fe89de
Merge pull request #47 from Molecule-AI/fix/issue-13-workspace-chown
fix(workspace): chown /workspace when root-owned bind mount (#13)
2026-04-14 08:10:58 -07:00
Hongming Wang
602f3ef685 fix(provisioner): stop rogue config-missing restart loop (#17)
Resolves #17.

Part A: scripts/cleanup-rogue-workspaces.sh deletes workspaces whose id
or name starts with known test placeholder prefixes (aaaaaaaa-, etc.)
and force-removes the paired Docker container. Documented in
tests/README.md.

Part B: add a pre-flight check in provisionWorkspace() — when neither a
template path nor in-memory configFiles supplies config.yaml, probe the
existing named volume via a throwaway alpine container. If the volume
lacks config.yaml, mark the workspace status='failed' with a clear
last_sample_error instead of handing it to Docker's unless-stopped
restart policy (which otherwise loops forever on FileNotFoundError).

New pure helper provisioner.ValidateConfigSource + unit tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 07:32:58 -07:00
Hongming Wang
f7683e3adf fix(provisioner): stop rogue config-missing restart loop (#17)
Resolves #17.

Part A: scripts/cleanup-rogue-workspaces.sh deletes workspaces whose id
or name starts with known test placeholder prefixes (aaaaaaaa-, etc.)
and force-removes the paired Docker container. Documented in
tests/README.md.

Part B: add a pre-flight check in provisionWorkspace() — when neither a
template path nor in-memory configFiles supplies config.yaml, probe the
existing named volume via a throwaway alpine container. If the volume
lacks config.yaml, mark the workspace status='failed' with a clear
last_sample_error instead of handing it to Docker's unless-stopped
restart policy (which otherwise loops forever on FileNotFoundError).

New pure helper provisioner.ValidateConfigSource + unit tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 07:32:58 -07:00
Hongming Wang
b6c2f15933 fix(workspace): recursive chown when /workspace bind mount is root-owned (#13)
On Docker Desktop (macOS/Windows), host-path bind mounts often appear
root-owned inside the container. The previous entrypoint only chowned
/workspace top-level, so agents (uid 1000) still couldn't write to
/workspace/repo/* — git clone, pip install, and file edits failed with
EACCES and fell back to /tmp. Detect the root-owned-contents case by
sampling the first entry; if it's root-owned, recursively chown the
tree. On normal Linux Docker with matching uids this is a no-op, so the
fast-startup path is preserved for the common case.

Part B of the issue (private-repo initial_prompt clone) was addressed
by PR #20.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 07:29:30 -07:00
Hongming Wang
cb47e89aa8 fix(workspace): recursive chown when /workspace bind mount is root-owned (#13)
On Docker Desktop (macOS/Windows), host-path bind mounts often appear
root-owned inside the container. The previous entrypoint only chowned
/workspace top-level, so agents (uid 1000) still couldn't write to
/workspace/repo/* — git clone, pip install, and file edits failed with
EACCES and fell back to /tmp. Detect the root-owned-contents case by
sampling the first entry; if it's root-owned, recursively chown the
tree. On normal Linux Docker with matching uids this is a no-op, so the
fast-startup path is preserved for the common case.

Part B of the issue (private-repo initial_prompt clone) was addressed
by PR #20.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 07:29:30 -07:00
Hongming Wang
707ee08673 Merge pull request #43 from Molecule-AI/fix/reduced-motion
fix(a11y): prefers-reduced-motion WCAG 2.3.3 compliance
2026-04-14 07:20:19 -07:00
Hongming Wang
5ab75532d0
Merge pull request #43 from Molecule-AI/fix/reduced-motion
fix(a11y): prefers-reduced-motion WCAG 2.3.3 compliance
2026-04-14 07:20:19 -07:00
Hongming Wang
b2b1a88202 Merge pull request #45 from Molecule-AI/feat/zoom-to-team-shortcut
feat(canvas): Z shortcut + help entry for double-click zoom-to-team
2026-04-14 07:19:23 -07:00
Hongming Wang
652fc31d9b
Merge pull request #45 from Molecule-AI/feat/zoom-to-team-shortcut
feat(canvas): Z shortcut + help entry for double-click zoom-to-team
2026-04-14 07:19:23 -07:00
Hongming Wang
c23a8c154f Merge pull request #46 from Molecule-AI/fix/a2a-client-auth-headers
fix(security): complete Phase 30.6 auth headers in a2a_client — fixes post-deploy break in get_peers
2026-04-14 07:18:16 -07:00
Hongming Wang
cfe1912997
Merge pull request #46 from Molecule-AI/fix/a2a-client-auth-headers
fix(security): complete Phase 30.6 auth headers in a2a_client — fixes post-deploy break in get_peers
2026-04-14 07:18:16 -07:00
Dev Lead Agent
363a55782b fix(security): complete Phase 30.6 auth headers in a2a_client get_peers and discover_peer
get_peers() was sending no auth headers to /registry/:id/peers — this would
return 401 for every workspace agent after PR #31 (WorkspaceAuth middleware)
deploys, breaking peer discovery entirely.

discover_peer() had X-Workspace-ID but was missing the bearer token, also
required by Phase 30.6 for /registry/discover/:id.

Both functions now send {"X-Workspace-ID": WORKSPACE_ID, **auth_headers()}.
get_workspace_info() was already correct (auth_headers() present since PR #39).

Adds test_request_sends_workspace_id_header to TestGetPeers; hardens the
discover_peer header assertion to use presence-check rather than exact equality.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 13:23:44 +00:00
Dev Lead Agent
b99497cd3f fix(security): complete Phase 30.6 auth headers in a2a_client get_peers and discover_peer
get_peers() was sending no auth headers to /registry/:id/peers — this would
return 401 for every workspace agent after PR #31 (WorkspaceAuth middleware)
deploys, breaking peer discovery entirely.

discover_peer() had X-Workspace-ID but was missing the bearer token, also
required by Phase 30.6 for /registry/discover/:id.

Both functions now send {"X-Workspace-ID": WORKSPACE_ID, **auth_headers()}.
get_workspace_info() was already correct (auth_headers() present since PR #39).

Adds test_request_sends_workspace_id_header to TestGetPeers; hardens the
discover_peer header assertion to use presence-check rather than exact equality.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 13:23:44 +00:00
Dev Lead Agent
93b38dfd22 feat(canvas): Z shortcut + help entry for double-click zoom-to-team
Adds Z as a keyboard equivalent for the existing double-click zoom-to-team
gesture (WCAG 2.1.1). When a team node is selected, pressing Z dispatches
molecule:zoom-to-team, which fitBounds to the parent and all children.
Input elements are guarded so Z still types normally in text fields.
Adds a 6th help panel entry documenting the Dbl-click / Z gesture.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 11:36:41 +00:00
Dev Lead Agent
7c336c680d feat(canvas): Z shortcut + help entry for double-click zoom-to-team
Adds Z as a keyboard equivalent for the existing double-click zoom-to-team
gesture (WCAG 2.1.1). When a team node is selected, pressing Z dispatches
molecule:zoom-to-team, which fitBounds to the parent and all children.
Input elements are guarded so Z still types normally in text fields.
Adds a 6th help panel entry documenting the Dbl-click / Z gesture.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 11:36:41 +00:00
Hongming Wang
5546aa5ca7 Merge pull request #42 from Molecule-AI/fix/a11y-audit-11
fix: ARIA tablist for side panel, Radix Dialog for create modal, aria-live for loading states (audit 11)
2026-04-14 04:27:35 -07:00
Hongming Wang
36ae95f6c2
Merge pull request #42 from Molecule-AI/fix/a11y-audit-11
fix: ARIA tablist for side panel, Radix Dialog for create modal, aria-live for loading states (audit 11)
2026-04-14 04:27:35 -07:00
Dev Lead Agent
889d397d32 fix(a11y): prefers-reduced-motion WCAG 2.3.3 compliance
globals.css: append @media (prefers-reduced-motion: reduce) block that zeroes
animation/transition durations, disables .animate-in/.slide-in-from-* entry
animations (Toaster, ApprovalBanner, SidePanel slide), strips dashdraw and
node-appear keyframes from React Flow elements.

Components: replace all bare animate-pulse (13 occurrences across WorkspaceNode,
StatusDot, Toolbar, SidePanel, Legend, SearchDialog, TerminalTab, TemplatePalette)
with motion-safe:animate-pulse so status indicator pulsing stops for users with
vestibular disorders. Replace 3 animate-bounce occurrences in ChatTab typing
indicator with motion-safe:animate-bounce.

Tests: new canvas/src/__tests__/reduced-motion.test.ts (12 tests) verifies the
@media block is present in globals.css and that every component file uses the
motion-safe: variant rather than bare animation classes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 11:25:23 +00:00
Dev Lead Agent
95abca2f4f fix(a11y): prefers-reduced-motion WCAG 2.3.3 compliance
globals.css: append @media (prefers-reduced-motion: reduce) block that zeroes
animation/transition durations, disables .animate-in/.slide-in-from-* entry
animations (Toaster, ApprovalBanner, SidePanel slide), strips dashdraw and
node-appear keyframes from React Flow elements.

Components: replace all bare animate-pulse (13 occurrences across WorkspaceNode,
StatusDot, Toolbar, SidePanel, Legend, SearchDialog, TerminalTab, TemplatePalette)
with motion-safe:animate-pulse so status indicator pulsing stops for users with
vestibular disorders. Replace 3 animate-bounce occurrences in ChatTab typing
indicator with motion-safe:animate-bounce.

Tests: new canvas/src/__tests__/reduced-motion.test.ts (12 tests) verifies the
@media block is present in globals.css and that every component file uses the
motion-safe: variant rather than bare animation classes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 11:25:23 +00:00
Dev Lead Agent
6f72bc5016 fix: Radix Dialog for create modal, ARIA tablist for side panel, aria-live for loading states (audit 11)
- CreateWorkspaceDialog: replace plain div modal with @radix-ui/react-dialog (focus-trap,
  Escape-to-close, aria-labelledby auto-wired); tier selector uses role=radiogroup/radio +
  aria-checked; error uses role=alert; required fields annotate with sr-only "(required)"
- SidePanel: WAI-ARIA tablist pattern — role=tablist + aria-label, role=tab + aria-selected +
  aria-controls + id, roving tabIndex (0/−1), ArrowRight/Left/Home/End keyboard nav with wrap,
  role=tabpanel + id + aria-labelledby on content area, tab icons are aria-hidden
- TemplatePalette: loading and empty-state divs gain role=status + aria-live=polite
- Canvas: sr-only role=status live region announces workspace count to screen readers
- Tests: 7 new a11y tests for CreateWorkspaceDialog (Radix role=dialog, aria-labelledby,
  data-state, Cancel close, role=alert validation, role=radio tier); 12 new tab tests for
  SidePanel (tablist, 12 tabs, aria-selected, roving tabIndex, aria-controls, tabpanel,
  ArrowRight/Left/Home/End)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 10:31:34 +00:00
Dev Lead Agent
9fe334779f fix: Radix Dialog for create modal, ARIA tablist for side panel, aria-live for loading states (audit 11)
- CreateWorkspaceDialog: replace plain div modal with @radix-ui/react-dialog (focus-trap,
  Escape-to-close, aria-labelledby auto-wired); tier selector uses role=radiogroup/radio +
  aria-checked; error uses role=alert; required fields annotate with sr-only "(required)"
- SidePanel: WAI-ARIA tablist pattern — role=tablist + aria-label, role=tab + aria-selected +
  aria-controls + id, roving tabIndex (0/−1), ArrowRight/Left/Home/End keyboard nav with wrap,
  role=tabpanel + id + aria-labelledby on content area, tab icons are aria-hidden
- TemplatePalette: loading and empty-state divs gain role=status + aria-live=polite
- Canvas: sr-only role=status live region announces workspace count to screen readers
- Tests: 7 new a11y tests for CreateWorkspaceDialog (Radix role=dialog, aria-labelledby,
  data-state, Cancel close, role=alert validation, role=radio tier); 12 new tab tests for
  SidePanel (tablist, 12 tabs, aria-selected, roving tabIndex, aria-controls, tabpanel,
  ArrowRight/Left/Home/End)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 10:31:34 +00:00
Hongming Wang
c271293e9f Merge pull request #40 from Molecule-AI/fix/keyboard-a11y
fix: keyboard navigation — ContextMenu ARIA menu pattern + SearchDialog combobox (WCAG 2.1.1)
2026-04-14 03:26:27 -07:00
Hongming Wang
a81ae1a0a3
Merge pull request #40 from Molecule-AI/fix/keyboard-a11y
fix: keyboard navigation — ContextMenu ARIA menu pattern + SearchDialog combobox (WCAG 2.1.1)
2026-04-14 03:26:27 -07:00
Hongming Wang
a565c49bce Merge pull request #41 from Molecule-AI/fix/security-h3-m4
noteworthy: secrets-handling — H3 github_pat_ redaction + M4 atomic 0600 token write. 7-gate verification PASS.
2026-04-14 03:21:49 -07:00
Hongming Wang
b5eb14e40d
Merge pull request #41 from Molecule-AI/fix/security-h3-m4
noteworthy: secrets-handling — H3 github_pat_ redaction + M4 atomic 0600 token write. 7-gate verification PASS.
2026-04-14 03:21:49 -07:00
Dev Lead Agent
1a109b3263 fix(security): H3 github_pat_ redaction + M4 atomic token write (audit cycle 10)
H3 (compliance.py): GitHub fine-grained PATs use the github_pat_ prefix
with an 82-character alphanumeric+underscore suffix — different from
classic tokens (36 chars). Add the missing pattern to _PII_PATTERNS so
fine-grained PATs are redacted in compliance logs alongside classic tokens.

M4 (platform_auth.py): Replace write_text()+chmod() in save_token() with
os.open(O_WRONLY|O_CREAT|O_TRUNC, 0o600) + os.write(). The old approach
had a TOCTOU window where a concurrent reader could access the token file
before chmod restricted permissions. os.open with explicit mode creates the
file with 0600 permissions atomically in a single syscall.

H2 (a2a_client.py): Already fixed in commit 6c78962 (Cycle 5); no-op.

Tests: 1136 passed, 2 skipped (workspace-template pytest suite)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 09:34:27 +00:00
Dev Lead Agent
1440bd732e fix(security): H3 github_pat_ redaction + M4 atomic token write (audit cycle 10)
H3 (compliance.py): GitHub fine-grained PATs use the github_pat_ prefix
with an 82-character alphanumeric+underscore suffix — different from
classic tokens (36 chars). Add the missing pattern to _PII_PATTERNS so
fine-grained PATs are redacted in compliance logs alongside classic tokens.

M4 (platform_auth.py): Replace write_text()+chmod() in save_token() with
os.open(O_WRONLY|O_CREAT|O_TRUNC, 0o600) + os.write(). The old approach
had a TOCTOU window where a concurrent reader could access the token file
before chmod restricted permissions. os.open with explicit mode creates the
file with 0600 permissions atomically in a single syscall.

H2 (a2a_client.py): Already fixed in commit bea0e96 (Cycle 5); no-op.

Tests: 1136 passed, 2 skipped (workspace-template pytest suite)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 09:34:27 +00:00
Dev Lead Agent
c032a7dbfb fix: keyboard navigation for ContextMenu (WCAG 2.1.1) and SearchDialog combobox pattern
- ContextMenu: role=menu/menuitem/separator, aria-label, aria-disabled,
  focus-visible ring, auto-focus first enabled item on open,
  ArrowDown/Up roving focus (wrapping), Escape + Tab dismiss,
  aria-hidden on decorative icons/status dot
- SearchDialog: role=dialog+aria-modal, combobox pattern on input
  (role=combobox, aria-expanded, aria-autocomplete, aria-controls,
  aria-activedescendant), focusedIndex state, ArrowDown/Up/Enter
  keyboard navigation, role=listbox+option, aria-selected, role=status
  + aria-live=polite on empty state, footer hints updated with ↑↓
- Add 10 ContextMenu keyboard tests (role, aria-label, menuitem,
  separator, Escape, Tab, ArrowDown, wrap, ArrowUp wrap, null guard)
- Add 13 SearchDialog keyboard tests (dialog, aria-modal, combobox,
  listbox, option, ArrowDown, double-ArrowDown, clamp, ArrowUp-clamp,
  Enter select, Enter noop, query reset, activedescendant)

Tests: 406 passed (383 existing + 23 new)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 09:28:10 +00:00
Dev Lead Agent
0725a818e7 fix: keyboard navigation for ContextMenu (WCAG 2.1.1) and SearchDialog combobox pattern
- ContextMenu: role=menu/menuitem/separator, aria-label, aria-disabled,
  focus-visible ring, auto-focus first enabled item on open,
  ArrowDown/Up roving focus (wrapping), Escape + Tab dismiss,
  aria-hidden on decorative icons/status dot
- SearchDialog: role=dialog+aria-modal, combobox pattern on input
  (role=combobox, aria-expanded, aria-autocomplete, aria-controls,
  aria-activedescendant), focusedIndex state, ArrowDown/Up/Enter
  keyboard navigation, role=listbox+option, aria-selected, role=status
  + aria-live=polite on empty state, footer hints updated with ↑↓
- Add 10 ContextMenu keyboard tests (role, aria-label, menuitem,
  separator, Escape, Tab, ArrowDown, wrap, ArrowUp wrap, null guard)
- Add 13 SearchDialog keyboard tests (dialog, aria-modal, combobox,
  listbox, option, ArrowDown, double-ArrowDown, clamp, ArrowUp-clamp,
  Enter select, Enter noop, query reset, activedescendant)

Tests: 406 passed (383 existing + 23 new)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 09:28:10 +00:00
Hongming Wang
be941c4737 Merge pull request #39 from Molecule-AI/fix/n1-python-auth-headers
fix(security): N1 — Python callers missing auth headers for /workspaces/* routes
2026-04-14 02:25:36 -07:00
Hongming Wang
264d490e06
Merge pull request #39 from Molecule-AI/fix/n1-python-auth-headers
fix(security): N1 — Python callers missing auth headers for /workspaces/* routes
2026-04-14 02:25:36 -07:00
Hongming Wang
eb91867340 Merge pull request #37 from Molecule-AI/fix/audit-run9
feat(canvas): WebSocket connection status indicator in Toolbar
2026-04-14 02:21:29 -07:00
Hongming Wang
ea6fdd58a6
Merge pull request #37 from Molecule-AI/fix/audit-run9
feat(canvas): WebSocket connection status indicator in Toolbar
2026-04-14 02:21:29 -07:00
Hongming Wang
34573d6a1d Merge pull request #38 from Molecule-AI/fix/ci-canvas-deploy-reminder
ci: post canvas deploy reminder after every main merge
2026-04-14 02:20:47 -07:00
Hongming Wang
8b33b374d1
Merge pull request #38 from Molecule-AI/fix/ci-canvas-deploy-reminder
ci: post canvas deploy reminder after every main merge
2026-04-14 02:20:47 -07:00
Backend Engineer
9649311d51 fix(security): N1 — add auth headers to all platform calls in Python callers
IMPACT WITHOUT THIS FIX: deploying PR #31 (WorkspaceAuth middleware on
/workspaces/*) without this patch causes EVERY delegation cycle to silently
break — the heartbeat poll returns 401, the self-message A2A POST returns
401, agents never wake up after task completion, and memory consolidation
stops. The entire multi-agent coordination system degrades to single-shot
interactions with no result delivery.

Changes (all using the existing platform_auth.auth_headers() pattern
already used for POST /registry/heartbeat):

heartbeat.py — 5 calls fixed:
  - GET  /workspaces/:id/delegations     (delegation poll)
  - GET  /workspaces/:id                 (self workspace info for parent lookup)
  - GET  /workspaces/{parent_id}         (parent workspace name lookup)
  - POST /workspaces/:id/a2a             (self-message to wake agent on results)
  - POST /workspaces/:id/notify          (canvas delegation result notification)
  Also moved `from platform_auth import auth_headers` from inline (per-call)
  to module-level import so _check_delegations() can use it without re-importing.

consolidation.py — 4 calls fixed:
  - GET    /workspaces/:id/memories      (fetch memories for consolidation)
  - POST   /workspaces/:id/memories      (write consolidated summary — agent path)
  - DELETE /workspaces/:id/memories/:id  (delete original memories post-consolidation)
  - POST   /workspaces/:id/memories      (write consolidated summary — fallback path)

a2a_client.py — 1 call fixed:
  - GET /workspaces/:id                  (get_workspace_info())

⚠️  DEPLOYMENT NOTE: This PR MUST be merged and deployed at the same time as
PR #31 (WorkspaceAuth middleware). Deploying #31 without this fix will
immediately break all delegation result delivery.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 08:37:50 +00:00
Backend Engineer
d8c670a687 fix(security): N1 — add auth headers to all platform calls in Python callers
IMPACT WITHOUT THIS FIX: deploying PR #31 (WorkspaceAuth middleware on
/workspaces/*) without this patch causes EVERY delegation cycle to silently
break — the heartbeat poll returns 401, the self-message A2A POST returns
401, agents never wake up after task completion, and memory consolidation
stops. The entire multi-agent coordination system degrades to single-shot
interactions with no result delivery.

Changes (all using the existing platform_auth.auth_headers() pattern
already used for POST /registry/heartbeat):

heartbeat.py — 5 calls fixed:
  - GET  /workspaces/:id/delegations     (delegation poll)
  - GET  /workspaces/:id                 (self workspace info for parent lookup)
  - GET  /workspaces/{parent_id}         (parent workspace name lookup)
  - POST /workspaces/:id/a2a             (self-message to wake agent on results)
  - POST /workspaces/:id/notify          (canvas delegation result notification)
  Also moved `from platform_auth import auth_headers` from inline (per-call)
  to module-level import so _check_delegations() can use it without re-importing.

consolidation.py — 4 calls fixed:
  - GET    /workspaces/:id/memories      (fetch memories for consolidation)
  - POST   /workspaces/:id/memories      (write consolidated summary — agent path)
  - DELETE /workspaces/:id/memories/:id  (delete original memories post-consolidation)
  - POST   /workspaces/:id/memories      (write consolidated summary — fallback path)

a2a_client.py — 1 call fixed:
  - GET /workspaces/:id                  (get_workspace_info())

⚠️  DEPLOYMENT NOTE: This PR MUST be merged and deployed at the same time as
PR #31 (WorkspaceAuth middleware). Deploying #31 without this fix will
immediately break all delegation result delivery.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 08:37:50 +00:00
Dev Lead Agent
f54d6c02ae ci: post canvas deploy reminder comment after every main merge
Adds a `canvas-deploy-reminder` job to ci.yml that fires on every
push to main once `canvas-build` passes. It posts a commit comment via
the built-in GITHUB_TOKEN (no new secrets needed) reminding whoever
monitors CI to run:

  cd /g/personal_programs/molecule-monorepo
  git pull origin main
  docker compose build canvas && docker compose up -d canvas

The comment includes the commit SHA and a direct link to the build log.

Rationale: 5 consecutive merge cycles (PRs #21, #25, #30, #32, #34)
went undeployed because there is no auto-deploy hook and the manual
step was silently forgotten. A commit comment on the merge commit is
the lowest-friction reminder that requires no external secrets or infra.

Does NOT run on PRs — only on direct pushes to main (i.e. post-merge).
Uses `needs: canvas-build` so the reminder only fires after build+tests
pass; a failing build produces no comment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 08:28:42 +00:00
Dev Lead Agent
64c95edf8d ci: post canvas deploy reminder comment after every main merge
Adds a `canvas-deploy-reminder` job to ci.yml that fires on every
push to main once `canvas-build` passes. It posts a commit comment via
the built-in GITHUB_TOKEN (no new secrets needed) reminding whoever
monitors CI to run:

  cd /g/personal_programs/molecule-monorepo
  git pull origin main
  docker compose build canvas && docker compose up -d canvas

The comment includes the commit SHA and a direct link to the build log.

Rationale: 5 consecutive merge cycles (PRs #21, #25, #30, #32, #34)
went undeployed because there is no auto-deploy hook and the manual
step was silently forgotten. A commit comment on the merge commit is
the lowest-friction reminder that requires no external secrets or infra.

Does NOT run on PRs — only on direct pushes to main (i.e. post-merge).
Uses `needs: canvas-build` so the reminder only fires after build+tests
pass; a failing build produces no comment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 08:28:42 +00:00
Hongming Wang
bf7eded450 Merge pull request #35 from Molecule-AI/fix/c18-c20-workspace-auth
fix(security): C18 URL hijacking + C20 unauthenticated workspace deletion
2026-04-14 01:27:00 -07:00
Hongming Wang
a531766d07
Merge pull request #35 from Molecule-AI/fix/c18-c20-workspace-auth
fix(security): C18 URL hijacking + C20 unauthenticated workspace deletion
2026-04-14 01:27:00 -07:00
Dev Lead Agent
7c52661280 fix(canvas): close 4 gaps in WS status indicator (env, toast, tests)
Gap 1 — WS_URL now derives from NEXT_PUBLIC_PLATFORM_URL when
NEXT_PUBLIC_WS_URL is not set (http→ws, appends /ws; https→wss).
Operators need only one env var. NEXT_PUBLIC_WS_URL remains an explicit
override escape hatch.

Gap 2 — Add canvas/.env.example documenting NEXT_PUBLIC_PLATFORM_URL
(required) and NEXT_PUBLIC_WS_URL (optional override, commented out).

Gap 3 — Toolbar fires showToast("Live updates restored", "success")
when wsStatus transitions connecting→connected. mountedRef (set after
2 s) suppresses the toast on the very first page-load connection so
only genuine reconnects notify the user.

Gap 4 — New canvas/src/store/__tests__/socket.url.test.ts (6 tests):
  · fallback to ws://localhost:8080/ws when no env set
  · http→ws derivation from NEXT_PUBLIC_PLATFORM_URL
  · https→wss derivation
  · NEXT_PUBLIC_WS_URL override takes precedence
  · api.ts PLATFORM_URL fallback
  · api.ts reads NEXT_PUBLIC_PLATFORM_URL

375/375 tests passing, production build clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 08:26:38 +00:00
Dev Lead Agent
30d9be1c26 fix(canvas): close 4 gaps in WS status indicator (env, toast, tests)
Gap 1 — WS_URL now derives from NEXT_PUBLIC_PLATFORM_URL when
NEXT_PUBLIC_WS_URL is not set (http→ws, appends /ws; https→wss).
Operators need only one env var. NEXT_PUBLIC_WS_URL remains an explicit
override escape hatch.

Gap 2 — Add canvas/.env.example documenting NEXT_PUBLIC_PLATFORM_URL
(required) and NEXT_PUBLIC_WS_URL (optional override, commented out).

Gap 3 — Toolbar fires showToast("Live updates restored", "success")
when wsStatus transitions connecting→connected. mountedRef (set after
2 s) suppresses the toast on the very first page-load connection so
only genuine reconnects notify the user.

Gap 4 — New canvas/src/store/__tests__/socket.url.test.ts (6 tests):
  · fallback to ws://localhost:8080/ws when no env set
  · http→ws derivation from NEXT_PUBLIC_PLATFORM_URL
  · https→wss derivation
  · NEXT_PUBLIC_WS_URL override takes precedence
  · api.ts PLATFORM_URL fallback
  · api.ts reads NEXT_PUBLIC_PLATFORM_URL

375/375 tests passing, production build clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 08:26:38 +00:00
Hongming Wang
03c5dfd410 Merge pull request #36 from Molecule-AI/fix/watcher-sha256
fix(security): H1 — replace MD5 with SHA-256 in watcher file-integrity checks
2026-04-14 01:25:29 -07:00
Hongming Wang
b7f4333f46
Merge pull request #36 from Molecule-AI/fix/watcher-sha256
fix(security): H1 — replace MD5 with SHA-256 in watcher file-integrity checks
2026-04-14 01:25:29 -07:00