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
13 changes: 13 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Public documentation and its publication contract
* @BartWaardenburg

/analysis/ @BartWaardenburg
/cli/ @BartWaardenburg
/configuration/ @BartWaardenburg
/explanations/ @BartWaardenburg
/frameworks/ @BartWaardenburg
/integrations/ @BartWaardenburg
/migration/ @BartWaardenburg
/.github/ @BartWaardenburg
/scripts/ @BartWaardenburg
/public-content-manifest.json @BartWaardenburg
56 changes: 56 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Documentation

on:
pull_request:
push:
branches:
- main

permissions:
contents: read

concurrency:
group: docs-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
validate:
name: Validate public documentation
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7

- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: 22
cache: npm

- name: Install dependencies
run: npm ci

- name: Check canonical public content
run: npm run content:check

- name: Test publication tooling
run: npm test

- name: Check links
run: npm run docs:broken-links

- name: Validate Mintlify site
run: npm run docs:validate

- name: Build public documentation archive
if: github.event_name == 'push'
run: npm run content:archive -- --source-commit "$GITHUB_SHA"

- name: Upload public documentation archive
if: github.event_name == 'push'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: fallow-public-docs-${{ github.sha }}
path: dist/
if-no-files-found: error
retention-days: 30
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
launch-content/
.DS_Store
dist/
node_modules/
5 changes: 5 additions & 0 deletions .mintignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ AGENTS.md
CONTRIBUTING.md
README.md
LICENSE
PUBLICATION.md
package-lock.json
package.json
public-content-manifest.json
scripts/
skills-lock.json
22 changes: 16 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@

Mintlify documentation site for [fallow](https://github.com/fallow-rs/fallow), deterministic codebase intelligence for TypeScript and JavaScript. Three audiences: AI agents, human developers, CI pipelines.

This repository is the canonical source for public user documentation. Read
`PUBLICATION.md` before changing publication tooling or moving content between
repositories.

## Dev server

```bash
npx mintlify dev
npm ci
npm run docs:dev
```

## File structure
Expand Down Expand Up @@ -59,11 +64,16 @@ Tabs, Steps, Cards, CardGroup, Accordion, Info, Tip, Warning, Note, CodeGroup.

- Document the public CLI, configuration, and integrations only.
- Do not document Rust internals.
- Never copy private repository content into this repository automatically.
- Private insights require a public rewrite and normal review in this repository.
- Keep `scripts/public-content.mjs` allowlisted. Do not package arbitrary
directories or follow symlinks.

## Verifying changes

1. Run `npx mintlify dev` and check the page renders.
2. Check all links resolve (no broken hrefs).
3. Confirm frontmatter has all four required fields.
4. If you added a page, add it to the correct group in `docs.json`.
5. Verify counts still match: 123 plugins, 15 issue types, 141 knip plugins.
1. Run `npm run content:manifest` after changing public content.
2. Run `npm run check`.
3. Check the changed page with `npm run docs:dev`.
4. Confirm frontmatter has all four required fields.
5. If you added a page, add it to the correct group in `docs.json`.
6. Verify counts still match: 123 plugins, 15 issue types, 141 knip plugins.
13 changes: 9 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,24 @@ Every page on [docs.fallow.tools](https://docs.fallow.tools) has "Suggest edits"
```bash
git clone https://github.com/fallow-rs/docs
cd docs
npm i -g mint
mint dev
npm ci
npm run docs:dev
```

Preview at `http://localhost:3000`.

## Before submitting

```bash
mint broken-links # Check for broken links
mint validate # Validate the build
npm run content:manifest
npm run check
```

Review the manifest diff before submitting. It is the exact public content set.
Do not add private implementation notes, operations material, security
runbooks, roadmap details, or content copied from a private repository. See
[PUBLICATION.md](PUBLICATION.md) for ownership and synchronization rules.

## Writing guidelines

- Sentence case for headings
Expand Down
57 changes: 57 additions & 0 deletions PUBLICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Public documentation ownership

This repository is the canonical source for fallow's public user documentation.
It owns the prose published at `docs.fallow.tools` and the public content archive
consumed by other fallow systems.

## Boundary

Content in the public archive is selected by an explicit allowlist in
`scripts/public-content.mjs`. The archive contains public MDX pages, site
configuration, styles, and public assets. It does not contain repository
instructions, development tooling, skills, private implementation notes, or
content from another repository.

Private repositories may consume a pinned archive from this repository. They
must not publish their own internal documentation or copy private content into
the archive automatically. A private insight that belongs in public user
documentation must be rewritten for the public audience and submitted here as
a normal reviewable change.

## Sources of truth

- Public user guidance and examples: this repository.
- Public CLI and configuration behavior: the `fallow-rs/fallow` implementation
and its generated contracts.
- Public protocol shapes: their public protocol repository.
- Private architecture, operations, security, roadmap, and commercial context:
the private repository that owns that information.

When product behavior and prose differ, fix the product contract first or
update this repository in the same coordinated change.

## Publication artifacts

`public-content-manifest.json` records every packaged path, byte size, and
SHA-256 digest. Its aggregate digest identifies the complete public content
set.

The CI workflow creates:

- `fallow-public-docs.tar.gz`, a reproducible archive with normalized metadata.
- `fallow-public-docs.provenance.json`, the source repository, branch, commit,
content digest, and archive digest.

Consumers must pin the source commit or verify both digests before using an
artifact.

## Changing the public content set

1. Add or edit public content in an allowlisted directory.
2. Update `docs.json` when navigation changes.
3. Run `npm run content:manifest`.
4. Run `npm run check`.
5. Review the manifest diff. Unexpected paths are a publication blocker.

Do not widen the allowlist to package an internal document. Move only public,
audience-appropriate content into this repository.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@
## Development

```bash
npm i -g mint
mint dev
npm ci
npm run docs:dev
```

Preview at `http://localhost:3000`.

This repository is the canonical source for fallow's public user
documentation. See [PUBLICATION.md](PUBLICATION.md) for the public-only boundary,
artifact provenance, and synchronization contract.

## Structure

```
Expand All @@ -34,4 +38,5 @@ snippets/ - Reusable MDX components

Edit any `.mdx` file and push to `main`. Mintlify deploys automatically.

Run `mint broken-links` and `mint validate` before pushing.
Run `npm run content:manifest` after changing public content, then run
`npm run check` before pushing.
101 changes: 101 additions & 0 deletions cloud/beacon.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
title: "Cloud beacon setup"
description: "Connect a browser or Node service to Fallow Cloud, verify the first ingest, and diagnose a setup that stays empty."
keywords: ["fallow beacon", "runtime coverage", "browser coverage", "node coverage", "cloud ingest"]
icon: "tower-broadcast"
---

The beacon sends function-level execution counts to Fallow Cloud. HTTP mode needs three values before it can send anything: an API key, a project id, and the Fallow Cloud endpoint.

## Browser setup

Install the beacon and an Istanbul-compatible build instrumenter:

```bash
npm install @fallow-cli/beacon
npm install --save-dev oxc-coverage-instrument
```

Configure `oxc-coverage-instrument` in the production build so it populates `window.__coverage__`. Then start the browser beacon from the application entrypoint:

```ts
import { createBrowserBeacon } from "@fallow-cli/beacon/browser";

const beacon = createBrowserBeacon({
apiKey: import.meta.env.VITE_BEACON_API_KEY,
endpoint: "https://api.fallow.cloud",
projectId: "your-org/your-repo",
commitSha: import.meta.env.VITE_GIT_SHA,
coverageOrigin: "production",
});

beacon.start();
```

Use an ingest-only key with prefix `fallow_pub_k1_` in browser code. It can only call `POST /v1/ingest`. Never embed a full `fallow_live_k1_` key in a browser bundle.

The first browser snapshot can contain only startup code. The beacon intentionally skips that incomplete snapshot. Navigate through at least one real workflow, wait for the 30-second flush, or hide the page to trigger a flush.

## Node setup

Node can read V8 coverage when `NODE_V8_COVERAGE` is present before process startup. The beacon cannot enable V8 coverage after the process has started.

```bash
NODE_V8_COVERAGE=./coverage node dist/index.js
```

Start the beacon from server code after boot:

```ts
import { createNodeBeacon } from "@fallow-cli/beacon";

const beacon = createNodeBeacon({
apiKey: process.env.BEACON_API_KEY,
endpoint: "https://api.fallow.cloud",
projectId: "your-org/your-repo",
commitSha: process.env.GIT_SHA,
coverageOrigin: "production",
});

beacon.start();
```

Use a full `fallow_live_k1_` key and keep it server-side. Bun and Deno need build-time Istanbul instrumentation because their V8 capture path is unavailable or incomplete.

## Verify the first ingest

The beacon is quiet on successful uploads. Verify one of these observable signals:

1. `POST https://api.fallow.cloud/v1/ingest` returns `202 Accepted` in the browser network panel or server proxy logs.
2. The onboarding card at [fallow.cloud](https://fallow.cloud) changes to a repository row after aggregation.
3. The key's `last used` value updates under Settings, API keys.

An accepted ingest is asynchronous. A short delay between the `202` response and the repository row is expected.

## If the dashboard stays empty

Check these in order:

1. `endpoint` is exactly `https://api.fallow.cloud`.
2. Browser code uses an ingest-only key. Server code uses a full key.
3. The configured environment variable exists in the production build or process.
4. `projectId` is stable and different for each repository or service.
5. Browser builds contain Istanbul counters, or Node started with `NODE_V8_COVERAGE`.
6. The app exercised real routes or jobs after the beacon started.
7. The first `/v1/ingest` response is `202`, not `401`, `403`, `402`, `413`, or `429`.

When no coverage source is available, the beacon emits one actionable `onRuntimeMismatch` error and stops. Fix that message before waiting for another batch.

## Add static inventory

Runtime capture tells Fallow what V8 or Istanbul observed. Upload the static inventory in CI to make functions that were never tracked visible as `untracked`:

```bash
fallow coverage upload-inventory --api-key "$FALLOW_KEY"
```

For bundled or minified code, also upload source maps from CI. See [`fallow coverage`](/cli/coverage) for the inventory and source-map commands.

## Privacy

The beacon sends function paths, names, positions, hit counts, project metadata, and delivery reports. It does not send arguments, request bodies, environment variables, or source code. See the [network activity disclosure](https://fallow.cloud/coverage/network-activity) for the complete contract.
5 changes: 5 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@
"analysis/limitations"
]
},
{
"group": "Cloud",
"icon": "cloud",
"pages": ["cloud/beacon"]
},
{
"group": "Configuration",
"icon": "gear",
Expand Down
Loading