gitspace 0.2.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +21 -0
- package/.gitspace/bundle.json +50 -0
- package/.gitspace/select/01-status.sh +40 -0
- package/.gitspace/setup/01-install-deps.sh +12 -0
- package/.gitspace/setup/02-typecheck.sh +16 -0
- package/AGENTS.md +439 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +25 -0
- package/README.md +607 -0
- package/bin/gssh +62 -0
- package/bun.lock +647 -0
- package/docs/CONNECTION.md +623 -0
- package/docs/GATEWAY-WORKER.md +319 -0
- package/docs/GETTING-STARTED.md +448 -0
- package/docs/GITSPACE-PLATFORM.md +1819 -0
- package/docs/INFRASTRUCTURE.md +1347 -0
- package/docs/PROTOCOL.md +619 -0
- package/docs/QUICKSTART.md +174 -0
- package/docs/RELAY.md +327 -0
- package/docs/REMOTE-DESIGN.md +549 -0
- package/docs/ROADMAP.md +564 -0
- package/docs/SITE_DOCS_FIGMA_MAKE.md +1167 -0
- package/docs/STACK-DESIGN.md +588 -0
- package/docs/UNIFIED_ARCHITECTURE.md +292 -0
- package/experiments/pty-benchmark.ts +148 -0
- package/experiments/pty-latency.ts +100 -0
- package/experiments/router/client.ts +199 -0
- package/experiments/router/protocol.ts +74 -0
- package/experiments/router/router.ts +217 -0
- package/experiments/router/session.ts +180 -0
- package/experiments/router/test.ts +133 -0
- package/experiments/socket-bandwidth.ts +77 -0
- package/homebrew/gitspace.rb +45 -0
- package/landing-page/ATTRIBUTIONS.md +3 -0
- package/landing-page/README.md +11 -0
- package/landing-page/bun.lock +801 -0
- package/landing-page/guidelines/Guidelines.md +61 -0
- package/landing-page/index.html +37 -0
- package/landing-page/package.json +90 -0
- package/landing-page/postcss.config.mjs +15 -0
- package/landing-page/public/_redirects +1 -0
- package/landing-page/public/favicon.png +0 -0
- package/landing-page/src/app/App.tsx +53 -0
- package/landing-page/src/app/components/figma/ImageWithFallback.tsx +27 -0
- package/landing-page/src/app/components/ui/accordion.tsx +66 -0
- package/landing-page/src/app/components/ui/alert-dialog.tsx +157 -0
- package/landing-page/src/app/components/ui/alert.tsx +66 -0
- package/landing-page/src/app/components/ui/aspect-ratio.tsx +11 -0
- package/landing-page/src/app/components/ui/avatar.tsx +53 -0
- package/landing-page/src/app/components/ui/badge.tsx +46 -0
- package/landing-page/src/app/components/ui/breadcrumb.tsx +109 -0
- package/landing-page/src/app/components/ui/button.tsx +57 -0
- package/landing-page/src/app/components/ui/calendar.tsx +75 -0
- package/landing-page/src/app/components/ui/card.tsx +92 -0
- package/landing-page/src/app/components/ui/carousel.tsx +241 -0
- package/landing-page/src/app/components/ui/chart.tsx +353 -0
- package/landing-page/src/app/components/ui/checkbox.tsx +32 -0
- package/landing-page/src/app/components/ui/collapsible.tsx +33 -0
- package/landing-page/src/app/components/ui/command.tsx +177 -0
- package/landing-page/src/app/components/ui/context-menu.tsx +252 -0
- package/landing-page/src/app/components/ui/dialog.tsx +135 -0
- package/landing-page/src/app/components/ui/drawer.tsx +132 -0
- package/landing-page/src/app/components/ui/dropdown-menu.tsx +257 -0
- package/landing-page/src/app/components/ui/form.tsx +168 -0
- package/landing-page/src/app/components/ui/hover-card.tsx +44 -0
- package/landing-page/src/app/components/ui/input-otp.tsx +77 -0
- package/landing-page/src/app/components/ui/input.tsx +21 -0
- package/landing-page/src/app/components/ui/label.tsx +24 -0
- package/landing-page/src/app/components/ui/menubar.tsx +276 -0
- package/landing-page/src/app/components/ui/navigation-menu.tsx +168 -0
- package/landing-page/src/app/components/ui/pagination.tsx +127 -0
- package/landing-page/src/app/components/ui/popover.tsx +48 -0
- package/landing-page/src/app/components/ui/progress.tsx +31 -0
- package/landing-page/src/app/components/ui/radio-group.tsx +45 -0
- package/landing-page/src/app/components/ui/resizable.tsx +56 -0
- package/landing-page/src/app/components/ui/scroll-area.tsx +58 -0
- package/landing-page/src/app/components/ui/select.tsx +189 -0
- package/landing-page/src/app/components/ui/separator.tsx +28 -0
- package/landing-page/src/app/components/ui/sheet.tsx +139 -0
- package/landing-page/src/app/components/ui/sidebar.tsx +726 -0
- package/landing-page/src/app/components/ui/skeleton.tsx +13 -0
- package/landing-page/src/app/components/ui/slider.tsx +63 -0
- package/landing-page/src/app/components/ui/sonner.tsx +25 -0
- package/landing-page/src/app/components/ui/switch.tsx +31 -0
- package/landing-page/src/app/components/ui/table.tsx +116 -0
- package/landing-page/src/app/components/ui/tabs.tsx +66 -0
- package/landing-page/src/app/components/ui/textarea.tsx +18 -0
- package/landing-page/src/app/components/ui/toggle-group.tsx +73 -0
- package/landing-page/src/app/components/ui/toggle.tsx +47 -0
- package/landing-page/src/app/components/ui/tooltip.tsx +61 -0
- package/landing-page/src/app/components/ui/use-mobile.ts +21 -0
- package/landing-page/src/app/components/ui/utils.ts +6 -0
- package/landing-page/src/components/docs/DocsContent.tsx +718 -0
- package/landing-page/src/components/docs/DocsSidebar.tsx +84 -0
- package/landing-page/src/components/landing/CTA.tsx +59 -0
- package/landing-page/src/components/landing/Comparison.tsx +84 -0
- package/landing-page/src/components/landing/FaultyTerminal.tsx +424 -0
- package/landing-page/src/components/landing/Features.tsx +201 -0
- package/landing-page/src/components/landing/Hero.tsx +142 -0
- package/landing-page/src/components/landing/Pricing.tsx +140 -0
- package/landing-page/src/components/landing/Roadmap.tsx +86 -0
- package/landing-page/src/components/landing/Security.tsx +81 -0
- package/landing-page/src/components/landing/TerminalWindow.tsx +27 -0
- package/landing-page/src/components/landing/UseCases.tsx +55 -0
- package/landing-page/src/components/landing/Workflow.tsx +101 -0
- package/landing-page/src/components/layout/DashboardNavbar.tsx +37 -0
- package/landing-page/src/components/layout/Footer.tsx +55 -0
- package/landing-page/src/components/layout/LandingNavbar.tsx +82 -0
- package/landing-page/src/components/ui/badge.tsx +39 -0
- package/landing-page/src/components/ui/breadcrumb.tsx +115 -0
- package/landing-page/src/components/ui/button.tsx +57 -0
- package/landing-page/src/components/ui/card.tsx +79 -0
- package/landing-page/src/components/ui/mock-terminal.tsx +68 -0
- package/landing-page/src/components/ui/separator.tsx +28 -0
- package/landing-page/src/lib/utils.ts +6 -0
- package/landing-page/src/main.tsx +10 -0
- package/landing-page/src/pages/Dashboard.tsx +133 -0
- package/landing-page/src/pages/DocsPage.tsx +79 -0
- package/landing-page/src/pages/LandingPage.tsx +31 -0
- package/landing-page/src/pages/TerminalView.tsx +106 -0
- package/landing-page/src/styles/fonts.css +0 -0
- package/landing-page/src/styles/index.css +3 -0
- package/landing-page/src/styles/tailwind.css +4 -0
- package/landing-page/src/styles/theme.css +181 -0
- package/landing-page/vite.config.ts +19 -0
- package/npm/darwin-arm64/bin/gssh +0 -0
- package/npm/darwin-arm64/package.json +20 -0
- package/package.json +74 -0
- package/scripts/build.ts +284 -0
- package/scripts/release.ts +140 -0
- package/src/__tests__/test-utils.ts +298 -0
- package/src/commands/__tests__/serve-messages.test.ts +190 -0
- package/src/commands/access.ts +298 -0
- package/src/commands/add.ts +452 -0
- package/src/commands/auth.ts +364 -0
- package/src/commands/connect.ts +287 -0
- package/src/commands/directory.ts +16 -0
- package/src/commands/host.ts +396 -0
- package/src/commands/identity.ts +184 -0
- package/src/commands/list.ts +200 -0
- package/src/commands/relay.ts +315 -0
- package/src/commands/remove.ts +241 -0
- package/src/commands/serve.ts +1493 -0
- package/src/commands/share.ts +456 -0
- package/src/commands/status.ts +125 -0
- package/src/commands/switch.ts +353 -0
- package/src/commands/tmux.ts +317 -0
- package/src/core/__tests__/access.test.ts +240 -0
- package/src/core/access.ts +277 -0
- package/src/core/bundle.ts +342 -0
- package/src/core/config.ts +510 -0
- package/src/core/git.ts +317 -0
- package/src/core/github.ts +151 -0
- package/src/core/identity.ts +631 -0
- package/src/core/linear.ts +225 -0
- package/src/core/shell.ts +161 -0
- package/src/core/trusted-relays.ts +315 -0
- package/src/index.ts +821 -0
- package/src/lib/remote-session/index.ts +7 -0
- package/src/lib/remote-session/protocol.ts +267 -0
- package/src/lib/remote-session/session-handler.ts +581 -0
- package/src/lib/remote-session/workspace-scanner.ts +167 -0
- package/src/lib/tmux-lite/README.md +81 -0
- package/src/lib/tmux-lite/cli.ts +796 -0
- package/src/lib/tmux-lite/crypto/__tests__/helpers/handshake-runner.ts +349 -0
- package/src/lib/tmux-lite/crypto/__tests__/helpers/mock-relay.ts +291 -0
- package/src/lib/tmux-lite/crypto/__tests__/helpers/test-identities.ts +142 -0
- package/src/lib/tmux-lite/crypto/__tests__/integration/authorization.integration.test.ts +339 -0
- package/src/lib/tmux-lite/crypto/__tests__/integration/e2e-communication.integration.test.ts +477 -0
- package/src/lib/tmux-lite/crypto/__tests__/integration/error-handling.integration.test.ts +499 -0
- package/src/lib/tmux-lite/crypto/__tests__/integration/handshake.integration.test.ts +371 -0
- package/src/lib/tmux-lite/crypto/__tests__/integration/security.integration.test.ts +573 -0
- package/src/lib/tmux-lite/crypto/access-control.test.ts +512 -0
- package/src/lib/tmux-lite/crypto/access-control.ts +320 -0
- package/src/lib/tmux-lite/crypto/frames.test.ts +262 -0
- package/src/lib/tmux-lite/crypto/frames.ts +141 -0
- package/src/lib/tmux-lite/crypto/handshake.ts +894 -0
- package/src/lib/tmux-lite/crypto/identity.test.ts +220 -0
- package/src/lib/tmux-lite/crypto/identity.ts +286 -0
- package/src/lib/tmux-lite/crypto/index.ts +51 -0
- package/src/lib/tmux-lite/crypto/invites.test.ts +381 -0
- package/src/lib/tmux-lite/crypto/invites.ts +215 -0
- package/src/lib/tmux-lite/crypto/keyexchange.ts +435 -0
- package/src/lib/tmux-lite/crypto/keys.test.ts +58 -0
- package/src/lib/tmux-lite/crypto/keys.ts +47 -0
- package/src/lib/tmux-lite/crypto/secretbox.test.ts +169 -0
- package/src/lib/tmux-lite/crypto/secretbox.ts +124 -0
- package/src/lib/tmux-lite/handshake-handler.ts +451 -0
- package/src/lib/tmux-lite/protocol.test.ts +307 -0
- package/src/lib/tmux-lite/protocol.ts +266 -0
- package/src/lib/tmux-lite/relay-client.ts +506 -0
- package/src/lib/tmux-lite/server.ts +1250 -0
- package/src/lib/tmux-lite/shell-integration.sh +37 -0
- package/src/lib/tmux-lite/terminal-queries.test.ts +54 -0
- package/src/lib/tmux-lite/terminal-queries.ts +49 -0
- package/src/relay/__tests__/e2e-flow.test.ts +1284 -0
- package/src/relay/__tests__/helpers/auth.ts +354 -0
- package/src/relay/__tests__/helpers/ports.ts +51 -0
- package/src/relay/__tests__/protocol-validation.test.ts +265 -0
- package/src/relay/authorization.ts +303 -0
- package/src/relay/embedded-assets.generated.d.ts +15 -0
- package/src/relay/identity.ts +352 -0
- package/src/relay/index.ts +57 -0
- package/src/relay/pipes.test.ts +427 -0
- package/src/relay/pipes.ts +195 -0
- package/src/relay/protocol.ts +804 -0
- package/src/relay/registries.test.ts +437 -0
- package/src/relay/registries.ts +593 -0
- package/src/relay/server.test.ts +1323 -0
- package/src/relay/server.ts +1092 -0
- package/src/relay/signing.ts +238 -0
- package/src/relay/types.ts +69 -0
- package/src/serve/client-session-manager.ts +622 -0
- package/src/serve/daemon.ts +497 -0
- package/src/serve/pty-session.ts +236 -0
- package/src/serve/types.ts +169 -0
- package/src/shared/components/Flow.tsx +453 -0
- package/src/shared/components/Flow.tui.tsx +343 -0
- package/src/shared/components/Flow.web.tsx +442 -0
- package/src/shared/components/Inbox.tsx +446 -0
- package/src/shared/components/Inbox.tui.tsx +262 -0
- package/src/shared/components/Inbox.web.tsx +329 -0
- package/src/shared/components/MachineList.tsx +187 -0
- package/src/shared/components/MachineList.tui.tsx +161 -0
- package/src/shared/components/MachineList.web.tsx +210 -0
- package/src/shared/components/ProjectList.tsx +176 -0
- package/src/shared/components/ProjectList.tui.tsx +109 -0
- package/src/shared/components/ProjectList.web.tsx +143 -0
- package/src/shared/components/SpacesBrowser.tsx +332 -0
- package/src/shared/components/SpacesBrowser.tui.tsx +163 -0
- package/src/shared/components/SpacesBrowser.web.tsx +221 -0
- package/src/shared/components/index.ts +103 -0
- package/src/shared/hooks/index.ts +16 -0
- package/src/shared/hooks/useNavigation.ts +226 -0
- package/src/shared/index.ts +122 -0
- package/src/shared/providers/LocalMachineProvider.ts +425 -0
- package/src/shared/providers/MachineProvider.ts +165 -0
- package/src/shared/providers/RemoteMachineProvider.ts +444 -0
- package/src/shared/providers/index.ts +26 -0
- package/src/shared/types.ts +145 -0
- package/src/tui/adapters.ts +120 -0
- package/src/tui/app.tsx +1816 -0
- package/src/tui/components/Terminal.tsx +580 -0
- package/src/tui/hooks/index.ts +35 -0
- package/src/tui/hooks/useAppState.ts +314 -0
- package/src/tui/hooks/useDaemonStatus.ts +174 -0
- package/src/tui/hooks/useInboxTUI.ts +113 -0
- package/src/tui/hooks/useRemoteMachines.ts +209 -0
- package/src/tui/index.ts +24 -0
- package/src/tui/state.ts +299 -0
- package/src/tui/terminal-bracketed-paste.test.ts +45 -0
- package/src/tui/terminal-bracketed-paste.ts +47 -0
- package/src/types/bundle.ts +112 -0
- package/src/types/config.ts +89 -0
- package/src/types/errors.ts +206 -0
- package/src/types/identity.ts +284 -0
- package/src/types/workspace-fuzzy.ts +49 -0
- package/src/types/workspace.ts +151 -0
- package/src/utils/bun-socket-writer.ts +80 -0
- package/src/utils/deps.ts +127 -0
- package/src/utils/fuzzy-match.ts +125 -0
- package/src/utils/logger.ts +127 -0
- package/src/utils/markdown.ts +254 -0
- package/src/utils/onboarding.ts +229 -0
- package/src/utils/prompts.ts +114 -0
- package/src/utils/run-commands.ts +112 -0
- package/src/utils/run-scripts.ts +142 -0
- package/src/utils/sanitize.ts +98 -0
- package/src/utils/secrets.ts +122 -0
- package/src/utils/shell-escape.ts +40 -0
- package/src/utils/utf8.ts +79 -0
- package/src/utils/workspace-state.ts +47 -0
- package/src/web/README.md +73 -0
- package/src/web/bun.lock +575 -0
- package/src/web/eslint.config.js +23 -0
- package/src/web/index.html +16 -0
- package/src/web/package.json +37 -0
- package/src/web/public/vite.svg +1 -0
- package/src/web/src/App.tsx +604 -0
- package/src/web/src/assets/react.svg +1 -0
- package/src/web/src/components/Terminal.tsx +207 -0
- package/src/web/src/hooks/useRelayConnection.ts +224 -0
- package/src/web/src/hooks/useTerminal.ts +699 -0
- package/src/web/src/index.css +55 -0
- package/src/web/src/lib/crypto/__tests__/web-terminal.test.ts +1158 -0
- package/src/web/src/lib/crypto/frames.ts +205 -0
- package/src/web/src/lib/crypto/handshake.ts +396 -0
- package/src/web/src/lib/crypto/identity.ts +128 -0
- package/src/web/src/lib/crypto/keyexchange.ts +246 -0
- package/src/web/src/lib/crypto/relay-signing.ts +53 -0
- package/src/web/src/lib/invite.ts +58 -0
- package/src/web/src/lib/storage/identity-store.ts +94 -0
- package/src/web/src/main.tsx +10 -0
- package/src/web/src/types/identity.ts +45 -0
- package/src/web/tsconfig.app.json +28 -0
- package/src/web/tsconfig.json +7 -0
- package/src/web/tsconfig.node.json +26 -0
- package/src/web/vite.config.ts +31 -0
- package/todo-security.md +92 -0
- package/tsconfig.json +23 -0
- package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/12b7107e435bf1b9a8713a7f320472a63e543104d633d89a26f8d21f4e4ef182.sqlite +0 -0
- package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/12b7107e435bf1b9a8713a7f320472a63e543104d633d89a26f8d21f4e4ef182.sqlite-shm +0 -0
- package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/12b7107e435bf1b9a8713a7f320472a63e543104d633d89a26f8d21f4e4ef182.sqlite-wal +0 -0
- package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/1a1ac3db1ab86ecf712f90322868a9aabc2c7dc9fe2dfbe94f9b075096276b0f.sqlite +0 -0
- package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/1a1ac3db1ab86ecf712f90322868a9aabc2c7dc9fe2dfbe94f9b075096276b0f.sqlite-shm +0 -0
- package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/1a1ac3db1ab86ecf712f90322868a9aabc2c7dc9fe2dfbe94f9b075096276b0f.sqlite-wal +0 -0
- package/worker/bun.lock +237 -0
- package/worker/package.json +22 -0
- package/worker/schema.sql +96 -0
- package/worker/src/handlers/auth.ts +451 -0
- package/worker/src/handlers/subdomains.ts +376 -0
- package/worker/src/handlers/user.ts +98 -0
- package/worker/src/index.ts +70 -0
- package/worker/src/middleware/auth.ts +152 -0
- package/worker/src/services/cloudflare.ts +609 -0
- package/worker/src/types.ts +96 -0
- package/worker/tsconfig.json +15 -0
- package/worker/wrangler.toml +26 -0
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
# Stacked PR Feature - Architecture Design
|
|
2
|
+
|
|
3
|
+
> **⚠️ FUTURE FEATURE DOCUMENT**
|
|
4
|
+
>
|
|
5
|
+
> This document describes a **planned feature** that is **not yet implemented**.
|
|
6
|
+
> The `gssh stack` command does not currently exist. This is a design document for future development.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
> AI-assisted splitting of work-in-progress commits into clean, logical PRs
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
The `gssh stack` command helps developers split messy WIP commits into clean, reviewable PRs using AI-assisted code analysis in a sandboxed environment.
|
|
15
|
+
|
|
16
|
+
## Core Concept
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
User's messy branch:
|
|
20
|
+
main ── wip1 ── wip2 ── debug ── wip3 ── fixup ── wip4 ── more...
|
|
21
|
+
└──────────── logical unit A ───────────┘ └── continued ──
|
|
22
|
+
|
|
23
|
+
After `gssh stack`:
|
|
24
|
+
main ── "Add auth" ── "Add tests" ──┬── (PR #1 created)
|
|
25
|
+
│
|
|
26
|
+
└── user's work rebased on top
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Key insight**: Instead of building a fixed algorithm, we give the AI tools (AST analysis, git operations) in a sandbox and let it explore different ways to split the code.
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
### High-Level Components
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
37
|
+
│ gssh stack command │
|
|
38
|
+
├─────────────────────────────────────────────────────────────────────┤
|
|
39
|
+
│ │
|
|
40
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
|
|
41
|
+
│ │ Diff │ │ Sandbox │ │ Interactive UI │ │
|
|
42
|
+
│ │ Analyzer │───▶│ + AI │───▶│ (TUI/Prompts) │ │
|
|
43
|
+
│ │ │ │ Explorer │ │ │ │
|
|
44
|
+
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
|
|
45
|
+
│ │ │ │ │
|
|
46
|
+
│ ▼ ▼ ▼ │
|
|
47
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
|
|
48
|
+
│ │ AST │ │ Virtual │ │ Git Operations │ │
|
|
49
|
+
│ │ Bindings │ │ Filesystem │ │ (rebase, PR create) │ │
|
|
50
|
+
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
|
|
51
|
+
│ │
|
|
52
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Dependencies
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"isomorphic-git": "^1.25.0", // Git ops in sandbox
|
|
61
|
+
"memfs": "^4.6.0", // Virtual filesystem
|
|
62
|
+
"@babel/parser": "^7.23.0", // AST parsing for JS/TS
|
|
63
|
+
"@babel/traverse": "^7.23.0", // AST traversal
|
|
64
|
+
"@babel/types": "^7.23.0", // AST type utilities
|
|
65
|
+
"isolated-vm": "^4.7.0", // V8 isolate sandbox
|
|
66
|
+
"ai-flow": "...", // AI abstraction (OpenAI responses API compatible)
|
|
67
|
+
"tensorzero": "..." // Multi-provider AI routing
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Component Design
|
|
75
|
+
|
|
76
|
+
### 1. Diff Analyzer (`src/core/stack/diff-analyzer.ts`)
|
|
77
|
+
|
|
78
|
+
Parses git diff and extracts structured change information.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
interface FileChange {
|
|
82
|
+
path: string;
|
|
83
|
+
status: 'added' | 'modified' | 'deleted' | 'renamed';
|
|
84
|
+
hunks: Hunk[];
|
|
85
|
+
oldContent?: string;
|
|
86
|
+
newContent?: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface Hunk {
|
|
90
|
+
oldStart: number;
|
|
91
|
+
oldLines: number;
|
|
92
|
+
newStart: number;
|
|
93
|
+
newLines: number;
|
|
94
|
+
content: string;
|
|
95
|
+
addedLines: Line[];
|
|
96
|
+
removedLines: Line[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Functions
|
|
100
|
+
function parseDiff(diffText: string): FileChange[];
|
|
101
|
+
function getChangesInRange(repoPath: string, range: string): Promise<FileChange[]>;
|
|
102
|
+
function getFileAtRevision(repoPath: string, file: string, rev: string): Promise<string>;
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 2. AST Analysis Bindings (`src/core/stack/ast-bindings.ts`)
|
|
106
|
+
|
|
107
|
+
Provides TypeScript API for the AI sandbox to analyze code.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
interface Symbol {
|
|
111
|
+
name: string;
|
|
112
|
+
kind: 'function' | 'class' | 'type' | 'variable' | 'import' | 'export';
|
|
113
|
+
file: string;
|
|
114
|
+
line: number;
|
|
115
|
+
exported: boolean;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
interface Reference {
|
|
119
|
+
symbol: string;
|
|
120
|
+
file: string;
|
|
121
|
+
line: number;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface ASTBindings {
|
|
125
|
+
// Parse code and return AST
|
|
126
|
+
parse(code: string, language: string): AST;
|
|
127
|
+
|
|
128
|
+
// Extract symbols defined in code
|
|
129
|
+
findDefinitions(code: string, language: string): Symbol[];
|
|
130
|
+
|
|
131
|
+
// Extract symbols referenced in code
|
|
132
|
+
findReferences(code: string, language: string): Reference[];
|
|
133
|
+
|
|
134
|
+
// Check if a set of changes is self-consistent
|
|
135
|
+
checkDependencies(changes: FileChange[]): {
|
|
136
|
+
valid: boolean;
|
|
137
|
+
missing: Symbol[]; // Referenced but not defined
|
|
138
|
+
circular: Symbol[][]; // Mutually dependent
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// Get language from file extension
|
|
142
|
+
detectLanguage(filename: string): string;
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 3. Dependency Graph (`src/core/stack/dependency-graph.ts`)
|
|
147
|
+
|
|
148
|
+
Builds and analyzes the dependency graph of changes.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
interface ChangeNode {
|
|
152
|
+
id: string;
|
|
153
|
+
files: string[];
|
|
154
|
+
hunks: Hunk[];
|
|
155
|
+
defines: Symbol[];
|
|
156
|
+
references: Symbol[];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
interface DependencyGraph {
|
|
160
|
+
nodes: Map<string, ChangeNode>;
|
|
161
|
+
edges: Map<string, Set<string>>; // node -> depends on
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Functions
|
|
165
|
+
function buildGraph(changes: FileChange[], ast: ASTBindings): DependencyGraph;
|
|
166
|
+
function findStronglyConnectedComponents(graph: DependencyGraph): ChangeNode[][];
|
|
167
|
+
function topologicalSort(graph: DependencyGraph): ChangeNode[];
|
|
168
|
+
function suggestGroupings(graph: DependencyGraph): ProposedCommit[];
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Dependency Analysis Flow:**
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
Change A: Define `validateUser()` function
|
|
175
|
+
Change B: Use `validateUser()` in login.ts
|
|
176
|
+
Change C: Add `UserRole` type
|
|
177
|
+
Change D: Use `UserRole` in validateUser()
|
|
178
|
+
|
|
179
|
+
Dependency graph:
|
|
180
|
+
─────────────────────────────────
|
|
181
|
+
C (UserRole)
|
|
182
|
+
│
|
|
183
|
+
▼
|
|
184
|
+
A (validateUser) ◄── D (uses UserRole in A)
|
|
185
|
+
│
|
|
186
|
+
▼
|
|
187
|
+
B (uses validateUser)
|
|
188
|
+
─────────────────────────────────
|
|
189
|
+
|
|
190
|
+
Valid orderings: C → A+D → B
|
|
191
|
+
Invalid: B before A (undefined function)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### 4. Virtual Filesystem + Sandbox (`src/core/stack/sandbox.ts`)
|
|
195
|
+
|
|
196
|
+
Creates an isolated environment where AI can experiment with different commit arrangements.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
interface SandboxFS {
|
|
200
|
+
// Read file (from base + overlay)
|
|
201
|
+
readFile(path: string): Promise<string>;
|
|
202
|
+
|
|
203
|
+
// Write to overlay (doesn't affect real FS)
|
|
204
|
+
writeFile(path: string, content: string): Promise<void>;
|
|
205
|
+
|
|
206
|
+
// Apply a patch to the virtual FS
|
|
207
|
+
applyPatch(patch: string): Promise<void>;
|
|
208
|
+
|
|
209
|
+
// Reset overlay, keep base
|
|
210
|
+
reset(): void;
|
|
211
|
+
|
|
212
|
+
// Snapshot current state
|
|
213
|
+
snapshot(): FSSnapshot;
|
|
214
|
+
|
|
215
|
+
// Restore from snapshot
|
|
216
|
+
restore(snapshot: FSSnapshot): void;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
interface Sandbox {
|
|
220
|
+
fs: SandboxFS;
|
|
221
|
+
git: SandboxGit; // isomorphic-git bound to virtual FS
|
|
222
|
+
ast: ASTBindings;
|
|
223
|
+
|
|
224
|
+
// Execute AI-generated code in isolated environment
|
|
225
|
+
execute(code: string): Promise<any>;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Implementation using memfs + isolated-vm
|
|
229
|
+
function createSandbox(repoPath: string, baseRef: string): Promise<Sandbox>;
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Sandbox Architecture:**
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
236
|
+
│ Virtual FS Layer │
|
|
237
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
238
|
+
│ │
|
|
239
|
+
│ Base: Git tree at main (read-only) │
|
|
240
|
+
│ │ │
|
|
241
|
+
│ ├── Overlay: Proposed changes (copy-on-write) │
|
|
242
|
+
│ │ │
|
|
243
|
+
│ └── AI can: │
|
|
244
|
+
│ • Apply patch A, run tree-sitter, check deps │
|
|
245
|
+
│ • Apply patch A+B, run tsc, see if it compiles │
|
|
246
|
+
│ • Rollback, try different arrangement │
|
|
247
|
+
│ • Read any file as it would exist at that state │
|
|
248
|
+
│ │
|
|
249
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### 5. AI Integration (`src/core/stack/ai-explorer.ts`)
|
|
253
|
+
|
|
254
|
+
Orchestrates AI exploration of different commit arrangements.
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
interface ProposedCommit {
|
|
258
|
+
message: string;
|
|
259
|
+
files: string[];
|
|
260
|
+
hunks: Hunk[];
|
|
261
|
+
reasoning: string;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
interface StackProposal {
|
|
265
|
+
commits: ProposedCommit[];
|
|
266
|
+
dependencyOrder: string[]; // Commit order
|
|
267
|
+
warnings: string[]; // Things user should review
|
|
268
|
+
conflicts: ConflictInfo[]; // Where user input needed
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
interface ConflictInfo {
|
|
272
|
+
type: 'circular' | 'interleaved' | 'ambiguous';
|
|
273
|
+
files: string[];
|
|
274
|
+
description: string;
|
|
275
|
+
options: string[];
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**AI Sandbox Bindings:**
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import { AIFlow } from 'ai-flow'; // OpenAI responses API compatible
|
|
283
|
+
|
|
284
|
+
const AI_SYSTEM_PROMPT = `
|
|
285
|
+
You are analyzing code changes to split them into logical PRs.
|
|
286
|
+
|
|
287
|
+
You have access to these TypeScript APIs in your sandbox:
|
|
288
|
+
- git.getDiff(range): Get diff for commit range
|
|
289
|
+
- git.getFile(path, rev): Get file at revision
|
|
290
|
+
- ast.parse(code): Parse JS/TS to AST
|
|
291
|
+
- ast.findDefinitions(code): Find defined symbols
|
|
292
|
+
- ast.findReferences(code): Find referenced symbols
|
|
293
|
+
- ast.checkDeps(changes): Check if changes are self-consistent
|
|
294
|
+
- propose.group(files[], message): Propose a commit grouping
|
|
295
|
+
- propose.validate(groups[]): Validate proposed groupings
|
|
296
|
+
|
|
297
|
+
Write TypeScript code to explore the changes and propose logical groupings.
|
|
298
|
+
Return your final proposal via propose.finalize(groups[]).
|
|
299
|
+
`;
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### 6. Interactive UI (`src/core/stack/ui.ts`)
|
|
303
|
+
|
|
304
|
+
TUI components for user interaction.
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
308
|
+
│ gssh stack - Analyzing changes... │
|
|
309
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
310
|
+
│ │
|
|
311
|
+
│ Found 47 changed lines across 8 files │
|
|
312
|
+
│ Base: main (3 commits behind) │
|
|
313
|
+
│ │
|
|
314
|
+
│ Proposed Stack: │
|
|
315
|
+
│ ─────────────── │
|
|
316
|
+
│ PR #1: "Add user authentication middleware" │
|
|
317
|
+
│ ├── src/middleware/auth.ts (+45 -12) │
|
|
318
|
+
│ ├── src/types/user.ts (+8 -0) │
|
|
319
|
+
│ └── src/routes/login.ts (+15 -3) │
|
|
320
|
+
│ │
|
|
321
|
+
│ PR #2: "Update button styles" │
|
|
322
|
+
│ └── src/styles/button.css (+5 -2) │
|
|
323
|
+
│ │
|
|
324
|
+
│ ⚠️ Needs Review: │
|
|
325
|
+
│ src/utils/helpers.ts has changes for both PRs │
|
|
326
|
+
│ │
|
|
327
|
+
│ [a] Accept [e] Edit [s] Split file [?] Help │
|
|
328
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**Features:**
|
|
332
|
+
- Show proposed groupings with file lists
|
|
333
|
+
- Highlight conflicts/warnings
|
|
334
|
+
- Allow editing commit messages
|
|
335
|
+
- Allow reassigning files/hunks to different commits
|
|
336
|
+
- Preview resulting git history
|
|
337
|
+
- Confirm before executing
|
|
338
|
+
|
|
339
|
+
### 7. Git Execution (`src/core/stack/git-executor.ts`)
|
|
340
|
+
|
|
341
|
+
Actually creates the branches and PRs.
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
interface StackExecutionPlan {
|
|
345
|
+
prBranches: string[]; // e.g., ["feature-auth", "feature-styles"]
|
|
346
|
+
continuationBranch: string; // Where remaining work goes
|
|
347
|
+
commits: Map<string, ProposedCommit[]>;
|
|
348
|
+
rebaseOnto: string;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async function executeStack(
|
|
352
|
+
workspacePath: string,
|
|
353
|
+
plan: StackExecutionPlan,
|
|
354
|
+
createPRs: boolean
|
|
355
|
+
): Promise<{
|
|
356
|
+
createdBranches: string[];
|
|
357
|
+
prUrls?: string[];
|
|
358
|
+
continuationBranch: string;
|
|
359
|
+
}>;
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### 8. Stack State Tracking (`src/core/stack/stack-state.ts`)
|
|
363
|
+
|
|
364
|
+
Persists stack relationships for future `gssh stack sync`.
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
// Stored in ~/gitspace/<project>/.stack-state.json
|
|
368
|
+
interface StackState {
|
|
369
|
+
stacks: Stack[];
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
interface Stack {
|
|
373
|
+
id: string; // UUID
|
|
374
|
+
createdAt: string;
|
|
375
|
+
baseBranch: string; // e.g., "main"
|
|
376
|
+
prs: StackedPR[]; // Ordered list (bottom to top)
|
|
377
|
+
continuationBranch?: string; // Branch with remaining work
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
interface StackedPR {
|
|
381
|
+
branch: string;
|
|
382
|
+
prNumber?: number;
|
|
383
|
+
prUrl?: string;
|
|
384
|
+
status: 'pending' | 'open' | 'merged' | 'closed';
|
|
385
|
+
baseBranch: string; // What this PR targets
|
|
386
|
+
headCommit: string; // For detecting updates
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### 9. Stack Sync (`src/core/stack/sync.ts`) - Future
|
|
391
|
+
|
|
392
|
+
Handles rebasing when PRs are merged/updated.
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
// gssh stack sync
|
|
396
|
+
async function syncStack(
|
|
397
|
+
workspacePath: string,
|
|
398
|
+
stackId: string
|
|
399
|
+
): Promise<{
|
|
400
|
+
rebased: string[]; // Branches that were rebased
|
|
401
|
+
conflicts: string[]; // Branches with conflicts
|
|
402
|
+
}>;
|
|
403
|
+
|
|
404
|
+
// Workflow:
|
|
405
|
+
// 1. Check status of each PR in stack (via gh api)
|
|
406
|
+
// 2. For merged PRs: rebase dependent branches onto new base
|
|
407
|
+
// 3. For updated PRs: detect force-push, rebase dependents
|
|
408
|
+
// 4. Report conflicts for manual resolution
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## File Structure
|
|
414
|
+
|
|
415
|
+
```
|
|
416
|
+
src/
|
|
417
|
+
├── commands/
|
|
418
|
+
│ └── stack.ts # Command entry point
|
|
419
|
+
├── core/
|
|
420
|
+
│ └── stack/
|
|
421
|
+
│ ├── index.ts # Main orchestrator
|
|
422
|
+
│ ├── diff-analyzer.ts # Diff parsing
|
|
423
|
+
│ ├── ast-bindings.ts # AST analysis API (Babel-based)
|
|
424
|
+
│ ├── dependency-graph.ts # Graph analysis
|
|
425
|
+
│ ├── sandbox.ts # Virtual FS + isolate
|
|
426
|
+
│ ├── ai-explorer.ts # AI integration (ai-flow)
|
|
427
|
+
│ ├── git-executor.ts # Git operations
|
|
428
|
+
│ ├── stack-state.ts # Persist stack relationships
|
|
429
|
+
│ ├── sync.ts # Stack sync operations (future)
|
|
430
|
+
│ └── ui.ts # Interactive UI components
|
|
431
|
+
├── types/
|
|
432
|
+
│ └── stack.ts # Type definitions
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**Integration Points:**
|
|
436
|
+
- `src/index.ts` - Register `stack` command with Commander.js
|
|
437
|
+
- `src/core/git.ts` - Reuse existing git utilities
|
|
438
|
+
- `src/utils/prompts.ts` - Reuse selectItem, promptInput, promptConfirm
|
|
439
|
+
- `src/core/config.ts` - Add getStackStateFile() path helper
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## Command Interface
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
# Basic usage - analyze current branch vs main
|
|
447
|
+
gssh stack
|
|
448
|
+
|
|
449
|
+
# Specify base branch
|
|
450
|
+
gssh stack --base develop
|
|
451
|
+
|
|
452
|
+
# Specify commit range
|
|
453
|
+
gssh stack --range HEAD~5..HEAD
|
|
454
|
+
|
|
455
|
+
# Non-interactive mode (for CI/scripts)
|
|
456
|
+
gssh stack --auto
|
|
457
|
+
|
|
458
|
+
# Just analyze, don't execute
|
|
459
|
+
gssh stack --dry-run
|
|
460
|
+
|
|
461
|
+
# Provide hints to AI
|
|
462
|
+
gssh stack --hint "The auth changes should be separate from the UI changes"
|
|
463
|
+
|
|
464
|
+
# Stack sync - rebase dependent branches when PRs merge/update
|
|
465
|
+
gssh stack sync
|
|
466
|
+
|
|
467
|
+
# List active stacks
|
|
468
|
+
gssh stack list
|
|
469
|
+
|
|
470
|
+
# Show stack status (PR states, rebase needed)
|
|
471
|
+
gssh stack status
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
**Interactive Prompts:**
|
|
475
|
+
1. After analysis: "Create PRs now, or just prepare branches?" → [Create PRs] [Branches only]
|
|
476
|
+
2. Conflict resolution: "These files have interleaved changes" → [Split] [Keep together] [Show diff]
|
|
477
|
+
3. Commit messages: "Edit commit messages?" → [Accept] [Edit]
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## Implementation Phases
|
|
482
|
+
|
|
483
|
+
### Phase 1: Foundation
|
|
484
|
+
**Files:** `package.json`, `src/types/stack.ts`, `src/core/stack/diff-analyzer.ts`
|
|
485
|
+
|
|
486
|
+
1. Add dependencies: `@babel/parser`, `@babel/traverse`, `memfs`, `isomorphic-git`, `isolated-vm`
|
|
487
|
+
2. Create type definitions
|
|
488
|
+
3. Implement diff analyzer
|
|
489
|
+
4. Add basic `gssh stack --dry-run` command
|
|
490
|
+
|
|
491
|
+
### Phase 2: AST Analysis
|
|
492
|
+
**Files:** `src/core/stack/ast-bindings.ts`, `src/core/stack/dependency-graph.ts`
|
|
493
|
+
|
|
494
|
+
1. Implement AST parsing with @babel/parser
|
|
495
|
+
2. Build dependency graph
|
|
496
|
+
3. Implement SCC detection and topological sort
|
|
497
|
+
|
|
498
|
+
### Phase 3: Sandbox Environment
|
|
499
|
+
**Files:** `src/core/stack/sandbox.ts`
|
|
500
|
+
|
|
501
|
+
1. Set up memfs virtual filesystem
|
|
502
|
+
2. Integrate isomorphic-git
|
|
503
|
+
3. Create isolated-vm sandbox with bindings
|
|
504
|
+
|
|
505
|
+
### Phase 4: AI Integration
|
|
506
|
+
**Files:** `src/core/stack/ai-explorer.ts`
|
|
507
|
+
|
|
508
|
+
1. Integrate ai-flow client
|
|
509
|
+
2. Create system prompt with binding docs
|
|
510
|
+
3. Implement exploration loop
|
|
511
|
+
|
|
512
|
+
### Phase 5: Interactive UI
|
|
513
|
+
**Files:** `src/core/stack/ui.ts`, `src/commands/stack.ts`
|
|
514
|
+
|
|
515
|
+
1. Analysis display
|
|
516
|
+
2. Conflict resolution UI
|
|
517
|
+
3. Commit message editing
|
|
518
|
+
4. File/hunk reassignment
|
|
519
|
+
|
|
520
|
+
### Phase 6: Git Execution
|
|
521
|
+
**Files:** `src/core/stack/git-executor.ts`, `src/core/stack/stack-state.ts`
|
|
522
|
+
|
|
523
|
+
1. Branch creation and commit application
|
|
524
|
+
2. PR creation via `gh` CLI
|
|
525
|
+
3. Continuation branch rebasing
|
|
526
|
+
4. State persistence
|
|
527
|
+
|
|
528
|
+
### Phase 7: Stack Management (Future)
|
|
529
|
+
**Files:** `src/core/stack/sync.ts`
|
|
530
|
+
|
|
531
|
+
1. `gssh stack list`
|
|
532
|
+
2. `gssh stack status`
|
|
533
|
+
3. `gssh stack sync`
|
|
534
|
+
|
|
535
|
+
### Phase 8: Polish
|
|
536
|
+
1. `--auto` mode
|
|
537
|
+
2. Progress indicators
|
|
538
|
+
3. Rollback on failure
|
|
539
|
+
4. Documentation
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
## Technical Decisions
|
|
544
|
+
|
|
545
|
+
| Decision | Choice | Rationale |
|
|
546
|
+
|----------|--------|-----------|
|
|
547
|
+
| AST Parser | @babel/parser | Pure JS, no native deps, excellent JS/TS support |
|
|
548
|
+
| Sandbox | isolated-vm + memfs | True V8 isolate, fast startup, matches Cloudflare's approach |
|
|
549
|
+
| AI Provider | ai-flow + TensorZero | OpenAI responses API compatible, multi-provider support |
|
|
550
|
+
| PR Creation | User choice per run | Prompt each time for flexibility |
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## Risk Mitigation
|
|
555
|
+
|
|
556
|
+
| Risk | Mitigation |
|
|
557
|
+
|------|------------|
|
|
558
|
+
| AI produces invalid groupings | Validate with AST before presenting to user |
|
|
559
|
+
| Complex merges fail | Always work on copies, never modify user's branch until confirmed |
|
|
560
|
+
| Large diffs overwhelm AI | Chunk analysis, summarize first |
|
|
561
|
+
| Circular dependencies | Detect and flag for user resolution |
|
|
562
|
+
| isolated-vm compatibility | Fall back to worker threads if needed |
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
## Success Criteria
|
|
567
|
+
|
|
568
|
+
1. User can run `gssh stack` and see proposed commit groupings
|
|
569
|
+
2. Each proposed commit is syntactically valid (passes AST validation)
|
|
570
|
+
3. User can adjust groupings interactively
|
|
571
|
+
4. User chooses: create PRs automatically OR just prepare branches
|
|
572
|
+
5. Executing creates clean branches with logical commits
|
|
573
|
+
6. User's remaining work is correctly rebased on top of stack
|
|
574
|
+
7. Stack state is persisted for future `gssh stack sync`
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## External Dependencies
|
|
579
|
+
|
|
580
|
+
1. **ai-flow** - AI abstraction library (OpenAI responses API compatible)
|
|
581
|
+
2. **TensorZero** - Multi-provider routing (optional)
|
|
582
|
+
|
|
583
|
+
---
|
|
584
|
+
|
|
585
|
+
## References
|
|
586
|
+
|
|
587
|
+
- [Cloudflare Code Mode](https://blog.cloudflare.com/code-mode/) - Inspiration for sandbox approach
|
|
588
|
+
- [Graphite](https://graphite.dev/) - Stacked PR workflow reference
|