Skip to content

Instantly share code, notes, and snippets.

@joemocha
Created May 19, 2026 01:47
Show Gist options
  • Select an option

  • Save joemocha/fe552c9601dc58c4f9731982ab0d1f8c to your computer and use it in GitHub Desktop.

Select an option

Save joemocha/fe552c9601dc58c4f9731982ab0d1f8c to your computer and use it in GitHub Desktop.
Block 3 audience materials patch for ai-engineering-workshop-draft
From 87a213729aba7bd86b4cb07a5e6630fdd0cdef19 Mon Sep 17 00:00:00 2001
From: Samuel Obukwelu <onyekwelu@obukwelu.com>
Date: Mon, 18 May 2026 21:35:28 -0400
Subject: [PATCH] Add Block 3 audience materials
---
.pi/extensions/inspect-verify.ts | 111 ++++++++++++++++++
.pi/skills/architecture-verifier/SKILL.md | 54 +++++++++
.pi/skills/performance-verifier/SKILL.md | 53 +++++++++
.pi/skills/project-inspector/SKILL.md | 53 +++++++++
.pi/skills/project-verifier/SKILL.md | 89 ++++++++++++++
AGENTS.md | 47 ++++++++
README.md | 16 ++-
SYSTEM.md | 11 ++
block3/README.md | 57 +++++++++
fixtures/agentic-target-sample/README.md | 59 ++++++++++
.../components/Header.vue | 16 +++
.../composables/useExample.ts | 4 +
fixtures/agentic-target-sample/nuxt.config.ts | 14 +++
fixtures/agentic-target-sample/package.json | 24 ++++
.../agentic-target-sample/pages/about.vue | 14 +++
.../agentic-target-sample/pages/index.vue | 14 +++
16 files changed, 634 insertions(+), 2 deletions(-)
create mode 100644 .pi/extensions/inspect-verify.ts
create mode 100644 .pi/skills/architecture-verifier/SKILL.md
create mode 100644 .pi/skills/performance-verifier/SKILL.md
create mode 100644 .pi/skills/project-inspector/SKILL.md
create mode 100644 .pi/skills/project-verifier/SKILL.md
create mode 100644 AGENTS.md
create mode 100644 SYSTEM.md
create mode 100644 block3/README.md
create mode 100644 fixtures/agentic-target-sample/README.md
create mode 100644 fixtures/agentic-target-sample/components/Header.vue
create mode 100644 fixtures/agentic-target-sample/composables/useExample.ts
create mode 100644 fixtures/agentic-target-sample/nuxt.config.ts
create mode 100644 fixtures/agentic-target-sample/package.json
create mode 100644 fixtures/agentic-target-sample/pages/about.vue
create mode 100644 fixtures/agentic-target-sample/pages/index.vue
diff --git a/.pi/extensions/inspect-verify.ts b/.pi/extensions/inspect-verify.ts
new file mode 100644
index 0000000..9105826
--- /dev/null
+++ b/.pi/extensions/inspect-verify.ts
@@ -0,0 +1,111 @@
+/**
+ * inspect-verify — Block 3 Pi extension
+ *
+ * Implements ARCH-A (sequential pipeline) on top of `project-inspector` and
+ * `project-verifier` skills. Two invocation paths, each with a different
+ * pedagogical purpose:
+ *
+ * 1. `/audit <path>` — explicit slash command. Injects a single coordinated
+ * prompt that asks the agent to run inspector then verifier in one turn.
+ * Works in BOTH interactive and non-interactive (-p / --print) modes.
+ * This is the primary, reliable path attendees install and use.
+ *
+ * 2. `agent_end` listener — when a turn ends and the output looks like a
+ * project-inspector structural briefing (JSON with `"architecture"` and
+ * `"entry_points"`), the extension calls `sendUserMessage` to queue a
+ * verifier follow-up. Works in INTERACTIVE mode only — `-p` mode exits
+ * after the first `agent_end` and ignores queued messages. The ambient
+ * lesson: once the pattern is wired, the system catches itself without
+ * the user remembering to invoke the verifier by name.
+ *
+ * Pedagogical thesis: a working engineer composes skills into self-checking
+ * systems instead of running each skill by hand. Inspector finds architecture;
+ * Verifier flags supply-chain risk; the extension wires them together. No
+ * single skill catches everything — that's why we compose.
+ */
+
+import type {
+ AgentMessage,
+ ExtensionAPI,
+} from "@earendil-works/pi-coding-agent";
+
+const VERIFIER_FOLLOWUP_PROMPT =
+ "The previous response looks like a project-inspector structural briefing. " +
+ "Now run the project-verifier skill on the same target. Read the " +
+ "dependency manifest (package.json, pyproject.toml, go.mod, etc.) of the " +
+ "repository you just inspected, identify pinned exact versions, and use web " +
+ "search to look up known CVE / GHSA advisories per pinned version. Emit the " +
+ "verifier's JSON report — do not produce another structural briefing.";
+
+const AUDIT_COMMAND_PROMPT = (target: string) =>
+ `Audit the repository at \`${target}\`. ` +
+ `Step 1 — run the project-inspector skill: produce a structural briefing in the inspector's JSON shape. ` +
+ `Step 2 — run the project-verifier skill on the same target: read the dependency manifest, identify pinned versions, look up CVE / GHSA advisories per pinned version, emit the verifier's JSON shape. ` +
+ `Return both JSON outputs in order, separated by a "---" line.`;
+
+/**
+ * Extract plain text from an assistant message's content blocks.
+ * AssistantMessage.content is (TextContent | ThinkingContent | ToolCall)[].
+ */
+function assistantText(message: AgentMessage): string {
+ if (message.role !== "assistant") return "";
+ const content = message.content;
+ if (typeof content === "string") return content;
+ if (!Array.isArray(content)) return "";
+ return content
+ .filter((block: any) => block && block.type === "text")
+ .map((block: any) => (typeof block.text === "string" ? block.text : ""))
+ .join("\n");
+}
+
+/**
+ * Heuristic: does the text look like a project-inspector output?
+ * Matches the inspector's documented JSON schema.
+ */
+function looksLikeInspectorBriefing(text: string): boolean {
+ return (
+ text.includes('"architecture"') &&
+ text.includes('"entry_points"') &&
+ // Quick exclusion: don't re-fire on verifier output
+ !text.includes('"lens"') &&
+ !text.includes('"findings"') &&
+ !text.includes('"missed_by_structural_briefing"')
+ );
+}
+
+export default function (pi: ExtensionAPI) {
+ // De-dupe: only fire the verifier once per distinct inspector output within
+ // a single session. The fingerprint is the first ~200 chars of the output;
+ // good enough for one session's worth of turns.
+ const firedFingerprints = new Set<string>();
+
+ pi.on("agent_end", async (event) => {
+ const lastAssistant = [...event.messages]
+ .reverse()
+ .find((m: AgentMessage) => m.role === "assistant");
+ if (!lastAssistant) return;
+
+ const text = assistantText(lastAssistant);
+ if (!looksLikeInspectorBriefing(text)) return;
+
+ const fingerprint = text.slice(0, 200);
+ if (firedFingerprints.has(fingerprint)) return;
+ firedFingerprints.add(fingerprint);
+
+ // Inject the verifier follow-up. `deliverAs: "followUp"` queues this for
+ // the next turn so it doesn't fight an in-flight stream.
+ pi.sendUserMessage(VERIFIER_FOLLOWUP_PROMPT, { deliverAs: "followUp" });
+ });
+
+ // Explicit, loop-safe path: `/audit <target>` triggers inspector + verifier
+ // in a single coordinated prompt. Useful when the auto-detect heuristic
+ // misses or when the user wants the pipeline by name.
+ pi.registerCommand("audit", {
+ description:
+ "Run project-inspector then project-verifier on the given repository path.",
+ handler: async (args, _ctx) => {
+ const target = args.trim() || ".";
+ pi.sendUserMessage(AUDIT_COMMAND_PROMPT(target));
+ },
+ });
+}
diff --git a/.pi/skills/architecture-verifier/SKILL.md b/.pi/skills/architecture-verifier/SKILL.md
new file mode 100644
index 0000000..713a636
--- /dev/null
+++ b/.pi/skills/architecture-verifier/SKILL.md
@@ -0,0 +1,54 @@
+---
+name: architecture-verifier
+description: Audit a codebase against architectural and structural quality concerns that a feature-focused briefing misses. Trigger when the user asks for an architecture review, structural critique, design audit, or wants to verify a project briefing against design-quality concerns.
+---
+
+# Architecture Verifier
+
+You are a staff-level architect reviewing a codebase for structural and design-quality concerns that a feature-focused inspector typically misses. Apply the **architecture lens**: coupling, layering, module boundaries, naming consistency, separation of concerns, and the structural debt that compounds as a system grows.
+
+## When you run
+
+You run alongside other verifiers (security, performance) as part of a multi-lens audit composed by a deliberator agent. Your output is one slice of a composed verification report.
+
+You may also run standalone when a user asks to architecturally review a codebase.
+
+## Process
+
+1. **Map the module boundaries.** Identify directories that represent layers (e.g., `pages/` vs `components/` vs `composables/` vs `server/`). Note whether boundaries are respected or whether code crosses them inappropriately.
+2. **Check coupling.** Sample a few entry points; trace their imports. Note tight coupling, circular references, or modules that "know too much" about their callers.
+3. **Naming + conventions.** Check whether names communicate purpose at the file, function, and module level. Flag inconsistencies (e.g., camelCase mixed with kebab-case in similar-purpose files).
+4. **Missing abstractions.** Look for repeated patterns that should be extracted (3+ near-duplicate handlers, recurring fetch-then-transform shapes, etc.).
+5. **Premature abstractions.** Look for the inverse: indirection that doesn't earn its keep — single-impl interfaces, factories that wrap one constructor, config layers nobody configures.
+6. **Test architecture.** If tests exist, note whether they exercise behavior or implementation. If they don't, flag the absence as architectural risk.
+7. **Score severity.** For each finding: severity (critical / high / moderate / low), one-sentence description, one-sentence recommendation.
+
+## Output format
+
+Return **only** valid JSON in the following shape — no prose before or after the JSON block:
+
+```json
+{
+ "verified": false,
+ "target": "<path>",
+ "lens": "architecture",
+ "findings": [
+ {
+ "concern": "<short label>",
+ "severity": "critical | high | moderate | low",
+ "summary": "<one sentence>",
+ "recommendation": "<one sentence>"
+ }
+ ],
+ "recommendation": "<2–3 sentence summary of architectural posture>"
+}
+```
+
+Set `verified: true` only when there are zero findings of severity `high` or `critical`.
+
+## Constraints
+
+- **Be specific.** Generic findings ("could be more modular") help no one. Cite file paths or directory names.
+- **Honest scoping.** A 7-file fixture has architectural choices but not architectural problems at scale. Don't manufacture findings to look thorough. If the project is genuinely clean, say so.
+- **One lens only.** This skill is architecture-focused. Don't comment on security, performance, dependencies, or test coverage outside the architecture-relevant slice. The composed audit covers those concerns through other verifiers.
+- **No fabrication.** Only reference patterns you can verify by reading the code.
diff --git a/.pi/skills/performance-verifier/SKILL.md b/.pi/skills/performance-verifier/SKILL.md
new file mode 100644
index 0000000..75b6389
--- /dev/null
+++ b/.pi/skills/performance-verifier/SKILL.md
@@ -0,0 +1,53 @@
+---
+name: performance-verifier
+description: Audit a codebase for performance and bundle-hygiene concerns that a structural briefing does not surface. Trigger when the user asks for a performance review, bundle audit, runtime cost analysis, or wants to verify a project briefing against build/runtime performance concerns.
+---
+
+# Performance Verifier
+
+You are a senior engineer reviewing a codebase for performance and bundle-hygiene concerns that a structural inspector typically misses. Apply the **performance lens**: bundle weight, dependency cost, runtime hot paths, render efficiency in framework code (Vue/Nuxt/React), and the operational performance debt that compounds in production.
+
+## When you run
+
+You run alongside other verifiers (security, architecture) as part of a multi-lens audit composed by a deliberator agent. Your output is one slice of a composed verification report.
+
+You may also run standalone when a user asks to performance-review a codebase.
+
+## Process
+
+1. **Read the dependency manifest.** Identify heavyweight deps (Lodash full import, Moment, large UI libs, AWS SDK monoliths). Note tree-shakable vs not.
+2. **Check the bundler config.** For Vite / webpack / Nuxt / Next, look for: missing code-splitting boundaries, large `manualChunks` opportunities missed, source maps shipped to production, devtools left enabled.
+3. **Sample a hot path.** For a framework like Nuxt/Vue, inspect a representative page. Look for: synchronous waterfalls in `setup()`, unbounded `watch` chains, unkeyed `v-for` over large arrays, deep reactivity where shallow would do.
+4. **Asset hygiene.** Note images > 200KB, unbounded fonts, CDN-vs-local mismatches in obvious places.
+5. **Build-time cost.** Note signals of slow builds: large `tsconfig` includes, missing `paths` aliases, `node_modules` directly imported from source.
+6. **Score severity.** For each finding: severity (critical / high / moderate / low), one-sentence description, one-sentence recommendation.
+
+## Output format
+
+Return **only** valid JSON in the following shape — no prose before or after the JSON block:
+
+```json
+{
+ "verified": false,
+ "target": "<path>",
+ "lens": "performance",
+ "findings": [
+ {
+ "concern": "<short label>",
+ "severity": "critical | high | moderate | low",
+ "summary": "<one sentence>",
+ "recommendation": "<one sentence>"
+ }
+ ],
+ "recommendation": "<2–3 sentence summary of performance posture>"
+}
+```
+
+Set `verified: true` only when there are zero findings of severity `high` or `critical`.
+
+## Constraints
+
+- **Be quantitative when possible.** "Lodash full import" → cite the file. "Large asset" → estimate the kB. Vague findings degrade the audit.
+- **Workshop-fixture awareness.** Small fixtures (<10 files) won't have many real performance findings. Don't manufacture issues to look thorough — say the project is performance-clean if it is.
+- **One lens only.** Performance-focused. Don't comment on security, architecture, dependencies' CVEs, or test coverage outside the performance-relevant slice.
+- **No fabrication.** Only reference patterns you can verify by reading the code.
diff --git a/.pi/skills/project-inspector/SKILL.md b/.pi/skills/project-inspector/SKILL.md
new file mode 100644
index 0000000..044a595
--- /dev/null
+++ b/.pi/skills/project-inspector/SKILL.md
@@ -0,0 +1,53 @@
+---
+name: project-inspector
+description: Inspect any code repository and produce a structured architectural briefing. Trigger whenever the user asks to understand, summarize, onboard to, get a briefing on, or describe a codebase, even if they do not literally say "inspect." Outputs valid JSON with architecture, entry_points, data_flow, key_dependencies, and test_patterns fields.
+---
+
+# Project Inspector
+
+You are a senior software engineer onboarding to a new project. Your job is to produce a structured, factual briefing of the codebase you're shown so that another senior engineer can navigate it cold.
+
+## Process (think step-by-step)
+
+1. **Scan the directory structure.** Note the top-level layout, any monorepo or workspace boundaries, and any unusual organization.
+2. **Identify the framework.** Read `package.json`, `pyproject.toml`, `go.mod`, or equivalent. Note the runtime, the framework, and the major libraries. If multiple frameworks are present, report them all.
+3. **Locate the entry points.** Identify where execution begins — main file(s), route registration, top-level components. List at least three when present.
+4. **Trace data flow.** For the most prominent entry point, follow the imports and call paths far enough to understand how a single request or invocation moves through the code.
+5. **Note test patterns.** Identify the test framework, where tests live, and a representative example. If tests are missing, say so.
+6. **Summarize.** Produce the structured output below.
+
+## Output format
+
+Return **only** valid JSON in the following shape — no prose before or after the JSON block:
+
+```json
+{
+ "architecture": "<2–4 sentence summary of the overall shape and framework>",
+ "entry_points": ["<file path>", "<file path>", "<file path>"],
+ "data_flow": "<2–3 sentence trace of how a request/invocation moves through the most prominent entry point>",
+ "key_dependencies": ["<package name>", "<package name>", "..."],
+ "test_patterns": "<1–2 sentence note on test framework, location, conventions; or 'No tests detected.'>"
+}
+```
+
+## Example
+
+For a small Express app:
+
+```json
+{
+ "architecture": "Node.js HTTP service built on Express 4. Single-package layout with handler functions in src/routes/, business logic in src/services/, and a thin server.ts entry point.",
+ "entry_points": ["src/server.ts", "src/routes/index.ts", "src/routes/users.ts"],
+ "data_flow": "HTTP request enters src/server.ts which mounts route handlers from src/routes/. Each route handler validates input and delegates to a service in src/services/. Services use a shared db client from src/db.ts.",
+ "key_dependencies": ["express", "zod", "pg", "pino"],
+ "test_patterns": "Vitest tests colocated next to source files as *.test.ts. One example: src/services/users.test.ts."
+}
+```
+
+## Constraints
+
+- **Never invent file paths.** Only reference files you can observe in the input. If a path is unclear, omit it rather than guess.
+- **Never echo secrets.** If the codebase contains API keys, access tokens, AWS credentials, or other secret-shaped values (e.g., strings matching `sk-`, `AKIA`, JWT shapes), **do not include those values in your output**. Note that secrets are present but redact the values themselves.
+- **Be honest about ambiguity.** If the framework is unclear (e.g., a Vite + React project with no meta-framework), report exactly what you see. Do not assert a framework that isn't there.
+- **If the input is not a codebase** — e.g., the user asks an unrelated question — refuse politely and ask for a codebase to inspect. Do not produce a briefing for non-repo input.
+- **If the codebase is empty or too small to analyze meaningfully**, return the JSON with appropriate fields noting the limitation rather than fabricating content.
diff --git a/.pi/skills/project-verifier/SKILL.md b/.pi/skills/project-verifier/SKILL.md
new file mode 100644
index 0000000..6d5a780
--- /dev/null
+++ b/.pi/skills/project-verifier/SKILL.md
@@ -0,0 +1,89 @@
+---
+name: project-verifier
+description: Audit a codebase against the security and supply-chain risks that a structural briefing misses. Trigger whenever the user asks to verify, audit, double-check, or second-opinion a project briefing, or asks about CVEs, vulnerable dependencies, security posture, or supply-chain risk in a repo. Especially trigger when a project-inspector briefing has just been produced.
+---
+
+# Project Verifier
+
+You are a security-aware verifier auditing a codebase against risks that a structural briefing does not cover. Your job is to apply a **different lens** to the same input the structural inspector saw — the lens of pinned versions, known advisories, and supply-chain risk — and produce a verification report that flags what the structural briefing missed.
+
+## When you run
+
+You run after a structural inspector (e.g., `project-inspector`) has produced an architectural briefing of a target repository. Your input is the target repository path. Your output is a verification report.
+
+You may also run standalone when a user asks to audit a repository for security issues.
+
+## Process (think step-by-step)
+
+1. **Locate the dependency manifest.** Read `package.json`, `pyproject.toml`, `go.mod`, `Cargo.toml`, or equivalent from the target repo. If none is found, report that and exit.
+2. **Extract pinned versions.** For each declared dependency, record its name and its version constraint. Note which are pinned to **exact** versions (no `^`, `~`, or range operators) vs. which are floating.
+3. **Look up known advisories.** For each pinned dependency, use web search / web grounding to look up known CVE advisories, security bulletins, or GitHub Security Advisories (GHSA) for that exact version. Prefer authoritative sources: NVD, GitHub Security Advisories, npm advisory database, Snyk vuln DB.
+4. **Cross-reference with `npm audit`** when available. If the target repo has a `package-lock.json` or you can run `npm audit --package-lock-only --json` against it, capture that output and reconcile against your web-grounded findings.
+5. **Score severity.** For each finding, capture: package name, pinned version, CVE/GHSA ID, severity (critical/high/moderate/low), one-sentence summary, and a remediation hint (typically: the patched version range).
+6. **Disagreement check.** If a structural-briefing input is provided (e.g., the output of `project-inspector`), explicitly note which of your findings the structural briefing did NOT mention. This is the verifier's primary value — surfacing what the prior agent missed.
+7. **Emit the report.**
+
+## Output format
+
+Return **only** valid JSON in the following shape — no prose before or after the JSON block:
+
+```json
+{
+ "verified": false,
+ "target": "<absolute or relative path to the audited repo>",
+ "lens": "security / supply-chain",
+ "manifest": "<path to dependency manifest read>",
+ "findings": [
+ {
+ "package": "<name>",
+ "pinned": "<exact version>",
+ "advisory": "<CVE-YYYY-NNNNN or GHSA-xxxx>",
+ "severity": "critical | high | moderate | low",
+ "summary": "<one sentence>",
+ "remediation": "<patched version or version range>"
+ }
+ ],
+ "missed_by_structural_briefing": ["<package name>", "..."],
+ "recommendation": "<2–3 sentence summary of risk posture and what to do next>"
+}
+```
+
+Set `verified: true` only when there are zero findings of severity `high` or `critical`. Otherwise `verified: false`.
+
+## Example output (illustrative)
+
+```json
+{
+ "verified": false,
+ "target": "fixtures/agentic-target-sample/",
+ "lens": "security / supply-chain",
+ "manifest": "fixtures/agentic-target-sample/package.json",
+ "findings": [
+ {
+ "package": "axios",
+ "pinned": "0.21.0",
+ "advisory": "CVE-2020-28168",
+ "severity": "high",
+ "summary": "Server-Side Request Forgery via maliciously-crafted URLs in axios <0.21.1.",
+ "remediation": "Upgrade to axios >=0.21.1"
+ }
+ ],
+ "missed_by_structural_briefing": ["axios", "lodash", "minimist", "serialize-javascript"],
+ "recommendation": "Four pinned dependencies have public high/critical advisories. The structural briefing identified the package names but did not flag the version-bound security exposure. Upgrade or pin to the indicated remediation ranges before shipping."
+}
+```
+
+## Constraints
+
+- **Never fabricate CVEs.** If you cannot find a verifiable advisory for a pinned version, omit it rather than guess. It is better to under-report than to fabricate.
+- **Cite the advisory ID.** Every finding must reference a real, lookup-able advisory ID (CVE or GHSA). If no ID is available, do not include the finding.
+- **Pinned-exact-versions are the focus.** Range-constrained deps (`^1.2.3`, `~4.5.6`) are usually resolved to the latest patched version by the package manager; report them only if the explicitly-allowed range includes vulnerable versions and there's no patched version within range.
+- **Be honest about limits.** If your web search is rate-limited, unavailable, or returns inconclusive results for a pinned version, say so in the recommendation field rather than asserting "no findings."
+- **Do not echo secrets.** If the dependency manifest or related files contain API keys, tokens, or credentials, do not include those values in your output. This skill audits dependencies, not secret-handling.
+- **Do not modify the target repo.** This skill is read-only with respect to the target.
+
+## Composition note (for the workshop)
+
+This skill is half of a composed pipeline. The other half is `project-inspector`, which produces a structural briefing. Run them together — either by chaining manually (`/inspect`, then `/verify`) or via the `inspect-verify` extension (`.pi/extensions/inspect-verify.ts`), which triggers this skill automatically after an inspector run.
+
+The pedagogical point: *no single skill catches everything.* The Inspector's spec doesn't ask for security posture. The Verifier's spec doesn't ask for architecture. Composed, they cover what either alone would miss. That's agentic engineering at the workflow altitude.
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..9494243
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,47 @@
+# AGENTS.md — AI Engineering Workshop
+
+> Project instructions loaded automatically by Pi (`pi.dev`) at session start. Pi reads `AGENTS.md` from `~/.pi/agent/`, every parent directory of the cwd, and the cwd itself — and concatenates them in that order. This file is the **project-local layer**: everything specific to this workshop repo lives here.
+
+## What this repo is
+
+Workshop materials for *AI Engineering: From Prompt Architecture to Production Infrastructure* — VueConf US 2026, Atlanta, 2026-05-19. Four blocks (see [README.md](README.md)). Block 3 is the Pi / agentic-engineering block; the `.pi/` directory below holds its skills + extensions.
+
+## Where things live
+
+| Path | What |
+|------|------|
+| `.pi/skills/project-inspector/` | Block 2 artifact, ported into Pi for Block 3 |
+| `.pi/skills/project-verifier/` | Block 3 security/CVE lens — primary lab skill |
+| `.pi/skills/architecture-verifier/` | Block 3 showcase stub (architectural critique lens) |
+| `.pi/skills/performance-verifier/` | Block 3 showcase stub (performance/bundle lens) |
+| `.pi/extensions/inspect-verify.ts` | Block 3 extension — wires inspector → verifier; registers `/audit` |
+| `fixtures/agentic-target-sample/` | Block 3 dramatic-failure target — Nuxt-shaped, vulnerable deps planted |
+| `fixtures/{nuxt,monorepo,vite-react,leaky-secret}-sample/` | Block 2 eval fixtures |
+| `prompts/project-inspector-v5.txt` | Canonical Block 1 fallback prompt |
+| `evals/` | Block 2 eval suite (with planted non-discriminating assertion) |
+| `bifrost/`, `nuxt-app/` | Block 4 infrastructure + Vue/Nuxt integration target |
+
+## Conventions when operating in this repo
+
+- **Skills are the unit of agent capability.** A new lens (security / architecture / performance / etc.) lives as a new skill under `.pi/skills/<name>/`. Don't bury new behavior in extension code if it could be a skill — extensions wire skills; skills implement reasoning.
+- **Extensions wire, skills reason.** Extensions hook into events and dispatch; they don't contain prompt logic. If you find yourself writing a prompt inside an extension, that's a skill in disguise.
+- **One JSON shape per verifier.** All verifier skills (`*-verifier`) emit `{verified, target, lens, findings[], recommendation}`. Don't drift the envelope — the deliberator pattern in Block 3's showcase relies on consistent shape.
+- **Never echo secrets.** This repo contains `fixtures/leaky-secret-sample/` with planted fake API keys for Block 2 adversarial testing. They are documented test patterns (`sk-test-*`, `AKIAEXAMPLE*`) but no skill should reproduce them in output regardless.
+- **Honest scoping.** On the small workshop fixtures (≤10 files each), don't manufacture findings to look thorough. A clean lens is a valid result.
+
+## What NOT to load into context
+
+Pi auto-discovers skills and extensions. Be deliberate about what runs:
+
+- `node_modules/`, `.nuxt/`, `.output/` — generated; never load
+- `bifrost/data/` (if present at workshop time) — runtime state; never load
+- `nuxt-app/` during Block 3 — out of scope; loading it inflates context unnecessarily
+- Session history under `~/.pi/agent/sessions/` — Pi manages this; don't reference
+
+If running `--tools read,bash,grep,find,ls` (the typical Block 3 toolset), the `find` / `grep` defaults will naturally skip these — but if you broaden tools, add explicit exclusions.
+
+## Workshop-day operational notes
+
+- **Default provider:** `pi` defaults to Google (Gemini). Gemini's web grounding is what makes the security-CVE lookup in `project-verifier` work without extra wiring.
+- **Print mode (`-p`) caveat:** `--print` exits after one `agent_end`. The extension's auto-fire on `agent_end` only lights up in interactive mode. The `/audit` slash command works in both modes — use it when scripting.
+- **Pre-staged extensions:** `.pi/extensions/inspect-verify.ts` is auto-loaded by Pi when run from the repo root. Override with `-e <path>` if loading from elsewhere.
diff --git a/README.md b/README.md
index 8d69258..d4d1d49 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ Workshop materials for four blocks of hands-on AI engineering:
|---|---|---|
| **1** | Foundations | Write a v5 prompt for the Project Inspector running example |
| **2** | Build & Eval a Skill | Promote the prompt to a working skill via the `skill-creator` plugin; run the eval loop; learn to *evaluate the eval* |
-| **3** | Vibe Coding → Agentic Engineering | (Instructor's separate materials) |
+| **3** | Vibe Coding → Agentic Engineering | Port your Block 2 skill into Pi; compose it with a verifier skill and a hook extension; watch the system catch what one skill alone misses |
| **4** | AI Gateway (Production) | Configure Bifrost; tour the production-gateway surface; integrate with a Vue/Nuxt app |
## Quick start
@@ -34,17 +34,26 @@ See the [Prerequisites](#) (handed out separately). Minimum:
- Two LLM provider API keys with $5+ credit each (Anthropic + OpenAI recommended)
- An AI coding CLI installed (Claude Code, Codex CLI, or Gemini CLI)
- The `skill-creator` plugin installed via the Anthropic plugin marketplace
+- **Pi installed** (`pi.dev`) — `bun install -g @earendil-works/pi-coding-agent`, then verify `pi --version` returns cleanly. (Block 3 runtime.)
+- **A second CLI for verification** — Gemini CLI authenticated against your Google account (primary) or Codex CLI against your OpenAI key (alternative). Used by Block 3's verifier skill.
## Repository layout
```
ai-engineering-workshop/
+├── AGENTS.md # Block 3: project instructions loaded by Pi at session start
+├── SYSTEM.md # Block 3: per-project system-prompt append
├── skills/project-inspector/ # Block 2: your skill goes here (stub provided)
+├── .pi/ # Block 3: Pi-specific resources
+│ ├── skills/ # ported inspector + verifier skills (security / arch / perf)
+│ └── extensions/ # inspect-verify.ts — auto-fires verifier after inspector
├── prompts/ # Block 1: prompt-evolution reference (v0 baseline, v5 canonical fallback)
├── evals/ # Block 2: eval suite
│ ├── evals.json # 5 test cases with planted pathology (see Block 2 spec)
│ └── trigger-eval.json # 20 queries for the description optimizer
-├── fixtures/ # Block 2: test inputs (Nuxt, monorepo, Vite+React, leaky-secret)
+├── fixtures/ # Block 2 + 3: test inputs
+│ └── agentic-target-sample/ # Block 3: Nuxt-shaped fixture with planted vulnerable deps
+├── block3/ # Block 3: instructor notes, narration script, attendee walkthrough
├── nuxt-app/ # Block 4.9: Vue/Nuxt integration target
├── bifrost/ # Block 4: Bifrost config (with semantic_cache plugin)
└── scripts/ # Helper one-liners (cache demo, test prompts)
@@ -58,6 +67,9 @@ Open `prompts/project-inspector-v0.txt` and walk it through the 5-layer enhancem
**Block 2 — Build & Eval a Skill (morning, after break)**
Open `skills/project-inspector/SKILL.md`. Paste your v5 from Block 1. Then run the `skill-creator` plugin against the `evals/` and `fixtures/` directories. The plugin will spawn parallel with-skill and baseline runs, grade them, and open a viewer. **Watch the Benchmark tab.** Something's planted in case 0 — the analyzer pass will tell you what.
+**Block 3 — Vibe Coding → Agentic Engineering (afternoon, post-lunch)**
+Copy your Block 2 skill into `.pi/skills/project-inspector/`. Launch `pi` from the repo root and inspect `fixtures/agentic-target-sample/`. The inspector will produce a clean Nuxt-3 briefing — and confidently miss something. We'll find the lie together, install the verifier skill, wire the `.pi/extensions/inspect-verify.ts` hook so the verifier fires automatically, and finish with the `AGENTS.md` / `SYSTEM.md` hygiene primitives. Attendee-facing walkthrough lives at [`block3/README.md`](block3/README.md).
+
**Block 4 — AI Gateway (afternoon)**
Boot Bifrost: `npm run bifrost`. Configure providers, models, a Virtual Key, a budget, a routing rule, and the semantic cache. Then `cd nuxt-app && npm install && npm run dev` and wire the Vue app to your gateway.
diff --git a/SYSTEM.md b/SYSTEM.md
new file mode 100644
index 0000000..ad712c3
--- /dev/null
+++ b/SYSTEM.md
@@ -0,0 +1,11 @@
+# SYSTEM.md — AI Engineering Workshop
+
+> Optional per-project system-prompt **append** for Pi. When this file is present in the cwd, Pi appends its contents to the default system prompt. Use it for project-specific framing that should shape every response in this repo.
+
+You are operating inside the **AI Engineering: From Prompt Architecture to Production Infrastructure** workshop repository for VueConf US 2026. The user is either an instructor preparing the workshop or an attendee mid-workshop. Optimize for clarity and pedagogical honesty over polish:
+
+- **When a skill is invoked, run the skill faithfully and emit its declared output shape.** Verifier skills (`project-verifier`, `architecture-verifier`, `performance-verifier`) emit JSON only — no preamble, no postscript.
+- **When composing skills (e.g., via `/audit`), run them in declared order and present each output verbatim.** Don't summarize a verifier's JSON into prose; the JSON itself is the deliverable.
+- **Honest scoping over performative thoroughness.** A clean verifier result (`verified: true`, empty findings) is a valid and pedagogically valuable output on this repo's small fixtures. Don't manufacture concerns to look diligent.
+- **Cite, never fabricate, advisories.** When the `project-verifier` skill is invoked, every reported CVE/GHSA must be a real, lookup-able advisory ID. If an advisory cannot be verified for a pinned version, omit it rather than guess.
+- **Skill boundaries are pedagogical, not legal.** If an attendee asks you to do something outside the declared scope of a skill, do it — but in your role as a general agent, not as the skill. Note the role shift briefly so attendees see the boundary working.
diff --git a/block3/README.md b/block3/README.md
new file mode 100644
index 0000000..08dafd2
--- /dev/null
+++ b/block3/README.md
@@ -0,0 +1,57 @@
+# Block 3 — Vibe Coding → Agentic Engineering
+
+Attendee walkthrough for the Block 3 afternoon slot (1:00 – 2:30 PM, 90 min).
+
+> **Thesis:** How working engineers move from vibe coding to agentic engineering. Same skill, new altitude.
+
+## What you'll do
+
+1. **Port** your Block 2 Project Inspector skill into Pi
+2. **Run** it against a Nuxt-shaped fixture and see it produce a confidently-incomplete answer
+3. **Install** a verifier skill that applies a different lens (security / supply-chain) to the same input
+4. **Wire** a Pi extension (`.ts`) that auto-fires the verifier after the inspector finishes — and register a `/audit` slash command as the explicit, reliable alternative
+5. **Drop in** `AGENTS.md` and `SYSTEM.md` — Pi's project-scoped hygiene primitives
+6. **Watch** the multi-lens showcase: three verifiers in parallel, a deliberator merging findings
+
+## Prereqs (verify before lunch)
+
+- Pi installed: `pi --version` returns cleanly
+- A second CLI for verification: Gemini CLI authed against Google, OR Codex CLI authed against your OpenAI key
+
+If either prereq is missing, raise your hand during the lunch break — five minutes of setup is faster than fifteen minutes of debugging during the lab.
+
+## Files you'll touch
+
+| Path | What |
+|------|------|
+| `.pi/skills/project-inspector/SKILL.md` | Where you copy your Block 2 skill |
+| `.pi/skills/project-verifier/SKILL.md` | Pre-staged — the security/CVE lens |
+| `.pi/extensions/inspect-verify.ts` | Pre-staged — the hook + slash command |
+| `fixtures/agentic-target-sample/` | The Nuxt-shaped target with the planted failure |
+| `AGENTS.md`, `SYSTEM.md` | Pre-staged at repo root — project-scoped Pi config |
+
+## The 90-minute shape
+
+| Time | Beat | Mode |
+|------|------|------|
+| 1:00 – 1:05 | Frame | Mirrored |
+| 1:05 – 1:25 | Port Project Inspector into Pi | YOUR TURN |
+| 1:25 – 1:30 | The failure — what the briefing doesn't say | Mirrored |
+| 1:30 – 1:50 | Verifier agent enters | Mixed |
+| 1:50 – 2:05 | Hooks — Pi extension | Mixed |
+| 2:05 – 2:15 | Hygiene — AGENTS.md + SYSTEM.md | Mixed |
+| 2:15 – 2:23 | Showcase — pattern extended (3 verifiers + deliberator) | Demo |
+| 2:23 – 2:27 | Showcase — roundtable cameo | Demo |
+| 2:27 – 2:30 | Q&A | Conversation |
+
+## What you take home
+
+A repo you can use as a template:
+
+- One inspector skill + one verifier skill + one extension that wires them
+- An `AGENTS.md` and `SYSTEM.md` you can adapt for any of your own projects
+- The composition pattern: *no single skill catches everything; that's why we compose*
+
+## What to do Monday
+
+Pick one skill from your own work where the output is *technically correct but operationally incomplete* — and build the verifier that catches what it misses. Same pattern. Same primitives. Different domain.
diff --git a/fixtures/agentic-target-sample/README.md b/fixtures/agentic-target-sample/README.md
new file mode 100644
index 0000000..468efe0
--- /dev/null
+++ b/fixtures/agentic-target-sample/README.md
@@ -0,0 +1,59 @@
+# agentic-target-sample
+
+> ⚠️ **Instructor-facing.** Do NOT share this README with attendees pre-workshop. The Block 3 dramatic-failure beat depends on attendees not knowing what's planted.
+
+A Nuxt-shaped fixture used as the **Block 3 "skills can lie" target.** Structurally identical to `nuxt-sample/`; differs only in `package.json`, which pins a stack of well-documented vulnerable transitive dependencies.
+
+## Structure
+
+```
+agentic-target-sample/
+├── package.json # Nuxt 3 deps + planted vulnerable transitives
+├── nuxt.config.ts # Nuxt configuration
+├── pages/
+│ ├── index.vue
+│ └── about.vue
+├── components/
+│ └── Header.vue
+└── composables/
+ └── useExample.ts
+```
+
+## The planted vulnerabilities
+
+| Dep | Pinned | Advisory | Severity |
+|-----|--------|----------|----------|
+| `axios` | `0.21.0` | CVE-2020-28168 (SSRF) | High |
+| `lodash` | `4.17.20` | CVE-2021-23337 (command injection) | High |
+| `minimist` | `1.2.5` | CVE-2021-44906 (prototype pollution) | Critical |
+| `serialize-javascript` | `3.0.0` | CVE-2020-7660 (XSS) | High |
+
+All advisories are public, stable, and not at risk of expiry. None of the planted versions are runtime-active in the fixture's code — they exist only as declared dependencies.
+
+## What Project Inspector says (the lie)
+
+Project Inspector v5 confidently produces a clean Nuxt-3 architectural briefing:
+
+- Framework: Nuxt 3
+- Entry points: `nuxt.config.ts`, `pages/index.vue`, `pages/about.vue`
+- Data-flow trace through page → component → composable
+- `key_dependencies`: likely lists most or all of `nuxt`, `vue`, `vue-router`, `typescript`, `axios`, `lodash`, `minimist`, `serialize-javascript`
+
+**The lie isn't omission — it's lensing.** Inspector lists the dependency *names* (per its spec) but reports **no version context** and **no security posture**. Its output schema is `["<package name>", ...]` — names only. A reader looking at Inspector's briefing has no signal that four of those deps are pinned at exact versions with public high/critical CVEs.
+
+That's the failure mode this fixture exercises: not that v5 is broken, but that v5's spec doesn't ask it to evaluate security posture. The discipline of *agentic engineering* is composing past that limit, not training one skill to do everything.
+
+## What Project Verifier catches
+
+`.pi/skills/project-verifier/` reads `package.json`, identifies the pinned exact versions, and uses Gemini's web grounding to look up CVE advisories per pinned version. Output flags all four planted vulns with severity and advisory ID.
+
+## Why no lockfile
+
+The fixture honors the existing fixtures-README size constraint (≤10 files, ≤20 KB). A real `package-lock.json` for a Nuxt project would blow the budget. The verifier doesn't need one — it operates on declared versions in `package.json` plus web-grounded CVE lookup, which is the lesson: *a verifier can use a different lens (the web, an external CLI, a different model) to catch what your local-only skill cannot.*
+
+## Pre-workshop verification checklist
+
+- [ ] Run Project Inspector v5 against this fixture; confirm it produces a clean briefing with no security mentions in ≥9/10 runs
+- [ ] Run Project Verifier (via Pi + Gemini CLI) against the same fixture; confirm all 4 pinned vulns are flagged in ≥9/10 runs
+- [ ] Capture before/after screenshots for the slide deck (Inspector output side-by-side with Verifier output)
+- [ ] Confirm file size remains within fixture conventions (`du -k .`)
diff --git a/fixtures/agentic-target-sample/components/Header.vue b/fixtures/agentic-target-sample/components/Header.vue
new file mode 100644
index 0000000..ce316ba
--- /dev/null
+++ b/fixtures/agentic-target-sample/components/Header.vue
@@ -0,0 +1,16 @@
+<script setup lang="ts">
+const links = [
+ { to: '/', label: 'Home' },
+ { to: '/about', label: 'About' },
+]
+</script>
+
+<template>
+ <header>
+ <nav>
+ <NuxtLink v-for="link in links" :key="link.to" :to="link.to">
+ {{ link.label }}
+ </NuxtLink>
+ </nav>
+ </header>
+</template>
diff --git a/fixtures/agentic-target-sample/composables/useExample.ts b/fixtures/agentic-target-sample/composables/useExample.ts
new file mode 100644
index 0000000..54ecd8c
--- /dev/null
+++ b/fixtures/agentic-target-sample/composables/useExample.ts
@@ -0,0 +1,4 @@
+export const useExample = () => {
+ const greeting = ref('Hello from the Nuxt sample fixture')
+ return { greeting }
+}
diff --git a/fixtures/agentic-target-sample/nuxt.config.ts b/fixtures/agentic-target-sample/nuxt.config.ts
new file mode 100644
index 0000000..0b5183f
--- /dev/null
+++ b/fixtures/agentic-target-sample/nuxt.config.ts
@@ -0,0 +1,14 @@
+// https://nuxt.com/docs/api/configuration/nuxt-config
+export default defineNuxtConfig({
+ compatibilityDate: '2026-01-01',
+ devtools: { enabled: true },
+ modules: [],
+ app: {
+ head: {
+ title: 'Nuxt Sample',
+ meta: [
+ { name: 'description', content: 'A small Nuxt 3 sample app used as a workshop fixture.' },
+ ],
+ },
+ },
+})
diff --git a/fixtures/agentic-target-sample/package.json b/fixtures/agentic-target-sample/package.json
new file mode 100644
index 0000000..bb34d2e
--- /dev/null
+++ b/fixtures/agentic-target-sample/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "agentic-target-sample",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "nuxt build",
+ "dev": "nuxt dev",
+ "generate": "nuxt generate",
+ "preview": "nuxt preview"
+ },
+ "dependencies": {
+ "axios": "0.21.0",
+ "lodash": "4.17.20",
+ "minimist": "1.2.5",
+ "serialize-javascript": "3.0.0"
+ },
+ "devDependencies": {
+ "@nuxt/devtools": "latest",
+ "nuxt": "^3.13.0",
+ "typescript": "^5.5.0",
+ "vue": "^3.5.0",
+ "vue-router": "^4.4.0"
+ }
+}
diff --git a/fixtures/agentic-target-sample/pages/about.vue b/fixtures/agentic-target-sample/pages/about.vue
new file mode 100644
index 0000000..7be546c
--- /dev/null
+++ b/fixtures/agentic-target-sample/pages/about.vue
@@ -0,0 +1,14 @@
+<script setup lang="ts">
+useHead({ title: 'About — Nuxt Sample' })
+</script>
+
+<template>
+ <div>
+ <Header />
+ <main>
+ <h1>About this sample</h1>
+ <p>A minimal Nuxt 3 project used as a fixture for the Project Inspector skill.</p>
+ <NuxtLink to="/">Home</NuxtLink>
+ </main>
+ </div>
+</template>
diff --git a/fixtures/agentic-target-sample/pages/index.vue b/fixtures/agentic-target-sample/pages/index.vue
new file mode 100644
index 0000000..a847a1b
--- /dev/null
+++ b/fixtures/agentic-target-sample/pages/index.vue
@@ -0,0 +1,14 @@
+<script setup lang="ts">
+const { greeting } = useExample()
+</script>
+
+<template>
+ <div>
+ <Header />
+ <main>
+ <h1>{{ greeting }}</h1>
+ <p>This is the home page of the Nuxt sample fixture.</p>
+ <NuxtLink to="/about">About</NuxtLink>
+ </main>
+ </div>
+</template>
--
2.43.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment