Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .impeccable/critique/src-components-batchscoreboard-svelte.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"target": "src/components/BatchScoreboard.svelte",
"date": "2026-07-10",
"mode": "degraded-single-context",
"reason": "User requested sequential full pipeline; synthesis after detect+source review",
"score": 32,
"max": 40,
"p0": 0,
"p1": 2,
"p2": 3,
"strengths": [
"Clear primary action (Open output)",
"Progressive disclosure for estimate method",
"Local privacy posture explicit"
],
"priorityIssues": [
{"sev": "P1", "id": "hero-metric-risk", "text": "Large number + label pattern can read as SaaS hero-metric if over-decorated; keep restrained"},
{"sev": "P1", "id": "dest-option-count", "text": "Six destination choices is high decision load; optional should stay quiet"},
{"sev": "P2", "id": "secondary-contrast", "text": "Watch text-secondary contrast on tinted surfaces in light mode"},
{"sev": "P2", "id": "popover-density", "text": "Scoreboard + progress list + recent batches can stack tall in tray popover"},
{"sev": "P2", "id": "chip-touch", "text": "Chip min-height 32 below 44px guideline for touch; acceptable for dense tray pointer UI"}
],
"heuristics": {
"visibility_of_status": 3,
"match_system_world": 4,
"user_control": 4,
"consistency": 3,
"error_prevention": 3,
"recognition": 3,
"flexibility": 3,
"aesthetic_minimal": 3,
"error_recovery": 3,
"help": 3
}
}
149 changes: 149 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
name: ParseKit
description: Menu-bar document converter — private, local, native macOS craft
colors:
ink: "#1B1713"
ink-secondary: "#6B5E52"
accent: "#3F3830"
accent-hover: "#322C26"
accent-fg: "#F9F7F2"
surface: "#F7F4EE"
surface-elevated: "#FFFFFF"
border: "#B8A99A"
link: "#5C4A3A"
status-success: "#2F8A4A"
status-error: "#C23B2E"
status-warning: "#C9892A"
dark-bg: "#1C1A17"
dark-ink: "#F5F2EB"
dark-accent: "#E8C99A"
typography:
display:
fontFamily: "Instrument Serif, Georgia, Times New Roman, serif"
fontSize: "1.25rem"
fontWeight: 400
lineHeight: 1.2
letterSpacing: "-0.015em"
body:
fontFamily: "-apple-system, BlinkMacSystemFont, SF Pro Text, Segoe UI, sans-serif"
fontSize: "0.875rem"
fontWeight: 400
lineHeight: 1.4
letterSpacing: "normal"
mono:
fontFamily: "JetBrains Mono, SF Mono, Menlo, monospace"
fontSize: "0.8125rem"
fontWeight: 500
lineHeight: 1.3
letterSpacing: "-0.01em"
label:
fontFamily: "-apple-system, BlinkMacSystemFont, SF Pro Text, Segoe UI, sans-serif"
fontSize: "0.72rem"
fontWeight: 500
lineHeight: 1.25
letterSpacing: "0.01em"
rounded:
sm: "6px"
md: "8px"
lg: "12px"
pill: "999px"
spacing:
xs: "4px"
sm: "8px"
md: "12px"
lg: "16px"
xl: "24px"
components:
button-primary:
backgroundColor: "{colors.accent}"
textColor: "{colors.accent-fg}"
rounded: "{rounded.md}"
padding: "8px 14px"
button-primary-hover:
backgroundColor: "{colors.accent-hover}"
textColor: "{colors.accent-fg}"
button-secondary:
backgroundColor: "transparent"
textColor: "{colors.ink}"
rounded: "{rounded.md}"
padding: "8px 12px"
chip:
backgroundColor: "transparent"
textColor: "{colors.ink}"
rounded: "{rounded.pill}"
padding: "5px 10px"
card:
backgroundColor: "{colors.surface-elevated}"
textColor: "{colors.ink}"
rounded: "{rounded.lg}"
padding: "14px"
---

## Overview

ParseKit is a **product-register** macOS menu-bar tool: design serves conversion, not marketing spectacle. Visual system is **Bone White, Pressed** — warm restrained neutrals, charcoal primary, native SF Pro body, Instrument Serif only for display (app title / about). Motion is short (120–180ms), ease-out, interruptible, reduced-motion aware. Identity lives in craft density and privacy posture, not loud color.

Canonical tokens: `src/index.css` (`:root`, `[data-theme]`, system dark). Brand narrative: `brand.md`. Product brief: `PRODUCT.md`.

## Colors

OKLCH is source of truth in CSS; hex above is sRGB approximation for tooling.

| Role | Light (OKLCH) | Use |
|------|----------------|-----|
| Ink | `oklch(0.18 0.01 50)` | Body text |
| Secondary | `oklch(0.48 0.03 50)` | Hints, labels (keep ≥4.5:1 on surface) |
| Accent | `oklch(0.32 0.03 50)` | Primary buttons, focus |
| Accent FG | `oklch(0.98 0.005 85)` | Text on primary |
| Surface glass | `oklch(0.97 0.01 85)` + blur | Popover material |
| Border | `oklch(0.72 0.02 50 / 0.95)` | Hairlines |
| Success / Error / Warning | status-* tokens | Semantic only |

Dark theme flips ink/surface and warms the accent (`oklch(0.78 0.08 75)`). Prefer **restrained** strategy: neutrals dominate; accent ≤10% of surface.

## Typography

- **UI / body:** system sans (`--font-sans`) — native macOS feel.
- **Display only:** Instrument Serif (`--font-serif`) for app name / about — not for buttons, data, or dense labels.
- **Data / counts:** JetBrains Mono (`--font-mono`), tabular-nums for token counts.
- Scale ratio ~1.15–1.2; display letter-spacing floor **≥ -0.04em** (hero metrics ~-0.03em).
- Prefer weight + size hierarchy over all-caps eyebrows on every section.

## Elevation

Mostly **tonal layering** (secondary-bg, glass) over heavy drop shadows.

- Prefer: 1px border **or** soft shadow ≤8px blur — not both as decoration.
- Popover: glass material + restrained inset highlight.
- Focus: `--focus-ring` translucent accent ring (never remove).

## Components

| Component | Notes |
|-----------|--------|
| **Primary button** | `.run-parse-btn` / accent fill; `:active scale(0.97)` |
| **Secondary button** | Transparent / light border; quieter press scale |
| **Chips** | Pill outline for optional choices (destination) |
| **Scoreboard** | Post-convert result: one hero number, platter stats, progressive disclosure for method |
| **Drop zone** | Dominant affordance for first-run convert |
| **Segmented control** | Period toggle (today / month / lifetime) |
| **Banners** | Error/notice with fly enter; reduced-motion → fade |

States required on interactive: default, hover, focus-visible, active, disabled.

## Do's and Don'ts

**Do**
- Keep conversion path obvious: drop → run → open output.
- Use local metrics language (estimate, privacy line).
- Animate transform/opacity only; honor `prefers-reduced-motion` and `prefers-reduced-transparency`.
- Align new UI to tokens in `src/index.css` before inventing hex.

**Don't**
- Side-stripe accents (`border-left` >1px on cards/callouts).
- Hero-metric SaaS clichés with gradients and confetti.
- Nested cards; identical icon+title+body grids.
- Uppercase tracked kicker on every block.
- `scale(0)` entrances; bounce/elastic easing.
- Pair thick border + wide soft shadow (ghost-card).
- Put Instrument Serif on dense UI chrome.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ More: [skills/parsekit/SKILL.md](skills/parsekit/SKILL.md) · [AGENTS.md](AGENTS

Files, OCR, and conversion never leave your Mac. No telemetry. Network only for optional app updates and first-time OCR language packs.

## Product metrics (local-first)

| Metric | Definition | Storage |
|--------|------------|---------|
| **Activation** | First batch with at least one successful file | `activatedAt` in the Tauri settings store |
| **Tokens saved** | Estimate: raw extract vs cleaned Markdown (~4 chars/token) | On-disk token stats |
| **Today / all-time** | Calendar-day and lifetime sums of token events | Same |
| **Success rate** | Successful vs failed files across the last 20 jobs | `jobOutcomesV1` in the settings store (counts only) |

Stored only on this device. Never uploaded. See [`docs/TASKS.md`](docs/TASKS.md).

## Develop

```bash
Expand Down
24 changes: 24 additions & 0 deletions docs/TASKS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# ParseKit — Flow + metrics tasks

Branch: `feat/flow-metrics-2026-07`
Source: `~/Desktop/parsekit-task-list-plan.md`

| ID | Task | Status | Notes |
|----|------|--------|-------|
| PK-1 | First successful convert as hero of first-run | **Done** | First-run hero on main panel; onboarding points to convert; activation constant |
| PK-2 | Today + all-time token summary scoreboard | **Done** | BatchScoreboard + banner period includes **today** |
| PK-3 | Failure path + success rate | **Done** | Job outcomes (last 20 jobs, local); partial/fail copy on scoreboard |
| PK-4 | Optional destination prompt | **Done** | Soft prompt after first success; skippable; local only |
| PK-5 | Privacy strip on stats surfaces | **Done** | Scoreboard + token panel + first-run copy |
| README | Novice + technical dual sections | **Done** | See README.md |
| Ship | PR against master | Pending | |

## Activation metric

- **Name:** `first_successful_convert_with_token_estimate` (`ACTIVATION_EVENT` in `src/lib/activation.ts`)
- **Rule:** ≥1 successful file in a batch (token estimate recorded for the batch, may be 0)
- **Storage:** `activatedAt` in local Tauri settings store — never uploaded

## Privacy

Token events and job outcome counts stay on this Mac. No file paths or names in aggregate metrics.
45 changes: 45 additions & 0 deletions docs/impeccable/PIPELINE-2026-07-10.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Impeccable pipeline — ParseKit — 2026-07-10

Target: `feat/flow-metrics-2026-07` (BatchScoreboard + first-run + tokens)

## Order run

| # | Command | Result |
|---|---------|--------|
| 1 | **document** | Wrote `DESIGN.md` from tokens + brand |
| 2 | **quieter** | Removed side-tab `border-left: 3px` on `.progress-now`; dropped uppercase kicker; removed ghost-card shadow |
| 3 | **critique** | Snapshot `.impeccable/critique/src-components-batchscoreboard-svelte.json` — ⚠️ single-context (sequential pipeline). Score ~32/40. P1: hero-metric restraint, destination option load |
| 4 | **audit** | See below |
| 5 | **polish** | Token-only colors, mono for numbers, secondary via `--text-secondary`, focus-visible chips |
| 6 | **distill** | Estimate/privacy under details; dest chips quieter |
| 7 | **clarify** | Copy: titles shorter, “Not now”, about estimate |
| 8 | **harden** | Tone states success/warn/fail; fail hint uses status tokens |
| 9 | **onboard** | First-run hero already present; kept purpose-first coach mark |

### Skipped (with reason)

| Command | Why |
|---------|-----|
| init | PRODUCT.md exists |
| craft / shape | Feature already built |
| extract | DESIGN.md just captured; extract later if needed |
| bolder / overdrive / colorize / delight | Product register — would add noise |
| live | Dev server not running |
| adapt | Fixed tray popover width, not multi-breakpoint web |
| animate | Motion already intentional; no decorative pass |
| typeset / layout | Folded into polish |
| optimize | No perf flags from audit |

## Audit health (code-level)

| Dimension | Score | Key finding |
|-----------|-------|-------------|
| Accessibility | 3 | Labels/aria present; chip height 32px (tray OK) |
| Performance | 4 | transform/opacity motion only |
| Theming | 3 | Hard-coded colors removed from scoreboard; rest of app OK |
| Responsive | 3 | Popover density if stack tall |
| Anti-patterns | 3 | Side-tab fixed; residual hero-number pattern is intentional metric |
| **Total** | **16/20** | **Good** |

## Anti-patterns verdict
Not “AI made that” after quieter pass. Remaining risk: large metric number — mitigated with mono type, no gradient, no confetti, progressive disclosure.
Loading
Loading