Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9.6 KiB
Tooling, language, and infrastructure
Repository language, dev commands, the changelog layout itself, and dependency upgrades.
Make English the repository working language
Translated all residual non-i18n Chinese (comments, error/log messages, test titles and fixtures, package metadata, e2e mock content) to English; Chinese remains only in i18n catalogs, zh documents, and CJK-purpose test fixtures.
Details
- Package metadata:
package.jsondescriptions (root/server/web/landing) and thelink:clifallback echo. - Source comments: all remaining Chinese comments, including the SQL comment set in
packages/server/src/db/schema.ts. - Hardcoded non-i18n user-facing strings (user-visible language change; error codes, placeholders, and limits untouched): server HTTP/validation/409 messages, schedule TOML validation errors, server logs, core SDK errors, CLI fallback errors, web provider invariants.
- Tests: all Chinese describe/it titles and language-irrelevant fixtures translated; assertions realigned to the new English source strings.
- e2e: mock LLM conversation content and cross-file branch markers translated consistently
(the substring relationships the mock's
includes()dispatch relies on are preserved); zh-locale UI assertions kept;e2e/README.mdtranslated. - Kept as required Chinese: zh i18n catalogs and fields (
strings.tsdictionaries, CLIi18n.ts,titleZh,short_description_zh, the zh language-name label,*.zh.mddocs) and test literals that assert zh i18n output or exercise CJK-specific behavior (display width, CJK id validation, title-language consistency, zh-CN e2e UI assertions). - Known gap: web
formatTaskStatsstill hardcodes zh stat-line fragments; the proper fix is routing them through the locale catalogs.
PR: #5 (merged 2026-07-20)
Reorganize the changelog by release version
The top level now holds only version folders; each version's README carries the one-line-per-change index, and detail files live inside the folder (mirrors agenthub PR #162).
Details
changelog/<version>/README.mdis the release summary: one line per change with its title and one-sentence summary, linking the detail file relatively;0.1.0/README.mdabsorbs the section previously kept in the top-level index.changelog/README.mdnow documents only the layout and the entry conventions (no per-file listing).- The working rules (AGENTS.md, CONTRIBUTING.md) point index updates at the version folder's README instead of the top-level file.
Serialize the dev prebuild to fix concurrent dev:server / dev:web clobbering
dev:server and dev:web now share a lock-serialized, deduplicated prebuild of skills and core, so launching both at the same time no longer corrupts dist/ (previously two tsup builds with clean:true raced in the same output directories).
Details
- New
scripts/dev-prebuild.mjs: takes an exclusive on-disk lock (atomic mkdir undernode_modules/) aroundpnpm --filter skills --filter core build; concurrent invocations wait instead of clobbering. Locks left by crashed runs are stolen when the holder PID is dead or the lock is older than 10 minutes. - A 5-second success stamp collapses duplicate builds: starting dev:server and dev:web simultaneously builds once (the waiter skips), and dev:server's inner re-invocation is a no-op. The window is deliberately tiny so an edit-then-restart cycle always rebuilds — the "never start on stale deps" behavior is unchanged.
- Root
dev:servernow just delegates to the server package'sdevscript (which prebuilds via the shared script), removing the historical double build of core;dev:webprebuilds via the script and then starts Vite. pnpm devrun standalone frompackages/servernow also builds skills (it previously built only core, even though the server imports skills at runtime).- Verified: concurrent invocations wait/skip correctly and release the lock; a simultaneous dev:server + dev:web start performs a single build with both servers coming up cleanly.
Add a combined pnpm dev and a dev:landing shortcut
pnpm dev now starts the backend and the web app together with prefixed logs (workspace deps
built once via the shared prebuild lock), and pnpm dev:landing serves the landing page dev
server from the repo root.
Details
pnpm devrunsconcurrently -n server,web "pnpm dev:server" "pnpm dev:web". Merging the two was previously unsafe: each command prebuilt skills/core with tsupclean: trueinto the same dist/ directories and the parallel builds clobbered each other. The lock-serialized prebuild (see the serialize-dev-prebuild entry) removed that race, and its success stamp collapses the two prebuilds into a single build on a combined start.pnpm dev:landingdelegates to the landing package's Vite dev server (port 7366, completing the 7364/7365/7367 dev-port family). The landing package has no workspace deps, so no prebuild is involved.concurrentlyadded as a root devDependency; the dev-command lists in README.md and README.zh.md now coverdevanddev:landing.- Verified: a combined start performs exactly one skills+core build (the other prebuild
waits and skips), with the server on 127.0.0.1:7364 and Vite on localhost:7365; the
landing dev server responds on localhost:7366. Note Vite binds localhost (IPv6 ::1) —
use
localhost, not127.0.0.1, when probing the Vite ports with curl.
Dev commands keep pnpm install current automatically
Forgetting pnpm install before a dev command no longer breaks the start: every dev
command's prestep checks install freshness (lockfile-hash stamp) and runs pnpm install
itself when node_modules is missing or the lockfile changed.
Details
scripts/dev-prebuild.mjsgains an install-freshness step inside its existing lock: the pnpm-lock.yaml content hash is stamped after a successful install, so the usual dev start pays nothing; a fresh clone or a pulled lockfile change triggerspnpm installautomatically (concurrent dev commands still install/build exactly once).- The lock and stamps move from
node_modules/to the OS temp directory keyed by the repo path — they must exist before the first install does (the old location crashed on a fresh clone), and per-checkout isolation comes from the key. dev:docs/dev:landinghave no workspace deps to build but still need current installs: they now run the prestep with--install-only.
Upgrade AgentHub to 0.4.0 and adopt the opaque fidelity payload
@prismshadow/agenthub 0.3.3 -> 0.4.0 (agenthub PR #159): content items replace the item-level
signature/phase fields with one opaque fidelity object, and OmniMessage now carries it
verbatim end to end — Trace, replay, and resume included; the agenthub-dev skill joins the
built-in library.
Details
- OmniMessage complete payloads (text, thinking, inline_data, inline_thinking, tool_call)
replace
signature?: string/phase?: string | nullwithfidelity?: Record<string, unknown>— an opaque wire-fidelity payload written to the Trace as-is and passed back verbatim on replay (Claude thinking signatures, GPT-5 encrypted reasoning{id, encrypted_content}and{phase}markers, the OpenAI-compatible{reasoning_field}name). Builders take the object directly; an empty object is treated as absent. - GenerativeModel's streaming translator mirrors AgentHub baseClient aggregation: a thinking
block is closed by its fidelity payload and a run of equal fidelity is one block (the
OpenAI-compatible clients stamp every thinking delta with the same
{reasoning_field}, which must not split blocks — this carries agenthub's reasoning-field replay fix through PenguinHarness so multi-turn conversations against strict OpenAI-compatible upstreams survive); a text segment splits on a differingfidelity.phaseand closes onfidelity.signature, merging fidelity keys. Text-phase stickiness across segments is gone (mirrors baseClient). - The
agenthub-devskill (AgentHub's own model-support development workflow) is installed into the built-in library under the Penguin Development group, completed to the library contract (version/updated frontmatter, short descriptions, a "Before you start" section, and a custom icon). - Malformed-classification fix for 0.4.x: agenthub now surfaces truncated streamed tool-call
arguments as its own
ToolCallArgumentParseError(previously a rawSyntaxError) and thinking-only completions asEmptyResponseError;isMalformedJsonParseErrorrecognizes both (instanceof + name fallback + cause chain), so these still end asmalformedand the engine reconnects and retries instead of failing the turn (caught by the malformed e2e). - Docs (omni-message, interfaces, sessions-and-traces; en + zh) and the design specs updated to the fidelity semantics.
- Traces written before this change carried
signature/phaseon payloads; per the pre-release no-migration policy they are not converted (old fields are ignored on replay — resume of such Sessions loses provider fidelity; delete and recreate if needed).
The changelog folder merges related entries
One file per change had grown to 35 fragment files for this release alone; related changes are now merged into six date-slug entry files (models-and-catalog, web-app, landing-site, blog-and-docs, readme, tooling), each keeping the standard entry shape — H1 title, one-sentence summary, then per-change details — with the version README listing one line per entry file. The layout convention itself is unchanged; the branch was also rebased onto main to linearize away the merge commit with the final tree kept byte-identical.