Skip to content

feat: add AdCP certification program#1348

Merged
bokelley merged 25 commits intomainfrom
bokelley/certification-program
Mar 11, 2026
Merged

feat: add AdCP certification program#1348
bokelley merged 25 commits intomainfrom
bokelley/certification-program

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

@bokelley bokelley commented Mar 7, 2026

Summary

  • Complete three-tier certification program (Basics → Practitioner → Specialist) with 16 learning modules across 5 tracks
  • Addie-led learning with scoring guides, exercises, and adaptive assessment
  • Certifier.io integration for verifiable digital badges (group IDs pending setup)
  • Site-wide integration: nav links, dashboard progress, member profile credentials, org team summary, member card badges

What's included

Backend (3 migrations, 5 new TypeScript files):

  • certification_tracks, certification_modules, learner_progress, certification_credentials, user_credentials tables
  • REST API: public tracks/credentials, authenticated progress/start/complete, org certification summary
  • Certifier API client for badge issuance
  • Auto-credential awarding when module requirements are met

Addie (7 new tools):

  • check_certification_progress, start_certification_module, evaluate_exercise, score_assessment, complete_module, start_capstone_exam, complete_capstone_exam
  • Certification-aware routing and system prompt updates

Content (11 Mintlify pages + 2 HTML pages):

  • Foundation modules (A1-A3), specialization tracks (B, C, D), specialist capstones (E1-E4)
  • Study guide with FAQ and preparation resources
  • Certification portal with interactive track/credential display

Site integration (8 files modified):

  • Certification + Study guide in "The Latest" nav dropdown
  • "Get certified" suggested prompt in Addie web chat
  • Dashboard section with progress ("X of Y completed") and credential badges
  • Org dashboard team certification summary with per-member breakdown
  • Credential tier badges (L1/L2/L3) on member cards
  • Design system tokens for credential tier colors

Test plan

  • All pre-existing tests pass (schema, example, migration, unit, integration)
  • TypeScript compiles (no new errors)
  • Playwright visual testing: nav, portal, study guide, chat, dashboard, members
  • API endpoints verified: tracks (200), credentials (200), progress (200), my-credentials (200)
  • Expert review feedback addressed (code, product, CSS, accessibility)
  • Verify Certifier badge issuance after group IDs are configured
  • Test full learning flow: start module → exercise → complete → auto-award credential

🤖 Generated with Claude Code

bokelley and others added 11 commits March 6, 2026 21:40
Complete certification system for AgenticAdvertising.org:

Backend:
- Database schema (learner_progress, certification_credentials, user_credentials)
- REST API routes for tracks, modules, progress, credentials, org summary
- Certifier API client for badge issuance (group IDs pending)
- Auto-award credentials when module requirements are met

Addie integration:
- 7 certification tools (check_progress, start_module, evaluate_exercise, etc.)
- Certification-aware routing and system prompts
- Learning mode with scoring guides and exercises

Content:
- 16 modules across 5 tracks (Foundations, Publisher, Buyer, Platform, Specialist)
- 11 Mintlify learning path pages with exercises and scoring guides
- Study guide page with FAQ and preparation resources
- Certification portal with three-tier credential display

Site integration:
- Nav links in "The Latest" dropdown (Certification, Study guide)
- "Get certified" suggested prompt in Addie web chat
- Dashboard certification section with progress display
- Dashboard sidebar link between Team and Membership
- Org dashboard team certification summary
- Credential badges on member cards (L1/L2/L3)
- Credentials section on member profile page
- Design system tokens for credential tier colors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ls field

- Changed /api/me/certification/credentials to use getPublicUserCredentials
  (joins certification_credentials for name/tier) instead of raw getUserCredentials
- Added credentials field to /api/me/certification/progress response
- Dashboard now reads credentials (with name/tier) instead of legacy certifications

Fixes: credential badges showed "undefined" for name and tier on dashboard and profile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Updated credential seed data with 5 Certifier group IDs (Signals skipped for now)
- Added Addie signature images for certificate badges (white + transparent bg)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Certification is a participation activity, not news content. Also removes
study guide as a standalone nav item since it's part of the certification flow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nd API

- Add explicit route handlers for /certification and /study-guide with requireAuth
- Redirect .html variants to clean URLs
- Skip certification paths in generic HTML middleware
- Gate /api/certification/tracks and /api/certification/modules/:id with requireAuth
- Keep /api/certification/credentials and /api/certification/users/:userId/credentials
  public (needed for profile badges on public member pages)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Link "Seek professional certification" table row to /certification
- Add certification mention with link in "What Membership Means" section
- Update join CTA benefit text to reference three-tier credential model

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…el fields

The /api/config endpoint returns user data nested under `config.user`,
but certification.html was reading `config.isAuthenticated` and
`config.isMember` which don't exist. This caused logged-in users to
be redirected to login when clicking "Start" on a learning module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Advanced users can skip modules they already know. Adds:
- "Assess my level" button on certification page (for users with no progress)
- test_out_modules Addie tool — marks modules as tested_out after probing assessment
- Chat deep links: ?topic=certification&module=A1 and ?action=assess
- Certification tools registered in web chat (were Slack-only)
- tested_out status treated as completed for prerequisites and credentials

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…sers

escapeHtml was defined inside setupGlobalSearch() but called by
buildNavHTML() in the outer scope, causing a ReferenceError that
prevented the navigation bar from rendering on any page with
authenticated user data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
getWebMemberContext called workos.userManagement.getUser() with dev
user IDs like user_dev_member_001, which aren't real WorkOS IDs. The
API call failed silently, returning a context without workos_user,
causing all certification tools to respond with "link your account."

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bokelley
Copy link
Copy Markdown
Contributor Author

bokelley commented Mar 9, 2026

Let's make sure that we red team this a bit. Let's see if we can trick Addy into giving us the certification, whether that's copy and paste in documentation or trying to get her to give us the simple answers or whatever else. Let's make sure that's not the case.

@bokelley
Copy link
Copy Markdown
Contributor Author

bokelley commented Mar 9, 2026

I wonder if we should give Addy the operating instruction here that she should be almost like a private tutor. Her job is to assemble all the information someone needs, and even inside any module, maybe we just open it up for the users and say, "What do you know about ADCP?"

"Help me understand what you're starting with." You can just tell me anything you know or anything you're curious about. Just tell me how to start.

@bokelley
Copy link
Copy Markdown
Contributor Author

bokelley commented Mar 9, 2026

Let's make sure there's a voice input. I know some people have Willow, but of course, other people may just want to have a little button they can press to record. I don't know if Tablas has this or if there are easy ways just to let people talk.

And I guess they could go into the full Addy chat experience, like the chat with Addy. Maybe there's a cheaper, faster version that's just the voice chat. But I still think latency is pretty high for that.

@bokelley
Copy link
Copy Markdown
Contributor Author

bokelley commented Mar 9, 2026

Have we thought about how to make sure that it's easy for people to share their certifications? When they have those, it's like a link to my LinkedIn or give them promotional text to tell them how to tell their friends, "Hey, I just got that CB Basics certification. Here's how you get that." I'm just trying to make this as viral as possible.

There's also a PR open for GEO, like how to get people to refer to adcp and aao. Maybe thiscan be part of that.

bokelley and others added 14 commits March 9, 2026 06:28
Teaching improvements:
- Addie acts as a private tutor, not a proctor — starts by understanding
  what the learner already knows and builds from there
- Mixed question formats: open-ended, multiple-choice, comparisons,
  scenario-based problems
- Only scores dimensions actually assessed (no phantom protocol_fluency)
- Target 90%+ in every dimension by teaching more, not by accepting
  low scores — if the teaching is good, scores should be high
- Links to learning resources throughout conversation, not just at end
- Per-module resource maps with docs, study guides, and reference pages

Security fix:
- Removed REST API module completion endpoint — was exploitable to
  self-report perfect scores with zero teaching, auto-earning credentials
- Exam completion endpoint returns 410 Gone with guidance to use Addie
- Module completion now only possible through Addie's tool calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add buildShareLinks() to certification-tools.ts — generates cert.io,
  LinkedIn "Add to profile", and dashboard links on module/exam completion
- Fix chat feedback prompt appearing mid-lesson: suppress when Addie's
  last message ends with a question, increase idle timeout from 45s to 3min
- Track lastAssistantContent on conversation load so question detection
  works for resumed threads
- Add certification program section to CLAUDE.md with impact checklist

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The seed migration's key_concepts contained protocol facts that Addie
parroted verbatim, leading to stale/incorrect teaching (e.g., claiming
AdCP only runs on MCP, missing A2A; governance only covers property
lists and content standards, missing creative policy).

Replace all key_concepts "explanation" fields with "teaching_notes" that
tell Addie *what to teach and how*, not *what the facts are*. The docs
are the single source of truth for protocol facts; the curriculum is
the source of truth for pedagogy.

- New migration 265 updates all 16 modules' key_concepts
- certification-db.ts type updated to support both formats
- certification-tools.ts prefers teaching_notes over explanation
- Adds instruction to never state protocol facts from memory

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…orting

Addie was sometimes teaching module content without calling
start_certification_module first, then awkwardly asking the learner to
confirm what topics were covered. Two new rules:

1. ALWAYS call start_certification_module before teaching — never
   retroactively assess without a progress record
2. Never ask the learner to confirm topics — assess from the
   conversation history, not self-reporting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The LinkedIn "Add certification" form wasn't pre-filling Credential ID
or Credential URL because we weren't passing the certId parameter.
Added certId to both the Addie chat share links and the certification
dashboard share links.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Certifier API was rejecting credential issuance with:
"Custom attribute [custom.credential] is not defined on the workspace
level." This left certifier_public_id null, breaking LinkedIn share
links and cert.io URLs.

Removed custom.credential, custom.tier, and custom.score attributes
from the API call — the credential group template already encodes
this info. Also removed unused QR code CSS (Certifier handles QR
codes on their hosted pages).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move credential sharing inline with tier cards — when a credential is
earned, the tier card expands to show:
- One-click share to X with pre-written viral copy encouraging others
  to get certified
- Share on LinkedIn (feed post) and Add to LinkedIn profile
- View credential & QR code link (cert.io hosted page)
- Embeddable badge snippets (HTML and Markdown) for email signatures,
  websites, and READMEs

The sharing panel appears right at the top of the page where credentials
are most visible, instead of buried at the bottom.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…posts

- Show Certifier badge image and QR code link in tier cards when earned
- Fix X share: separate text and url params for proper card rendering
- Fix LinkedIn share: accept that share-offsite only carries URL
  (LinkedIn generates preview card from cert.io page metadata)
- Keep Add to LinkedIn profile for certification section
- Use Certifier badge image in embed snippets instead of org logo
- Remove old bottom credentials section (sharing is now inline)
- Add getOwnUserCredentials() that returns certifier IDs to the owner
- Update /api/me/certification/credentials to include certifier data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The badge image URL cert.io/c/{id}/badge returns HTML, not an image.
Credentials awarded during the earlier custom attributes bug had NULL
certifier IDs, so sharing links were broken.

- Add getCredentialDesigns/getCredentialBadgeUrl to certifier-client
- Store badge CDN URL in new certifier_badge_url column (migration 266)
- Fetch and store badge URL when issuing credentials
- Add admin backfill endpoint for credentials missing certifier data
- Strip internal certifier_group_id from public credentials API
- Escape credential names in embed snippets

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Addie was re-assessing learners on modules they already completed.
Added rule 9: call get_learner_progress first, then only assess
incomplete modules during placement assessments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cert.io/c/{publicId} redirects to cert.io/main/ — the correct domain
for Certifier credential pages is credsverse.com/credentials/{publicId}.
Fixes LinkedIn share (which needs a non-redirecting URL to scrape OG tags)
and the "View credential" verification link.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restructure the curriculum around hands-on learning and building:

Foundations (free, 5 modules):
- A1: Your first agent conversation (query live agents across 19 channels)
- A2: Your first media buy (Addie runs a real buy for you)
- A3: Product data and catalogs (feeds, PMAX, 13 catalog types)
- A4: Accounts, brands, and billing (how money flows)
- A5: The ecosystem (governance, participation)

Role tracks now include build projects (B4, C4, D4) where learners
create working AdCP integrations using starter templates and any AI
coding assistant.

New specialist track (S1-S5) replaces old E-track capstones:
- S1: Media buy mastery
- S2: Creative mastery
- S3: Signals and audiences
- S4: Governance and brand safety
- S5: Sponsored Intelligence (new)

Credentials updated:
- Basics renamed to "AdCP Explorer" (requires A1+A2+A3)
- Practitioner requires A1-A5 + complete role track with build project
- 5 specialist credentials (added Sponsored Intelligence)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Teaching quality improvements (expert-reviewed, 9.4/10):
- Per-request teaching rule reinforcement in buildCertificationContext
  so critical rules survive long conversations (150 word limit,
  mandatory questions, turn variety, inline doc links, demo pivot,
  self-assessment prompts)
- Scaffold-then-fade pedagogy, session resumption with retrieval,
  coverage-vs-brevity triage, delight patterns, reflection moments
- Edge case handling: disengaged learners, overqualified fast-track,
  no-demo fallback, tangent redirect, retake anti-memorization
- Tone calibration and domain mapping guidance
- Stronger resource injection with inline link directive

Anti-gaming hardening:
- Score inflation detection (>20pt jump from checkpoint rejected)
- Shared validateCompletionScores() and checkAndFormatCredentials()
- Scaled placement turns by module count
- A3 dimension rebalancing (synthesis 15%→25%)

Code review fixes:
- Fix non-null assertion on weightMap.get() that could silently corrupt scores
- Let countUserTurns propagate DB errors instead of returning 0
- Normalize checkpoint module_id casing with toUpperCase()
- Guard against empty score objects in get_learner_progress
- Parallelize DB calls in buildCertificationContext with Promise.all

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Main introduced migrations 262-268 for geo/brand features. Renumber
certification migrations from 262-272 to 269-279 to run after main's.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bokelley bokelley merged commit b96dcf0 into main Mar 11, 2026
8 checks passed
@bokelley bokelley deleted the bokelley/certification-program branch March 11, 2026 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant