18d5f5bfc0720ba0a5b42a630644b4d6cbe0143e
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
18d5f5bfc0 |
Make Piggy part of the product rather than a guest in it
Piggy arrived as a chat panel bolted onto a CRM and then grew a workspace around it. The layout was already right — the audit found the approval card to be the best-designed object in the repo, and the account page's empty panels less finished than anything in the workspace. What was wrong was vocabulary: nobody had written the small things down, so both halves kept inventing them. Piggy was drawn with five different marks — a pig in the dock, a sparkle in the sidebar and again on the model picker, a speech bubble on the Ask buttons, and a stock robot glyph on every assistant message, which is the one people look at most. There is now one mark. The composer, which is the first control in the product since sign-in lands on /piggy, was the only un-adapted shadcn field left: 6px radius against a 12px Send button it sat 8px from. A stat tile had been reinvented six times at three numeral scales, and the same uppercase micro-label existed in five variants, two of them one tab apart in the same rail. There were 63 hand-written font sizes: not a scale, sixty-three opinions. Underneath that, the focus ring was invisible. The global rule used ring-accent, which Tailwind deliberately aliases onto the hover tint, so the ring measured 1.01:1 against the light canvas — no visible focus indicator anywhere in the product, for any accent, in either theme. It is ring-brand now and measures 17:1. The warning, positive and info tones were darkened until each clears 4.5:1 on a card, on inset and on its own chip, and the light canvas moved to 98% so a card lifts without leaning on its shadow. The mobile work is the part worth reading. A landscape phone gave the transcript 28% of the viewport and a keyboard-up phone 16%, against a 45% floor — and the fixed tab bar painted over the composer, covering the safety sentence and half the Send button, because two source comments asserted the bar stood down on short viewports and it never had. Both fixed and measured by hit-testing rather than by screenshot. The composer itself was 64px tall for a blank second line nobody typed, because the auto-resize effect sizes to scrollHeight and scrollHeight counts rows — a CSS height could not win against an inline style, so the attribute was the honest lever. Verified across both themes driven through the app's own control: no horizontal overflow on 15 routes at four viewports, 672 stat values that fit, 297 labels at exactly 11px/500, Escape returning focus to its opener rather than the body on every overlay, and a rejected write no longer reporting "Succeeded" with a green check. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
99d165b5e5 |
Rebuild Piggy's interface, and give the demo book a business to describe
Piggy answered in raw markdown, threw away every tool result it streamed, and fought the reader's scroll on every token. The three surfaces that made it worth having — what it read, how it reasoned, what it cost — were all on the wire and none of them reached the screen. The transcript is now composed of five parts under components/piggy: answers render through streamdown, the container sticks to the bottom without pinning the reader there, tool steps say what they read and link to the record, and each turn carries its model and token count. Three lifecycle bugs went with them: Stop left a permanent spinner, a truncated stream was indistinguishable from thinking, and a failed send destroyed the message it failed to send. Underneath, the inference path grew timeouts, jittered retries on 429 and 5xx, tolerance of the malformed frames a 30B model emits, and an agent_runs row per turn so chat spend is observable. The system prompt now states that a field ending in Cents is cents — without it nemotron renders costPerGpuHourCents: 189 as "$189 per GPU-hour", which is a 100x error on the most scrutinised number in the room. The demo book was arithmetically incoherent: every deal's value contradicted its own allocation revenue by up to 3.6x, nothing had ever closed, no customer had any paper, and the marketplace was empty. Deal value is now derived from the allocation, the book clears 5.3% across five blocks with one deliberately underwater, and the renewal, compliance and agent-provenance machinery finally has rows to act on. A --clear that deleted every obligation, SLA term and capacity request in the database regardless of origin is scoped to the demo's own ids. Around that: accounts have a detail page, ⌘K searches the book, Settings can mint the API keys it always claimed to, and deploy.sh actually ships the agent instead of silently skipping its compose profile. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e12d27edd1 |
Polish every product workflow across desktop and mobile
CI / verify (push) Successful in 3m32s
Reframe each screen around the decisions compute brokers make: sellable capacity, full-cost margin, pipeline movement, contract deadlines, evidence review, staged imports, and controlled agent access. Group the shell by operating domain, strengthen mobile navigation and sheets, add responsive record treatments, and make loading, error, empty, readiness, and retry states explicit. The visual audit exposed sortable table targets and an unnamed file input only after exercising the rendered app, so this commit also pins those accessibility decisions at their actual interaction boundaries. Manrope is self-hosted as a single Latin variable subset to keep the stronger hierarchy without shipping unused font payloads. |
||
|
|
2763531ce4 |
Align shadcn's accent token with what shadcn means by it
CI / verify (push) Successful in 2m53s
shadcn uses `bg-accent` for its SUBTLE surfaces — dropdown item hover, command row selection, ghost and outline button hover, the dialog close affordance. The brand colour in shadcn is `primary`. PIG's Tailwind config mapped `accent` to `--accent`, which is the brand. That inverted the meaning, so every shadcn hover and selection state painted a full-strength brand block. With the monochrome "pig" palette in dark mode the brand is near-white, so a selected command row rendered as a white slab against a near-black sheet. Measured before the change: selected row rgb(250,250,250) on a rgb(9,9,11) body. `accent` now aliases `--accent-subtle` and `accent-foreground` aliases `--accent-fg`, which is what those tokens were created for. The eleven places where PIG's own components wanted a solid brand fill — filled chips, selected card borders, progress bars — move to `primary`, which still resolves to `--accent`. A `brand` alias is added for clarity. After: selected row rgb(39,39,42) in dark and rgb(244,244,245) in light, both a subtle tint above the body; the pipeline's active stage chip stays a solid rgb(250,250,250) fill, unchanged. Found by opening overlays, which earlier screenshot sweeps never did — every route had been checked, but a dropdown or a command palette only misbehaves once it is open. Worth remembering: page-level sweeps do not exercise portals. Typecheck clean, 135 unit tests and e2e green, CSP hash unchanged, 0px horizontal overflow across 12 routes at 393px and 1440px. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
853bde2265 |
Build the agent-native compute CRM platform
CI / verify (push) Successful in 3m6s
|
||
|
|
d154a78d48 |
Polish: per-route titles and a way to sign out
There was no sign-out control anywhere. Easy to miss when you develop permanently signed in, and a stranded feeling for anyone on a shared machine. Clearing the identity provider's session is sufficient — PIG holds no session of its own — and the auth listener returns to sign-in without a reload. A hard redirect follows regardless, so a failed provider call cannot leave a half-signed-out interface. Every route now sets its own document title. A single static title makes browser history and a wall of tabs useless: every entry reads "pig" and nobody can tell the margin view from the pipeline. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
de33a03524 |
Add the web app, seed data, and user-selectable theming
apps/web — React, Vite, Tailwind, shadcn-idiom components. Mobile Safari is a first-class target, not an afterthought: - Two navigation treatments rather than one compromise. A bottom tab bar on phones, because the top of a large phone is out of thumb reach; a persistent sidebar from lg upward, so an iPad in portrait gets it too. - Safe-area insets throughout, so the tab bar clears the home indicator and the last row of a list is actually reachable. - Inputs are pinned to a 16px minimum, which is the correct fix for Safari zooming on focus. user-scalable=no is not used: it breaks pinch-zoom for everyone and recent iOS ignores it anyway. - The pipeline board becomes a stage picker on phones. An eight-column board scrolling horizontally on a 390px screen is technically responsive and practically useless. Theming: users pick an accent and the whole interface re-tints. Accent values live once, in @pig/core, and are written onto the root element at runtime — there is no CSS copy to drift from the TypeScript. Preferences are stored server-side so they follow a person between laptop and phone, mirrored into localStorage only so the pre-paint script can avoid a white flash. Status colours stay fixed regardless of accent: if "at risk" re-tinted to whatever someone picked, the signal would be gone. Seed data is public research, every record carrying a confidence grade and a source URL. No email addresses are seeded or inferred — none are published, and guessing them from a name and a domain is unreliable and rude. Authorship is not promoted to employment: contributors, residency participants and alumni are recorded as what the evidence actually shows, and a name that could not be sourced at all is listed as unresolved rather than invented. Three defects found and fixed by actually running it rather than assuming: 1. The seed was not idempotent. onConflictDoNothing() with no target is a no-op without a matching unique constraint, so a second run duplicated 27 contacts. There is deliberately no unique index on (account, name) — two people at one company can share a name — so idempotency is enforced in the seed instead of by bending the schema. 2. /capacity scrolled sideways on a phone. Grid items default to min-width:auto and `truncate` sets nowrap, so a long title became unshrinkable content and widened the track. Fixed with min-w-0 on every truncating grid child. 3. The idle-capacity alert silently failed to fire at exactly 80% utilisation, losing a float comparison against a 0.2 threshold. Moved to 0.15, which is also a more sensible line for "worth attention". The worked example is tuned to teach rather than to flatter: 70% sold at a 53% markup lands at +6.7% margin with 20% still idle, so both the healthy number and the alert are visible. Drop the sold share to 55% and the same block goes underwater — that sensitivity is the argument for the product. Verified in a real browser at 393px and 1440px, light and dark: zero horizontal overflow on every route, zero console errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |