Skip to content

feat(orchestrator): pick task skills by project traits, in shadow - #1497

Draft
edwinyjlim wants to merge 2 commits into
mainfrom
dag/w1-skills-by-traits
Draft

edwinyjlim wants to merge 2 commits into
mainfrom
dag/w1-skills-by-traits

Conversation

@edwinyjlim

@edwinyjlim edwinyjlim commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Summary

Orchestrator runs pick each task's skill two ways: the exact-match pick used today, and a criteria pick from the skill menu's tags and the project's traits. With wizard-agent-dag off, the exact match decides and the criteria pick runs in shadow. With it on, the criteria pick decides and the exact match is its fallback. The flag does not exist in PostHog yet, so every run takes the off path.

Stack

The four PRs, in merge order:

PR What it does How it fits in
C1 · PostHog/context-mill#447 Adds a title, description and tags to every skill-menu entry. Wizards in the field ignore the new fields. Ships first, in a context-mill release. W1 picks skills by these tags, and W1 and W2 record their fixtures and prompts from this release.
W1 · #1497 (this PR) Adds project traits and a tag-based skill pick that runs beside today's pick, plus the wizard-agent-dag flag that decides which pick installs. Base of the wizard stack, on main. Reads C1's tags but works without them. D1 builds on its traits service, and W2 on its traits and flag.
D1 · #1499 Records every framework write as a project trait with its source. No flag; the values a run uses don't change. On W1. Extends W1's traits service, so the traits carry the framework as it was written. W1's skill pick and W2's flow conditions read it.
W2 · #1498 Moves the task graphs and prompts of the five orchestrator programs into the wizard. With wizard-agent-dag on, runs use them instead of the fetched prompts and the planner's graph. Top of the stack, on D1. Its flow conditions read W1's traits, W1's flag switches it on, and its prompts come from C1's release.

W1, D1 and W2 merge in that order and ship together in one wizard release, with wizard-agent-dag off. A later PR, W3, removes the flag and the paths it replaced after a week at 100%.

How a task's skill is picked

flowchart TD
  task["Task's skill id<br/>from its prompt's frontmatter"] --> legacy & criteria
  menu["Skill menu<br/>tags, group, framework, default"] --> legacy & criteria
  traits["Project traits as tags,<br/>such as framework:nextjs"] --> criteria
  legacy["Exact-match pick<br/>the id, else its group's variant<br/>for the run's framework"]
  criteria["Criteria pick<br/>the id, else skills carrying its tag<br/>and the framework tag, ranked by<br/>default, then menu order"]
  legacy & criteria --> flag{"wizard-agent-dag"}
  legacy & criteria -. "when they differ" .-> event(["orchestrator skill resolver<br/>disagreement event"])
  flag -- off --> off["Installs the exact match"]
  flag -- on --> on["Installs the criteria pick,<br/>else the exact match"]
Loading

The framework's reference skill (integration-<variant>) goes through the same picker. A menu without tags, such as v1.59.0, resolves the same: each entry's group, framework and default count as tags.

Project traits

@services/project-traits reads the traits from static detection. traitsToSkillTags turns them into the tags the criteria pick uses, and the program runner passes those to the orchestrator through RunConfig.traitTags.

Trait Value Skill tag
framework the detected integration, such as nextjs framework:nextjs
callsLlmApi yes when an LLM SDK is a dependency; absent otherwise none

Menu and fixtures

  • SkillEntry carries title, description and tags. Bundle variants inherit the bundle's title and description.
  • fixtures/context-mill/ holds a context-mill build's skill menu, agent menu and 41 agent prompts. pnpm record:context-mill-fixtures [base-url] re-records them from a release.

Telemetry

Event or property Sent
orchestrator skill resolver disagreement when the two picks differ, once per task and skill, with both picks and which one decided
context_mill_version on every event after the skill menu loads
$feature/<key> on setup wizard finished, one per wizard flag, so run outcomes split by flag

Test plan

  • pnpm typecheck
  • pnpm lint: no errors, and no new warnings in changed files
  • pnpm test: 258 files, 3,822 tests
  • Equivalence test: 0 disagreements for every prompt skill × framework, against the fixtures and against the live v1.59.0 menu (CONTEXT_MILL_MENU=<path>), which has no tags
  • Before merge: re-record the fixtures from the context-mill release that carries Emit a coding-agent handoff doc alongside posthog-setup-report.md #447 (they come from a local build of it today, buildVersion: dev)
  • After release: 0 disagreement events in the field before wizard-agent-dag goes to 50%, where it holds until a judgment call takes it to 100%

🤖 Generated with Claude Code

Orchestrator runs resolve each task's skills two ways. The exact-match
pick (the id itself, else its group's variant for the run's framework)
decides. The criteria resolver in `@shared/skill-resolution` picks beside
it from menu tags and the run's project traits, and each disagreement is
logged as `orchestrator skill resolver disagreement`. With the
`wizard-agent-dag` flag on, the criteria pick decides and the exact match
is its fallback.

`@services/project-traits` holds the run's project traits from static
detection: the framework, and `callsLlmApi` when an LLM SDK is a
dependency. `traitsToSkillTags` maps the framework to its
`framework:<id>` tag, and the program runner hands the tags to the
orchestrator through `RunConfig.traitTags`.

Skill-menu entries carry `title`, `description` and `tags`, and bundle
variants inherit the bundle's title and description. Every event after
the menu loads carries `context_mill_version`, and the terminal
`setup wizard finished` event carries the run's wizard flags.

`fixtures/context-mill/` holds a context-mill build's skill menu, agent
menu and 41 agent prompts; `pnpm record:context-mill-fixtures` re-records
them from a release. The equivalence test checks that both resolvers pick
the same skill for every prompt skill and framework.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci ai-observability
  • /wizard-ci basic-integration
  • /wizard-ci feature-flags
  • /wizard-ci mcp-analytics
  • /wizard-ci replay-vision
  • /wizard-ci revenue
  • /wizard-ci self-driving
  • /wizard-ci warehouse
  • /wizard-ci warehouse-seeded

Test an individual app:

  • /wizard-ci ai-observability/anthropic
  • /wizard-ci ai-observability/google-adk
  • /wizard-ci ai-observability/groq
Show more apps
  • /wizard-ci ai-observability/manual-capture
  • /wizard-ci ai-observability/openai
  • /wizard-ci ai-observability/openai-agents
  • /wizard-ci ai-observability/opentelemetry
  • /wizard-ci ai-observability/vercel-ai
  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /wizard-ci basic-integration/flutter
  • /wizard-ci basic-integration/javascript-node
  • /wizard-ci basic-integration/javascript-web
  • /wizard-ci basic-integration/laravel
  • /wizard-ci basic-integration/next-js
  • /wizard-ci basic-integration/nuxt
  • /wizard-ci basic-integration/python
  • /wizard-ci basic-integration/rails
  • /wizard-ci basic-integration/react-native
  • /wizard-ci basic-integration/react-router
  • /wizard-ci basic-integration/sveltekit
  • /wizard-ci basic-integration/swift
  • /wizard-ci basic-integration/tanstack-router
  • /wizard-ci basic-integration/tanstack-start
  • /wizard-ci basic-integration/vue
  • /wizard-ci feature-flags/django
  • /wizard-ci feature-flags/next-js
  • /wizard-ci mcp-analytics/custom-dispatcher
  • /wizard-ci mcp-analytics/typescript-sdk
  • /wizard-ci replay-vision/javascript-node
  • /wizard-ci replay-vision/next-js
  • /wizard-ci replay-vision/react-vite
  • /wizard-ci revenue/stripe
  • /wizard-ci self-driving/astro
  • /wizard-ci self-driving/fastapi
  • /wizard-ci self-driving/nuxt
  • /wizard-ci self-driving/react-router
  • /wizard-ci self-driving/sveltekit
  • /wizard-ci warehouse/monorepo-env
  • /wizard-ci warehouse/multi-source-next
  • /wizard-ci warehouse/stripe-node
  • /wizard-ci warehouse/zero-source
  • /wizard-ci warehouse-seeded/next-stripe
  • /wizard-ci warehouse-seeded/next-stripe-declined

Test against a Context Mill branch:

  • /wizard-ci all context-mill:my-branch

Add context-mill:<branch> to any command above to pin the Context Mill branch. It defaults to main.

Results will be posted here when complete.

Flows in the program contract read project traits, and the contract
imports no service, so the vocabulary types live there and
`@services/project-traits` produces their values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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