Vancetope — Settings Panel
A guided surface for everything configurable per Scope: Setting Forms, Settings Document Kinds, the free Key/Value editor and the complete administration inventory (Tenant, Project Groups, Projects, Languages, Session Groups, Copy, Kits, Tool Templates) in one place.
settings.htmlhas replaced the old Scopes page in a strangler pattern —scopes.htmlandsetting-forms.htmlare deleted (design history and migration rules: planning/settings-panel.md); it uses exactly the same backends — no separate API root.See also: setting-forms (Form contract,
availableIn) | settings-system (Scopes, Cascades, Wire Layer) | wizards (Form Engine) | web-ui
1. What the Surface Solves
Before the Settings Panel, it was unclear where something was configured:
- User Settings: partly self-service in
profile.html, partly as Docs/Settings in the_user_<login>Project, which was not selectable as a Scope in any UI. - Tenant/Project Settings: in the Raw Key/Value Editor of the Scopes page — only those who knew the keys could achieve their goal.
- Setting Forms: correctly listed, but in three places without a common inventory.
- Settings Doc Kinds (
vance-research-source, …): only discoverable via document browsing.
The Panel shows, per Scope, what is configurable here — in four tabs: Areas (Settings Doc Kinds as areas with entry management and inline view), Settings (guided Setting Forms), Project/Tenant (administration: Properties, Groups, Session Groups, Copy, Languages, Kits, Tool Templates — only for Tenant and Project Scopes) and Advanced (free Key/Value editor).
2. Scope Model
Three Scope rows in the sidebar, identical to the Wire Form from settings-system.md §3:
| Sidebar Row | Wire-referenceType/referenceId |
projectId at Forms/Doc Endpoints |
|---|---|---|
| My Settings | user / <login> |
_user_<login> |
| Tenant | tenant / <Tenant> |
_tenant |
Project <name> |
project / <name> |
<name> |
The User row is new: _user_<me> was previously not selectable as a Scope in
any interface. It is always accessible for one’s own login (implicit ADMIN on
one’s own Hub, see Permission System R7); personal Forms (availableIn: ["_user_*"])
are located thereunder.
Default selection on boot: URL parameter → last used Project (lastProject) →
Tenant row.
3. The “Areas” Tab — Settings Doc Kinds (pluggable)
Settings Doc Kinds get their own tab, separate from the Setting Forms: the tab lists the areas (Research, …) as items; a click opens the entry list of the area with Add and Delete buttons; a click on an entry opens its view inline in the Settings page — the only Cortex reference is the jump link of the opened entry.
A Kind declares that its documents are configuration interfaces — as an optional
settingsProvider attribute on the existing KindEntry (@vance/kind-registry,
the same globalThis-registry switch; no second registry):
settingsProvider?: SettingsProvider;
interface SettingsProvider {
/** i18n key for the area label (e.g., settings.areas.research.title). */
titleKey: string;
/** Entry inventory for a Scope; error → empty list. */
list: (scope: SettingsScope) => Promise<SettingsDocRow[]>;
/** Create a new entry with this name, return row (opens directly).
* Without create, the area shows no Add button. */
create?: (scope: SettingsScope, name: string) => Promise<SettingsDocRow>;
}
interface SettingsScope {
kind: 'tenant' | 'user' | 'project';
projectId: string; // _tenant | _user_<login> | <project>
login?: string;
}
interface SettingsDocRow {
name: string; // Instance key (e.g., file stem)
title: string;
description?: string;
kindId: string;
documentId: string; // loads and renders the Settings page inline
projectId: string;
path?: string;
}
3.1 Area Level
The tab has three levels, each with its own URL:
Areas (Area List)
└─ area=<kindId> Entry List + Add/Delete
└─ entry=<documentId> Inline View of the Entry
The host renders, the provider inventories. AreaEntryView.vue loads the
document (GET documents/{id} — Storage-backed Docs read the body via
GET documents/{id}/content, the same path as the Cortex tab), parses it with
the Kind’s codec, and renders the registered view component (:doc /
@update:doc, the minimal Kind contract). Two Save verbs: “Apply” persists
and stays on the entry (banner “Saved.”, continue editing), “Save” persists and
jumps back to the entry list (@close → host clears the entry parameter).
Next to it is the Cortex jump ↗: a link to /cortex?project=<projectId>&path=<docPath>,
which opens the same document in the full editor — Settings configured, Cortex
working; the handoff is a path link, not a second editor. Kinds without View/Codec
or bodies rejected by the codec fall back to a raw text editor with the same
Save verbs — an entry is never a dead end. Delete is generic
(DELETE documents/{documentId}), the provider needs no hook for it.
First Area: Research (vance-research-source). Lists the Zarniwoop sources
under _vance/config/research/ in the Scope Project
(documents/folder?projectId=…&path=_vance/config/research/, client-filtered
to kind === "vance-research-source"); create creates an inactive minimal
source. Serves only the Tenant and Project layers — the Source Config Cascade
(project → _tenant → classpath) has no User layer, so the User row gets no
lines.
Further Areas: Mounts (vance-mount-source, core: Jaglan Mounts under
_vance/config/mounts/, form with rootDir/writable for the local protocol)
and Feed Sources (vance-feed-source, _vance/config/feeds/). The latter
are proof of addon pluggability: the Centauri Addon registers Kind,
settingsProvider, and form view in its own client bundle via the Federation
seam; the Settings page loads the addon registers on boot (manifest-declared
Kinds, once, only this page) and the areas appear without the host knowing the
Centauri name. Both have server-side Kind Handlers (MountSourceKindHandler,
FeedSourceKindHandler): detectsPath flags atypical writes to the config
folder, validation tells during editing what the factory would otherwise silently
drop. Fourth Area: AI Models (vance-model + vance-model-provider, core
client; single file modelCatalogSettingsProvider.ts). Inventory is path-based
like the catalog itself (documents/search with pathPrefix=_vance/model/):
The ModelCatalog scans the path prefix and deep-merges what it finds — a Kind
filter would be alien to its contract; the line gets its view Kind from the
filename (_provider.yaml ⇒ Sidecar form). Create knows both forms: provider
seeds a Sidecar, provider/model a model document — with the catalog’s Wire
Name encoding (: → wireName field + file slug, / → subdirectories); the
hint below says this (createHintKey, a contract extension on SettingsProvider).
The form is partial-override-first: cleared fields are struck keys, struck keys
inherit — numeric owned fields are written as YAML numbers, not digit strings.
Server-side: ModelDocKindHandler (detectsPath on the MANUAL tree, model-auto
stays out; type error validation, wireType hardcoded in the Sidecar).
Fifth Area: Recipes (vance-recipe, core client; recipeSettingsProvider.ts) —
the first administration surface Recipes ever had. Raw text, intentionally:
The Kind registers no View and no Codec, the Settings host falls back to its raw
text editor with Save — Recipe YAMLs are the most complex configuration documents
in the system (Engine, Params, Prompt Templates, Tool Adjustments, Profiles, Guards);
a form would either render a fraction or duplicate the loader parser. The inventory
is flat and path-based like the loader itself (documents/folder, one level):
what is resolved by name — the Slart working trees _user//_slart/ remain outside.
create seeds the minimal body required by the loader (description + engine),
the kebab-case name becomes the file and thus the Recipe name. Server-side:
RecipeDocKindHandler — all findings are errors, because the loader logs WARN and
the Recipe is then silently gone.
Sixth and Seventh Areas: Chat Themes and Report Themes (vance-chat-theme,
vance-report-theme, core client; a factory themeSettingsProvider.ts — the
mechanics are identical in both systems, only the vocabulary differs). Like Recipes
without View/Codec (raw text, here with CSS highlighting via MIME type), inventory
flat and path-based, Create with the name check of the resolvers ([a-z0-9-]+)
and a vocabulary comment as seed. Intentionally no server-side Kind Handlers:
both pipelines are fail-open — an invalid Theme falls back to default.css or is
skipped; there is no finding that the runtime itself would not absorb. Theme files
do not carry a Kind marker (CSS has no place for it) — the identity lies in the
lines of the area, the documents remain plain CSS everywhere.
Eighth Area: Prompts (vance-prompt, core client; promptSettingsProvider.ts) —
the Engine Prompt Overrides under _vance/prompts/ (<engine>-prompt.md, Plan Mode
variants). Create is the override workflow: The name of the bundled Prompt
shadows it by name for every Spawn of the Scope — the hint says it, the seed carries
the convention as a comment. Raw text editor like with Recipes/Themes (Markdown via
MIME type); an empty override is intentionally allowed (the resolver filters empty
content, the bundled version remains active — the server handler reports it as a hint).
Unlike Themes, there is a handler: PromptDocKindHandler compiles the body as
Pebble — a syntax error breaks the turn, not a fallback; the finding is the difference
between edit-time message and spawn end.
Ninth to Eleventh Areas: Scheduler, Workflows, Hooks — three operational configurations with existing server Kind Handlers or new handlers, all path-based inventoried (loaders scan, never Kind markers):
- Scheduler (
vance-scheduler,schedulerSettingsProvider.ts):_vance/scheduler/, flat, typed — the registered SchedulerFormView + Codec open inline, the Cron breakdown contract is the same as in the Cortex Document tab. Firing and event log deliberately remain in the Insights tab (both read the same documents, no data redundancy). Seed fulfills the two loader rules: exactly one target (recipe/workflow/script), exactly one trigger (cron or at). Server handlerUrsaSchedulerKindHandleralready exists. - Workflows (
vance-workflow,workflowSettingsProvider.ts):_vance/workflows/, flat, typed-viewer — the registered WorkflowFlowView renders the state graph inline (parse/serialize are identity, the view never emitsupdate:doc): the graph is the map, not the road; Workflow YAML is edited as text. First administration surface for definitions — the Magrathea Admin inspects Runs, not Workflows. Seed is a valid single-state Workflow (start: work, anagent_task, terminal withouttransitions:). - Hooks (
vance-hook, new,hookSettingsProvider.ts):_vance/hooks/, recursive (Event is path segment:_vance/hooks/<event>/<name>.yaml), raw text — a Hook body is exactly one TriggerAction (recipe/script/workflow) plus Lifecycle keys, not worth a form. Structured Create Name like with Models:event/hook-name, Event validated against the seven Wire Names, Hook Name against the loader grammar. Server handlerHookDocKindHandlerdelegates to the canonicalUrsaHookYamlParser— a finding means exactly what the loader does (skip, logged, never fatal); the Event segment is checked first (Registry lists by Event — unknown Event = invisible). Hooks register only with Project activation — the area writes the document, the loader loads it on bootstrap/refresh. The write path via Document REST accepts User Actor (verified) — the area uses the same path as any Operator edit; the Hook tools additionally remain the Agent path with Admin gate and SYSTEM Actor for audit.
Twelfth and Thirteenth Areas: Guards, Wizards — the last two
area candidates from the _vance/ inventory, both path-based, both
raw text (no View/Codec):
- Guards (
vance-guard, new,guardSettingsProvider.ts):_vance/guards/, flat,.js— the script library, not the wiring: which Recipe fires which Guard at which point remains in the Recipeguard:block, which cites the path. Server handlerGuardDocKindHandlerdelegates to the parse-only GraalJS validator (JsValidationService) — the sameSource.newBuilder + Context.parseas in the Executor. Rationale: the points are not uniform — STOP/TERMINATE and START fail-open (script error is absorbed, the Guard silently never runs), COMMAND fail-closed (script error breaks the Command). A syntax finding is worth both. The fix to the validator (js.top-level-await+ experimental gate as in the Executor) prevents false positives: the bundledllm-judge.jsshipped with top-levelreturn— a GraalJS syntax error that fail-open swallowed, the Guard silently never ran; the script is repaired (if/else instead of Early-Return). - Wizards (
vance-wizard, new,wizardSettingsProvider.ts):_vance/wizards/, flat — the first area with a User layer: the Wizard Cascade isproject → _user_<login> → _vance → classpath, and the User Scope of the Panel is exactly the_user_level; the same provider serves all three Scopes unchanged. Server handlerWizardDocKindHandlerruns via avalidateBodyseam on the canonicalWizardLoader.parse— a finding is what the loader skips with WARN (localized title/description, at least one Field, Pebble-compilingpromptTemplate). Inherited Entries (Contract Extension). Previously, each area listed only the documents of the selected Scope. For Kinds with a cascade, this is insufficient: if a Project is selected, one also wants to see what it inherits from the Tenant or from the bundled defaults. A provider may therefore supply, in addition to itsSettingsDocRows (documentId, the Scope owns the document), alsoSettingsInheritedRows —inherited: 'tenant' | 'bundled', withoutdocumentId;listreturnsSettingsAreaRow[](the union). The host shows inherited rows below its own, with an origin badge, without deletion and without opening; the only action is “Override here” → the optional provider hookoverride(scope, row)creates a local copy with the resolved content and returns itsSettingsDocRow, which the host opens immediately. The copy shadows the original only in this Scope; deleting it restores the inherited one. Inherited rows withoutoverridewould be a dead end — the contract couples both. Existing providers remain unchanged (SettingsDocRowis the same type as before, only withinherited?: undefinedas a discriminator). Candidates for the same approach: Prompts, Recipes, Themes — it is still pending there.
Fourteenth Area: Server Tools (vance-server-tool, new, core client;
serverToolSettingsProvider.ts, ServerToolFormView.vue, serverToolCodec.ts)
— has replaced the dedicated page tools.html. _vance/server-tools/, flat,
typed: the form of the old page as a Kind View (Type, Description,
Active/Primary, Pack specifications, Labels, now also promptHint), for
mcp_server the structured server form with JSON toggle, login block,
and connection test (mcp-client-oauth.md §6), for all
other types JSON parameters with the type’s parameter schema. The model is the
entire YAML map; the codec writes in the order of the server writer
(ServerToolConfigYamlWriter) so that diffs look consistent. The first
area with inherited rows: own documents come from documents/folder,
the cascade including tier from the unchanged Admin list
(GET admin/projects/{p}/server-tools, source TENANT/BUNDLED);
override reads the resolved Tool (GET …/server-tools/{name}) and writes
it as a document into the Scope. create seeds a disabled MCP server
(a server without a URL would fail on the first lookup). Only Tenant and
Project layers — the cascade has no User layer.
Saving is done via the document pipeline; the registry follows via the
existing ServerToolDocumentListener. Because the Admin REST was previously the
only validating write path, ServerToolDocKindHandler now validates the same
on the document: ServerToolLoader.validateYaml (what the loader would silently
skip) and the type against the ToolFactoryRegistry (what
ServerToolService rejects). Login and test act on the saved state
(the server resolves the Tool by name) — the View states this. The
MCP login returns via returnTo with mcpLogin=1 to exactly the open view
(Settings entry or Cortex tab). The Admin REST
(/admin/projects/{p}/server-tools…) remains unchanged.
MCP Packs and Skills are not Areas (decision): MCP/REST Packs are client
files of the Foot (.vancetope/foot-tools/), not a document in the Scope;
Skills are kit-bundled Manuals, not a configuration document.
Neither has anything an Area could inventory.
In perspective (intentionally not yet): carry the area declaration server-side and validate fail-fast on boot (like the Setting Form Loader). Until then, the client registry entry is the truth.
Standard Shell Behavior (Focus Model): The Settings page runs the
EditorShell in standard mode like any other editor (Cortex, Chat,
Insights, Tools, Runs, …): focus-model="auto" + v-model:focus-zone +
full-height (Spec web-ui.md §7.2.1). This collapses the sidebars to 0 on small
viewports (≤900px), the reclaim handles at the zone edges bring them back, the
focused zone stands out — and the Project selection on the left reports
@focus-main, so that selecting a Project jumps back into the content. The left
sidebar is the universally used ProjectListSidebar.
Context Help via the Standard Drawer (Resolution in settingsHelp.ts):
The Settings page uses the helpPath-Prop of the EditorShell — the same
“?” toggle in the Topbar, the same Drawer, the same useHelp-Load as in
Cortex. The Settings contribution is only the resolution of which file the
context wants (three levels):
- Entry open →
doc-kind-<kindId>.md— the Cortex convention: exactly the same file that the Cortex Help tab shows for this document. One file per document type, one place for maintenance. - Area open (Entry list) →
settings-area-<areaId>.md— what this area configures, naming conventions, cascade, pitfalls. Without Cortex counterpart. - Otherwise (Area list, Forms/Properties/Advanced) →
settings.md— the page itself.
A path change leaves the Drawer open as the user set it and swaps the text
(EditorShell contract). Missing files result in a “no help yet” hint, not an
error — help grows incrementally. All areas and their editor document types
are covered; the Feed Sources help is in the Centauri Addon (Classpath
resources travel with the Addon, ClassPathResource finds them).
3.2 The “Settings” Tab — Setting Forms
GET /brain/{tenant}/setting-forms?projectId=<projectId> — unchanged.
Without parameters (= Tenant row), the Tenant context applies; for the User row,
_user_<login> is passed as projectId, which correctly filters availableIn-globs
(_user_*) and live cascade values. Clicking a card opens the Form inline
(SettingFormView.vue, reused unchanged) with a back button; Apply/Validate/Reset
run via the existing Setting Forms endpoints.
3.3 The “Project/Tenant” Tab — Administration (only Tenant and Project Scopes)
The complete administration port of the Scopes page, with the same backends and
i18n keys (scopes.project.*, scopes.group.*, scopes.tenant.*,
scopes.kit.*, scopes.sessionGroups.* — the vocabulary of the Scopes page
lives on here):
- Tenant Card (
TenantCard.vue, Tenant Scope): Name read-only, Title, Enabled, Save viaadmin/tenant(useAdminTenant). - Group Card (
GroupCard.vue, when a group row is selected): Name read-only, Title, Enabled, Delete (reserved Grouparchivedis read-only) viaadmin/project-groups(useAdminProjectGroups). ProjectTab.vue(Project Scope):- Properties Card: Title, Enabled, Group (Move), the read-only facts
(Status, Pod, claimed, Lifecycle Type + explanation, Placement-
pending, created) via
admin/projects(useAdminProjects); Save viaPUT, Archive viaarchive(confirm-guarded), Copy (dialog with report — remains open because the report is the point of the operation; the Open button jumps to the copied Project). - Languages Card:
chat.language/content.languageas dropdowns via the Settings REST (useScopeSettings, Project Wire Scope) — “not set” deletes the override, the cascade falls outward. Language names fromIntl.DisplayNames, no second label table. - Session Groups Card: List (with session counter), Rename inline,
Delete (confirm), Create with Slugify —
admin/session-groups(useSessionGroups). KitAdminSection.vue: installed Kits (signature status, license expiry, origin artifacts), Install (Project picker forproject:sources + Library picker + Git form), Update/Single/All, Apply (trackInstall off), Export (source role), Uninstall (prune question), Per-Kit-Config (Update Policy rules, sortIndex) — viauseKitAdmin/useKitSourceProjects, reused unchanged.ToolTemplatesSection.vue: the Tool Template catalog (_tenant/config/tool-templates.yaml) with search, input dialog, pre-filling from the last Apply and result report — replaces the dedicated pagetool-templates.html. Stands next to Kits because a Template is a Kit with a form: it installs documents, settings, and server tools into the Scope — an action on the Scope, not an area. The target is the Scope itself (the free Project field of the old page is removed); in the Tenant Scope, the section is below the Tenant Card and writes to_tenant. The catalog is Tenant-Admin-only — if403, the section remains hidden. Backend (admin/tool-templates/*) unchanged.
- Properties Card: Title, Enabled, Group (Move), the read-only facts
(Status, Pod, claimed, Lifecycle Type + explanation, Placement-
pending, created) via
The tab is scope-cooked: it appears only for Tenant and Project
Scopes (label “Tenant” or “Project” — the Scope, not a generic
word); a URL with tab=properties on the User row falls back to the
Settings tab (effectiveTab), and a Scope change with an open
tab lands on the Settings tab.
Sidebar in Edit Mode: the reused ProjectListSidebar
(edit-enabled, show-group-rows) brings Project/Group creation (with
Kit catalog dropdown), Drag&Drop move, and status badges (deactivated,
archived, ⏳ waiting for Pod); the Settings page reacts to
@data-changed like the Scopes page did before (Reload, selection, banner — incl.
“created, waiting for placement”).
3.4 The “Actions” Tab — Operator Actions (only Tenant and Project Scopes)
Operator commands behind a backend SPI: each action is an
AdminAction Spring Bean in the Brain (id, multilingual title/description
maps with en-fallback, Scope type, run) — the Registry collects all Beans,
addons can contribute some without host code. REST:
GET admin/actions (descriptors) and POST admin/actions/{id}?projectId=….
The controller enforces ADMIN on Tenant (and for Project runs on the
Project); a TENANT_ONLY action with projectId is a 400 before it runs.
The result is a generic form for all actions
(AdminActionRunResultDto: ok, summary, Items with key/ok/detail/durationMs)
— the tab renders each action without knowing it. A finding (failed
model ping) is ok=false with HTTP 200; only execution aborts become errors.
Actions (v1):
model-catalog-refresh(TENANT_ONLY) — immediate catalog reload instead of 30-minute timer. Migrated here from the Profile.model-discovery(TENANT_ONLY) — a Discovery run over the Tenant (walks all Projects, writes_vance/model-auto/). Migrated from the Profile.model-check(TENANT_AND_PROJECT) — checks only the configured aliases (ai.alias.*, e.g., default:code), not the entire catalog: each alias is resolved as a Spawn would resolve it, each different target model gets exactly one minimal call (“Hello”). Bounded parallel (5, 20s deadline each).research-check(TENANT_AND_PROJECT) — a minimal investigation via the same dispatcher as the Research Tools; Tenant checks_tenant.
The tab is scope-filtered: on Project rows, TENANT_ONLY actions disappear,
User Scope does not show the tab. The URL tab=actions is state like everywhere else.
3.5 The “Advanced” Tab — Raw Editor
Free Key/Value editing per Scope via the existing
AdminSettingsController interface (useScopeSettings-Composable, reused
without change): List, Inline Edit, Delete, Create with type selection.
The same editor as the Raw tab of the old Scopes page — built as a new,
standalone component (RawSettingsPanel.vue), not extracted from
ScopesApp.vue.
Semantics as in the Scopes page: empty for encrypted types means
“do not change”; "" for plaintext types is the explicit
cascade breaker; null values continue to cascade (display distinguishes
“empty — inherits” from “empty — does not inherit”).
Permission Note: listing the Admin Settings REST requires Tenant-ADMIN (existing behavior, same backend rule as the Scopes page). Users without this role see the endpoint’s error message in the Raw tab — the guided forms remain usable, they authorize per Scope on apply.
4. Navigation — The URL is the State
The page follows the Cortex contract (cortexUrl.ts): the URL is the
state, no hidden session storage. The owner of the query contract is
settingsUrl.ts (Parse/Serialize/Push/Replace in one place):
| Parameter | Meaning |
|---|---|
scope |
tenant | user | Project name (any non-keyword value) |
tab |
areas (Areas) | properties (Administration, only Tenant/Project) | actions (Actions, only Tenant/Project) | raw (Advanced); missing = Settings (Forms, Default, not serialized) |
form |
Name of the opened Setting Form; missing = Form listing |
area |
Kind ID of the opened Area; missing = Area list |
entry |
Document ID of the opened Entry; missing = Entry list |
group |
Selected Project Group row (only meaningful with scope=tenant&tab=properties); missing = no group. Is cleared on every Scope change. |
Follow-up behavior: Browser Back/Forward navigates between visited Scopes/Forms, F5 maintains the state, shared links reproduce the view. A stale form (Scope change, listing no longer has the form) is removed from the view instead of being rendered dead.
Deep-Link from the User Menu: the Topbar menu item “Settings”
builds editorHref('settings', { scope: 'user' }) — thus it is not a
special case, but one of the usual addresses of this page.
editorHref (platform/editorHref.ts) is the single place for Surface URLs;
settings is a StandaloneSurface with its own Vite entry
(settings.html).
5. UI Structure
settings.html (Standalone Surface)
└── EditorShell (Mandatory Shell)
├── Sidebar
│ └── ProjectListSidebar (Component reused: Group rows,
│ Filter, Edit mode: Create + Drag&Drop Move, Kit Catalog,
│ Status Badges)
└── Main
├── Scope Header (Label + Wire ID) + Banner
├── Tab Bar: Areas | Settings | Project/Tenant* | Advanced
│ (* only Tenant/Project Scopes, Label = the Scope)
├── Areas: Area List → Entry List (+Add/Delete)
│ └── Entry open: Back + AreaEntryView (Inline Kind View)
├── Settings: Form Listing by Category
│ └── Form open: Back + SettingFormView
├── Project/Tenant:
│ ├── Group selected (group=…): GroupCard
│ ├── Tenant: TenantCard, ToolTemplatesSection
│ └── Project: ProjectTab — Properties Card (Title, Enabled,
│ Group, Facts, Archive, Copy), Languages Card
│ (chat/content.language), Session Groups Card,
│ KitAdminSection (installed Kits, Install/Update/Export,
│ Per-Kit-Config), ToolTemplatesSection
└── Advanced: RawSettingsPanel
Component rules according to agent/face.md: Primitives from @vance/components,
DaisyUI only in allowed directories, i18n in its own
settings.*-namespace (en + de), everything user-facing translated.
6. Cutover Status and Open Items
- Scopes Page is gone: parity is complete (Tenant, Group,
Project Card including languages, Session Groups, Copy, Kits, Raw Editor,
Setting Forms listing, Create/Move/Badges) and link checking is
done —
scopes.html,setting-forms.htmlalong with apps and Vite entries are deleted;editorHrefno longer knows these Surfaces. All entry points (Landing Tile, Megadodo Kit Link, User Menu) point tosettings.html. Thescopes.*-i18n keys used by the ported components live on; dead page ballast (scopes.settingsPanel.*,scopes.sidebar.*, …) has been removed. - Tools and Tool Templates pages are gone:
tools.htmlandtool-templates.htmlalong with apps, Vite entries,editorHrefsurfaces, and landing tiles are deleted. Server Tools are an area (§3.1), the Templates a section in the Project/Tenant tab (§3.3). The help of the old page lives on asdoc-kind-vance-server-tool.md, plussettings-area-vance-server-tool.md. - No server-side Kind declaration (see §3.2) — client registry remains the truth until caught up.
- Areas extended (done): Mounts (core client), Feed Sources
(Centauri Addon, via Federation — proof of pluggability),
AI Models, Recipes, Chat Themes, Report Themes, and Prompts
(core client, path-based inventories) are present as
settingsProvidercontributions; MCP Packs and Skills are intentionally not areas (not configuration documents, §3.1). - Open: Category vocabulary of the areas (rough groups in the area listing) and the server-side area declaration (§3.1).
See also: planning/settings-panel.md (Design History, Strangler Phases, Parity Checklist) | readme/settings-panel.md (Implementation Documentation)