Commit Graph

5 Commits

Author SHA1 Message Date
karti 8a6601dfce Re-cut the Motion films in landscape, and hold the camera still
CI / verify (push) Successful in 7m14s
CI / publish (push) Has been skipped
THE FORMAT. The first pair were vertical. That was wrong for this product: PIG
is a desktop application, and reframing it 9:16 either shrinks it past reading
or crops away the sidebar and half the table. These are 1920x1080, like the five
already on the page, and the app is filmed at a real 1920 desktop viewport —
the previous renderer set the viewport to 960 and captured at 2x, which produced
a 1920px image of the COLLAPSED layout, because the viewport is what the product
responds to and the scale factor is only how much detail there is to zoom into.

THE CAMERA. It now holds still, and eases in on the thing the narration is
naming, holds, and eases back out — the way Cap zooms toward a click. The first
cut drifted a slow zoom across every shot, which reads as restless rather than
as emphasis and is the thing people mean when they call a screen recording
annoying. Six of fourteen shots move in the customer film; the rest are locked
off. The curve is a smoothstep either side of a hold, written as a function of
the frame number rather than accumulated through zoompan's own `zoom` variable,
which refers to the previous frame and drifts off its endpoints.

Zoom targets are chosen as the SMALLEST element already in frame, not the last
match in document order. That was wrong in a way only a long page shows: the
Halcyon engagement prints the same phrases twice — once in the score note and
again inside the artefact bodies below — so "kappa 0.54" resolved to a paragraph
two and a half thousand pixels below the fold that no amount of scrolling would
reveal, because an ancestor clips it. Preferring what is on screen keeps the
zoom inside the frame the shot chose; preferring the smallest match makes naming
a figure land on the figure rather than on the card around it.

THE SCRIPTS were rewritten from nothing through a judge panel — three
independent angles each, scored on hook, concreteness, ear, tension and ending,
then synthesised and adversarially checked against the running product.

The second film is the one that was asked for: one customer, end to end. Halcyon
Research, scored 52.8 and scope down on the day of first discovery because
nothing had been measured, through legal and scoping and a budget path, to 82.8
and build once the verifier, the baseline and the environment landed — and the
two dimensions that fell inside that same twenty-five point rise. It closes on
the week-two dev split reading under its trajectory, because the honest thing
about that record is that the gate might not be met and it says so before anyone
asks. It runs 68 seconds; a feature tour is 30 and a story is not.
2026-08-19 02:59:29 -07:00
karti 075cd765c5 Stop seeding illustrative Cap rows onto Learn
CI / verify (push) Successful in 7m14s
CI / publish (push) Has been skipped
The `supply` and `demand` concept tracks each carried one `DEMO — ` card
embedding a public recording from the Cap instance at video.karti.ai. Both are
gone, for two reasons that arrived together.

One of the recordings is no longer there. `sjqqvthbfma27bm` now answers 404 on
both `/s/` and `/embed/`, so "DEMO — What a hold takes off the board" promised
six seconds of teaching and played a dead frame. That is precisely the failure
the comment above these rows was written to record the last time it happened,
and it came back — because the footage lives on an instance this repository does
not control, so no amount of care in this file can keep the claim true. Checked
just now rather than assumed: the surviving id, `1rqq9rk4dpp71fd`, still answers
200.

The other reason is judgement. /learn is the page deliberately shown to people
outside this company, and a `DEMO — ` card sitting beside genuine product
footage makes the whole page read as half-placeholder to exactly the audience it
exists to convince. The previous version of this file argued the opposite — that
an empty track hides the shape of the page — and that was the wrong trade. An
empty concept track renders an empty state saying nothing has been published to
it yet, which is true, and true beats furnished.

`seedLearn` and its call site go with them rather than being left as an empty
array behind live machinery. If those tracks get purpose-shot recordings they
belong in `HOSTED_LEARN_MANIFEST`, rendered by `scripts/learn-film.mjs` like the
platform track, and served by PIG itself.

The two rows were also deleted from production directly, matching what
`clear()` does for prefixed learn rows, so the page is correct now rather than
at the next reseed. The underlying Cap recording is untouched.
2026-08-19 02:22:15 -07:00
karti e0473e7258 Cut two vertical Motion films, and write down the pipeline that makes them
CI / verify (push) Successful in 7m23s
CI / publish (push) Has been skipped
THE PIPELINE. The five existing platform videos were cut by an ad-hoc process
that was never committed, so the first time the UI moved nobody could re-shoot
them — which is the same failure `scripts/screenshots.mjs` was written to stop.
`scripts/learn-film.mjs` is that pipeline, and it reuses both of the screenshot
script's hard-won lessons: the appearance preference is stored server-side and
adopted after hydration, so the theme has to be forced by rewriting the profile
response rather than by seeding localStorage; and per-device layout state has to
be pinned or the framing is whatever a human last left behind.

Order is load-bearing. The narration is rendered first and its MEASURED duration
drives every shot length, because a shot list timed by guess leaves the narrator
talking over a frozen frame. Shot durations are then proportional to the words
spoken over them, so the cut lands on the sentence.

Typography is composed in the browser rather than in ffmpeg. The product's face
is Manrope Variable and drawtext would have fallen back to DejaVu, which reads
as a different company. Playwright renders a transparent chrome layer per shot
and ffmpeg only moves pixels.

Detail shots crop to the content column rather than the whole viewport. The
first attempt cropped a box around the element being talked about, which is
narrower than the column, so it sliced the cards either side of centre and the
frame read as broken rather than as close. Width first, height from the aspect.

CRF is 22, not 18. The frame is a static UI with a slow zoom, and 18 spent
3.7 Mbps — a 15 MB download for a video whose whole point is that somebody opens
it on a phone between meetings.

THE STAGE RAIL BUG, which the films found. Every stage label was losing its last
letters — "QUALIFICATIO", "PROCUREMEN" — with no ellipsis to show for it. Three
attempts to fix that by widening the card did nothing, because the card was
never the thing being measured: the LI holding it had `min-w-0` and no
`shrink-0`, so it took its flex share of 88px while the card inside stayed 160,
and every card was overpainted by the next one. The DOM reported no overflow the
whole time, because there wasn't any — the clipping was one level up. `shrink-0`
moves to the LI, where it belongs, and the rail scrolls as it was always meant
to. The labels also wrap rather than truncate now: they are a fixed vocabulary
of eight words we control, and losing a letter is worse than taking a line.

THE FILMS. Two 9:16 clips for the team, narrated in Karti's cloned voice through
Chatterbox at 1.20x and scored with the platform's own ambient bed, ducked and
loudness-normalised so they do not jump against the five already on the page.
Both open dark and switch to light at the midpoint. Shot lists live beside the
narration in `docs/learn-films/`, because a script and its shot list timed
against each other are one object and splitting them is how they drift.
2026-08-19 01:58:35 -07:00
claude 18d5f5bfc0 Make Piggy part of the product rather than a guest in it
CI / verify (push) Successful in 7m10s
CI / publish (push) Has been skipped
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>
2026-08-14 18:22:15 -07:00
claude 99d165b5e5 Rebuild Piggy's interface, and give the demo book a business to describe
CI / verify (push) Successful in 4m57s
CI / publish (push) Has been skipped
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>
2026-08-14 00:34:18 -07:00