11 KiB
Replacement repository source layout
Tracking issue: #55
Authority and scope
Jason requested canonical codebase storage for extensions, skills, and other components, with phased replacement of mosaicstack/stack. Source organization does not authorize deployment, credential migration, commit, push, or changes to the live fleet. The accepted goal extension is the first migration candidate. This record is an investigation and recommendation, not an implemented move.
Measured legacy structure
Read through the Gitea contents API on 2026-09-06 at 06:14 UTC. Requests returned HTTP 200.
apps/contains appservice, gateway, and web.packages/contains shared domains including agent, auth, brain, comms, config, coord, db, forge, log, memory, queue, storage, and types.plugins/contains discord, macp, mosaic-framework, and telegram. These names alone do not establish that these plugins are Pi extensions.- Root also has
skills/,tools/,scripts/,profiles/,infra/,docker/, and documentation. - Root package manifest is private, declares pnpm 10.6.2, and delegates build, lint, typecheck, and tests to Turbo.
- Workspace membership is explicit: apps/, packages/, plugins/*, and tools/matrix-presence-harness. Skills are not declared as JavaScript workspace packages.
- Turbo builds dependency packages before dependents and records dist/** as build output. Tests and typechecking depend on dependency builds.
Inspected manifest blobs:
- package.json:
5910f98225226274141a6da4c81098fa122f3f46 - pnpm-workspace.yaml:
abb7a60e203c6d44dcf8dc9bf7c99cb3cb72cbd8 - turbo.json:
cf8ef998ee52391cc581c16c865f6d0c0066b24f
The recursive main tree response identified commit/tree 7102ccb93e007d98faab3994ea552d03f522ad2c but was truncated at 1,000 entries. Follow-up contents reads supplied complete targeted directories. This is a targeted structural and packaging inspection, not a complete legacy inventory.
Recommendation for stack-v2
Adopt the monorepo principle now, not the entire legacy directory tree or build system.
extensions/goal/becomes canonical goal source and tests.extensions/mosaic-core/lib/initially holds its existing supporting dependencies. This does not activate Mosaic Core as a separate extension.- Existing
skills/,contracts/,adapters/,roles/,scripts/, anddocs/retain their distinct responsibilities. .pi/extensions/becomes a generated native-test installation. Never edit it as canonical source. Populate it by deterministic ordinary-file copying, not symlinks..pi/state/remains ignored runtime state and must never enter an extension artifact.- Introduce apps/ or packages/ when an actual service or shared package requires them. Do not create empty placeholder packages or rename existing components merely to resemble the old repository.
- Package explicit source inventories and dependency versions. Record artifact hashes and fail rather than overwrite unknown local edits in the development installation.
The current private npm manifest and pinned Pi dependency do not need to become pnpm/Turbo merely to store one extension. Decide workspace tooling when independently built JavaScript packages justify it. Native Pi 0.85.1 testing versus the container's 0.84.4 pin is an unresolved compatibility gate before managed-runtime promotion.
Measured legacy packaging and installation
Targeted Gitea reads returned HTTP 200 for the installer, release verifier, publish pipeline, publishing helper, and representative manifests.
- Shared packages such as
@mosaicstack/agentbuild TypeScript intodist/, publish onlydist, and use explicit workspace dependencies. - The
@mosaicstack/mosaicpackage publishes bothdistandframework. This is the legacy bundle for CLI plus framework resources. plugins/mosaic-frameworkdeclares an OpenClaw extension in its own package manifest. It is not a Pi extension package.- The main installer separates framework files under
~/.config/mosaicfrom the globally installed npm CLI. Its development mode builds the monorepo, packs local tarballs, and installs those tarballs without registry writes. - The publish pipeline installs from a frozen lockfile, verifies that CI's commit equals checkout HEAD, runs one terminal release verifier, builds, and only then publishes. Registry, authentication, network, and unknown publication failures fail the job. The
nextlane snapshots and restores modified manifests. - A separate npmjs helper mutates manifests temporarily and restores them. It tolerates publish failures broadly, so it is not a model for stack-v2's fail-closed publication path.
The useful pattern is source, build output, installation, and publication as separate states tied to explicit manifests and immutable identity. The volume and complexity of the old framework package should not be copied into the first stack-v2 extension increment.
Phases
- Source ownership: move accepted goal source, dependencies, and tests into canonical directories; preserve source provenance and user acceptance evidence.
- Native development packaging: deterministic install into .pi, drift checks, source/package tests, explicit runtime version compatibility, and repeat native acceptance if behavior changes.
- Managed runtime integration: approved extension allowlist, image packaging, policy compatibility, isolation, and rollback checks. Docker remains deferred until authorized.
- Component-by-component legacy replacement: inventory dependencies, contracts, state ownership, acceptance criteria, and rollback for each component before migration. No wholesale adoption of operational state.
Implemented first increment
The accepted goal extension now follows the recommended ownership boundary.
- Canonical source and tests are under
extensions/goal/. - Imported support modules are under
extensions/mosaic-core/lib/; no second entrypoint exists. scripts/sync-dev-extensions.shstages and verifies ordinary-file copies in.pi/extensions/. It records the installed manifest, rejects source symlinks or extra entrypoints, detects installation drift, and refuses to overwrite it.scripts/goal-dev.shsynchronizes before launching isolated native Pi..pi/goal-dev.shremains a compatibility wrapper for the accepted test command.scripts/test-extension-package.shruns 18 controls. It covers initial installation, full-tree equality, extra destination entries, source and destination symlinks, local drift, canonical updates, nested entrypoints, active and stale locks, and interruption rollback/recovery..pi/extensions/, state, generated manifests, and local evidence are ignored. They are installations or runtime evidence, not canonical source.
Verification after the move passed: 67 goal tests, all 18 development-package controls, and native Pi PTY checks at 45 and 120 columns for Waiting, Paused, Blocked, Complete, bare /goal, Alt+G, and NO_COLOR. A separate read-only reviewer first requested stronger full-tree, nested-entrypoint, interruption, and lock controls. After correction, the reviewer returned APPROVE and identified each prior finding as closed. The exact canonical-source manifest is .pi/evidence/canonical-source.sha256, whose SHA-256 is c2096c00fb505a53482ff6a94a0f293dbc1ca2058d7a1996961601af80c29946.
No package-manager change, npm publication, Docker inclusion, live-fleet installation, commit, or push is part of this increment. Unrelated CURRENT.md work remains untouched.
Replacement method
Use the repository as a component monorepo with explicit boundaries, not as one undifferentiated package. Keep declarative resources in their existing top-level directories. Add executable packages or apps only when they have independent build and dependency needs. Every migrated component gets canonical source, tests, a deterministic development installation, an explicit release inventory, exact runtime compatibility, independent review, and user acceptance before the old implementation can be retired.
For Pi resources, the Pi package format supports explicit pi.extensions and pi.skills paths. Do not publish the entire private repository by convention. When external distribution becomes necessary, create a bounded package manifest or staged artifact that names only approved resources and declares Pi APIs as peer dependencies. The current sync installation is deliberately narrower and precedes that release decision.
Coordination request
MS55-DW-1 asks darkwing, the current owner of CURRENT.md and issue #53 phase-2 planning, to reconcile the next foundation goal before Jason sets it. Requested return: darkwing's intended technical-mapping scope, paths this session must avoid, and a recommended division of work that incorporates #55 without overlapping writers. Destination is the default tmux session darkwing; follow-up owner is this assistant. tools/tmux/agent-send.sh returned rc=2 at 2026-09-06 06:55 UTC: it could not confirm submission after three attempts and reported that the message may be undelivered. Delivery is unknown, so this session will not resend without reconciliation. No source or shared-plan work starts from this request.
Reconciliation finding
CURRENT.md says issue #53 phase 2 is accepted and awaits Jason's separate authorization for technical mapping. ROADMAP.md also records an earlier owner decision: the succession target uses packages/*, while broad restructuring waits for M20 because moving current bash entrypoints sooner would create two migrations. The #55 extensions/ location is therefore a valid canonical source improvement now, but it cannot silently become the final post-M20 package layout. Jason's latest direction does not explicitly revoke the earlier sequencing decision.
The next safe step is a coordination and baseline goal, not another code move. It should reconcile the extensions/ staging location with the packages/* target, assign non-overlapping writers for the current dirty tree, and define the exact committed revision that a later as-built/planned map will cite. Archify mapping requires a commit SHA and will not treat the current dirty working tree as evidence.
Darkwing replied directly to MS55-DW-1 at 2026-09-06. The reply supports an evidence-backed current-versus-planned component/package map with #55 as input and no runtime implementation. Agreed ownership: darkwing owns requirement-to-code mapping and CURRENT integration; Dewey owns source, package, installation boundaries, and phased inventory in this #55 plan or a separately agreed file. Darkwing will avoid extensions/**, .pi/**, #54/#55 plans, and the four extension development scripts. Dewey will avoid CURRENT.md, the three foundation/phase-2/schema plans, and foundation-v1-candidate/**. Shared logs remain append-only. Both sides await Jason's explicit mapping authorization. A non-author must review the resulting candidate. The acknowledgement send returned rc=2 after three unconfirmed attempts; delivery is unknown and it was not resent.