Skip to content

Commit 0afdedd

Browse files
author
lpb-docs
committed
feat(lpb-config): move pin sync to lpb-config sync-pins
- scripts: lpb-config gains sync-pins (+ --tag dev|main pipeline detection); lpb-devstack workspace sync-pins removed; release/validate/workspace stack scripts updated to the new command - docs: lpb-config.md (Align & Pin Sync section), lpb-devstack.md, lpb-cli.md, lpb-config skill, manual-tagging doc, env/fork/config docs - skills: repo-workflow skill resolution (reference-doc note, 0.0.N placeholder convention, sync-pins command); docs-workflow skill link-checker example fixed (was breaking the mandated validation) - docs: add install-browser + install-openspec setup pages Ports the docs-branch working session onto dev (orphaned switch-with-changes state resolved as a regular commit).
1 parent 22e3168 commit 0afdedd

17 files changed

Lines changed: 717 additions & 437 deletions

.pi/skills/localpibox-docs-workflow/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ failure means a raw code block on GitHub.
8787
3. **Links (devstack):** README links doc pages as `doc/<x>.md` — that path
8888
works on GitHub, and `generate.py` rewrites it to `reference/<x>.md` in
8989
the derived site copy. Doc pages link siblings with bare filenames
90-
(`[lpb CLI](lpb-cli.md)`). **Every linked `doc/*.md` must exist in
90+
(e.g. the link target `lpb-cli.md`). **Every linked `doc/*.md` must exist in
9191
generate.py's CONTENT map + mkdocs nav** or the site link 404s.
9292
4. **Callouts:** use `> ⚠️ …` blockquotes — they render on GitHub *and* the
9393
site. MkDocs admonitions (`!!! warning`) do **not** render on GitHub.
@@ -179,7 +179,7 @@ every repo touched, and (for release) `release status` shows `READY`.
179179
404s on the site.
180180
- **mike 2.x** has no `mike build`; use `mkdocs build` / `mike serve`.
181181
- **Version stamps:** generate.py matches the devstack VERSION **exactly**
182-
(substring matching confuses `0.0.62-lpb` with `0.0.62-lpb-dev`).
182+
(substring matching confuses `0.0.N-lpb` with `0.0.N-lpb-dev`).
183183
- **Docs branch is not a PR target** — content is merged `dev → docs` by
184184
`release docs-ready`; only the site plumbing lives there.
185185
- **mermaid/jsdom pin:** the parse check is pinned to `mermaid@11.12.2` +

.pi/skills/localpibox-repo-workflow/SKILL.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ on `main` is the trigger:
161161

162162
Then align the runtime to the stable pipeline:
163163
```bash
164-
lpb-devstack --tag main workspace sync --extensions # pins → stable tag
164+
lpb-config --tag main sync-pins # pins → stable version
165165
pi update --extensions
166166
lpb-devstack --tag main validate
167167
```
@@ -206,6 +206,8 @@ push. `bump` (without `--push`) warns about this.
206206
lpb-config status | update | reset [--force] | merge # config repo
207207
lpb-config render [--force] # regen runtime config from templates
208208
lpb-config align # pins → latest GitHub tags
209+
lpb-config sync-pins [--tag dev|main] # pins → pipeline's stack VERSION
210+
lpb-config setup # first-run setup wizard
209211
lpb-config memory show | setup # lpb-memory config
210212
```
211213

@@ -223,7 +225,7 @@ local keys win in the memory config).
223225
```bash
224226
lpb-devstack bump [--minor|--major] [--set V] [--no-commit] [--push]
225227
lpb-devstack tag-repos [--branch dev|main] [--version V] [--dry-run]
226-
lpb-devstack workspace status | sync [--extensions] | ensure [--fix]
228+
lpb-devstack workspace status | sync
227229
lpb-devstack validate
228230
lpb-devstack release status | docs-ready | promote [--yes] [--dry-run] [--rebase] [--force]
229231
lpb-devstack validate-hooks # full pre-commit checks (tests included)
@@ -246,7 +248,7 @@ Both tools are thin CLIs over the shared `scripts/localpibox/stack/` library
246248
merge) — this is the recovery path when the rendered file is lost or
247249
its pins are stale after a stack version move
248250
4. No model/provider preconfigured — user runs `/login lemonade`
249-
5. Pin sync: `lpb-devstack workspace sync --extensions`
251+
5. Pin sync: `lpb-config sync-pins`
250252
(main pipeline reads the stable version from devstack `origin/main`)
251253
6. `lpb-devstack validate` checks pins match the current stack version
252254
7. Persistent on the host volume — survives container rebuilds

doc/config-repo.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ Extensions are pinned in the `packages` array of `settings.json` as
6363
```json
6464
{
6565
"packages": [
66-
"git:github.com/lpb-stack/lemonade-pi-plugin@0.0.55-lpb-dev",
67-
"git:github.com/lpb-stack/lpb-memory@0.0.55-lpb-dev",
66+
"git:github.com/lpb-stack/lemonade-pi-plugin@0.0.N-lpb-dev",
67+
"git:github.com/lpb-stack/lpb-memory@0.0.N-lpb-dev",
6868
"npm:pi-mcp-adapter",
69-
"git:github.com/lpb-stack/pi-subagents@0.0.55-lpb-dev",
69+
"git:github.com/lpb-stack/pi-subagents@0.0.N-lpb-dev",
7070
"npm:pi-powerline-footer",
7171
"@upstash/context7-mcp"
7272
]
@@ -75,7 +75,7 @@ Extensions are pinned in the `packages` array of `settings.json` as
7575

7676
The `__LPB_VERSION__` placeholder in the template is replaced with the
7777
stack version at boot. Pins are synced to a new stack version by
78-
`lpb-devstack workspace sync-pins`.
78+
`lpb-config sync-pins`.
7979

8080
## Extension Clones
8181

@@ -146,7 +146,7 @@ lpb-config update
146146
lpb-devstack validate
147147

148148
# Sync extension pins to stack version
149-
lpb-devstack workspace sync-pins
149+
lpb-config sync-pins
150150

151151
# Reset config repo
152152
lpb-config reset

doc/env-vars.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export LPB_IMAGE_TAG=main
140140
lpb /project
141141

142142
# Pin an exact version
143-
lpb --tag 0.0.55-lpb-dev /project
143+
lpb --tag 0.0.N-lpb-dev /project
144144

145145
# Custom editor port (shell env wins over .env and defaults)
146146
export LPB_ED_PORT=8080

doc/fork-improvements.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,15 @@ per-call. Cannot point at local Lemonade server. Not usable with this stack.
224224

225225
### Support Files
226226

227+
Paths match the Dockerfile `COPY` lines (source of truth):
228+
227229
| Path | Purpose |
228230
|---|---|
229-
| `/opt/pi-support/bin/session-uuid` | Generate unique session IDs |
230-
| `/opt/pi-support/bin/browser-state-cleanup` | Cleanup browser state volumes |
231+
| `/opt/devstack/install-browser.py` | Install Chrome-for-Testing + agent-browser |
232+
| `/opt/devstack/validate.py` | Stack validation helper |
233+
| `/opt/pi-support/browser-state-cleanup.py` | Cleanup browser state volumes |
231234
| `/opt/pi-support/browser-validate.ts` | Browser validation entry point |
232-
| `/opt/pi-support/start.sh` | Start script |
235+
| `/opt/pi-support/install-openspec.py` | Bootstrap OpenSpec in a project |
236+
| `/opt/devstack/start.sh` | Container start script |
233237
| `/opt/pi-support/config/agent-browser-action-policy.json` | Agent action policies |
234238
| `/opt/pi-support/validate-subagent-output.ts` | Subagent output validation |

doc/install-browser.md

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# Browser Automation Setup (install-browser)
2+
3+
> Installed: `support/install-browser.py`
4+
> Purpose: Install Chrome-for-Testing + agent-browser MCP server
5+
> Platform: Container environment (Linux)
6+
7+
---
8+
9+
## What It Does
10+
11+
`install-browser` sets up browser automation for the LocalPibox stack by:
12+
13+
1. **Downloading Chrome-for-Testing** — fetches the latest stable Chrome from Google's official CDN
14+
2. **Installing agent-browser** — runs `agent-browser install`, then `install --with-deps` (Playwright dependency resolver)
15+
3. **Configuring container-safe defaults** — writes container-optimized Chrome launch args
16+
17+
### Why `install-browser` over `agent-browser install` alone
18+
19+
Running `agent-browser install --with-deps` directly downloads a system Chrome and handles deps, but:
20+
21+
- **Slow connections** — the built-in download has a hardcoded timeout that can fail on slow networks
22+
- **Chrome-for-Testing CDN**`install-browser` fetches from Google's official CDN (`googlechromelabs.github.io``storage.googleapis.com`) with explicit timeouts (30s for version fetch, no hard cap on the download itself)
23+
- **Exec bit self-healing** — Python's `zipfile.extractall()` drops Unix exec bits; `install-browser` detects and restores them automatically (Chrome crashes at startup if `chrome_crashpad_handler` is not executable)
24+
- **Container config merging** — writes `~/.agent-browser/config.json` with container-safe launch args, **merged** into any existing config (preserves user customizations)
25+
- **Version tracking** — installs from the same version JSON API that Playwright uses, keeping Chrome in sync with agent-browser's expectations
26+
- Visual testing of web apps
27+
- Browser-based validation (login flows, form submission, UI testing)
28+
- Capturing screenshots and accessibility audits
29+
- Testing the pi.dev agent-browser integration
30+
31+
---
32+
33+
## Installation Process
34+
35+
### Step 1: Chrome Download
36+
37+
```
38+
Downloads from: https://googlechromelabs.github.io/chrome-for-testing/
39+
Target path: /home/lpb/.agent-browser/browsers/chrome-<version>/
40+
```
41+
42+
- Fetches the latest stable version from Google's version JSON API
43+
- Extracts `chrome-linux64.zip` to the target directory
44+
- Restores Unix exec bits (Python's `zipfile.extractall()` drops them)
45+
- Self-heals existing installs if exec bits were lost
46+
47+
**Chrome executables tracked:**
48+
- `chrome` — main binary
49+
- `chrome_crashpad_handler` — crash reporter
50+
- `headless_shell` — headless mode shell
51+
52+
### Step 2: agent-browser Install
53+
54+
```
55+
Runs: agent-browser install → agent-browser install --with-deps
56+
```
57+
58+
- Installs the `agent-browser` CLI globally (already installed via npm)
59+
- Uses Playwright's dependency resolver to install only the exact libraries needed
60+
- System deps are installed per the downloaded Chrome version
61+
62+
### Step 3: Container Config
63+
64+
```
65+
Writes: ~/.agent-browser/config.json
66+
```
67+
68+
Container-safe launch args are merged into the config:
69+
```json
70+
{
71+
"args": "--no-sandbox,--no-first-run,--disable-gpu,--disable-crashpad"
72+
}
73+
```
74+
75+
These args are required because:
76+
- `--no-sandbox` — Chrome refuses to run as root without it
77+
- `--no-first-run` — skips the first-run dialog
78+
- `--disable-gpu` — no GPU in containers
79+
- `--disable-crashpad` — crash reports can't be sent from containers
80+
81+
The config is **merged** (not replaced) — user customizations are preserved.
82+
83+
### Step 4: Verification
84+
85+
The script verifies:
86+
- Chrome binary is present and executable
87+
- `agent-browser` binary is present
88+
- Chrome reports a valid version string
89+
- agent-browser reports installed status
90+
91+
---
92+
93+
## Usage
94+
95+
`install-browser` is installed in the PATH (user-space, no root/sudo needed).
96+
97+
```bash
98+
install-browser
99+
```
100+
101+
### What's Installed
102+
103+
| Component | Path | Version Source |
104+
|---|---|---|
105+
| Chrome | `/home/lpb/.agent-browser/browsers/chrome-<ver>/chrome-linux64/chrome` | Google CDN |
106+
| agent-browser | `/home/lpb/.npm-global/bin/agent-browser` | npm global install |
107+
| Config | `~/.agent-browser/config.json` | Generated on first run |
108+
109+
### Source Files
110+
111+
| File | Purpose |
112+
|---|---|
113+
| `support/install-browser.py` | Python script — main logic |
114+
| `~/.local/bin/install-browser` | User-space CLI wrapper (in PATH) |
115+
116+
### Self-Healing
117+
118+
If Chrome is extracted without exec bits (e.g., from a broken zip extraction), `install-browser` detects and restores them automatically. The following files are checked:
119+
- `chrome`
120+
- `chrome_crashpad_handler`
121+
- `headless_shell`
122+
123+
---
124+
125+
## Architecture
126+
127+
```
128+
┌─────────────────────────────────────────────────────────────────────┐
129+
│ install-browser.py │
130+
│ │
131+
│ 1. fetch_stable_chrome_version() │
132+
│ → GET https://googlechromelabs.github.io/chrome-for-testing/ │
133+
│ last-known-good-versions-with-downloads.json │
134+
│ │
135+
│ 2. install_chrome(cons) │
136+
│ → Download chrome-linux64.zip │
137+
│ → Extract with mode restoration │
138+
│ → Self-heal exec bits if needed │
139+
│ │
140+
│ 3. install_agent_browser(cons) │
141+
│ → Run agent-browser install │
142+
│ → Run agent-browser install --with-deps │
143+
│ → Merge container-safe args into config.json │
144+
│ │
145+
│ 4. verify_installation(cons) │
146+
│ → Check Chrome binary exists + executable │
147+
│ → Run chrome --version │
148+
│ → Run agent-browser --version │
149+
└─────────────────────────────────────────────────────────────────────┘
150+
```
151+
152+
---
153+
154+
## Troubleshooting
155+
156+
### Chrome PermissionError (errno 13)
157+
158+
**Symptom:** Chrome crashes on startup with `PermissionError: [Errno 13] Permission denied`
159+
160+
**Cause:** Chrome binary lacks exec bit (Python's `zipfile.extractall()` drops Unix modes)
161+
162+
**Fix:** Re-run `install-browser` — it restores exec bits automatically:
163+
```bash
164+
install-browser
165+
```
166+
167+
### Chrome Already Installed
168+
169+
The script is idempotent — if Chrome is already present and executable, it skips installation:
170+
```
171+
Chrome already installed at /home/lpb/.agent-browser/browsers/chrome-123.0.6275.0
172+
```
173+
174+
### Missing System Dependencies
175+
176+
If `agent-browser install --with-deps` fails partially, Chrome may work but with reduced functionality. Check:
177+
```bash
178+
agent-browser install --with-deps
179+
```
180+
181+
### Chrome Version Mismatch
182+
183+
If Chrome version doesn't match Playwright's expectations:
184+
```bash
185+
agent-browser install # reinstalls Playwright browsers
186+
agent-browser install --with-deps # reinstalls system deps
187+
```
188+
189+
---
190+
191+
## Current Status
192+
193+
| Component | Status | Version |
194+
|---|---|---|
195+
| Chrome | ✅ Installed | Latest stable (auto-updated) |
196+
| agent-browser | ✅ Installed | Via npm global |
197+
| Config | ✅ Generated | Container-safe args merged |
198+
| MCP Server | ✅ Ready | `agent-browser` MCP available |
199+
200+
**Last verified:** 2026-08-25

0 commit comments

Comments
 (0)