Commit Graph

4934 Commits

Author SHA1 Message Date
Molecule AI Core Platform Lead
02c2226e46 Merge remote-tracking branch 'origin/main' into trig-210 2026-05-10 01:22:02 +00:00
a3e437b43f Merge pull request 'fix(ci): replace dorny/paths-filter with shell-based git diff (Gitea Actions compatibility)' (#208) from infra/fix-harness-replays-paths-filter-and-failure into main 2026-05-10 01:18:25 +00:00
Molecule AI Core Platform Lead
9c35057c98 trigger 2026-05-10 01:18:14 +00:00
ad1a4a2d49 test(canvas): add component tests for ThemeToggle and BundleDropZone
- ThemeToggle.test.tsx (13 tests): renders radiogroup with 3 options,
  aria radiogroup/radio semantics, aria-checked per option, setTheme
  calls on click, custom className prop
- BundleDropZone.test.tsx (11 tests): hidden file input + keyboard
  accessibility (WCAG 2.1.1), drag-over state, import success/error
  toast, auto-clear timeouts (3s error, 4s success), importing
  status indicator, file input reset on re-select

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 01:18:10 +00:00
796201e09f fix(ci): replace dorny/paths-filter with shell-based git diff (Gitea Actions compatibility)
dorny/paths-filter is GitHub-Actions-only and does not work correctly on
Gitea Actions — it silently returns no file changes regardless of what
files were modified, causing the harness-replays workflow to silently
skip on Gitea even when workspace-server/** or canvas/** files change.

Verified: zero harness-replays statuses on PR #188 and #168 (both changed
workspace-server files) vs GitHub Actions where the same workflow
correctly detects changes.

Replace with a shell-based approach that uses:
- github.event.pull_request.base.sha  (Gitea + GitHub: merge-base for PRs)
- github.event.before                (Gitea + GitHub: previous tip for pushes)
- git diff --name-only <BASE> github.sha (portable git, works on both platforms)

Also adds detect-changes.debug output so future no-op passes show WHY
the workflow decided to skip, and the first real run on Gitea will
confirm the diff detection is working.

Closes #141 (followup: root-cause fix still TBD — failure logs
inaccessible via Gitea Actions API).
2026-05-10 01:11:45 +00:00
c6e286e081 Merge pull request 'test(canvas): add component tests for Tooltip, Legend, TermsGate, ApprovalBanner' (#205) from test/canvas-component-tests into main 2026-05-10 00:47:28 +00:00
Molecule AI Core Platform Lead
4524f4aeb1 Merge remote-tracking branch 'origin/main' into trig-205 2026-05-10 00:46:56 +00:00
Molecule AI Core Platform Lead
3549a38d10 trigger: re-run sop-tier-check 2026-05-10 00:46:33 +00:00
cdc5522b3e docs(canvas-audit): record PR #205 test coverage addition
Adds a note to the audit doc footer tracking the new component tests
(PR #205: Tooltip, Legend, TermsGate, ApprovalBanner) and bumps the
updated date.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 00:45:47 +00:00
29c6be81bd test(canvas): add component tests for Tooltip, Legend, TermsGate, ApprovalBanner
Adds vitest tests for 4 previously untested canvas components:

- Tooltip.test.tsx (17 tests): portal rendering, 400ms hover delay,
  keyboard focus reveal, Esc dismiss (WCAG 1.4.13), aria-describedby
- Legend.test.tsx (10 tests): open/closed state, localStorage persistence,
  palette-offset positioning, status/tier/comm items, aria labels
- TermsGate.test.tsx (14 tests): loading→accepted, pending modal (WCAG
  2.4.3 focus), accept flow, error state, children always rendered
- ApprovalBanner.test.tsx (15 tests): empty state, approval card render,
  polling cleanup, approve/deny decisions, toast notifications, error recovery

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 00:44:45 +00:00
4725606560 Merge pull request 'feat(plugins): plugin drift detector + queue + admin apply endpoint (#123)' (#204) from feat/plugin-drift-queue-123 into main 2026-05-10 00:43:17 +00:00
Molecule AI Core Platform Lead
e97a6b43d8 Merge remote-tracking branch 'origin/main' into trig-204 2026-05-10 00:42:57 +00:00
Molecule AI Core Platform Lead
5475940ebe trigger: re-run sop-tier-check 2026-05-10 00:42:39 +00:00
Molecule AI Core Platform Lead
cf09233202 Merge remote-tracking branch 'origin/main' into trig-204 2026-05-10 00:42:38 +00:00
ada1008012 feat(plugins): plugin drift detector + queue + admin apply endpoint (#123)
## Summary

Adds the version-subscription drift detection and operator-apply workflow for
per-workspace plugin tracking (core#113).

## Components

**Migration** (`20260510000000_plugin_drift_queue`):
- Adds `installed_sha` column to `workspace_plugins` — records the commit SHA
  installed so the drift sweeper can compare against upstream.
- Creates `plugin_update_queue` table with status: pending | applied | dismissed.
- Adds partial unique index to prevent duplicate pending rows per
  (workspace_id, plugin_name).

**GithubResolver** (`github.go`):
- `LastFetchSHA` field + `LastSHA()` getter — populated by `Fetch` after a
  successful shallow clone (captured before `.git` is stripped). Used by the
  install pipeline to seed `installed_sha`.
- `ResolveRef(ctx, spec)` method — resolves a plugin spec to its full commit
  SHA using `git fetch --depth=1 + git rev-parse`. Used by the drift sweeper
  to get the current upstream SHA for a tracked ref (tag:vX.Y.Z, tag:latest,
  sha:…, or bare branch).

**Drift sweeper** (`plugins/drift_sweeper.go`):
- Periodic sweep every 1h: SELECTs rows where `tracked_ref != 'none' AND
  installed_sha IS NOT NULL`, resolves upstream SHA, queues drift if different.
- `ListPendingUpdates()` — reads pending queue rows for the admin endpoint.
- `ApplyDriftUpdate()` — marks entry applied (idempotent).
- ctx.Err() guard on ticker arm to avoid post-shutdown work.

**Install pipeline** (`plugins_install_pipeline.go`, `plugins_tracking.go`,
`plugins_install.go`):
- `stageResult.InstalledSHA` field — carries the SHA from Fetch to the DB.
- `recordWorkspacePluginInstall` now accepts and stores `installed_sha`.
- `deleteWorkspacePluginRow` — removes tracking row on uninstall so a stale
  SHA doesn't prevent the next install from creating a fresh row.
- Both Docker and EIC uninstall paths call `deleteWorkspacePluginRow`.

**Admin endpoints** (`handlers/admin_plugin_drift.go`):
- `GET /admin/plugin-updates-pending` — list all pending drift entries.
- `POST /admin/plugin-updates/:id/apply` — re-installs plugin from source_raw
  (re-fetching the same tracked ref), records the new SHA, marks entry applied,
  triggers workspace restart. Idempotent (already-applied returns 200).

**Router wiring** (`router.go`, `cmd/server/main.go`):
- Plugin registry created in main.go and shared between PluginsHandler and drift
  sweeper.
- `router.Setup` accepts optional `pluginResolver` param.
- `PluginsHandler.Sources()` export for the sweeper wiring pattern.

## Tests

- `plugins/github_test.go` — `ResolveRef` coverage (invalid spec, git error,
  not-found mapping, no-panic for all ref shapes).
- `plugins/drift_sweeper_test.go` — `ResolveRef` happy path, stub resolver
  interface compliance.
- `handlers/admin_plugin_drift_test.go` — ListPending (empty, non-empty, DB
  error), Apply (not found, already applied, already dismissed, workspace_plugins
  missing).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 00:39:50 +00:00
96a9868bf5 Merge pull request 'test(canvas): add StatusDot component tests' (#203) from test/canvas-status-dot into main 2026-05-10 00:33:12 +00:00
Molecule AI Core Platform Lead
6f564c92d3 Merge remote-tracking branch 'origin/main' into trig-203 2026-05-10 00:32:45 +00:00
Molecule AI Core Platform Lead
3c1c08fa2a trigger: re-run sop-tier-check 2026-05-10 00:32:26 +00:00
45113fab6b Merge pull request 'docs(canvas): clean up Known Issues section — remove duplicate + fix pre-commit action' (#202) from docs/fix-audit-known-issues into main 2026-05-10 00:27:50 +00:00
Molecule AI Core Platform Lead
bd5faf1ff5 trigger: re-run sop-tier-check 2026-05-10 00:26:38 +00:00
858f996196 test(canvas): add StatusDot component tests
Add 10 tests for StatusDot covering:
- All known STATUS_CONFIG statuses (online, offline, degraded,
  failed, paused, not_configured, provisioning)
- Correct color class applied per status
- Glow class applied when declared in STATUS_CONFIG
- motion-safe:animate-pulse on provisioning status
- Fallback to bg-zinc-500 for unknown status
- size prop (sm/md) applies correct Tailwind dimension class
- aria-hidden="true" for accessibility tree isolation

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 00:25:46 +00:00
65af68d13b docs(canvas): clean up Known Issues section — remove duplicate entry + fix pre-commit action line
- Pre-commit Hook: moved stray "Action:" line inside the section (was appended to
  WCAG entry below it after a rebase conflict resolution)
- Removed duplicate text-ink-soft WCAG AA entry (lines 62-68 were a rebase artifact)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 00:23:18 +00:00
fedfb49c0a Merge pull request 'docs(canvas): correct Canvas Controls section — Controls keyboard-accessible, MiniMap present' (#201) from docs/fix-minimap-audit into main 2026-05-10 00:13:32 +00:00
Molecule AI Core Platform Lead
ef40701a78 trigger: re-run sop-tier-check 2026-05-10 00:13:18 +00:00
26946367a0 docs(canvas): correct Canvas Controls section — Controls keyboard-accessible, MiniMap present
- Controls: all three buttons (zoom in/out/fit) have aria-label attributes from
  React Flow; verified from @xyflow/react source (index.mjs:4453). Removed "verify
  if keyboard accessible" caveat.
- MiniMap: actually present in Canvas.tsx (rendered at line 310). The old audit
  note "not present (mocked as null in tests)" referred to the minimap being absent
  from unit test renders, not from production. Updated to reflect actual presence
  and status-coloring behavior.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 00:12:08 +00:00
36dcf076d2 Merge pull request 'fix(canvas): correct KeyboardShortcutsDialog + fix min-clamp test expectations' (#200) from fix/keyboard-shortcuts-dialog-update into main 2026-05-10 00:08:52 +00:00
Molecule AI Core Platform Lead
ad9e11d8c4 Merge remote-tracking branch 'origin/main' into trig-200 2026-05-10 00:08:44 +00:00
Molecule AI Core Platform Lead
e8eeb5ff8e trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-10 00:08:28 +00:00
78890703f5 Merge pull request 'ci(docker): pin base image digests in all Dockerfiles' (#199) from ci/pin-dockerfile-base-digests into main 2026-05-10 00:03:28 +00:00
Molecule AI Core Platform Lead
6ab1184c15 Merge remote-tracking branch 'origin/main' into trig-199 2026-05-10 00:03:03 +00:00
Molecule AI Core Platform Lead
6029ccb964 trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-10 00:02:43 +00:00
Molecule AI Core Platform Lead
306262a315 Merge remote-tracking branch 'origin/main' into trig-199 2026-05-10 00:02:43 +00:00
4baf60f01d fix(canvas): correct KeyboardShortcutsDialog descriptions + fix min-clamp test expectations
- Fix arrow-key nudge description: was "20px/100px" (wrong), now "10px/50px" (matches useKeyboardShortcuts)
- Add Cmd/Ctrl+Arrow resize shortcut row to dialog (missing since PR #192)
- Fix 3 tests in useKeyboardShortcuts.test.tsx that asserted shrink below min dimensions:
  "resizes height down" expected height:100, clamped to 110 (node starts at minHeight)
  "resizes width down" expected width:200, clamped to 210 (node starts at minWidth)
  "2px step with Shift" expected height:108, clamped to 110 (minHeight wins)
  All three tests updated to assert clamped values with explanatory comments.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 00:01:40 +00:00
1492b40b38 ci(docker): pin base image digests in all Dockerfiles
Pins all FROM image tags to exact SHA256 digests for reproducible
builds. Without digest pinning, a registry push of a new image to the
same tag can silently change the layer content between builds — a
supply-chain risk especially for prod-deployed images.

Pinned images (7 Dockerfiles):
- golang:1.25-alpine → sha256:c4ea15b... (workspace-server/Dockerfile,
  Dockerfile.dev, Dockerfile.tenant, tests/harness/cp-stub/Dockerfile)
- alpine:3.20 → sha256:c64c687c... (workspace-server/Dockerfile,
  tests/harness/cp-stub/Dockerfile)
- node:20-alpine → sha256:afdf982... (workspace-server/Dockerfile.tenant)
- node:22-alpine → sha256:cb15fca... (canvas/Dockerfile)
- python:3.11-slim → sha256:e78299e... (workspace/Dockerfile)
- nginx:1.27-alpine → sha256:62223d6... (tests/harness/cf-proxy/Dockerfile)

Note: docker-compose.yml service images (postgres, redis, clickhouse,
litellm, ollama) are intentionally left on major-version tags — those
are runtime-pulled and updated regularly for local-dev ergonomics.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 23:56:39 +00:00
c0ee500e47 Merge pull request 'fix(canvas): WCAG AA contrast fix + KeyboardShortcutsDialog improvements' (#198) from fix/ink-soft-wcag-contrast into main 2026-05-09 23:48:38 +00:00
Molecule AI Core Platform Lead
7b60008d33 Merge remote-tracking branch 'origin/main' into trig-198 2026-05-09 23:48:27 +00:00
Molecule AI Core Platform Lead
be2de6351f trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 23:48:09 +00:00
Molecule AI Core Platform Lead
96ae24a83c Merge remote-tracking branch 'origin/main' into trig-198 2026-05-09 23:48:09 +00:00
0ba16cded6 Merge pull request 'docs(canvas): update audit status — all accessibility gaps now closed' (#197) from docs/update-canvas-audit-status into main 2026-05-09 23:45:13 +00:00
Molecule AI Core Platform Lead
aff8831817 Merge remote-tracking branch 'origin/main' into trig-197 2026-05-09 23:44:38 +00:00
Molecule AI Core Platform Lead
fb3ab76456 trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 23:44:22 +00:00
Molecule AI Core Platform Lead
e541889150 Merge remote-tracking branch 'origin/main' into trig-197 2026-05-09 23:44:21 +00:00
bc1d602883 Merge pull request 'test(canvas): add tests for Cmd/Ctrl+Arrow keyboard node resize' (#196) from test/canvas-keyboard-resize-tests into main 2026-05-09 23:44:16 +00:00
Molecule AI Core Platform Lead
6b73c7abc7 Merge remote-tracking branch 'origin/main' into trig-196 2026-05-09 23:44:07 +00:00
Molecule AI Core Platform Lead
0722bf3df8 trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 23:43:51 +00:00
2da036204c test(canvas): add tests for Cmd/Ctrl+Arrow keyboard node resize
Add 10 tests covering the Cmd/Ctrl+Arrow resize shortcut:
- ArrowUp/Down resizes height (−/+10px)
- ArrowLeft/Right resizes width (−/+10px)
- Shift modifier uses 2px step for fine control
- min-height constraint respected when shrinking
- Guard: no-op when no node selected
- Guard: skipped when modal dialog is open
- Plain arrow keys (no modifier) fire moveNode instead
- Alt+Arrow is skipped (not a resize combo)

Also extends the mock store state with `onNodesChange` and node
`width`/`height` fields needed for the resize tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 23:41:29 +00:00
e53cbeae2f docs(canvas): mark keyboard node drag as done in audit
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 23:36:36 +00:00
cc2dbb1f3d Merge pull request 'fix(test): poll error counter to 0 before asserting in RecordsMetricsOnSuccess' (#194) from infra/fix-issue-22-sweeper-test-flaky into main 2026-05-09 23:29:45 +00:00
Molecule AI Core Platform Lead
0de7771a72 trigger: re-run sop-tier-check after core-lead approval + main sync 2026-05-09 23:29:29 +00:00
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