Moving a company to the new names
A company's own files were renamed: overbot.yml is structure.yml, and .overbot/ is
.structure/. The old names are still read for one release, structure check says "rename it",
and structure migrate does the move. The names and the one rule that reads them are
packages/engine/src/paths.ts; the verb is packages/cli/src/migrate.ts.
What changed
| what | was | is | read as a fallback until |
|---|---|---|---|
| the policy file | overbot.yml | structure.yml | the release after this one |
| the record directory | .overbot/ | .structure/ | the release after this one |
| the product's environment variables | OVERBOT_<NAME> | STRUCTURE_<NAME> | the release after this one |
| the release's asset manifest | overbot-assets.json | structure-assets.json | read under the new name first; still written under the old one (see below) |
A company that is written new — new, genesis, a starter — gets the new names. A company
written earlier keeps working exactly as it did: every reader asks for the new name first and the
old one second, and every writer writes where the company's files already are. Nothing is moved
for you.
When both names exist, the new one is read and the old one is ignored; the two are never merged.
check says which is which.
What check says
One warning, on a company still on the old names:
rename overbot.yml to structure.yml and .overbot/ to .structure/ — run: structure migrate.
The old names are read until the release after this one
It is a warning, not an error: the check stays green, hooks and work finish are not blocked.
One case is an error: a checkout whose hooks are not running. check asks git which folder it
runs hooks from in this checkout (whatever core.hooksPath says, however it is spelled, from
whichever config it comes) and says so when that folder is not there — the move reached this clone
by a pull or a merge and the setting still names the old folder — or when a hook in it is not
executable, or when a hook this checkout keeps in its record directory has no link in the clone's
shared hooks folder. Run migrate in that checkout (or the chmod +x the finding names) and
they run again. A clone that never set core.hooksPath is not this finding; doctor says so.
migrate
Run it in the company folder. It makes one commit:
git mv overbot.yml structure.yml— the same bytes under the new name, sogit log --followstill reaches the file's history;- everything under
.overbot/moves to the same place under.structure/— tracked files withgit mv; the device-local files git ignores (the attention canary, set-aside work, the company index) with a plain rename; - what was ignored stays ignored, and git is the one asked: every line in
.git/info/excludeand in your own root.gitignorethat names.overbot/as a path segment gets a twin for.structure/(/.overbot/x,.overbot/,!.overbot/keep,**/.overbot/private/); then git lists what it ignores under.overbot/today and says, file by file, whether it would still be ignored under.structure/— a file that would not gets a line in the file whose pattern ignored it (a pattern from a global excludes file gets its twin in.git/info/exclude, said on the terminal), and a file that cannot be kept ignored is a refusal before anything moves. The.gitignorelines ride in the same commit; - lines in your root
.gitattributesthat name.overbot/get their twin the same way, and git is asked afterwards whether every moved file's attributes are what they were — a difference is said; - hooks in
.githooks/are left alone. If your hooks live under the record directory — asked of git, which folder it runs hooks from in this checkout, not read off the setting's spelling (./.overbot/hooks,.overbot/hooks/,~/…, an absolute path, a symlink on the way, any scope or include) —core.hooksPathis pointed at one folder inside the clone's git directory that runs each checkout's own hooks, whichever names that checkout is on, so they keep running in every worktree of the clone, moved or not; an absolute path into this checkout's record directory simply follows the directory. The setting is written where this checkout's value lives — and nowhere else: a checkout of the clone whose hooks git ran from somewhere outside the moved directory (its own.githooks, a folder of its own, in its own worktree config) is left as it was, setting, folder and hooks. Then git is asked, in every checkout, where it runs hooks from: the same place as before, unless that place was inside the moved directory. Any other answer, or a value git takes from somewhere this command does not write (its command line, a config outside the clone that wins), is a refusal before anything moves. The clone's shared hooks folder links exactly the hooks some checkout has — to git an absent hook and a silent one are different things (push-to-checkout) — and a hook added later is acheckfinding until the nextmigratelinks it; - the compiled files the company already has (
AGENTS.md, the hooks) are rewritten so they name the new files. It never creates a compiled file the company did not have.
migrate --dry-run says what would move and moves nothing.
It refuses, before anything moves, when:
- the tree has uncommitted changes — it names them. The move is one commit you can read.
- a serve is running on the company — it names the process and the port. Stop it
(
serve --stop), migrate, start it again. overbot.ymlandstructure.ymlboth exist — which one is kept is yours to settle.- the same file exists under
.overbot/and.structure/— it names them. .overbot/is a link, not a folder, a submodule lives under it, or git tracks files under it that this checkout does not have (a sparse checkout) — each named.- the hooks could not be kept running in every checkout, or a file git ignores would show as untracked after the move — each named, with where the setting or the pattern comes from.
Run it twice and the second run says there is nothing to do.
If the company's own commit gate refuses the commit, everything is put back and the gate's words
are shown. A gate compiled by this release reads the rename for what it is — the same bytes under
a new name is not a change to canon — so bring an older gate up to date first
(compile --write, commit that), then migrate.
The policy file moves byte for byte, so a line in it that names the file or the record directory
(overbot.yml: owner, a line over .overbot/) still spells the old name. It means what it meant:
the two names are read as one path wherever a policy line, a link, an answer's source or a
routine's declared path is matched. Change the spelling when you next edit the policy.
The approved-by scan reads the migration commit for what it is. The same bytes leaving the old
name for the new one is not an unsigned change; a later unsigned edit to structure.yml is.
Before you run it: everyone on the company upgrades first
A build from before the rename cannot read structure.yml. Migrate once every device that opens
the company runs a build that can.
Work that is in flight
| in flight | what happens |
|---|---|
| a work entered in its own worktree | Its branch keeps overbot.yml and .overbot/ — its own copy of the files — and keeps working. When it lands, git carries its edits to overbot.yml into structure.yml. Its work record, added under .overbot/work/, lands there: check then says .overbot/ was left behind, and migrate (run again, or run in the work's worktree before it lands) moves it. |
| a proposal waiting for approval | The same: read under either name, approved as usual. Its discussion is taken out of the tree at approval, as always, wherever it sat. |
| a batch run mid-flight | The record keeps the destinations it declared (.overbot/runs/… is the artifact's identity); batch close reads each file where it is now. A process whose canon declares .overbot/runs/<run-id>… still binds. |
a thread's record branch (overbot/runs/*) | Unchanged; read under either name. |
What does not change
The branch names (overbot/proposals/*, overbot/attention, overbot/runs/*,
overbot/machines, work/*), the record ref namespace (refs/overbot/*),
the worktree folder beside a company (.overbot-worktrees/), and the device's config directory
(~/.config/overbot). These are identity, not file names. The files inside the shared record
branches (overbot/machines, overbot/attention) and the claim refs also keep their paths this
release: every device of a company writes them, whatever build it runs.
Environment variables
Every variable the product reads is read as STRUCTURE_<NAME> first and OVERBOT_<NAME> second
— the new name when it is set, even to nothing (a person who set it meant it), else the old. The
old names stop being read in the release after this one. When the product starts a child of its
own (the CLI, or the desktop host starting a serve) it sets both names where it sets either, and
removes both where it removes either. If both names are set to different values, the new one is
the one read, and a serve says so when it starts — on the terminal, and in its instance record.
| new name | old name (fallback) | what it is |
|---|---|---|
STRUCTURE_CONFIG_DIR | OVERBOT_CONFIG_DIR | where this device's state lives (config, instance records) |
STRUCTURE_ACTOR | OVERBOT_ACTOR | who this process signs as (human/<name>, agent/<name>) |
STRUCTURE_MACHINE | OVERBOT_MACHINE | this device's name in the fleet |
STRUCTURE_MACHINE_ADDRESS | OVERBOT_MACHINE_ADDRESS | the address this device is reached at |
STRUCTURE_MASTER_KEY | OVERBOT_MASTER_KEY | the company key for the encrypted store (CI) |
STRUCTURE_KEYCHAIN | OVERBOT_KEYCHAIN | which macOS keychain holds mail and sign-in tokens |
STRUCTURE_ASSET_ROOT | OVERBOT_ASSET_ROOT | the folder a serve reads its pages from |
STRUCTURE_INSTANCE_OWNER | OVERBOT_INSTANCE_OWNER | who owns a serve (cli, app:<host>) — set by a host for its child |
STRUCTURE_REPO | OVERBOT_REPO | the company a host opens |
STRUCTURE_SERVE_REQUIRE_TOKEN | OVERBOT_SERVE_REQUIRE_TOKEN | 1 asks every caller for the serve token |
STRUCTURE_TRUST_PROXY | OVERBOT_TRUST_PROXY | 1 trusts a reverse proxy's forwarded address |
STRUCTURE_TAILSCALE_BIN | OVERBOT_TAILSCALE_BIN | where the tailscale binary is |
STRUCTURE_GENESIS_SCRIPT | OVERBOT_GENESIS_SCRIPT | a scripted genesis conversation |
STRUCTURE_GENESIS_THINKING | OVERBOT_GENESIS_THINKING | the model's thinking setting for genesis |
STRUCTURE_CLAIM_LEASE, STRUCTURE_CLAIM_GRACE | OVERBOT_CLAIM_LEASE, OVERBOT_CLAIM_GRACE | claim timing, in seconds (tuning) |
STRUCTURE_PLACEMENT_POLL_MS, STRUCTURE_BOUNDARY_POLL_MS | OVERBOT_PLACEMENT_POLL_MS, OVERBOT_BOUNDARY_POLL_MS | serve polling intervals (tuning) |
STRUCTURE_CREATION_TTL_MS, STRUCTURE_CREATION_SWEEP_MS | OVERBOT_CREATION_TTL_MS, OVERBOT_CREATION_SWEEP_MS | how long an unfinished creation is kept (tuning) |
STRUCTURE_TURN_STREAMS_MAX | OVERBOT_TURN_STREAMS_MAX | how many turn streams a serve keeps open (tuning) |
STRUCTURE_TUI_SNAP | OVERBOT_TUI_SNAP | a folder the terminal UI writes frame snapshots to (testing) |
STRUCTURE_MENU_BAR_LIFETIME, STRUCTURE_GATE_OPEN_COCKPIT | OVERBOT_MENU_BAR_LIFETIME, OVERBOT_GATE_OPEN_COCKPIT | a host's gate switches (set by the release gates) |
Not renamed, and why:
| name | why it stays |
|---|---|
OVERBOT_APIFY_TOKEN, OVERBOT_X_BEARER_TOKEN, OVERBOT_X_MONTHLY_CAP_USD, OVERBOT_ELEVENLABS_API_KEY | not environment variables: the names of lines in a company's encrypted store. Renaming them would orphan what a company has stored. |
OVERBOT_REPO_TOKEN, OVERBOT_READ_TOKEN, OVERBOT_ROUTINE_TOKEN, OVERBOT_MAINTAINER_ENABLED | GitHub secrets and variables a company set in its own repository, named in the workflow the compiler writes. |
OVERBOT_SIGN_IDENTITY, OVERBOT_NOTARY_PROFILE, OVERBOT_COSIGN*, OVERBOT_RELEASE_REPO, OVERBOT_TAP_REPO, OVERBOT_SKIP_GATES, OVERBOT_BUILD_STAMP | the release tooling's own (bin/), read by a shell script and by TypeScript in the same cut: they move together, with the release's names. |
OVERBOT_TEST_*, OVERBOT_GATE_*, OVERBOT_ACCEPTANCE_SCRATCH, OVERBOT_SCREENS_DIR, OVERBOT_GENESIS_GOLDEN, and the build's three flags (named only in bin/, never in a shipped guide — the static gate refuses them in the binary's bytes) | the suite's and the build's own: no person sets them. The gate removes every STRUCTURE_* variable from the environment it hands a suite unit, so a variable in your shell cannot outrank the suite's isolation. |
A scheduled routine's crontab line carries the settings folder under both names (STRUCTURE_CONFIG_DIR and OVERBOT_CONFIG_DIR), so the build cron fires reads it whichever it knows.
The asset manifest
A serve reads structure-assets.json from an asset root first and overbot-assets.json second.
The release pipeline still writes overbot-assets.json; renaming the written name is the
release's to do with the rest of its names.