opengstack 0.13.4

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.
Files changed (73) hide show
  1. package/AGENTS.md +47 -0
  2. package/CLAUDE.md +370 -0
  3. package/LICENSE +21 -0
  4. package/README.md +80 -0
  5. package/SKILL.md +226 -0
  6. package/autoplan/SKILL.md +96 -0
  7. package/autoplan/SKILL.md.tmpl +694 -0
  8. package/benchmark/SKILL.md +358 -0
  9. package/benchmark/SKILL.md.tmpl +222 -0
  10. package/browse/SKILL.md +396 -0
  11. package/browse/SKILL.md.tmpl +131 -0
  12. package/canary/SKILL.md +89 -0
  13. package/canary/SKILL.md.tmpl +212 -0
  14. package/careful/SKILL.md +58 -0
  15. package/careful/SKILL.md.tmpl +56 -0
  16. package/codex/SKILL.md +90 -0
  17. package/codex/SKILL.md.tmpl +417 -0
  18. package/connect-chrome/SKILL.md +87 -0
  19. package/connect-chrome/SKILL.md.tmpl +195 -0
  20. package/cso/SKILL.md +93 -0
  21. package/cso/SKILL.md.tmpl +606 -0
  22. package/design-consultation/SKILL.md +94 -0
  23. package/design-consultation/SKILL.md.tmpl +415 -0
  24. package/design-review/SKILL.md +94 -0
  25. package/design-review/SKILL.md.tmpl +290 -0
  26. package/design-shotgun/SKILL.md +91 -0
  27. package/design-shotgun/SKILL.md.tmpl +285 -0
  28. package/docs/designs/CHROME_VS_CHROMIUM_EXPLORATION.md +84 -0
  29. package/docs/designs/CONDUCTOR_CHROME_SIDEBAR_INTEGRATION.md +57 -0
  30. package/docs/designs/CONDUCTOR_SESSION_API.md +108 -0
  31. package/docs/designs/DESIGN_SHOTGUN.md +451 -0
  32. package/docs/designs/DESIGN_TOOLS_V1.md +622 -0
  33. package/docs/skills.md +880 -0
  34. package/document-release/SKILL.md +91 -0
  35. package/document-release/SKILL.md.tmpl +359 -0
  36. package/freeze/SKILL.md +78 -0
  37. package/freeze/SKILL.md.tmpl +77 -0
  38. package/gstack-upgrade/SKILL.md +224 -0
  39. package/gstack-upgrade/SKILL.md.tmpl +222 -0
  40. package/guard/SKILL.md +78 -0
  41. package/guard/SKILL.md.tmpl +77 -0
  42. package/investigate/SKILL.md +105 -0
  43. package/investigate/SKILL.md.tmpl +194 -0
  44. package/land-and-deploy/SKILL.md +88 -0
  45. package/land-and-deploy/SKILL.md.tmpl +881 -0
  46. package/office-hours/SKILL.md +96 -0
  47. package/office-hours/SKILL.md.tmpl +645 -0
  48. package/package.json +43 -0
  49. package/plan-ceo-review/SKILL.md +94 -0
  50. package/plan-ceo-review/SKILL.md.tmpl +811 -0
  51. package/plan-design-review/SKILL.md +92 -0
  52. package/plan-design-review/SKILL.md.tmpl +446 -0
  53. package/plan-eng-review/SKILL.md +93 -0
  54. package/plan-eng-review/SKILL.md.tmpl +303 -0
  55. package/qa/SKILL.md +95 -0
  56. package/qa/SKILL.md.tmpl +316 -0
  57. package/qa-only/SKILL.md +89 -0
  58. package/qa-only/SKILL.md.tmpl +101 -0
  59. package/retro/SKILL.md +89 -0
  60. package/retro/SKILL.md.tmpl +820 -0
  61. package/review/SKILL.md +92 -0
  62. package/review/SKILL.md.tmpl +281 -0
  63. package/scripts/cleanup.py +100 -0
  64. package/scripts/filter-skills.sh +114 -0
  65. package/scripts/filter_skills.py +140 -0
  66. package/setup-browser-cookies/SKILL.md +216 -0
  67. package/setup-browser-cookies/SKILL.md.tmpl +81 -0
  68. package/setup-deploy/SKILL.md +92 -0
  69. package/setup-deploy/SKILL.md.tmpl +215 -0
  70. package/ship/SKILL.md +90 -0
  71. package/ship/SKILL.md.tmpl +636 -0
  72. package/unfreeze/SKILL.md +37 -0
  73. package/unfreeze/SKILL.md.tmpl +36 -0
@@ -0,0 +1,84 @@
1
+ # Chrome vs Chromium: Why We Use Playwright's Bundled Chromium
2
+
3
+ ## The Original Vision
4
+
5
+ When we built `$B connect`, the plan was to connect to the user's **real Chrome browser** — the one with their cookies, sessions, extensions, and open tabs. No more cookie import. The design called for:
6
+
7
+ 1. `chromium.connectOverCDP(wsUrl)` connecting to a running Chrome via CDP
8
+ 2. Quit Chrome gracefully, relaunch with `--remote-debugging-port=9222`
9
+ 3. Access the user's real browsing context
10
+
11
+ This is why `chrome-launcher.ts` existed (361 LOC of browser binary discovery, CDP port probing, and runtime detection) and why the method was called `connectCDP()`.
12
+
13
+ ## What Actually Happened
14
+
15
+ Real Chrome silently blocks `--load-extension` when launched via Playwright's `channel: 'chrome'`. The extension wouldn't load. We needed the extension for the side panel (activity feed, refs, chat).
16
+
17
+ The implementation fell back to `chromium.launchPersistentContext()` with Playwright's bundled Chromium — which reliably loads extensions via `--load-extension` and `--disable-extensions-except`. But the naming stayed: `connectCDP()`, `connectionMode: 'cdp'`, `BROWSE_CDP_URL`, `chrome-launcher.ts`.
18
+
19
+ The original vision (access user's real browser state) was never implemented. We launched a fresh browser every time — functionally identical to Playwright's Chromium, but with 361 lines of dead code and misleading names.
20
+
21
+ ## The Discovery (2026-03-22)
22
+
23
+ During a `/office-hours` design session, we traced the architecture and discovered:
24
+
25
+ 1. `connectCDP()` doesn't use CDP — it calls `launchPersistentContext()`
26
+ 2. `connectionMode: 'cdp'` is misleading — it's just "headed mode"
27
+ 3. `chrome-launcher.ts` is dead code — its only import was in an unreachable `attemptReconnect()` method
28
+ 4. `preExistingTabIds` was designed for protecting real Chrome tabs we never connect to
29
+ 5. `$B handoff` (headless → headed) used a different API (`launch()` + `newContext()`) that couldn't load extensions, creating two different "headed" experiences
30
+
31
+ ## The Fix
32
+
33
+ ### Renamed
34
+ - `connectCDP()` → `launchHeaded()`
35
+ - `connectionMode: 'cdp'` → `connectionMode: 'headed'`
36
+ - `BROWSE_CDP_URL` → `BROWSE_HEADED`
37
+
38
+ ### Deleted
39
+ - `chrome-launcher.ts` (361 LOC)
40
+ - `attemptReconnect()` (dead method)
41
+ - `preExistingTabIds` (dead concept)
42
+ - `reconnecting` field (dead state)
43
+ - `cdp-connect.test.ts` (tests for deleted code)
44
+
45
+ ### Converged
46
+ - `$B handoff` now uses `launchPersistentContext()` + extension loading (same as `$B connect`)
47
+ - One headed mode, not two
48
+ - Handoff gives you the extension + side panel for free
49
+
50
+ ### Gated
51
+ - Sidebar chat behind `--chat` flag
52
+ - `$B connect` (default): activity feed + refs only
53
+ - `$B connect --chat`: + experimental standalone chat agent
54
+
55
+ ## Architecture (after)
56
+
57
+ ```
58
+ Browser States:
59
+ HEADLESS (default) ←→ HEADED ($B connect or $B handoff)
60
+ Playwright Playwright (same engine)
61
+ launch() launchPersistentContext()
62
+ invisible visible + extension + side panel
63
+
64
+ Sidebar (orthogonal add-on, headed only):
65
+ Activity tab — always on, shows live browse commands
66
+ Refs tab — always on, shows @ref overlays
67
+ Chat tab — opt-in via --chat, experimental standalone agent
68
+
69
+ Data Bridge (sidebar → workspace):
70
+ Sidebar writes to .context/sidebar-inbox/*.json
71
+ Workspace reads via $B inbox
72
+ ```
73
+
74
+ ## Why Not Real Chrome?
75
+
76
+ Real Chrome blocks `--load-extension` when launched by Playwright. This is a Chrome security feature — extensions loaded via command-line args are restricted in Chromium-based browsers to prevent malicious extension injection.
77
+
78
+ Playwright's bundled Chromium doesn't have this restriction because it's designed for testing and automation. The `ignoreDefaultArgs` option lets us bypass Playwright's own extension-blocking flags.
79
+
80
+ If we ever want to access the user's real cookies/sessions, the path is:
81
+ 1. Cookie import (already works via `$B cookie-import`)
82
+ 2. Conductor session injection (future — sidebar sends messages to workspace agent)
83
+
84
+ Not reconnecting to real Chrome.
@@ -0,0 +1,57 @@
1
+ # Chrome Sidebar + Conductor: What We Need
2
+
3
+ ## What we're building
4
+
5
+ Right now when Claude is working in a Conductor workspace — editing files, running tests, browsing your app — you can only watch from Conductor's chat window. If Claude is doing QA on your website, you see tool calls scrolling by but you can't actually *see* the browser.
6
+
7
+ We built a Chrome sidebar that fixes this. When you run `$B connect`, Chrome opens with a side panel that shows everything Claude is doing in real time. You can type messages in the sidebar and Claude acts on them — "click the signup button", "go to the settings page", "summarize what you see."
8
+
9
+ The problem: the sidebar currently runs its own separate Claude instance. It can't see what the main Conductor session is doing, and the main session can't see what the sidebar is doing. They're two separate agents that don't talk to each other.
10
+
11
+ The fix is simple: make the sidebar a *window into* the Conductor session, not a separate thing.
12
+
13
+ ## What we need from Conductor (3 things)
14
+
15
+ ### 1. Let us watch what the agent is doing
16
+
17
+ We need a way to subscribe to the active session's events. Something like an SSE stream or WebSocket that sends us events as they happen:
18
+
19
+ - "Claude is editing `src/App.tsx`"
20
+ - "Claude is running `npm test`"
21
+ - "Claude says: I'll fix the CSS issue..."
22
+
23
+ The sidebar already knows how to render these events — tool calls show as compact badges, text shows as chat bubbles. We just need a pipe from Conductor's session to our extension.
24
+
25
+ ### 2. Let us send messages into the session
26
+
27
+ When the user types "click the other button" in the Chrome sidebar, that message should appear in the Conductor session as if the user typed it in the workspace chat. The agent picks it up on its next turn and acts on it.
28
+
29
+ This is the magic moment: user is watching Chrome, sees something wrong, types a correction in the sidebar, and Claude responds — without the user ever switching windows.
30
+
31
+ ### 3. Let us create a workspace from a directory
32
+
33
+ When `$B connect` launches, it creates a git worktree for file isolation. We want to register that worktree as a Conductor workspace so the user can see the sidebar agent's file changes in Conductor's file tree. This also sets up the foundation for multiple browser sessions, each with their own workspace.
34
+
35
+ ## Why this matters
36
+
37
+ Today, `/qa` and `/design-review` feel like a black box. Claude says "I found 3 issues" but you can't see what it's looking at. With the sidebar connected to Conductor:
38
+
39
+ - **You watch Claude test your app** in real time — every click, every navigation, every screenshot appears in Chrome while you watch
40
+ - **You can interrupt** — "no, test the mobile view" or "skip that page" — without switching windows
41
+ - **One agent, two views** — the same Claude that's editing your code is also controlling the browser. No context duplication, no stale state
42
+
43
+ ## What's already built (gstack side)
44
+
45
+ Everything on our side is done and shipping:
46
+
47
+ - Chrome extension that auto-loads when you run `$B connect`
48
+ - Side panel that auto-opens (zero setup for the user)
49
+ - Streaming event renderer (tool calls, text, results)
50
+ - Chat input with message queuing
51
+ - Reconnect logic with status banners
52
+ - Session management with persistent chat history
53
+ - Agent lifecycle (spawn, stop, kill, timeout detection)
54
+
55
+ The only change on our side: swap the data source from "local `claude -p` subprocess" to "Conductor session stream." The extension code stays the same.
56
+
57
+ **Estimated effort:** 2-3 days Conductor engineering, 1 day gstack integration.
@@ -0,0 +1,108 @@
1
+ # Conductor Session Streaming API Proposal
2
+
3
+ ## Problem
4
+
5
+ When Claude controls your real browser via CDP (gstack `$B connect`), you look at two
6
+ windows: **Conductor** (to see Claude's thinking) and **Chrome** (to see Claude's actions).
7
+
8
+ gstack's Chrome extension Side Panel shows browse activity — every command, result,
9
+ and error. But for *full* session mirroring (Claude's thinking, tool calls, code edits),
10
+ the Side Panel needs Conductor to expose the conversation stream.
11
+
12
+ ## What this enables
13
+
14
+ A "Session" tab in the gstack Chrome extension Side Panel that shows:
15
+ - Claude's thinking/content (truncated for performance)
16
+ - Tool call names + icons (Edit, Bash, Read, etc.)
17
+ - Turn boundaries with cost estimates
18
+ - Real-time updates as the conversation progresses
19
+
20
+ The user sees everything in one place — Claude's actions in their browser + Claude's
21
+ thinking in the Side Panel — without switching windows.
22
+
23
+ ## Proposed API
24
+
25
+ ### `GET http://127.0.0.1:{PORT}/workspace/{ID}/session/stream`
26
+
27
+ Server-Sent Events endpoint that re-emits Claude Code's conversation as NDJSON events.
28
+
29
+ **Event types** (reuse Claude Code's `--output-format stream-json` format):
30
+
31
+ ```
32
+ event: assistant
33
+ data: {"type":"assistant","content":"Let me check that page...","truncated":true}
34
+
35
+ event: tool_use
36
+ data: {"type":"tool_use","name":"Bash","input":"$B snapshot","truncated_input":true}
37
+
38
+ event: tool_result
39
+ data: {"type":"tool_result","name":"Bash","output":"[snapshot output...]","truncated_output":true}
40
+
41
+ event: turn_complete
42
+ data: {"type":"turn_complete","input_tokens":1234,"output_tokens":567,"cost_usd":0.02}
43
+ ```
44
+
45
+ **Content truncation:** Tool inputs/outputs capped at 500 chars in the stream. Full
46
+ data stays in Conductor's UI. The Side Panel is a summary view, not a replacement.
47
+
48
+ ### `GET http://127.0.0.1:{PORT}/api/workspaces`
49
+
50
+ Discovery endpoint listing active workspaces.
51
+
52
+ ```json
53
+ {
54
+ "workspaces": [
55
+ {
56
+ "id": "abc123",
57
+ "name": "gstack",
58
+ "branch": "garrytan/chrome-extension-ctrl",
59
+ "directory": "/Users/garry/gstack",
60
+ "pid": 12345,
61
+ "active": true
62
+ }
63
+ ]
64
+ }
65
+ ```
66
+
67
+ The Chrome extension auto-selects a workspace by matching the browse server's git repo
68
+ (from `/health` response) to a workspace's directory or name.
69
+
70
+ ## Security
71
+
72
+ - **Localhost-only.** Same trust model as Claude Code's own debug output.
73
+ - **No auth required.** If Conductor wants auth, include a Bearer token in the
74
+ workspace listing that the extension passes on SSE requests.
75
+ - **Content truncation** is a privacy feature — long code outputs, file contents, and
76
+ sensitive tool results never leave Conductor's full UI.
77
+
78
+ ## What gstack builds (extension side)
79
+
80
+ Already scaffolded in the Side Panel "Session" tab (currently shows placeholder).
81
+
82
+ When Conductor's API is available:
83
+ 1. Side Panel discovers Conductor via port probe or manual entry
84
+ 2. Fetches `/api/workspaces`, matches to browse server's repo
85
+ 3. Opens `EventSource` to `/workspace/{id}/session/stream`
86
+ 4. Renders: assistant messages, tool names + icons, turn boundaries, cost
87
+ 5. Falls back gracefully: "Connect Conductor for full session view"
88
+
89
+ Estimated effort: ~200 LOC in `sidepanel.js`.
90
+
91
+ ## What Conductor builds (server side)
92
+
93
+ 1. SSE endpoint that re-emits Claude Code's stream-json per workspace
94
+ 2. `/api/workspaces` discovery endpoint with active workspace list
95
+ 3. Content truncation (500 char cap on tool inputs/outputs)
96
+
97
+ Estimated effort: ~100-200 LOC if Conductor already captures the Claude Code stream
98
+ internally (which it does for its own UI rendering).
99
+
100
+ ## Design decisions
101
+
102
+ | Decision | Choice | Rationale |
103
+ |----------|--------|-----------|
104
+ | Transport | SSE (not WebSocket) | Unidirectional, auto-reconnect, simpler |
105
+ | Format | Claude's stream-json | Conductor already parses this; no new schema |
106
+ | Discovery | HTTP endpoint (not file) | Chrome extensions can't read filesystem |
107
+ | Auth | None (localhost) | Same as browse server, CDP port, Claude Code |
108
+ | Truncation | 500 chars | Side Panel is ~300px wide; long content useless |