docs(6210): acceptance sweep — src, scripts and frontend leftovers described in the present tense
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 1m9s
CI & Build / Python tests (push) Successful in 1m55s
CI & Build / Build & push image (push) Successful in 34s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 1m9s
CI & Build / Python tests (push) Successful in 1m55s
CI & Build / Build & push image (push) Successful in 34s
The acceptance greps found what the per-area passes missed: - src/scribe: "Phase 7/8" removal notes in projects, settings and user_profile; a paragraph promising an auto-summary side effect that no longer exists; user_profile's claim that "upcoming MCP profile tools" read the profile, which nothing does; an instance count and instance rule titles in plugin_context; "MILESTONE 323 DECIDED" in rulebooks. - scripts/: check_plugin's header and inline comments were a history of the incidents behind each guard, with issue numbers in two failure messages; check_dangling_styles named this app's classes as its examples; check_design_tokens, measure_duplication and mint_plugin_version cited issues and checklists. - frontend/src: forty-odd comments with four-digit issue numbers that the earlier frontend scan filtered out as hex colours, plus "used to" and "Phase N" notes. Kept: illustrative ids (`#4181` as a bare-id example, `PR #198`), migration Create Date headers and one migration's dated data floor, and the plugin skills' worked examples of how to cite a record. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,11 +13,10 @@ import { fetchVersion } from "@/api/version";
|
||||
useTheme();
|
||||
|
||||
const router = useRouter();
|
||||
// THREE states, not two (#3127 checklist 12). `null` is "not answered yet" and
|
||||
// renders nothing; a string renders; `appVersionFailed` renders its own thing.
|
||||
// This used to default to the literal "dev" and swallow the error, which meant
|
||||
// an instance that could not answer was indistinguishable from a local build
|
||||
// that genuinely reports "dev" — a blank standing in for `unknown`, in the one
|
||||
// THREE states, not two. `null` is "not answered yet" and renders nothing; a
|
||||
// string renders; `appVersionFailed` renders its own thing. Defaulting to the
|
||||
// literal "dev" and swallowing the error would make an instance that cannot
|
||||
// answer indistinguishable from a local build that genuinely reports "dev" — a blank standing in for `unknown`, in the one
|
||||
// readout whose whole job is to say what is running.
|
||||
const appVersion = ref<string | null>(null);
|
||||
const appVersionFailed = ref(false);
|
||||
|
||||
@@ -41,8 +41,8 @@ async function handleResponse<T>(res: Response, path: string): Promise<T> {
|
||||
/**
|
||||
* The server's `{"error": "..."}` message from a failed call, or `fallback`
|
||||
* when the failure carried none (network error, non-JSON body). The one place
|
||||
* the error envelope is unpacked on the client — views used to restate this
|
||||
* as a six-line `"body" in e` branch at every catch site.
|
||||
* the error envelope is unpacked on the client, so no view restates it as a
|
||||
* `"body" in e` branch at its catch site.
|
||||
*/
|
||||
export function apiErrorMessage(e: unknown, fallback: string): string {
|
||||
if (e && typeof e === "object" && "body" in e) {
|
||||
@@ -61,8 +61,7 @@ export function apiErrorMessage(e: unknown, fallback: string): string {
|
||||
* surface can show for "pending forever" that is not a lie.
|
||||
*
|
||||
* 30s is chosen to be longer than anything healthy: it has to clear a cold
|
||||
* embedding call and a list view under connection-pool contention (#2384 had
|
||||
* /api/projects fanning 25 concurrent sessions at a 15-connection pool), so
|
||||
* embedding call and a list view under connection-pool contention, so
|
||||
* tripping it means something is genuinely wrong rather than merely busy. Slow
|
||||
* BY DESIGN is a different case and passes its own value — see the callers in
|
||||
* SettingsView that do.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Design systems — the stylesheet held as records (milestone #254).
|
||||
* Design systems — the stylesheet held as records.
|
||||
*
|
||||
* A design system is a named set of tokens with an optional parent. A system
|
||||
* with no parent is a "family"; one with a parent holds ONLY what it changes,
|
||||
@@ -82,8 +82,8 @@ export interface StarterRoleGroup {
|
||||
}
|
||||
|
||||
/** The starter token ROLES offered at creation — names and purposes, never
|
||||
* values. A default palette would be one install's taste shipped as product
|
||||
* (rule #115), so the values are always the operator's to fill. */
|
||||
* values. A default palette would be one install's taste shipped as product,
|
||||
* so the values are always the operator's to fill. */
|
||||
export const listStarterRoleGroups = () =>
|
||||
apiGet<{ groups: StarterRoleGroup[]; default_prefix: string }>(
|
||||
"/api/design-systems/starter-roles",
|
||||
|
||||
@@ -88,7 +88,7 @@ export interface Lesson {
|
||||
no_rule?: { why: string; judged_at: string | null };
|
||||
/** Sent by a create or update that recorded "no rule fits" when that answer
|
||||
* completes a group: lessons with no rule that keep landing in one
|
||||
* situation, which may want a rule written for it (#4634). */
|
||||
* situation, which may want a rule written for it. */
|
||||
convergence?: { lessons: { id: number; title: string }[] };
|
||||
/** Set when another user owns this record. */
|
||||
shared?: boolean;
|
||||
|
||||
@@ -30,7 +30,7 @@ export interface SnippetFields {
|
||||
* no `locations`/`tags` predates that attribution and cannot be un-merged. */
|
||||
merged_from: { id: number; locations?: SnippetLocation[]; tags?: string[] }[];
|
||||
code: string;
|
||||
/** Free text that is not the situation — why, history, caveats (#4378).
|
||||
/** Free text that is not the situation — why, history, caveats.
|
||||
* Kept out of `when_to_use`, which the snippet is ranked on. */
|
||||
notes: string;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export interface System {
|
||||
open_issue_count: number;
|
||||
/**
|
||||
* How often this area's rulings were shown to a session because its files
|
||||
* were touched (`surfaced_count`), and how often it was opened (#4769).
|
||||
* were touched (`surfaced_count`), and how often it was opened.
|
||||
* Present on the list and detail reads; optional because a System returned
|
||||
* by a create or update carries none.
|
||||
*/
|
||||
@@ -45,7 +45,7 @@ export async function listSystems(projectId: number): Promise<System[]> {
|
||||
* caller to accept or ignore.
|
||||
*
|
||||
* A same-named System in this project is a 409 ApiError carrying
|
||||
* `{duplicate, existing_id}` — the same gate the MCP door enforces (#2482).
|
||||
* `{duplicate, existing_id}` — the same gate the MCP door enforces.
|
||||
*/
|
||||
export interface CreatedSystem extends System {
|
||||
canonical_suggestion?: CanonicalMatch;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* The sweep-row visual language (#3207).
|
||||
/* The sweep-row visual language.
|
||||
*
|
||||
* A "sweep" is a pane that lists records in the order they most need a human
|
||||
* — the note verification sweep, the rule sweep, preference drift — as one
|
||||
|
||||
@@ -132,11 +132,10 @@ router.afterEach(() => {
|
||||
}
|
||||
/* Three tracks, not a flex row with an absolutely-centred overlay.
|
||||
*
|
||||
* The pill bar used to be `position: absolute; left: 50%`, which meant it did
|
||||
* not participate in layout: when the header ran out of room it OVERLAPPED the
|
||||
* brand and the utility cluster rather than pushing them, and nothing wrapped
|
||||
* or scrolled to signal it. A sixth link reached that point at ~1270px, which
|
||||
* is an ordinary window on any monitor.
|
||||
* A pill bar at `position: absolute; left: 50%` does not participate in
|
||||
* layout: when the header runs out of room it OVERLAPS the brand and the
|
||||
* utility cluster rather than pushing them, and nothing wraps or scrolls to
|
||||
* signal it — at an ordinary window width on any monitor.
|
||||
*
|
||||
* `1fr auto 1fr` fixes it structurally. A `1fr` track has an AUTO minimum, so
|
||||
* neither side can be squeezed below its content, and the two side tracks stay
|
||||
@@ -327,7 +326,7 @@ router.afterEach(() => {
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
/* The grid above means running out of room can no longer cause a collision —
|
||||
/* The grid above means running out of room cannot cause a collision —
|
||||
but it can still make the header wider than the window, and a horizontally
|
||||
scrolling header is its own defect. So shed width before that happens. The
|
||||
wordmark goes first: the logo beside it says the same thing and is still the
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
* A COMPONENT rather than markup inside the task editor, because the same
|
||||
* question is worth answering on any record a lesson can cite — an issue, a
|
||||
* spike, a dev-log. One panel, mounted wherever that is true, instead of the
|
||||
* shape being written a second time the first time someone wants it on notes
|
||||
* (#3207).
|
||||
* shape being written a second time the first time someone wants it on notes.
|
||||
*
|
||||
* SILENT WHEN EMPTY. Most records taught no lesson, and a panel that renders
|
||||
* "None yet" on every page is a panel people learn to skip — which costs the
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* A project's own code, checked against the design system it is bound to (#2432).
|
||||
* A project's own code, checked against the design system it is bound to.
|
||||
*
|
||||
* This is what the design surface is FOR: a project's recorded components
|
||||
* measured against the sheet they are supposed to use. The check itself is not
|
||||
@@ -38,7 +38,7 @@ async function run() {
|
||||
} catch {
|
||||
// Said out loud rather than rendered as an empty result. "Couldn't check"
|
||||
// and "nothing to report" look identical if you let them, and that is how
|
||||
// a check comes to sit dead without anyone noticing (#2419).
|
||||
// a check comes to sit dead without anyone noticing.
|
||||
failed.value = true;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Deliberately not StatusBadge. That component is typed to TaskStatus and
|
||||
* speaks a different vocabulary; these two only ever shared a CSS class name,
|
||||
* which is what made them look like one shape that had drifted (#3132).
|
||||
* which is what makes them look like one shape that has drifted.
|
||||
*
|
||||
* Extracted because ProjectView and ProjectListView really were spelling the
|
||||
* same pill twice, with the differences you get from two hands rather than
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* The starter token ROLES offered when a design system is created (#2349).
|
||||
* The starter token ROLES offered when a design system is created.
|
||||
*
|
||||
* WHY THIS IS A COMPONENT
|
||||
* DesignSystemsView has two creation forms — the empty state and the one inside
|
||||
@@ -11,7 +11,7 @@
|
||||
* WHAT IT OFFERS
|
||||
* Names and purposes, never values. A role is a question the operator answers
|
||||
* with their own palette; a default palette would be one install's taste
|
||||
* shipped as product (rule #115). Every group is individually skippable —
|
||||
* shipped as product. Every group is individually skippable —
|
||||
* an operator who wants three tokens should get three.
|
||||
*
|
||||
* All groups are checked by default. That default lives HERE rather than in the
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { TaskStatus } from "@/types/task";
|
||||
const props = defineProps<{
|
||||
status: TaskStatus;
|
||||
clickable?: boolean;
|
||||
/** Dense surfaces — smaller, unshouted. The canon (#2960) names compact a
|
||||
/** Dense surfaces — smaller, unshouted. The canon names compact a
|
||||
VARIANT of this component rather than a reason to re-spell it. */
|
||||
compact?: boolean;
|
||||
}>();
|
||||
|
||||
@@ -72,7 +72,7 @@ function areaName(system: System): string | null {
|
||||
return canon.byId(system.canonical_id)?.name ?? null;
|
||||
}
|
||||
|
||||
/** How many times this area's rulings reached a session (#4769). Not the
|
||||
/** How many times this area's rulings reached a session. Not the
|
||||
* UsageBadge: its "N/M used" reads opens over showings, and rulings are
|
||||
* delivered in full in the line, so an unopened System is the arm working,
|
||||
* not dead weight. */
|
||||
@@ -721,16 +721,16 @@ async function confirmDelete() {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* RESTORED (#2444). Both lost their base rule to a CSS sweep; only the
|
||||
`--archived` modifier and the `:hover .system-actions` reveal survived.
|
||||
The card WAS a flex row and every child still says so — `.system-swatch`
|
||||
/* BASE RULES for the card and the list. Without them only the `--archived`
|
||||
modifier and the `:hover .system-actions` reveal would remain.
|
||||
The card is a flex row and every child says so — `.system-swatch`
|
||||
and `.system-actions` are `flex-shrink: 0`, `.system-body` is `flex: 1`,
|
||||
and `.system-form--inline` is `flex: 1`. `align-items: flex-start` is why
|
||||
the swatch carries `margin-top: 0.3rem`: it is nudged onto the first line
|
||||
of text rather than centred against the whole card.
|
||||
|
||||
The list had no rule at all, so it rendered with browser bullets and
|
||||
indent — invisible to the dangling-style check, which can only see a class
|
||||
Without its rule the list renders with browser bullets and indent —
|
||||
invisible to the dangling-style check, which can only see a class
|
||||
that is PARTLY styled. A class with no rules anywhere looks exactly like a
|
||||
semantic-only hook.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* A design system's tokens, drawn rather than listed (#2431).
|
||||
* A design system's tokens, drawn rather than listed.
|
||||
*
|
||||
* WHAT MAKES THIS WORK FOR A SYSTEM YOU AREN'T RUNNING
|
||||
* Every value is resolved on an offscreen probe carrying only this system's
|
||||
@@ -14,7 +14,7 @@
|
||||
* SPECIMENS ARE CHOSEN BY VALUE SHAPE, NEVER BY NAME
|
||||
* A colour is drawn as a swatch, a length as a rule of that length, a font
|
||||
* stack as text set in it. Nothing here matches `--fs-space-*` or any other
|
||||
* naming convention, because the convention is the install's (rule #115) — a
|
||||
* naming convention, because the convention is the install's — a
|
||||
* system that calls its spacing `--gap-N` gets the same treatment.
|
||||
*
|
||||
* A token with no value for the chosen mode is shown as undecided rather than
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
* fields moved".
|
||||
*
|
||||
* What was genuinely shared is shared: DiffView.vue takes DiffLine[] and
|
||||
* nothing note-shaped, and the LCS walk now lives in utils/diff.ts, which
|
||||
* this file uses rather than copying a fourth time (#3207).
|
||||
* nothing note-shaped, and the LCS walk lives in utils/diff.ts, which this
|
||||
* file uses rather than carrying a copy of its own.
|
||||
*/
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import DiffView from "@/components/DiffView.vue";
|
||||
|
||||
@@ -62,7 +62,7 @@ ul { list-style: none; padding: 0; margin: 1rem 0; }
|
||||
li { padding: 0.5rem; cursor: pointer; border-radius: 6px; }
|
||||
li.active { background: var(--fs-accent-soft); }
|
||||
li:hover { background: var(--fs-surface-hover); }
|
||||
/* `.new-topic` is deliberately bare (#2444): it wraps a button-or-form whose
|
||||
/* `.new-topic` is deliberately bare: it wraps a button-or-form whose
|
||||
children style themselves, and namespaces the descendant rule below. */
|
||||
.new-topic input {
|
||||
width: 100%; margin-bottom: 0.5rem;
|
||||
|
||||
@@ -12,8 +12,7 @@ export function relativeTime(iso: string): string {
|
||||
|
||||
/**
|
||||
* relativeTime() for the recent past, a short date once it's a week old —
|
||||
* the workspace panels' list-row timestamp ("3h ago" / "Jan 15"). Two
|
||||
* panels used to carry identical copies of this.
|
||||
* the workspace panels' list-row timestamp ("3h ago" / "Jan 15").
|
||||
*/
|
||||
export function relativeTimeOrDate(iso: string): string {
|
||||
const d = new Date(iso);
|
||||
|
||||
@@ -7,7 +7,7 @@ import "./assets/theme.css";
|
||||
import "./assets/components.css";
|
||||
import "./assets/prose.css";
|
||||
// Global rather than `<style src>` per pane: plugin-vue cannot compile one
|
||||
// src stylesheet shared by several SFCs (#3207 broke the image build).
|
||||
// src stylesheet shared by several SFCs, and the image build fails on it.
|
||||
import "./assets/sweep-shared.css";
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
@@ -137,10 +137,9 @@ const router = createRouter({
|
||||
},
|
||||
{
|
||||
// The design systems this install RECORDS — for the projects it tracks,
|
||||
// not for the install itself. There was a sibling `/design` that read the
|
||||
// running app's own stylesheet out of the browser; it could only ever
|
||||
// inspect the instance it was served from, which made it a mirror rather
|
||||
// than a tool (#274).
|
||||
// not for the install itself. A page reading the running app's own
|
||||
// stylesheet out of the browser could only inspect the instance it was
|
||||
// served from, a mirror rather than a tool.
|
||||
path: "/design-systems",
|
||||
name: "design-systems",
|
||||
component: () => import("@/views/DesignSystemsView.vue"),
|
||||
|
||||
@@ -54,9 +54,8 @@ export const useTasksStore = defineStore("tasks", () => {
|
||||
|
||||
async function updateTask(
|
||||
id: number,
|
||||
// IssueFields carries `kind`, which the PATCH route now reads. It has
|
||||
// always been SENT by the task editor; until #3129 the route dropped it
|
||||
// and the save reported success while changing nothing.
|
||||
// IssueFields carries `kind`, which the PATCH route reads. A route that
|
||||
// dropped it would report success while changing nothing.
|
||||
data: Partial<
|
||||
Pick<Task, "title" | "body" | "tags" | "status" | "priority" | "due_date" | "project_id" | "milestone_id" | "parent_id" | "recurrence_rule">
|
||||
> & IssueFields
|
||||
|
||||
@@ -7,11 +7,10 @@
|
||||
* position more often has a trigger that fires on the wrong work. Telling an
|
||||
* operator to delete one of those would be the wrong nudge about half the time.
|
||||
*
|
||||
* The table lives here because the copy was about to exist in five places.
|
||||
* Three already had their own: `SnippetListView`, `RuleListPane`, and
|
||||
* `LessonDetailView` with the sentence inline in its template. The unified
|
||||
* Knowledge browse renders notes, tasks, processes, snippets and lessons in one
|
||||
* mixed feed (#4230), so it needs all of them at once — and a per-view constant
|
||||
* The table lives here because several surfaces need it: `SnippetListView`,
|
||||
* `RuleListPane`, `LessonDetailView`, and the unified Knowledge browse, which
|
||||
* renders notes, tasks, processes, snippets and lessons in one mixed feed and
|
||||
* so needs all of them at once — and a per-view constant
|
||||
* is how three surfaces end up giving three different answers to the same
|
||||
* question.
|
||||
*
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/**
|
||||
* Turning a design system's RECORDED values into ones you can look at.
|
||||
*
|
||||
* Replaces `designTokens.ts` and `designDrift.ts`, which between them read the
|
||||
* running app's own stylesheet — names out of a bundled `theme.css`, values out
|
||||
* of `getComputedStyle(document.documentElement)`. That could only ever describe
|
||||
* the install serving the page, and the design surface is for the projects an
|
||||
* install TRACKS (#274). What is left here works on any system's record,
|
||||
* including one for an app this browser has never loaded.
|
||||
* Reading the running app's own stylesheet — names out of a bundled
|
||||
* `theme.css`, values out of `getComputedStyle(document.documentElement)` —
|
||||
* could only describe the install serving the page, and the design surface is
|
||||
* for the projects an install TRACKS. Everything here works on any system's
|
||||
* record, including one for an app this browser has never loaded.
|
||||
*
|
||||
* Nothing in this module reads the document's own tokens or mutates the page.
|
||||
*/
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* Design systems — the stylesheets this install RECORDS, for the projects it
|
||||
* tracks (milestone #254 step 5).
|
||||
* tracks.
|
||||
*
|
||||
* It had a sibling, `/design`, which showed the system as the BROWSER had it —
|
||||
* names out of a bundled stylesheet, values out of `getComputedStyle`. That
|
||||
* could only ever describe the install serving the page, so it was a mirror
|
||||
* rather than a tool and was retired (#274). Everything here works on a system
|
||||
* whose app this browser has never loaded.
|
||||
* Showing the system as the BROWSER has it — names out of a bundled
|
||||
* stylesheet, values out of `getComputedStyle` — could only describe the
|
||||
* install serving the page, a mirror rather than a tool. Everything here works
|
||||
* on a system whose app this browser has never loaded.
|
||||
*
|
||||
* The layout follows the model rather than decorating it. A system with a
|
||||
* parent holds only what it changes, so this page has two lists and they are
|
||||
@@ -153,7 +152,7 @@ const newTitle = ref("");
|
||||
const newDescription = ref("");
|
||||
const newParentId = ref<number | null>(null);
|
||||
const creating = ref(false);
|
||||
// Starter roles (#2349). The picker fills these on mount; empty means the
|
||||
// Starter roles. The picker fills these on mount; empty means the
|
||||
// operator unchecked everything, which is a real answer.
|
||||
const starterGroups = ref<string[]>([]);
|
||||
const tokenPrefix = ref("");
|
||||
@@ -500,8 +499,8 @@ watch(selectedId, () => {
|
||||
* `var()` reference states nothing on its own: rendering
|
||||
* `color-mix(in srgb, var(--accent) 15%, transparent)` as a background resolves
|
||||
* `--accent` against THIS app, so a system that isn't the one Scribe runs on
|
||||
* would be drawn in Scribe's palette. It looked right, which is why it went
|
||||
* unnoticed (#274).
|
||||
* would be drawn in Scribe's palette — and look right, which is why it would
|
||||
* go unnoticed.
|
||||
*
|
||||
* The preview above resolves values properly, on a probe carrying only that
|
||||
* system's declarations. So this list draws only what needs no resolving, and
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
*
|
||||
* IT BINDS NOBODY, and the page says so once, plainly. That sentence is the
|
||||
* difference between this kind and a rule, and it is the reason the kind
|
||||
* exists (#3727) — sessions were proposing rules for things that should never
|
||||
* have bound anyone.
|
||||
* exists — without it, sessions propose rules for things that should never
|
||||
* bind anyone.
|
||||
*
|
||||
* BUT IT CAN POINT AT ONE. A lesson that is an instance of a
|
||||
* rule says so, and the page shows which of the three answers it holds: the
|
||||
|
||||
@@ -231,7 +231,7 @@ async function save(force = false) {
|
||||
? await updateLesson(lessonId.value, payload)
|
||||
: await createLesson(payload);
|
||||
toast.show(isEdit.value ? "Lesson updated" : "Lesson recorded");
|
||||
// "No rule fits" just completed a group of lessons in one situation (#4634).
|
||||
// "No rule fits" just completed a group of lessons in one situation.
|
||||
// Said once, here, because the page this goes to does not recompute it.
|
||||
if (saved.convergence) {
|
||||
toast.show(
|
||||
|
||||
@@ -116,8 +116,9 @@ function truncate(text: string | null, max = 120): string {
|
||||
return text.length > max ? text.slice(0, max) + "..." : text;
|
||||
}
|
||||
|
||||
// A card is a glance, not a report. Roundtable had ~35 milestones and its tile
|
||||
// ran several viewport-heights tall, which made the grid unreadable (#2391).
|
||||
// A card is a glance, not a report. A project with dozens of milestones would
|
||||
// otherwise run its tile several viewport-heights tall and make the grid
|
||||
// unreadable.
|
||||
const MAX_MILESTONE_BARS = 10;
|
||||
|
||||
interface MilestoneBar extends MilestoneSummary {
|
||||
|
||||
@@ -977,8 +977,6 @@ onMounted(async () => {
|
||||
// Load user profile
|
||||
await loadProfile();
|
||||
|
||||
// Load journal config (locations, temp unit; prep/closeout UI removed in Phase 7)
|
||||
|
||||
// Check SearXNG status
|
||||
try {
|
||||
const sr = await apiGet<{ configured: boolean; searxng_url: string }>("/api/settings/search");
|
||||
|
||||
@@ -35,7 +35,7 @@ function locParts(loc: { repo: string; path: string; symbol: string }): string[]
|
||||
return [loc.repo, loc.path, loc.symbol].filter((p) => p && p.trim());
|
||||
}
|
||||
|
||||
// Un-merge (#2165)
|
||||
// Un-merge
|
||||
const unmerging = ref<number | null>(null);
|
||||
|
||||
/** Only entries carrying what the source contributed can be reversed exactly.
|
||||
|
||||
@@ -119,9 +119,6 @@ async function toggleSubTask(sub: SubTask) {
|
||||
const showPreview = ref(false);
|
||||
const sidebarOpen = ref(true);
|
||||
|
||||
// reconsolidate / isBodyAutoMaintained removed in Phase 8 — the curator
|
||||
// that auto-maintained task bodies is gone, so the body editor is now
|
||||
// always user-controlled.
|
||||
const editorRef = ref<InstanceType<typeof TiptapEditor> | null>(null);
|
||||
const titleRef = ref<HTMLInputElement | null>(null);
|
||||
const tiptapEditor = computed<Editor | null>(() => {
|
||||
|
||||
Reference in New Issue
Block a user