Skip to content
Closed
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
Empty file.
115 changes: 115 additions & 0 deletions .cursor/skills/verify-kylecesmat/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
---
name: verify-kylecesmat
description: Prove kylecesmat.com — a static Astro personal site (browser). Use after homepage, IA, or content changes. Preview-only local/preview proof; never production go-live, custom domain, or orange-cloud.
---

# Verify kylecesmat.com

Static Astro 7 personal site. Users hit HTML in a browser. There is no app server, auth, or database. Verification proves a **local preview** of `dist/`. Do not attach `kylecesmat.com`, orange-cloud DNS, or retire GitHub Pages / `gh-pages`.

Hard constraints from Kyle:

1. **No quantitative metrics** in site copy or in assertions that require numbers on the page (no `0→15`, enablement %, MCP counts, latency). The Syntax.fm episode title is a talk name, not a KPI — match the heading text, do not treat it as a metric.
2. **Preview-only.** This skill never deploys, never flips DNS, never hits production as the system under test.
3. **Locked qualitative hero.** Homepage `<h1>` is `Building Agent Experience for enterprise engineering orgs`. If you still see `headlinePick` or `[TODO: headline`, stop and fix copy before driving.

Default origin: `http://127.0.0.1:4321`.

## Launch

Preferred (production-build proof):

```bash
npm install
npm run build
.cursor/skills/verify-kylecesmat/helpers/launch.sh
```

`launch.sh` stops this checkout’s leftover Astro preview **lockfile PID** (`.astro/preview.json`) if present, then runs `./node_modules/.bin/astro preview --host 127.0.0.1 --port ${VERIFY_PORT:-4321}` with `ASTRO_PREVIEW_BACKGROUND=1` so Cursor does not daemonize the server out from under the recorded PID. It writes PID/port to `.cursor/skills/verify-kylecesmat/.run/state` and waits until `/` returns 200 **and** that PID tree owns the port.

Do not `pkill astro`. Do not kill a listener that is not this checkout’s lockfile PID.

Faster loops (not a production-build proof): `npm run dev` on the same host/port, then write the PID you started into `.run/state` yourself. Prefer `launch.sh` for a recorded proof.

Teardown: `.cursor/skills/verify-kylecesmat/helpers/cleanup.sh` (kills the PID in `.run/state` and any listener it spawned). Never `pkill astro` / never kill by process name.

If port `4321` is already bound by a process this run did not start, **refuse**. Set `VERIFY_PORT` to an open port only for an instance **you** launch. Do not drive a foreign preview.

## Doctor

```bash
.cursor/skills/verify-kylecesmat/helpers/doctor.sh
```

Read-only. Passes only when all of these hold:

- Node major version `>= 22` (`node -v`, `.nvmrc` is `22`).
- `.run/state` exists and names a live PID.
- That PID (or a descendant) owns `LISTEN` on `VERIFY_PORT` / `127.0.0.1`.
- `GET /` returns **200**.
- Response body contains the locked hero string: `Building Agent Experience for enterprise engineering orgs`.
- Response body contains the trajectory line: `Coinbase SEM · formerly Formidable`.

Fail if the hero is still a placeholder (`headlinePick`, `[TODO: headline`). Do not assert counts, percents, or latency figures.

## Drive

Harness: **curl** (HTTP + HTML) plus **Google Chrome headless** for screenshots. Prefer visible **link text and headings** (`about`, `writing`, `talks`, `contact`, section `h2`s). Do not target CSS classes as the primary handle.

Stable routes (from `src/pages/`):

| User path | Handle |
| --- | --- |
| Home | `/` — heading `Building Agent Experience for enterprise engineering orgs` |
| About | nav link `about` → `/about` |
| Writing index | nav `writing` or home `all writing` → `/writing` |
| Talks index | nav `talks` or home `all talks` → `/talks` |
| Contact | nav `contact` → `/contact` |
| Now | footer `now` → `/now` (not in primary nav) |
| Archive | footer `archive` → `/archive` (not in primary nav) |

Chrome (this environment): `/usr/bin/google-chrome-stable`. Always pass `--headless=new --disable-gpu --no-sandbox`.

```bash
RUN_ID=homepage-$(date -u +%Y%m%dT%H%M%SZ)
export RUN_ID
.cursor/skills/verify-kylecesmat/helpers/snapshot.sh http://127.0.0.1:${VERIFY_PORT:-4321}/ homepage
```

Read `features/` before driving. For the first proof, drive **homepage-hiring-brief** only.

## Evidence

Directory: `.cursor/skills/verify-kylecesmat/evidence/<run-id>/` (gitignored except `.gitkeep`).

A homepage proof must include (stem `homepage`):

- `homepage.status.txt` — HTTP status for `/` (expect `200`)
- `homepage.html` — response body
- `homepage.aria.txt` — headings, `aria-label` / `aria-current`, and link names
- `homepage.png` — screenshot with the wordmark `Kyle Cesmat` and hero heading visible

Capture the **request** (URL) and the **resulting** HTML/screenshot together. Do not prove via reading `src/` instead of fetching the preview.

Cleanup must **not** delete this directory.

## Cleanup

```bash
.cursor/skills/verify-kylecesmat/helpers/cleanup.sh
```

Stops only the preview PID recorded in `.run/state`. Removes `.run/state`. Leaves `evidence/` untouched. Confirm evidence still exists at the named path after cleanup.

## Helpers

All under `.cursor/skills/verify-kylecesmat/helpers/`. Executable. Invocations:

| Script | Purpose |
| --- | --- |
| `launch.sh` | `npm install` + `npm run build` + `astro preview`; write `.run/state`; wait until `/` answers |
| `doctor.sh` | Node, PID owns port, GET `/` 200, locked hero + trajectory strings |
| `snapshot.sh <url> <stem>` | curl headers/body + Chrome screenshot + heading/link snapshot into `evidence/$RUN_ID/` |
| `cleanup.sh` | kill recorded PID only; keep evidence |

Optional env: `VERIFY_PORT` (default `4321`), `RUN_ID` (snapshot target folder name).
Empty file.
38 changes: 38 additions & 0 deletions .cursor/skills/verify-kylecesmat/features/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# kylecesmat.com verification map

Maintained source for proving user-facing behavior of the static Astro site. Read this index, then the matching feature file.

## Baseline preconditions

- Preview origin `http://127.0.0.1:${VERIFY_PORT:-4321}` started by `helpers/launch.sh` (build then `astro preview`).
- `helpers/doctor.sh` exits 0 (Node >=22, our PID owns the port, `/` is 200, locked qualitative hero is present).
- Never drive a foreign process on 4321.
- Never assert quantitative metrics (org size, enablement %, MCP counts, latency).
- Preview-only: do not treat production `kylecesmat.com` as the system under test.

## Driving conventions

- Start from `/` unless a feature lists another entry.
- Prefer link text and headings over CSS.
- Use `helpers/snapshot.sh` for HTTP + HTML + screenshot + `aria.txt`.
- Chrome: `/usr/bin/google-chrome-stable --headless=new --disable-gpu --no-sandbox`.
- Cleanup with `helpers/cleanup.sh`; evidence stays on disk.

## Proof and skip reporting

- Capture the URL fetched and the resulting status/HTML/screenshot.
- UI proof includes `aria.txt` and a screenshot with `Kyle Cesmat` visible.
- Record `RUN_ID` and feature id on every artifact.
- Do not report a skipped route as verified via a different URL.

## Feature entry contract

Each feature file: H1, one paragraph, then exactly four H2s — `Sub-features`, `How to get to it (user POV)`, `Driving it with helpers`, `Gotchas`.

## Features

- [Homepage hiring brief](./homepage-hiring-brief.md) — hero, trajectory, three qualitative proof blocks, writing/talks, contact.
- [Writing and talks](./writing-and-talks.md) — MDX writing stubs; Syntax.fm episode listed first.
- [About and contact](./about-and-contact.md) — press-kit bio, ways I can help, email and LinkedIn.
- [Now and archive](./now-and-archive.md) — `/now` stub; Formidable work demoted to `/archive`.
- [Build and headers](./build-and-headers.md) — `npm run build`; `dist` has robots, sitemap, `_headers`.
34 changes: 34 additions & 0 deletions .cursor/skills/verify-kylecesmat/features/about-and-contact.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# About and contact

About is the press kit: qualitative bio, ways I can help, and contact links. Contact is a short page with the same email and LinkedIn.

## Sub-features

- `about-bio` shows the qualitative Agent Experience bio (no org-size or enablement figures).
- `about-help` shows `Ways I can help` and the governed-leverage paragraph.
- `about-contact` lists `kylecesmat@gmail.com` and `LinkedIn`.
- `contact-page` repeats email and LinkedIn at `/contact`.

## How to get to it (user POV)

- Primary nav `about`.
- Primary nav `contact`.
- Home section `contact` mailto / LinkedIn (same destinations).

## Driving it with helpers

Preconditions:

- Preview is healthy (`helpers/doctor.sh`).

- **Open about.** Choose nav link `about`. Run `helpers/snapshot.sh http://127.0.0.1:${VERIFY_PORT:-4321}/about about`. Status `200`. Heading `About`. Body includes `Senior Engineering Manager at Coinbase leading Agent Experience` and `Ways I can help`. Fail if the bio contains metric patterns (`0→`, `2,200`, enablement `%`).
- **Confirm help.** Paragraph starting `I help engineering organizations turn AI coding tools into governed, measurable developer leverage`.
- **Confirm about contact.** Links `kylecesmat@gmail.com` and `LinkedIn`.
- **Open contact page.** Choose nav `contact`. Snapshot `/contact`. Status `200`. Same email and LinkedIn link names.
- **Proof.** Screenshots show `about` or `contact` current in nav (`aria-current="page"`).

## Gotchas

- About is MDX (`src/pages/about.mdx`); prove the rendered page, not the source file alone.
- LinkedIn is off-site; proving the href is enough — do not scrape LinkedIn.
- Do not “fix” a failed bio assertion by allowing numbers back onto the page.
33 changes: 33 additions & 0 deletions .cursor/skills/verify-kylecesmat/features/build-and-headers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Build and headers

A production static build writes `dist/` with HTML plus `robots.txt`, sitemap, and Cloudflare `_headers`. CI is build-only (no deploy).

## Sub-features

- `build-ok` — `npm run build` exits 0.
- `robots` — `dist/robots.txt` exists and allows crawlers, pointing at the sitemap.
- `sitemap` — `dist/sitemap-index.xml` exists.
- `headers` — `dist/_headers` exists (security headers for when the hostname is later proxied).

## How to get to it (user POV)

- A visitor never sees this directly. Authors run `npm run build` or CI `Build`. Preview serves the same `dist/` via `astro preview`.

## Driving it with helpers

Preconditions:

- Node >=22. This feature does **not** require a running preview if you only inspect `dist/`. For a served proof, run `helpers/launch.sh` first (it builds).

- **Build.** From repo root: `npm run build`. Exit code `0`. Directory `dist/` exists.
- **Robots.** `test -f dist/robots.txt`. File contains `User-agent: *` and a `Sitemap:` line. Do not require production DNS to resolve.
- **Sitemap.** `test -f dist/sitemap-index.xml`.
- **Headers.** `test -f dist/_headers`. File mentions `X-Content-Type-Options` (and typically `Referrer-Policy`).
- **Optional serve check.** After launch, `curl -sI http://127.0.0.1:${VERIFY_PORT:-4321}/robots.txt` is 200.
- **Proof.** Copy those three files (or `ls -l` output) into `evidence/$RUN_ID/` as `robots.txt`, `sitemap-index.xml`, `_headers`. Cleanup must not delete `evidence/`. Do not delete `dist/` in cleanup (build output is not proof; the copies in `evidence/` are).

## Gotchas

- CI must stay build-only. A passing build is not permission to attach a custom domain or orange-cloud.
- `_headers` apply on Cloudflare when the hostname is proxied; absence of `cf-ray` on today’s live GitHub Pages origin is expected.
- `npm run check` (`astro check`) is useful but not a substitute for the `dist/` artifact checks.
38 changes: 38 additions & 0 deletions .cursor/skills/verify-kylecesmat/features/homepage-hiring-brief.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Homepage hiring brief

The home page is a short hiring brief: locked qualitative headline and subhead, a one-line trajectory, three restrained proof blocks, writing and talks lists, then contact.

## Sub-features

- `hero-lock` shows heading `Building Agent Experience for enterprise engineering orgs` and the qualitative subhead (no `headlinePick` placeholder).
- `trajectory` shows `Coinbase SEM · formerly Formidable`.
- `proof-blocks` shows three headings: `Agent Experience`, `Governed agent platform`, `Platform / App Infra`, each with a qualitative paragraph (no numeric KPIs).
- `writing-tease` lists writing titles and an `all writing` link.
- `talks-tease` lists talks with Syntax.fm first and an `all talks` link.
- `contact-cta` shows `kylecesmat@gmail.com` and `LinkedIn`.

## How to get to it (user POV)

- Open `/` (wordmark `Kyle Cesmat` also returns here).
- Land from any primary nav item by choosing the wordmark.

## Driving it with helpers

Preconditions:

- `helpers/launch.sh` has started preview.
- `helpers/doctor.sh` exits 0.

- **Open home.** Fetch `/`. Run `helpers/snapshot.sh http://127.0.0.1:${VERIFY_PORT:-4321}/ homepage`. `status.txt` is `200`. `aria.txt` and `homepage.html` include the locked `<h1>` text `Building Agent Experience for enterprise engineering orgs`.
- **Confirm trajectory.** In the same HTML, the line `Coinbase SEM · formerly Formidable` is present.
- **Confirm proof.** Headings `Agent Experience`, `Governed agent platform`, and `Platform / App Infra` appear. Bodies are prose. Fail the proof if the HTML contains metric patterns such as `0→`, `%→`, or `MCP servers`.
- **Confirm writing and talks.** A heading `writing` and a link `all writing`; a heading `talks` and a link `all talks`. Syntax.fm talk title is listed (match the visible title string; do not assert a productivity percentage).
- **Confirm contact.** Links named `kylecesmat@gmail.com` (mailto) and `LinkedIn`.
- **Proof.** `homepage.png` shows the wordmark `Kyle Cesmat` and the locked hero heading. Keep artifacts under `evidence/$RUN_ID/`.

## Gotchas

- A 200 with a placeholder hero (`[TODO: headline`) is a failed proof, not a pass.
- Do not use production `https://kylecesmat.com` as the origin.
- Nav labels are lowercase (`about`, `writing`, `talks`, `contact`).
- Proof copy is qualitative. If a future edit reintroduces counts or percents, fail — do not “update the assertion” to match metrics.
32 changes: 32 additions & 0 deletions .cursor/skills/verify-kylecesmat/features/now-and-archive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Now and archive

`/now` is a dated-focus stub. `/archive` holds Formidable-era projects and meetup talks off the primary nav.

## Sub-features

- `now-stub` renders `/now` with heading `now` and placeholder focus/reading/location slots.
- `archive-demote` renders `/archive` with Formidable projects and meetup talks, not linked from primary nav.

## How to get to it (user POV)

- Footer link `now`.
- Footer link `archive`.
- Direct URL `/now` or `/archive`.
- Not listed in the primary nav (`about` / `writing` / `talks` / `contact`).

## Driving it with helpers

Preconditions:

- Preview is healthy (`helpers/doctor.sh`).

- **Confirm demotion.** Snapshot `/`. `aria.txt` primary nav (`aria-label="Primary"`) has `about`, `writing`, `talks`, `contact` and does **not** include `now` or `archive`. Footer does.
- **Open now.** Choose footer `now`. Run `helpers/snapshot.sh http://127.0.0.1:${VERIFY_PORT:-4321}/now now`. Status `200`. Heading `now`.
- **Open archive.** Choose footer `archive`. Snapshot `/archive`. Status `200`. Heading `archive`. Visible copy mentions Formidable and lists project titles (NDA-light).
- **Proof.** Keep HTML + screenshot for both routes plus the homepage nav snapshot that shows they are footer-only.

## Gotchas

- `/currently` redirects to `/` (legacy). Do not treat it as Now.
- Archive titles are historical names, not current hiring metrics.
- Placeholders on `/now` (`[TODO: now`) are expected until that copy is written.
35 changes: 35 additions & 0 deletions .cursor/skills/verify-kylecesmat/features/writing-and-talks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Writing and talks

Writing is a list of MDX pillar stubs. Talks is a separate list with the Syntax.fm episode first, plus notes at `/talks/syntax-fm-944`.

## Sub-features

- `writing-index` lists pillar stubs at `/writing` with titles from MDX frontmatter.
- `writing-piece` opens a stub at `/writing/<id>` (heading is the piece title).
- `talks-index` lists talks at `/talks` with Syntax.fm first.
- `talk-notes` opens `/talks/syntax-fm-944` notes.

## How to get to it (user POV)

- Primary nav `writing` or home link `all writing`.
- Primary nav `talks` or home link `all talks`.
- A writing or talk title on the home page.

## Driving it with helpers

Preconditions:

- Preview is healthy (`helpers/doctor.sh`).
- Drive from `/` unless noted.

- **Open writing.** Choose link `writing` or `all writing`. Run `helpers/snapshot.sh http://127.0.0.1:${VERIFY_PORT:-4321}/writing writing-index`. Status `200`. Heading `writing`. At least one title link is present (stubs may say `draft`).
- **Open a piece.** Follow a writing title link (prefer the visible title, not a CSS selector). Snapshot that URL. Status `200`. The `<h1>` matches the link text.
- **Open talks.** Choose `talks` or `all talks`. Run `helpers/snapshot.sh http://127.0.0.1:${VERIFY_PORT:-4321}/talks talks-index`. Status `200`. First listed title is `Is Coinbase Really Writing Half Their Code With AI?` (episode name, not a metric assertion).
- **Open notes.** Follow that title to `/talks/syntax-fm-944`. Status `200`. Heading matches the talk title.
- **Proof.** Keep HTML, `aria.txt`, and screenshots for index + one piece + talk notes.

## Gotchas

- Writing stubs are placeholders; empty body is OK if the title heading renders.
- Do not require a public Syntax.fm URL; notes are on-site.
- `#944` is the episode id in the venue string — match the visible venue/title, do not parse it as a site KPI.
Loading
Loading