# StackOne Agent Skills

Skills are instructions Claude loads when they are relevant to the task.

**Eleven skills, all flat.** The bundled-skill loader does one `readdirSync` of this directory
and requires `<name>/SKILL.md`, so a skill nested any deeper is invisible to it — and
because sync copies `skills/<name>/**` recursively, a nested skill never reaches a sandbox
at all. Everything that used to live under `skills/build/`, `skills/research/` and
`skills/validation/` was unreachable on both counts; it is now reference material under the
phase skill that owns it, which is what those files always were (they already carried
`user-invocable: false`).

Detailed technique lives in `references/` beside the phase skill and is **read as a file**,
never invoked.

The plugin's flow is **Research → Build → Validate**, orchestrated by `/connector:full` (see `commands/connector-full.md`). Each phase has one phase skill that does the work and one deterministic gate script that decides completion.

## Phase Skills

| Skill | Phase | Gate |
|---|---|---|
| `research-provider` | 1 — research the provider's API and write `.connector-dev/<provider>/research/<provider>_research.json` | `scripts/gates/research.js` |
| `build-connector` | 2 — project the research artifact into connector YAML (main file + partials) | `scripts/gates/auth.js`, then `scripts/gates/build.js` + `scripts/gates/conventions.js` |
| `validate-config` | 3 — re-derive the connector from the provider's **live** docs and reconcile every difference | `scripts/gates/validate.js` |

## The Gate Loop

Every phase runs the same loop — completion is decided by a script, not by judgement:

```
do the phase's work
run its gate: node ${CLAUDE_PLUGIN_ROOT}/scripts/gates/<gate>.js --provider <p>
  exit 0  →  mark the phase complete, 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
```

Two consecutive rounds resolving nothing → mark the phase `exhausted`, record what remains, move on. Run state lives in `.connector-dev/<provider>/run.json`, written only by `scripts/state/run.js`.

## Research References (`research-provider/references/`)

Read by `research-provider` / `/connector:research` for specific investigation work:

| Document | Purpose |
|---|---|
| `list-provider-apis` | Discover the full endpoint surface (OpenAPI spec first, then deep crawl) and classify it into MoSCoW tiers |
| `fetch-endpoint-parts` | Extract one endpoint's 10 parts (params, headers, auth, errors, pagination) from its docs page |
| `investigate-auth-oauth2` | Extract OAuth2 config for one specific grant type |
| `investigate-auth-custom` | Extract non-OAuth2 auth config (API key, PAT, basic, bearer, header) for one specific type |
| `identify-provider-category` | Classify the provider into a known category (HRIS, CRM, ATS, …) |
| `use-case-catalog` | Static Layer 1/2 use-case catalogs used for priority scoring |
| `discover-dynamic-use-cases` | Generate Layer 3/4 dynamic use-case catalogs from the provider's docs and API surface |
| `consolidate-research-output` | Merge per-auth-type and per-resource findings into consolidated output |

Shared rules live in `research-provider/references/auth-investigation-common.md`. Fetch strategy everywhere: built-in **WebFetch** first, Playwright MCP fallback for JS-rendered pages.

## Build References (`build-connector/references/`)

**Actions family:**

| Document | Owns |
|---|---|
| `build-actions` | Adding all actions for one resource to its partial, then running the build gates |
| `action-config` | The action envelope — actionId, effects, label, description, result pattern |
| `input-config` | The full `inputs` schema — types, enums, objects, arrays, variants |
| `args-config` | Wiring inputs into the request — value, in, condition, spread, arrayFormat |
| `step-function-request` | `request` / `paginated_request` steps for REST and GraphQL |
| `step-function-upload-download` | Multipart upload and binary download steps |

**Connector family:**

| Document | Owns |
|---|---|
| `build-connector-config` | The initial main YAML — info block, baseUrl, auth, one test action, `$ref` structure |
| `config-ratelimit` | Researching and setting `rateLimit` |
| `auth-oauth2` | The OAuth 2.0 auth block |
| `auth-oauth2-client-credentials` | Client-credentials grant variant |
| `auth-oauth2-code-exchange` | Authorization-code exchange variant |
| `auth-oauth2-code-longterm` | Code flow with long-lived tokens |
| `auth-oauth2-code-refresh` | Code flow with refresh-token rotation |
| `auth-custom` | API key / basic / bearer auth blocks |
| `auth-soap` | SOAP/WS-Security auth |

## Connector Patterns (`connector-patterns/`)

Evidence-based reference mined from the shipped connector corpus — **load it before writing any YAML**, not when stuck. `SKILL.md` covers inputs, args, pagination and result shapes; `references/` holds `naming-conventions.md` (rules N1–N12), `authentication.md`, `tricky-handling.md` (SOAP, GraphQL, files, events) and `schema-vs-corpus.md` (the three expression formats).

## Validation References (`validate-config/references/`)

| Document | Purpose |
|---|---|
| `validation-rules` | Pre-validation structural rules applied by the `schema-reviewer` agent and enforced by the build/validate gates |
| `provider-schema-comparison` | Compare connector schema against the provider's official docs — missing params, type mismatches, documentation gaps |

## Utility Skills

| Skill | Purpose |
|---|---|
| `connector-flow` | Routes ANY connector request into the gated flow — the entry point when a request arrives as plain natural language rather than a slash command |
| `test-connector` | Test every action with every auth type via `stackone run`, tracked in `.connector-dev/<provider>/testing/actions_tracking.json` |
| `test-mcp-connector` | MCP-based agentic testing of action descriptions — only when the user explicitly asks for MCP testing |
| `scramble-credentials` | Replace real credentials with random values before any storage or commit |
| `discover-actions` | Autonomous async action discovery for a provider (S3-cached) |
| `improve-descriptions` | Async improvement of action descriptions in a connector |
| `version-validation` | Analyze API version conflicts for discovered endpoints |

## How Skills Work

Unlike slash commands (`/connector:full`, `/connector:research`, `/connector:build`,
`/connector:validate`, `/connector:status`), skills are **model-invoked**: Claude loads one
when the task matches.

Reference documents are not skills. They are read with the Read tool at the path given
above, and nothing registers or auto-loads them — which is why adding one costs no context
until something actually needs it. Keep them in `references/` beside the phase skill that
uses them; a new top-level directory here becomes a skill and shows up in every session.
