Skip to content

fix(harness): complete Studio onboarding and project continuity - #818

Closed
ynadge wants to merge 4 commits into
conductor/sap-3152-unified-agent-cutoverfrom
fix/studio-onboarding-followups
Closed

fix(harness): complete Studio onboarding and project continuity#818
ynadge wants to merge 4 commits into
conductor/sap-3152-unified-agent-cutoverfrom
fix/studio-onboarding-followups

Conversation

@ynadge

@ynadge ynadge commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Primary change type

  • Bug fix

Problem and motivation

Follow-up fixes from testing a fresh, empty Studio after the Agent Map rework:

  • The create-agent composer sent internal scaffolding instructions through terminal input and could leave the user's first request waiting for another Enter around CLI onboarding/trust screens.
  • Project-map upkeep and project-tool discovery lacked actionable guidance.
  • Agents scaffolded by the same coding conversation into sibling folders were not immediately discovered or associated with their creating Studio project. They could appear under "Outside your projects folder"; selecting them lost the project's existing conversation.

Summary and scope

Three focused commits complete the onboarding-to-multi-agent-project path:

  • Prepare scaffolding and ordered attachments server-side before launching the coding agent. Deliver the plain user task as a protected positional launch argument to Claude Code or Codex; never replay it on resume.
  • Keep internal instructions in startup context, recognize current Claude trust prompts, retain project identity during asynchronous preparation, and preserve composer drafts on errors.
  • Teach initial map creation and meaningful artifact/contract updates, with read → validate → propose → read verification. Keep runtime capabilities and agent authoring primary, with build plans and writable delegation optional when useful.
  • Document all nine project MCP tools, exact-source references, retry identities, plan rebasing, brief refresh, shared-filesystem delegation boundaries, and kickoff versus completed-work semantics.
  • Correct bundled orientation and upgrade only the exact known legacy served-prompt revision at materialization. Custom/newer remote prompts remain unchanged.
  • Register successful, authenticated scaffold completions under the creating session's durable project before scanning their exact directories. Persist explicit ownership independently of physical nesting and observe those directories for subsequent changes.
  • Recover previously recorded successful creations on startup. Reject failed/malformed results, stale or foreign session authority, path mismatches, and ownership conflicts; do not infer ownership from sibling location alone.
  • Use the same published membership for sidebar Project/Group grouping, selection, closed-project visibility, and session scope. Selecting an associated sibling preserves the original conversation; explicitly starting a session uses the original project root.
  • Add harness patch release notes and regression coverage.

No files are moved, shared parent directories claimed as project roots, or extra conversations created automatically. No changes to previous PRs, coworkers' branches, deployed backend prompts, or the local-run working-directory behavior investigated during testing. No visual/style redesign.

Related work

Requested follow-up bug fixes from the local onboarding test; no separate Linear issue.

Stacked on #811 (conductor/sap-3152-unified-agent-cutover), rather than duplicating the unmerged Agent Map stack in a diff against main.

Merge coordination: #814 and #815 also edit the bundled Studio prompt and digest pin. Preserve their newer runtime/authoring content when reconciling, and synchronize the backend served copy/pin before publishing. This PR does not deploy or modify that backend copy.

Validation

Fresh checks on the PR worktree at 3acd6af (2026-09-05). Commands run from packages/harness unless noted:

node node_modules/vitest/vitest.mjs run <34 suites listed below> --maxWorkers=2 --silent — 897 passed
node node_modules/typescript/bin/tsc --noEmit — passed
node node_modules/typescript/bin/tsc --noEmit -p web/tsconfig.json — passed
node ../../node_modules/eslint/bin/eslint.js src --ext .ts — passed
node node_modules/typescript/bin/tsc --project tsconfig.build.json — passed
node node_modules/vite/bin/vite.js build --config web/vite.config.ts — passed
git diff --check origin/conductor/sap-3152-unified-agent-cutover...HEAD — passed (repository root)

Existing Vite dynamic-import/chunk-size warnings remain; no failing checks in the commands above.

Exact targeted test command
node node_modules/vitest/vitest.mjs run \
  src/core/adapters/claude-code.test.ts \
  src/core/adapters/codex.test.ts \
  src/core/session-manager.test.ts \
  src/server/rest.test.ts \
  src/server/scaffold.test.ts \
  src/server/first-request.test.ts \
  web/src/lib/new-session-attachments.test.ts \
  web/src/lib/terminal-drop.test.ts \
  src/core/project-bootstrap.test.ts \
  src/profiles/default.test.ts \
  src/profiles/project-agent.test.ts \
  src/profiles/system-prompt-fetch.test.ts \
  src/core/inject/system-prompt.test.ts \
  src/server/served-system-prompt.test.ts \
  src/server/agent-map-mcp.test.ts \
  src/server/agent-map-mcp-wiring.test.ts \
  src/core/agent-brief-compiler.test.ts \
  src/core/build-plan-service.test.ts \
  src/core/agent-map-proposal-schema.test.ts \
  src/core/created-agent-registration.test.ts \
  src/core/studio-workspace-preferences.test.ts \
  src/server/created-agent-wiring.test.ts \
  src/server/studio-workspace-wiring.test.ts \
  src/server/workspace-rescan.test.ts \
  src/server/auto-bind-rescan.test.ts \
  src/server/ingest.test.ts \
  src/server/agent-map-auth-wiring.test.ts \
  src/server/agent-map.test.ts \
  src/server/project-bootstrap-outbox.test.ts \
  src/server/agent-move.test.ts \
  web/src/lib/project-tree.test.ts \
  web/src/lib/agent-map.test.ts \
  web/src/lib/session-scope.test.ts \
  web/src/lib/project-membership.test.ts \
  --maxWorkers=2 --silent

Earlier local verification on the same membership-fix source, before this publication:

  • All 14 project-map-navigation.spec.ts browser tests passed on the Mac, including sibling selection/reload with the same conversation, Group-axis membership, explicit Start from the original root, and hiding siblings when their project closes. The cloud run passed the new cases but hit page-loading failures in several older navigation cases; the complete Mac run passed.
  • Rebuilt and refreshed the user's existing Mac preview without resetting its data. Verified one original project, all three agents beneath it, the original active session/native CLI conversation, and an unchanged map. No extra session or user prompt was created.
  • All 51 changed files were byte-identical across the clean PR checkout and retained cloud/Mac test checkouts.
  • Earlier first-request testing passed 18 onboarding browser checks and confirmed a real Claude run accepted exactly one startup task after the trust screen.

Browser/manual checks were not repeated during this publication; the 34-suite run, typechecks, lint, and build above were. Prompt-delivery tests verify supplied instructions, not reliable model compliance.

Validation is scoped to the affected harness package; full-monorepo and packaged-Electron suites were not run in this resource-constrained cloud worktree. CI remains separate from these local results.

Tests and documentation

Regression coverage includes CLI arguments/resume behavior, attachment validation/order, scaffold guards, pending project scope, composer success/error behavior, all nine MCP tools, and served/bundled prompt delivery for Claude and Codex. New membership coverage includes authenticated ingest through websocket/state publication, restart recovery, targeted watching, invalid/foreign completions, stable ownership, grouping, and project-scoped conversation selection. Updated shared-build-plan documentation and added user-facing changesets. No screenshot attached: this retains the existing layout/styles and corrects discovery/grouping/navigation behavior, verified in browser tests and the live preview.

Compatibility and release impact

  • Breaking changes: none intended. New create-session fields are optional; existing project and resume paths remain supported.
  • Successfully scaffolded sibling agents now appear under their creating Studio project. Private persisted creation evidence extends the existing binding store; public opaque project/agent IDs are preserved.
  • Changesets: added @sapiom/harness patch release notes for onboarding and created-agent membership.

Security

  • No secrets, credentials, private data, or unsanitized logs included.
  • No suspected vulnerability is publicly disclosed.

AI assistance

  • AI assistance used: Codex implemented and self-reviewed the changes, inspected the scoped diffs, and ran the checks above. No separate review subsessions were launched.

Checklist

  • Read CONTRIBUTING.md; these are requested follow-up bug fixes.
  • Scoped to Studio onboarding and continuity of the resulting project.
  • Tests and documentation updated.
  • Relevant package build, typecheck, lint, and tests passed; broader limits documented.
  • Changesets added.
  • Submitted changes are understood and explained.

@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Review — PR #818 (round 1)

🔒 Confidentiality: no leak found. The changeset, docs/shared-build-plan.md, the prompt
edits and profiles/fixtures/legacy-system-prompt.md name only Sapiom, Claude Code, Codex and
docs.sapiom.ai — all already-public vocabulary, and the fixture is a verbatim copy of a prompt
this package already shipped.


1. A failed first request leaves an orphaned, npm-installed project behind

packages/harness/src/server/first-request.ts:60-66

prepareFirstRequest scaffolds first, then materializes attachments; the rollback deliberately
unlinks only the UUID uploads. But by then scaffoldAgentProject has copied the template, run
npm install, and onScaffolded has already broadcast workflows.changed.

Failure scenario: user pastes a clipboard image, writeAttachment fails (ENOSPC, EACCES, or the
wx collision path). The create rejects, the composer shows an error and keeps the draft — and a
fully installed, empty project is now in the rail. On retry uniqueProjectDir (App.tsx:2158)
sees that new workflow and picks <slug>-2, so every failed attempt permanently adds another
stray project the user never asked for. scaffold.ts already has removeFailedScaffold for the
scaffold-threw case; the post-scaffold failure path needs the same treatment (or the error must
name the folder to reuse).

2. Changeset is patch for a public API addition

.changeset/studio-onboarding-followups.md:2

src/index.ts:6 is export * from "./shared/types.js", so this PR adds published contract:
CreateSessionRequest.{initialPrompt,initialAttachments,scaffold}, LaunchOpts.initialPrompt,
and the new CREATE_SESSION_JSON_LIMIT_BYTES constant. Backward-compatible additions are a
minor, not a patch.

The changeset body is also missing the one thing an embedder needs: adapters is a public
HarnessServerOptions field, and any host supplying its own HarnessAdapter now silently drops
the user's first turn unless it reads the new LaunchOpts.initialPrompt. That belongs in the
release note with the field name.

3. The first request has no recovery path if the CLI never consumes it

packages/harness/src/shared/types.ts:334, web/src/App.tsx:2187-2200

initialPrompt is by design never persisted and never replayed on resume/restart, and this PR
deletes the held-prompt → readiness → inject → toast fallback the composer used to have. So the
only delivery attempt is one positional argv on one spawn. If claude/codex exits during the
trust/login screen, or a custom adapter ignores the field (see #2), the typed request is gone —
no error, no draft, nothing in sessions.json to resume from. The e2e suite asserts the argv is
present (new-session-composer.spec.ts:715), not that anything consumed it, and the PR body
concedes the vendor-compliance check was manual and not rerun. At minimum, keep the composer
draft until the session reports ready, so the user can resend rather than retype.

Nit

  • rest.ts:471 puts POST /sessions on the same 30-req/min attachmentUploadRateLimiter
    instance as POST /sessions/:id/attachments. A user who drags ~30 files into one session and
    then starts a new one gets a 429 on the create. Give the create route its own bucket.

HYGIENE (advisory — not a gate)

  1. Dead client-side twin of the new server path. web/src/lib/new-session-attachments.ts:162
    materializeAttachments now has no production caller — App.tsx dropped its import and only
    new-session-attachments.test.ts still exercises it. Delete it (and its test block) so the
    client and server materialization recipes cannot drift.
  2. Two recipes for "idea → new project". The composer now goes through
    CreateSessionRequest.scaffold server-side, while handleScaffoldSession (App.tsx:1863,
    wired at App.tsx:3288 via WorkflowsRail's onScaffold) still injects the English
    composerScaffoldPrompt (web/src/lib/templates.ts:302) into the PTY through
    sendPromptWhenReady. Every future change to first-request delivery now has to be made in
    both. If the rail door is meant to keep the old behavior, say so where sendScaffoldPrompt is
    defined.

Verdict: request changes — #1 is a user-visible data-litter bug with an existing helper to
fix it, and #2 is a one-line changeset correction before publish; #3 is a design gap worth a
decision, not necessarily a blocker.

Register authenticated scaffold completions before targeted discovery and persist their creating project. Recover prior creations from local events and preserve project-scoped navigation and conversations for sibling directories.
@ynadge ynadge changed the title fix(harness): complete onboarding handoff and project guidance fix(harness): complete Studio onboarding and project continuity Sep 5, 2026
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Review — PR #818 (round 2, follow-up)

Delta since c201c3d: one commit, 3acd6af (created-agent membership). No round-1 finding
was addressed. 🔒 Confidentiality: the new changeset and the MockApi fixture are clean
(acme-app/demo placeholders only).

New findings

1. Creation ownership permanently outranks a project rooted at the agent's own folder.
packages/harness/src/core/studio-workspace-preferences.ts:215-225

The new eligible filter is unconditional: once a binding has createdBySessionId, any
other project's reconcile drops that workflow, including a project whose root is the
agent directory. Scenario: scaffold /work/reviewer beside project /work/app, then "Open
as project" on /work/reviewer. Its reconcile excludes the workflow, so no binding to the
new project is issued; agentBelongsToProjectRoot (web/src/lib/project-tree.ts:7-21) then
returns false for its own root and the new project renders empty. Worse if the creating
project is closed: WorkflowsRail.tsx:699-709 hides the agent outright (owners.length === 0 + binding to a known project ⇒ false), so it is visible nowhere. createdBySessionId
is only cleared on an explicit disk move (:525), so there is no in-app escape. Physical
containment in a root that equals the agent path should win, or the rail needs a fallback.

2. recover() blocks the HTTP port. packages/harness/src/server/index.ts:4552-4557

await createdAgentRegistration.recover(...) runs before httpServer.listen, replaying
every tool.call event for every session and then doing one sequential projectForPath +
watch + scan per persisted created agent. No timeout; a slow/hung FS scan means Studio
never opens its port. The repo's own pattern is the opposite — see the
afterListenBeforeRecovery hook at :4573. Move it after listen and broadcast when done
(scan() already publishes workflows.changed).

Not fixed from round 1

  • cleanup HTTP SDKs #1 orphaned scaffolded project on post-scaffold attachment failure — first-request.ts untouched.
  • update SDKs to use payment protocol data #2 .changeset/studio-onboarding-followups.md still patch despite new exported types; no LaunchOpts.initialPrompt note for embedders. The new changeset is also patch for a membership behavior change.
  • langchain SDK config cleanup #3 no recovery path if the CLI never consumes initialPrompt.
  • Nit: POST /sessions still shares the attachment rate-limit bucket.
  • Hygiene 1 & 2 (dead materializeAttachments, duplicate scaffold-prompt path) unchanged.

Nothing in round 1 appears to have been wrong.

Verdict: request changes — finding 1 is a user-visible dead end, and the round-1 changeset
level still has to be corrected before publish.

ynadge commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by the maintainer-authorized 15-part Agent Map review stack. This PR is closed without merging; its branch and review history remain preserved.

Replacement increments:

The complete testing branch remains fix/studio-onboarding-followups. Full stack: #819 through #834. Final hosted-review corrections and Mac journey validation are continuing on those same replacement PRs.

@ynadge ynadge closed this Sep 5, 2026
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.

1 participant