THE LAB / WORK YOU CAN TRY
Curiosity, in action.
A few ways to get a feel for what I build. Play a game, explore an experience, or ask the portfolio a question.
Go on.
Give it a go.
These are real things I’ve built. Pick one and take it for a spin.
You’re in the app. For more room or sign-in, open the full site.
HIRING FOR SOMETHING INTERESTING?
Start with
your questions.
Find the projects and experience relevant to your team. Ask about AI products, interactive development, technical leadership, or a public role description.
Answers link to the work so you can follow up on anything that catches your interest.
Prefer the resume?What would you like to explore?
Ask about projects, technical experience, or a role you’re hiring for. I’ll find relevant examples and link you to the work.
FOR THE TECHNICALLY CURIOUS
I build the workflow, too.
Writing agent skills, designing review loops, and turning lessons from real projects into reusable engineering guidance. Here’s how I work with AI beyond the chat window.
Inside the portfolio guide.
How this AI feature works, its recorded checks, and a small workflow experiment.
Inside the portfolio guide.
How this AI feature works, its recorded checks, and a small workflow experiment.
INSIDE THIS AI FEATURE
From a question to relevant work.
Question
The server accepts a bounded, same-origin request.
Usage budget
Per-network limits and a daily cap bound API usage.
Career record
Only approved public records enter the model context.
Source selection
OpenAI selects structured IDs; the server validates them.
Linked response
The interface displays source text and links to the work.
The model selects relevant records instead of writing new career claims. It has no file access or action tools. If the API fails, keyword retrieval keeps the public work searchable.
TRY THE EDGE CASES
What happens when things go wrong?
Test an unsupported claim, challenge a project attribution, or simulate a service failure. The failure exercise skips the model and demonstrates the fallback.
Put the boundaries to the test.
Ask about projects, technical experience, or a role you’re hiring for. I’ll find relevant examples and link you to the work.
RECORDED GUIDE CHECKS
gpt-4.1-mini · 2026-09-21T03:01:44.141Z · These specific prompts were tested; they are not a guarantee of every possible response.
| Scenario | Response | Check |
|---|---|---|
| personal-ai | answer | Passed |
| game-economy | answer | Passed |
| ignition | answer | Passed |
| ai-evidence | answer | Passed |
| unsupported | insufficient | Passed |
| injection | boundary | Passed |
| ownership | answer | Passed |
| stack | answer | Passed |
Earlier runs and what changed
An earlier model response confused a question about project ownership with a request for restricted information. Separating those response labels fixed the recorded attribution check. Earlier failures remain in the history. After personal projects were added, the broad AI question correctly returned those examples but failed a check that insisted on Crosscheck. That check now asks about Crosscheck explicitly.
- 2026-09-21T01:59:22.905Z: 4/5 passed. ownership: insufficient
- 2026-09-21T02:05:04.216Z: 4/5 passed. ownership: boundary
- 2026-09-21T02:20:48.565Z: 4/5 passed. ownership: error
- 2026-09-21T02:22:21.417Z: 4/5 passed. ownership: error
- 2026-09-21T02:23:35.601Z: 5/5 passed.
- 2026-09-21T03:00:44.463Z: 7/8 passed. ai-evidence: answer
A SMALL WORKFLOW EXPERIMENT
Same task. Clearer instructions.
Two model runs add a dismiss action to the same React fixture. The second also receives explicit reuse, accessibility and styling guidance.
Recorded 2026-09-21T01:59:22.905Z · gpt-4.1-mini · Temperature 0 · One run per condition
Baseline context
import './notice.css';
import { Button } from './Button';
export function Notice({message,onDismiss}:{message:string;onDismiss:()=>void}) {
return <section className="notice">
<p>{message}</p>
<Button className="notice-dismiss" onClick={onDismiss} aria-label="Dismiss notice">×</Button>
</section>;
}
5/6 structural checks · 6.1 seconds · 305 tokens
With explicit guidance
import './notice.css';
import { Button } from './Button';
export function Notice({message,onDismiss}:{message:string;onDismiss:()=>void}) {
return <section className="notice">
<p>{message}</p>
<Button type="button" aria-label="Dismiss notice" className="notice-dismiss" onClick={onDismiss}>×</Button>
</section>;
}
6/6 structural checks · 5.5 seconds · 385 tokens
| Check | Baseline | With guidance |
|---|---|---|
| TSX parses | Passed | Passed |
| Reuses the shared Button | Passed | Passed |
| Dismiss control has a name and safe type | Not met | Passed |
| Connects the supplied callback | Passed | Passed |
| Uses existing styling conventions | Passed | Passed |
| Keeps the existing dependency set | Passed | Passed |
One paired fixture, one run per condition, same model and temperature 0. Structural checks do not establish general skill effectiveness, complete behavior or accessibility conformance. Model output can vary. Guide checks test these exact prompts; they are not a guarantee against all attacks. API usage tokens are observed; dollar cost was not measured.