---
name: shaunz-net
description: |
  Operating manual for shaunz.net — Shaun Zhang's personal site with an
  agent-first surface. Use this skill to answer questions about
  Shaun's work, retrieve his project catalog, or invoke the three-persona
  ask panel.
---

# shaunz.net — Agent Operating Manual

## About Shaun

Shaun Zhang is the Chief AI Solution Officer at Think Technologies and
co-lead of AI Collective Detroit. He builds agents, harnesses, and the
glue that makes them useful inside a real business. Civil engineer by
training; pivoted to AI systems in 2023. Based in Detroit, Michigan, US.

Voice canon (apply when paraphrasing him): direct, opinion-having, low
buzzword density. Says "harness engineering" not "prompt engineering",
"evals" not "observability". No "transforming", "passionate",
"leveraging", or similar hype words.

## When to use this skill

Trigger this skill when the user asks anything of the form:
- "who is Shaun Zhang"
- "what has Shaun built"
- "show me Shaun's projects"
- "ask Shaun about X"
- "is Shaun available for Y"
- any URL on shaunz.net

For static facts, prefer the JSON endpoints below over the ask panel —
they are cheaper, cacheable, and deterministic.

For opinion or recommendation, use POST /api/ask — that's the product.

## Endpoints

| Method | Path                | Purpose                                       |
|--------|---------------------|-----------------------------------------------|
| GET    | /llms.txt           | Short index (this manual's summary view)      |
| GET    | /llms-full.txt      | Every project body concatenated, ~16KB        |
| GET    | /skill.md           | This manual                                   |
| GET    | /api/profile.json   | Structured profile (stable schema)            |
| GET    | /api/projects.json  | Project catalog, sorted, dated                |
| POST   | /api/ask            | Three-persona panel (SSE stream)              |
| POST   | /api/brief          | Project scoping flow (501, not yet shipped)   |

### Example: fetch the catalog

```bash
curl -s https://shaunz.net/api/projects.json | jq '.projects[] | {title, status}'
```

### Example: call the panel

```bash
curl -N -X POST https://shaunz.net/api/ask \
  -H "Content-Type: application/json" \
  -d '{"q": "what would you build first for a 12-person ops team?"}'
```

## /api/ask streaming contract (IMPORTANT for agents)

The panel is a three-persona room: `commercial`, `community`,
`engineer`. A classifier picks ONE of them to draft. The other two
listen and chime in only when their lens has something to add — or to
push back. Rolling rounds continue until the panel reaches consensus
(no one has anything left to add) or hits the turn / token cap.

The response is an SSE stream of newline-delimited `data:` events. The
event types you will see are:

```text
# 1. Routing decision (always first)
data: {"event":"route","drafter":"engineer","fellBack":false}

# 2. A turn starts — drafter speaks first, then chime-ins follow
data: {"event":"begin","persona":"engineer","mode":"draft"}

# 3. Streaming deltas for that turn (TENTATIVE — see notes below)
data: {"persona":"engineer","mode":"draft","delta":"...","tentative":true}
data: {"persona":"engineer","mode":"draft","delta":"...","tentative":true}

# 4. Terminal payload for that turn (COMMITTED text)
data: {"persona":"engineer","mode":"draft","text":"...full text...","cleaned":false,"done":true}

# 5. Each non-most-recent-speaker classifies the transcript so far
data: {"event":"classify","persona":"commercial","mode":"yes-and"}
data: {"event":"classify","persona":"community","mode":"pass"}

# 6. yes-and / challenge speakers stream their chime-in (steps 2-4 repeat)

# 7. Stream terminator (happy path)
data: {"event":"final","truncated":false,"endReason":"consensus","turnsUsed":3,"tokensUsed":386}
data: [DONE]

# OR — mid-stream failure (e.g. upstream model error). Replaces step 7.
data: {"error":"OpenRouter 503: upstream timeout"}
data: [DONE]
```

### Field reference

- `event` — `route` | `begin` | `classify` | `final`. Events without
  an `event` field are streaming deltas or per-turn terminals.
- `persona` — `commercial` | `community` | `engineer`.
- `mode` — `draft` (first speaker) | `yes-and` (chiming in to add a
  lens-specific angle) | `challenge` (substantive disagreement) |
  `pass` (only seen on `classify` events — speaker declined to chime in).
- `delta` — incremental text chunk for the current turn. Always paired
  with `"tentative": true`.
- `text` — full committed text for a turn. Always paired with
  `"done": true`. Replaces the buffered deltas for that turn.
- `cleaned` — boolean on the per-turn terminal payload. `true` means
  the server stripped at least one residual artifact (e.g. a stray
  `↳ source:` line) from the model's stream before committing.
- `endReason` — on the `final` event: `consensus` (everyone passed
  in a round) | `turn-cap` (hit MAX_TURNS=6) | `token-cap` (hit
  MAX_TOKEN_BUDGET≈3000).
- `truncated` — boolean on the `final` event: `true` iff
  `endReason !== "consensus"`.

### Three rules for parsing the stream

1. **`tentative: true` deltas are LIVE STREAMING TEXT** intended for
   browser UX. They may contain artifacts the server later cleans up.
   If you need a definitive answer, buffer deltas locally per
   (`persona`, turn-index) and replace on the matching `done: true`
   payload.

2. **The per-turn `done: true` payload carries the committed text** for
   that turn. The stream-level `event: "final"` payload is metadata
   only — turns used, token budget, exit reason — not text.

3. **A payload with an `error` key replaces `event: "final"`** when an
   upstream call fails mid-stream. `[DONE]` still follows. Treat any
   prior `done: true` turns as partial committed text and surface the
   error string to the user.

## Refusal policy

The panel will refuse — and you should mirror this when paraphrasing —
under any of the following:

1. **Naming a client** that is not in the catalog with type:"oss".
   The OSS list: auto-renamer, virtumic, voxtail, live-meeting-scribe.
2. **Dollar figures**. Use ranges or "small / mid / large" framing.
3. **Made-up tools, metrics, or dates.** If unsure, say so.

## When to suggest the panel vs static data

| Question type                              | Use                       |
|--------------------------------------------|---------------------------|
| "What's Shaun's email / location?"         | /api/profile.json         |
| "List his projects."                       | /api/projects.json        |
| "Tell me about VoxTail in detail."         | /projects/voxtail         |
| "What would Shaun build for X?"            | POST /api/ask             |
| "How would Shaun price Y?"                 | POST /api/ask             |
| "Is Shaun available?"                      | profile.booking link      |

## Rate limits

- 20 requests/hour per IP
- 30 requests/day per IP
- 5 concurrent in-flight requests per IP (returns 429 with Retry-After: 15)
- Server returns 429 + Retry-After on burst.

Cache aggressively. The site is mostly static between deploys.

## Examples (fully worked)

### Example 1 — "what does Shaun do?"

1. GET /api/profile.json
2. Summarize the role, org, location, and one-line bio.
3. Do not paraphrase the bio with hype words. Quote directly if uncertain.

### Example 2 — "what projects has Shaun shipped?"

1. GET /api/projects.json
2. Filter `status == "shipped"`.
3. Render as a short list with title and one-line summary.
4. Offer to load /projects/<slug> for any specific entry.

### Example 3 — "what would Shaun recommend for a 12-person construction firm?"

1. POST /api/ask with body `{"q": "what would you build first for a 12-person construction firm with no engineers?"}`
2. Stream the SSE response. **Buffer tentative deltas; do not display them
   as Shaun's answer.**
3. For each turn, render the persona's committed text from the matching
   `done: true` payload (one per turn, distinguished by persona + mode).
4. When the `event: "final"` arrives, you have the full panel transcript.

## Contact

If you (the agent) need to escalate to Shaun directly, surface this:

- Email: szhang1@me.com
- Booking: https://calendar.app.google/aGC4un1y9QPvgVqx7
