Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions docs/HELPERS-RUNTIME.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Generated provider helpers

`Ctx` exposes the relayfile helper clients as lazy journaled steps. For example:

```ts
await f.github.createIssue({ repo: 'owner/repo', title: 'Investigate', body: 'Details' });
await f.linear.createIssue({ teamId: 'team-id', title: 'Investigate' });
await f.stripe.createInvoice({ customer: 'cus_123' });
await f.asana.tasks.write({}, { name: 'Investigate' });
await f.googleDrive.files.write({}, { name: 'Report' });
```

Provider names with hyphens become camelCase namespaces. Resource names retain
upstream spelling (`f.github['issue-comments'].write(...)`). The upstream
resource clients expose `write`, `read`, `list`, and a pure `path` resolver.
All asynchronous methods become `Step`s; `path` performs no I/O.

A provider directory must exist under the first configured nonempty mount root:
`RELAYFILE_MOUNT_PATH`, `WORKSPACE_ROOT`, `WORKFORCE_SANDBOX_ROOT`,
`RELAYFILE_MOUNT_ROOT`, or `RELAYFILE_ROOT`. Direct provider tokens are not a
transport. Explicit declarations such as `tools: { github: true }` and direct
body references are checked before the body runs; dynamic aliases are checked
when their steps execute.

`RELAYFLOWS_<PROVIDER>_MOCK=1` enables mock delivery for available providers.
Uppercase provider names and replace hyphens with underscores, for example
`RELAYFLOWS_GOOGLE_DRIVE_MOCK=1`. Mock writes are captured under
`<data-dir>/mock-writeback/<provider>/`; mock reads return an empty object and
mock lists return an empty array. These are test responses, not provider data.

Writes use `(run id, step id)` as the writeback idempotency key. Collection
paths receive stable draft filenames; item paths remain canonical. Delivery
must be confirmed before the receipt is persisted and the journal effect is
confirmed. Resume recovers the receipt, and repeats only an unconfirmed effect
using its original key. Provider failures complete with `worker_error`;
journal and receipt-storage failures fail closed.

## Regeneration

```sh
npm run gen --prefix packages/surface
node scripts/generate-helpers.mjs --adapters-dir /path/to/relayfile-adapters
```

The pinned published catalog and helper clients provide reproducible API types
and runtime factories. `--adapters-dir` additionally walks every adapter package
to discover providers that have not published writeback clients. Generated
files include factories, namespace types, a runtime client registry, and
preflight metadata. An unpublished client is marked unavailable rather than
assigned invented writeback paths.

## Upstream gaps in slice S

The supplied provider list contains 48 names including the five original
providers. The pinned catalog also includes GitLab and Ramp, so regeneration
currently emits 50 namespaces. Forty have runtime clients. These ten are
explicitly unavailable, including in mock mode:

- airtable
- docker-hub
- fathom
- gcp
- neon
- posthog
- segment
- shopify
- webhook-server
- x

The supplied checkout's catalog lists all except webhook-server under
`ADAPTERS_WITHOUT_WRITEBACK_PATHS`. Webhook-server is infrastructure, not a
writeback provider. These require upstream client/catalog work before slice S
can meet its full provider acceptance bar.

Stripe has an adapter writeback route for invoice creation but no exported
helper client. The invoice convenience wrapper submits that existing route
through the shared transport and consumes `created()` from relay-helpers.

`f.notion.appendBlock({ pageId, block })` is **mock-only**. The supplied Notion
adapter supports page content replacement and comments, but no append-block
writeback route. Real mount execution is refused before starting the effect;
mock execution can test types and journal lowering. This is an outstanding
acceptance gap, not live append-block support. Existing catalog Notion
resources continue to use the upstream client.

No triggers or direct-token transports are added by this slice.
143 changes: 143 additions & 0 deletions evidence/slice-S/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Slice S verification

Run from `/Users/khaliqgant/fl-slice-S` on branch
`feat/spec-S-helpers-runtime-fanout`. No push or external provider write was
performed. Local mount tests simulate delivery receipts; provider writes in
kernel integration tests use mock mode.

## Scope and outstanding acceptance

See [HELPERS-RUNTIME.md](../../docs/HELPERS-RUNTIME.md) for the API and upstream
limitations. The generated registry covers 50 discovered namespaces, 40 with
runtime clients. Ten namespaces have no upstream client and are explicitly
unavailable. Notion appendBlock is mock-only because the adapter has no such
writeback route. This commit must not be treated as closing #340's full live
provider acceptance bar.

The final catalog factory adjustment is also covered by the full final run.
The earlier successful run is retained in
[sdk-tests-before-catalog-fallback.txt](sdk-tests-before-catalog-fallback.txt).

Registry inventory command:

```sh
node --input-type=module - <<'JS'
import { helperProviders } from './packages/surface/dist/runtime.js';
console.log(JSON.stringify({
namespaces: helperProviders.length,
runtimeClients: helperProviders.filter(p => p.supported).length,
unavailable: helperProviders.filter(p => !p.supported).map(p => p.provider),
}, null, 2));
JS
```

Literal output: [provider-inventory.txt](provider-inventory.txt).

## Local package resolution

The SDK's `node_modules/@relayflows/surface` points to this worktree's
`packages/surface`, not the published 2.0.8 package. Dependencies were installed
with `npm install --ignore-scripts --prefix packages/surface` and
`npm install --ignore-scripts --prefix packages/sdk`, then the local surface
was built and linked. The surface lockfile repair is included in the commit.

For a fresh worktree, CI's equivalent local-package setup is:

```sh
npm ci --ignore-scripts --prefix packages/surface
npm run build --prefix packages/surface
npm ci --ignore-scripts --prefix packages/sdk
npm install ./packages/surface --prefix packages/sdk --no-save --ignore-scripts
```

## Commands and literal output

Surface typecheck:

```sh
npm run typecheck --prefix packages/surface
```

Captured output:

```text
> @relayflows/surface@2.0.8 typecheck
> tsc --noEmit
```

Surface tests and typed smoke fixture:

```sh
npm test --prefix packages/surface
```

Full captured output: [surface-tests.txt](surface-tests.txt).

Surface regression typechecks and codegen drift guard:

```sh
npm run typecheck:regressions --prefix packages/surface
```

Full captured output: [surface-regressions.txt](surface-regressions.txt).

Discovery from the supplied adapter checkout, followed by byte comparison with
regeneration from the pinned published inputs:

```sh
node scripts/generate-helpers.mjs --adapters-dir /Users/khaliqgant/Projects/AgentWorkforce/relayfile-adapters
node packages/surface/scripts/check-generated-helpers.mjs
```

Full captured output: [codegen.txt](codegen.txt).

Full SDK check, including kernel build, SDK and test typechecks, build, and all
SDK tests:

```sh
PATH=/Users/khaliqgant/.cargo/bin:$PATH RUSTUP_TOOLCHAIN=stable RELAYFLOWD_BIN=/Users/khaliqgant/.relayflows-toolchain/target/2945819964/debug/relayflowd VITEST_MAX_FORKS=2 VITEST_MIN_FORKS=1 npm test --prefix packages/sdk
```

Full captured output: [sdk-tests-final.txt](sdk-tests-final.txt). Exit status: 1: two watch-mode tests hit their unchanged five-second timeout under concurrent load. All typecheck/build phases completed successfully.

Literal final test output:

```text
Test Files 1 failed | 70 passed | 1 skipped (72)
Tests 2 failed | 1314 passed | 3 skipped (1319)
```

Both timeout failures were rerun as part of the entire watch suite, in isolation:

```sh
cd /Users/khaliqgant/fl-slice-S/packages/sdk
npm exec -- vitest run tests/cli-watch.test.ts --maxWorkers=1 --minWorkers=1
```

Literal output: [sdk-watch-retry.txt](sdk-watch-retry.txt). Exit status: 0.

```text
Test Files 1 passed (1)
Tests 10 passed (10)
```

No assertions, timeouts, or test selection within that suite were changed.
The final tree therefore has passing evidence for every enabled test across
the full run and isolated retry; the final full invocation was not green.

The skipped tests are the existing opt-in real CLI adapter suite. The new
helper tests and the existing Slack crash/resume tests ran.

The explicit Rust toolchain bypasses a stale mise shim; RELAYFLOWD_BIN points
all test consumers at this worktree's freshly built daemon. The fork limits
reduce contention without changing test selection or timeout assertions.

The earlier full run is retained at [sdk-tests.txt](sdk-tests.txt):

```sh
PATH=/Users/khaliqgant/.cargo/bin:$PATH RUSTUP_TOOLCHAIN=stable npm test --prefix packages/sdk
```

It exposed the memory.recall/provider-name collision and missing refusal-kind
coverage, which were repaired, as well as missing daemon paths and timeout
failures. Its output is not passing evidence.
2 changes: 2 additions & 0 deletions evidence/slice-S/codegen.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Generated 50 provider helpers (10 without upstream writeback clients)
HELPERS_GENERATED_OK airtable.ts, asana.ts, azure-blob.ts, box.ts, calendly.ts, clickup.ts, clients.ts, cloudflare.ts, confluence.ts, daytona.ts, docker-hub.ts, dropbox.ts, fathom.ts, gcp.ts, gcs.ts, github.ts, gitlab.ts, gmail.ts, google-calendar.ts, google-drive.ts, granola.ts, hubspot.ts, index.ts, intercom.ts, jira.ts, linear.ts, mailgun.ts, mixpanel.ts, neon.ts, notion.ts, onedrive.ts, pipedrive.ts, postgres.ts, posthog.ts, providers.ts, ramp.ts, recall.ts, reddit.ts, redis.ts, s3.ts, salesforce.ts, segment.ts, sendgrid.ts, sharepoint.ts, shopify.ts, shortcut.ts, slack.ts, stripe.ts, teams.ts, telegram.ts, webhook-server.ts, x.ts, zendesk.ts
16 changes: 16 additions & 0 deletions evidence/slice-S/provider-inventory.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"namespaces": 50,
"runtimeClients": 40,
"unavailable": [
"airtable",
"docker-hub",
"fathom",
"gcp",
"neon",
"posthog",
"segment",
"shopify",
"webhook-server",
"x"
]
}
Loading
Loading