Skip to content

EDGE-642: rename Orchestrator to Device and Device to vPLC across the documentation - #18

Open
Thiago-Pio-Autonomy wants to merge 19 commits into
developmentfrom
docs/edge-642/rename-device-vplc
Open

EDGE-642: rename Orchestrator to Device and Device to vPLC across the documentation#18
Thiago-Pio-Autonomy wants to merge 19 commits into
developmentfrom
docs/edge-642/rename-device-vplc

Conversation

@Thiago-Pio-Autonomy

@Thiago-Pio-Autonomy Thiago-Pio-Autonomy commented Sep 10, 2026

Copy link
Copy Markdown

What this is

EDGE-642, the user-docs half of
EDGE-633.

The product vocabulary changes across the documentation. Orchestrator becomes Device, the
child that was Device becomes vPLC, the agent becomes the Device Agent, and inside the
Editor's documentation the platform entity reads Edge Device, because "Device" there already
means the PLC target being programmed.

This is not a find-and-replace, and the reason is the next section.

"Device" has seven senses in this repository, and only one of them changes

This is the repository where they were catalogued, so the list belongs here. Every occurrence of
"orchestrator", "orchestration" and "device" carries a recorded decision code (FR17, FR20) in
docs/exploration/RENAME-DECISION-RECORD.md, with the census in rename-census.csv. Counts are
from the base-commit census, with the final tree in brackets.

# Sense Decision n
1 The child entity, the virtual PLC Changes to vPLC (BR02) 110 -> [0]
2 The machine the agent runs on, "your edge device" Stays, lowercase. This is the sense the new vocabulary promotes, so it gets a consistency pass, not a rename 84 -> [83]
3 The Editor's Device node and its Device Configuration screens Stays. The PLC target being programmed, a different concept. This is also why the on-disk devices/ directory is not renamed (BR06, FR09) 129 -> [125]
4 Remote device: a Modbus master, an EtherCAT bus or slave Stays. The industry's word, not ours 192 -> [186]
5 Plain networking or hardware English Stays 29 -> [28]
6 LicensedDevice, the VPP licensing unit Stays (BR12). Zero occurrences: user-docs does not document VPP licensing 0
7 The PLC or runtime the editor is connected to Stays. Absent from the original framework and added here: that target can be a vPLC or physical hardware, so calling it a vPLC would make these pages wrong for anyone running a real PLC 98 -> [95]

Sense 7 is the one worth a reviewer's attention, because it is the one nobody had written down.

The asymmetry that made this safe

The Editor's documentation holds 533 of the census rows, and only 84 of them change. 449 stay:
they are senses 3, 4 and 7. A global replace inside openplc-editor/ would have been destructive,
and the split is not something a reader would guess from the page titles.

Where the platform entity does appear in those pages it reads Edge Device (BR05, FR10), and the
tree's own Device node keeps its name.

Phase 7 quotes the Editor's labels from the editor PR branches, and that is a live dependency

Everywhere else, interface strings are quoted from origin/development, because that is what a
reader sees today. The Editor pages are the one documented exception: the labels they quote do not
exist on development yet, and by BR14 the six repositories ship together, so the documentation
is written against the interface that ships with it.

If openplc-editor#1096 or
openplc-web#745 changes those strings
before merge, Phase 7 has to be revisited.
A test pins the screen title in both repositories,
orchestrators-list.test.tsx:114, it('titles the screen Edge Devices'), which lowers the risk
without removing it.

The old paths are gone, with no redirects

By decision BR10. platform/orchestrators/ and troubleshooting/orchestrator-not-connecting.md
no longer exist, and nothing redirects to their replacements. A held bookmark gets the standard
not-found response rather than outdated guidance, which the risk assessment records as the safer of
the two outcomes.

The image work is a map, not a recapture

FR21 is delivered as docs/exploration/RENAME-IMAGE-MAP.md. FR22 is deferred until the new
interface exists, by decision and by CON04. Recapture is tiered on mechanical triggers rather than
an inherited verdict:

Tier Trigger Count
A Its own alt text or filename changed here, so the words no longer match the picture 47
B A full-window Editor capture: the tree in it reads Device > Orchestrators 53
C A full-window capture outside the Editor docs. Needs a look, not a decision 48
D A crop with no window chrome. Likely fine 43

A + B = 100 certain.

The finding worth carrying forward: the driver is background chrome, not subject matter. An
Editor screenshot needs recapture because the project tree in its left panel reads
Device > Orchestrators, regardless of what the screenshot is about.
communication/ethercat/images/bus-tab.png is a screenshot of an EtherCAT bus whose tree plainly
shows the old vocabulary. Nobody would predict that from the page text, which is exactly why the map
is a deliverable and not a formality. It holds for full windows and fails for crops:
variables-table.png is a tight crop with no tree and needs nothing.

26 images that no page displays were deleted, in their own commit so they review alone. Verified by
set equality rather than by a link count: the set of images a published page actually displays is
identical before and after, 187 both times.

Two Editor UI generations coexist in the screenshots

bus-tab.png shows the tree parent as singular Device; device-selected-connect.png shows it as
plural Devices. The documentation is already visually inconsistent, independently of this
demand, so the FR22 recapture pass is also a consistency pass. Filed separately.

Two content defects found and deliberately not fixed

Both are missing content rather than wrong vocabulary, so neither belongs in a rename. Both were
confirmed against Edge origin/development rather than assumed:

  1. platform/devices/device-detail.md:3 says the page has two tabs. Edge ships three. vPLCs
    and Runtime Images at $orchestratorId.tsx:247 and :260, plus the Device tab.
    "Runtime Images" is documented nowhere in this repository.
  2. getting-started/quick-start.md:71 tells the reader to navigate via a left sidebar. Edge's
    global chrome is a top nav bar whose links are sign-in, sign-up and the dashboard home; it has no
    Devices entry, and the sidebars that do exist are scoped to documentation, the profile and the
    project tree. The route the rest of this repository documents is the dashboard's Devices card
    and its Manage devices button.

How it was verified

Everything below was run against commits exported with git archive, never against a live worktree.
Each tool was proved to read before its verdict was accepted.

  • Census gate, rename-census.py --verify: PASS, rc=0. No occurrence carries a changes code
    and every one of the 1123 survivors carries a stays code from the legend. The gate is the code
    check, not a count
    : the live total falls with every phase for correct reasons, so it is
    provenance-tagged in the record and asserted nowhere. Three negative controls, each on a full copy
    of the tree that was then diffed against the worktree: a planted O-ENTITY sentence, a planted
    child-sense "Add Device", and a removed override each went red for its own reason.
  • Link check: 6, against a baseline of exactly 6 recalibrated on origin/development, and the
    same six items. linkcheck.py always exits 0, so the verdict is its "TOTAL BROKEN" line.
    Planted broken link, image and _config.json leaf moved it to 7, 8 and 9, each named.
  • _config.json and the one SVG by hand, because the census reads *.md only. Zero
    "orchestrat" in either. The SVG's three strings now read "Device Agent".
  • BR03 spelling gate: 0 violations across the 179 reader-facing pages, with the gate masking
    code spans and link targets, or it reports legitimate lowercase ../vplcs/ paths as violations.
    The base tree reports 1, so this branch removed a pre-existing BR03 violation.
  • The security-relevant diff over the five CRA pages holds. Fenced blocks, inline code spans and
    digit-bearing tokens are byte-identical, except for two deliberate instruction changes, and both
    are repairs rather than renames
    : orchestrator-agent became orchestrator_agent in four
    docker commands, confirmed as CONTAINER_NAME in both installers, so the hyphenated form never
    worked; and vplc-stuck-stopped.md:27 gained the listing form docker ps -a | grep openplc-runtime, confirmed as the image name at create_runtime_container.py:207.

Figures were re-measured rather than inherited, and two did not reproduce: the predicted BR03
unmasked count of 13 is 145, and the image map's "191 referenced" turned out to answer "named on
a page" where "displayed by a page" is 187. Both are recorded where they were found.

Repository gates

This repository has no CI, no package.json and no build. Its gates are the three scripts under
docs/exploration/, all committed and all run above.

Before merge, and not covered by this PR

  • The risk assessment needs its pass 2 and its signatures. Section 9 is still empty and the
    technical reviewer and PM signatures are Pending. The assessment's constraint, that renaming must
    not change what a security-relevant page instructs, is discharged and evidenced above. One
    correction it needs: it names "the Node network isolation model" as security-relevant guidance
    carried here, and user-docs never mentions Autonomy Node at all.
  • Requirements Gathering section 19 is deliberately held open until all six repositories land,
    so it is filled once rather than six times.
  • BR14: the six repositories ship together.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4

Thiago-Pio-Autonomy and others added 19 commits September 8, 2026 22:56
The rename can only be verified against a complete inventory, so the
inventory comes before any page is touched. FR17 and FR20 ask for a
decision on every occurrence of "orchestrator" and "device", including
the ones that stay, and this is the evidence for AC05.

Writing a reason 1237 times would produce something nobody reads. So the
census carries one row per occurrence with a decision code, and the reason
is written once per code in the legend. Fourteen codes cover everything;
520 occurrences change and 717 stay.

Two findings worth naming. There is a seventh sense of "device" that the
demand's framework does not have: in the Editor's build-and-run pages the
word means the PLC or runtime the editor is connected to, and that target
can be physical hardware, so renaming those 101 occurrences to vPLC would
make the pages wrong for anyone running a real PLC. They stay. And two
senses the framework does carry, the software-engineering sense of
orchestrator and the VPP licensed device, do not occur in this repository
at all.

The classification is rule-based and then audited, which is what earned
its keep: the audit caught a rule that turned 21 occurrences of the entity
into the agent, and a rule that would have renamed 14 remote-device and
device-config paths that must not move. 84 rows are pinned by hand.

No documentation changes here. The census excludes its own artefacts, and
the pre-existing broken-link baseline of 2 image refs and 4 doc links is
recorded so the rewrite cannot be blamed for it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
Orchestrator becomes Device and the child entity becomes vPLC, so the section
that documents the parent has to live at platform/devices/ before its prose can
be rewritten. Splitting the move from the rewrite is deliberate: git records
these as renames, so the phase that changes the words reviews as words.

Nothing but paths changed here. Masking every ](...) target makes all 21 edited
markdown files byte-identical to their pre-move versions, so no prose, heading,
alt text or fenced block moved with them.

Four image renames had to be sequenced, because the child held a name the parent
was taking: the vPLC wizard captures gave up new-device-step* and the vPLC plan
limit gave up device-plan-limit.png before the parent's captures claimed those
names. Verified by blob hash rather than by trusting the order, and 276 images
went in and 276 came out.

platform-architecture.svg is drawn by hand rather than captured, so its
"Orchestrator Agent" layer is corrected here instead of waiting for the
screenshot recapture. "Physical I/O and Devices" and "Runs on edge device" stay:
they are the plain hardware sense and the host sense, neither of which is
renamed.

_config.json still points at the old paths. That is the next phase, so the
navigation is knowingly broken for one commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
Phase 2 moved the files and left _config.json naming the old paths, so the
navigation has been broken for one commit by design. This closes it: the six
leaves that pointed into platform/orchestrators/ and troubleshooting/
orchestrator-not-connecting now resolve, and the titles a reader sees carry the
new vocabulary.

Eleven of the twelve occurrences of the two words in the file changed. The one
that stays is the EtherCAT "Device Info" tab, which names the slave's own tab
and not the platform entity. "vPLC devices" becomes "vPLCs" while its path
stays vplcs, because the "devices" in that title was the child sense and the
path was already correct.

Also adds the census code the move made necessary. D-PATH assumed that any
"device" inside a link target meant the child entity, which was true before the
rename and is false now that platform/devices/ is the right destination: it had
gone from 10 occurrences to 59, all of them correct paths, and would have failed
the verification gate forever. D-PATH-NEW, rule R11c, is the stays code for a
path that already names the new entity. Measured: D-PATH 59 -> 2, D-PATH-NEW
0 -> 57, total unchanged at 1229, no other code moved. The 2 survivors are the
two getting-started captures whose rename belongs to the phase that rewrites the
page quoting them.

Verified: valid JSON, all 167 navigation leaves resolve, and the link check is
back to exactly the 6-item pre-existing baseline with zero broken _config.json
leaves, down from 6. The baseline was reproduced against origin/development
before the checker was trusted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
… as staying

The census is what eight later phases consume, and its two error directions are
not symmetrical. A row coded "changes" that should stay produces a wrong edit
that --verify catches. A row coded "stays" that should change produces a wrong
edit the gate can never catch, because --verify only fails on a surviving
"changes" row. A page-by-page review found 17 rows in that invisible direction.

52 rows move and 1 is added, total 1237 -> 1238. Every one is justified in
RENAME-DECISION-RECORD.md, section "Review pass: the 52 rows that moved and why".
No page content is touched.

The 17 stays-to-changes flips are all the child entity, and two defect classes
produced them: the blanket path rule that reads anything under openplc-editor/
as the Editor's own Device node, and loose alternations in the sense patterns.
The remote-equipment rule matched "pdo" inside the ordinary word "dropdown" and
"esi" inside "beside", which filed the platform's own vPLC creation wizard as
remote equipment; the host rule's "on the device" captured "on the device row"
and "on the device card", which are vPLCs.

Five rule fixes, all measured before and after:
- the remote-equipment abbreviations are anchored on word boundaries, and
  "scanned device" and "configured device" were added so the EtherCAT panels do
  not fall through to the blanket rule;
- the link-target rule now runs before the prose "Device Orchestrators" rule, so
  a path occurrence gets a path code, and R11d handles the half of an image
  filename built on that label;
- R06 routes any inflection of "orchestrate" other than the noun to REVIEW
  instead of guessing;
- the abandoned EDITOR_SCREEN pattern is deleted rather than wired up: its
  "expand **device**" alternative is the one reading that must not become Edge
  Device;
- the fenced-code fallback no longer converts a "changes" row into a literal.
  Only the REVIEW half of that hole had been closed. Proved in both directions.

A new "changes" code, O-REWRITE, marks the 7 sentences that define the Device in
terms of the Device Agent, or the Agent in terms of its machine. Word-substituting
those produces "a Device that is an agent" on the first page a new reader opens,
so the record names the intended reading for each row instead.

O-SE is no longer 0. Its emptiness was an artefact of the word list: the pattern
could not see "container orchestration" in quick-start.md, which is the ordinary
software-engineering sense in published copy. The pattern now includes it, which
is where the extra row comes from.

Three record numbers that did not reproduce are corrected: the agent-window bug
flips 22 rows not 21, the path rule without its exclusion flips 17 occurrences
across 12 distinct link targets not "14 paths", and of R09's 7 rows six sat under
stays codes while the seventh sat under D-PATH.

Verified over 182 resolved files in the base tree: four independent completeness
counts agree at 1238, the generator still reproduces the committed CSV byte for
byte except the 8 documented D-PATH/D-PATH-NEW path rows, and --verify still
fails with 461 outstanding against the post-Phase-3 tree rather than passing
vacuously.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
The agent-window bug, "pdo" matching inside "dropdown" and "on the device"
matching inside "on the device card" are one defect found three times, not
three unrelated bugs: an alternation matching a phrase fragment against a
140-character window will eventually be satisfied by text that has nothing to
do with the sense being tested, and the row lands on a plausible code with
nothing to report it. It bites hardest in the invisible direction, because
these rules mostly assign "stays" codes, so an absorbed "changes" row drops
out of the gate.

Recorded with the three instances, their row counts and the defence that
worked in all three: judge positionally on the text touching the match, or
anchor the alternative on word boundaries. Written down so the next person
adding a sense pattern asks whether the phrase governs this occurrence rather
than whether it appears nearby.

Record only. No classification changes: the census, the overrides and the
generator are untouched by this commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
…e new vocabulary

Phase 4. The six pages the risk assessment calls security-relevant:
platform/devices/{overview, devices-list, device-detail, managing-devices,
installing-the-agent} and troubleshooting/device-not-connecting.

The CRA's constraint is that renaming must not change what these pages
instruct, so it is proved rather than asserted. Every fenced code block and
every inline code span is byte-identical before and after, across all six
files. Every token containing a digit is identical, so no port, version,
timeout, count or path moved. All ten O-LITERAL strings survive with unchanged
occurrence counts, the agent's runtime log strings included. The diff is
vocabulary only. device-not-connecting stays reachable: still in the
navigation, still the target of eight inbound links, and the link check is at
exactly the six-item pre-existing baseline, checked with a control that
injects a bad link and watches the count move.

platform/devices/overview.md opens with a rewritten definition rather than a
word substitution. "An orchestrator is the cloud-side representation of a
small piece of software that you run on your edge hardware" cannot become
"A Device is ...": a Device is the machine, and the Device Agent is the
daemon on it. Substituting the word would have published a definition the
demand's own glossary contradicts.

Orchestrator ID becomes Device ID, which was already settled and is confirmed
in Edge's frontend today. The rest of the quoted interface strings are left
byte-identical pending the coordinator's release, and all thirty are listed
in the plan so none has to be rediscovered.

_config.json carries one line Phase 3 could not see: "Installing the agent"
names the daemon without using either census word, so a census-driven sweep
stepped over it. It is applied here because this page's heading changed in
this commit and a navigation label disagreeing with its own heading would be
a defect this phase introduced. 167 navigation leaves still resolve.

Recorded in the plan, not acted on here: the deferral's premise is void
because Edge already ships the new strings; the classifier needs the prose
analogue of D-PATH-NEW, which is the record owner's call; five docker commands
on these pages name a container that does not exist, which predates this
demand; and vplc-stuck-stopped.md:27 cannot be fixed by the approved swap
because the container name is the vPLC's cuid, not any name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
Releases the thirty quotes Phase 4 held back. The hold existed to avoid
guessing at strings EDGE-637 had not written; the strings turned out to be
shipped in origin/development already, so the documentation was behind the
interface rather than ahead of it. Every one is re-sourced against
origin/development rather than against the working branch, because that is
what a reader sees.

+ New Orchestrator becomes + New Device, Create Orchestrator becomes Create
Device, the wizard is New Device, Manage orchestrators becomes Manage devices
on the Devices card, What is an Orchestrator? becomes What is a Device?, the
detail page's tabs become vPLCs and Device, and its breadcrumb becomes
Devices -> {Device name}.

One of these corrects the table in the Phase 4 report: the vPLC creation tile
is New vPLC, not New Device. The parent's tile and the child's tile were
conflated there. Edge ships New vPLC at $orchestratorId.tsx:339, the wizard as
New vPLC at devices/create.tsx:235,469, the modal as Add New vPLC and the
button as Add vPLC, so device-detail.md now says + New vPLC and New vPLC
wizard. The expandable row on a Device card is N vPLCs, rendered from
{deviceCount} vPLC{s} at index.tsx:237, not N devices.

The CRA constraint is re-proved after these edits, not assumed: fenced blocks,
inline code spans and every digit-bearing token are still identical to the
pre-Phase-4 versions in all six files. The ten O-LITERAL strings are the only
occurrences of the old word left on these pages. Link check at the six-item
baseline.

Not changed, and reported instead: device-detail.md still says the page has two
tabs. Edge ships three, the third being Runtime Images, which this page has
never documented. That is missing content rather than wrong vocabulary, so it
does not belong in a rename commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
…ctually has

Correctness fix, not part of the terminology rename. Found by EDGE-642 rather
than caused by it: these commands were already broken before this demand
started.

The installer names the container with an underscore. orchestrator-agent's
install/install.sh:24 sets CONTAINER_NAME="orchestrator_agent" and line 1233
runs docker with --name "$CONTAINER_NAME"; install-staging.sh:38 does the same.
No hyphenated container is ever created anywhere in that repository. The
hyphenated form is the IMAGE, ghcr.io/autonomy-logic/orchestrator-agent, and it
stays hyphenated in the two places that genuinely name the image and the
GitHub repository.

So these four commands fail today, on the page an operator opens when their
device will not connect:

    docker start orchestrator-agent
    docker restart orchestrator-agent
    docker logs --tail 100 orchestrator-agent
    docker logs orchestrator-agent

and these two, on the page about managing a Device:

    docker stop orchestrator-agent
    docker start orchestrator-agent

docker ps | grep orchestrator-agent did work, by accidentally matching the
image column rather than the name, and it is changed too: a page that tells you
to grep one spelling and then start another teaches the wrong name.

Kept deliberately: the image reference at device-not-connecting.md:22, the
repository URL at platform/devices/overview.md:36, and the agent's own log
strings "Unauthorized" and "Unknown orchestrator", none of which is a container
name.

This is a separate commit so it reads as what it is. The rename commits around
it changed no instruction; this one changes six, toward working.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
…total

Three record and tooling corrections that the phases depend on.

D-PROSE-NEW, a stays code, is the prose analogue of D-PATH-NEW and exists for
the same reason one layer up. After a page is rewritten, a sentence containing
"Device" is usually right, and R18 cannot tell, because "Device" with a "vPLC"
nearby is exactly what the child sense used to look like. Left alone it codes
35 finished sentences as D-VPLC and the Phase 10 gate fails forever on prose
that is already done. Capitalisation is the discriminator, which is why the
capitalised-in-prose convention is recorded as a decision and not a preference:
the gate depends on it. Rule R20 is scoped to an enumerated set of finished
files rather than applied tree-wide, because before a page is rewritten its
capitalised "Device" is usually the child, and a tree-wide rule would mark
outstanding work as done in the one direction the gate cannot catch.

The correctness fix in the previous commit broke is_o_literal, which only knew
orchestrator-agent with a hyphen. Four docker commands inside fenced blocks
fell through to O-AGENT and were REPORTED rather than silently converted to
literals, which is the fenced-block hole closed earlier doing exactly its job.
is_o_literal now knows both separators: the hyphen is the image and the
repository, the underscore is the container.

Every census total is now tagged with the commit and the script it belongs to.
1237 and 1238 looked like a contradiction and are not: 1237 is the base at
c86992f, where the committed CSV and a live run agree byte-for-byte, and 1238
is that same base corrected, the extra row being the O-SE occurrence the old
pattern could not match. 1229 and 1230 are the same live tree after Phase 3
under the old and the corrected classifier. The record now says plainly that
Phase 10 must gate on the code check and not on a count, because the live total
falls with every phase for correct reasons.

Also recorded: the casing divergence from autonomy-node is deliberate. Node's
interface carries one sense of the word and keeps prose lowercase; these pages
carry five senses in the same paragraphs and four of them stay lowercase, so
capitalising the entity is the only thing that keeps them apart. We chose
disambiguation over cross-repository symmetry, written down so nobody
harmonises one to the other without re-opening it.

linkcheck.py is committed next to the census script, as Phase 10 needs it. Its
header carries the two ways it has already produced a wrong verdict: it always
exits 0, so it must be read and not trusted by exit code, and it checks nothing
at all without the docs directory as argv[1].

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
…eference

Phase 5, everything except the getting-started pages and their captures. 25
pages: the vPLCs section, organizations, projects, plans-and-billing, account
settings, the AI assistant, the forum, the FAQ, index and the two remaining
troubleshooting pages.

vplc-stuck-stopped.md:27 does NOT get the swap that was approved for it. The
approved <device-name> -> <vplc-name> would have been a different wrong answer:
Edge names a vPLC container by the row's cuid, not by any name the customer
chose. create-device.use-case.ts:330 sends container_name: device.id, the agent
passes it to Docker verbatim in create_runtime_container.py:358-361, and
device.id is @default(cuid()) in prisma/models/device.prisma:31, so the vPLC's
visible name appears in no column of docker ps -a. The page now gives both
halves a reader needs: grep the image, ghcr.io/autonomy-logic/openplc-runtime,
to see whether anything is running at all, and then find one vPLC by its id,
which is the last segment of that vPLC's page URL. The image name is verified
in the agent's own source rather than taken on trust.

Interface strings are quoted as Edge ships them, sourced against
origin/development: + New vPLC, the New vPLC wizard, Create vPLC, vPLC Name,
the vPLCs tab, the Devices card with its Manage devices button, and the
breadcrumb Devices -> {Device name} -> {vPLC name}.

DEFERRED, and this one is a real deferral rather than a stale premise: three
sentences quote the OpenPLC Editor's own labels, "Devices -> Orchestrators" and
the Orchestrators panel, at connecting-from-editor.md:3 and :8 and
projects/overview.md:46. openplc-web still ships "Orchestrators" in the project
tree, at explorer/project.tsx:218, so renaming them here would put the docs
ahead of that screen, which is the Phase 4 mistake in reverse. They belong to
the Editor pass.

Two classifier corrections came out of running the gate rather than trusting it.
R20 is now off by default and enabled only by --verify, because D_PROSE_DONE
means "rewritten in the tree you are classifying" and against the base commit
those same files still carry the old child-sense "Device": "+ New Device",
"Add Device wizard", "Device Name". Left on, it marked 20 genuine changes rows
on the base tree as stays, which is the invisible direction, and the base-tree
diff jumping from 8 rows to 28 is what caught it. Separately, an override pinned
to a base-commit position that has drifted onto a different word no longer
asserts its old decision: an O-ENTITY, O-AGENT, O-REWRITE or O-SE code describes
an occurrence of "orchestrator" and nothing else, so if that word is gone the
rules are a better answer than a stale pin. O-EDGEDEV and O-PATH are exempt,
because both halves of the Editor's "Device Orchestrators" label move together
and legitimately put an O- code on a "device" word; guarding those broke the
reproducibility check by 21 rows, which is how the over-reach was found.

Verified: the base tree still reproduces the committed CSV byte for byte except
the 8 documented path rows; link check at the six-item baseline; zero BR03
spelling violations across 179 pages with paths and code spans masked, since an
unmasked check counts every ../vplcs/ path as a violation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
…ick-start

what-is-autonomy-edge.md, account-and-signup.md and dashboard-tour.md.
quick-start.md is deliberately not here: it is the densest page in the
repository and it carries every sense of the word at once, so it gets its own
commit with the captures it quotes.

Two sentences needed rewriting rather than substituting, both the same class the
O-REWRITE code exists for. "One orchestrator on a beefy edge device" cannot
become "One Device on a beefy edge device", since the Device is that machine; it
reads "One beefy Device" now. And "the orchestrator starts an OpenPLC v4 runtime
in a Docker container" is the daemon's work, not the machine's, so it names the
Device Agent. That second row is coded O-ENTITY in the census, which is a
further instance of the R03 blind spot the O-REWRITE section already describes:
the daemon sense expressed without the literal word "agent" falls through to the
entity. Recorded rather than silently absorbed.

The dashboard card and its button are quoted as Edge ships them, Devices and
Manage devices, sourced at components/dashboard/orchestrators-card.tsx:30,79.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
The densest page in the repository, 90 of the original occurrences, carrying
every sense of the word at once: the terminology block, the Device wizard, the
vPLC wizard, the host machine, the Modbus remote-device walkthrough and plain
hardware English. It gets its own commit, with the six captures it is the only
referrer of.

The terminology block is rewritten, not substituted. "Orchestrator: An agent
that runs on an edge device ... and manages your vPLC instances" would have
become "Device: An agent that runs on an edge device", which the demand's own
glossary contradicts. It now names the machine and the daemon separately. The
sentence keeps the words "container orchestration", which is the O-SE
occurrence: the ordinary software-engineering sense, used correctly, and the
reason the census pattern had to learn to see "orchestration" at all.

Six captures renamed, content verified rather than assumed: each new name's blob
hash equals the old name's, one for one, and 276 images in the tree before and
after. No sequencing was needed and none is claimed: all six targets were free
names in a directory none of them shared with the child, unlike the one genuine
same-name collision Phase 2 had to order. The first verification loop reported
OK on empty hashes because zsh does not word-split an unquoted variable, so it
was rewritten before being believed.

D_PATH_PENDING is empty now, which was the condition for this commit. All ten of
the base commit's D-PATH rows are D-PATH-NEW under the current rule and D-PATH
is 0 in the live tree: no outstanding path work anywhere. The base-tree
reproducibility delta therefore grows from 8 rows to 10, which is the rule
working rather than a regression, and the record says so with both figures.

Interface strings are Edge's own: Add Device and Create Device for the Device
wizard, Add vPLC and the Add New vPLC dialog and the vPLCs tab for the child.

DEFERRED, three occurrences, and genuinely so: quick-start.md:262 and :350 quote
the OpenPLC Editor's "Orchestrators" panel, which openplc-web still ships under
that name. Line 263 was NOT deferred, because it is prose rather than a label,
and leaving it would have told the reader to expand "QuickStartOrchestrator"
four screens after naming their Device "QuickStartDevice".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
Decision 7: this is not a substitution and there is no phrase to roll out.
"edge device" stays wherever it reads as natural English for the physical
machine, because that is what it is, and Device is used only where the sentence
names the platform entity. The pass is confirming that each occurrence still
reads correctly under the new vocabulary.

All 44 outside openplc-editor were read. 42 are correct as written: "your Linux
edge device", "on the device", "the edge device's specs", "Check device-side
logs", "Live CPU usage on the device". Two named the entity rather than the
machine and are capitalised: what-is-autonomy-edge.md:18, which enumerates
"one project, one vPLC, one Device", and :20, whose "Fleets of identical
Devices" are the same Devices the next clause pushes a project to.

Left for Phase 6: the two D-HOST rows in reference/glossary.md, whose entries
FR19 rewrites wholesale.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
Phase 6, FR19. Fifteen rows, and the shape of the entries matters more than the
count.

One entry survives for the child. "Device (vPLC device)" and "vPLC" defined the
same object, so the duplicate goes and its content folds into vPLC, which keeps
the name, the runtime version and the NICs.

The Orchestrator entry becomes Device and is REDEFINED, not reworded. It said
"the cloud-side entity representing an edge device", which under the new
vocabulary is circular, and the obvious substitution would have defined a Device
as an agent, which is the O-REWRITE class this demand keeps running into. It now
says what a Device is: the machine, explicitly not the software on it, with the
Device Agent running on it and hosting its vPLCs.

The agent entry becomes Device Agent, keeping its curl command byte-identical.

Two entries are added so the Editor's reading and the platform's stay
distinguishable, which is what BR05 and BR06 are for: "Edge Device" for the
platform entity as the Editor documentation names it, and "Device (in the
Editor)" for the project-tree node that keeps its name. A reader who meets
"Device" in two places now has both meanings side by side rather than having to
infer which is which.

Entries re-sorted alphabetically, since the renamed ones move out of A and O
into D and E. The re-sort also puts "Pro plan" before "Project", correcting a
pre-existing mis-ordering as a side effect rather than as a separate change.

Plan tiers now read in the new units: 1 Device and 2 vPLCs on Community, 20 and
100 on Pro, unlimited on Enterprise.

Verified: no entry content lost, checked by diffing the set of body lines rather
than eyeballing the diff, 32 of 41 untouched and all 9 removed lines accounted
for as rewrites or folds; zero occurrences of the old word left in the file;
still alphabetical with the footer last; link check at the six-item baseline,
which also confirms the new Device-configuration cross-link resolves; and the
base tree still reproduces the committed census except the documented 10 path
rows.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
…e 7 quotes from

Record only, no classification or page changes.

Two classifier bugs are written into the record rather than left in a report,
because both were caught by a number moving in an unexpected direction and both
sat in the direction --verify can never see. R20 firing on the base tree marked
20 genuine changes rows as stays, and nothing in --verify could have reported it,
since a stays row is what --verify wants to see; the base-tree reproducibility
diff jumping from 8 rows to 28 was the only signal. The stale-override guard
being too strong broke reproducibility by 21 rows, because O-EDGEDEV and O-PATH
legitimately sit on a "device" word.

One line on the fenced-block hole for the same reason: when the container name
was corrected, is_o_literal still only knew the hyphen, so four fenced docker
commands fell through and were reported. The old fallback would have made them
literals in silence and nobody would have learned the classifier had stopped
recognising them.

Both sourcing rules are now stated together so the difference is visible. The
default is origin/development, because that is the screen a reader is looking
at. Phase 7 is the one documented exception: the Editor's labels come from
feat/edge-639/rename-device-vplc in openplc-editor and openplc-web, because
BR14 ships all six repositories together, so those labels land in the same
release as these pages and the documentation is correct at the joint ship rather
than briefly wrong.

Verified on both branches rather than taken on trust, and they carry a
byte-identical shared surface: project.tsx:433 renders the tree leaf and tab as
Edge Devices, orchestrators-list.tsx:333 renders the panel heading the same, the
copy around it agrees, no Orchestrators label survives in either tree, and a
test pins the screen title. The tree's Device node and its Configuration leaf
keep their names, which is BR06. Line numbers differ from development because
the branch restructured the shared surface, which is expected and not a
discrepancy.

The single dependency is recorded in both the decision record and the plan: if
the editor pull requests change those strings before merge, Phase 7 must be
revisited. They are under review, so it is live.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
Phase 7, the last of the rewrites. The 82 changes rows in the Editor
documentation plus the 7 Editor-label deferrals that Phase 5 could not take.

The Editor's own labels are quoted from the editor pull request branches,
feat/edge-639/rename-device-vplc in openplc-editor and openplc-web, NOT from
development. That is the one documented exception to sourcing quotes from what
ships today, and BR14 is the reason: all six repositories release together, so
these labels land in the same window as these pages and the documentation is
correct at the joint ship rather than briefly wrong. Verified on both branches,
which carry a byte-identical shared surface: the tree leaf and tab name at
project.tsx:433,436 and the panel heading at orchestrators-list.tsx:333 all read
Edge Devices, and no Orchestrators label survives in either tree.

THE DEPENDENCY: if the editor pull requests change those strings before merge,
this phase must be revisited. They are under review now. A test pins the screen
title at orchestrators-list.test.tsx:114, so a change would break a suite that
is currently green, which lowers the risk without removing it.

The project tree's Device node keeps its name, which is BR06, confirmed at
project-tree/index.tsx:114 where the branch label is the singular "Device". So
the docs read "expand Device and click Edge Devices". quick-start.md:261 said
"expand Devices", plural, which was a pre-existing error the plan flagged and
this pass corrects.

Nothing was replaced globally, and that was the point of doing this phase last:
the 109 Editor pages carry 533 census rows of which only 84 change. The seventh
sense is intact, 93 D-TARGET rows still in building-deploying alone, because the
target can be physical hardware and calling it a vPLC would make those pages
wrong for anyone running a real PLC. D-REMOTE, D-EDITORNODE and D-PLAIN are
likewise untouched.

Four images renamed, content verified hash for hash: orchestrators-screen,
orchestrators-expanded and orchestrators-vplc-selected take edge-devices-*
names, and device-orchestrators-expanded becomes edge-devices-expanded-full,
which is the collision the plan resolved in advance. device-orchestrators-connect
and device-orchestrators-list are referenced by nothing and are left for Phase 9.
My first reference sweep called orchestrators-expanded.png doubly referenced; it
is not. That was a substring match against the longer device-orchestrators-
expanded.png, the same unanchored-match defect the record names, and a
boundary-correct sweep confirms the plan's decision stands.

R20 had to be narrowed, found by D-TARGET dropping from 98 to 93. Inside the
Editor documentation a bare capitalised "Device" is the Editor's own node, not
the platform entity, so R20 must not fire there; and "Edge Device" needs
catching positionally ahead of R15, because "edge device" is HOST's very first
alternative and every correctly renamed occurrence was being filed as the
machine it is not. R20a does that. Letting R20 run there had mis-filed 46 stays
rows across D-EDITORNODE, D-REMOTE and D-TARGET: no decision moved, but the
record is evidence.

Zero occurrences in the repository now carry a CHANGES code. 22 carry REVIEW,
every one an occurrence the base-commit overrides no longer reach: 44 of the 115
still land on a live row and 71 have drifted off entirely. Re-deriving them
against the final tree is Phase 10's job by decision, so they are reported
rather than silenced with a rule, and --verify now says HALF PASS instead of
claiming every survivor carries a stays code, which it no longer does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
Phase 8, the FR21 deliverable. docs/exploration/RENAME-IMAGE-MAP.md. The
deliverable is the map; regenerating the images is FR22 and out of scope.

Every count is re-measured against the tree as it stands, and three inherited
figures did not reproduce.

The plan draft said 43 published-area orphans and 89 orphans in total.
Measured: 39 and 85. The decision record's own figure of 39 was right and the
plan draft's 43 was not. The 89 came from counting all 46 files under
exploration/screenshots as orphans; they are referenced by the internal
planning documents, so they are unpublished rather than unreferenced, and only
2 of them are referenced by nothing at all. That conflated two different
questions.

The headline finding is confirmed and then bounded. Background chrome really is
the driver: bus-tab.png is a screenshot about an EtherCAT bus whose project tree
plainly reads Device > Orchestrators, which nobody would predict from the page
text. But it only holds for full-window captures. variables-table.png is a tight
crop of the variables table with no tree and no tab strip and needs nothing, so
the inherited claim that roughly 45 Editor screenshots about EtherCAT, Modbus,
variables and data types carry the old vocabulary is true of the full windows and
false of the crops. 68 live Editor images are full-window captures.

Recapture is classified by three mechanical triggers rather than by an inherited
verdict: tier A, the image's own alt text or filename changed here, so the words
no longer match the picture; tier B, a full-window Editor capture; tier C, a
full-window capture outside the Editor docs, which needs a look rather than a
decision. A+B is 100 certain, C is 48 to inspect. The inherited 82 sits inside
that band, and the difference is that a visual sweep judged each non-Editor full
window individually where this method declines to guess.

Two instruments, both reproducible and both sample-validated. The reference sweep
matches basenames on word boundaries, because plain substring matching made
orchestrators-expanded.png look like a two-page image when it matched inside
device-orchestrators-expanded.png. The full-window test reads PNG IHDR
dimensions, with the threshold validated against four images; a first attempt at
1600 wide excluded the entire 1550x1035 family and had to be corrected after
reading one of them.

Folded in as instructed: platform-architecture.svg is hand-authored SVG text
rather than a capture, was edited in Phase 2, already reads Device Agent, and is
the one image that needed no recapture at all.

Recorded while sampling: two Editor UI generations coexist in the captures.
bus-tab.png shows the tree parent as singular Device, device-selected-connect.png
as plural Devices. The documentation is already visually inconsistent
independently of this demand, so a recapture pass is also a consistency pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
Phase 9. An image no page references is dead weight, and recapturing one would
be work for nobody, so these are deleted rather than carried into FR22.

Each of the 26 was re-verified as unreferenced immediately before deletion
rather than on the strength of the earlier sweep, and the check fired. It fired
on the Phase 8 map, which names every candidate in backticks as a record of what
is being deleted. That is not a reference, so the sweep now tests for an actual
markdown embed or link, ](...basename), excludes this demand's own two
artefacts, and was run with a control in both directions: a planted embed is
detected, a bare filename mention is not counted as one. Without that
distinction the pre-check would have blocked the deletion it was written to
authorise.

19 Editor orphans that would otherwise have needed recapture:

  openplc-editor/communication/modbus/images/add-element-menu.png
  openplc-editor/communication/modbus/images/add-remote-device-dialog.png
  openplc-editor/communication/modbus/images/add-server-dialog.png
  openplc-editor/communication/modbus/images/io-group-expanded.png
  openplc-editor/communication/modbus/images/io-group-with-iec-location.png
  openplc-editor/communication/modbus/images/modbus-server-full.png
  openplc-editor/communication/modbus/images/new-io-group-dialog.png
  openplc-editor/communication/modbus/images/remote-device-protocol-dropdown.png
  openplc-editor/communication/modbus/images/server-protocol-dropdown.png
  openplc-editor/communication/s7comm/images/s7-server-overview.png
  openplc-editor/images/build-process-started.png
  openplc-editor/images/device-orchestrators-connect.png
  openplc-editor/images/device-orchestrators-list.png
  openplc-editor/images/device-selected-connect.png
  openplc-editor/images/program-running.png
  openplc-editor/images/simulator-chart-plotting.png
  openplc-editor/images/workspace-overview-raw.png
  openplc-editor/workspace-overview/images/project-explorer-clean.png
  openplc-editor/workspace-overview/images/workspace-layout-full.png

7 images in docs/platform-features/, a directory holding no markdown at all,
the leftover of a platform-features/orchestrator-management/ section that only
the internal planning document still describes:

  platform-features/project-management/images/create-project-step1.png
  platform-features/project-management/images/create-project-step2.png
  platform-features/project-management/images/create-project-step3.png
  platform-features/project-management/images/dashboard-overview.png
  platform-features/project-management/images/pinned-section.png
  platform-features/project-management/images/projects-page.png
  platform-features/project-management/images/trash-section.png

The directory is now gone entirely, not left empty.

device-orchestrators-connect.png and device-orchestrators-list.png, which
Phase 7 deliberately left behind, are INSIDE that 19 rather than additional to
it, so the total is 26 and not 28.

13 further orphans are deliberately NOT deleted, because they show no old
vocabulary and are not full-window Editor captures, so removing them is not this
demand's call: five getting-started sign-in and profile captures, seven Editor
menu and detail crops, and platform/images/changelog.png.

Verified after deleting: 276 images down to 250, exactly 26; link check still at
the six-item pre-existing baseline, so nothing that was embedded was removed;
167 navigation leaves still resolve; census total unchanged, images not being
markdown.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
…d not reproduce

Phase 10. The gate now reads PASS rather than HALF PASS: no occurrence
carries a changes code, and all 1123 survivors carry a stays code from the
legend. The live total is not the gate and is not asserted anywhere.

The 22 residual REVIEW rows are closed by a SECOND override layer,
rename-census-overrides-final.csv, pinned to the final tree and loaded only
by --verify. The base layer is left untouched on purpose: the base-tree
reproducibility check reads it, and re-pinning it to a later tree would
destroy the record it exists to be. Verified by putting the new layer inside
a base-commit checkout and confirming the generated CSV is unchanged at 1238
rows with a 10-row delta, and that no new code leaks into it.

Eleven of the 22 were never new decisions. Six D-HOST rows drifted only
because Phase 2 renamed their file, and they land at the same line and the
same column; four D-PLAIN rows shifted a uniform +8 lines; one O-SE row
shifted 28 columns on the same line. All eleven are re-pinned under their
original hand-rule id so the provenance stays readable. Of the eleven that
are genuinely new, three are the Edge button label "Manage devices",
confirmed at orchestrators-card.tsx:79 on autonomy-edge origin/development
rather than taken from a summary, and eight get a new code.

D-DOCTITLE is that code: this documentation's own sentence-case page title,
and the link text quoting it, where the entity's plural lands after the first
word and is lowercase by the titling convention the base tree already
followed. It is not D-PROSE-NEW because that code is decidable only on the
capital letter, and filing a lowercase "devices" there would falsify its
legend entry.

Also found, and it is the reason this was looked for at all:
override_still_applies() guards only the O- codes, so two D-HOST pins in
what-is-autonomy-edge.md kept asserting the machine sense over prose that now
reads the platform entity. Both are stays codes either way, so no decision
moved and the gate could never have caught it. Found by checking all 39
effective base overrides against the base tree line by line: 32 sit on a
byte-identical line, 7 on a changed line, 5 of those 7 still correct.

Adds br03-spelling-check.py, which masks fenced blocks, code spans and link
targets and skips exploration/. Zero violations across the 179 reader-facing
pages, and the base tree had one that this branch removed. The inherited "13
violations unmasked" does not reproduce: it is 145, and the reasoning behind
it holds all the same, since every one is a path, a filename or a literal.

RENAME-IMAGE-MAP.md keeps its 191 and gains 187 beside it. The two are
different questions, not a miscount: the sweep matches basenames, so 191 is
"named on a published page" and 187 is "displayed by one". Four images differ,
three reachable only through a broken or duplicated path, and two of those sit
in tier A, so FR22 has to fix the path before recapturing them.

The HALF PASS message is rewritten because it still called the override
re-derivation future work and described two layers as "base-commit".

Verification, all of it from commits rather than a live worktree: link check
6 against a 6 baseline recalibrated on origin/development, same six items,
with planted link, image and _config.json failures moving it to 7, 8 and 9.
_config.json and the one SVG checked by hand since the census cannot see
either. The five CRA pages differ only in the two recorded instruction
changes, both re-confirmed in the agent's own source: orchestrator_agent is
CONTAINER_NAME in both installers, and openplc-runtime is the image at
create_runtime_container.py:207. Three census controls, on a full copy of the
tree that was diffed against the worktree afterwards, each went red for its
own reason.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEHN6E4oZKbi6ekw1da6A4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant