On this page
Deciding what products are called
A product has an id, the word every program, receipt, release and route keys it by, and a display name. Both live in its record in catalog/products.yml, together with the decision that gave them and every name it had before. stado product name is the one place they change: stado product registry add gives a new product its first name, and registry set no longer takes --name.
stado product name list
stado product name show ALPHA
stado product name check omega --as-id --org wisent-ai
stado product name set alpha --id gamma --name Gamma --decided-by operator --reason "the name the operator chose"
stado product name set gamma --name "Gamma Prime" --decided-by operator --reason "a display name only"
stado product name forget gamma alpha
stado product name adopt
stado product name usages stado
stado product name sync --check
stado product name sync
Every verb takes --json.
What the catalog keeps
naming:{decided_by, decided_at, reason}, the decision that gave the product its current names.decided_atis an RFC 3339 time and is not in the future;decided_byandreasonare not empty.former_names: one row per earlier name,{id, name, until}, with thedecided_by,decided_atandreasonit stood under when one was recorded. A row is written byname setand removed only byname forget.- A name, current or former, belongs to one product. Names are compared without regard to case or surrounding spaces. Any write of the catalog (
registry,name,create) refuses a catalog where two products share one:<product>: its <what> "<name>" is already the <held as> of <other>; a name, current or former, belongs to one product, so give <product> another name (stado product name check NAMEsays whether a name is free). - No product id names a directory Stado keeps for itself under
~/.stado/products, beside the receipt directories named for products:output,builds,placed,workspace,cargo-build,inputs(the pinned input archives a build keeps by their digest) andwisent-products. A product so named would keep its installation receipts in Stado's own output, build areas, staged bundles or kept archives, so every read of the catalog refuses it (stado.product.catalog.record.product-kept-directory):holding the catalog record of <id> to its declarations: product id <id> names a directory Stado keeps for itself under ~/.stado/products (one of output, builds, placed, workspace, cargo-build, inputs, wisent-products), so the product's installation receipts would share it; observed: id: <id>, fixed by giving the product another id. Stado never reads one of those directories as a product's receipts.
The verbs
listprints every product's id, display name, the decision behind them and each former name with when it stopped.show NAMEanswers which product a name belongs to and how it holds it (id,display name,former id,former display name), with the product's naming record. A word no product holds or held is refused:no product is or was called "<name>" in <catalog>:stado product name listlists every name, current and former.check NAMEexits 0 when no product holds the name and 1 when one does, naming it.--as-idalso refuses a name that cannot be an id (lowercase letters, digits and inner hyphens) and one that names a directory Stado keeps under~/.stado/products, with the refusal above.--org ORGalso reads the organization's repositories throughgh repo listand calls the name taken by a repository named for it or for one of its surfaces (<name>-desktop), saying which product claims it.set PRODUCTrecords one decision. It requires--decided-byand--reason, and--id,--nameor both.forget PRODUCT FORMERremoves a former name recorded in error. A name the product really had stays, because it is how a reader of an older page finds the product.adoptmoves this machine's installation receipts kept under a former id to the product's current id.stado product syncdoes the same at the start of every pass (--dry-runonly says what would move), so every machine follows a rename on its own.syncwriteswisent-names.jsonat the root of the workspace checkout of every repository a record claims and commits that file alone (git commit --only), so another session's staged or unstaged work in the same checkout is neither committed nor touched. The file holdsown, the names of the product that claims the repository, andauthority, the names of the product that owns the catalog (authority.owner), through which every other product is reached by capability; no checkout needs a third product's names. Each is{id, name, program, programs, state_directory, environment_prefix, site, address, unit_label, owner_repository, former_ids}, derived from the record alone:programis the first program the installations declare, else the id;state_directory(.<program>) andenvironment_prefix(<PROGRAM>_) follow the program;siteis the cli surface'sdocs_origin, elsehttps://<id>.wisent.com, andaddressis the site without its scheme;unit_labelisservice.unit, elsecom.wisent.<id>. Each repository answers one row:current,written and committed,rewritten and committed,written, not committed: <git's words>,absent: the workspace holds no checkout of it, orrefused: claimed by <products>, so it has no one own product.--checkwrites nothing and exits 1 naming every file that ismissingorstale, and every repository claimed by several products:a checkout's names file is missing, stale or has no one own product, so what it reads is not the name the catalog decided. A names file the system will not read is refused:the system refused to read it, so whether it says what the catalog says cannot be told.
What set changes
With --name alone, the display name changes, the decision is recorded, and the names it had become a former name.
With --id, also:
- every other record's
integrationsanddependenciesnaming the product are carried to the new id; - the declarations other systems already hold under the former id are kept, written out where the id implied them:
service.unit(com.wisent.<former>, the label hosts run),service.directory_service(the service directory key),release_producton eachstado-releaseinstallation (the name its published releases and release manifest carry) and the cli surface'sdocs_origin(https://<former>.wisent.com). Catalog validation accepts a former id's unit label for this reason. A renamed product therefore keeps installing from its published releases, keeps its running service and its documentation; each moves to the new id when its owner moves it; - this machine's receipts move from
~/.stado/products/<former>/to~/.stado/products/<id>/and are rewritten to name the new id; syncruns, so every checkout'swisent-names.jsoncarries the decision, and every page and program that reads the file follows it with no edit.
Only the renamed record and the records whose references changed are rewritten; every other record and every comment in the file is kept byte for byte. The answer lists references, kept, receipts, outside and names (one row per repository, as sync answers), and, like registry, uncommitted: for a catalog a checkout tracks, readers read the committed catalog, so the answer names the checkout, the path and the git commit that makes the decision what every reader sees; it is null for a file no checkout tracks. forget answers the same field.
Where pages and programs read the names
A product's documentation pages write {{own.name}}, {{own.program}}, {{own.address}}, {{own.site}}, {{own.state_directory}}, {{own.environment_prefix}}, {{own.unit_label}} and {{own.id}}, and the same fields of authority, instead of the words; a page that shows a placeholder itself writes a backslash before it (\{{own.name}}). The same three commands of landing-cli serve every product's site. landing docs names check --corpus <pages> --names wisent-names.json refuses a line that writes a name by hand and a placeholder the file does not answer, each by page and line, so a new page cannot bring a name back. landing docs names publish … --out <directory> fills the placeholders into a directory of their own, which the site's build reads; a missing names file is refused with stado product name sync as what writes it. landing docs names adopt moves pages written by hand onto the file: each spelling of the product's names becomes its placeholder, and a name joined into another name (stado-rs, a repository's owner/name, a page slug) is left, because it names that thing and moves only when that thing is renamed. The site's own titles, metadata and sidebar read the same file through src/lib/site/names.ts.
What set names but does not change
outside lists every place that still carries the former id, each with what, state and next, the command that moves it. Nothing outside the catalog file, this machine's receipts and each checkout's wisent-names.json is changed, because each place has its own owner:
- a repository the record claims that is named for the former id or
<former>-<surface>:gh repo rename <new> --repo <owner>/<old>, thenstado product registry set <id>with the new repository; - a release manifest in the workspace checkout of any repository the record claims whose
productis the former id, read once per manifest: the catalog keepsrelease_producton the installations that read it, so change the manifest'sproductand removerelease_productin one change when releases move to the new id; a manifest the workspace does not hold is listed asnot read; - the documentation site at
https://<former>.wisent.com: publish the site at the new address, then dropdocs_origin; - with
--org ORG, a repository of the organization named for the former id that no record claims; - the lines of the workspace's checkouts that still write the former id, counted as
usagescounts them:<lines> lines in <n> of the <total> checkouts still write <former>, withstado product name usages <former>as what names each one.
Refusals
Each leaves the catalog as it was.
| Refusal | Cause |
|---|---|
name set <product> names nothing to change: give --id NEW-ID, --name "New Name" or both; nothing was changed |
neither --id nor --name |
--decided-by and --reason must say who decided the name and why; nothing was changed |
one of them is blank; clap refuses a missing one with exit 2 |
--id "<id>" cannot be a product id; nothing was changed |
the id is not lowercase letters, digits and inner hyphens |
<product> is already called <product> (<name>); nothing was changed |
the decision changes nothing |
--id|--name "<word>" is already the <held as> of <other>: a name, current or former, belongs to one product, so choose another (...); nothing was changed |
another product holds the name, now or before |
<word> is the <held as> of <product>, not a product id: name the product as <product>; nothing was changed |
PRODUCT is a former name or a display name |
no product <word> in <catalog>: stado product name list lists every product; nothing was changed |
unknown product |
<catalog> does not exist: a name is decided in the catalog file, so run this where the workspace holds stado/catalog/products.yml (--workspace), or name the file with --catalog; nothing was changed |
only the catalog compiled into Stado is available |
another writer owns <catalog>.lock; held by pid ... |
another catalog write is running |
catalog changed during the operation; nothing was overwritten |
the file changed between reading and writing |
"<word>" is <product>'s current name, not a former one: a current name changes with stado product name set; nothing was changed |
forget of a current name |
<product> has no former name "<word>"; its former names are <list>; nothing was changed |
forget of a name never recorded |
set and adopt refuse to move receipts when the new id already has a receipt directory (<from> and <to> both hold receipts: ...) or an installation of the product is running (the <surface> installation of <former> is running (...); its receipts move to <id> once it ends: run stado product name adopt then). set reports this after the catalog is written; adopt lists such a directory as refused with the cause, moves the rest and exits 1.
Name register
stado product catalog --names adds a Former names table to ~/NAMES.md listing each former id and display name with the product that carries it now and when it stopped, so an older name still leads to its product.
Desktop
Stado Desktop's Products screen runs every verb through the selected Stado API host: Read what every product is called, Read which product a name belongs to, Check whether a name is free for a product, Rename a product: record the decision and carry the new name through the catalog (asks for confirmation), Remove a former name recorded in error, Move installation receipts kept under a former product id to the current one and Read every line of the workspace's checkouts that writes a product's name by hand: what renaming it has to change. Update a catalog product no longer offers a display name field. Answers and refusals are shown as the CLI prints them.
Real journey
STADO_BIN=<stado> node tests/product/name_decisions.mjs in Stado runs every verb against an isolated catalog and home, reads the catalog file and receipts back after each, and asserts each refusal sentence above. STADO_BIN=<stado> node tests/product/name_usages.mjs builds an isolated workspace of two git checkouts that write a fictional product's name in every kind, reads usages back line by line, renames the product and reads the former id's lines in set's outside, and asserts the unknown-name, unlistable-workspace and unreadable-checkout refusals.
Source: this website