Skip to content

feat(web): Studio Builder PR-3 — connected mode#2051

Open
seanrobertwright wants to merge 2 commits into
coleam00:devfrom
seanrobertwright:feat/studio-builder-pr3-connected-mode
Open

feat(web): Studio Builder PR-3 — connected mode#2051
seanrobertwright wants to merge 2 commits into
coleam00:devfrom
seanrobertwright:feat/studio-builder-pr3-connected-mode

Conversation

@seanrobertwright

@seanrobertwright seanrobertwright commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Problem: The PR-2 builder could only edit throwaway fixtures — no way to load, save, create, rename, or delete a real workflow from the console UI.
  • Why it matters: Authors can now build and maintain workflow YAML visually instead of hand-editing files, completing M1 of the Archon Studio integration.
  • What changed: A connected route (/console/builder[/:name]) that loads/saves real workflows via the existing CRUD endpoints, a project picker, explicit Save with a dirty + nav guard, full create/rename/delete, server-tier validation surfaced into the issue panel, and bundled→Save-as.
  • What did NOT change (scope boundary): No server changes (reuses existing GET/PUT/DELETE /api/workflows/:name, POST /api/workflows/validate, GET /api/commands untouched), no DB, no other package, no production /workflows/builder route. BuilderPage stays a controlled component — its only change is an additive extraIssues prop.

UX Journey

Before

User                    Builder (/console/builder)
────                    ──────────────────────────
opens builder ────────▶ seeds BuilderPage from a FIXTURE (switcher)
edits nodes ──────────▶ in-memory only; header says "load/save lands next milestone"
(no way to persist) ──x  nothing reaches disk

After

User                    BuilderConnected (/console/builder[/:name])
────                    ───────────────────────────────────────────
picks project ────────▶ [resolves cwd; persisted + ?project= deep-link]
opens workflow ───────▶ [loadWorkflow(name,cwd) -> fromWorkflowDefinition]
edits nodes ──────────▶ dirty dot; import+client issues in IssueList
clicks Save ──────────▶ [client-validate -> validateWorkflow -> PUT -> invalidate]
                        [server 400 detail surfaces as a source:'server' issue]
New / Rename / Delete ▶ [create-on-save / new-then-old rename / guarded delete]
bundled workflow ─────▶ [read-only banner; "Save as" writes a project override]
navigates away dirty ─▶ [confirm prompt]; reload dirty -> [beforeunload prompt]

Architecture Diagram

After

ConsoleApp routes
  └─[~] /console/builder[/:name] ── [+] BuilderConnected.tsx
                                       ├── useBuilderProject (localStorage + ?project=)
                                       ├── skills/workflows: load/save/delete/validate  ──> existing /api/workflows*
                                       ├── [+] connect/save-logic.ts (pure: issues, planRename, name validation)
                                       ├── store/cache useEntity + invalidate ; [~] store/keys K.workflow(cwd,name)
                                       └─[~] BuilderPage (additive extraIssues prop) ── IssueList
  [-] BuilderRoute.tsx (fixture route deleted; fixture switcher already lives in PreviewPage)

Connection inventory:

From To Status Notes
ConsoleApp BuilderConnected new mounts builder + builder/:name
BuilderConnected skills/workflows new load/save/delete/validate verbs
skills/workflows /api/workflows* unchanged existing endpoints, no server change
BuilderConnected connect/save-logic new pure issue/rename/name logic
BuilderConnected BuilderPage modified additive extraIssues prop
ConsoleApp BuilderRoute removed fixture route deleted

Label Snapshot

  • Risk: risk: low
  • Size: size: M
  • Scope: web
  • Module: web:console-builder

Change Metadata

  • Change type: feature
  • Primary scope: web

Linked Issue

Validation Evidence (required)

bun run type-check        # exit 0 (all 10 packages)
bun run lint              # exit 0 (zero warnings)
bun run format:check      # exit 0
bun --filter @archon/web test   # 338 pass / 0 fail (incl. 19 new)
bun --filter @archon/web build  # exit 0
  • Evidence: re-validated after rebasing onto upstream/dev (59bbd00b) — type-check (0), format (0), web tests 338 pass / 0 fail, and the PR-3/console files lint clean. All gates green. bun run validate's only failure is a pre-existing, environment-specific Windows test in @archon/providers (pathKind > broken symlinkEPERM; symlink creation needs Developer Mode/admin). That package is untouched by this PR and the test passes on Linux CI.
  • Skipped: Level-4 manual steps (no DOM/browser test harness — a console house rule); the nav-guard UX and visual surface are manual gates.

Security Impact (required)

  • New permissions/capabilities? No
  • New external network calls? No (reuses existing workflow endpoints)
  • Secrets/tokens handling changed? No
  • File system access scope changed? No (writes go through the existing server-validated PUT, which validates cwd against registered codebases)

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Database migration needed? No

Human Verification (required)

  • Verified scenarios: type-check/lint/format/build/tests green; code-reviewed (1 HIGH race + 2 LOW items found and fixed, re-validated).
  • Edge cases checked (unit + reasoning): server 400 → source:'server' issue; blocking client errors gate Save; rename collision/no-op/invalid-name blocked; rename delete-fail → non-fatal warning; bundled Save-as; create-on-save flips to edit mode; controlled-select revert on cancelled nav-guard; beforeunload teardown.
  • What was not verified: live-server Level-4 manual walkthrough (no DOM harness).

Side Effects / Blast Radius (required)

  • Affected subsystems: packages/web/src/experiments/console/ only.
  • Potential unintended effects: none outside the console builder; saving normalizes YAML key order (lossless but not byte-identical — documented).
  • Guardrails: isolation ESLint guard, no-logging rule, 19 unit tests.

Rollback Plan (required)

  • Fast rollback: revert this single commit (af0ba60b); nothing outside the console experiment changes.
  • Feature flags: none (behind the /console/* experiment surface).
  • Observable failure symptoms: builder fails to load/save a workflow; issue panel shows a source:'server' error.

Risks and Mitigations

  • Risk: nav guard does not intercept the browser Back button or external ProjectRail clicks (the app is a non-data <BrowserRouter>, so useBlocker is unavailable).
    • Mitigation: beforeunload + confirm-on-intercept on the builder's own controls; documented as a known limitation; data-router migration is out of scope.
  • Risk: subfoldered workflows don't load via the single-name GET.
    • Mitigation: surfaced as a clear "not found → offer New" empty state; documented; matches PR-2's limitation.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Launched connected workflow builder routes at /console/builder and /console/builder/:name with deep-link editing.
    • Added project picker with persisted selection (URL ?project= sync) and full CRUD: New, Save, Save as (bundled read-only), Rename, Delete.
  • Bug Fixes
    • Improved workflow save validation and server error reporting, including merged/deduplicated issue display and stricter workflow-name checks.
    • Enhanced rename behavior to handle collisions/no-ops more reliably.
  • Tests
    • Added unit tests for save/rename logic and workflow URL building.
  • Documentation
    • Updated builder and console README plus added builder terminology glossary.

PR-3 of the Archon Studio integration. Replaces the fixture-backed builder
route with a connected route that loads, edits, creates, renames, and deletes
real workflow YAML through the existing workflow CRUD endpoints (no server
changes).

- BuilderConnected at /console/builder[/:name]: project picker (per-cwd
  discovery, persisted + ?project= deep-link), workflow open/New/Rename/Delete,
  explicit Save with a dirty indicator and beforeunload + confirm nav guard
- skills/workflows.ts: loadWorkflow/saveWorkflow/deleteWorkflow/validateWorkflow
  verbs + pure buildWorkflowPath/buildSavePath helpers
- connect/save-logic.ts: pure serverErrorToIssues/serverValidationToIssues/
  blockingErrors/planRename/isValidWorkflowName (mirrors server isValidCommandName)
- BuilderPage gains an additive extraIssues prop; import + server issues merge
  into the existing IssueList
- bundled workflows open read-only, Save-as writes a project override; filename
  (:name) and in-YAML name: stay in sync
- HttpError exposes bodySnippet; K.workflow(cwd,name) cache key
- 19 new unit tests (save-logic, workflows path builders)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a connected workflow-builder route with live project selection, workflow CRUD, save/rename/delete flows, validation issue merging, and route wiring that replaces the fixture-based builder route. Supporting changes add workflow API helpers, pure save logic, cache keys, and updated builder documentation.

Changes

Connected Builder Mode

Layer / File(s) Summary
Workflow API client, HTTP error detail, cache keys
packages/web/src/experiments/console/skills/workflows.ts, packages/web/src/experiments/console/skills/workflows.test.ts, packages/web/src/experiments/console/lib/http.ts, packages/web/src/experiments/console/store/keys.ts
Adds workflow CRUD types and helpers, URL path builders, HttpError.bodySnippet, and K.workflow; tests cover path encoding and source query behavior.
Save/rename pure logic and project hook
packages/web/src/experiments/console/builder/connect/save-logic.ts, packages/web/src/experiments/console/builder/connect/save-logic.test.ts, packages/web/src/experiments/console/builder/connect/use-builder-project.ts
Adds issue mapping, read-only/save-target rules, name validation, rename planning, and persisted project selection synced with ?project= and localStorage.
BuilderConnected route component
packages/web/src/experiments/console/builder/BuilderConnected.tsx
Loads project/workflow data, manages dirty state and editor identity, and implements save/delete/rename/new handlers with navigation guards and route-state transitions.
BuilderPage extraIssues integration
packages/web/src/experiments/console/builder/BuilderPage.tsx
Adds optional extraIssues and merges them with client validation issues before rendering IssueList.
Routing wiring and route removal
packages/web/src/experiments/console/ConsoleApp.tsx, packages/web/src/experiments/console/builder/BuilderRoute.tsx, packages/web/src/experiments/console/builder/CONTEXT.md
Routes /console/builder and /console/builder/:name to BuilderConnected, removes the old fixture route, and adds builder terminology context.
Documentation updates
packages/web/src/experiments/console/README.md, packages/web/src/experiments/console/builder/README.md
Updates console and builder README content for the connected-mode routes, persisted project preference, architecture split, and PR status text.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

Possibly related PRs

  • coleam00/Archon#1315: Introduces the 'global' workflow source and source-aware workflow handling that this PR’s save-target logic builds on.
  • coleam00/Archon#1557: Adds source-preserving workflow load/save behavior that aligns with the workflow CRUD helpers used here.
  • coleam00/Archon#1870: Extends the builder validation model and issue merging path that this PR consumes through extraIssues.

Suggested reviewers: coleam00, leex279

Poem
A builder wakes with routes anew,
Projects, saves, and renames too.
Fixtures fade; the live path leads,
With issues merged and guarded deeds.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: replacing the fixture-backed console builder with connected mode for the web app.
Description check ✅ Passed The PR description is largely complete and follows the template, but the Architecture Diagram section is missing a Before diagram.
Docstring Coverage ✅ Passed Docstring coverage is 82.35% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
packages/web/src/experiments/console/builder/BuilderConnected.tsx (1)

95-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Replace arbitrary UI values with design tokens.

This new UI introduces arbitrary typography/radius/width classes such as text-[12.5px], rounded-[8px], and max-w-[220px]. Please use existing Archon token utilities or add tokens first. As per coding guidelines, “Use brand tokens, not ad-hoc values; colors, gradients, surfaces, typography must come from design tokens or brand guide, not hard-coded hex values.”

Also applies to: 451-566, 592-607

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/src/experiments/console/builder/BuilderConnected.tsx` around
lines 95 - 96, Replace the ad-hoc Tailwind values in BuilderConnected and the
other affected sections with design-token-based classes or token utilities
instead of arbitrary typography/width/radius values like text-[12.5px],
rounded-[8px], and max-w-[220px]. Update the relevant UI wrappers and components
in BuilderConnected to use existing Archon design tokens, or add the missing
tokens first, and then switch the affected usages throughout the referenced
areas to those named tokens.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/web/src/experiments/console/builder/BuilderConnected.tsx`:
- Around line 443-444: The current not-found logic in BuilderConnected treats
any `loadView.error` as a missing workflow, so update the workflow-loading flow
to distinguish a 404 from other failures. Use the existing
`loadView`/`workflowOpen`/`notFound` branching in `BuilderConnected` to only
show the “No workflow named…” empty state when the error is truly not found, and
render the `workflowLoadError` path for 500/network/auth failures the same way
the list-load banner does. Also update the related render block around the
workflow load error handling so non-404 errors surface as load failures instead
of not-found.
- Around line 412-417: The empty project selection in onPickProject is being
treated as an empty string instead of no selection, which breaks the useCallback
flow and the confirmIfDirty/setProjectId/navigation contract. Normalize the
“Select a project…” option to undefined before calling setProjectId and building
the /console/builder URL, and make sure the project query param is omitted when
there is no selection rather than persisting project=.
- Around line 286-299: In doDelete within BuilderConnected, the busy state is
set before deleteWorkflow but is only cleared in the catch path, so a successful
delete leaves the shared BuilderConnected instance stuck busy. Update the
success flow after deleteWorkflow, invalidate calls, and navigate to reset busy
to false (or use a finally block that always clears it) while preserving the
existing error handling and references to deleteWorkflow, invalidate, and
navigate.

In `@packages/web/src/experiments/console/builder/connect/use-builder-project.ts`:
- Around line 35-48: useBuilderProject only seeds projectId from the initial
?project= value, so later URL navigation is ignored and can be overwritten by
BuilderConnected. Update the hook to react to search param changes from
useSearchParams and keep projectId in sync when the project query changes while
the route stays mounted, while still preserving the existing
setProjectId/writeStored behavior for explicit user-driven updates.

In `@packages/web/src/experiments/console/store/keys.ts`:
- Line 14: The K.workflow key is ambiguous because it concatenates cwd and name
with ":" while workflow names can also contain ":". Update the workflow key
generation in the K.workflow helper to use an unambiguous encoding or delimiter
scheme, and make sure the save-logic flow in BuilderConnected still produces and
consumes the same key shape so distinct (cwd, name) pairs cannot collide.

---

Nitpick comments:
In `@packages/web/src/experiments/console/builder/BuilderConnected.tsx`:
- Around line 95-96: Replace the ad-hoc Tailwind values in BuilderConnected and
the other affected sections with design-token-based classes or token utilities
instead of arbitrary typography/width/radius values like text-[12.5px],
rounded-[8px], and max-w-[220px]. Update the relevant UI wrappers and components
in BuilderConnected to use existing Archon design tokens, or add the missing
tokens first, and then switch the affected usages throughout the referenced
areas to those named tokens.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5eee84ed-d74e-47d9-acf7-11700e13806d

📥 Commits

Reviewing files that changed from the base of the PR and between 59bbd00 and 835f596.

📒 Files selected for processing (14)
  • packages/web/src/experiments/console/ConsoleApp.tsx
  • packages/web/src/experiments/console/README.md
  • packages/web/src/experiments/console/builder/BuilderConnected.tsx
  • packages/web/src/experiments/console/builder/BuilderPage.tsx
  • packages/web/src/experiments/console/builder/BuilderRoute.tsx
  • packages/web/src/experiments/console/builder/CONTEXT.md
  • packages/web/src/experiments/console/builder/README.md
  • packages/web/src/experiments/console/builder/connect/save-logic.test.ts
  • packages/web/src/experiments/console/builder/connect/save-logic.ts
  • packages/web/src/experiments/console/builder/connect/use-builder-project.ts
  • packages/web/src/experiments/console/lib/http.ts
  • packages/web/src/experiments/console/skills/workflows.test.ts
  • packages/web/src/experiments/console/skills/workflows.ts
  • packages/web/src/experiments/console/store/keys.ts
💤 Files with no reviewable changes (1)
  • packages/web/src/experiments/console/builder/BuilderRoute.tsx

Comment thread packages/web/src/experiments/console/builder/BuilderConnected.tsx
Comment thread packages/web/src/experiments/console/builder/BuilderConnected.tsx
Comment thread packages/web/src/experiments/console/builder/BuilderConnected.tsx Outdated
Comment thread packages/web/src/experiments/console/store/keys.ts Outdated
@seanrobertwright

Copy link
Copy Markdown
Contributor Author

PR Review Summary — multi-agent (7 agents)

7 specialized agents reviewed the diff (upstream/dev...HEAD, 14 files). Advisory only — no files modified. Suite is green (522 pass / 0 fail); type-check, format, and the console-subtree lint all pass.

Critical Issues (0)

None. No correctness-blocking or security issues; isolation guard, no-console.* rule, and explicit-return-type rules are all clean.

Important Issues (2 — recommend fixing before merge)

Agent Issue Location
silent-failure-hunter · type-design validateWorkflow returning { valid:false } with empty/absent errors calls setServerIssues([]) → panel silently clears and Save/Rename re-enables with no explanation (infinite "why won't it save?" loop). Latent today (the server always populates errors), but the type permits it. Fix: emit a fallback issue when errors is empty and tighten ValidateWorkflowResponse to a discriminated union ({valid:true} | {valid:false; errors: string[]}) to drop the ?? []. BuilderConnected.tsx:259 (doSave) & :328 (doRename); skills/workflows.ts:111
silent-failure-hunter All loadWorkflow errors (500 / 403 / network drop — not just 404) render the "No workflow named X was found … Create a new workflow" state. On a transient server error for a workflow that exists, this misleads and the recovery action invites a duplicate. Fix: gate notFound on loadView.error instanceof HttpError && status === 404; show a distinct "failed to load" state otherwise. BuilderConnected.tsx:444, :578

Suggestions (nice to have)

Agent Suggestion Location
type-design WorkflowSource is declared twice (silent-divergence risk) — re-export from primitives/workflow.ts instead. skills/workflows.ts:92
silent-failure · comment Rename-delete warning and the serverErrorToIssues empty-body fallback both say "Save failed" / leak raw HttpError.message (internal URL + JSON) for a DELETE. Reuse serverErrorToIssues for the detail; use a verb-neutral fallback. BuilderConnected.tsx:337; save-logic.ts:20
silent-failure · code-reviewer doDelete lacks finally { setBusy(false) }. Not a current bug (success path unmounts the component), but cheap hygiene against a future same-component navigation. BuilderConnected.tsx:289
pr-test-analyzer Extract the two pure functions still inside the component (errorToIssues, renameReasonMessage) into save-logic.ts so they're unit-testable; add tests for the empty-error body branch and planRename precedence ordering. BuilderConnected.tsx:68,80
code-simplifier Extract a clientIssue(rule,message) helper for the 4 near-identical instant-error blocks; collapse the redundant loadKey/loadView guards; reuse editorKey for the BuilderPage key (currently duplicated with a name vs name ?? '' divergence); inline single-use pid; truthiness check in serverErrorToIssues (~−18 lines). BuilderConnected.tsx:141,182,233,245…; save-logic.ts:23
type-design RenamePlan.steps is unused (decorative) — drive execution from it or drop it; annotate extraIssues as readonly Issue[]. save-logic.ts:85; BuilderPage.tsx:56
comment-analyzer openOptions comment examples are no-ops (real cases are create-mode/timing); "≤200-char truncated" is actually ≤203 (... suffix) in two places; drop/inline the 4 Spike #N refs (they point into gitignored .agents/plans/). BuilderConnected.tsx:432; lib/http.ts:21; save-logic.ts:15
code-reviewer Consolidate the split listWorkflows import into the existing block (cosmetic; below threshold). BuilderConnected.tsx:51

Documentation Issues

Agent Issue Location
docs-impact PR-2 (this layer) is stale now that PR-2 is merged → PR-2 (merged). builder/README.md:2
docs-impact Status section still says "In progress: the builder/ subtree" though PR-1→PR-3 are now shipped. README.md (Status)

(Confirmed correct: the new archon.console.builderProject localStorage key, the /console/builder[/:name] routes, and the full PR-3 specifics are all already documented.)

Strengths

  • code-reviewer: PASS — isolation guard, zero console.*, explicit return types all clean; the editorKey-ref reset guard is sound against the post-save stale-while-revalidate refetch; rename new-then-old atomicity is correct.
  • type-design: IssueId/makeIssue rated 9.75/10 (textbook branded type); RenamePlan 8.5; HttpError.bodySnippet 8; WorkflowSaveSource correctly encodes "bundled is never a write target."
  • comment-analyzer: GOOD — contract claims verified true: isValidWorkflowName is an exact parity mirror of the server's isValidCommandName, validateWorkflow genuinely returns HTTP 200 on invalid, and the subdir limitation is real.
  • pr-test-analyzer: extraction discipline is principled — every pure transform in save-logic.ts is tested at the right boundary.
  • silent-failure-hunter: 5 patterns confirmed safe (localStorage guards, res.text().catch, void doX() handlers, rename-warning surfacing).

Verdict

NEEDS FIXES — no blockers, but the two Important items (silent blocked-save on empty errors; load errors masquerading as "not found") are worth addressing before merge. Everything else is advisory polish.

Recommended Actions

  1. Add the empty-errors fallback + make ValidateWorkflowResponse a discriminated union (kills the silent-block in doSave/doRename).
  2. Distinguish 404 from other loadWorkflow errors; show a real error state instead of "not found → Create".
  3. Optional cleanups: re-export WorkflowSource; extract errorToIssues/renameReasonMessage (+ tests); clientIssue helper; doc nits.

🤖 Generated via /prp-review-agents (code-reviewer · docs-impact · pr-test-analyzer · comment-analyzer · silent-failure-hunter · type-design-analyzer · code-simplifier)

…nnected mode

CodeRabbit:
- doDelete clears busy via finally (toolbar no longer locks after a delete)
- normalize the empty "Select a project…" option to undefined (no bare project=
  shadowing the persisted default)
- distinguish 404 from 500/403/network on workflow load — non-404 shows a load
  error state instead of misleading "not found → Create"
- useBuilderProject follows later ?project= changes while mounted (back/forward)
- K.workflow encodes both parts (names may contain ':', avoiding key collisions)

Multi-agent review:
- validateWorkflow valid:false with empty errors surfaces a fallback issue (no
  silent blocked Save); ValidateWorkflowResponse is now a discriminated union
- re-export WorkflowSource from primitives/workflow (single source of truth)
- extract errorToIssues/renameReasonMessage/clientIssue/errorDetail/
  validationFailureToIssues into save-logic (pure + unit-tested)
- drop unused RenamePlan.steps; readonly extraIssues; verb-neutral HttpError
  fallback; rename-delete warning uses parsed detail; comment precision + doc
  staleness (PR-2 merged; Status) + drop gitignored Spike refs

Tests: +14 (352 web pass / 0 fail). type-check / format / console lint green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 1, 2026 13:56
@seanrobertwright

Copy link
Copy Markdown
Contributor Author

Follow-up: multi-agent review — actions taken

All findings from the 7-agent review above have been addressed in 583e587 (on top of 835f596). The two Important items and every actionable suggestion were applied; one simplification was intentionally skipped (justified below). Gates re-run green: repo-root type-check (0), format (0), console eslint --max-warnings 0 (0), web tests 352 pass / 0 fail (+14 new).

Important (both applied)

Finding Action
validateWorkflow valid:false with empty errors → silent panel clear / re-enabled Save Applied — new pure validationFailureToIssues() guarantees a fallback issue when errors is empty/absent; ValidateWorkflowResponse is now a discriminated union ({valid:true} | {valid:false; errors?}). Used in both doSave and doRename.
All loadWorkflow errors render "not found → Create" AppliednotFound now gates on HttpError.status === 404; non-404 failures render a distinct workflowLoadError state. (Same as CodeRabbit's Major finding.)

Suggestions (applied)

Finding Action
WorkflowSource duplicated (silent-divergence risk) Applied — re-exported from primitives/workflow (single source of truth).
Extract errorToIssues / renameReasonMessage for testability Applied — moved both to save-logic.ts; also extracted clientIssue, errorDetail, validationFailureToIssues.
Add empty-error-body + planRename precedence tests Applied — plus new tests for the extracted helpers (+14 unit tests).
clientIssue() helper for the 4 instant-error blocks Applied.
Reuse editorKey for the BuilderPage key; inline single-use pid; truthiness in serverErrorToIssues Applied.
RenamePlan.steps unused (false promise) Applied — dropped the field; success variant is now { ok: true } (tests updated).
readonly extraIssues Applied.
doDelete missing finally Applied — code-reviewer judged it a non-bug (navigation unmounts), but it's cheap hardening and CodeRabbit flagged it Major, so finally { setBusy(false) } it is.
Rename-delete warning / serverErrorToIssues "Save failed" fallback leaked raw HttpError.message and was verb-specific Applied — warning now uses errorDetail() (parsed server message); fallback is verb-neutral ("Request failed").
Comment nits: openOptions example, "≤200/203-char" precision (×2), editorKey null-branch, drop gitignored Spike #N refs Applied (all).
Consolidate split listWorkflows import Applied.
Docs: builder/README "PR-2 (this layer)"→"(merged)"; console/README "In progress" Status Applied.

Not applied (justified)

Finding Why not
code-simplifier: collapse the redundant loadKey / loadView guards using non-null assertions (cwd!, name!) Skipped. @typescript-eslint/no-non-null-assertion is error in this repo, so the assertions won't lint. The repeated cwd === undefined || name === undefined checks are load-bearing for TypeScript's control-flow narrowing (a plain idle boolean can't narrow the other vars), so the verbose form stays.

Thanks to the review agents — the silent-block and load-error items were the highest-value catches.

🤖 review-response generated with Claude Code

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds “connected mode” to the experimental Console workflow builder so it can load, validate, and persist real workflow YAMLs through existing /api/workflows* endpoints (plus project selection, explicit Save flow, and CRUD operations), completing the console-side wiring for the Archon Studio builder.

Changes:

  • Introduces a new connected builder route (/console/builder[/:name]) with project selection, load/save/rename/delete, dirty tracking, and a navigation guard.
  • Adds workflow CRUD/validation “skill” helpers (pure URL builders + request wrappers) and supporting pure save/rename/issue logic with unit tests.
  • Extends BuilderPage to accept additive extraIssues so server/import issues can be merged into the existing issue panel.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/web/src/experiments/console/store/keys.ts Adds a safer cache key for single-workflow entities by encoding (cwd, name).
packages/web/src/experiments/console/skills/workflows.ts Adds connected-mode workflow CRUD + validation helpers (build paths + load/save/delete/validate).
packages/web/src/experiments/console/skills/workflows.test.ts Unit tests for workflow path builder helpers.
packages/web/src/experiments/console/README.md Documents the new /console/builder routes and persisted builder project key.
packages/web/src/experiments/console/lib/http.ts Enhances HttpError to retain a truncated server body snippet for better UX error surfacing.
packages/web/src/experiments/console/ConsoleApp.tsx Switches routing from fixture-backed builder to BuilderConnected (and adds builder/:name).
packages/web/src/experiments/console/builder/README.md Updates builder documentation to reflect PR-3 connected mode shipping in the console experiment.
packages/web/src/experiments/console/builder/CONTEXT.md Adds a terminology glossary for the builder/Studio domain language.
packages/web/src/experiments/console/builder/connect/use-builder-project.ts Adds persisted project selection state (localStorage + ?project= deep-link seeding).
packages/web/src/experiments/console/builder/connect/save-logic.ts Adds pure helper logic for save/rename flows and mapping errors/validation into issues.
packages/web/src/experiments/console/builder/connect/save-logic.test.ts Unit tests for the pure save/rename/issue helpers.
packages/web/src/experiments/console/builder/BuilderRoute.tsx Removes the old fixture-backed builder route.
packages/web/src/experiments/console/builder/BuilderPage.tsx Adds extraIssues prop and merges it into the issue panel with dedupe-by-id.
packages/web/src/experiments/console/builder/BuilderConnected.tsx New connected route component implementing project picker, loading, CRUD, Save, dirty/nav guard, and issue surfacing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +30 to +41
export function serverErrorToIssues(err: HttpError): Issue[] {
let message = err.bodySnippet || `Request failed (${String(err.status)})`;
try {
const parsed = JSON.parse(err.bodySnippet) as { error?: string; detail?: string };
if (parsed.error) {
message = parsed.detail ? `${parsed.error}: ${parsed.detail}` : parsed.error;
}
} catch {
/* truncated/non-JSON body — keep the raw snippet */
}
return [serverIssue('server.validation', message)];
}
Comment on lines +75 to +78
export function errorToIssues(e: unknown, rule: string, fallback: string): Issue[] {
if (e instanceof HttpError) return serverErrorToIssues(e);
return [serverIssue(rule, e instanceof Error ? e.message : fallback)];
}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/web/src/experiments/console/builder/BuilderConnected.tsx (1)

279-330: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Rename is reachable on read-only bundled workflows — Delete guards readOnly, Rename doesn't.

The Rename button is gated only by !isCreateMode (Line 493), while Delete correctly requires !readOnly && !isCreateMode (Line 505). For an unsaved bundled workflow (effectiveSource === 'bundled', so readOnly === true), Rename is still clickable.

doRename then: saves the new name under saveTargetFor(effectiveSource) = 'project' (fine, acts like a scoped save-as), but attempts to delete the old bundled name also under source: 'project' — a project file with the old bundled name never existed, so this either surfaces a spurious "removing the old file failed... delete it manually" warning (misleading, since nothing needed deleting), or, if a stale existingNames/source cache masks an actual same-named project file, could delete an unrelated file. "Rename" has no coherent semantics for a shared, immutable bundled default — it should be excluded the same way Delete is.

🐛 Proposed fix
-    if (name === undefined || cwd === undefined || currentWorkflow === null) return;
+    if (name === undefined || cwd === undefined || currentWorkflow === null || readOnly) return;
-  }, [name, cwd, currentWorkflow, existingNames, effectiveSource, navigate, projectQuery]);
+  }, [name, cwd, currentWorkflow, existingNames, effectiveSource, readOnly, navigate, projectQuery]);
-            {!isCreateMode ? (
+            {!readOnly && !isCreateMode ? (
               <button
                 type="button"
                 disabled={busy}
                 onClick={(): void => {
                   void doRename();
                 }}

Also applies to: 493-504

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/src/experiments/console/builder/BuilderConnected.tsx` around
lines 279 - 330, The Rename action in BuilderConnected should be disabled for
read-only bundled workflows, matching the Delete guard. Update the rename button
gating and the doRename flow so it exits early when readOnly is true or
effectiveSource is bundled, using the existing readOnly/effectiveSource checks
alongside doRename, planRename, and saveTargetFor. This prevents saving a
misleading “rename” of an immutable bundled workflow and avoids the attempted
delete of the old bundled name.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/web/src/experiments/console/builder/BuilderConnected.tsx`:
- Around line 279-330: The Rename action in BuilderConnected should be disabled
for read-only bundled workflows, matching the Delete guard. Update the rename
button gating and the doRename flow so it exits early when readOnly is true or
effectiveSource is bundled, using the existing readOnly/effectiveSource checks
alongside doRename, planRename, and saveTargetFor. This prevents saving a
misleading “rename” of an immutable bundled workflow and avoids the attempted
delete of the old bundled name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b5b94e6f-078b-4957-8a83-7a1af54ab1e7

📥 Commits

Reviewing files that changed from the base of the PR and between 835f596 and 583e587.

📒 Files selected for processing (11)
  • packages/web/src/experiments/console/README.md
  • packages/web/src/experiments/console/builder/BuilderConnected.tsx
  • packages/web/src/experiments/console/builder/BuilderPage.tsx
  • packages/web/src/experiments/console/builder/README.md
  • packages/web/src/experiments/console/builder/connect/save-logic.test.ts
  • packages/web/src/experiments/console/builder/connect/save-logic.ts
  • packages/web/src/experiments/console/builder/connect/use-builder-project.ts
  • packages/web/src/experiments/console/lib/http.ts
  • packages/web/src/experiments/console/skills/workflows.test.ts
  • packages/web/src/experiments/console/skills/workflows.ts
  • packages/web/src/experiments/console/store/keys.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/web/src/experiments/console/builder/README.md
  • packages/web/src/experiments/console/README.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/web/src/experiments/console/skills/workflows.test.ts
  • packages/web/src/experiments/console/store/keys.ts
  • packages/web/src/experiments/console/lib/http.ts
  • packages/web/src/experiments/console/builder/BuilderPage.tsx
  • packages/web/src/experiments/console/skills/workflows.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants