Raven Scott

This commit is contained in:
2026-05-17 16:01:52 +00:00
parent 0f056c65e2
commit 7de85968cc
42 changed files with 4808 additions and 26 deletions
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env node
/**
* Create a writable Pear link for local stage/release on this host.
* Writes packages/<app>/.pear-stage-link (gitignored).
*
* Usage: node scripts/bootstrap-pear-stage-link.mjs <package-dir>
*/
import { execSync } from 'node:child_process'
import { writeFileSync } from 'node:fs'
import path from 'node:path'
const pkgDir = path.resolve(process.argv[2] ?? '')
if (!pkgDir) {
console.error('usage: bootstrap-pear-stage-link.mjs <package-dir>')
process.exit(1)
}
let out
try {
out = execSync('pear touch --json', {
cwd: pkgDir,
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'inherit']
})
} catch (err) {
console.error(`pear touch failed: ${err.message}`)
process.exit(1)
}
let link = null
for (const line of out.trim().split('\n').filter(Boolean).reverse()) {
try {
const row = JSON.parse(line)
link = row.data?.link ?? row.link ?? null
if (link) break
} catch {
/* skip non-JSON lines (warnings) */
}
}
if (!link || !/^pear:\/\/[a-z0-9]+$/i.test(link)) {
console.error('pear touch --json did not return a pear:// link')
process.exit(1)
}
const dest = path.join(pkgDir, '.pear-stage-link')
writeFileSync(dest, `${link}\n`, 'utf8')
console.error(`Wrote ${dest}`)
process.stdout.write(`${link}\n`)
+48 -4
View File
@@ -59,11 +59,50 @@ const concreteClosureByPkgRel = new Map([
function linkTo(src, dst) {
mkdirSync(dirname(dst), { recursive: true })
const abs = resolve(src)
if (process.platform === 'win32') {
symlinkSync(abs, dst, 'junction')
} else {
symlinkSync(relative(dirname(dst), abs), dst, 'dir')
// Absolute targets avoid Pear stage rejecting relative links with many '..'.
symlinkSync(abs, dst, process.platform === 'win32' ? 'junction' : 'dir')
}
/** Collect npm package names (scoped + unscoped) reachable from a workspace package.json. */
function dependencyClosure(pkgRoot, rootNm) {
const seen = new Set()
const queue = []
const pkgJsonPath = join(pkgRoot, 'package.json')
if (!existsSync(pkgJsonPath)) return seen
const rootPkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
const forPearStage =
process.env.BARE_OS_PEAR_NODE_MODULES === '1' ||
process.env.BARE_OS_PEAR_NODE_MODULES === 'true'
const seedSpecs = [...Object.keys(rootPkg.dependencies || {})]
// bare-os-booter lists catalog bare-* packages under optionalDependencies; never mirror those.
if (!forPearStage) {
seedSpecs.push(...Object.keys(rootPkg.devDependencies || {}))
}
for (const spec of seedSpecs) queue.push(spec)
while (queue.length) {
const spec = queue.shift()
if (!spec || seen.has(spec)) continue
seen.add(spec)
const pkgDir = packagePath(rootNm, spec)
const depJsonPath = join(pkgDir, 'package.json')
if (!existsSync(depJsonPath)) continue
let pkg
try {
pkg = JSON.parse(readFileSync(depJsonPath, 'utf8'))
} catch {
continue
}
const deps = {
...(pkg.dependencies || {}),
...(pkg.optionalDependencies || {})
}
for (const depName of Object.keys(deps)) queue.push(depName)
}
return seen
}
function packagePath(nmRoot, spec) {
@@ -87,6 +126,8 @@ if (existsSync(localNm)) {
}
mkdirSync(localNm, { recursive: true })
const needed = dependencyClosure(pkgRoot, rootNm)
for (const name of readdirSync(rootNm)) {
if (name === '.bin' || name === '.package-lock.json' || name.startsWith('.'))
continue
@@ -100,6 +141,8 @@ for (const name of readdirSync(rootNm)) {
if (name.startsWith('@') && st.isDirectory()) {
for (const sub of readdirSync(srcPath)) {
if (sub.startsWith('.')) continue
const spec = `${name}/${sub}`
if (!needed.has(spec)) continue
const scopedSrc = join(srcPath, sub)
try {
if (!lstatSync(scopedSrc).isDirectory()) continue
@@ -110,6 +153,7 @@ for (const name of readdirSync(rootNm)) {
}
continue
}
if (!needed.has(name)) continue
if (st.isDirectory() || st.isSymbolicLink()) {
linkTo(srcPath, join(localNm, name))
}
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
# Release + seed current package.json pear.link keys (after stage-release staged content).
# Usage: scripts/finish-pear-setup.sh
set -euo pipefail
export PATH="${HOME}/.config/pear/bin:${PATH:-}"
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
rm -f "${HOME}/.config/pear/lock"
SEEDER_LINK="$(node "$ROOT/scripts/resolve-pear-link.mjs" "$ROOT/packages/bare-os-seeder")"
BOOTER_LINK="$(node "$ROOT/scripts/resolve-pear-link.mjs" "$ROOT/packages/bare-os-booter")"
release() {
local dir="$1"
local link="$2"
local name="$3"
echo ""
echo "Releasing $name ($link)…"
(cd "$dir" && pear release "$link")
}
seed() {
local dir="$1"
local link="$2"
local name="$3"
echo ""
echo "Seeding $name ($link)…"
(cd "$dir" && pear seed "$link" --no-ask --no-tty) || true
}
release "$ROOT/packages/bare-os-seeder" "$SEEDER_LINK" bare-os-seeder
release "$ROOT/packages/bare-os-booter" "$BOOTER_LINK" bare-os-booter
seed "$ROOT/packages/bare-os-seeder" "$SEEDER_LINK" bare-os-seeder
seed "$ROOT/packages/bare-os-booter" "$BOOTER_LINK" bare-os-booter
echo ""
echo "Done."
echo " Seeder: $SEEDER_LINK"
echo " Booter: $BOOTER_LINK"
echo ""
echo "Run (wait ~10s for first log line):"
echo " source scripts/pear-path.sh"
echo " pear run $SEEDER_LINK --checkout=release"
echo "Dev (from disk, recommended locally):"
echo " npm run os:seeder"
+60
View File
@@ -0,0 +1,60 @@
{
"apps": [
{
"name": "pear-seed-bare-os-seeder",
"cwd": ".",
"script": "scripts/pm2-pear-seed.sh",
"args": ["packages/bare-os-seeder"],
"interpreter": "bash",
"instances": 1,
"exec_mode": "fork",
"autorestart": true,
"min_uptime": 10000,
"max_restarts": 20,
"restart_delay": 5000,
"kill_timeout": 10000
},
{
"name": "pear-seed-bare-os-booter",
"cwd": ".",
"script": "scripts/pm2-pear-seed.sh",
"args": ["packages/bare-os-booter"],
"interpreter": "bash",
"instances": 1,
"exec_mode": "fork",
"autorestart": true,
"min_uptime": 10000,
"max_restarts": 20,
"restart_delay": 5000,
"kill_timeout": 10000
},
{
"name": "bare-os-seeder",
"cwd": ".",
"script": "scripts/pm2-pear-run.sh",
"args": ["packages/bare-os-seeder"],
"interpreter": "bash",
"instances": 1,
"exec_mode": "fork",
"autorestart": true,
"min_uptime": 15000,
"max_restarts": 20,
"restart_delay": 8000,
"kill_timeout": 15000
},
{
"name": "bare-os-booter",
"cwd": ".",
"script": "scripts/pm2-pear-run.sh",
"args": ["packages/bare-os-booter"],
"interpreter": "bash",
"instances": 1,
"exec_mode": "fork",
"autorestart": true,
"min_uptime": 15000,
"max_restarts": 20,
"restart_delay": 8000,
"kill_timeout": 15000
}
]
}
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# PM2 helper: run a Bare OS Pear app (long-lived) using pear.link from package.json.
# Usage: scripts/pm2-pear-run.sh packages/bare-os-seeder
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PKG_REL="${1:?package path required, e.g. packages/bare-os-seeder}"
export PATH="${HOME}/.config/pear/bin:${PATH:-}"
LINK="$(node "$ROOT/scripts/resolve-pear-link.mjs" "$ROOT/$PKG_REL")"
cd "$ROOT/$PKG_REL"
echo "[pm2-pear-run] $(basename "$PKG_REL")$LINK" >&2
exec pear run "$LINK" --checkout=release
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# PM2 helper: seed a Bare OS Pear app using pear.link from package.json.
# Usage: scripts/pm2-pear-seed.sh packages/bare-os-seeder
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PKG_REL="${1:?package path required, e.g. packages/bare-os-seeder}"
export PATH="${HOME}/.config/pear/bin:${PATH:-}"
LINK="$(node "$ROOT/scripts/resolve-pear-link.mjs" "$ROOT/$PKG_REL")"
if [[ -z "$LINK" || "$LINK" == "." ]]; then
echo "[pm2-pear-seed] ERROR: invalid Pear link for $PKG_REL (got: ${LINK:-<empty>})" >&2
exit 1
fi
cd "$ROOT/$PKG_REL"
echo "[pm2-pear-seed] $(basename "$PKG_REL")$LINK" >&2
exec pear seed "$LINK" --no-ask --no-tty
+8 -8
View File
@@ -2,10 +2,10 @@
"apps": [
{
"name": "pear-seed-bare-os-seeder",
"cwd": "./packages/bare-os-seeder",
"script": "pear",
"args": ["seed", "--no-ask", "bare-os-seeder", "."],
"interpreter": "none",
"cwd": ".",
"script": "scripts/pm2-pear-seed.sh",
"args": ["packages/bare-os-seeder"],
"interpreter": "bash",
"instances": 1,
"exec_mode": "fork",
"autorestart": true,
@@ -16,10 +16,10 @@
},
{
"name": "pear-seed-bare-os-booter",
"cwd": "./packages/bare-os-booter",
"script": "pear",
"args": ["seed", "--no-ask", "bare-os-booter", "."],
"interpreter": "none",
"cwd": ".",
"script": "scripts/pm2-pear-seed.sh",
"args": ["packages/bare-os-booter"],
"interpreter": "bash",
"instances": 1,
"exec_mode": "fork",
"autorestart": true,
+99
View File
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
# Fully remove Pear, reinstall from npm, mint new bare-os keys, stage, release, seed.
#
# Usage (from repo root): scripts/reinstall-pear-and-setup.sh
#
# Stops PM2 pear/os-seeder jobs, deletes ~/.config/pear, reinstalls `npm i -g pear`,
# bootstraps the platform (`pear run pear://runtime`), then runs stage-release + seed.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
PEAR_HOME="${HOME}/.config/pear"
BARE_OS_HOME="${BARE_OS_HOME:-$HOME/.bare-os}"
log() {
printf '\n%s\n' "$*"
}
stop_pm2_pear_jobs() {
if ! command -v pm2 >/dev/null 2>&1; then
return 0
fi
log "Stopping PM2 processes that use Pear…"
for name in os-seeder os-booter pear-seed-bare-os-seeder pear-seed-bare-os-booter; do
pm2 delete "$name" 2>/dev/null || true
done
}
kill_pear_sidecars() {
log "Stopping Pear sidecar / pear-runtime processes…"
pkill -f 'pear-runtime' 2>/dev/null || true
pkill -f 'pear\.sock' 2>/dev/null || true
rm -f "${PEAR_HOME}/lock"
sleep 2
}
uninstall_pear() {
log "Removing Pear platform data (~/.config/pear, ~20GB+ if present)…"
kill_pear_sidecars
rm -rf "${PEAR_HOME}" "${HOME}/.pear"
if command -v npm >/dev/null 2>&1; then
npm uninstall -g pear 2>/dev/null || true
fi
# Remove nvm/global shim if present (reinstall recreates it)
if [[ -n "${NVM_BIN:-}" && -f "${NVM_BIN}/pear" ]]; then
rm -f "${NVM_BIN}/pear"
fi
if [[ -f "${HOME}/.nvm/versions/node/$(node -v 2>/dev/null | tr -d v)/bin/pear" ]]; then
rm -f "${HOME}/.nvm/versions/node/"*/bin/pear 2>/dev/null || true
fi
}
install_pear() {
log "Installing Pear CLI (npm i -g pear)…"
npm install -g pear
export PATH="${PEAR_HOME}/bin:${PATH:-}"
if [[ ! -x "${PEAR_HOME}/bin/pear" ]] && command -v pear >/dev/null 2>&1; then
log "Bootstrapping Pear platform (first run)…"
pear 2>&1 | head -20 || true
log "Pear runtime is installed under ${PEAR_HOME}/bin"
export PATH="${PEAR_HOME}/bin:${PATH:-}"
fi
if [[ ! -x "${PEAR_HOME}/bin/pear" ]] && ! command -v pear >/dev/null 2>&1; then
echo "Pear binary not found after install. Add ${PEAR_HOME}/bin to PATH and run: pear run pear://runtime" >&2
exit 1
fi
export PATH="${PEAR_HOME}/bin:${PATH:-}"
log "Pear binary: $(command -v pear)"
pear 2>&1 | head -15 || true
}
write_path_snippet() {
local snippet="${ROOT}/scripts/pear-path.sh"
cat >"$snippet" <<EOF
# Source before pear commands: . scripts/pear-path.sh
export PATH="\${HOME}/.config/pear/bin:\${PATH}"
EOF
log "Wrote ${snippet} — run: source scripts/pear-path.sh"
}
log "=== Pear reinstall + Bare OS stage/release ==="
log "Repo: $ROOT"
stop_pm2_pear_jobs
uninstall_pear
install_pear
write_path_snippet
export PATH="${PEAR_HOME}/bin:${PATH:-}"
rm -rf "${BARE_OS_HOME}/corestore/seeder" "${BARE_OS_HOME}/corestore/booter"
rm -f "${ROOT}/packages/bare-os-seeder/.pear-stage-link" "${ROOT}/packages/bare-os-booter/.pear-stage-link"
log "Minting keys, stage, release, seed…"
"${ROOT}/scripts/reset-pear-apps.sh"
log "=== Complete ==="
log "Add to shell profile: export PATH=\"\${HOME}/.config/pear/bin:\${PATH}\""
log "Dev run: cd $ROOT && npm run os:seeder"
log "Pear run: pear run \$(node scripts/resolve-pear-link.mjs packages/bare-os-seeder)"
log "PM2 seed: pm2 start scripts/pm2-pear-seeders.ecosystem.json"
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin/env bash
# Clear Pear + Bare OS host storage for bare-os-seeder and bare-os-booter,
# mint new pear:// links, update package.json, then stage, release, and seed.
#
# Usage (from repo root): scripts/reset-pear-apps.sh
# Env: BARE_OS_HOME — host data root (default: $HOME/.bare-os)
set -euo pipefail
export PATH="${HOME}/.config/pear/bin:${PATH:-}"
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
SEEDER="$ROOT/packages/bare-os-seeder"
BOOTER="$ROOT/packages/bare-os-booter"
BARE_OS_HOME="${BARE_OS_HOME:-$HOME/.bare-os}"
log() {
printf '\n%s\n' "$*"
}
collect_pear_links() {
node --input-type=module -e "
import fs from 'fs'
const pkgs = ['$SEEDER', '$BOOTER']
const links = new Set()
for (const pkg of pkgs) {
const p = JSON.parse(fs.readFileSync(pkg + '/package.json', 'utf8'))
if (p.pear?.link) links.add(p.pear.link)
const local = pkg + '/.pear-stage-link'
if (fs.existsSync(local)) links.add(fs.readFileSync(local, 'utf8').trim())
}
for (const l of links) if (l) console.log(l)
"
}
drop_pear_link() {
local link="$1"
log "Resetting Pear app storage: $link"
rm -f "${HOME}/.config/pear/lock"
printf 'RESET\n' | pear drop app "$link" 2>&1 || true
}
touch_pear_link() {
node "$ROOT/scripts/bootstrap-pear-stage-link.mjs" "$1" 2>/dev/null | tail -1
}
verify_pear_link() {
local link="$1"
local label="$2"
local tmp
rm -f "${HOME}/.config/pear/lock"
tmp="$(mktemp -d)"
if timeout 90 pear dump "$link" "$tmp" --force >/dev/null 2>&1 && [[ -f "$tmp/index.js" ]]; then
log "$label: staged bundle OK (index.js present at $link)"
rm -rf "$tmp"
return 0
fi
rm -rf "$tmp"
log "WARN: could not verify $label via pear dump (link may still work with pear run --checkout=staged)"
return 0
}
log "Repo root: $ROOT"
log "Pear PATH uses: ${PATH%%:*}"
rm -f "${HOME}/.config/pear/lock"
while IFS= read -r link; do
[[ -n "$link" ]] && drop_pear_link "$link"
done < <(collect_pear_links)
rm -f "$SEEDER/.pear-stage-link" "$BOOTER/.pear-stage-link"
if [[ -d "$BARE_OS_HOME/corestore" ]]; then
log "Removing Bare OS host corestores under $BARE_OS_HOME/corestore/{seeder,booter}"
rm -rf "$BARE_OS_HOME/corestore/seeder" "$BARE_OS_HOME/corestore/booter"
fi
log "Pear GC (cores)…"
pear gc cores 2>&1 || true
log "Minting new Pear links (pear touch)…"
SEEDER_LINK="$(touch_pear_link "$SEEDER")"
BOOTER_LINK="$(touch_pear_link "$BOOTER")"
log " seeder: $SEEDER_LINK"
log " booter: $BOOTER_LINK"
node "$ROOT/scripts/set-pear-package-link.mjs" "$SEEDER" "$SEEDER_LINK"
node "$ROOT/scripts/set-pear-package-link.mjs" "$BOOTER" "$BOOTER_LINK"
log "Stage, release, and seed (scripts/stage-release.sh + pear seed)…"
unset BARE_OS_PEAR_USE_PUBLISHED_LINK
unset BARE_OS_SEEDER_PEAR_LINK
unset BARE_OS_BOOTER_PEAR_LINK
rm -f "$SEEDER/.pear-stage-link" "$BOOTER/.pear-stage-link"
"$ROOT/scripts/stage-release.sh"
log "Seeding $SEEDER_LINK"
(cd "$SEEDER" && pear seed "$SEEDER_LINK" --no-ask --no-tty) || true
log "Seeding $BOOTER_LINK"
(cd "$BOOTER" && pear seed "$BOOTER_LINK" --no-ask --no-tty) || true
verify_pear_link "$SEEDER_LINK" "bare-os-seeder"
verify_pear_link "$BOOTER_LINK" "bare-os-booter"
log "Done."
log " bare-os-seeder: $SEEDER_LINK"
log " bare-os-booter: $BOOTER_LINK"
log "Update docs/PEAR-RUN.md and any pear:// references in the repo with these keys."
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env node
/**
* Resolve the Pear link for a workspace package (stage / release).
*
* Pear CLI v2.5+ requires pear://<key> (not channel names).
*
* Resolution order:
* 1. BARE_OS_SEEDER_PEAR_LINK / BARE_OS_BOOTER_PEAR_LINK (always wins)
* 2. If BARE_OS_PEAR_USE_PUBLISHED_LINK=1 (seeder): package.json pear.link, then pear.stageLink
* 3. <package-dir>/.pear-stage-link (writable local; gitignored)
* 4. package.json pear.stageLink
* 5. package.json pear.link (booter default; seeder fallback)
*
* Usage: node scripts/resolve-pear-link.mjs <package-dir>
*/
import { readFileSync, existsSync } from 'node:fs'
import path from 'node:path'
const pkgDir = path.resolve(process.argv[2] ?? '')
if (!pkgDir) {
console.error('usage: resolve-pear-link.mjs <package-dir>')
process.exit(1)
}
const ENV_BY_PKG = {
'bare-os-seeder': 'BARE_OS_SEEDER_PEAR_LINK',
'bare-os-booter': 'BARE_OS_BOOTER_PEAR_LINK'
}
const LOCAL_LINK_FILE = '.pear-stage-link'
const pkgJsonPath = path.join(pkgDir, 'package.json')
let pkgJson
try {
pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
} catch (err) {
console.error(`Could not read ${pkgJsonPath}: ${err.message}`)
process.exit(1)
}
const name = pkgJson.pear?.name ?? pkgJson.name
const envKey = ENV_BY_PKG[name]
const fromEnv = envKey ? process.env[envKey]?.trim() : undefined
const localPath = path.join(pkgDir, LOCAL_LINK_FILE)
const fromLocal = existsSync(localPath)
? readFileSync(localPath, 'utf8').trim()
: undefined
const fromStageLink = pkgJson.pear?.stageLink?.trim()
const fromPublishedLink = pkgJson.pear?.link?.trim()
const usePublished =
process.env.BARE_OS_PEAR_USE_PUBLISHED_LINK === '1' ||
process.env.BARE_OS_PEAR_USE_PUBLISHED_LINK === 'true'
let link = ''
if (fromEnv) {
link = fromEnv
} else if (name === 'bare-os-booter') {
link = fromLocal ?? fromStageLink ?? fromPublishedLink ?? ''
} else if (usePublished) {
link = fromPublishedLink ?? fromStageLink ?? fromLocal ?? ''
} else {
link = fromLocal ?? fromStageLink ?? fromPublishedLink ?? ''
}
if (!link) {
const publishedHint =
name === 'bare-os-seeder'
? `Production seeder link (pear.link) is read-only on most hosts.\n` +
` node scripts/bootstrap-pear-stage-link.mjs ${pkgDir}\n` +
` Or set ${envKey}.\n` +
` Maintainer host only: BARE_OS_PEAR_USE_PUBLISHED_LINK=1`
: `Set ${envKey} or add "pear": { "link": "pear://…" } to ${pkgJsonPath}.`
console.error(`Missing Pear link for ${name ?? pkgDir}.\n${publishedHint}`)
process.exit(1)
}
if (!/^pear:\/\/[a-z0-9]+$/i.test(link)) {
console.error(`Invalid Pear link (expected pear://<key>): ${link}`)
process.exit(1)
}
process.stdout.write(`${link}\n`)
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env node
/**
* Set package.json pear.link for a workspace Pear app.
* Usage: node scripts/set-pear-package-link.mjs <package-dir> <pear://link>
*/
import { readFileSync, writeFileSync } from 'node:fs'
import path from 'node:path'
const pkgDir = path.resolve(process.argv[2] ?? '')
const link = (process.argv[3] ?? '').trim()
if (!pkgDir || !link) {
console.error('usage: set-pear-package-link.mjs <package-dir> <pear://link>')
process.exit(1)
}
if (!/^pear:\/\/[a-z0-9]+$/i.test(link)) {
console.error(`Invalid link: ${link}`)
process.exit(1)
}
const pkgJsonPath = path.join(pkgDir, 'package.json')
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
pkgJson.pear = pkgJson.pear ?? {}
pkgJson.pear.link = link
writeFileSync(pkgJsonPath, `${JSON.stringify(pkgJson, null, 2)}\n`, 'utf8')
console.log(`Updated ${pkgJsonPath}${link}`)
+30 -6
View File
@@ -3,6 +3,8 @@
# Run from anywhere; resolves repo root from this script's location.
set -euo pipefail
export PATH="${HOME}/.config/pear/bin:${PATH:-}"
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
SEEDER="$ROOT/packages/bare-os-seeder"
BOOTER="$ROOT/packages/bare-os-booter"
@@ -29,7 +31,7 @@ prepare_pkg_for_pear() {
local nm="$pkg/node_modules"
local rel="${pkg#"$ROOT"/}"
log "Mirroring root node_modules → $rel/node_modules (ensure-pear-node-modules)"
(cd "$ROOT" && node scripts/ensure-pear-node-modules.mjs "$rel")
(cd "$ROOT" && BARE_OS_PEAR_NODE_MODULES=1 node scripts/ensure-pear-node-modules.mjs "$rel")
rm -rf "$nm/bare-os-protocol"
log "Copying bare-os-protocol into $(basename "$pkg")/node_modules"
cp -R "$PROTO" "$nm/bare-os-protocol"
@@ -40,7 +42,22 @@ prepare_pkg_for_pear() {
fi
}
# Pear CLI v2.5+ requires pear://<key>, not channel names (bare-os-seeder).
resolve_pear_link() {
local pkg="$1"
local link
link="$(node "$ROOT/scripts/resolve-pear-link.mjs" "$pkg" 2>/dev/null)" || true
if [[ -n "$link" ]]; then
printf '%s' "$link"
return 0
fi
log "Bootstrapping Pear link for $(basename "$pkg")"
node "$ROOT/scripts/bootstrap-pear-stage-link.mjs" "$pkg" >/dev/null
node "$ROOT/scripts/resolve-pear-link.mjs" "$pkg"
}
log "Repo root: $ROOT"
rm -f "${HOME}/.config/pear/lock"
ensure_root_deps
log "Sync kernel/ -> packages/bare-os-seeder/kernel/"
@@ -50,14 +67,21 @@ cp -R "$ROOT/kernel/." "$SEEDER/kernel/"
prepare_pkg_for_pear "$SEEDER"
prepare_pkg_for_pear "$BOOTER"
SEEDER_LINK="$(resolve_pear_link "$SEEDER")"
BOOTER_LINK="$(resolve_pear_link "$BOOTER")"
log "Pear links: seeder=$SEEDER_LINK booter=$BOOTER_LINK"
log "Staging bare-os-seeder…"
(cd "$SEEDER" && pear stage bare-os-seeder --no-ask)
(cd "$SEEDER" && pear stage "$SEEDER_LINK" --no-ask)
log "Releasing bare-os-seeder…"
(cd "$SEEDER" && pear release bare-os-seeder)
(cd "$SEEDER" && pear release "$SEEDER_LINK")
log "Staging bare-os-booter…"
(cd "$BOOTER" && pear stage bare-os-booter --no-ask)
(cd "$BOOTER" && pear stage "$BOOTER_LINK" --no-ask)
log "Releasing bare-os-booter…"
(cd "$BOOTER" && pear release bare-os-booter)
(cd "$BOOTER" && pear release "$BOOTER_LINK")
log "Done. Use pear stage … --json | tail -1 for verlink, or pear run pear://<key>"
log "Done."
log " bare-os-seeder: $SEEDER_LINK"
log " bare-os-booter: $BOOTER_LINK"
log " pear stage … --json | tail -1 for verlink, or pear run <link>"