Commit Graph

4881 Commits

Author SHA1 Message Date
e29b166f60 fix(test): poll error counter to 0 before asserting in RecordsMetricsOnSuccess
Race-detector CI runs (-race) slow goroutines enough that a
prior sweeper goroutine (e.g. TestStartSweeper_TransientErrorDoesNotCrashLoop)
can still be running and incrementing pendingUploadsSweepErrors after
metricDelta() captures its baseline, but before the success-path sweeper
records its success metrics. The test then reads deltaError=1 instead of 0.

Fix: add waitForMetricDelta(t, deltaError, 0, 2*time.Second) before the
assertion, matching the polling pattern already used in the error-path
test (TestStartSweeper_RecordsMetricsOnError). This ensures the error
counter has settled before we assert on it.

Fixes molecule-core#22.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 23:27:19 +00:00
7bc249ff7a Merge pull request 'feat(canvas): keyboard-accessible node resize via Cmd/Ctrl+Arrow' (#192) from feat/canvas-keyboard-node-resize into main 2026-05-09 23:13:52 +00:00
Molecule AI Core Platform Lead
bf0e47814e Merge remote-tracking branch 'origin/main' into trig-192 2026-05-09 23:13:38 +00:00
2c3b36f5cd Merge pull request 'fix(ci): replace gh api calls with Gitea-compatible alternatives (closes #75)' (#191) from fix/gh-api-gitea-sweep-75 into main 2026-05-09 23:13:20 +00:00
Molecule AI Core Platform Lead
f263f89ca9 trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 23:13:09 +00:00
Molecule AI Core Platform Lead
9c44bdf4fe Merge remote-tracking branch 'origin/main' into trig-192 2026-05-09 23:12:59 +00:00
Molecule AI Core Platform Lead
02a8303bb5 trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 23:12:47 +00:00
Molecule AI Core Platform Lead
41283b1919 Merge remote-tracking branch 'origin/main' into trig-192 2026-05-09 23:12:47 +00:00
534cdb5aa4 feat(canvas): keyboard-accessible node resize via Cmd/Ctrl+Arrow
Cmd/Ctrl+Arrow Up/Down resizes node height (±10px, ±2px with Shift).
Cmd/Ctrl+Arrow Left/Right resizes node width (±10px, ±2px with Shift).
Uses the same onNodesChange('dimensions') path that NodeResizer uses
— no new store action needed. Respects min-width/min-height matching
the NodeResizer constraints (360×200 with children, 210×110 without).

The Arrow-key move shortcut now skips when a modifier key is held,
so Cmd/Ctrl+Arrow unambiguously means resize (not move).

Updates canvas audit doc: Node Rendering section updated and
the LOW node-resize item marked done. All Remaining Gaps items
are now complete.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 23:10:51 +00:00
9368b20d49 [core-be-agent] fix(ci): replace gh api calls with Gitea-compatible alternatives
Issue #75 PR-D: two remaining `gh` CLI calls in .github/workflows/.

1. ci.yml canvas-deploy-reminder:
   - Replaced `gh api POST repos/.../commits/.../comments` with writing
     to GITHUB_STEP_SUMMARY. Gitea has no commit-comments API (confirmed
     in issue #75), so the gh call always failed. GITHUB_STEP_SUMMARY works
     on both GitHub Actions and Gitea Actions as the workflow-run summary
     page, which is the natural place for post-deploy action items.
   - Removed now-unnecessary GH_TOKEN env var and contents:write permission.

2. check-merge-group-trigger.yml:
   - Converted to no-op stub. Gitea has no merge queue feature and no
     merge_group: event type, so this workflow's lint would find nothing
     to verify (all workflows vacuously pass). Keeping workflow+job name
     unchanged preserves commit-status context names for branch protection
     consumers. Dropped the merge_group: trigger since it would never fire
     on Gitea. Dropped the full bash linter + gh api call.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 23:10:07 +00:00
13375ed902 Merge pull request 'fix(deps): migrate gh-identity from GitHub to Gitea module path' (#189) from infra/fix-issue-91-gh-identity-module-migration into main 2026-05-09 22:58:53 +00:00
Molecule AI Core Platform Lead
a07e2df1c0 Merge remote-tracking branch 'origin/main' into trig-189 2026-05-09 22:58:45 +00:00
Molecule AI Core Platform Lead
64b970657f trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 22:58:33 +00:00
Molecule AI Core Platform Lead
2a04233d5a Merge remote-tracking branch 'origin/main' into trig-189 2026-05-09 22:58:32 +00:00
a9bb2c47da Merge pull request 'feat(canvas): keyboard-accessible edge anchors via Enter/Space' (#190) from feat/canvas-keyboard-edge-anchors into main 2026-05-09 22:58:29 +00:00
Molecule AI Core Platform Lead
5a5a7bce27 Merge remote-tracking branch 'origin/main' into trig-190 2026-05-09 22:58:21 +00:00
Molecule AI Core Platform Lead
4e69b88d82 trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 22:58:09 +00:00
Molecule AI Core Platform Lead
a8df558909 Merge remote-tracking branch 'origin/main' into trig-190 2026-05-09 22:58:08 +00:00
d144827ea4 Merge pull request 'fix(handlers): auto-restart workspace after file write/delete/replace' (#188) from infra/fix-issue-151-restart-after-file-write into main 2026-05-09 22:53:29 +00:00
Molecule AI Core Platform Lead
0a571a1f1e Merge remote-tracking branch 'origin/main' into trig-188f 2026-05-09 22:52:43 +00:00
19bb3430e5 feat(canvas): keyboard-accessible edge anchors via Enter/Space
Target handle (top of card): Enter/Space extracts this node from
its parent, moving it to the root level.

Source handle (bottom of card): Enter/Space nests the currently
selected node as a child of this node (requires another node to be
selected first).

Both handles gain tabIndex=0, role="button", a descriptive aria-label,
and a blue focus ring so keyboard-only users can navigate the
workspace hierarchy without a mouse. Uses the existing nestNode store
action — no new API surface needed.

Updates the canvas audit doc to mark the LOW edge-anchor item done.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:52:33 +00:00
Molecule AI Core Platform Lead
b42cc0e0a0 trigger: re-run sop-tier-check after conflict resolution + main sync 2026-05-09 22:52:21 +00:00
a0e815672f Merge pull request 'docs(canvas): fix stale audit doc text from PR #182' (#187) from docs/canvas-audit-fix-stale-text into main 2026-05-09 22:51:49 +00:00
Molecule AI Core Platform Lead
bd0a52a9a1 merge main into infra/fix-issue-151: keep PR #183 root-skip wording in local_test.go 2026-05-09 22:51:03 +00:00
ebc56a2ce6 fix(deps): migrate gh-identity from GitHub to Gitea module path
Update go.mod require and main.go import to use the Gitea-hosted
module path go.moleculesai.app/plugin/gh-identity (migrated from
github.com/Molecule-AI/molecule-ai-plugin-gh-identity).

Follows the pattern of the org-template URL migrations (github.com ->
git.moleculesai.app) applied to Go module imports.

Fixes molecule-core#91.
Ref: molecule-internal#71.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:50:45 +00:00
Molecule AI Core Platform Lead
1d644f451d trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 22:50:00 +00:00
Molecule AI Core Platform Lead
b33f372085 Merge remote-tracking branch 'origin/main' into trig-187f 2026-05-09 22:49:43 +00:00
eaf7dbb7c4 fix(handlers): auto-restart workspace after file write/delete/replace
PUT /workspaces/:id/files and DELETE /workspaces/:id/files updated the
config volume but never restarted the container, so the running agent
continued serving stale file content from its in-memory cache. The
SecretsHandler already had this pattern (issue #15); TemplatesHandler
was missing it.

Fix: after every successful write/delete in WriteFile, DeleteFile, and
ReplaceFiles, call h.wh.RestartByID(workspaceID) asynchronously, guarded
by h.wh != nil (nil-tolerant for callers that only use read-only
surfaces). The RestartByID coalescing gate prevents thundering-herd on
concurrent requests.

Fixes #151.
Fixes #87 (duplicate effort closed — core-be also filed #183).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:43:27 +00:00
278952c13d docs(canvas): fix stale audit doc text from PR #182
The "Node Rendering" and "Drag and Drop" sections still said
"mouse only, no keyboard alternative" and "Keyboard alternative: None"
despite PR #182 (Arrow keys) being merged. Update both to reflect
the keyboard-accessible node drag.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:41:35 +00:00
9e2cbd337c Merge pull request 'fix(pendinguploads/test): correct sweeper test isolation (closes #86)' (#185) from fix/sweeper-test-isolation-86 into main 2026-05-09 22:41:11 +00:00
Molecule AI Core Platform Lead
ede4551c73 Merge remote-tracking branch 'origin/main' into trig-185 2026-05-09 22:41:01 +00:00
Molecule AI Core Platform Lead
281b1493f8 trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 22:40:45 +00:00
Molecule AI Core Platform Lead
51ddc50592 Merge remote-tracking branch 'origin/main' into trig-185 2026-05-09 22:40:44 +00:00
2077cf4054 [core-be-agent] fix(pendinguploads/test): correct sweeper test isolation
Issue #86: TestStartSweeper_RecordsMetricsOnSuccess fails in full-suite.

Root cause: two cooperating bugs in the sweeper test harness.

1. Sweeper loop called sweepOnce after ctx cancellation (double-increment).
   When ctx was cancelled the loop's select received ctx.Done(), called
   sweepOnce with the cancelled ctx, storage.Sweep returned context error,
   and metrics.PendingUploadsSweepError() incremented the error counter a
   SECOND time before the loop exited. Subsequent tests captured a polluted
   error baseline and their deltaError assertions failed.

2. Tests called defer cancel() without waiting for the goroutine to exit.
   The goroutine could still be blocked on Sweep (waiting for the next
   ticker's C channel) when the next test called metricDelta(). If the
   goroutine's Sweep returned during the next test's measurement window,
   the shared metric counters mutated mid-baseline.

Fix (production code):
- Guard the ticker arm: if ctx.Err() != nil, continue instead of calling
  sweepOnce. This prevents the post-cancellation sweep from running.

Fix (test harness):
- startSweeperWithInterval gains a done chan struct{} parameter. When the
  loop exits the channel is closed exactly once.
- StartSweeperForTest starts the goroutine and returns the done channel,
  allowing tests to drain it with <-done after cancel() — guaranteeing
  the goroutine has fully terminated before the next test's baseline.

All 8 sweeper tests now use StartSweeperForTest and drain the done
channel before returning, ensuring stable metric baselines across the
full suite.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:30:28 +00:00
afdb546026 Merge pull request '[core-be-agent] fix(plugins/test): skip TestLocalResolver_BubblesUpCopyFailure when running as root' (#183) from fix/test-local-resolver-root-skip into main 2026-05-09 22:28:10 +00:00
Molecule AI Core Platform Lead
050db66b36 Merge remote-tracking branch 'origin/main' into trig-183 2026-05-09 22:28:01 +00:00
Molecule AI Core Platform Lead
70347e916e trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 22:27:44 +00:00
e65633bf15 fix(test): skip TestLocalResolver_BubblesUpCopyFailure when uid==0
os.Chmod(dst, 0o555) silently passes when os.Geteuid() == 0 because
root bypasses POSIX permission checks. A previous attempt to use a
symlink to /dev/full also fails: Go's os.MkdirAll resolves the symlink
during path traversal and the kernel allows mkdir("/dev/full") as a
device-table entry — io.Copy to /dev/full then succeeds with 0 bytes
written and returns nil.

The honest, consistent fix mirrors TestLocalResolver_CopyFileSourceUnreadable:
skip when running as root. The write-failure propagation logic is
exercised correctly in non-root CI environments.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:22:44 +00:00
4d9850df53 Merge pull request 'feat(canvas): keyboard-accessible node drag via Arrow keys' (#182) from feat/canvas-keyboard-node-drag into main 2026-05-09 22:22:25 +00:00
Molecule AI Core Platform Lead
b9fdaf6b61 Merge remote-tracking branch 'origin/main' into trig-182 2026-05-09 22:22:15 +00:00
Molecule AI Core Platform Lead
2f13fd24a1 trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 22:21:47 +00:00
Molecule AI Core Platform Lead
56b4f6d7e1 Merge remote-tracking branch 'origin/main' into trig-182 2026-05-09 22:21:47 +00:00
e3ea8ff74a [core-be-agent]
fix(plugins/test): skip TestLocalResolver_BubblesUpCopyFailure when running as root

Fixes issue #87: the test sets chmod(dst, 0o555) to make the
destination read-only and asserts the copy fails. On Linux, root
bypasses filesystem permissions and can write to 0o555 directories,
so the copy succeeds when running as root and the assertion fails.

Fix: check os.Getuid() == 0 at the start of the test and skip with
a clear message. Mirrors the existing skip in
TestLocalResolver_CopyFileSourceUnreadable (line 175) which already
handles the same root-bypass issue for unreadable source files.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:21:35 +00:00
449a49f31a Merge pull request '[core-be-agent] fix(tests): clear platform_auth cache before each test' (#181) from fix/workspace-tests-clear-auth-cache into main 2026-05-09 22:19:35 +00:00
Molecule AI Core Platform Lead
0183fe66cb Merge remote-tracking branch 'origin/main' into trig-181 2026-05-09 22:19:23 +00:00
3e2ff63f7f feat(canvas): keyboard-accessible node drag via Arrow keys
Closes canvas audit item: MEDIUM keyboard-accessible node drag.

- Arrow keys move the selected node by 10px per press; Shift+Arrow
  moves by 50px. Position is persisted to the backend via savePosition.
- The modal-dialog guard (same pattern as ? shortcut) prevents Arrow
  keys from moving nodes when a modal like KeyboardShortcutsDialog is
  open — dialogs own their own arrow semantics.
- All shortcuts guarded by the inInput check so Arrow keys still work
  for text navigation inside inputs/textareas.

Changes:
- canvas.ts: new moveNode(dx, dy) store action — updates position
  directly without the grow-parents pass that onNodesChange runs on
  every drag tick (avoids edge-chase flicker).
- useKeyboardShortcuts.ts: Arrow key handler added.
- canvas.test.ts: new moveNode unit tests (position update, no-op,
  savePosition call).
- useKeyboardShortcuts.test.tsx: new integration tests for all
  keyboard shortcuts including the new Arrow key handlers.
- canvas-audit-items.md: Keyboard Shortcuts section upgraded to ,
  drag item marked done.
- canvas-events.test.ts: fix pre-existing double-}); syntax error.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:19:01 +00:00
Molecule AI Core Platform Lead
1cbdf69c8d trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 22:18:45 +00:00
76ac5a88dc [core-be-agent]
fix(tests): clear platform_auth cache before each test

Fixes issue #160: workspace tests fail when MOLECULE_WORKSPACE_TOKEN
is set in the environment.

The bug: platform_auth._cached_token is populated at module import or
first get_token() call and persists for the process lifetime. Tests
that use monkeypatch.delenv("MOLECULE_WORKSPACE_TOKEN") to simulate "no
token in env" were failing because delenv removes the env var but not
the module-level cache — subsequent get_token() calls returned the
stale cached value.

Fix: add a function-scoped autouse fixture in conftest.py that calls
platform_auth.clear_cache() before every test. The import is inside the
fixture to avoid collection-time import issues when platform_auth is
not yet available.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:16:11 +00:00
ab7bb20545 Merge pull request '[core-be-agent] fix(handlers+a2a): treat delivery-confirmed proxy errors as delegation success' (#170) from fix/a2a-delegation-success-rendered-as-error into main 2026-05-09 22:13:47 +00:00
Molecule AI Core Platform Lead
b54101947f trigger: re-run sop-tier-check after tier:medium relabel + new approval 2026-05-09 22:13:29 +00:00