fix: remove redundant code in processing logic
Some checks failed
CI / build-and-test (push) Failing after -31m35s

This commit is contained in:
Hein
2026-04-30 16:04:04 +02:00
parent 537e65ea6d
commit 65715f7ad3
31 changed files with 2691 additions and 61 deletions

View File

@@ -313,6 +313,21 @@ export const api = {
dry_run: input?.dry_run ?? false
})
},
plans: {
list: async (params?: { status?: string; priority?: string; project_id?: string; limit?: number }) => {
const filters: ResolveSpecFilter[] = [];
if (params?.status) filters.push({ column: 'status', operator: 'eq', value: params.status });
if (params?.priority) filters.push({ column: 'priority', operator: 'eq', value: params.priority });
if (params?.project_id) filters.push({ column: 'project_id', operator: 'eq', value: params.project_id });
const rows = await rsReadMany<Omit<import('./types').Plan, 'tags'> & { tags?: unknown }>('plans', {
filters,
limit: params?.limit ?? 500,
sort: [{ column: 'updated_at', direction: 'desc' }]
});
return rows.map((row) => ({ ...row, tags: normalizeTags(row.tags) }));
}
},
stats: async () => {
type StatsThoughtRow = {
metadata?: {

View File

@@ -0,0 +1,197 @@
<script lang="ts">
import { GridlerFull, type GridlerColumn } from "@warkypublic/svelix";
import { GlobalStateStore } from "../../shellState";
import { adminGridTheme } from "../../gridTheme";
import type { Plan } from "../../types";
let selectedPlan = $state<Plan | null>(null);
let gridTotal = $state<number | null>(null);
const plansDataSourceOptions = {
url: "/api/rs",
authToken: GlobalStateStore.getState().session.authToken,
schema: "public",
entity: "plans",
uniqueID: "id",
sort: [{ column: "updated_at", direction: "desc" }],
} as unknown as {
url: string;
authToken?: string;
schema: string;
entity: string;
uniqueID: string;
};
const columns: GridlerColumn[] = [
{ id: "title", title: "Title", dataKey: "title", width: 340 },
{ id: "status", title: "Status", dataKey: "status", width: 120 },
{ id: "priority", title: "Priority", dataKey: "priority", width: 110 },
{ id: "owner", title: "Owner", dataKey: "owner", width: 160 },
{ id: "due_date", title: "Due", dataKey: "due_date", width: 180, format: "datetime" },
{ id: "last_reviewed_at", title: "Reviewed", dataKey: "last_reviewed_at", width: 180, format: "datetime" },
{ id: "updated_at", title: "Updated", dataKey: "updated_at", width: 180, format: "datetime" },
];
function normalizeTags(value: unknown): string[] {
if (Array.isArray(value)) return value.map((t) => String(t).trim()).filter(Boolean);
if (typeof value !== "string" || !value.trim()) return [];
const trimmed = value.trim();
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
return trimmed.slice(1, -1).split(",").map((t) => t.trim().replace(/^"(.*)"$/, "$1")).filter(Boolean);
}
return trimmed.split(",").map((t) => t.trim()).filter(Boolean);
}
function normalizePlan(rowData: Record<string, unknown>): Plan {
return {
id: String(rowData.id ?? ""),
title: typeof rowData.title === "string" ? rowData.title : "",
description: typeof rowData.description === "string" ? rowData.description : "",
status: (typeof rowData.status === "string" ? rowData.status : "draft") as Plan["status"],
priority: (typeof rowData.priority === "string" ? rowData.priority : "medium") as Plan["priority"],
project_id: typeof rowData.project_id === "string" ? rowData.project_id : undefined,
owner: typeof rowData.owner === "string" && rowData.owner ? rowData.owner : undefined,
due_date: typeof rowData.due_date === "string" ? rowData.due_date : undefined,
completed_at: typeof rowData.completed_at === "string" ? rowData.completed_at : undefined,
reviewed_by: typeof rowData.reviewed_by === "string" ? rowData.reviewed_by : undefined,
last_reviewed_at: typeof rowData.last_reviewed_at === "string" ? rowData.last_reviewed_at : undefined,
supersedes_plan_id: typeof rowData.supersedes_plan_id === "string" ? rowData.supersedes_plan_id : undefined,
tags: normalizeTags(rowData.tags),
created_at: String(rowData.created_at ?? ""),
updated_at: String(rowData.updated_at ?? ""),
};
}
function onRowClick(_row: number, rowData: Record<string, unknown> | undefined) {
selectedPlan = rowData ? normalizePlan(rowData) : null;
}
function onGridEvent(
type: string,
_item?: unknown,
_column?: unknown,
_coords?: unknown,
detail?: Record<string, unknown>,
) {
if (type !== "page_loaded" && type !== "load") return;
const total = detail?.total;
if (typeof total === "number") gridTotal = total;
}
function formatDate(value?: string): string {
if (!value) return "—";
return new Date(value).toLocaleString();
}
const statusClasses: Record<string, string> = {
draft: "bg-slate-700/60 text-slate-300",
active: "bg-cyan-900/60 text-cyan-200",
blocked: "bg-amber-900/60 text-amber-200",
completed: "bg-emerald-900/60 text-emerald-200",
cancelled: "bg-slate-800/60 text-slate-500",
superseded: "bg-purple-900/60 text-purple-300",
};
const priorityClasses: Record<string, string> = {
low: "bg-slate-700/60 text-slate-400",
medium: "bg-cyan-900/60 text-cyan-300",
high: "bg-amber-900/60 text-amber-300",
critical: "bg-rose-900/60 text-rose-300",
};
</script>
<div class="space-y-4 w-full">
<div class="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
<div>
<h2 class="text-2xl font-semibold text-white">Plans</h2>
<p class="mt-1 text-sm text-slate-400">
{#if gridTotal === null}
Server-backed grid
{:else}
{gridTotal} plan{gridTotal !== 1 ? "s" : ""}
{/if}
</p>
</div>
</div>
<div class="grid gap-4 xl:grid-cols-[1.6fr_1fr]">
<div class="rounded-2xl border border-white/10 bg-slate-950/30 p-3">
<GridlerFull
{columns}
theme={adminGridTheme}
rowMarkers="number"
height={560}
width="100%"
pageSize={40}
dataSource="resolvespec"
dataSourceOptions={plansDataSourceOptions}
serverSideSearch={true}
searchColumns={["title", "description", "status", "priority", "owner"]}
{onGridEvent}
{onRowClick}
/>
</div>
<aside class="rounded-2xl border border-white/10 bg-slate-900/70 p-4">
<h3 class="text-sm font-semibold text-white">Plan Inspector</h3>
{#if !selectedPlan}
<p class="mt-3 text-sm text-slate-500">
Select a plan row to inspect details and relationships.
</p>
{:else}
<div class="mt-3 space-y-3 text-sm text-slate-300">
<p class="text-base font-semibold text-slate-100">{selectedPlan.title}</p>
<div class="flex flex-wrap gap-2">
<span class={`inline-flex items-center rounded-lg px-2.5 py-0.5 text-xs font-medium ${statusClasses[selectedPlan.status] ?? "bg-slate-700/60 text-slate-300"}`}>
{selectedPlan.status}
</span>
<span class={`inline-flex items-center rounded-lg px-2.5 py-0.5 text-xs font-medium ${priorityClasses[selectedPlan.priority] ?? "bg-slate-700/60 text-slate-300"}`}>
{selectedPlan.priority}
</span>
</div>
<div class="rounded-xl border border-white/10 bg-white/5 p-3 space-y-1">
<p><strong class="text-slate-100">Owner:</strong> {selectedPlan.owner || "—"}</p>
<p><strong class="text-slate-100">Due:</strong> {formatDate(selectedPlan.due_date)}</p>
<p><strong class="text-slate-100">Completed:</strong> {formatDate(selectedPlan.completed_at)}</p>
<p><strong class="text-slate-100">Last reviewed:</strong> {formatDate(selectedPlan.last_reviewed_at)}</p>
<p><strong class="text-slate-100">Reviewed by:</strong> {selectedPlan.reviewed_by || "—"}</p>
<p><strong class="text-slate-100">Created:</strong> {formatDate(selectedPlan.created_at)}</p>
<p><strong class="text-slate-100">Updated:</strong> {formatDate(selectedPlan.updated_at)}</p>
</div>
{#if selectedPlan.description}
<div class="rounded-xl border border-white/10 bg-white/5 p-3">
<p class="text-xs uppercase tracking-[0.18em] text-slate-500">Description</p>
<p class="mt-2 whitespace-pre-wrap text-slate-300">{selectedPlan.description}</p>
</div>
{/if}
{#if selectedPlan.tags.length > 0}
<div class="rounded-xl border border-white/10 bg-white/5 p-3">
<p class="text-xs uppercase tracking-[0.18em] text-slate-500">Tags</p>
<div class="mt-2 flex flex-wrap gap-1.5">
{#each selectedPlan.tags as tag}
<span class="rounded-md bg-white/10 px-2 py-0.5 text-xs text-slate-300">{tag}</span>
{/each}
</div>
</div>
{/if}
{#if selectedPlan.project_id || selectedPlan.supersedes_plan_id}
<div class="rounded-xl border border-white/10 bg-white/5 p-3 space-y-1">
{#if selectedPlan.project_id}
<p><strong class="text-slate-100">Project:</strong> <span class="font-mono text-xs text-slate-400">{selectedPlan.project_id}</span></p>
{/if}
{#if selectedPlan.supersedes_plan_id}
<p><strong class="text-slate-100">Supersedes:</strong> <span class="font-mono text-xs text-slate-400">{selectedPlan.supersedes_plan_id}</span></p>
{/if}
</div>
{/if}
</div>
{/if}
</aside>
</div>
</div>

View File

@@ -3,6 +3,7 @@
import FilesPage from '../files/FilesPage.svelte';
import GuardrailsPage from '../guardrails/GuardrailsPage.svelte';
import LearningsPage from '../learnings/LearningsPage.svelte';
import PlansPage from '../plans/PlansPage.svelte';
import MaintenancePage from '../maintenance/MaintenancePage.svelte';
import DashboardPage from '../dashboard/DashboardPage.svelte';
import ProjectsPage from '../projects/ProjectsPage.svelte';
@@ -41,6 +42,8 @@
<ThoughtsPage />
{:else if currentPage === 'learnings'}
<LearningsPage />
{:else if currentPage === 'plans'}
<PlansPage />
{:else if currentPage === 'skills'}
<SkillsPage />
{:else if currentPage === 'guardrails'}

View File

@@ -16,6 +16,7 @@
{ id: 'projects', label: 'Projects', description: 'Browse and manage projects.' },
{ id: 'thoughts', label: 'Thoughts', description: 'Search and inspect thoughts.' },
{ id: 'learnings', label: 'Learnings', description: 'Curated insights and outcomes.' },
{ id: 'plans', label: 'Plans', description: 'Structured plans and workstreams.' },
{ id: 'skills', label: 'Skills', description: 'Agent skill registry.' },
{ id: 'guardrails', label: 'Guardrails', description: 'Agent guardrail registry.' },
{ id: 'files', label: 'Files', description: 'Stored file inventory.' },

View File

@@ -56,7 +56,7 @@ export type NavItem = {
disabled?: boolean;
};
export type ShellPage = 'dashboard' | 'projects' | 'thoughts' | 'learnings' | 'skills' | 'guardrails' | 'files' | 'maintenance';
export type ShellPage = 'dashboard' | 'projects' | 'thoughts' | 'learnings' | 'plans' | 'skills' | 'guardrails' | 'files' | 'maintenance';
export type Project = {
id: string;
@@ -181,6 +181,24 @@ export type Learning = {
updated_at: string;
};
export type Plan = {
id: string;
title: string;
description: string;
status: 'draft' | 'active' | 'blocked' | 'completed' | 'cancelled' | 'superseded';
priority: 'low' | 'medium' | 'high' | 'critical';
project_id?: string;
owner?: string;
due_date?: string;
completed_at?: string;
reviewed_by?: string;
last_reviewed_at?: string;
supersedes_plan_id?: string;
tags: string[];
created_at: string;
updated_at: string;
};
export type MaintenanceTask = {
id: string;
name: string;

File diff suppressed because one or more lines are too long