Skip to content

Latest commit

 

History

History
218 lines (179 loc) · 10.1 KB

File metadata and controls

218 lines (179 loc) · 10.1 KB

Local GhostGet development

Use a stable lane for real work and a separate worktree lane for development. This keeps local source edits, dependencies, builds, and private state from changing underneath another chat or the installed ghostget command.

Stable and development lanes

Keep the control checkout on main and use it to create and retire worktrees. Keep the normally installed ghostget command and its normal state for trusted day-to-day work, especially provider mutations. Do not globally link a changing development checkout over that command.

Give every development chat a unique task name. Its worktree gets a codex/<task> branch, its own frozen Bun install, and private state and media roots. Chats that may edit source must not share a task worktree. They may run in parallel when each uses its own task.

The helpers require Bun 1.3.14. Git worktrees cannot inherit uncommitted files, so first commit the local-development setup and any source every new task needs. The helper uses the control checkout's current HEAD by default; fetch and advance that checkout only when you explicitly want a newer base:

git fetch --prune origin # optional: refresh the local base first
./scripts/local-dev/new-worktree codex-20260814-example

The helper does not fetch or merge implicitly. GHOSTGET_WORKTREE_BASE may select another locally known commit or ref. By default it creates the worktree in a sibling directory named <control-checkout>-worktrees. Set an absolute GHOSTGET_WORKTREE_ROOT to put worktrees elsewhere:

GHOSTGET_WORKTREE_ROOT=/absolute/path/ghostget-worktrees \
  ./scripts/local-dev/new-worktree codex-20260814-example

Task names contain only lowercase letters, digits, and internal hyphens and are at most 48 characters. The helper refuses an existing target or branch and runs bun install --frozen-lockfile only after Git creates the worktree. If the install fails, it leaves the worktree in place for inspection or an explicit cleanup.

Run the current source

Invoke the task's source CLI through the control checkout's runner:

./scripts/local-dev/run-ghostget codex-20260814-example doctor --json

The runner starts a new Bun process against that worktree's source on every call and disables Bun's automatic package installation. A tiny tracked launcher binds Bun to the worktree's configuration before restoring the caller's working directory and loading src/cli.ts. No build or global relink is needed: a completed edit is visible to the next invocation. An already-running invocation keeps the code it loaded, so source edits do not hot-swap its process. Let long-running commands finish before changing behavior they depend on. The runner also disables caller .env loading and verifies the exact registered codex/<task> worktree before executing it. Ambient BUN_CONFIG_FILE, BUN_OPTIONS, and NODE_OPTIONS runtime hooks are discarded as part of that boundary.

The runner briefly enters the Ghostget worktree to bind Bun configuration; the tracked launcher restores the caller directory before the CLI loads. Relative CLI inputs and outputs therefore continue to resolve from the caller's directory:

cd /absolute/path/to/a/caller-project
/absolute/path/to/ghostget/scripts/local-dev/run-ghostget \
  codex-20260814-example doctor --json

Each task uses these private roots by default:

$HOME/.local/share/ghostget-dev/<task>/state
$HOME/.local/share/ghostget-dev/<task>/media

Move that development root with an absolute GHOSTGET_DEV_HOME. Use the same overrides for every invocation of a task:

GHOSTGET_WORKTREE_ROOT=/absolute/path/ghostget-worktrees \
GHOSTGET_DEV_HOME=/absolute/private/path/ghostget-dev \
  /absolute/path/to/ghostget/scripts/local-dev/run-ghostget \
  codex-20260814-example doctor --json

Never point a development task at the stable Ghostget state or media roots, and never symlink state, media, auth, browser profiles, node_modules, or dist between tasks.

Mutation boundary

State isolation also isolates confirmation, dispatch, and at-most-once evidence. Separate task ledgers cannot coordinate with each other or with the stable installation. Do not submit the same real R2 or R3 provider mutation from multiple lanes. Route real mutations through one stable Ghostget installation and its normal state. Use development roots for reads, local fixtures, and deliberately isolated test accounts or targets.

Refresh the Agent Skill

The repository's skills/ghostget/ directory is the skill source; an agent does not automatically read edits from that directory. Keep the normally installed skill pinned to the same stable release as plain ghostget; CLI worktree iteration does not require replacing it.

Skill replacement is a serialized maintenance boundary, not hot reload. When no active task may still discover or use the installed Ghostget skill, validate the revision, stage a complete copy on the same filesystem but outside Codex's skill-discovery directory, and publish that complete tree with rollback. Then refresh Codex and start a new task. Do not run rsync --delete directly into the live installed directory, and do not switch one user-level skill between parallel worktrees.

For example, after quiescing Ghostget tasks:

(
  set -eu
  CODEX_ROOT="${CODEX_HOME:-$HOME/.codex}"
  CODEX_SKILLS_HOME="$CODEX_ROOT/skills"
  SKILL_SWAP_ROOT="$CODEX_ROOT/local-skill-snapshots/ghostget"
  mkdir -p "$SKILL_SWAP_ROOT"
  SKILL_SWAP="$(mktemp -d "$SKILL_SWAP_ROOT/swap.XXXXXX")"
  SKILL_STAGE="$SKILL_SWAP/stage"
  SKILL_BACKUP="$SKILL_SWAP/previous"
  cp -R ./skills/ghostget "$SKILL_STAGE"
  mv "$CODEX_SKILLS_HOME/ghostget" "$SKILL_BACKUP"
  if ! mv "$SKILL_STAGE" "$CODEX_SKILLS_HOME/ghostget"; then
    mv "$SKILL_BACKUP" "$CODEX_SKILLS_HOME/ghostget"
    exit 1
  fi
)

The preserved local-skill-snapshots/ghostget/swap.*/previous directory is an explicit rollback candidate outside live skill discovery; inspect and retire it manually only after the new skill is accepted. The quiesced replacement has a brief gap between moving the prior directory aside and publishing the complete staged tree, and the snippet restores the prior directory if publication fails. Adjust the destination if the agent host uses a different skills directory. Existing tasks may have already loaded instructions, so the safe guarantee is only that new tasks started after the refresh see the new complete snapshot. When testing local code, tell the new task the absolute run-ghostget command and task name so it does not fall back to the stable ghostget executable.

Verify and retire a task

Before source delivery, run relevant focused local checks inside the task worktree and obtain independent impact and diff review. Complete Required PR CI is the normal final source integration gate for executable and documentation changes. It runs the complete Linux aggregate plus a selected macOS suite; preserve its executable phase-composition and disjoint source coverage contracts:

cd /absolute/path/ghostget-worktrees/codex-20260814-example
bun test scripts/ci-pr-gate.test.ts

Record the repository, reviewed workflow, successful run and attempt, complete required job union, actual checked commit and tree, PR head, and current base. Revalidate immediately before conditional merge; head or base movement requires matching current-candidate CI. An older candidate's receipt never qualifies the new integration.

The selected macOS inventory in scripts/ci-macos-check.ts does not cover every native behavior or establish complete macOS package or installation equivalence. For impacted native behavior outside that suite, run relevant focused macOS checks or add and pass an independently reviewed CI extension. Keep every explicit local, native, coupled-sequence, live, installation, package-release, provider-control, and production acceptance requirement, including opt-in qualifications when required. Hosted runners do not qualify the user's Keychain, signed-in browser, profiles, devices, installation, or production state.

Keep bun run check available as the complete local aggregate and use it when coverage or equivalence is uncertain, a coupled sequence must run together, or a known failure needs the complete local reproduction. Diagnose observed failures and retain their relevant reproduction and repair checks. Independently review workflow, discovery, command, deadline, and platform changes against the prior required coverage; edited coverage assertions alone cannot certify a weakened workflow.

CI bounds each Apalache check to 25 minutes, each Quint shard step to 40 minutes, and its job to 45 minutes. This preserves time for the remaining model checks, mutants, replay, setup, and diagnostic upload. The September 27, 2026 passing source run took 18 minutes 23 seconds for fenceSafety and 29 minutes 38 seconds for its whole shard; three subsequent merged-source runs exhausted the former 20-minute checker ceiling, the latest during final-state checks. The larger ceilings retain every model, depth, seed, invariant, and mutant. A timeout remains a failed gate; release admission still requires success for the current source candidate.

Before cleanup, make sure no chat or shell is using the worktree and commit or otherwise preserve wanted changes. Then remove the exact worktree through Git, delete its branch only after Git accepts the removal, and prune stale metadata:

git -C /absolute/path/to/ghostget worktree remove \
  /absolute/path/ghostget-worktrees/codex-20260814-example
git -C /absolute/path/to/ghostget branch -d codex/codex-20260814-example
git -C /absolute/path/to/ghostget worktree prune

Review the exact <GHOSTGET_DEV_HOME>/<task> directory separately before deleting it. It can contain private auth, provider, plugin, and media state. Do not use a broad glob or remove the worktree directory directly.

The read runtime ownership guide describes the R1 Effect programs, native cleanup proof and the bun run check:effect architecture gate. The confirmed-write guide explains synchronous durable callbacks, reconciliation and native cleanup for R2/R3 confirmation.