{"vulnerability": "CVE-2020-7660", "sightings": [{"uuid": "958237f8-1a39-44e0-acbf-b25bae1c91bb", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2020-7660", "type": "seen", "source": "https://gist.github.com/joemocha/fe552c9601dc58c4f9731982ab0d1f8c", "content": "From 87a213729aba7bd86b4cb07a5e6630fdd0cdef19 Mon Sep 17 00:00:00 2001\nFrom: Samuel Obukwelu \nDate: Mon, 18 May 2026 21:35:28 -0400\nSubject: [PATCH] Add Block 3 audience materials\n\n---\n .pi/extensions/inspect-verify.ts              | 111 ++++++++++++++++++\n .pi/skills/architecture-verifier/SKILL.md     |  54 +++++++++\n .pi/skills/performance-verifier/SKILL.md      |  53 +++++++++\n .pi/skills/project-inspector/SKILL.md         |  53 +++++++++\n .pi/skills/project-verifier/SKILL.md          |  89 ++++++++++++++\n AGENTS.md                                     |  47 ++++++++\n README.md                                     |  16 ++-\n SYSTEM.md                                     |  11 ++\n block3/README.md                              |  57 +++++++++\n fixtures/agentic-target-sample/README.md      |  59 ++++++++++\n .../components/Header.vue                     |  16 +++\n .../composables/useExample.ts                 |   4 +\n fixtures/agentic-target-sample/nuxt.config.ts |  14 +++\n fixtures/agentic-target-sample/package.json   |  24 ++++\n .../agentic-target-sample/pages/about.vue     |  14 +++\n .../agentic-target-sample/pages/index.vue     |  14 +++\n 16 files changed, 634 insertions(+), 2 deletions(-)\n create mode 100644 .pi/extensions/inspect-verify.ts\n create mode 100644 .pi/skills/architecture-verifier/SKILL.md\n create mode 100644 .pi/skills/performance-verifier/SKILL.md\n create mode 100644 .pi/skills/project-inspector/SKILL.md\n create mode 100644 .pi/skills/project-verifier/SKILL.md\n create mode 100644 AGENTS.md\n create mode 100644 SYSTEM.md\n create mode 100644 block3/README.md\n create mode 100644 fixtures/agentic-target-sample/README.md\n create mode 100644 fixtures/agentic-target-sample/components/Header.vue\n create mode 100644 fixtures/agentic-target-sample/composables/useExample.ts\n create mode 100644 fixtures/agentic-target-sample/nuxt.config.ts\n create mode 100644 fixtures/agentic-target-sample/package.json\n create mode 100644 fixtures/agentic-target-sample/pages/about.vue\n create mode 100644 fixtures/agentic-target-sample/pages/index.vue\n\ndiff --git a/.pi/extensions/inspect-verify.ts b/.pi/extensions/inspect-verify.ts\nnew file mode 100644\nindex 0000000..9105826\n--- /dev/null\n+++ b/.pi/extensions/inspect-verify.ts\n@@ -0,0 +1,111 @@\n+/**\n+ * inspect-verify \u2014 Block 3 Pi extension\n+ *\n+ * Implements ARCH-A (sequential pipeline) on top of `project-inspector` and\n+ * `project-verifier` skills. Two invocation paths, each with a different\n+ * pedagogical purpose:\n+ *\n+ *   1. `/audit ` \u2014 explicit slash command. Injects a single coordinated\n+ *      prompt that asks the agent to run inspector then verifier in one turn.\n+ *      Works in BOTH interactive and non-interactive (-p / --print) modes.\n+ *      This is the primary, reliable path attendees install and use.\n+ *\n+ *   2. `agent_end` listener \u2014 when a turn ends and the output looks like a\n+ *      project-inspector structural briefing (JSON with `\"architecture\"` and\n+ *      `\"entry_points\"`), the extension calls `sendUserMessage` to queue a\n+ *      verifier follow-up. Works in INTERACTIVE mode only \u2014 `-p` mode exits\n+ *      after the first `agent_end` and ignores queued messages. The ambient\n+ *      lesson: once the pattern is wired, the system catches itself without\n+ *      the user remembering to invoke the verifier by name.\n+ *\n+ * Pedagogical thesis: a working engineer composes skills into self-checking\n+ * systems instead of running each skill by hand. Inspector finds architecture;\n+ * Verifier flags supply-chain risk; the extension wires them together. No\n+ * single skill catches everything \u2014 that's why we compose.\n+ */\n+\n+import type {\n+  AgentMessage,\n+  ExtensionAPI,\n+} from \"@earendil-works/pi-coding-agent\";\n+\n+const VERIFIER_FOLLOWUP_PROMPT =\n+  \"The previous response looks like a project-inspector structural briefing. \" +\n+  \"Now run the project-verifier skill on the same target. Read the \" +\n+  \"dependency manifest (package.json, pyproject.toml, go.mod, etc.) of the \" +\n+  \"repository you just inspected, identify pinned exact versions, and use web \" +\n+  \"search to look up known CVE / GHSA advisories per pinned version. Emit the \" +\n+  \"verifier's JSON report \u2014 do not produce another structural briefing.\";\n+\n+const AUDIT_COMMAND_PROMPT = (target: string) =&gt;\n+  `Audit the repository at \\`${target}\\`. ` +\n+  `Step 1 \u2014 run the project-inspector skill: produce a structural briefing in the inspector's JSON shape. ` +\n+  `Step 2 \u2014 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. ` +\n+  `Return both JSON outputs in order, separated by a \"---\" line.`;\n+\n+/**\n+ * Extract plain text from an assistant message's content blocks.\n+ * AssistantMessage.content is (TextContent | ThinkingContent | ToolCall)[].\n+ */\n+function assistantText(message: AgentMessage): string {\n+  if (message.role !== \"assistant\") return \"\";\n+  const content = message.content;\n+  if (typeof content === \"string\") return content;\n+  if (!Array.isArray(content)) return \"\";\n+  return content\n+    .filter((block: any) =&gt; block &amp;&amp; block.type === \"text\")\n+    .map((block: any) =&gt; (typeof block.text === \"string\" ? block.text : \"\"))\n+    .join(\"\\n\");\n+}\n+\n+/**\n+ * Heuristic: does the text look like a project-inspector output?\n+ * Matches the inspector's documented JSON schema.\n+ */\n+function looksLikeInspectorBriefing(text: string): boolean {\n+  return (\n+    text.includes('\"architecture\"') &amp;&amp;\n+    text.includes('\"entry_points\"') &amp;&amp;\n+    // Quick exclusion: don't re-fire on verifier output\n+    !text.includes('\"lens\"') &amp;&amp;\n+    !text.includes('\"findings\"') &amp;&amp;\n+    !text.includes('\"missed_by_structural_briefing\"')\n+  );\n+}\n+\n+export default function (pi: ExtensionAPI) {\n+  // De-dupe: only fire the verifier once per distinct inspector output within\n+  // a single session. The fingerprint is the first ~200 chars of the output;\n+  // good enough for one session's worth of turns.\n+  const firedFingerprints = new Set();\n+\n+  pi.on(\"agent_end\", async (event) =&gt; {\n+    const lastAssistant = [...event.messages]\n+      .reverse()\n+      .find((m: AgentMessage) =&gt; m.role === \"assistant\");\n+    if (!lastAssistant) return;\n+\n+    const text = assistantText(lastAssistant);\n+    if (!looksLikeInspectorBriefing(text)) return;\n+\n+    const fingerprint = text.slice(0, 200);\n+    if (firedFingerprints.has(fingerprint)) return;\n+    firedFingerprints.add(fingerprint);\n+\n+    // Inject the verifier follow-up. `deliverAs: \"followUp\"` queues this for\n+    // the next turn so it doesn't fight an in-flight stream.\n+    pi.sendUserMessage(VERIFIER_FOLLOWUP_PROMPT, { deliverAs: \"followUp\" });\n+  });\n+\n+  // Explicit, loop-safe path: `/audit ` triggers inspector + verifier\n+  // in a single coordinated prompt. Useful when the auto-detect heuristic\n+  // misses or when the user wants the pipeline by name.\n+  pi.registerCommand(\"audit\", {\n+    description:\n+      \"Run project-inspector then project-verifier on the given repository path.\",\n+    handler: async (args, _ctx) =&gt; {\n+      const target = args.trim() || \".\";\n+      pi.sendUserMessage(AUDIT_COMMAND_PROMPT(target));\n+    },\n+  });\n+}\ndiff --git a/.pi/skills/architecture-verifier/SKILL.md b/.pi/skills/architecture-verifier/SKILL.md\nnew file mode 100644\nindex 0000000..713a636\n--- /dev/null\n+++ b/.pi/skills/architecture-verifier/SKILL.md\n@@ -0,0 +1,54 @@\n+---\n+name: architecture-verifier\n+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.\n+---\n+\n+# Architecture Verifier\n+\n+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.\n+\n+## When you run\n+\n+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.\n+\n+You may also run standalone when a user asks to architecturally review a codebase.\n+\n+## Process\n+\n+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.\n+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.\n+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).\n+4. **Missing abstractions.** Look for repeated patterns that should be extracted (3+ near-duplicate handlers, recurring fetch-then-transform shapes, etc.).\n+5. **Premature abstractions.** Look for the inverse: indirection that doesn't earn its keep \u2014 single-impl interfaces, factories that wrap one constructor, config layers nobody configures.\n+6. **Test architecture.** If tests exist, note whether they exercise behavior or implementation. If they don't, flag the absence as architectural risk.\n+7. **Score severity.** For each finding: severity (critical / high / moderate / low), one-sentence description, one-sentence recommendation.\n+\n+## Output format\n+\n+Return **only** valid JSON in the following shape \u2014 no prose before or after the JSON block:\n+\n+```json\n+{\n+  \"verified\": false,\n+  \"target\": \"\",\n+  \"lens\": \"architecture\",\n+  \"findings\": [\n+    {\n+      \"concern\": \"\",\n+      \"severity\": \"critical | high | moderate | low\",\n+      \"summary\": \"\",\n+      \"recommendation\": \"\"\n+    }\n+  ],\n+  \"recommendation\": \"&lt;2\u20133 sentence summary of architectural posture&gt;\"\n+}\n+```\n+\n+Set `verified: true` only when there are zero findings of severity `high` or `critical`.\n+\n+## Constraints\n+\n+- **Be specific.** Generic findings (\"could be more modular\") help no one. Cite file paths or directory names.\n+- **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.\n+- **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.\n+- **No fabrication.** Only reference patterns you can verify by reading the code.\ndiff --git a/.pi/skills/performance-verifier/SKILL.md b/.pi/skills/performance-verifier/SKILL.md\nnew file mode 100644\nindex 0000000..75b6389\n--- /dev/null\n+++ b/.pi/skills/performance-verifier/SKILL.md\n@@ -0,0 +1,53 @@\n+---\n+name: performance-verifier\n+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.\n+---\n+\n+# Performance Verifier\n+\n+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.\n+\n+## When you run\n+\n+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.\n+\n+You may also run standalone when a user asks to performance-review a codebase.\n+\n+## Process\n+\n+1. **Read the dependency manifest.** Identify heavyweight deps (Lodash full import, Moment, large UI libs, AWS SDK monoliths). Note tree-shakable vs not.\n+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.\n+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.\n+4. **Asset hygiene.** Note images &gt; 200KB, unbounded fonts, CDN-vs-local mismatches in obvious places.\n+5. **Build-time cost.** Note signals of slow builds: large `tsconfig` includes, missing `paths` aliases, `node_modules` directly imported from source.\n+6. **Score severity.** For each finding: severity (critical / high / moderate / low), one-sentence description, one-sentence recommendation.\n+\n+## Output format\n+\n+Return **only** valid JSON in the following shape \u2014 no prose before or after the JSON block:\n+\n+```json\n+{\n+  \"verified\": false,\n+  \"target\": \"\",\n+  \"lens\": \"performance\",\n+  \"findings\": [\n+    {\n+      \"concern\": \"\",\n+      \"severity\": \"critical | high | moderate | low\",\n+      \"summary\": \"\",\n+      \"recommendation\": \"\"\n+    }\n+  ],\n+  \"recommendation\": \"&lt;2\u20133 sentence summary of performance posture&gt;\"\n+}\n+```\n+\n+Set `verified: true` only when there are zero findings of severity `high` or `critical`.\n+\n+## Constraints\n+\n+- **Be quantitative when possible.** \"Lodash full import\" \u2192 cite the file. \"Large asset\" \u2192 estimate the kB. Vague findings degrade the audit.\n+- **Workshop-fixture awareness.** Small fixtures (&lt;10 files) won't have many real performance findings. Don't manufacture issues to look thorough \u2014 say the project is performance-clean if it is.\n+- **One lens only.** Performance-focused. Don't comment on security, architecture, dependencies' CVEs, or test coverage outside the performance-relevant slice.\n+- **No fabrication.** Only reference patterns you can verify by reading the code.\ndiff --git a/.pi/skills/project-inspector/SKILL.md b/.pi/skills/project-inspector/SKILL.md\nnew file mode 100644\nindex 0000000..044a595\n--- /dev/null\n+++ b/.pi/skills/project-inspector/SKILL.md\n@@ -0,0 +1,53 @@\n+---\n+name: project-inspector\n+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.\n+---\n+\n+# Project Inspector\n+\n+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.\n+\n+## Process (think step-by-step)\n+\n+1. **Scan the directory structure.** Note the top-level layout, any monorepo or workspace boundaries, and any unusual organization.\n+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.\n+3. **Locate the entry points.** Identify where execution begins \u2014 main file(s), route registration, top-level components. List at least three when present.\n+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.\n+5. **Note test patterns.** Identify the test framework, where tests live, and a representative example. If tests are missing, say so.\n+6. **Summarize.** Produce the structured output below.\n+\n+## Output format\n+\n+Return **only** valid JSON in the following shape \u2014 no prose before or after the JSON block:\n+\n+```json\n+{\n+  \"architecture\": \"&lt;2\u20134 sentence summary of the overall shape and framework&gt;\",\n+  \"entry_points\": [\"\", \"\", \"\"],\n+  \"data_flow\": \"&lt;2\u20133 sentence trace of how a request/invocation moves through the most prominent entry point&gt;\",\n+  \"key_dependencies\": [\"\", \"\", \"...\"],\n+  \"test_patterns\": \"&lt;1\u20132 sentence note on test framework, location, conventions; or 'No tests detected.'&gt;\"\n+}\n+```\n+\n+## Example\n+\n+For a small Express app:\n+\n+```json\n+{\n+  \"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.\",\n+  \"entry_points\": [\"src/server.ts\", \"src/routes/index.ts\", \"src/routes/users.ts\"],\n+  \"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.\",\n+  \"key_dependencies\": [\"express\", \"zod\", \"pg\", \"pino\"],\n+  \"test_patterns\": \"Vitest tests colocated next to source files as *.test.ts. One example: src/services/users.test.ts.\"\n+}\n+```\n+\n+## Constraints\n+\n+- **Never invent file paths.** Only reference files you can observe in the input. If a path is unclear, omit it rather than guess.\n+- **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.\n+- **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.\n+- **If the input is not a codebase** \u2014 e.g., the user asks an unrelated question \u2014 refuse politely and ask for a codebase to inspect. Do not produce a briefing for non-repo input.\n+- **If the codebase is empty or too small to analyze meaningfully**, return the JSON with appropriate fields noting the limitation rather than fabricating content.\ndiff --git a/.pi/skills/project-verifier/SKILL.md b/.pi/skills/project-verifier/SKILL.md\nnew file mode 100644\nindex 0000000..6d5a780\n--- /dev/null\n+++ b/.pi/skills/project-verifier/SKILL.md\n@@ -0,0 +1,89 @@\n+---\n+name: project-verifier\n+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.\n+---\n+\n+# Project Verifier\n+\n+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 \u2014 the lens of pinned versions, known advisories, and supply-chain risk \u2014 and produce a verification report that flags what the structural briefing missed.\n+\n+## When you run\n+\n+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.\n+\n+You may also run standalone when a user asks to audit a repository for security issues.\n+\n+## Process (think step-by-step)\n+\n+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.\n+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.\n+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.\n+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.\n+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).\n+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 \u2014 surfacing what the prior agent missed.\n+7. **Emit the report.**\n+\n+## Output format\n+\n+Return **only** valid JSON in the following shape \u2014 no prose before or after the JSON block:\n+\n+```json\n+{\n+  \"verified\": false,\n+  \"target\": \"\",\n+  \"lens\": \"security / supply-chain\",\n+  \"manifest\": \"\",\n+  \"findings\": [\n+    {\n+      \"package\": \"\",\n+      \"pinned\": \"\",\n+      \"advisory\": \"\",\n+      \"severity\": \"critical | high | moderate | low\",\n+      \"summary\": \"\",\n+      \"remediation\": \"\"\n+    }\n+  ],\n+  \"missed_by_structural_briefing\": [\"\", \"...\"],\n+  \"recommendation\": \"&lt;2\u20133 sentence summary of risk posture and what to do next&gt;\"\n+}\n+```\n+\n+Set `verified: true` only when there are zero findings of severity `high` or `critical`. Otherwise `verified: false`.\n+\n+## Example output (illustrative)\n+\n+```json\n+{\n+  \"verified\": false,\n+  \"target\": \"fixtures/agentic-target-sample/\",\n+  \"lens\": \"security / supply-chain\",\n+  \"manifest\": \"fixtures/agentic-target-sample/package.json\",\n+  \"findings\": [\n+    {\n+      \"package\": \"axios\",\n+      \"pinned\": \"0.21.0\",\n+      \"advisory\": \"CVE-2020-28168\",\n+      \"severity\": \"high\",\n+      \"summary\": \"Server-Side Request Forgery via maliciously-crafted URLs in axios &lt;0.21.1.\",\n+      \"remediation\": \"Upgrade to axios &gt;=0.21.1\"\n+    }\n+  ],\n+  \"missed_by_structural_briefing\": [\"axios\", \"lodash\", \"minimist\", \"serialize-javascript\"],\n+  \"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.\"\n+}\n+```\n+\n+## Constraints\n+\n+- **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.\n+- **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.\n+- **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.\n+- **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.\"\n+- **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.\n+- **Do not modify the target repo.** This skill is read-only with respect to the target.\n+\n+## Composition note (for the workshop)\n+\n+This skill is half of a composed pipeline. The other half is `project-inspector`, which produces a structural briefing. Run them together \u2014 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.\n+\n+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.\ndiff --git a/AGENTS.md b/AGENTS.md\nnew file mode 100644\nindex 0000000..9494243\n--- /dev/null\n+++ b/AGENTS.md\n@@ -0,0 +1,47 @@\n+# AGENTS.md \u2014 AI Engineering Workshop\n+\n+&gt; 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 \u2014 and concatenates them in that order. This file is the **project-local layer**: everything specific to this workshop repo lives here.\n+\n+## What this repo is\n+\n+Workshop materials for *AI Engineering: From Prompt Architecture to Production Infrastructure* \u2014 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.\n+\n+## Where things live\n+\n+| Path | What |\n+|------|------|\n+| `.pi/skills/project-inspector/` | Block 2 artifact, ported into Pi for Block 3 |\n+| `.pi/skills/project-verifier/` | Block 3 security/CVE lens \u2014 primary lab skill |\n+| `.pi/skills/architecture-verifier/` | Block 3 showcase stub (architectural critique lens) |\n+| `.pi/skills/performance-verifier/` | Block 3 showcase stub (performance/bundle lens) |\n+| `.pi/extensions/inspect-verify.ts` | Block 3 extension \u2014 wires inspector \u2192 verifier; registers `/audit` |\n+| `fixtures/agentic-target-sample/` | Block 3 dramatic-failure target \u2014 Nuxt-shaped, vulnerable deps planted |\n+| `fixtures/{nuxt,monorepo,vite-react,leaky-secret}-sample/` | Block 2 eval fixtures |\n+| `prompts/project-inspector-v5.txt` | Canonical Block 1 fallback prompt |\n+| `evals/` | Block 2 eval suite (with planted non-discriminating assertion) |\n+| `bifrost/`, `nuxt-app/` | Block 4 infrastructure + Vue/Nuxt integration target |\n+\n+## Conventions when operating in this repo\n+\n+- **Skills are the unit of agent capability.** A new lens (security / architecture / performance / etc.) lives as a new skill under `.pi/skills//`. Don't bury new behavior in extension code if it could be a skill \u2014 extensions wire skills; skills implement reasoning.\n+- **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.\n+- **One JSON shape per verifier.** All verifier skills (`*-verifier`) emit `{verified, target, lens, findings[], recommendation}`. Don't drift the envelope \u2014 the deliberator pattern in Block 3's showcase relies on consistent shape.\n+- **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.\n+- **Honest scoping.** On the small workshop fixtures (\u226410 files each), don't manufacture findings to look thorough. A clean lens is a valid result.\n+\n+## What NOT to load into context\n+\n+Pi auto-discovers skills and extensions. Be deliberate about what runs:\n+\n+- `node_modules/`, `.nuxt/`, `.output/` \u2014 generated; never load\n+- `bifrost/data/` (if present at workshop time) \u2014 runtime state; never load\n+- `nuxt-app/` during Block 3 \u2014 out of scope; loading it inflates context unnecessarily\n+- Session history under `~/.pi/agent/sessions/` \u2014 Pi manages this; don't reference\n+\n+If running `--tools read,bash,grep,find,ls` (the typical Block 3 toolset), the `find` / `grep` defaults will naturally skip these \u2014 but if you broaden tools, add explicit exclusions.\n+\n+## Workshop-day operational notes\n+\n+- **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.\n+- **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 \u2014 use it when scripting.\n+- **Pre-staged extensions:** `.pi/extensions/inspect-verify.ts` is auto-loaded by Pi when run from the repo root. Override with `-e ` if loading from elsewhere.\ndiff --git a/README.md b/README.md\nindex 8d69258..d4d1d49 100644\n--- a/README.md\n+++ b/README.md\n@@ -12,7 +12,7 @@ Workshop materials for four blocks of hands-on AI engineering:\n |---|---|---|\n | **1** | Foundations | Write a v5 prompt for the Project Inspector running example |\n | **2** | Build &amp; Eval a Skill | Promote the prompt to a working skill via the `skill-creator` plugin; run the eval loop; learn to *evaluate the eval* |\n-| **3** | Vibe Coding \u2192 Agentic Engineering | (Instructor's separate materials) |\n+| **3** | Vibe Coding \u2192 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 |\n | **4** | AI Gateway (Production) | Configure Bifrost; tour the production-gateway surface; integrate with a Vue/Nuxt app |\n \n ## Quick start\n@@ -34,17 +34,26 @@ See the [Prerequisites](#) (handed out separately). Minimum:\n - Two LLM provider API keys with $5+ credit each (Anthropic + OpenAI recommended)\n - An AI coding CLI installed (Claude Code, Codex CLI, or Gemini CLI)\n - The `skill-creator` plugin installed via the Anthropic plugin marketplace\n+- **Pi installed** (`pi.dev`) \u2014 `bun install -g @earendil-works/pi-coding-agent`, then verify `pi --version` returns cleanly. (Block 3 runtime.)\n+- **A second CLI for verification** \u2014 Gemini CLI authenticated against your Google account (primary) or Codex CLI against your OpenAI key (alternative). Used by Block 3's verifier skill.\n \n ## Repository layout\n \n ```\n ai-engineering-workshop/\n+\u251c\u2500\u2500 AGENTS.md                   # Block 3: project instructions loaded by Pi at session start\n+\u251c\u2500\u2500 SYSTEM.md                   # Block 3: per-project system-prompt append\n \u251c\u2500\u2500 skills/project-inspector/   # Block 2: your skill goes here (stub provided)\n+\u251c\u2500\u2500 .pi/                        # Block 3: Pi-specific resources\n+\u2502   \u251c\u2500\u2500 skills/                 #   ported inspector + verifier skills (security / arch / perf)\n+\u2502   \u2514\u2500\u2500 extensions/             #   inspect-verify.ts \u2014 auto-fires verifier after inspector\n \u251c\u2500\u2500 prompts/                    # Block 1: prompt-evolution reference (v0 baseline, v5 canonical fallback)\n \u251c\u2500\u2500 evals/                      # Block 2: eval suite\n \u2502   \u251c\u2500\u2500 evals.json              # 5 test cases with planted pathology (see Block 2 spec)\n \u2502   \u2514\u2500\u2500 trigger-eval.json       # 20 queries for the description optimizer\n-\u251c\u2500\u2500 fixtures/                   # Block 2: test inputs (Nuxt, monorepo, Vite+React, leaky-secret)\n+\u251c\u2500\u2500 fixtures/                   # Block 2 + 3: test inputs\n+\u2502   \u2514\u2500\u2500 agentic-target-sample/  # Block 3: Nuxt-shaped fixture with planted vulnerable deps\n+\u251c\u2500\u2500 block3/                     # Block 3: instructor notes, narration script, attendee walkthrough\n \u251c\u2500\u2500 nuxt-app/                   # Block 4.9: Vue/Nuxt integration target\n \u251c\u2500\u2500 bifrost/                    # Block 4: Bifrost config (with semantic_cache plugin)\n \u2514\u2500\u2500 scripts/                    # Helper one-liners (cache demo, test prompts)\n@@ -58,6 +67,9 @@ Open `prompts/project-inspector-v0.txt` and walk it through the 5-layer enhancem\n **Block 2 \u2014 Build &amp; Eval a Skill (morning, after break)**\n 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 \u2014 the analyzer pass will tell you what.\n \n+**Block 3 \u2014 Vibe Coding \u2192 Agentic Engineering (afternoon, post-lunch)**\n+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 \u2014 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).\n+\n **Block 4 \u2014 AI Gateway (afternoon)**\n Boot Bifrost: `npm run bifrost`. Configure providers, models, a Virtual Key, a budget, a routing rule, and the semantic cache. Then `cd nuxt-app &amp;&amp; npm install &amp;&amp; npm run dev` and wire the Vue app to your gateway.\n \ndiff --git a/SYSTEM.md b/SYSTEM.md\nnew file mode 100644\nindex 0000000..ad712c3\n--- /dev/null\n+++ b/SYSTEM.md\n@@ -0,0 +1,11 @@\n+# SYSTEM.md \u2014 AI Engineering Workshop\n+\n+&gt; 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.\n+\n+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:\n+\n+- **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 \u2014 no preamble, no postscript.\n+- **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.\n+- **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.\n+- **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.\n+- **Skill boundaries are pedagogical, not legal.** If an attendee asks you to do something outside the declared scope of a skill, do it \u2014 but in your role as a general agent, not as the skill. Note the role shift briefly so attendees see the boundary working.\ndiff --git a/block3/README.md b/block3/README.md\nnew file mode 100644\nindex 0000000..08dafd2\n--- /dev/null\n+++ b/block3/README.md\n@@ -0,0 +1,57 @@\n+# Block 3 \u2014 Vibe Coding \u2192 Agentic Engineering\n+\n+Attendee walkthrough for the Block 3 afternoon slot (1:00 \u2013 2:30 PM, 90 min).\n+\n+&gt; **Thesis:** How working engineers move from vibe coding to agentic engineering. Same skill, new altitude.\n+\n+## What you'll do\n+\n+1. **Port** your Block 2 Project Inspector skill into Pi\n+2. **Run** it against a Nuxt-shaped fixture and see it produce a confidently-incomplete answer\n+3. **Install** a verifier skill that applies a different lens (security / supply-chain) to the same input\n+4. **Wire** a Pi extension (`.ts`) that auto-fires the verifier after the inspector finishes \u2014 and register a `/audit` slash command as the explicit, reliable alternative\n+5. **Drop in** `AGENTS.md` and `SYSTEM.md` \u2014 Pi's project-scoped hygiene primitives\n+6. **Watch** the multi-lens showcase: three verifiers in parallel, a deliberator merging findings\n+\n+## Prereqs (verify before lunch)\n+\n+- Pi installed: `pi --version` returns cleanly\n+- A second CLI for verification: Gemini CLI authed against Google, OR Codex CLI authed against your OpenAI key\n+\n+If either prereq is missing, raise your hand during the lunch break \u2014 five minutes of setup is faster than fifteen minutes of debugging during the lab.\n+\n+## Files you'll touch\n+\n+| Path | What |\n+|------|------|\n+| `.pi/skills/project-inspector/SKILL.md` | Where you copy your Block 2 skill |\n+| `.pi/skills/project-verifier/SKILL.md` | Pre-staged \u2014 the security/CVE lens |\n+| `.pi/extensions/inspect-verify.ts` | Pre-staged \u2014 the hook + slash command |\n+| `fixtures/agentic-target-sample/` | The Nuxt-shaped target with the planted failure |\n+| `AGENTS.md`, `SYSTEM.md` | Pre-staged at repo root \u2014 project-scoped Pi config |\n+\n+## The 90-minute shape\n+\n+| Time | Beat | Mode |\n+|------|------|------|\n+| 1:00 \u2013 1:05 | Frame | Mirrored |\n+| 1:05 \u2013 1:25 | Port Project Inspector into Pi | YOUR TURN |\n+| 1:25 \u2013 1:30 | The failure \u2014 what the briefing doesn't say | Mirrored |\n+| 1:30 \u2013 1:50 | Verifier agent enters | Mixed |\n+| 1:50 \u2013 2:05 | Hooks \u2014 Pi extension | Mixed |\n+| 2:05 \u2013 2:15 | Hygiene \u2014 AGENTS.md + SYSTEM.md | Mixed |\n+| 2:15 \u2013 2:23 | Showcase \u2014 pattern extended (3 verifiers + deliberator) | Demo |\n+| 2:23 \u2013 2:27 | Showcase \u2014 roundtable cameo | Demo |\n+| 2:27 \u2013 2:30 | Q&amp;A | Conversation |\n+\n+## What you take home\n+\n+A repo you can use as a template:\n+\n+- One inspector skill + one verifier skill + one extension that wires them\n+- An `AGENTS.md` and `SYSTEM.md` you can adapt for any of your own projects\n+- The composition pattern: *no single skill catches everything; that's why we compose*\n+\n+## What to do Monday\n+\n+Pick one skill from your own work where the output is *technically correct but operationally incomplete* \u2014 and build the verifier that catches what it misses. Same pattern. Same primitives. Different domain.\ndiff --git a/fixtures/agentic-target-sample/README.md b/fixtures/agentic-target-sample/README.md\nnew file mode 100644\nindex 0000000..468efe0\n--- /dev/null\n+++ b/fixtures/agentic-target-sample/README.md\n@@ -0,0 +1,59 @@\n+# agentic-target-sample\n+\n+&gt; \u26a0\ufe0f **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.\n+\n+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.\n+\n+## Structure\n+\n+```\n+agentic-target-sample/\n+\u251c\u2500\u2500 package.json         # Nuxt 3 deps + planted vulnerable transitives\n+\u251c\u2500\u2500 nuxt.config.ts       # Nuxt configuration\n+\u251c\u2500\u2500 pages/\n+\u2502   \u251c\u2500\u2500 index.vue\n+\u2502   \u2514\u2500\u2500 about.vue\n+\u251c\u2500\u2500 components/\n+\u2502   \u2514\u2500\u2500 Header.vue\n+\u2514\u2500\u2500 composables/\n+    \u2514\u2500\u2500 useExample.ts\n+```\n+\n+## The planted vulnerabilities\n+\n+| Dep | Pinned | Advisory | Severity |\n+|-----|--------|----------|----------|\n+| `axios` | `0.21.0` | CVE-2020-28168 (SSRF) | High |\n+| `lodash` | `4.17.20` | CVE-2021-23337 (command injection) | High |\n+| `minimist` | `1.2.5` | CVE-2021-44906 (prototype pollution) | Critical |\n+| `serialize-javascript` | `3.0.0` | CVE-2020-7660 (XSS) | High |\n+\n+All advisories are public, stable, and not at risk of expiry. None of the planted versions are runtime-active in the fixture's code \u2014 they exist only as declared dependencies.\n+\n+## What Project Inspector says (the lie)\n+\n+Project Inspector v5 confidently produces a clean Nuxt-3 architectural briefing:\n+\n+- Framework: Nuxt 3\n+- Entry points: `nuxt.config.ts`, `pages/index.vue`, `pages/about.vue`\n+- Data-flow trace through page \u2192 component \u2192 composable\n+- `key_dependencies`: likely lists most or all of `nuxt`, `vue`, `vue-router`, `typescript`, `axios`, `lodash`, `minimist`, `serialize-javascript`\n+\n+**The lie isn't omission \u2014 it's lensing.** Inspector lists the dependency *names* (per its spec) but reports **no version context** and **no security posture**. Its output schema is `[\"\", ...]` \u2014 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.\n+\n+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.\n+\n+## What Project Verifier catches\n+\n+`.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.\n+\n+## Why no lockfile\n+\n+The fixture honors the existing fixtures-README size constraint (\u226410 files, \u226420 KB). A real `package-lock.json` for a Nuxt project would blow the budget. The verifier doesn't need one \u2014 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.*\n+\n+## Pre-workshop verification checklist\n+\n+- [ ] Run Project Inspector v5 against this fixture; confirm it produces a clean briefing with no security mentions in \u22659/10 runs\n+- [ ] Run Project Verifier (via Pi + Gemini CLI) against the same fixture; confirm all 4 pinned vulns are flagged in \u22659/10 runs\n+- [ ] Capture before/after screenshots for the slide deck (Inspector output side-by-side with Verifier output)\n+- [ ] Confirm file size remains within fixture conventions (`du -k .`)\ndiff --git a/fixtures/agentic-target-sample/components/Header.vue b/fixtures/agentic-target-sample/components/Header.vue\nnew file mode 100644\nindex 0000000..ce316ba\n--- /dev/null\n+++ b/fixtures/agentic-target-sample/components/Header.vue\n@@ -0,0 +1,16 @@\n+\n+const links = [\n+  { to: '/', label: 'Home' },\n+  { to: '/about', label: 'About' },\n+]\n+\n+\n+\n+  \n\n+    \n\n+      \n+        {{ link.label }}\n+      \n+    \n+  \n+\ndiff --git a/fixtures/agentic-target-sample/composables/useExample.ts b/fixtures/agentic-target-sample/composables/useExample.ts\nnew file mode 100644\nindex 0000000..54ecd8c\n--- /dev/null\n+++ b/fixtures/agentic-target-sample/composables/useExample.ts\n@@ -0,0 +1,4 @@\n+export const useExample = () =&gt; {\n+  const greeting = ref('Hello from the Nuxt sample fixture')\n+  return { greeting }\n+}\ndiff --git a/fixtures/agentic-target-sample/nuxt.config.ts b/fixtures/agentic-target-sample/nuxt.config.ts\nnew file mode 100644\nindex 0000000..0b5183f\n--- /dev/null\n+++ b/fixtures/agentic-target-sample/nuxt.config.ts\n@@ -0,0 +1,14 @@\n+// https://nuxt.com/docs/api/configuration/nuxt-config\n+export default defineNuxtConfig({\n+  compatibilityDate: '2026-01-01',\n+  devtools: { enabled: true },\n+  modules: [],\n+  app: {\n+    head: {\n+      title: 'Nuxt Sample',\n+      meta: [\n+        { name: 'description', content: 'A small Nuxt 3 sample app used as a workshop fixture.' },\n+      ],\n+    },\n+  },\n+})\ndiff --git a/fixtures/agentic-target-sample/package.json b/fixtures/agentic-target-sample/package.json\nnew file mode 100644\nindex 0000000..bb34d2e\n--- /dev/null\n+++ b/fixtures/agentic-target-sample/package.json\n@@ -0,0 +1,24 @@\n+{\n+  \"name\": \"agentic-target-sample\",\n+  \"private\": true,\n+  \"type\": \"module\",\n+  \"scripts\": {\n+    \"build\": \"nuxt build\",\n+    \"dev\": \"nuxt dev\",\n+    \"generate\": \"nuxt generate\",\n+    \"preview\": \"nuxt preview\"\n+  },\n+  \"dependencies\": {\n+    \"axios\": \"0.21.0\",\n+    \"lodash\": \"4.17.20\",\n+    \"minimist\": \"1.2.5\",\n+    \"serialize-javascript\": \"3.0.0\"\n+  },\n+  \"devDependencies\": {\n+    \"@nuxt/devtools\": \"latest\",\n+    \"nuxt\": \"^3.13.0\",\n+    \"typescript\": \"^5.5.0\",\n+    \"vue\": \"^3.5.0\",\n+    \"vue-router\": \"^4.4.0\"\n+  }\n+}\ndiff --git a/fixtures/agentic-target-sample/pages/about.vue b/fixtures/agentic-target-sample/pages/about.vue\nnew file mode 100644\nindex 0000000..7be546c\n--- /dev/null\n+++ b/fixtures/agentic-target-sample/pages/about.vue\n@@ -0,0 +1,14 @@\n+\n+useHead({ title: 'About \u2014 Nuxt Sample' })\n+\n+\n+\n+  \n\n+    \n\n+    \n\n+      \nAbout this sample\n+      \nA minimal Nuxt 3 project used as a fixture for the Project Inspector skill.\n+      Home\n+    \n+  \n+\ndiff --git a/fixtures/agentic-target-sample/pages/index.vue b/fixtures/agentic-target-sample/pages/index.vue\nnew file mode 100644\nindex 0000000..a847a1b\n--- /dev/null\n+++ b/fixtures/agentic-target-sample/pages/index.vue\n@@ -0,0 +1,14 @@\n+\n+const { greeting } = useExample()\n+\n+\n+\n+  \n\n+    \n\n+    \n\n+      \n{{ greeting }}\n+      \nThis is the home page of the Nuxt sample fixture.\n+      About\n+    \n+  \n+\n-- \n2.43.0\n\n", "creation_timestamp": "2026-05-19T01:47:50.000000Z"}]}