---
phase: 2
name: Build Connector
description: Project the research artifact into Falcon connector YAML — auth first, then actions
skills:
  - connector-patterns
  - build-connector-config
  - build-actions
  - action-config
  - input-config
  - args-config
  - step-function-request
  - step-function-upload-download
  - config-ratelimit
  - auth-oauth2
  - auth-oauth2-client-credentials
  - auth-oauth2-code-exchange
  - auth-oauth2-code-longterm
  - auth-oauth2-code-refresh
  - auth-custom
  - auth-soap
dependencies:
  - phase: 1
    requires: research artifact
entryConditions:
  - Research phase recorded complete (or exhausted) in run.json
  - Research artifact exists at .connector-dev/{{provider}}/research/{{provider}}_research.json
exitConditions:
  - stackone validate exits 0 on the connector path
  - auth.js (A1–A12) exits 0
  - build.js (B1–B16) and conventions.js (N1–N20) exit 0
  - Phase recorded complete via scripts/state/run.js set-phase
---

# Phase 2: Build Connector

## Purpose

Project the research artifact faithfully into Falcon connector YAML — provider metadata,
the authentication block, and one action per in-scope endpoint. Nothing here is executed
against a live API: this phase authors YAML locally and never deploys, connects an
account, or calls the provider.

Build only what `run.json → scope` selected. Endpoints in `scope.dropped[]` are deliberate
exclusions — do not build them, do not remove them from the record.

## Skills Used (orchestrated by `/connector:build`)

| Skill | Owns |
|-------|------|
| `connector-patterns` | **Load before writing any YAML** — corpus-mined reference: `references/authentication.md` for the auth block, `references/naming-conventions.md` for the naming rules, `SKILL.md` for actions |
| `build-connector-config` | Main `{{provider}}.connector.s1.yaml` — info, baseUrl, auth scaffold, `$ref` entries |
| `auth-oauth2` (+ `-client-credentials`, `-code-exchange`, `-code-longterm`, `-code-refresh`) | OAuth 2.0 auth blocks, dispatched per grant/refresh pattern |
| `auth-custom` | API Key, Basic, Bearer, custom-header auth |
| `auth-soap` | SOAP credential patterns (WS-Security, credentials in payload) |
| `config-ratelimit` | `rateLimit` block from documented provider limits |
| `build-actions` + sub-skills `action-config`, `input-config`, `args-config`, `step-function-request`, `step-function-upload-download` | Per-resource partials — the action envelope, inputs, args wiring, and HTTP / file-transfer steps |

No agents are spawned in this phase — the build skills run in the main context.

## Entry Checkpoint

Phase 2 requires:
- [ ] `run.json` records the research phase as `complete` (or `exhausted` with a gap list)
- [ ] Research artifact exists at `.connector-dev/{{provider}}/research/{{provider}}_research.json`

```bash
node ${CLAUDE_PLUGIN_ROOT}/scripts/state/run.js summary --provider {{provider}}
```

If research is not recorded, stop and run `/connector:research {{provider}}` first.

## Execution Flow

1. **Capture build state** — resolve `connector_path` and write
   `.connector-dev/{{provider}}/build-state.yaml`. State files live under
   `.connector-dev/{{provider}}/`, never inside `connector_path`.

2. **Load `connector-patterns`** — before any YAML is written, not when a gate fails.
   The wrong shapes (`- key:` on an input, `in: header`, a bare `values:` enum) are valid
   YAML that passes `stackone validate` and does nothing at runtime.

3. **Loop 1 — auth to green first.** Generate the main connector file
   (`build-connector-config`), then the auth block via the auth skill matching each
   in-scope mechanism, recording the provider auth docs read in
   `.connector-dev/{{provider}}/build/auth-evidence.json` (A10 fails without it). Loop
   until green **before writing any action** — a wrong auth block breaks every action at
   once:

   ```bash
   node ${CLAUDE_PLUGIN_ROOT}/scripts/gates/auth.js \
     --provider {{provider}} --connector-path "$CONNECTOR_PATH"

   # post-write: the environment and baseUrl rules
   node ${CLAUDE_PLUGIN_ROOT}/scripts/gates/conventions.js \
     --provider {{provider}} --connector-path "$CONNECTOR_PATH" --only N7,N8,N10
   ```

4. **Loop 2 — actions.** For each in-scope resource, read its slice of the research
   artifact and write `{{provider}}.{{resource}}.s1.partial.yaml` via the `build-actions`
   sub-skill chain (`action-config` → `input-config` → `step-function-request` /
   `step-function-upload-download` → `args-config`), `$ref`'d from the main file. Then:

   ```bash
   stackone validate "$CONNECTOR_PATH"

   # --cli-ok carries the stackone validate verdict; B1 fails when omitted
   node ${CLAUDE_PLUGIN_ROOT}/scripts/gates/build.js \
     --provider {{provider}} --connector-path "$CONNECTOR_PATH" --cli-ok <true|false>

   # naming and content rules across the whole connector
   node ${CLAUDE_PLUGIN_ROOT}/scripts/gates/conventions.js \
     --provider {{provider}} --connector-path "$CONNECTOR_PATH"
   ```

## The gate loop

```
run the gate
  exit 0  →  move on
  exit 1  →  fix what the gate reported, run it again
  exit 2  →  the gate could not evaluate; that is a bug, fix it and rerun
```

**Stop looping when two consecutive rounds resolve nothing.** Mark the phase `exhausted`,
record what remains, and move on — a connector plus an honest gap list beats no connector.
After a targeted fix, re-check only what changed:

```bash
node ${CLAUDE_PLUGIN_ROOT}/scripts/gates/build.js --provider {{provider}} --scope candidates
```

## Exit Checkpoint

Phase 2 is complete when:
- [ ] `stackone validate "$CONNECTOR_PATH"` exits 0
- [ ] `auth.js` (A1–A12) exits 0 — auth block complete, credentials resolve, evidence recorded
- [ ] `build.js` (B1–B16) exits 0 — every in-scope endpoint has an action with full parameter fidelity
- [ ] `conventions.js` (N1–N20) exits 0 — corpus-mined naming and content rules hold

## Artifacts Produced

```
{{connector_path}}/                            # from build-state.yaml — connector YAML only
├── {{provider}}.connector.s1.yaml             # Main: info, baseUrl, auth, $refs
├── {{provider}}.{{resource}}.s1.partial.yaml  # One per in-scope resource
└── ...

.connector-dev/{{provider}}/
├── build-state.yaml                           # provider, connector_path, started_at
└── build/
    └── auth-evidence.json                     # Provider auth docs read per mechanism (A10)
```

## Phase Transition

Record the transition — `run.json` is written only by `scripts/state/run.js`, never by hand:

```bash
node ${CLAUDE_PLUGIN_ROOT}/scripts/state/run.js set-phase \
  --provider {{provider}} --phase build --status complete
# or --status exhausted [--unmet B3,B7] when the loop stopped converging
```

Next phase: **Phase 3 — Validation & Benchmarking**
