Skip to content

Commit 1169a61

Browse files
committed
Merge remote-tracking branch 'origin/dev'
2 parents dc168e6 + a8bd12c commit 1169a61

39 files changed

Lines changed: 3279 additions & 1390 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ LPB_AGENT_BROWSER_IDLE_TIMEOUT_MS=300000
7979
# 0.20 → 262K context → 52.4K max tokens
8080
# LPB_MAX_TOKENS_CONTEXT_RATIO=0.06
8181

82+
# SSH port for `lpb --ssh` (default: 2222)
83+
# LPB_SSH_PORT=2222
84+
8285
# ─── Persistence ─────────────────────────────────────────────────────────────
8386

8487
# Persist gh CLI auth to ~/.config/gh inside container, stored in

.github/workflows/build-and-publish.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# Phase 2: build-cli — only if VERSION changed
1919
# Phase 3: build-web — only if VERSION changed
2020
# Phase 4: tag-repos — only if VERSION changed (after build)
21+
# Phase 4.5: docs-publish — main only, stable docs version (mike)
2122
# Phase 5: status — always runs
2223
# - Cron / manual dispatch always build (keep image fresh / on-demand)
2324
# - Dev pipeline (push to dev): 0.0.x-lpb-dev, images :dev-*, :{v}-*, :{sha}-*
@@ -371,6 +372,78 @@ jobs:
371372
exit 1
372373
fi
373374
375+
# ──────────────────────────────────────────────────────
376+
# Phase 3.5: Publish stable docs (main pipeline only)
377+
# Docs are gated into the release BEFORE promotion:
378+
# lpb-devstack release docs-ready (merge dev→docs, review, flag)
379+
# lpb-devstack release promote (refuses unless docs are ready)
380+
# This job re-verifies the flag (catches --force promotions), then cuts
381+
# the immutable docs version and points the `latest` alias at it.
382+
# Output: gh-pages branch (mike) → https://lpb-stack.github.io/devstack/<version>/
383+
# ──────────────────────────────────────────────────────
384+
docs-publish:
385+
name: Publish docs (mike)
386+
runs-on: ubuntu-latest
387+
timeout-minutes: 20
388+
needs: [tag-repos, VERSION_CHECK]
389+
if: ${{ github.ref_name == 'main' && github.event_name == 'push' && needs.VERSION_CHECK.outputs.changed == 'true' && needs.tag-repos.result == 'success' }}
390+
steps:
391+
- name: Checkout docs branch
392+
uses: actions/checkout@v6
393+
with:
394+
ref: docs
395+
fetch-depth: 0
396+
397+
- name: Verify docs flag
398+
run: |
399+
set -e
400+
VERSION=$(git show origin/main:VERSION | tr -d '[:space:]')
401+
FLAG=$(git show HEAD:DOCS_READY 2>/dev/null | tr -d '[:space:]' || true)
402+
if [ "$FLAG" != "$VERSION" ]; then
403+
echo "::error::docs not flagged ready for $VERSION (DOCS_READY='${FLAG:-<missing>}') — run 'lpb-devstack release docs-ready' before promoting, then re-run this job"
404+
exit 1
405+
fi
406+
echo "docs flag OK: $FLAG"
407+
408+
- name: Fetch stack repos at the release tag
409+
run: |
410+
set -e
411+
VERSION=$(git show origin/main:VERSION | tr -d '[:space:]')
412+
mkdir -p ws/git
413+
git clone --quiet https://github.com/lpb-stack/config.git ws/config
414+
for r in lpb-memory pi-subagents lemonade-pi-plugin; do
415+
git clone --quiet "https://github.com/lpb-stack/$r.git" "ws/git/$r"
416+
done
417+
git clone --quiet https://github.com/lpb-stack/pi.git ws/pi
418+
for d in ws/config ws/git/lpb-memory ws/git/pi-subagents \
419+
ws/git/lemonade-pi-plugin ws/pi; do
420+
git -C "$d" fetch --quiet --depth 1 origin tag "$VERSION"
421+
git -C "$d" checkout -q "$VERSION"
422+
done
423+
424+
- name: Install docs tooling
425+
run: python3 -m pip install --quiet "mkdocs-material==9.7.7" mike
426+
427+
- name: Prepare docs tree + version stamp
428+
env:
429+
AGENT_DIR: ${{ github.workspace }}/ws/config
430+
LPB_AGENT_GIT: ${{ github.workspace }}/ws/git
431+
LPB_WORKSPACE_ROOT: ${{ github.workspace }}/ws
432+
run: python3 scripts/generate.py --tag "$(git show origin/main:VERSION | tr -d '[:space:]')"
433+
434+
- name: Configure git identity for mike
435+
run: |
436+
git config user.name "lpb-docs"
437+
git config user.email "ci@lpb-stack.dev"
438+
439+
- name: Publish tagged docs version
440+
run: |
441+
set -e
442+
VERSION=$(git show origin/main:VERSION | tr -d '[:space:]')
443+
mike deploy "$VERSION" latest --push --update-aliases
444+
mike set-default latest --push
445+
echo "Docs version: https://lpb-stack.github.io/devstack/$VERSION/"
446+
374447
status:
375448
name: Build status
376449
needs: [build-cli, build-web]

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

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,26 @@ commits to the repo (manual tagging).
110110

111111
## Stable Release Procedure (dev → main)
112112

113+
**Docs are gated into the release**`promote` refuses until the docs
114+
branch is flagged ready for the version being released (`--force`
115+
overrides). Doc content changes on `dev` in place as usual; the one-shot
116+
docs sync + review happens at release time via `docs-ready`.
117+
113118
**`lpb-devstack release` is the tool** (there is no other local version path).
114119

115120
```bash
116-
# 1. Readiness check (all 6 repos, non-destructive, fetches first)
121+
# 0. Flag docs as reviewed for the release (merge dev→docs, build site,
122+
# review with `cd ~/.lpb-stack/docs-preview && mike serve`, confirm →
123+
# commits DOCS_READY=<stable-version> on the docs branch + pushes)
124+
lpb-devstack release docs-ready
125+
126+
# 1. Readiness check (all 6 repos + docs verdict, non-destructive, fetches first)
117127
lpb-devstack release status
118128

119129
# 2. Inspect the exact plan without changing anything
120130
lpb-devstack release promote --dry-run
121131

122-
# 3. Promote (interactive confirmation)
132+
# 3. Promote (interactive confirmation; blocked unless docs are READY)
123133
lpb-devstack release promote
124134
```
125135

@@ -150,9 +160,17 @@ lpb-devstack --tag main validate
150160
```
151161

152162
Flags: `--yes` (skip confirmation), `--dry-run` (plan only), `--rebase`
153-
(first-release mode for unrelated histories). Re-runs are safe: promoted
163+
(first-release mode for unrelated histories), `--force` (promote even if
164+
docs are not flagged ready). Re-runs are safe: promoted
154165
repos fast-forward or no-op.
155166

167+
Docs readiness verdicts (`release status`, checked by `promote`):
168+
- `READY``DOCS_READY` on the `docs` branch matches the release version
169+
and doc content matches `dev`
170+
- `MISSING` — no flag yet → run `lpb-devstack release docs-ready`
171+
- `STALE` — flag for another version, or doc content changed on `dev`
172+
after flagging → re-run `docs-ready`
173+
156174
## Shipping a Dev Image (the common case)
157175

158176
```bash
@@ -179,18 +197,28 @@ push. `bump` (without `--push`) warns about this.
179197

180198
```bash
181199
lpb-config status | update | reset [--force] | merge # config repo
200+
lpb-config render [--force] # regen runtime config from templates
182201
lpb-config align # pins → latest GitHub tags
183202
lpb-config memory show | setup # lpb-memory config
184203
```
185204

205+
`render` recreates the gitignored runtime files (`settings.json`,
206+
`lpb-memory-config.json`) from the repo's templates. lpb-config auto-renders
207+
after `reset` (force) / `update` / `merge` (non-forcing): without it the
208+
rendered config was unrecoverable after `reset` (start.sh only renders on
209+
first boot, gated by `~/.pi/.initialized`). Non-forcing render never
210+
overwrites — it creates missing files and warns on stale pins; `--force`
211+
merges (user keys/packages preserved, template pins win in settings.json,
212+
local keys win in the memory config).
213+
186214
**`lpb-devstack`** — DevOps workspace tool (container + host):
187215

188216
```bash
189217
lpb-devstack bump [--minor|--major] [--set V] [--no-commit] [--push]
190218
lpb-devstack tag-repos [--branch dev|main] [--version V] [--dry-run]
191219
lpb-devstack workspace status | sync [--extensions] | ensure [--fix]
192220
lpb-devstack validate
193-
lpb-devstack release status | promote [--yes] [--dry-run] [--rebase]
221+
lpb-devstack release status | docs-ready | promote [--yes] [--dry-run] [--rebase] [--force]
194222
lpb-devstack validate-hooks # full pre-commit checks (tests included)
195223

196224
# Pipeline override (dev vs main) on any command:
@@ -207,11 +235,14 @@ Both tools are thin CLIs over the shared `scripts/localpibox/stack/` library
207235

208236
1. Config repo ships `settings.json.template` with `__LPB_VERSION__` placeholders
209237
2. First boot: `start.sh` generates `settings.json` (replaces placeholders)
210-
3. No model/provider preconfigured — user runs `/login lemonade`
211-
4. Pin sync: `lpb-devstack workspace sync --extensions`
238+
3. `lpb-config render` regenerates it on demand (auto after reset/update/
239+
merge) — this is the recovery path when the rendered file is lost or
240+
its pins are stale after a stack version move
241+
4. No model/provider preconfigured — user runs `/login lemonade`
242+
5. Pin sync: `lpb-devstack workspace sync --extensions`
212243
(main pipeline reads the stable version from devstack `origin/main`)
213-
5. `lpb-devstack validate` checks pins match the current stack version
214-
6. Persistent on the host volume — survives container rebuilds
244+
6. `lpb-devstack validate` checks pins match the current stack version
245+
7. Persistent on the host volume — survives container rebuilds
215246

216247
Pins look like: `git:github.com/lpb-stack/pi-subagents@0.0.57-lpb-dev`
217248

@@ -269,7 +300,12 @@ Jobs:
269300
and **fails the run if any repo's tag fails** (a partially-tagged stack
270301
is a release bug — re-running the job is idempotent, 422 = already
271302
tagged). A missing branch aborts immediately.
272-
5. **status** — always runs; passes when builds were skipped (no VERSION
303+
5. **docs-publish** — main pipeline only, after tag-repos, only if VERSION
304+
changed: re-verifies the `DOCS_READY` flag on the `docs` branch matches
305+
the released VERSION (catches `--force` promotions), then
306+
`mike deploy <version> latest` + `set-default latest``gh-pages`
307+
branch. Served at `lpb-stack.github.io/devstack/<version>/`.
308+
6. **status** — always runs; passes when builds were skipped (no VERSION
273309
change), fails otherwise only on build failure
274310

275311
Images: `ghcr.io/lpb-stack/devstack` in two flavours per tag — `…-cli`

Dockerfile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,13 @@ COPY support/validate-subagent-output.ts /opt/pi-support/validate-subagent-outpu
174174
COPY support/config/ /opt/pi-support/config/
175175
COPY support/docs/ /opt/pi-support/docs/
176176
COPY support/schemas/ /opt/pi-support/schemas/
177-
# Shared Python helpers used by the ported support tools (import via the
178-
# script directory, which Python adds to sys.path automatically).
177+
# ── Shared Python helpers + user-facing CLIs ─────────────────────────────
178+
# The localpibox package and the lpb-config/lpb-devstack CLIs are the source of
179+
# truth in scripts/ (single copy — no support/ duplicates). They must live
180+
# under /opt/pi-support/ for their sys.path resolution.
179181
COPY scripts/localpibox/ /opt/pi-support/localpibox/
182+
COPY --chmod=755 scripts/lpb-config /opt/pi-support/lpb-config
183+
COPY --chmod=755 scripts/lpb-devstack /opt/pi-support/lpb-devstack
180184

181185
# ── Devstack deployment scripts ──
182186
COPY --chmod=755 support/install-browser.py /opt/devstack/install-browser.py
@@ -204,8 +208,6 @@ RUN mkdir -p /home/lpb/.local/bin \
204208
# lpb-config / lpb-devstack need to live under /opt/pi-support/ for their
205209
# sys.path resolution (the localpibox package is copied there above).
206210
# Symlinks at ~/.local/bin give users the clean CLI names.
207-
COPY --chmod=755 support/lpb-config /opt/pi-support/lpb-config
208-
COPY --chmod=755 support/lpb-devstack /opt/pi-support/lpb-devstack
209211

210212
# ── Root operations: ownership + gitconfig + shell PATH ─────────────────────
211213
USER root

README.md

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,16 @@ lpb # resumes your last project (or ~)
2626
```
2727

2828
On the **first run** the container pulls the image, clones the config preset,
29-
generates `settings.json`, and installs the extensions — then Pi starts.
30-
You'll be asked to connect a model:
29+
generates `settings.json`, and installs the extensions. Before Pi starts, the
30+
**first-run setup wizard** walks you through connecting your Lemonade server:
3131

32-
```
33-
/login lemonade # connect to the local Lemonade server (must be running on the host)
34-
/model # pick a model (e.g. the Qwen3.6-35B reasoning model)
35-
```
32+
1. server URL (pre-filled from `LEMONADE_BASE_URL`, health-checked)
33+
2. API key (a placeholder like `lemonade` is fine for a local server)
34+
3. default model (picked from the server's model list)
35+
4. lpb-memory configuration
36+
37+
After that Pi starts fully configured. Re-run it any time inside the
38+
container with `lpb-config setup --reconfigure`.
3639

3740
### Common commands
3841

@@ -119,7 +122,8 @@ CI tags images per pipeline: `:0.0.x-lpb[-dev]-cli/web` (versioned),
119122
| `lpb /path` | Pi CLI session (foreground); no path → last project or `~` |
120123
| `lpb --web /path` | VSCodium (background); `--port 8080` to change the port |
121124
| `lpb --shell /path` | Interactive bash inside the container |
122-
| `lpb --ssh [pubkey] /path` | sshd server in the container for remote login |
125+
| `lpb --ssh [pubkey\|path] /path` | sshd server in the container for remote login (key auto-detected from `~/.ssh` when omitted) |
126+
| `lpb --ssh --ssh-password [pw]` | SSH password login (random if omitted, shown once; can combine with a key) |
123127
| `lpb --stop` / `--remove` / `--logs` | Stop / stop+remove+state cleanup / stream logs |
124128
| `lpb --update` | Self-update launcher + pull latest image for the selected pipeline |
125129
| `lpb /path -- <pi-args>` | Pass args to Pi, e.g. `lpb /path -- -p "summarize this repo"` |
@@ -194,14 +198,14 @@ flowchart LR
194198
## Forked Repos & Upstream Policy
195199

196200
Fork URLs and branches are tracked in `lpb.stack.env` at the repo root.
197-
Each fork carries its LocalPibox work as a **single squashed commit** on top
198-
of upstream, so the delta vs upstream is always one clean patch.
201+
Each fork keeps its LocalPibox work as clean commits on top of upstream
202+
merges, so the delta vs upstream can always be extracted as one patch.
199203

200204
| Repo | Upstream | LocalPibox work | Update policy |
201205
|---|---|---|---|
202206
| **pi** | `earendil-works/pi` (v0.84.2) | Qwen `reasoning_effort` + context-overflow patches | rebase onto new upstream releases |
203207
| **lemonade-pi-plugin** | `lemonade-sdk/lemonade-pi-plugin` (no stable release) | Qwen thinking + vision support | follow upstream `main`, check periodically |
204-
| **pi-subagents** | `tintinweb/pi-subagents` (v0.14.3) | centralized local-first subagent model registry | follow `master`; submit upstream if clean |
208+
| **pi-subagents** | `tintinweb/pi-subagents` (v0.16.1) | centralized local-first subagent model registry | follow upstream; merge + repair as needed |
205209
| **lpb-memory** | *(independent project)* | Pi memory extension (subprocess reviews) | no upstream to track |
206210
| **config** / **devstack** || own | own |
207211

@@ -230,8 +234,10 @@ Versioning is **manual**: `lpb-devstack bump` commits a new `VERSION`, and CI
230234
builds + tags only when VERSION changed in the pushed commit. Pipeline jobs:
231235
**VERSION check****test** (always) → **build & publish images**
232236
**tag repos** (CI tags the other 5 stack repos on their pipeline branches) →
233-
**status**. Devstack itself is tracked by its `VERSION` file and is never
234-
tagged.
237+
**docs publish** (main pipeline only — publishes the stable docs version,
238+
gated on the docs being flagged ready via `lpb-devstack release docs-ready`
239+
before promotion) → **status**. Devstack itself is tracked by its `VERSION`
240+
file and is never tagged.
235241

236242
## Troubleshooting
237243

@@ -281,24 +287,25 @@ devstack/
281287
├── lpb.stack.env # fork URLs, image names, container identity
282288
├── lpb.conf.env # runtime defaults (baked into the image)
283289
├── .env.example # template for per-project .env (LPB_ vars)
284-
├── scripts/
290+
├── scripts/ # CLIs + shared package (single source, baked to
291+
│ │ # /opt/pi-support/ by the Dockerfile)
285292
│ ├── lpb # bash wrapper
286293
│ ├── lpb.py # launcher engine (stdlib-only Python)
294+
│ ├── lpb-config # config repo manager (in-container)
295+
│ ├── lpb-devstack # DevOps tool (bump/tag/workspace/validate/release)
287296
│ ├── install.sh # host installer (lpb + stack tools)
288297
│ └── localpibox/ # shared Python helpers (env/log/run/cli/stack)
289-
├── support/
298+
├── support/ # runtime image tools (start.sh, browser, schemas…)
290299
│ ├── start.sh # container bootstrap (config, .env, extensions)
291300
│ ├── entrypoint-*.sh # cli / web entrypoints
292-
│ ├── lpb-config # config repo manager (in-container)
293-
│ ├── lpb-devstack # DevOps tool (bump/tag/workspace/validate/release)
294301
│ └── docs/ # operational docs (e.g. subagent spawning)
295302
└── doc/ # reference docs (mirrored to the docs site)
296303
```
297304

298305
## Documentation & Related Repos
299306

300-
- [Documentation site](https://lpb-stack.github.io/devstack/)versioned
301-
per stack tag
307+
- [Documentation site](https://lpb-stack.github.io/devstack/)one version
308+
per stable release (served from the `docs` branch)
302309
- [lpb-stack/pi](https://github.com/lpb-stack/pi) — Pi monorepo fork
303310
- [lpb-stack/config](https://github.com/lpb-stack/config) — agent config preset
304311
- [lpb-stack/lemonade-pi-plugin](https://github.com/lpb-stack/lemonade-pi-plugin) — Lemonade provider plugin

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.60-lpb
1+
0.0.62-lpb-dev

doc/config-repo.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ Extensions are pinned in the `packages` array of `settings.json` as
7171

7272
The `__LPB_VERSION__` placeholder in the template is replaced with the
7373
stack version at boot. Pins are synced to a new stack version by
74-
`lpb-devstack workspace sync --extensions`.
74+
`lpb-devstack workspace sync-pins`.
7575

7676
## Extension Clones
7777

@@ -142,7 +142,7 @@ lpb-config update
142142
lpb-devstack validate
143143

144144
# Sync extension pins to stack version
145-
lpb-devstack workspace sync --extensions
145+
lpb-devstack workspace sync-pins
146146

147147
# Reset config repo
148148
lpb-config reset

0 commit comments

Comments
 (0)