feat: port upstream #2460 (combine workspace project stack) onto main-fluke#47
Merged
Merged
Conversation
…k) onto main-fluke Ports upstream PR AgentWrapper#2460 (7a87caa, ~3,500 lines) which adds the workspace-project-stack capability: a project can be a multi-repo workspace whose sessions materialise a root worktree plus one worktree per child repo, all on a shared branch, with SCM observation, lifecycle teardown, and a desktop import UI. Every conflict was resolved to KEEP main-fluke behavior while ADDING AgentWrapper#2460's capability. Key reconciliations: - manager.go spawn: kept AI branch-naming + per-project git-convention prefix + auto-named-collision retry; routed through AgentWrapper#2460's createSessionWorkspace and workspace-aware defaultSpawnBranch. Threaded main-fluke's --base (cfg.BaseBranch) override into createSessionWorkspace (upstream hardcoded the project default). - manager.go restore: kept main-fluke's RuntimeConfig ProjectID/Branch (feed tmux SessionNameFor) inside the extracted relaunchRestoredSession. - manager.go reconcileLive: kept main-fluke's idle-close-TTL fast-path; delegated the not-idle capture to AgentWrapper#2460's workspace-aware saveAndTeardownOne. - manager.go buildSystemPrompt: kept prompts.ConfidentialityGuard + effectiveBase (main-fluke prompts-package refactor), added AgentWrapper#2460's workspaceProjectPrompt injection; dropped upstream's duplicate local systemPromptGuard const and dead orchestratorPrompt. - observer.go: kept main-fluke's live-branch PR attribution AND subjectRepoForPR Owner/Name hydration; added AgentWrapper#2460's workspace child-repo scanning + multi-repo repoForTrackedPR selection. Composed the two (repoForTrackedPR selects, subjectRepoForPR hydrates) so upstream AgentWrapper#2510 is redundant; favor main-fluke's non-drop on no-match. - Sidebar.tsx: ported AgentWrapper#2460's full workspace-import UI flow (mode → folder+scan → agents) into main-fluke's inlined CreateProjectFlow; dropped the create-flow sr-only error span (duplicated error text, incompatible with upstream's multi-dialog tests). Kept the standalone CreateProjectFlow.tsx deleted (main-fluke inlined it). - _shell.tsx: kept main-fluke's throw on orchestrator-startup failure (upstream's setOrchestratorStartupError state is not wired in main-fluke). Not taken: AgentWrapper#2510 (Owner/Name hydration) — redundant, subjectRepoForPR already hydrates. AgentWrapper#2497 (Kimi/Qwen prompt-delivery refactor) — recommended as a follow-up (independent concern, re-touches manager.go). Backend: go build/vet/test ./... green (except the documented in-session CLI e2e 404s and a transient kilocode timeout, both in untouched packages); golangci-lint 0 issues. Frontend: tsc clean, 661 vitest green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cherry-pick left frontend/package-lock.json internally inconsistent — @rolldown/binding-wasm32-wasi pinned @emnapi/core/runtime at 1.10.0 while requiring exactly 1.11.1 — so `npm ci` failed the package.json↔lock sync check. Regenerated the lockfile (npm install --package-lock-only), a targeted fix of the @emnapi/rolldown subtree only. The auto-merge also left preload.ts, ProjectSettingsForm.tsx, and types/workspace.ts unformatted; ran prettier@3 --write (cosmetic only). Frontend: tsc clean, 661 vitest green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The previous commit reformatted types/workspace.ts with a prettier run that did not resolve the repo's root .prettierrc (printWidth 120), so it wrapped the WorkerDisplayStatus union under the default width 80 — which CI's root-run prettier@3 then rejected. Restored the auto-merged version (which CI accepted); verified with the exact CI command from the repo root. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ports upstream PR AgentWrapper#2460 – "combine workspace project stack" (
7a87caae, ~3,500 lines) ontomain-fluke(on top of the batch-1 sync / PR #45). AgentWrapper#2460 adds the workspace-project-stack capability: a project can be a multi-repo workspace whose sessions materialise a root worktree plus one worktree per child repo — all on a shared branch — with SCM observation of child repos, workspace-aware lifecycle teardown, and a desktop import UI.Every conflict was resolved to keep main-fluke behavior while adding AgentWrapper#2460's capability — reconciled, not one-sided.
Verification
go build ./.../go vet ./...golangci-lint rungo test ./...tsc --noEmit(frontend)vitest run(frontend)ao preview(screenshots below)Two backend failures are pre-existing/environmental in packages this port never touches:
internal/clie2e give the documented spuriousHTTP 404when run inside a live AO session (real daemonAO_*env leaks in — confirmed present), and onekilocodeauth testcontext deadline exceededthat passes on isolated re-run (transient timeout).Conflict hot-spots & reconciliations
manager.go(spawn / kill / restore rewrite, +737 upstream — 5 conflicts)applyConventionPrefix) + auto-named-collision retry; routed provisioning through feat: combine workspace project stack AgentWrapper/agent-orchestrator#2460'screateSessionWorkspaceand the workspace-awaredefaultSpawnBranch(delegates to main-fluke'sdefaultSessionBranch→ao/<id>/rootfor regular projects).--baseoverride —createSessionWorkspacehardcoded the project default branch; threaded main-fluke'scfg.BaseBranchback through it (both the regular and workspace paths).relaunchRestoredSessiondroppedRuntimeConfig.ProjectID/Branch; restored them (they feedtmux.SessionNameFor, i.e. the per-project branch naming), using the in-scoperec.ID.reconcileLive— kept main-fluke's idle-close-TTL fast-path; delegated the not-idle capture to feat: combine workspace project stack AgentWrapper/agent-orchestrator#2460's workspace-awaresaveAndTeardownOne(behaviorally equivalent to the old inline stash+marker+destroy, and multi-repo aware).prompts.ConfidentialityGuard+effectiveBase(main-fluke's prompts-package refactor) and added feat: combine workspace project stack AgentWrapper/agent-orchestrator#2460'sworkspaceProjectPromptinjection; dropped upstream's re-introduced localsystemPromptGuardconst (verbatim duplicate ofConfidentialityGuard) and the now-deadorchestratorPrompt.observe/scm/observer.go(PR attribution)subjectRepoForPROwner/Name hydration; added feat: combine workspace project stack AgentWrapper/agent-orchestrator#2460's workspace child-repo scanning (workspaceSCMSessionRepos) + multi-reporepoForTrackedPRselection.repoForTrackedPRselects the owning repo among the session's repos, thensubjectRepoForPRhydrates Owner/Name — so fix(scm): hydrate tracked PR repo owner and name AgentWrapper/agent-orchestrator#2510 is redundant (see below). On no-match, favored main-fluke's non-drop: attribute via the PR's recorded repo instead of dropping it.Sidebar.tsx(+464 upstream — 8 conflicts)CreateProjectFlowinto the sidebar and deleted the standaloneCreateProjectFlow.tsx→ kept it deleted.preload/bridgescanImportFolder/chooseDirectory(title),_shellasWorkspacewiring, API) was already present via clean auto-merge.sr-onlyerror span (a minor main-fluke a11y touch): it duplicated the error text and is incompatible with upstream's multi-dialog flow + tests, which surface errors visibly in both dialogs. The unrelated project-removalsr-onlyspan is untouched._shell.tsx— kept main-fluke'sthrowon orchestrator-startup failure; upstream'ssetOrchestratorStartupErrorstate path isn't wired in main-fluke's shell (undefined reference).Lockfile —
package-lock.jsonis secondary (pnpm is primary); took AgentWrapper#2460's transitive@emnapibump.pnpm installchurn onpnpm-lock.yamlwas reverted to the merged state.Related PRs
subjectRepoForPRalready hydrates, and this port composes it withrepoForTrackedPRso the refresh target always carries Owner/Name.GetPromptDeliveryStrategy), 670 lines across 13 files that re-touchmanager.go(+87) /manager_test.go(+215) — the same spawn/prompt path just reconciled here against main-fluke's AI-naming and convention customizations. Keeping it separate keeps this PR reviewable and revertable, and Refactor Kimi and Qwen agent adapters for improved prompt delivery an… AgentWrapper/agent-orchestrator#2497 is cleanly portable now that feat: combine workspace project stack AgentWrapper/agent-orchestrator#2460 (its blocker) has landed.Demo
ao previewof the new import flow (mock-data renderer):Both render with main-fluke's design system.
🤖 Generated with Claude Code