# Versioning Policy

Fouria is a monorepo containing published packages, private Cloudflare Workers, OpenClaw plugins, and an Elixir application. These components serve different audiences and deployment models, so they use two versioning schemes. The monorepo itself has no version.

## Version Schemes

### 1. Semantic Versioning (Semver)

**Applies to:** Published npm packages (`moltlazy`).

```
MAJOR.MINOR.PATCH   e.g. 0.4.0
```

| Bump  | When                                | Examples                                                     |
| ----- | ----------------------------------- | ------------------------------------------------------------ |
| MAJOR | Breaking API or CLI changes         | SDK type renames, removed config keys, dropped Node versions |
| MINOR | New features, backward-compatible   | New config modules, new SDK methods, new CLI flags           |
| PATCH | Bug fixes, docs, internal refactors | Config generation fixes, type corrections, test additions    |

Each version bump gets a changelog entry in the component's `CHANGELOG.md`. Follow the existing format in `packages/moltlazy/CHANGELOG.md`.

### 2. Date-Based Versioning

**Applies to:** Cloudflare Workers, deployed apps, and OpenClaw plugins.

```
YYYY.M.D            e.g. 2026.6.1
```

For multiple releases on the same day, append a hyphen and counter:

```
YYYY.M.D-N          e.g. 2026.6.1-2
```

#### Components using date-based versioning

| Component                       | Path                                   | Version field |
| ------------------------------- | -------------------------------------- | ------------- |
| Tenant worker (moltbot-sandbox) | `apps/fouria/package.json`             | `version`     |
| Dispatch worker                 | `workers/fouria-dispatch/package.json` | `version`     |
| Fouria Dashboard                | `apps/lerma/package.json`              | `version`     |

#### OpenClaw plugins

OpenClaw plugins use date-based versioning **locked to the openclaw version they target**. The plugin version must equal `minOpenclawVersion` in `openclaw.plugin.json`.

| Component                  | Path                                                       | Current    |
| -------------------------- | ---------------------------------------------------------- | ---------- |
| Cloudflare Unified Billing | `packages/plugins/cloudflare-unified-billing/package.json` | `2026.7.1` |

When the `openclaw` dependency is bumped, the plugin version bumps with it.

### 3. Elixir-Native Versioning

**Applies to:** The Elixir/Phoenix application.

| Component                  | Path                                  |
| -------------------------- | ------------------------------------- |
| Fouria Dashboard (Phoenix) | `apps/lerma/` (managed via `mix.exs`) |

Follows standard Elixir/Mix version conventions. Independent from the JS versioning policy.

## Release Train

Deployed components (workers, apps, plugins) follow a **release train**: on deployment day, all components that have changed since their last version bump receive today's date as their version. Unchanged components stay on their prior version.

### Release day workflow

1. **Identify changed components.** Compare each component's current version against the commits since its last tag or version bump.
2. **Bump semver packages.** If `moltlazy` code changed, bump its version per semver rules and add a CHANGELOG entry.
3. **Bump OpenClaw plugins.** If `openclaw` dependency changed, update both the plugin version and `minOpenclawVersion`.
4. **Bump date-based components.** Set all changed workers/apps to today's date (`YYYY.M.D`).
5. **Tag and deploy.** Each component gets a git tag (see tagging below).

### Git tags

Each component is tagged independently:

```
packages/moltlazy/v0.4.0
apps/fouria/2026.6.1
workers/fouria-dispatch/2026.6.1
packages/plugins/cloudflare-unified-billing/2026.7.1
```

Tags are created at the commit where the version was bumped.

## Rules

1. **No root version.** The monorepo `package.json` stays unversioned.
2. **One scheme per component.** Published packages use semver. Everything else (except Elixir) uses date-based. Elixir uses its own conventions.
3. **Truly independent semver.** `moltlazy` versions independently of the deployed workers. Its semver bump does not depend on whether workers changed.
4. **Coupled date components.** Workers and apps share a release train. If any worker ships, all changed workers get the same date.
5. **Plugin version = openclaw version.** Never diverge. If `openclaw` is at `2026.6.3`, the plugin is at `2026.6.3`.
6. **Versions live in `package.json`** (or `mix.exs` for Elixir). No separate version files or constants.
7. **Bump before deploy.** Always bump the version in source before running `wrangler deploy` or equivalent.

## Release Notes

Each GitHub release is titled with today's CalVer date (`vYYYY.M.D`). The release body contains **only** a table of components whose versions were bumped, showing old → new version. No per-PR changelogs, no commit lists, no category grouping.

### Format

```
## Bumped components

| Component                 | Old version | New version |
| ------------------------- | ----------- | ----------- |
| `packages/moltlazy`       | `0.4.0`     | `0.4.1`     |
| `apps/fouria`             | `2026.6.1`  | `2026.7.14` |
| `workers/fouria-dispatch` | `2026.6.1`  | `2026.7.14` |
```

Unchanged components do not appear in the release notes.

### Release trigger

Releases are triggered automatically on pushes to `develop`. For semver components (`packages/moltlazy` and `apps/lerma`), the bump level (patch, minor, major) must be selected manually via the `workflow_dispatch` trigger with `moltlazy_bump` and `lerma_bump` inputs. On automatic push triggers, semver components are detected but their versions are **not** bumped — only CalVer components receive automatic version bumps.

### Git tags

Each bumped component receives a per-component git tag:

```
packages/moltlazy/v0.4.1
apps/fouria/2026.7.14
workers/fouria-dispatch/2026.7.14
packages/plugins/cloudflare-unified-billing/2026.6.12
apps/lerma/v0.1.1
```

CalVer components use the date directly as the tag suffix (e.g. `apps/fouria/2026.7.14`). Semver components include a `v` prefix (e.g. `packages/moltlazy/v0.4.1`, `apps/lerma/v0.1.1`).

### Same-day releases

If multiple releases occur on the same day, the CalVer version appends a `-N` counter:

```
v2026.7.14       first release
v2026.7.14-2     second release
v2026.7.14-3     third release
```

The counter is computed from existing root tags and applies to all CalVer components bumped in that release.

> [!NOTE]
> Github release **always** today date (CalVer), on release notes, it must appear only the bumped versions

### Scenario A: Only a bug fix in moltlazy

- `moltlazy`: `0.3.0` → `0.3.1` (PATCH bump)
- All workers: unchanged, stay at prior date
- Plugin: unchanged

### Scenario B: New feature in tenant worker + openclaw upgrade

- `openclaw`: `2026.7.1` → `2026.6.12`
- Plugin: `2026.7.1` → `2026.6.12` (locked to openclaw)
- Tenant worker: `1.0.0` → `2026.6.1` (changed, gets today's date)
- Dispatch worker: unchanged (stays at prior)
- Outbound worker: unchanged (stays at prior)
- `moltlazy`: unchanged (no semver bump needed)

### Scenario C: Multi-component release day

- `moltlazy`: `0.3.1` → `0.4.0` (breaking SDK change)
- Tenant worker: `2026.6.1` → `2026.6.15`
- Dispatch worker: `1.0.0` → `2026.6.15`
- Outbound worker: `1.0.0` → `2026.6.15`
- Plugin: unchanged (openclaw not bumped)
