Skip to content

Conversation

@BaiyuScope3
Copy link
Collaborator

@BaiyuScope3 BaiyuScope3 commented Jan 5, 2026

Merge main into 2.6.x and update schema references

Catch up with latest main
Update 2.6.x referencing the 2.6.x schema in the document

Changes

  • Merge main: Brings in docs versioning support, workflow updates, and 2.5.2 changelog
  • Update schema references: Documentation now references /schemas/2.6.0/
  • Release announcement: Updated intro to announce v2.6.0 with unified assets feature

Version (rc)

  • Package version: 2.6.0
  • Schema registry: 2.6.0

nastassiafulconis and others added 30 commits December 17, 2025 09:04
Update documentation to show MCP responses with task-specific fields
at the top level instead of nested inside a `data` wrapper.

This aligns docs with what @adcp/client actually expects:
- `response.products` instead of `response.data.products`
- `response.media_buy_id` instead of `response.data.media_buy_id`

Files updated:
- mcp-guide.mdx: Updated response format section and examples
- core-concepts.mdx: Updated response structure and code examples
- getting-started.mdx: Updated MCP quick comparison example
- protocol-comparison.mdx: Updated all MCP response examples
- a2a-guide.mdx: Fixed incorrect `response.data` usage in A2A context

Note: A2A examples correctly remain with `{"kind": "data", "data": {...}}`
inside artifact parts, which is proper A2A protocol structure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…creatives

Instead of showing raw A2A artifact parsing code, reference the
sync_creatives task reference which has proper testable examples
using @adcp/client.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Consolidate to single Slack bot (Addie) instead of dual-bot setup:

- ADDIE_BOT_TOKEN is now primary, with SLACK_BOT_TOKEN fallback for migration
- Remove useAddieToken parameter from sendChannelMessage and getThreadReplies
- Remove getSlackUserWithAddieToken helper function (use getSlackUser instead)
- Update all callers to use simplified API
- Update error messages to reference ADDIE_BOT_TOKEN

This fixes the industry alerts "not_in_channel" error since Addie (not the
AAO bot) is the bot added to notification channels.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add event registrations to contact activity history

Extends the contact activity API to include event registrations
alongside email activities using a UNION query. This provides a
unified view of all engagement with a contact.

The activity response now includes:
- activity_type: 'email' or 'event_registration'
- title: email subject or event title
- description: email direction or registration status
- metadata: includes event_id, event_slug, ticket_type, attended

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Extract CONTACT_ACTIVITIES_QUERY to shared constant

- Reduces code duplication between two contact endpoints
- Adds NULL::TEXT cast for explicit type in UNION
- Adds NULLS LAST to ORDER BY for consistent sorting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
When streaming responses in Assistant threads, we were always passing
thread_ts (falling back to event.ts for new threads), which caused Slack
to create a nested thread on the user's message. Now we only pass
thread_ts when continuing an existing thread.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…t level to Addie (#492)

- Email webhook now auto-links contacts to orgs by domain lookup (falls back after
  membership lookup fails). This fixes contacts from prospect emails not being linked
  to their organization when the domain is already verified.

- Admin org detail page improvements:
  - Moved Account Team section to top of left column for visibility
  - Replaced "I'm connected" button with role dropdown (Owner/Interested/Connected)
  - Fixed interest level modal display style consistency

- Added interest_level parameter to Addie's update_prospect tool so she can set
  prospect interest levels when logging notes with engagement signals.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Replace verbose priority headers (":star: HIGH - Agentic AI in Advertising")
  with clean article title as the Slack header
- Change "addie_notes" prompt from explanatory to engagement-driving "addie_take"
  with spicy, opinionated takes that end with discussion prompts
- Remove summary section from Slack alerts (Slack unrolls links anyway)
- Remove tags from Slack output (kept in DB for filtering)
- Fix HTML entity decoding in RSS feed titles (&#x27; → ')
- Reduce false positives in agentic/AdCP detection by only checking
  original article content, not AI-generated summaries
- Add defensive validation for Slack header length (150 char limit)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Fix Addie not seeing forwarded Slack messages

When users forward messages in Slack (via channel @mention or DM), the
forwarded content is in the `attachments` array, not the `text` field.
This caused Addie to miss the forwarded content entirely.

Changes:
- Add `extractForwardedContent()` helper to extract text from attachments
- Apply extraction in `handleAppMention` for channel @mentions
- Apply extraction in `handleDirectMessage` for DMs
- Update type guard in `handleChannelMessage` to allow DMs with attachments

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add reaction confirmations, file awareness, and URL extraction

- Reaction confirmations: When users react to Addie's messages with
  thumbs up/check, treat as "yes, proceed". Thumbs down/X means no.
  Non-confirmation reactions are recorded as feedback.

- File share awareness: Extract file metadata (name, type, size, link)
  from file_share messages so Addie knows what files were shared.

- URL extraction: Helper function to extract URLs from Slack messages
  for future link-following capability.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add URL fetching and Slack file reading tools

New tools for Addie:
- fetch_url: Fetch and read content from web URLs shared in messages
  - Extracts text from HTML
  - Supports text/html/markdown extraction modes
  - Handles timeouts and size limits
  - Blocks localhost and local IPs

- read_slack_file: Download and read files shared in Slack
  - Uses bot token for authentication
  - Supports text-based files (txt, md, json, code files, etc.)
  - Gracefully handles PDFs and images (acknowledges but can't read)
  - Enforces size limits

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add unified account management system

- Add migration 100 for user_stakeholders and action_items tables
- Create account-management-db.ts service for stakeholders and action items
- Add momentum-check.ts job for analyzing outreach and creating action items
- Enhance admin-users.html with action items panel and My Accounts tab
- Reorganize admin sidebar with Account Management section
- Add API routes for action items (list, create, complete, dismiss, snooze)
- Add dry-run and preview endpoints for momentum check testing
- Update outreach service to auto-assign stakeholders

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add journalist-proofing and outreach improvements for Addie

Key changes:
- Add sensitive topic detection with 40+ patterns across 8 categories
  (vulnerable populations, political, named individuals, org positions,
  media inquiries, competitive, privacy/surveillance, ethical concerns)
- Deflect high-severity questions to human contacts automatically
- Track known media contacts with configurable handling levels
- Flag conversations for admin review queue

Outreach improvements (from red team testing):
- Add response sentiment/intent analysis (positive, negative, refusal, deferred)
- Detect refusal patterns and respect opt-outs
- Parse "remind me later" intents and schedule follow-ups
- Add grace period for new Slack members (24 hours)
- Add improved message variants (loss-framed, peer-triggered, etc.)
- Add tire-kicker detection in momentum checks

New admin tools:
- add_media_contact: Flag journalists for careful handling
- list_flagged_conversations: Review queue for sensitive topics
- review_flagged_conversation: Mark items as reviewed

Testing framework:
- User journey simulator with realistic personas
- Red team scenarios for edge cases
- Action trigger validation tests
- Sensitive topic detection tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Implements a personalized "mission control" experience for Addie that works
in both Slack's App Home tab and the web chat interface.

Architecture:
- Platform-agnostic HomeContent data structure
- Separate builders for alerts, activity, stats, quick actions, admin panel
- Slack Block Kit renderer and HTML renderer
- Per-user TTL cache (5 minutes)

Features:
- Personalized greeting with membership status
- Alerts for pending invoices, incomplete profiles, upcoming renewals
- Activity feed with upcoming events and working group activity
- User stats (working groups, Slack activity, subscription status)
- Admin panel with flagged threads and insight goal progress
- Quick actions that route through Addie conversations

Web integration:
- GET /api/me/addie-home endpoint for authenticated users
- Addie Home displayed on chat.html for logged-in users
- Admin preview in user context modal (/admin/users)

Security improvements from code review:
- Input validation on admin preview endpoint
- Action ID whitelist validation
- URL protocol validation for links

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Replace daily digest with paced single-article posting:
- Quality 5 articles post immediately
- Quality 4 articles post only if channel quiet for 3+ hours
- Quality < 4 articles ignored (not relevant for Slack or website)

Add community article amplification:
- React with 👀 when someone shares an article in managed channels
- Queue shared articles for processing through content pipeline
- Reply with Addie's take after processing

Fixes SQL injection vulnerability in isChannelQuiet function.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
PostgreSQL requires partial index predicates to use IMMUTABLE functions,
but CURRENT_DATE is STABLE. The date filtering can happen at query time
instead.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Fix migration 101: Remove CURRENT_DATE from index predicate

PostgreSQL requires partial index predicates to use IMMUTABLE functions,
but CURRENT_DATE is STABLE. The date filtering can happen at query time
instead.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add safer deployments and enhanced health checks

1. Use release_command for migrations
   - Migrations now run ONCE before deployment, not on every machine
   - If migrations fail, deployment is automatically rolled back
   - Prevents both machines from crashing on bad migrations

2. Enhanced /health endpoint
   - Checks database connectivity
   - Checks Addie readiness
   - Returns 503 if any check fails (triggers Fly health alerts)
   - External uptime monitors can use this for alerting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Add database migration for org discount fields (percent, amount, reason, granted_by, etc.)
- Add Stripe coupon/promotion code creation functions
- Enable promotion codes for one-time payments (was subscription-only)
- Add admin HTTP routes for discount management
- Add Addie admin tools: grant_discount, remove_discount, list_discounts, create_promotion_code
- Add input validation for discount bounds (1-100% or positive amounts)

This allows admins to grant discounts to organizations (like startups) and create
promotion codes they can use at checkout. Discounts are tracked at the org level
with attribution (who granted it and why).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The users table has workos_user_id VARCHAR(255) as its primary key,
not an integer id column. Fixed the foreign key references in
flagged_conversations and known_media_contacts tables.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Bug: Addie's list_pending_invoices tool only checked organizations with
stripe_customer_id in our database, missing invoices for customers not
yet linked (e.g., sent via send_invoice without saving customer ID back).

Fix: Query Stripe directly for all open/draft invoices instead of
iterating over database organizations. The tool now:
- Queries Stripe API for all open and draft invoices
- Extracts customer info including workos_organization_id from metadata
- Matches invoices to organizations where possible
- Falls back to showing customer name for unlinked invoices
- Shows total amount due across all invoices

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Implements tools to detect and resolve organization duplicates in the
membership system, ensuring every corporate email domain maps to a
known organization (member or prospect).

New features:
- Organization merge tool (mergeOrganizations, previewMerge) in db layer
- Addie admin tools: merge_organizations, find_duplicate_orgs, check_domain_health
- Domain Health admin page at /admin/domain-health with:
  - Orphan domains (corporate emails without organizations)
  - Misaligned users (corporate users in personal workspaces)
  - Unverified organizations (orgs without verified domains)
  - Domain conflicts (multiple orgs claiming same domain)
- API endpoint at /api/admin/domain-health

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Remove duplicate `const selectedOrg` declaration at line 2146 that was
causing "Cannot declare a const variable twice" JavaScript error,
preventing users from logging in. The variable was already declared
at line 2126 in the same scope.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The marked.js parser was producing garbled output when receiving incomplete
markdown during streaming (e.g., unbalanced ** for bold text). Added a
hasBalancedMarkdown() check that validates markdown markers are balanced
before rendering, falling back to plain text if not.

- Uses arithmetic instead of lookbehind regex for Safari < 16.4 compatibility
- Checks for balanced **, *, `, and ``` markers
- Falls back to plain text rendering when markers are unbalanced
- Final message is always rendered with full markdown after streaming completes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Fix navigation showing "Log in/Sign up" when user is authenticated by adding
  session refresh to `getUserFromRequest()` and updating the cookie when refreshed
- Hide "0 Messages" and "0 Active Days" stats when there's no activity
- Include web chat messages in user stats alongside Slack activity by:
  - Adding `getUserActivityStats()` method to thread-service.ts
  - Adding `conversation_activity` to member context
  - Updating stats builder and renderer to prefer combined stats
- Use `last_message_at` instead of `started_at` for active days calculation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add unified payment request tool and quick action bar

- Add `send_payment_request` Addie tool that:
  - Finds or creates prospects by name/domain
  - Shows contacts and registered users
  - Generates Stripe payment links
  - Sends invoices with billing address
  - Suggests membership tier based on company size

- Add Quick Action Bar to admin prospects page:
  - Type-to-search for companies
  - One-click payment link or invoice generation
  - Create new prospect if not found
  - Pre-fills forms with contact info

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add discount support to payment links

- Add couponId and promotionCode parameters to createCheckoutSession
- Pre-apply discounts to Stripe checkout sessions
- Add discount_percent, discount_amount_dollars, discount_reason
  parameters to send_payment_request Addie tool
- Auto-apply existing org discounts when generating payment links
- Create new discounts on-the-fly when requested

Now Addie can handle requests like:
- "Give Acme a 20% discount and send them a payment link"
- "Send a discounted link to the startup"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add Addie email response capability

When Addie is CC'd on prospect emails and explicitly invoked (e.g., "Addie,
send a payment link"), she can now process the request and reply in the
email thread.

Changes:
- Add email-handler.ts for detecting Addie invocations and processing requests
- Add sendEmailReply to notifications/email.ts with proper threading headers
- Add 'email' event type to AddieInteractionLog for audit logging
- Wire up email handler in bolt-app.ts initialization
- Pass workosUserId (not contactId) for proper admin authorization
- Sanitize email metadata in prompts to prevent injection
- Validate fromEmail domain to prevent spoofing
- Fix recipient filtering to use domain-based exclusion

Security improvements based on code review:
- Sanitize email From/Subject before including in Claude prompt
- Validate fromEmail is from agenticadvertising.org domain
- Use domain-based pattern for excluding our addresses from recipients

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…#508)

When both member context and channel context were present in Slack
messages, they were concatenated directly without proper markdown
paragraph spacing. This caused sections to run together visually.

Changes:
- Remove leading \n from channel context header (was a workaround)
- Use array filter/join pattern to properly space sections with \n\n
- Add extra newline before --- separator for consistent formatting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Fix Stripe API expand depth and add trust proxy config

- Remove data.lines.data.price.product from Stripe API expand arrays
  (exceeds 4-level depth limit causing errors)
- Add product caching in getPendingInvoices to fetch products separately
- Configure Express trust proxy for Fly.io to fix rate limiter IP detection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix Fly.io health check to use /health endpoint

- Change health check path from "/" to "/health"
- The homepage "/" can be slow due to external API calls (Stripe, etc.)
- The /health endpoint is designed for quick health checks
- Increase timeout from 2s to 5s and grace_period from 5s to 30s
  to allow proper initialization on startup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add empty changeset for infrastructure fixes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Replace N+1 WorkOS API calls with efficient SQL using LEFT JOIN LATERAL
  to get member emails from local organization_memberships table
- Move 5 members-related routes from http.ts to new members.ts module:
  - GET /api/admin/members (list all members)
  - POST /api/admin/members/:orgId/sync (sync from WorkOS/Stripe)
  - PATCH /api/admin/members/:orgId/memberships/:membershipId (update role)
  - GET /api/admin/members/:orgId/payments (payment history)
  - DELETE /api/admin/members/:orgId (delete workspace)
- Reduces http.ts by ~456 lines

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add configurable billing notification channel for Addie

Replaces the hardcoded webhook-based billing notifications with a
configurable Slack channel that admins can select via a new System
Settings page. This allows billing notifications (new subscriptions,
payments, failures, cancellations) to be sent to a dedicated channel
instead of the general admin channel.

- Add system_settings table for key-value config storage
- Add admin settings API with Slack channel picker
- Add admin-settings.html page under Settings > System Settings
- Create billing notification service using sendChannelMessage
- Update http.ts to use new billing notifications

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix duplicate migration number - rename 105 to 106

Main branch already has 105_addie_email_event_type.sql, so renaming
the system_settings migration to 106.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add regional chapters and industry event presence features

Enable user location tracking and event groups for member engagement:

- Add user location tracking (city, country) with migration 105
- Add event groups (committee_type: 'event') linked to industry events with migration 106
- Implement Slack channel auto-sync: joining a channel auto-adds users to working groups
- Add admin UI sections for event groups in Events admin page
- Add 'event' committee type filter to Working Groups admin page
- Create Addie tools for member-driven chapter creation
- Add UUID validation and member count to event group API endpoints
- Fix SQL injection in findChaptersNearLocation with proper LIKE escaping

This enables temporary "chapter-like" groups for industry events like CES and Cannes Lions,
where Slack channel membership automatically syncs to working group membership.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix migration version conflict with main branch

Renumber migrations to avoid conflict with 106_system_settings.sql:
- 106_user_location.sql → 107_user_location.sql
- 107_event_groups.sql → 108_event_groups.sql

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Add 6 missing tables to database merge: revenue_events, subscription_line_items,
  event_registrations, event_sponsorships, user_agreement_acceptances, org_admin_group_dms
- Add WorkOS membership sync: migrate users from secondary org to primary org
- Delete secondary organization from WorkOS after merge
- Add Stripe warnings in preview for secondary orgs with customers/subscriptions
- Update merge_organizations tool description to clarify preview vs execute
- Add pagination warning for orgs with >100 members
- Remove obsolete migration script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Replace N+1 WorkOS API calls for member counts with a single batch SQL
query against the local organization_memberships table. This eliminates
the serialized HTTP calls that were causing 2-3 second load times.

The organization_memberships table is kept in sync via WorkOS webhooks,
so member counts remain accurate.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add agent context system with secure token storage for Addie

- Add agent_contexts and agent_test_history tables for persisting agent URLs
- Implement AES-256-GCM encrypted token storage with org-specific keys
- Add save_agent, list_saved_agents, remove_saved_agent tools to Addie
- Extend test_adcp_agent to auto-lookup saved credentials and record history
- Add agent-tester.ts with E2E test scenarios including response_consistency

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix BASE_URL port priority for Docker internal calls

PORT (internal server port, 8080 in Docker) should take precedence over
CONDUCTOR_PORT (external mapping) when making internal API calls.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add Addie testing documentation to testing.mdx

Document the new E2E agent testing capabilities:
- Testing scenarios (discovery, full_sales_flow, etc.)
- Edge case scenarios (error_handling, validation)
- Behavioral analysis features
- Sales agent compliance checklist

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add GitHub issue offer for open-source agent test failures

When users test agents via Addie and the tests fail on a known open-source
agent (test-agent.adcontextprotocol.org, wonderstruck.sales-agent.scope3.com,
or creative.adcontextprotocol.org), Addie now offers to help file a GitHub
issue to the appropriate repository.

Also refactors to use @adcp/client/testing library directly instead of local
agent-tester.ts wrapper:
- Imports runAgentTests, formatTestResults, createTestClient from library
- Adds call_adcp_tool handler for raw task execution
- Removes redundant local agent-tester.ts (2570 lines)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add image/iframe support to web chat and update homepage link

- Update homepage "Test AdCP" button to route to Addie chat (/chat.html)
  instead of external testing.adcontextprotocol.org
- Add image support to chat.html with clickable images that open in new tab
- Add iframe support for creative previews with sandbox and styling
- Add CSS styles for embedded images and creative preview containers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add "Try AdCP live" prompt and fix migration conflict

- Add "Try AdCP with a test agent" as suggested prompt in Addie chat
  (replaces "Become a member" to encourage testing)
- Rename 079_agent_contexts.sql to 109_agent_contexts.sql to resolve
  migration number conflict with main branch

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add query string prompt parameter to chat.html

- Support ?prompt= query parameter to pre-fill and auto-send a message
- Update homepage "Test with Addie" button to include prompt parameter
- Waits for Addie to be ready before sending, with 10s timeout
- Cleans URL after sending to avoid re-triggering on refresh

Now clicking "Test with Addie" on homepage will automatically trigger
the test agent flow: /chat.html?prompt=Try%20AdCP%20with%20a%20test%20agent

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix check-snippets CI workflow to use .cjs extension

The script file is check-testable-snippets.cjs but the workflow
was referencing check-testable-snippets.js, causing CI failures.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
bokelley and others added 28 commits January 4, 2026 19:30
* Redesign chat UI with vertical sidebar tabs

- Replace floating "Chats" button with always-visible vertical sidebar
- Add Home tab, New Chat button, Active section, History section
- Implement activity indicators (pulsing yellow when thinking, green when ready)
- Add browser notifications (opt-in) when Addie finishes responding
- Track active tabs in localStorage with max 7 tabs
- Add document title unread count badge
- Mobile: collapsible sidebar with hamburger menu
- Security fixes: validate URLs in image/iframe rendering, sandbox HTML creatives
- Performance: use event delegation for tab clicks, debounce thread refresh

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add native app safe area support for sidebar

Add CSS rules to ensure the chat sidebar works correctly in native
mobile/desktop apps (Tauri, Capacitor) with proper handling of iOS
safe area insets for the notch, home indicator, and landscape mode.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Create dedicated /industry-gatherings page with API endpoint
- Update nav to link to /industry-gatherings instead of /committees filter
- Fix event timezone display - use event's timezone instead of viewer's local
- Add external event support:
  - New external_registration_url and is_external_event fields
  - Committee admins can mark events as third-party (CES, etc.)
  - Event detail page shows "Register on Event Site" for external events
  - "Industry Event" badge for external events

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add enforcement and admin tools for personal vs team accounts

- Enforce personal workspace restrictions:
  - Block invitations to personal workspaces
  - Block join request approval for personal workspaces
  - Block domain verification for personal workspaces

- Update onboarding to clarify individual account limitations:
  - Updated description on individual option
  - Added prominent warning box listing restrictions
  - Added link to go back if user meant to join as company

- Update UI to hide team features for personal workspaces:
  - Hide Team nav item in dashboard sidebar
  - Hide Team section on main dashboard
  - Show notice on team page explaining limitations

- Add admin tools for account management:
  - PUT /admin/accounts/:id/account-type - convert between personal/team
  - POST /admin/accounts/:id/migrate-members - move members between accounts
  - Account type badge on admin detail page (clickable to convert)
  - Migrate Members modal with member selection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Address code review feedback

- Fix race condition: add to target org before removing from source
- Update local cache when migrating members to target org
- Add validation for user_ids array in migrate-members endpoint
- Fix duplicate HTML ID (migrateMembersBtn -> migrateMembersSubmitBtn)
- Add changeset

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Fix profile goal to only show for paid members and handle personal workspaces

- Add is_member to PlannerContext to track membership status
- Add is_personal_workspace to company context to identify auto-generated workspaces
- Profile completion goal now only shows for paid members (profiles are only visible to members)
- Personal workspaces show as "your account" instead of "User's Workspace"
- Remove legacy addie_goal fallback in admin-users.html (planner is now primary)
- Update all PlannerContext construction sites with new required fields

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add admin collaboration features for outreach

- Add insight button to admin user detail panel
- Update year references (2025 -> 2026 cleanup) via migration 132
- Add vendor membership goal for tech companies via migration 133
- Add admin nudge/override for outreach direction
- Fix message personalization to use first name instead of full name
- Fix input validation for goal_id in admin insights endpoint
- Fix event listener accumulation in nudge modal
- Fix personal workspace detection consistency across files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Renumber migrations to avoid conflict with main

Migrations 132 and 133 already exist on main, so renumber ours to 134 and 135.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Fix mobile responsive styles for organization profile modal

The organization profile modal on dashboard pages was not mobile-responsive,
causing text to be truncated on narrow screens (e.g., "AI & Te..." instead
of "AI & Tech Platforms").

Changes:
- Add @media (max-width: 480px) responsive styles to dashboard.html and
  dashboard-membership.html
- Modal goes full-screen on mobile with reduced padding
- Add iOS safe area support (env(safe-area-inset-*)) for notched devices
- Use 100dvh for dynamic viewport height on iOS

Also adds Playwright test suite for mobile viewport testing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Remove playwright tests (used for verification only)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Add "Add to Org" button for misaligned users (Users Who Should Join Their Company)
  - Modified misaligned_users query to include target_org_id and target_org_name
  - Shows which org the user should be added to based on their email domain
  - One-click to add all users from a domain to the company org

- Add "Link Domain" button for Organizations Without Verified Domains
  - Suggests first corporate domain found from user emails
  - Filters out personal email domains (gmail, yahoo, etc.)
  - One-click to link domain to the organization

- New API endpoint: POST /api/admin/organizations/:orgId/add-users
  - Accepts array of user IDs
  - Validates org exists and is not personal workspace
  - Adds membership records for users
  - Includes input validation and rate limiting (max 100 users)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Add API endpoints for response rates by goal type and time-series stats
- Add migration 136_outreach_goal_stats.sql with analytics views
- Enhance user context page with detailed outreach history and thread links
- Add Analytics tab to admin-outreach.html with goal performance metrics
- Fix null check in getOutreachTimeStats() for empty data
- Use encodeURIComponent for thread_id in URLs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Extend Slack channel auto-add to all committee types

When users join a Slack channel linked to any committee (working group,
council, chapter, or industry gathering), they are now auto-added as a
member if they have a WorkOS account mapping.

Previously, this only worked for chapters and industry gatherings.

Security: Private (invite-only) groups are explicitly excluded from
auto-add to preserve the intended access control.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Allow private committee sync when Slack channel is also private

For the real-time member_joined_channel event, we now check if the Slack
channel is private (channel_type 'G'). If a private committee is linked
to a private Slack channel, we allow auto-add since Slack already
enforces access control.

For the sync function (when accounts are linked), we only process public
channels since getUserChannels API only fetches public channel
memberships. Private committees remain excluded in this path.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…ort (#611)

* Add committee leadership tools for Addie and industry gatherings support

- Add Addie admin tools: add_committee_leader, remove_committee_leader, list_committee_leaders
- Display industry gatherings in dashboard committees section
- Add "Committee Leader" dev user for testing committee management
- Seed CES 2026 and Cannes Lions 2026 as industry gatherings
- Fix committees nav to link to #committees anchor

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Move Industry Gatherings from Events dropdown to Committees

- Add Industry Gatherings as 5th option in Committees dropdown
- Events nav becomes a simple link instead of dropdown
- Add industry_gathering type config to committees page
- Add Industry Gatherings tab on committees page

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Remove unused industryGatheringsUrl variable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Rename migrations 135/136 to 137/138 to avoid conflicts with main

Main branch now has 135_vendor_visibility_goal.sql and 136_outreach_goal_stats.sql,
so renumber our migrations to 137 and 138.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
When admins edit an organization's name via the admin panel edit form,
the change now syncs to WorkOS before updating the local database.
This ensures the name stays consistent between WorkOS and the local DB.

Changes:
- Pass WorkOS client to setupProspectRoutes
- Update PUT /api/admin/prospects/:orgId to sync name to WorkOS
- Add warning log when WorkOS is not configured
- Include error details in failure responses

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Fix PostgreSQL ROUND() function calls with FILTER clause by wrapping
  aggregate expressions in parentheses before casting to numeric
- Add performance data (latency, tokens, timing) to reaction handler
- Add error handling for reaction message logging
- Add logging when streaming completes without done event
- Change || to ?? (nullish coalescing) to preserve 0 values for tokens

The main bug was SQL queries failing with "function round(double precision,
integer) does not exist" because ROUND() requires numeric type, and the
::numeric cast wasn't being applied to the full aggregate expression.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Changes:
- Fix missing showContextModal function in admin-users.html that was
  causing "Can't find variable" errors when adding insights
- Update Addie's system prompt to use conversational onboarding style
  instead of survey-style questions
- Update suggested prompts to be more casual (e.g., "What brings you
  here?" instead of "What can you help me with?")
- Add migration for new insight types (initial_interest, team_context,
  perspective_preference) and conversational welcome goal

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The profile modal's Continue button wasn't enabling when users selected
options on mobile/some browsers. The issue was that onclick handlers on
<label> elements containing radio buttons don't fire reliably due to
the native label-for-input behavior interfering with the event.

Changes:
- Add proper change event listeners to radio inputs via initProfileModalListeners()
- Refactor to reduce code duplication using a radioGroups array
- Remove redundant inline onclick attributes from labels
- Add CSS :has() fallback for styling when radio is checked
- Explicitly set radio.checked = true in selectProfileOption()

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The `details` property now specifies `"type": "object"` with
`"additionalProperties": true`, making the schema explicit about
what types are accepted.

Fixes #343

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…mcp-response-docs

Fix MCP response format docs to use flat structure
* Add diagnostic logging to email webhook handler

Track progress through prospect email processing to identify where
tracking is failing. Added logs at key checkpoints:
- After contact creation/update
- Before/after insight extraction
- Before/after activity storage
- After contact linking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add empty changeset for diagnostic logging

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add timeout and logging to Anthropic API call

The webhook was hanging at insight extraction. Added:
- 25s timeout to prevent indefinite hangs
- Logging before API call to track progress

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add changeset

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The slug field was missing from COLUMN_MAP in updateWorkingGroup(),
causing slug changes to be silently skipped. Also adds slug format
and uniqueness validation to the PUT endpoint, matching the existing
validation in the POST endpoint.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Fix feed email slug lookup

The webhook extracts email addresses like feed-campaign-uk@updates.agenticadvertising.org
and looks up feeds by slug 'feed-campaign-uk'. However, migration 060 seeded email slugs
without the 'feed-' prefix (e.g., 'campaign-uk'), causing lookups to fail with
"No matching feed found for inbound email".

This adds migration 141 to prepend 'feed-' to existing slugs, matching the format used by
generateEmailSlug() and expected by the webhook handler.

Also adds unit tests for feed email address parsing to prevent regression.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Increase markdown link checker timeout and retries

The CI was failing due to a transient 504 timeout from GitHub.
Increase timeout from 10s to 20s and retries from 3 to 5 with
a 5s fallback delay between retries.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Add `get_account` as the primary tool for looking up any organization
- Introduce `computeLifecycleStage()` function that combines subscription_status
  and prospect_status into a unified view: prospect → contacted → responded →
  interested → negotiating → member (or declined/churned)
- Handle all subscription statuses: active, trialing, canceled, past_due,
  unpaid, incomplete, incomplete_expired
- Mark `lookup_organization` and `find_prospect` as deprecated (still functional)
- Update `find_prospect` to show lifecycle stage instead of raw prospect_status
- Export `LIFECYCLE_STAGE_EMOJI` constant for consistent emoji usage

This fixes the issue where paying members (like Mediaocean) would incorrectly
show as "prospect" in find_prospect because it didn't check subscription_status.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Fix organization_domains column name in interaction-analyzer

The column is workos_organization_id, not organization_id.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add changeset for interaction-analyzer fix

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Add Mintlify versioning support in docs.json
- Create sync-versioned-docs.yml workflow to sync 2.6.x branch to v2.6-rc
- Add local sync script (scripts/sync-versioned-docs.sh)
- Add npm run sync:docs command
- Update broken-links.yml to trigger after sync workflow
- Sync initial v2.6-rc docs from 2.6.x branch
- Update package.json version to 2.5.2
- Update schema registry adcp_version to 2.5.2
- Add changeset for docs versioning feature
- Update CHANGELOG.md with 2.5.2 release notes
- Generated 183 schema files from 2.6.x branch
- Includes bundled schemas (25 files) with resolved $ref
* Add PostHog analytics integration

Adds PostHog for tracking user behavior:
- Rage clicks detection
- Dead clicks detection
- Session recordings (with masked inputs)
- Heatmaps
- Performance metrics

Configuration:
- POSTHOG_API_KEY (optional) - enable by setting your project API key
- POSTHOG_HOST (default: https://us.i.posthog.com)

When a user is logged in, they're identified by their user ID for
filtering sessions. The script respects DNT (Do Not Track) browser
settings and masks all form inputs except search fields.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add error tracking to PostHog integration

Frontend:
- Enable capture_exceptions option
- Add window.onerror handler for uncaught errors
- Add onunhandledrejection handler for promise rejections

Backend:
- Add posthog-node package for server-side tracking
- Create server/src/utils/posthog.ts utility with:
  - captureEvent() for custom events
  - captureException() for error tracking
  - identifyUser() for user identification
  - shutdownPostHog() for graceful shutdown
- Add global Express error middleware to capture unhandled errors
- Flush PostHog events on server shutdown

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
feat: Add Documentation Versioning (2.5 / 2.6-rc)
- Keep version 2.6.0
- Add docs versioning support from main
- Add sync workflow triggers for 2.6.x branch
@github-actions
Copy link
Contributor

github-actions bot commented Jan 5, 2026

IPR Policy Agreement Required

Thank you for your contribution! Before we can accept your pull request, you must agree to our Intellectual Property Rights Policy.

By making a Contribution, you agree that:

  • You grant the Foundation a perpetual, irrevocable, worldwide, non-exclusive, royalty-free copyright license to your Contribution
  • You grant a patent license under any Necessary Claims
  • You represent that you own or have sufficient rights to grant these licenses

To agree, please comment below with the exact phrase:

I have read the IPR Policy

You can read the full IPR Policy here.


I have read the IPR Policy


1 out of 2 committers have signed the CLA.
✅ (bokelley)[https://github.com/bokelley]
@nastassiafulconis
You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@BaiyuScope3 BaiyuScope3 merged commit f002b01 into 2.6.x Jan 5, 2026
5 of 6 checks passed
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.

5 participants