From 2b708d37fe5274292054d5f03e8ebb2f999e6539 Mon Sep 17 00:00:00 2001 From: Yaowei Zheng Date: Tue, 28 Jul 2026 01:57:59 +0800 Subject: [PATCH] release: 0.1.4 (#99) Co-authored-by: Claude Fable 5 --- CHANGELOG.md | 1 + .../0.1.4/2026-07-27-release-pipeline.md | 7 +++ changelog/0.1.4/2026-07-27-sites-and-blog.md | 11 ++++ changelog/0.1.4/README.md | 7 +++ changelog/0.1.4/RELEASE.md | 52 +++++++++++++++++++ changelog/unreleased/README.md | 2 +- package.json | 2 +- packages/cli/package.json | 2 +- packages/core/package.json | 2 +- packages/core/src/index.ts | 2 +- packages/docs/package.json | 2 +- packages/landing/package.json | 2 +- packages/server/package.json | 2 +- packages/skills/package.json | 2 +- packages/web/package.json | 2 +- 15 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 changelog/0.1.4/2026-07-27-release-pipeline.md create mode 100644 changelog/0.1.4/2026-07-27-sites-and-blog.md create mode 100644 changelog/0.1.4/README.md create mode 100644 changelog/0.1.4/RELEASE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fd2dcf..abd8152 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ One brief line per release. Per-release detail lives in [`changelog//`](changelog/). +- **0.1.4** — 2026-07-27. Carries the whole 0.1.3 feature set to npm, which 0.1.3 itself never reached: its publish job failed on a version-endpoint test asserting a hard-coded build date, and only the release jobs stamp one. Plus blog images hosted in the sibling community repo rather than in this clone. ([details](changelog/0.1.4/README.md)) - **0.1.3** — 2026-07-27. Windows support (shell selection, `install.ps1`, a win-x64 package), goal mode looping Tasks until an objective completes, a docked subagents panel with a live call graph, LLM-error reconnects with a visible countdown, and in-app version display with update checks and admin self-update. ([details](changelog/0.1.3/README.md)) - **0.1.2** — 2026-07-26. Builtin file tools with git-style edit diffs, mid-run steering and queued follow-ups, handoff-style model switching with a per-request thinking level, free OpenRouter models, and isolated-origin Workspace HTML previews. ([details](changelog/0.1.2/README.md)) - **0.1.1** — 2026-07-22. Gemini 3.6 Flash and 3.5 Flash-Lite in the model catalog, a Workspace-grouped chat sidebar, in-place upgrades via `penguin update`, and the vLLM / Ollama / LlamaFactory and bento-slides skills. ([details](changelog/0.1.1/README.md)) diff --git a/changelog/0.1.4/2026-07-27-release-pipeline.md b/changelog/0.1.4/2026-07-27-release-pipeline.md new file mode 100644 index 0000000..c4c76e3 --- /dev/null +++ b/changelog/0.1.4/2026-07-27-release-pipeline.md @@ -0,0 +1,7 @@ +# Release pipeline: a version test that could only fail where it mattered + +`packages/server/test/version.test.ts` asserted the `/api/version` body against `{ version: VERSION, buildDate: null }`. The version came from core's constant; the build date was a hard-coded literal — and `null` is only ever true of a source build. The release workflow **stamps both constants before it builds and tests**: `VERSION` from the tag, `BUILD_DATE` with the run's UTC date. So the assertion held in every ordinary CI run, in every local run, and in the `release` job that builds the tarballs (it runs no tests at all), and failed in exactly one place — the `publish-npm` job's build-and-test step, the gate in front of the registry. + +That is what happened to v0.1.3. Its GitHub Release published in full: all 15 assets, the first-ever `penguin-win32-x64.zip`, `install.ps1`. The npm chain never moved, leaving `@prismshadow/penguin-{skills,core,server,cli}` at 0.1.2 on the registry. The two jobs are independent and parallel by design — a deliberate property, so a registry outage cannot cost a Release — which also means a green Release says nothing about npm, and the gap was invisible until someone went looking for it. + +The assertion now compares `buildDate` against `BUILD_DATE`, the same constant the endpoint serves, so it is true of a stamped release build and a source build alike, and the endpoint's contract is still pinned end to end. The v0.1.3 tag could not be moved to pick the fix up — the repo's protected-tag rules forbid it — so 0.1.4 is the delivery vehicle: for anyone installing from npm, this is the release that carries the entire 0.1.3 feature set. diff --git a/changelog/0.1.4/2026-07-27-sites-and-blog.md b/changelog/0.1.4/2026-07-27-sites-and-blog.md new file mode 100644 index 0000000..d0ced09 --- /dev/null +++ b/changelog/0.1.4/2026-07-27-sites-and-blog.md @@ -0,0 +1,11 @@ +# Sites: blog images move to the community repo + +Blog images are the one asset class in this repo whose growth has no ceiling. A published post's images are never deleted, and every new post adds a few hundred KB more — bytes that only the marketing site ever renders, carried forever by everyone who clones the repo to build the product. They now live where the demo videos already do, in the sibling `Prism-Shadow/penguin-harness-community` repo, served from raw.githubusercontent with `access-control-allow-origin: *` and a five-minute cache; the seven files this repo carried under `packages/landing/public/blog-assets/` (six post images plus the generated `benchmark-light.svg`) are deleted. The accepted trade is that a GitHub outage degrades the site to missing images, which is cheaper than the bytes. + +## Post bodies did not change + +Markdown keeps writing the portable `/blog-assets/` path, both in `![alt](…)` images and in the raw `` tags some posts use for theme-swapped screenshots, and the blog renderer resolves it to the hosted URL at render time — a `blogAssetUrl` helper in `src/lib/links.ts` plus an `img` adapter in `src/pages/blog-post.tsx` (rehype-raw has already turned the raw tags into ordinary `img` nodes by the time it is consulted). Keeping the rewrite there rather than in the Markdown leaves one source of truth for the hosting location: post bodies stay readable and diffable, the tests that assert on those paths keep asserting on paths, and moving the host again is a one-line change instead of a sweep over every post. Every other image source — absolute URLs, GitHub user-attachment uploads, site assets such as `/og-cover.png` — is forwarded untouched, pinned by tests alongside the rewrite itself. + +## Regenerating images is now a two-step flow + +Both capture scripts changed where they write. `scripts/capture-blog-shots.mjs` and `scripts/render-benchmark-svg.mjs` emit into the gitignored staging directory `packages/landing/.blog-assets/` (created on demand, since it does not exist in a fresh clone); the files they produce are then uploaded to the `blog-assets/` directory of the community repo, which is what the posts load from. The README's benchmark SVGs are unaffected — `assets/readme/benchmark-{light,dark}.svg` are still rendered from the same landing-page data and still committed here. diff --git a/changelog/0.1.4/README.md b/changelog/0.1.4/README.md new file mode 100644 index 0000000..531e5cf --- /dev/null +++ b/changelog/0.1.4/README.md @@ -0,0 +1,7 @@ +# Version 0.1.4 + +Released on 2026-07-27. + +- [2026-07-27] Release pipeline: the server's version-endpoint test asserted a literal `buildDate: null`, which can only fail in the one job that stamps `BUILD_DATE` — the npm publish. v0.1.3's GitHub Release shipped complete while `@prismshadow/penguin-{skills,core,server,cli}` stayed at 0.1.2 on the registry; the assertion now compares against core's constant, so a stamped release build passes too. ([details](2026-07-27-release-pipeline.md)) + +- [2026-07-27] Sites: blog images move to the sibling community repo — post bodies keep the portable `/blog-assets/` path and the renderer resolves it to the hosted URL, so a clone no longer carries screenshots only the marketing site renders, and the two capture scripts now stage their output in the gitignored `packages/landing/.blog-assets/`. ([details](2026-07-27-sites-and-blog.md)) diff --git a/changelog/0.1.4/RELEASE.md b/changelog/0.1.4/RELEASE.md new file mode 100644 index 0000000..a434ebb --- /dev/null +++ b/changelog/0.1.4/RELEASE.md @@ -0,0 +1,52 @@ +PenguinHarness 0.1.4 — everything 0.1.3 shipped, plus the release-pipeline fix that lets it reach npm. + +v0.1.3's GitHub Release published in full, but its npm publish job failed on a test that asserted a hard-coded build date, so `@prismshadow/penguin-{skills,core,server,cli}` never moved off 0.1.2 on the registry. The tag could not be re-cut, so the fix ships here. **If you install from npm, 0.1.4 is where the whole 0.1.3 feature set arrives** — Windows support, goal mode, the subagents panel, LLM errors that recover. If you used the one-liner, you already have all of it and this is a housekeeping release. + +## Install + +```sh +curl -fsSL https://penguin.ooo/install.sh | sh +penguin web +``` + +Windows (PowerShell): + +```powershell +irm https://penguin.ooo/install.ps1 | iex +penguin web +``` + +Linux, macOS and Windows, with a bundled Node runtime. Or via npm (needs Node >= 24): + +```sh +npm install -g @prismshadow/penguin-cli +``` + +## Highlights + +These four landed in 0.1.3 and reach the npm packages for the first time here. + +**Windows support.** The first release that runs on Windows: command sessions pick a real shell (Git-Bash first, then pwsh, then powershell, with a `PENGUIN_SHELL` override) and announce the choice to the model, so it writes commands in the syntax it actually has. `install.ps1` mirrors the POSIX installer — version and directory knobs, SHA256 verification, a staged swap that never touches your data — and the release ships `penguin-win32-x64.zip` with a bundled Node runtime, all verified by a windows-latest CI job running the full test suite. + +**Goal mode.** State an objective, optionally with a token budget, and the system keeps driving Tasks on the same Session until the goal is done — the objective is re-injected every round, the model reports completion through a `GOAL.yaml` protocol rather than by going quiet, and a budget that runs out triggers one wrap-up round before the goal ends. Runaway safeguards bound the loop. Available as the Web composer's "+" menu, `/goal` and `run --goal` in the CLI, and `session.run(input, { goal })` in the SDK. + +**A panel for subagents.** Child conversations move out of the message stream into a docked agents panel, topped by a live call graph of the current Task — one node per agent with its run state and elapsed time, edges for who spawned whom. Click a node to watch that agent's conversation stream live, approvals included; the stream keeps a compact one-line chip per child, with an amber dot whenever an approval is pending anywhere in the subtree. + +**LLM errors that recover.** A dropped connection or a provider quota rejection no longer aborts the turn: requests reconnect on an exponential ladder (up to 8 attempts, ~62s of patience) with a live countdown and Retry now / Give up controls, and the real cause — not a generic "timeout" — reaches the Cost center. Authentication failures lock the composer recoverably: fix the key on the Models page and open Sessions unlock instantly. + +## Notable in this release + +- **The npm publish, fixed.** The server's version-endpoint test asserted a literal `buildDate: null` — true of a source build, but not of the release jobs, which stamp `BUILD_DATE` with the run's date before building and testing. It therefore passed everywhere except the one job that gates the registry. The assertion now compares against core's constant, so it holds for a stamped release build and a source build alike. +- **Blog images move out of the clone.** Post images are hosted in the sibling community repo instead of being committed here, so contributors stop cloning assets only the marketing site renders. Post bodies are unchanged — they keep the portable `/blog-assets/` path and the renderer resolves it at render time; the two capture scripts now stage their output in a gitignored directory for upload. +- **Replies survive refresh.** An in-progress reply lives in a server-kept tail, so refreshing or reconnecting mid-Task shows the stream exactly where it was. +- **Live header statistics.** Tokens, cost and elapsed time tick live in the session header while a Task runs. +- **Trace import and export.** Trace files move in and out of the Traces page, so a session can be inspected — or reported — from another machine. +- **Version and updates, in the app.** The sidebar user menu shows the running version, checks for new releases (offline-tolerant, `PENGUIN_UPDATE_CHECK=off` to disable), links the release notes, and lets admins run the self-update. +- **One-line rows on mobile.** Running-state session rows stay one line on phones, with icon-only colored approval buttons. +- **Compaction hardening.** An empty compaction summary is a failure, not a result: the request keeps its tools byte-identical (protecting the prompt-cache prefix), rejects empty or tool-calling responses with paired repairs and retries, and resume replays the original context instead of a fabricated empty summary — and a committed mid-task attempt absorbs the turn's pending input, so nothing is ever re-sent. + +## Requirements + +Linux or macOS (x64 / arm64), or Windows 10+ (x64; the one-liner installs via PowerShell). The installer bundles its own Node runtime; installing from npm needs Node >= 24. All data stays under `~/.penguin/data`. + +Full detail: [changelog/0.1.4/](https://github.com/Prism-Shadow/penguin-harness/tree/main/changelog/0.1.4). Per-entry detail for everything under Highlights lives in the [v0.1.3 release notes](https://github.com/Prism-Shadow/penguin-harness/releases/tag/v0.1.3) and [changelog/0.1.3/](https://github.com/Prism-Shadow/penguin-harness/tree/main/changelog/0.1.3). diff --git a/changelog/unreleased/README.md b/changelog/unreleased/README.md index 41987f6..d73cb02 100644 --- a/changelog/unreleased/README.md +++ b/changelog/unreleased/README.md @@ -1,3 +1,3 @@ # Unreleased -Changes since v0.1.3. The version number is assigned at release, when this folder is renamed. +Changes since v0.1.4. The version number is assigned at release, when this folder is renamed. diff --git a/package.json b/package.json index a495c51..4a59f9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "penguin-harness", - "version": "0.1.3", + "version": "0.1.4", "private": true, "type": "module", "description": "PenguinHarness — TypeScript AI Agent (SDK + CLI).", diff --git a/packages/cli/package.json b/packages/cli/package.json index 3a1517f..a18bcfc 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@prismshadow/penguin-cli", - "version": "0.1.3", + "version": "0.1.4", "type": "module", "description": "PenguinHarness CLI: interactive REPL and single-task runner over @prismshadow/penguin-core.", "license": "Apache-2.0", diff --git a/packages/core/package.json b/packages/core/package.json index 3e4b53b..a93dc38 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@prismshadow/penguin-core", - "version": "0.1.3", + "version": "0.1.4", "type": "module", "description": "PenguinHarness core SDK: context_engine, OmniMessage protocol, LLM/Environment interfaces.", "license": "Apache-2.0", diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 6a2c915..c15093b 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -52,7 +52,7 @@ export { Agent, createAgent } from "./agent.js"; export type { CreateAgentOptions, CreateSessionOptions, ResumeSessionOptions } from "./agent.js"; /** SDK version number. */ -export const VERSION = "0.1.3"; +export const VERSION = "0.1.4"; /** Release build date (UTC yyyy-mm-dd), stamped by the release workflow next to VERSION; null in a dev/source build. */ export const BUILD_DATE: string | null = null; // Version-string helpers (shared by the CLI's `penguin update` and the server's update check). diff --git a/packages/docs/package.json b/packages/docs/package.json index 0ba7365..c649b15 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -1,6 +1,6 @@ { "name": "@prismshadow/penguin-docs", - "version": "0.1.3", + "version": "0.1.4", "private": true, "type": "module", "description": "PenguinHarness documentation site (React + Vite + Tailwind CSS): bilingual zh/en Markdown pages with light/dark themes and per-page Copy Markdown, deployed to GitHub Pages under /docs/ next to the landing page.", diff --git a/packages/landing/package.json b/packages/landing/package.json index 0917da6..0767317 100644 --- a/packages/landing/package.json +++ b/packages/landing/package.json @@ -1,6 +1,6 @@ { "name": "@prismshadow/penguin-landing", - "version": "0.1.3", + "version": "0.1.4", "private": true, "type": "module", "description": "PenguinHarness landing page (React + Vite + Tailwind CSS): multilingual, light/dark themes, benchmark showcase, and a local Markdown blog, deployed to GitHub Pages via GitHub Actions.", diff --git a/packages/server/package.json b/packages/server/package.json index 9ee01b5..07b8d3f 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@prismshadow/penguin-server", - "version": "0.1.3", + "version": "0.1.4", "type": "module", "description": "PenguinHarness web server: multi-user authentication and authorization, Session execution with SSE streaming, and usage accounting, built on @prismshadow/penguin-core.", "license": "Apache-2.0", diff --git a/packages/skills/package.json b/packages/skills/package.json index 9c052d1..a437d4d 100644 --- a/packages/skills/package.json +++ b/packages/skills/package.json @@ -1,6 +1,6 @@ { "name": "@prismshadow/penguin-skills", - "version": "0.1.3", + "version": "0.1.4", "type": "module", "description": "PenguinHarness skill library: built-in SKILL.md documents and skill groups, decoupled from core.", "license": "Apache-2.0", diff --git a/packages/web/package.json b/packages/web/package.json index 8d47645..43055f2 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,6 +1,6 @@ { "name": "@prismshadow/penguin-web", - "version": "0.1.3", + "version": "0.1.4", "private": true, "type": "module", "description": "PenguinHarness web frontend SPA: React + Vite + Tailwind CSS, rendering conversations streamed over the OmniMessage protocol, plus Agent configuration, model configuration, usage stats, and Traces.",