Repository-aware editor generation
praetorctl editors generate --path PATH and praetorctl editors verify --path PATH
resolve the same repository capabilities before generating or checking editor
files. A repository without Go sources or a selected Go profile receives no Go
settings, Go inspections or Go problem matcher.
Selecting editors
A repository declares the editors it uses in .standards.yaml:
praetorctl adopt, onboarding and both editors subcommands resolve that list
through editor.SelectEditors (internal/editor/selection.go):
| Declaration | Result |
|---|---|
key absent (or editors: with no value) |
every supported editor, as before the key existed |
| a list of ids or aliases | exactly those editors |
editors: [] |
no editor; nothing is generated or verified |
Every supported editor outside the selection is reported as not applicable:
[NOT_APPLICABLE] Editors not selected: ... from the CLI, and a skip action on
editors in the adoption report. Its files are neither generated nor verified, so a
file the repository deleted is not recreated by the next run. Existing files of an
unselected editor are left in place; delete them yourself.
Both subcommands also take --editors=id[,id...], a comma-separated list of editor
ids or aliases (cmd/standardsctl/editors.go). A non-empty flag overrides the
manifest for that run. Omitting the flag, or passing an empty or all-separator value,
falls back to the manifest. Any id that does not resolve, from the flag or the
manifest, fails the whole run with unknown editor id(s): <ids>; supported:
<canonical ids> and writes nothing: a partially-matched list used to synthesize only
the recognized subset and silently drop the rest. Without the flag, a manifest that
cannot be read fails the same way instead of falling back to every editor.
Tests: internal/editor/selection_test.go,
cmd/standardsctl/editors_selection_test.go,
internal/adopt/client_selection_test.go,
internal/harvester/onboard_selection_test.go.
Selecting agent clients
agent_clients selects the vendor context files praetorctl compile-context compiles
from AGENTS.md and the persona directories it copies .agents/agents/*.md into, with
the same absent, list and empty rules as editors:
| Id | Context file | Persona directory |
|---|---|---|
claude |
CLAUDE.md |
.claude/agents |
cursor |
.cursor/rules/hiss-invariants.mdc |
none |
copilot |
.github/copilot-instructions.md |
.github/agents |
windsurf |
.windsurfrules |
none |
gemini |
.gemini/GEMINI.md |
.gemini/agents |
codex |
.codex/rules.md |
.codex/agents |
The registry is vendorTargets in internal/agentcontext/render.go. Repository-relative
links are rewritten for subdirectory targets by prefixing ../ per directory depth.
The compiler reads the key from the manifest beside AGENTS.md, the one that already
governs the text register block, so compile-context, compile-context
--verify, praetorctl audit, adoption, onboarding and the MCP
standards_compile_context tool agree on which projections exist. Persona copies are
resolved by compiler.SelectPersonaDirs from the manifest at the root the personas are
projected into, which is the same file when AGENTS.md sits at that root. Unselected
context files and persona directories print as [NOT_APPLICABLE] and are neither
written, verified nor removed, so a directory the repository deletes stays deleted and
one it keeps for its own use is left alone. An unknown id fails with
unknown agent client id(s): <ids>; supported: <ids>.
The plugin copy under .agents/plugins/praetor/agents belongs to no client and is kept
whenever .agents/plugins/praetor/plugin.json exists. Tests:
internal/agentcontext/render_selection_test.go,
internal/compiler/transpiler_selection_test.go,
internal/compiler/agents_selection_test.go,
cmd/standardsctl/compile_context_clients_test.go,
internal/adopt/client_selection_test.go.
Persona model tiers and client projections
Every canonical agent persona in .agents/agents/*.md declares a model tier key in its
front matter (model: flash or model: pro). Missing keys, inherit, or any other
values are refused by compile-context, compile-context --verify, and audit with an
error naming the file and the allowed values (flash, pro).
Each refusal of a persona that declares no tier names its remedy
(adopt.PersonaModelTierRemedy):
- an unedited copy of an earlier generated persona (
repo-auditor.md,repo-gatekeeper.md): a plainpraetorctl adoptreplaces it with the current template; - a generated persona the repository edited: a plain
praetorctl adoptadds its template's tier (profor the auditor,flashfor the gatekeeper) as the last front matter line, in the file's own line endings, and keeps every other byte; - a persona the repository wrote itself, or one declaring a value outside the tiers: the
modelline by hand.
TestAdopt_Positive_EditedPersonaGainsModelTier,
TestAdopt_Negative_InvalidOrOwnPersonaTierLeftAlone and
TestAuditAgentDefinitions_Negative_ModelTierNamesTheRemedy cover the three cases.
flash: tier for mechanical runs, fuzzing, dogfooding, and packaging.pro: tier for review and complex reasoning.
Projections carry the tier in each client's own vocabulary or drop it with a stated reason:
| Target directory | Client | Model policy | Reason | Source URL + read date |
|---|---|---|---|---|
.claude/agents |
Claude Code | flash -> haiku, pro -> sonnet |
Claude Code accepts family aliases sonnet, opus, haiku, fable, full model ID, or inherit |
https://code.claude.com/docs/en/sub-agents (read 2026-10-14) |
.agents/plugins/praetor/agents |
Antigravity Plugin | byte copy, tier kept | Native Antigravity schema accepts flash and pro |
https://antigravity.google/docs/subagents/ (read 2026-10-14) |
.github/agents |
GitHub Copilot | model line removed | Copilot value space unverified in docs | https://docs.github.com/en/copilot/reference/custom-agents-configuration (read 2026-10-14) |
.gemini/agents |
Gemini CLI | model line removed | Gemini CLI reads .gemini/agents/*.md with a model key, but it takes a concrete Gemini model id (default inherit) and no tier alias, so the tier is dropped and the persona inherits the session model |
https://github.com/google-gemini/gemini-cli/blob/main/docs/core/subagents.md (read 2026-10-14) |
.codex/agents |
OpenAI Codex | model line removed | Codex reads standalone TOML files (#1076) | https://developers.openai.com/codex/subagents (read 2026-10-14) |
The transform edits only the model line inside the leading front matter block; body bytes
and line endings are preserved unchanged.
Antigravity IDE
antigravity (aliases agy, antigravity-ide) joins the VS Code-compatible
family alongside vscode, cursor and windsurf, and shares their single
.vscode/settings.json. Requesting it adds two keys to that file, confirmed
against the installed IDE rather than assumed from its docs:
antigravity.searchMaxWorkspaceFileCount: 50000— raises Jetski's per-workspace embedding scan bound above its shipped default of 5,000 (confirmed:contributes.configurationin the IDE'sextensions/antigravity/package.json).files.watcherExclude— a core VS Code setting (confirmed: the workbench's own configuration schema) extended with every resolved private directory (editor.Options.PrivateDirs, default.workingdirand.workingdir2), build output (bin,dist) and the isolated gate/dogfood run worktrees under.standards/worktrees, to keep inotify-heavy scratch out of the file watcher.
These two keys are only added when antigravity is part of the requested editor
set; vscode/cursor/windsurf-only runs do not receive them. Run-count
retention for ~/.local/state/praetor/dogfood-local is a separate, still-open
fix tracked on the issue that requested this key.
The shared resolver combines supported project markers and source formats with
explicit caller options. It excludes private state, dependency/build directories,
nested agent worktrees, and the trees Zig writes inside a checkout: zig-pkg
(fetched packages), zig-out and .zig-cache (util.IsToolchainTreeDir). A
native build marker adds c and cpp for meson.build or CMakeLists.txt and
zig for build.zig or build.zig.zon (needs.NativeLanguages), so a pure-Zig
repository gets no C/C++ tooling (internal/editor/native_languages_test.go).
cuda comes only from .cu and .cuh sources. An incomplete scan is an error rather than a claim
that the unexamined part of the repository has no relevant languages. The scan
walks at most 65536 files by default (Options.MaxWorkspaceFiles, zero selects the
default, util.DefaultDiscoveryEntries). praetorctl adopt passes the entry bound its verification walk resolved,
so --verification-max-entries, or verification.max_entries in .standards.yaml, raises
this scan too, up to the same 200000 ceiling.
A bound past the ceiling is refused, and adoption names the flag when the scan
stops at the bound (large repositories;
internal/editor/workspace_bound_test.go,
internal/adopt/large_repo_bounds_test.go). praetorctl editors keeps the default.
Every renderer reads the resolved plan and nothing else (Plan in
internal/editor/capabilities.go); a capability the resolver rejected is omitted,
not asserted anyway:
- Commands. Default commands include
make verify-allonly when the reader finds that literal target; a Makefile it cannot read that far offers no command. The Makefile is read by the reader adoption decidesverify-allownership with (util.MakefileHasTargetininternal/util/makefile_target.go, called byhasLiteralMakeTargetininternal/editor/capabilities.go), so a line that only binds a variable, such asverify-all ?= a:borverify-all: CFLAGS := -g, offers no command, and neither does a rule line inside adefinebody; adoption verification lists the forms. The reader joins backslash continuations first, as Make does, so the first rule-shaped line below is part of the value ofHELPand offers no command, while the continued target list declaresverify-alland offers it:
A computed target name counts once the file fixes its value, so $(NAME): after
GATE := verify and NAME := $(GATE)-all offers the command; the adoption guide
lists the bindings the reader resolves.
A line the reader claims no rule from offers no command either, although adoption
preserves such a file as possibly owning the target: an include, an $(eval ...)
call, a pattern target such as verify-%, a target list holding a reference the
file does not fix, such as $(PREFIX) verify-all: dep with PREFIX bound nowhere,
every rule of a Makefile that names .RECIPEPREFIX
(assigning it changes which lines are recipe lines), and every rule at or after the
first point the reader cannot resolve: line 4097, a logical line longer than 8192
bytes, a chain of more than 256 continuation lines (257 physical lines), a
tab-indented define or conditional whose meaning depends on a conditional branch,
or a binding whose computed name may be .RECIPEPREFIX. The reader evaluates no
condition, so a verify-all rule inside ifdef CI ... endif offers the command
whichever branch Make takes, a known gap the adoption guide lists.
The tests are internal/editor/makefile_task_test.go and
internal/util/makefile_target_test.go. The generator does not add make build
merely because a Makefile exists. VS Code tasks, JetBrains external tools, Neovim
user commands, Zed tasks, the Emacs compile-command, Fleet run configurations and
Sublime build systems
list exactly the resolved commands; an empty plan binds none. Target presence is
structural evidence; generation does not run or certify the command. Callers
using the Go API can provide explicit commands and languages through
editor.Options.
- Language server. The Praetor LSP is written only for a Go workspace where the
host can start the workspace-relative command editor.Options.LSPPath, or,
when that is unset, <BinaryDir>/standards-lsp. Otherwise VS Code settings
carry no standards.lsp.* key and Neovim registers no server. The settings
name the command, never the file it resolves to, so one tracked
.vscode/settings.json verifies on every host. On Linux and macOS the command
is an executable regular file. On Windows the VS Code client spawns it without
a shell through libuv, whose search_path (src/win/process.c) appends .com
and then .exe to a name without an extension: a built
bin/standards-lsp.exe starts as bin/standards-lsp. Node rejects .bat
and .cmd files in that spawn, so they never count as a language server.
Tests: internal/editor/lsp_launch_test.go and
cmd/standardsctl/editors_self_gate_test.go.
- Extensions. Recommendations are exactly the caller-supplied IDs verified in
editor.Options.ExtensionRegistry; the generator does not contact an extension
marketplace or prove publication from an extension's source directory. Without
that evidence .vscode/extensions.json recommends nothing, golang.go included.
These settings do not prove installation, startup or native client activation.
internal/editor/plan_render_test.go covers each rule with evidence present,
absent and at its boundary.
Complexity ceilings
The JetBrains inspection profile and the Neovim server settings state the
complexity ceilings the repository's policy resolves to, which are the ceilings
praetorctl audit enforces there. The JetBrains profile carries the cyclomatic
limit (GoCyclomaticComplexity's m_limit) and otherwise names only inspections
the IDE provides; it no longer lists HISS01DAGControlFlow, HISS02BoundedLoops,
HISS04ComplexityLOC or HISS07ZeroUnwrap, which no plugin implements, so their
function-length and statement options were never applied. Those limits reach an
editor through standards-lsp. praetorctl adopt uses the policy its
session already resolved. praetorctl editors, standards-lsp (for the
workspace named in its initialize request) and the MCP
standards_inspect_symbols tool (for its server root) use
config.ResolveRepositoryComplexity (internal/config/repository_policy.go).
A locked repository resolves exactly as praetorctl plan resolves it: pinned
profiles, repository overrides and the audit function-length cap.
Every other state resolves to config.HISSComplexityCeiling (cyclomatic 10,
cognitive 15, statements 50 and the audit's function length,
config.AuditMaxFuncLOC = 60), tightened by any complexity override the
manifest declares. Overrides only tighten, so these states never state a limit
looser than the ceiling:
| Workspace state | Result | Stated |
|---|---|---|
no .standards.yaml |
ceiling | nothing |
manifest, no .standards.lock |
ceiling tightened by overrides | nothing |
manifest or lock that does not resolve, including the lock praetorctl init writes |
ceiling tightened by any readable override | [WARN] repository policy unresolved ... (CLI output, MCP report, LSP window/logMessage) |
The lock-less row differs from praetorctl plan on purpose. The plan preview
shows built-in defaults plus overrides (cyclomatic 15, cognitive 20, 60 lines,
75 statements before overrides); an editor told the looser cyclomatic, cognitive
and statement limits would accept what the HISS-04 ceiling rejects. Function
length agrees in both: it is hiss.DefaultMaxFuncLOC (internal/hiss/hiss.go),
the one constant every function-length default derives from. An unresolvable
policy warns rather than failing, because these commands generated editor files
before they read policy at all; praetorctl audit still fails on that state.
Only a nil or cancelled context fails the resolution: editors and the MCP
inspection return the error, and standards-lsp keeps its current ceiling and
logs the reason. Tests:
internal/config/repository_policy_test.go,
cmd/standardsctl/editors_test.go, cmd/standards-lsp/policy_test.go,
cmd/standards-mcp/server_test.go.
Reference integrations under editors/
editors/neovim/lua/standards.lua and
editors/jetbrains/inspectionProfiles/standards.xml are the Neovim module and
JetBrains inspection profile for editors without a Praetor extension. They are
generator output: editor.ReferenceSet (internal/editor/reference.go) renders
them with the same renderers as editors generate, from a fixed plan (a Go
workspace, praetorctl on PATH, bin/standards-lsp, the HISS-04 ceiling), so
they do not depend on what the host has built. The Neovim module defines
:StandardsAudit, :StandardsCompileContext, :StandardsVerifyAll and
:StandardsRatchetSweep; the ratchet sweep runs praetorctl audit, which
evaluates the baseline ratchet against the working tree
(cmd/standardsctl/audit_ratchet.go).
Never edit them by hand. After changing a renderer, regenerate and check:
make editors-reference # praetorctl editors reference
make editors-reference-verify # praetorctl editors reference --verify
make verify-all runs editors-reference-verify, which fails with the drifted
file's path. Tests: internal/editor/reference_test.go,
cmd/standardsctl/editors_reference_test.go.
The engine's own editor files
The engine checks its own editor files the way an adopter's are checked. Its
.standards.yaml selects editors: [universal, vscode], and make verify-all
runs make editors-verify (praetorctl editors verify) against that selection:
The gate fails when a selected file is missing or has lost a managed value. The
tracked .editorconfig adds two-space sections for the TypeScript, Lua, shell and
web sources, so the gate reports it as preserved but unverified. Neovim is not
selected: its module is compared byte for byte, and it holds a language-server
block only when bin/standards-lsp is built, so a fresh checkout and a built one
would disagree. Tests: cmd/standardsctl/editors_self_gate_test.go, which the
platform matrix runs on Linux, macOS and Windows.
VS Code extension trace level
To see the messages the extension and the Praetor LSP exchange, open the command palette, run Developer: Set Log Level..., pick the Praetor LSP output channel and choose Trace. The trace then appears in that output channel. At any other log level, including the default Info, nothing is traced.
While the channel is at Trace, the standards.lsp.trace.server setting picks
the detail:
| Value | Traced |
|---|---|
messages (default) |
method names, request ids and response times |
verbose |
the same, plus parameters and results |
off |
the same as messages |
To stop tracing, set the channel's log level back above Trace; the setting
cannot switch tracing off. vscode-languageclient 10 introduced this gate
(refreshTrace in its lib/common/client.js); 9.x read the setting alone, so
off disabled tracing and messages traced at every log level.
The extension starts its language client with the id standards.lsp and the
name Praetor LSP (LSP_CLIENT_ID and LSP_CLIENT_NAME in
editors/vscode/src/setup.ts). The client reads the setting from
<client id>.trace.server and names its output channel after the client name.
The former id standardsLSP read a key nothing contributes. Tests in
editors/vscode/src/setup.test.ts: "the language client reads its trace level
from the contributed setting" checks the contributed key and its description;
"the locked language client traces only at the Trace log level" runs the locked
client's refreshTrace at the Trace, Debug and Info levels.
VS Code extension MCP server
Generated .vscode/settings.json files carry no standards.mcp.* key and no
MCP server entry. The extension registers standards-mcp itself through the MCP
server definition provider API, defaulting to ${workspaceFolder}/bin/standards-mcp
in a trusted workspace; its engine floor is VS Code 1.107. The generated
standards.sentinel.headroomMB value is the headroom the extension's
Check Sentinel Host Headroom command passes to
praetorctl sentinel --min-free-mb. Details and tests:
editors/vscode/README.md, sections "MCP server" and "Settings".
Existing configuration
Generation preflights configuration conflicts before writing editor files. JSON configuration retains unrelated user keys and list entries while adding missing managed requirements. A conflicting managed value is reported for review. Verification checks those requirements rather than requiring every JSON byte to match a generated template.
An existing JSON file is read in the format its editor documents for it. VS Code
reads .vscode/settings.json, .vscode/extensions.json, .vscode/launch.json and
.vscode/tasks.json as
JSON with Comments, so in those
four files // comments, /* */ comments and a trailing comma are accepted. Every
other JSON editor file (.zed, .fleet, .sublime-project) is strict JSON, and a
comment there is a syntax error. The rule is DialectOf in
internal/strictjson/dialect.go;
the flavor audit applies the same rule to .vscode/settings.json
(onboarding). In both formats a duplicate key is refused.
- A commented file that holds every managed value is in sync.
editors generatereports itPRESENTand leaves its bytes alone, andeditors verifypasses it. - A commented file that lacks a managed value is never rewritten. A merge decodes
the file and writes it again, which would delete every comment.
editors generatestops before it writes any editor file, and onboarding before it writes any file, withcannot safely merge existing <path>: it carries comments or trailing commas, which a merge would lose because it rewrites the file, followed by the JSON Pointer of each managed value the file lacks. Add those values by hand, or remove the comments and trailing commas and generate again.
Tests: internal/editor/jsonc_test.go and TestRunEditors_Boundary_CommentedVSCodeFiles
in cmd/standardsctl/vscode_jsonc_cli_test.go.
Known legacy Go, unavailable LSP, unpublished extension and invented build-task settings are reported as conflicts when they are no longer supported by the resolved plan. They are retained for review; automatic migration of legacy generated files is not supported. Resolve each reported conflict using the actual repository's languages and commands, then generate and verify again.
Non-JSON formats do not yet have semantic merge adapters. Once they exist, the
developer-owned files are never replaced: .editorconfig and .clang-tidy carry
hand-tuned project policy, and .idea/workspace.xml, .nvim.lua and
.dir-locals.el hold IDE session state or a developer's own editor setup.
Generation reports each of them as PRESERVED, and verification lists them as
preserved but unverified, because their existence is not semantic verification of
XML, Lua or editor Lisp. Any other existing non-JSON file that differs from its
template, such as lua/standards.lua or the JetBrains inspection profile, belongs
to Praetor and editors generate rewrites it. A file whose only difference is one
consistent CRLF line-ending style, as a Windows checkout with core.autocrlf leaves
it, is the template: generation reports it PRESENT and verification passes it,
while mixed line endings still count as a difference. Missing files are still
generated from the resolved plan. The list lives in one place,
internal/editor/editor.go
(IsPreservedEditorFile).
A successful workspace configuration check does not imply that an IDE extension, coding-agent wrapper, hook or MCP connection is installed and active. Those require the separate client bootstrap and agent lifecycle checks.
Adoption and onboarding
praetorctl adopt resolves an existing editor file with the rule editors generate
uses, editor.ResolveExisting in internal/editor/editor.go. Because no audit gate
verifies an editor file, adoption keeps differing files, except that it refreshes a
recorded, unedited earlier JetBrains inspection profile. The adoption side is
internal/adopt/editor_files.go. The editors step runs after the
Makefile step (adoptSteps in internal/adopt/adopt.go), so a first adoption's
editor files already offer the verify-all target it scaffolds, and a re-run finds
them unchanged:
| Existing file | Plain run | --force |
|---|---|---|
| identical (CRLF line endings included), or JSON holding every managed value | verified | verified |
| unedited earlier Praetor JetBrains inspection profile | refreshed to current output; report says Refreshed an unedited earlier |
refreshed to current output; report says Refreshed an unedited earlier |
| developer-owned and different | preserved | preserved |
| JSON missing managed values | kept; the warning names each one as a JSON Pointer, such as "/standards.sentinel.headroomMB" |
merged: every adopter key and list entry stays, the managed values are added, and the report lists a merge |
.vscode JSON missing managed values and carrying comments or a trailing comma |
kept; the warning names the values to add by hand | kept, with the same warning: a merge would lose the comments |
JSON adoption cannot merge: a duplicate key, a conflicting managed value, or outside .vscode a comment or a trailing comma |
kept, with a warning naming the reason and the fix | kept, with a warning; adoption continues |
any other file that differs, such as lua/standards.lua |
kept, with a warning and the line delta regenerating would apply | kept, with a warning |
The JetBrains refresh recognizes only recorded generator output. Its digest fixtures
cover every distinct profile shipped from the first release through #476, including
the app-service and native-gpu-systems variants; a hand edit keeps the existing
file unverified. Current profile output is recorded too, so the boundary test fails
when the generator changes without a matching fixture and digest.
A merge re-indents the file with two spaces and sorts its keys. Its report entry carries the line delta and the backup location that every adoption overwrite records (replaced files); a dry run plans the merge and writes nothing.
How a kept file stops warning depends on what it is:
- Non-JSON file that differs. Delete it and re-run adoption, which regenerates it
from the template for the repository's adopted profile.
praetorctl editors generateis no substitute here: it renders the framework profile whatever profile adoption selected, so for another profile it rewrites files adoption had verified. - A
.vscodefile with comments or a trailing comma that lacks managed values. Adoption reads the file as JSON with Comments (existing configuration) and keeps it,--forceincluded, because merging would rewrite it without its comments. Add the values the warning names by hand and re-run adoption, which then verifies the file with its comments in place; or remove the comments and trailing commas and re-run adoption with--forceto merge the values. - A duplicate key, or a comment or trailing comma outside
.vscode. Such a file is not valid in the format adoption andpraetorctl editors verifyread it in, so it never verifies, even when it holds every managed value.praetorctl editors generaterefuses it too: it stops withcannot safely merge existing <path>before it writes any file. Remove what the warning names, then re-run adoption with--forceto merge the managed values; or delete the file and re-run adoption to regenerate it. - A conflicting managed value.
praetorctl editors generaterefuses it the same way. Set the value the warning names to the managed one, then re-run adoption with--force; or delete the file and re-run adoption.
Onboarding (praetorctl harvest onboard, prepareOnboardEditors and
publishOnboardEditors in internal/harvester/onboard.go) applies the
editors generate rule itself, under the caller's context and confined to the
repository, so a link below it is refused rather than followed:
- Resolve first.
editor.PrepareWritesInresolves every editor file before onboarding writes anything, dry run included. A commented.vscodefile that lacks managed values, like any other file the rule refuses, fails the run with thecannot safely merge existing <path>error and nothing written: no manifest, baseline,AGENTS.md, vendor or editor file. A dry run reports the same error. - Merge, keep, create. An existing JSON file keeps every key and gains the missing managed values, a developer-owned file is preserved, and an absent file is created.
- Publish bound to the read.
PreparedWrites.Publishwrites each file only while it still holds the bytes it was resolved from, or is still absent, so an edit made in the meantime is refused instead of overwritten. That failure comes after the scaffold is written, so the error saysscaffold files have been writtenand names the command that finishes the run:praetorctl harvest onboard --repo=<path> --dry-run=false. - Report. The run prints each file's outcome (
CREATED,MERGED,PRESENT,REWRITTENorPRESERVED) aseditors generateprints it, and its plan lists them undereditor_files; a dry run lists none.
Before #717 onboarding replaced every existing editor file that was not developer-owned, dropping the repository's own keys and comments.
Tests: internal/adopt/editor_files_test.go, internal/adopt/editor_jsonc_test.go,
internal/editor/resolve_existing_test.go, internal/editor/write_in_test.go,
internal/editor/prepared_writes_test.go,
internal/harvester/onboard_editor_merge_test.go,
TestOnboardRepository_Boundary_KeepsDeveloperOwnedNvimLua in
internal/harvester/onboard_selection_test.go and
cmd/standardsctl/harvest_onboard_editors_test.go.