refactor(design): retire /design — a surface that could only inspect itself
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / integration (push) Successful in 29s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Successful in 59s
CI & Build / Build & push image (push) Successful in 40s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / integration (push) Successful in 29s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Successful in 59s
CI & Build / Build & push image (push) Successful in 40s
The design surface is for the projects an install tracks. /design read the running app's own stylesheet — names out of a bundled theme.css, values out of getComputedStyle(document.documentElement) — so it could only ever describe the instance serving the page. Scribe is one project among the projects Scribe tracks; it gets no view hardcoded into every install. The mechanism that makes this a tool rather than a mirror already existed and already covers Scribe: scripts/check_design_tokens.py runs in CI against a sheet path it knows nothing about, using check_code_against_tokens — the same engine behind check_snippets_against_system. /design was redundant even here. Removed: DesignView, DesignTabs (nothing left to tab between), api/design.ts, routes/design.py and its blueprint, the /design route, ui_design_system() and its setting, and the Settings picker that designated "this app's UI". utils/designTokens.ts and utils/designDrift.ts go with it — between them they were the browser-reading half. What survives is utils/designValues.ts, which works on a record rather than a document: valueForMode, modesPresent, and resolveDeclared. resolveDeclared gained real isolation in the move. Custom properties inherit and `all: initial` does not reset them, so a probe sitting in this page would resolve any reference a record leaves undeclared against the SURROUNDING app's tokens — previewing another project's system would quietly borrow this one's palette wherever that system was incomplete, and a token already reported under unknown_refs would render as though it were fine. Undeclared references are now blanked on the probe first, so they resolve to nothing, which is what the record says they are. Migration 0075 absorbs ui_design_system_id alongside design_rulebook_id rather than an 0076 undoing it: 0075 has not run anywhere, since dev is unmerged and deploys come from main. Both keys named a design source for the running install, and a project already carries its own pointer. This retires the agreement panel shipped yesterday. It asked whether the sheet was actually loaded and applied — the one question a record cannot answer about itself — but only ever about the app you are already inside. Nothing replaces it; recorded in #2430 rather than quietly dropped. Step 1 of milestone #274. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs
This commit is contained in:
@@ -4,7 +4,6 @@ import { useSettingsStore } from "@/stores/settings";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import { useToastStore } from "@/stores/toast";
|
||||
import { apiGet, apiPost, apiPut, apiDelete, listGroups, createGroup, deleteGroup, listGroupMembers, addGroupMember, removeGroupMember, searchUsers, listApiKeys, createApiKey as apiCreateApiKey, revokeApiKey as apiRevokeApiKey, getProfile, updateProfile, type ApiKeyEntry, type GroupEntry, type GroupMember, type UserSearchResult, type UserProfile } from "@/api/client";
|
||||
import { fetchDesignSystems } from "@/api/designSystems";
|
||||
import type { User } from "@/types/auth";
|
||||
import PaginationBar from "@/components/PaginationBar.vue";
|
||||
import TagInput from "@/components/TagInput.vue";
|
||||
@@ -32,12 +31,6 @@ const kbWritePathThreshold = ref("0.68");
|
||||
// gate: that one BLOCKS a create and must be unforgiving of noise, this one only
|
||||
// suggests a merge the operator reviews (services/dedup.py).
|
||||
const kbDuplicateThreshold = ref("0.82");
|
||||
// Which design system this install's own UI is built from, for the /design
|
||||
// agreement panel. Empty = none designated, which is the normal state for a
|
||||
// fresh install rather than a misconfiguration — the panel explains itself when
|
||||
// unset. Replaced design_rulebook_id when the rulebook was retired (#2419).
|
||||
const uiDesignSystemId = ref("");
|
||||
const designSystems = ref<{ id: number; title: string }[]>([]);
|
||||
const savingKbInject = ref(false);
|
||||
const kbInjectSaved = ref(false);
|
||||
|
||||
@@ -107,9 +100,6 @@ async function saveKbInject() {
|
||||
kb_writepath_enabled: kbWritePathEnabled.value ? 'true' : 'false',
|
||||
kb_writepath_threshold: String(wpT),
|
||||
kb_duplicate_threshold: String(dupT),
|
||||
// Empty string DELETES the setting (see routes/settings.py), which is
|
||||
// exactly right for "no design system" — absent rather than zero.
|
||||
ui_design_system_id: uiDesignSystemId.value,
|
||||
});
|
||||
kbInjectSaved.value = true;
|
||||
setTimeout(() => (kbInjectSaved.value = false), 2000);
|
||||
@@ -500,16 +490,6 @@ onMounted(async () => {
|
||||
if (allSettings.kb_duplicate_threshold !== undefined) {
|
||||
kbDuplicateThreshold.value = allSettings.kb_duplicate_threshold;
|
||||
}
|
||||
uiDesignSystemId.value = allSettings.ui_design_system_id ?? "";
|
||||
// Best-effort: the picker degrades to "none available" rather than blocking
|
||||
// the whole settings page if design systems can't be listed.
|
||||
try {
|
||||
designSystems.value = (await fetchDesignSystems()).design_systems.map(
|
||||
(s) => ({ id: s.id, title: s.title }),
|
||||
);
|
||||
} catch {
|
||||
designSystems.value = [];
|
||||
}
|
||||
if (allSettings.notify_task_reminders !== undefined) {
|
||||
notifyTaskReminders.value = allSettings.notify_task_reminders !== "false";
|
||||
}
|
||||
@@ -1280,25 +1260,12 @@ function formatUserDate(iso: string): string {
|
||||
location, not by resemblance.
|
||||
</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="ui-design-system">This app's design system</label>
|
||||
<select id="ui-design-system" v-model="uiDesignSystemId" class="input" style="max-width: 22rem">
|
||||
<option value="">None — don't check the interface against a record</option>
|
||||
<option v-for="ds in designSystems" :key="ds.id" :value="String(ds.id)">
|
||||
{{ ds.title }}
|
||||
</option>
|
||||
</select>
|
||||
<p class="field-hint">
|
||||
Which design system this interface is supposed to be built from. Once
|
||||
set, the <router-link to="/design">Design</router-link> page compares
|
||||
every token the system declares against what the browser has actually
|
||||
resolved, and reports the ones the app is missing, renders differently,
|
||||
or has never heard of. That catches a stylesheet that was regenerated
|
||||
but never shipped — which the record alone cannot tell you, since the
|
||||
sheet is generated from it. Leave it as None if this install's
|
||||
interface isn't described by one of your design systems.
|
||||
</p>
|
||||
</div>
|
||||
<!-- A design system belongs to a PROJECT, and the picker for it lives on
|
||||
the project. There was a setting here that designated the system
|
||||
this install's own interface was built from; it only ever described
|
||||
the app you were already looking at, which is not what the feature
|
||||
is for (#274). -->
|
||||
|
||||
<div class="field">
|
||||
<label for="kb-duplicate-threshold">Near-duplicate report threshold</label>
|
||||
<input
|
||||
|
||||
Reference in New Issue
Block a user