Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
50 changes: 25 additions & 25 deletions .claude/skills/adding-framework-support/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,49 +20,49 @@ creating its own runner or changing existing routing defaults.

## Extend the framework configuration

Start with [FrameworkConfig](../../../src/lib/framework-config.ts) and a nearby
example under [src/frameworks](../../../src/frameworks/). Framework-specific
detection, context, environment conventions, and UI metadata belong here.
Integration instructions and examples belong in context-mill.

1. Add the integration to [Integration](../../../src/lib/constants.ts). Its
order controls first-match detection and the framework picker. Keep specific
frameworks before language fallbacks and generic Node last; preserve the
overlap rules in the
[detection checks](../../../src/lib/detection/__tests__/framework.test.ts).
2. Add the config under `src/frameworks/<name>/<name>-wizard-agent.ts`. Use a
Start with [FrameworkConfig](../../../src/store/framework-config.ts) and a
nearby example under [src/store/frameworks](../../../src/store/frameworks/).
Framework-specific detection, context, environment conventions, and UI metadata
belong here. Integration instructions and examples belong in context-mill.

1. Add the integration to [Integration](../../../src/store/shared/constants.ts).
Its order controls first-match detection and the framework picker. Keep
specific frameworks before language fallbacks and generic Node last; preserve
the overlap rules in the
[detection checks](../../../src/store/detection/__tests__/framework.test.ts).
2. Add the config under `src/store/frameworks/<name>/<name>-wizard-agent.ts`. Use a
`type` for framework context so it satisfies `Record<string, unknown>`.
Export the config; the integration program already supplies execution.
3. Import the config into [FRAMEWORK_REGISTRY](../../../src/lib/registry.ts).
3. Import the config into [FRAMEWORK_REGISTRY](../../../src/store/registry.ts).
The display label comes from `metadata.name`.

Read the current interface for the complete required fields. In particular,
`detection.detectPackageManager` is required: reuse an adapter from
[package-manager detection](../../../src/lib/detection/package-manager.ts). Use
`metadata.setup.questions` for unresolved project variants; `gatherContext`
[package-manager detection](../../../src/store/detection/package-manager.ts).
Use `metadata.setup.questions` for unresolved project variants; `gatherContext`
collects framework context. Optional notices and extra MCP servers also belong
in metadata.

Use `usesPackageJson: false` for frameworks without a package.json dependency.
Their required `getVersion` callback can return `undefined`. Minimum-version
checking requires both `minimumVersion` and `getInstalledVersion`; unknown
versions pass. [Context detection](../../../src/lib/detection/context.ts)
versions pass. [Context detection](../../../src/store/detection/context.ts)
returns unsupported-version data for the integration UI rather than aborting
itself.

## Detection and examples

| Starting point | Pattern to reuse |
| ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| [Next.js](../../../src/frameworks/nextjs/) | `hasDeclaredDependency` from `utils/package-json`, `tryGetPackageJson` from `utils/setup-utils`, and router setup questions |
| [Django](../../../src/frameworks/django/) | Python project files, context gathering, and Python package-manager detection |
| [Laravel](../../../src/frameworks/laravel/) | Composer and framework-specific filesystem signals |
| [Rails](../../../src/frameworks/rails/) | Gemfile detection and Ruby conventions |
| [Next.js](../../../src/store/frameworks/nextjs/) | `hasDeclaredDependency` from `utils/package-json`, `tryGetPackageJson` from `utils/setup-utils`, and router setup questions |
| [Django](../../../src/store/frameworks/django/) | Python project files, context gathering, and Python package-manager detection |
| [Laravel](../../../src/store/frameworks/laravel/) | Composer and framework-specific filesystem signals |
| [Rails](../../../src/store/frameworks/rails/) | Gemfile detection and Ruby conventions |

Use [bounded filesystem helpers](../../../src/utils/bounded-fs.ts) for project
scans and reads. They bound traversal and skip dependency/build directories; add
framework-specific exclusions with `extraIgnore`. Keep complex parsers and
detectors beside the config so they can be checked independently.
Use [bounded filesystem helpers](../../../src/store/shared/bounded-fs.ts) for
project scans and reads. They bound traversal and skip dependency/build
directories; add framework-specific exclusions with `extraIgnore`. Keep complex
parsers and detectors beside the config so they can be checked independently.

## Complete the content side

Expand All @@ -71,7 +71,7 @@ matching integration reference and task-skill variants for the framework. A
registry entry alone does not provide integration knowledge. The orchestrator
resolves framework variants from the skill menu and rejects missing task
variants; see the
[orchestrator runner](../../../src/lib/agent/runner/sequence/orchestrator/orchestrator-runner.ts).
[orchestrator runner](../../../src/agent/runner/sequence/orchestrator/orchestrator-runner.ts).

Keep project-specific facts in configuration and reusable integration guidance
in that content. Model IDs, reasoning efforts, and gateway-required system
Expand All @@ -88,7 +88,7 @@ content-mill variants. For an end-to-end run, use a disposable test app and the
[exploration guide](../exploring-the-wizard/SKILL.md).

For prompt, environment-upload, or outro changes, inspect the current
[integration program](../../../src/lib/programs/posthog-integration/) and the
[integration program](../../../src/store/programs/posthog-integration/) and the
selected sequence. Some fields remain in the interface without a current
consumer: `getOutroNextSteps` is not used by the integration outro. Linear
post-run/outro hooks are not shared by the orchestrator; see the
Expand Down
84 changes: 41 additions & 43 deletions .claude/skills/adding-skill-program/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,20 @@ guide owns the fallback criteria and gateway model/effort/system-prompt
contract.

These are contribution defaults. Current runtime
[bindings](../../../src/lib/agent/runner/switchboard/index.ts) still default
many programs to Anthropic plus linear; documentation changes do not migrate
them.
[bindings](../../../src/agent/runner/switchboard/index.ts) still default many
programs to Anthropic plus linear; documentation changes do not migrate them.

## Choose the contribution surface

- **Content-only capability:** use the existing skill command machinery when it
can express the workflow.
[Context-mill](https://github.com/PostHog/context-mill) owns skill content and
`cliEntries`. A new skill-backed child of an existing family ships through
context-mill; inspect
[family dispatch](../../../src/lib/programs/dispatch-family.ts). Unpromoted
skills run through [the skill command](../../../src/commands/skill.ts).
context-mill; inspect [family dispatch](../../../src/cli/dispatch-family.ts).
Unpromoted skills run through
[the skill command](../../../src/cli/commands/skill.ts).
- **Native program:** use a
[ProgramConfig](../../../src/lib/programs/program-step.ts) when the wizard
[ProgramConfig](../../../src/store/programs/program-step.ts) when the wizard
needs its own flow, screens, detection, composition, or other native behavior.
Keep product instructions in context-mill.

Expand All @@ -45,32 +44,33 @@ is `id`, not the retired `flowKey`.

## Build a native orchestrator program

Use [metrics](../../../src/lib/programs/metrics/) as the current Pi/orchestrator
example and read the
Use [metrics](../../../src/store/programs/metrics/) as the current
Pi/orchestrator example and read the
[runner architecture](../wizard-development/references/ARCHITECTURE.md) when
changing execution behavior.

1. Add the program config under `src/lib/programs/<name>/`. Set `agentFlow` when
its content-mill flow differs from `id`; setting it explicitly also documents
the content dependency. Keep a `run` definition so the outer runner executes
agent work.
1. Add the program config under `src/store/programs/<name>/`. Set `agentFlow`
when its content-mill flow differs from `id`; setting it explicitly also
documents the content dependency. Keep a `run` definition so the outer runner
executes agent work.
2. Supply the flow's seed and task prompts in context-mill, including the task
dependencies and applicable skill variants. The
[orchestrator](../../../src/lib/agent/runner/sequence/orchestrator/orchestrator-runner.ts)
[orchestrator](../../../src/agent/runner/sequence/orchestrator/orchestrator-runner.ts)
loads `agentFlow ?? id`, requires a seed prompt, and checks task-skill
variants before running. `run.skillId` alone does not define this flow.
3. Register the config in
[PROGRAM_REGISTRY](../../../src/lib/programs/program-registry.ts) and add its
Pi/orchestrator entry to
[PROGRAM_BINDINGS](../../../src/lib/agent/runner/switchboard/index.ts).
[Existing binding checks](../../../src/lib/agent/runner/__tests__/switchboard.test.ts)
[PROGRAM_REGISTRY](../../../src/store/programs/program-registry.ts) and add
its Pi/orchestrator entry to
[PROGRAM_BINDINGS](../../../src/agent/runner/switchboard/index.ts).
[Existing binding checks](../../../src/agent/runner/__tests__/switchboard.test.ts)
enforce coverage; `ProgramId` currently widens to `string`.
4. For a standalone native command, create a command module with
[nativeCommandFactory](../../../src/commands/factories/native-command-factory.ts)
[nativeCommandFactory](../../../src/cli/commands/factories/native-command-factory.ts)
and register it in [bin.ts](../../../bin.ts). A native family child uses the
handlers in family dispatch. Program registration derives screen sequences
and store lookup, not the top-level CLI `.use()` chain.
5. Check [program OAuth scopes](../../../src/lib/oauth/program-scopes.ts)
5. Check
[program OAuth scopes](../../../src/store/services/oauth/program-scopes.ts)
against the tools the program needs; add scopes only when the base set is
insufficient.

Expand All @@ -82,53 +82,51 @@ or changing gateway-required prompt material.
## Simple linear programs and existing flows

For a very simple linear flow, use
[createSkillProgram](../../../src/lib/programs/agent-skill/index.ts) to
[createSkillProgram](../../../src/store/programs/agent-skill/index.ts) to
configure installation of one skill. Register the native program as above with
an explicit Pi/linear binding; the factory does not select a sequence. Read
`SkillProgramOptions` for required fields;
[audit](../../../src/lib/programs/audit/) demonstrates factory customization and
a dynamic `run(session)` that seeds a ledger.
[Revenue analytics](../../../src/lib/programs/revenue-analytics/) builds its
[audit](../../../src/store/programs/audit/) demonstrates factory customization
and a dynamic `run(session)` that seeds a ledger.
[Revenue analytics](../../../src/store/programs/revenue-analytics/) builds its
config directly and adds prerequisite detection.

`ProgramRun.customPrompt`, `abortCases`, `postRun`, and `buildOutroData` are
consumed by the
[linear sequence](../../../src/lib/agent/runner/sequence/linear.ts). `postRun`
runs after success; `buildOutroData` receives session and credentials, with host
information inside credentials. The orchestrator currently uses its own task
prompts, failure handling, and outro, and does not invoke those hooks. Check
this limitation before migrating a linear flow; setting an orchestrator binding
does not preserve these behaviors automatically.
consumed by the [linear sequence](../../../src/agent/runner/sequence/linear.ts).
`postRun` runs after success; `buildOutroData` receives session and credentials,
with host information inside credentials. The orchestrator currently uses its
own task prompts, failure handling, and outro, and does not invoke those hooks.
Check this limitation before migrating a linear flow; setting an orchestrator
binding does not preserve these behaviors automatically.

## Screens, prerequisites, and composition

Reuse [AGENT_SKILL_STEPS](../../../src/lib/programs/agent-skill/steps.ts):
Reuse [AGENT_SKILL_STEPS](../../../src/store/programs/agent-skill/steps.ts):
intro, health check, auth, run, outro, and keep-skills. Auth also applies the
shared [AI opt-in gate](../../../src/lib/programs/ai-opt-in-gate.ts) for agent
shared [AI opt-in gate](../../../src/store/programs/ai-opt-in-gate.ts) for agent
programs. Override `screenId`, not `screen`, when adapting a step. New screens
need an entry in [ScreenId](../../../src/ui/tui/screen-sequences.ts), a
component, and registration in
[screen-registry](../../../src/ui/tui/screen-registry.tsx). Follow
[ink-tui](../ink-tui/SKILL.md) for rendering and store usage.
need an entry in [ScreenId](../../../src/tui/screen-sequences.ts), a component,
and registration in [screen-registry](../../../src/tui/screen-registry.tsx).
Follow [ink-tui](../ink-tui/SKILL.md) for rendering and store usage.

Use a headless step's `onReady` for session-dependent detection, then render
structured `frameworkContext.detectError` data in the intro. `onInit` runs when
the TUI starts rendering with its initial session; `onReady` runs after the real
session is assigned. See [store hooks](../../../src/ui/tui/store.ts) and
[run-wizard](../../../src/lib/runners/run-wizard.ts). The
[noninteractive runner](../../../src/lib/runners/run-non-interactive.ts) also
session is assigned. See [store hooks](../../../src/store/state/store.ts) and
[run-wizard](../../../src/cli/runners/run-wizard.ts). The
[noninteractive runner](../../../src/cli/runners/run-non-interactive.ts) also
walks `onReady` by default; set `ciPreRun` only when it needs a different
prerequisite strategy.

`requires` currently records metadata; it does not execute or enforce prior
programs. Compose real work through `ProgramStep.run`, with `onRunPrep` and
`targetDir` when needed. The
[integration run step](../../../src/lib/programs/posthog-integration/index.ts)
and [self-driving](../../../src/lib/programs/self-driving/) demonstrate this.
[integration run step](../../../src/store/programs/posthog-integration/index.ts)
and [self-driving](../../../src/store/programs/self-driving/) demonstrate this.
Composed sub-runs are structurally linear; orchestrators cannot nest. A host run
step without `run` can also set `targetDir` and `onRunPrep` to scope the
program's own agent to a picked project and keep its sequence, as
[error-tracking](../../../src/lib/programs/error-tracking/) does.
[error-tracking](../../../src/store/programs/error-tracking/) does.

## Validate the affected path

Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/exploring-the-wizard/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ MCP snapshots are plain `.txt`; the CI snapshot route writes colored `.ans`
frames. Keep the screen path and failure evidence with the snapshots. Do not
stop a progressing run at an invented turn count: the MCP exposes no turn limit;
Pi's continuation and tool-call guards are described in its
[harness README](../../../src/lib/agent/runner/harness/pi/README.md).
[harness README](../../../src/agent/runner/harness/pi/README.md).

## Sweep the workbench

Expand All @@ -129,5 +129,5 @@ The shared log is `/tmp/posthog-wizard.log`. Record its byte count before a run
and read from that count plus one afterward. Run sweeps serially so their logs
remain attributable. `read_state` omits `frameworkContext`; an empty
`setupQuestions` list alone does not prove a router mode. When necessary,
inspect the detector under [`src/frameworks/`](../../../src/frameworks/) against
inspect the detector under [`src/store/frameworks/`](../../../src/store/frameworks/) against
the same fixture.
39 changes: 20 additions & 19 deletions .claude/skills/ink-tui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ conventions rather than copying upstream component manuals.

## Add a screen

1. Create a component in [screens](../../../src/ui/tui/screens/).
1. Create a component in [screens](../../../src/tui/screens/).
2. Add its `ScreenId` in
[screen-sequences.ts](../../../src/ui/tui/screen-sequences.ts).
[screen-sequences.ts](../../../src/tui/screen-sequences.ts).
3. Register the component in
[screen-registry.tsx](../../../src/ui/tui/screen-registry.tsx).
[screen-registry.tsx](../../../src/tui/screen-registry.tsx).
4. Reference it through `screenId` in the owning
[program's steps](../../../src/lib/programs/), with the appropriate
[program's steps](../../../src/store/programs/), with the appropriate
visibility, completion, and gate predicates.

Screen sequences derive from program steps. Do not hand-maintain a second
Expand All @@ -49,27 +49,28 @@ service wiring depends on the screen's needs; `App` remains the shared shell.

## Preserve the UI boundary

Business logic calls [WizardUI](../../../src/ui/wizard-ui.ts) through
[getUI](../../../src/ui/index.ts). Screens use
[WizardStore](../../../src/ui/tui/store.ts) setters for reactive changes. The
router resolves program screens from session predicates; overlays interrupt that
resolution. Local state is appropriate for presentation details such as tab
Business logic calls [WizardUI](../../../src/store/ui/wizard-ui.ts) through
[getUI](../../../src/store/ui/index.ts). Screens use
[WizardStore](../../../src/store/state/store.ts) setters for reactive changes.
The router resolves program screens from session predicates; overlays interrupt
that resolution. Local state is appropriate for presentation details such as tab
selection, not wizard progression.

For new state, first decide whether it belongs in
[WizardSession](../../../src/lib/wizard-session.ts) or display-only store state.
Use an explicit setter that notifies subscribers. When business logic needs the
operation, extend `WizardUI`, [InkUI](../../../src/ui/tui/ink-ui.ts), and
[LoggingUI](../../../src/ui/logging-ui.ts) together. Reuse existing enums and
union types rather than introducing competing status vocabularies.
[WizardSession](../../../src/store/session/wizard-session.ts) or display-only
store state. Use an explicit setter that notifies subscribers. When business
logic needs the operation, extend `WizardUI`,
[InkUI](../../../src/store/ui/store-ui.ts), and
[LoggingUI](../../../src/tui/console/logging-ui.ts) together. Reuse existing
enums and union types rather than introducing competing status vocabularies.

## Reuse and check

Compose existing primitives and use [styles.ts](../../../src/ui/tui/styles.ts)
for shared colors, icons, and alignment. Export new public primitives from
[primitives/index.ts](../../../src/ui/tui/primitives/index.ts), add a realistic
[playground demo](../../../src/ui/tui/playground/demos/), and register it in
[PlaygroundApp.tsx](../../../src/ui/tui/playground/PlaygroundApp.tsx).
Compose existing primitives and use [styles.ts](../../../src/tui/styles.ts) for
shared colors, icons, and alignment. Export new public primitives from
[primitives/index.ts](../../../src/tui/primitives/index.ts), add a realistic
[playground demo](../../../src/tui/playground/demos/), and register it in
[PlaygroundApp.tsx](../../../src/tui/playground/PlaygroundApp.tsx).

Run `pnpm try --playground` to inspect primitives. Use
[exploring-the-wizard](../exploring-the-wizard/SKILL.md) when exercising actual
Expand Down
Loading
Loading