refactor(7.1): consolidate 23 packages → 8 (the 7.x Phase 1)#2
Merged
Conversation
The 3 docs/7.0-*.md (design + 132 decisions + resolved) are the locked single source of truth. Derived an ordered task backlog into docs/tasks/ (00-index with the 3 working principles + phase-0 + 14 task files mapping to per-phase design docs 7.1-7.14). docs/7.1-design.md = the consolidation (23->8 pkg) design, codex-R1 folded. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (Phase 0 A3) A contributor behind a regional mirror (~/.npmrc=npmmirror) can bun-install a lockfile pinned to that mirror, which then fails CI's bun --compile on GitHub runners (the v1.0.0 root cause, see bunfig.toml). Guard the typescript job (pre-install): fail fast if bun.lock records any non-npmjs registry host. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…runtime (consolidation Step 1)
Phase 1 / Step 1 of the 23->8 package consolidation (docs/7.1-design.md). Zero behavior change. config+telemetry+telemetry-otel src moved to runtime/src/{config,telemetry,telemetry-otel}/; runtime now exports ./config, ./telemetry, ./otel (subpaths -> dist) and absorbs the @opentelemetry/* optional peer+dev deps. Internal imports relativized; 23 external consumers rewritten @chances-ai/{config,telemetry,telemetry-otel} -> @chances-ai/runtime/{config,telemetry,otel} (incl. the load-runtime computed specifier). Removed stale dep+tsconfig refs (root + apps/cli + tools/mcp/lsp/core; lsp's config dep was dead). depcruise rules 1/4/6 dead-name cleanup. smoke-compile-otel redefined: optional-absence surface shrinks from (sub-package + peer) to @opentelemetry/* only (the sub-package now ships inside runtime). bun.lock is host-agnostic after bun install (bunfig pins npmjs.org).
Gates: check 45/45 · test 45/45 (runtime now 291 tests/18 files incl 8 moved) · boundaries 1061 modules 0 violations · smoke otel/oauth/lsp all green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dation Step 2) Phase 1 / Step 2 of the 23->8 consolidation (lowest-risk merge). Zero behavior change. ink-ext/src moved to tui/src/ink-ext/ (ink-ext was imported ONLY by tui, and is a leaf — imports no workspace pkg). 15 tui files rewritten @chances-ai/ink-ext -> ./ink-ext/index.js; removed tui dep + tui/root tsconfig refs; deleted the depcruise ink-ext-is-a-leaf rule and dropped ink-ext from rules 1/2 (tui now covers the folded path). bun.lock normalized to npmjs.org (a local bun install re-pinned npmmirror via ~/.npmrc; sed'd back — the ci.yml A3 guard enforces this). Gates: check 43/43 · test 43/43 (tui now 190 tests/20 files incl 5 moved ink-ext) · boundaries 1061 modules 0 violations · smoke-compile-tui green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nsolidation Step 3)
Phase 1 / Step 3 of the 23->8 consolidation. Zero behavior change. New @chances-ai/client: '.' = client-core (browser-safe RPC client, React-free), './react' = web-ui (HeroUI/React DOM components). client-core/src + web-ui/src moved under client/src/{client-core,web-ui}/; 18 web-ui files rewritten @chances-ai/client-core -> ../client-core/index.js; react/react-dom/@heroui made OPTIONAL peers (only ./react needs them, per design [2.4]). apps/web: @chances-ai/client-core -> @chances-ai/client, @chances-ai/web-ui -> @chances-ai/client/react. depcruise browser-safe rules (1/2/3/4) renamed client-core|web-ui -> client; root tsconfig merged. browser-safe.test made RECURSIVE over the whole client/src tree (R1 #8); boundaries.test fixture paths re-depthed (one extra nesting level).
happy-dom isolation: client-core's transport.test drives a REAL loopback WebSocket (Bun.serve) that happy-dom clobbers, while web-ui's *.dom.test.tsx NEED happy-dom — so the client 'test' script runs TWO separate bun-test processes (src/client-core WITHOUT happy-dom; src/web-ui WITH --preload ./happydom.ts). No global preload in bunfig.
Gates: check 41/41 · test 41/41 (client-core 77 tests/5 files incl real-WS transport + recursive browser-safe; web-ui 83 tests/11 files DOM) · boundaries 1059 modules 0 violations · apps/web vite build node-free.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… Step 4)
Phase 1 / Step 4 of the 23->8 consolidation. Zero behavior change; driver.ts EngineHost seam byte-identical. New @chances-ai/wire: './rpc' (ACP/RPC core over the EngineHost) + './serve' (relay/replay-hub/tls/auth/pairing). rpc/src + serve/src moved under wire/src/{rpc,serve}/; serve's 8 @chances-ai/rpc imports relativized to ../rpc/index.js; @agentclientprotocol/sdk stays an optional peer (computed-specifier lazy load in acp/load-sdk.ts); ws/selfsigned stay hard deps reachable only via ./serve. Consumers (apps/cli, apps/desktop, client) rewritten @chances-ai/rpc -> @chances-ai/wire/rpc, @chances-ai/serve -> @chances-ai/wire/serve. wire is the SERVER tier: it legitimately imports ui-core (server-side view-model projection), so it's governed by depcruise no-client-to-tui (rules 2), NOT no-domain-to-ui (rule 1) — rpc removed from rule 1 from-list; serve->wire in rules 1/2/4/6; boundaries.test now asserts no-client-to-tui. smoke-compile-rpc ACP stash path -> packages/wire.
Gates: check 39/39 · test 39/39 (wire 272 tests/22 files incl driver/cross-transport/boundaries) · boundaries 1057 modules 0 violations · smoke-compile-rpc (acp-sdk present+absent) · smoke-compile-serve (compile + start + /health + WS /acp initialize).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lidation Step 5, XL) Phase 1 / Step 5 — the big merge. Zero behavior change. ai+agents+tools+plugin-api+plugin-logger+memory+local-vault+lsp+mcp+session+core folded into @chances-ai/engine with granular subpath exports (./ai ./agents ./tools ./plugin-api ./plugin-logger ./memory ./local-vault ./lsp ./mcp ./session ./core), NO '.' barrel (subpath = the lazy-peer + tree-shake boundary). Intra-engine cross-domain imports relativized depth-aware (core/mcp have nested subdirs, so core/compaction/*->../../ vs core/*->../, via a throwaway script). mcp->local-vault is now a plain relative dynamic import (local-vault always ships in engine; keyring stays lazy). Optional peers consolidated onto engine: ai+@ai-sdk/* + @modelcontextprotocol/sdk + @napi-rs/keyring + vscode-jsonrpc (all computed-specifier lazy). External consumers (apps/cli, tui, ui-core, wire, scripts/benchmark, root devDeps) rewritten @chances-ai/<domain> -> @chances-ai/engine/<domain>; apps/cli's 11 domain deps collapse to one @chances-ai/engine. depcruise rules 1/4/6 domain names -> engine; lsp boundaries.test re-depthed (still no-domain-to-ui). load-runtime loadLsp computed specifier -> ["@chances-ai","engine","lsp"]. smoke-compile-oauth/lsp redefined: optional-absence surface shrinks from (sub-package + peer) to external-peer-only (sub-packages now always ship in engine); stash paths -> packages/engine/node_modules. Gates: check 19/19 · test 19/19 (engine now 1069 tests/74 files, 2 skip, 0 fail — no cross-test interference) · boundaries 1057 modules 0 violations · all 6 smokes green (otel/oauth/lsp/rpc/serve/tui). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uctural rules (consolidation Step 6) Phase 1 / Step 6. Clean rewrite of .dependency-cruiser.cjs for the consolidated 8-package tiers (apps -> ui[tui] -> client[ui-core/client/design-system, browser-safe] -> server[wire] -> domain[engine] -> infra[runtime] -> native), with refreshed comments (dropped the stale web-ui/client-core/serve/ink-ext/config/telemetry names). design-system pre-listed in the browser-safe tier rules (reserved for task 03). TWO new structural rules: no-static-optional-peer ([2.1]) — engine/wire/runtime may load mcp-sdk/vscode-jsonrpc/@napi-rs/keyring/acp-sdk/@opentelemetry/* ONLY via computed-specifier dynamic import (dependencyTypes:[import,require] catches a static value import; computed/dynamic/type-only allowed; @ai-sdk excluded as bundled); no-deep-cross-package-src ([2.8]) — apps must import packages via their exports, never reach into src/. Added a committed no-static-optional-peer regression fixture to engine/src/lsp/boundaries.test.ts. Both new rules verified to FIRE (ad-hoc negative fixtures). Gates: engine test 1070 tests/74 files 0 fail (incl the new rule-7 fixture) · boundaries 1057 modules 0 violations. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (Step 7) Phase 1 / Step 7 (finalize). turbo.json needs no change (build graph auto-derived from package.json deps; no hardcoded package names). publint: all 8 consolidated packages 'All good!' (incl the no-'.'-barrel engine/wire subpath-only packages). smoke-release (Node out-of-bun) green. Added the 7.1 major changeset with the full old->new import-specifier migration table (fixed-group anchors @chances-ai/cli). Ticked Steps 3-7 in docs/tasks/01-consolidation-task.md. CONSOLIDATION COMPLETE: 23 packages -> 7 libs (client/engine/native/runtime/tui/ui-core/wire) + design-system reserved = 8 target. Final gate all green: check + test + boundaries (1057 modules, 0 violations) + publint + smoke-release + all 6 compile smokes. Zero behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
codeweiz
added a commit
that referenced
this pull request
Jun 3, 2026
… (Step 3)
Focused port of oh-my-pi pi-natives grep.rs: a #[napi] async grep() on the
libuv pool (so a serve fan-out can't freeze the event loop), keeping the
load-bearing pieces and the facade's option set, dropping pi's context
lines / type filters / output modes / in-memory search+has_match (no
consumer yet — R1 #5).
Native (src/grep.rs):
- ripgrep stack: grep-regex + grep-searcher + globset filter + ignore
parallel walker (gitignore-aware, hidden included, node_modules/.git
pruned); per-128 heartbeat; mmap for files > 128 KiB, skip > 4 MiB.
- two-step sanitize: sanitize_braces (`${x}`→`$\{x\}`, valid quantifiers
and \p{}/\x{}/\u{} pass through) + escape_unescaped_parentheses retry on
a group-syntax error (so `fn(` searches literally instead of erroring).
- matched line text trimmed both ends to match jsGrep; results sorted by
(path, line) then truncated to maxResults.
Facade (breaking, async flip): grep(pattern, root, opts) is now
Promise<GrepMatch[]>; the native addon returns {path,lineNumber,line} and
the facade adapts to the UNCHANGED {file,line,text} contract (R1 #2). Added
addonOrForced() — the unified CHANCES_NATIVE_FORCE_FALLBACK switch (R1 #8).
Repoint: grep.ts awaits; native package grep tests await + go async.
Tests: 7 Rust unit (sanitize/paren-recovery/relative+line/per-file-limit/
glob/gitignore) + 4 native↔JS facade equivalence (literal / regex+case+glob
/ perFileLimit+maxResults / sanitized brace; non-multiline on a clean tree
where both walkers agree — §9 #1/R1 #22). Multiline divergence documented:
the native stack coalesces ADJACENT multiline match-blocks (ripgrep
semantics, verified) — the "multiple matches" test spaces blocks out; the
grep-tool invalid-regex test now uses an unclosed char class (malformed on
both backends) since bare parens are recovered.
Gates: cargo fmt + clippy -D warnings clean + cargo test 47/0 · native
61/0 · check 19/19 · boundaries 1057/0 · full test 19/19. .node 752 KiB →
2.3 MiB (ripgrep stack). deps: globset/grep-matcher/grep-regex/
grep-searcher/memmap2.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1 of the 7.x program (
docs/7.0-design.md/docs/tasks/01-consolidation-task.md). Zero runtime behavior change — the published@chances-ai/clibinary behaves identically; this is internal restructuring. Major version because the workspace package surface (names SDK consumers import) changed.23 libraries → 7 (+ design-system reserved = 8 target)
client·engine·native·runtime·tui·ui-core·wireb482cef./config/./telemetry/./otel)09d9a49ce31687././react)561929c./rpc/./serve)d820c8b.barrel)af2be7954d656d9d71e50How it stays honest
.barrel on engine/wire (forces explicit subpath imports).no-static-optional-peerdepcruise rule structurally enforces the lazy optional-peer contract (mcp-sdk / vscode-jsonrpc / @napi-rs/keyring / acp-sdk / @opentelemetry/* loaded only via computed-specifier dynamic import).no-deep-cross-package-src— apps import via package exports, never reach intosrc/.client(split test: real-WebSocketclient-corewithout happy-dom; DOMweb-uiwith--preload).Gates (all green, every step)
bun run check·bun run test(engine 1070 tests/74 files 0 fail; full suite green) ·bun run boundaries(1057 modules, 0 violations) · all 6smoke-compile-*·publint(8 pkgs) ·smoke-release.Review
codex R1 (design) + R2 (implementation) both run; R2 findings verified as false positives (codex ran root
bun testvs canonicalbun run test; test-file peer imports are excluded by design). No real blockers. Migration table in.changeset/7-1-consolidation.md.🤖 Generated with Claude Code