Workspace release sets
flog publish validates that a workspace publication is coherent before it
runs lifecycle scripts or mutates a registry. flog bump is the corresponding
release-authoring step: it can propose minimum mechanical version and range
edits, but it does not infer semantic intent or generate changelogs.
The failure this prevents#
Suppose the registry contains core@1.9.0 and adapter@2.4.0. The published
adapter depends on core@^1.9.0, while the workspace now contains adapter with
core: workspace:^ and local core is 2.0.0. Packing adapter converts that
declaration to core@^2.0.0.
Publishing core alone can leave local adapter code ahead of its published
package. Publishing adapter as 2.5.0 would move its dependency across a
compatibility boundary while advertising only a compatible adapter update.
Flog therefore requires adapter in a new compatibility line, such as 3.0.0,
and propagates that requirement to adapter's dependents.
workspace: conversion uses the current local workspace version; it does not
mean the registry's latest tag. Registry tags only select the published
baseline for comparison.
Compatibility lines#
Flog uses these conservative compatibility lines:
- packages at
1.0.0or above use their major version; 0.xpackages use their minor version;- every
0.0.xversion is a separate line.
Thus 1.8 → 2.0, 0.4 → 0.5, and 0.0.4 → 0.0.5 propagate release
requirements. Changes within 1.x or 0.4.x do not. A dependent is not forced
into the release set when its actual published range already accepts the
proposed dependency version, including a deliberately broad explicit range.
The baseline comes from the requested publication tag. A next publication is
compared with next, not with an unrelated stable latest release.
Edges and availability#
Runtime, optional, and peer workspace dependencies participate in release closure. Development dependencies are reported for review but do not force publication. Private and never-published dependents create no public release obligation.
A tagged published dependent with a non-empty npm registry deprecation message
does not require another release merely because its published range excludes a
new dependency version. This checks the registry version selected by the
requested tag, not a local package.json flag or any other deprecated
version. An exemption is reported as deprecated-dependent in the JSON plan.
If that dependent has a new version planned, normal release closure and forward
dependency availability checks still apply. Flog revalidates the deprecation
metadata before registry mutation, including when npm undeprecates the version.
The workspace root participates when it is a public package: its workspace dependencies are checked when publishing the root, and its published manifest can require a release when a child crosses a compatibility line. A private root remains configuration only and creates no publication obligation. Public roots and public workspace children must have distinct package names; workspace discovery rejects an ambiguous duplicate publication identity.
Mutually dependent packages are analyzed as one deterministic release unit. Because uploads are still sequential, a cycle is publishable only when each forward range is satisfied by an existing registry version or by a package that can be uploaded earlier; otherwise the availability check blocks it.
Every selected unpublished package is also checked in the forward direction. Its converted workspace ranges must be satisfied by a registry version or a package in the dependency-first publication plan. Exact versions already in the registry are not treated as proposed releases; their published dependency ranges are used instead of repacking local source. This prevents references to versions that consumers cannot obtain without misrepresenting skipped packages as new artifacts.
JSON release-set diagnostics record the package chain, dependency field, old and new versions, published and proposed ranges, required bump, corrective action, availability source, and override status. Human plans summarize successful checks and skipped packages; they foreground the actual publish candidates and actionable blockers. Successful JSON dry runs report those diagnostics in the final summary on stdout; blocked dry runs also print the full plan to stderr.
Reviewing and overriding#
After deliberately changing one or more package versions, inspect the exact transitive manifest proposal:
flog bump --dry-run
flog bump --dry-run --json
The requested --tag selects the registry baseline. With no local versions
different from that baseline, bump reports no proposal rather than inventing a
release. Existing higher author-chosen versions are preserved. Runtime,
optional, and peer obligations receive the minimum next compatibility line;
development-only and deprecated-dependent transitions remain informational,
and broad published ranges that already accept the seed version require no
dependent release.
Plain flog bump asks for confirmation; --yes is required when applying
noninteractively. Application revalidates every input and atomically replaces
the changed package.json files together with a synchronized flog.lock.
Range-only repairs may update an otherwise unreleased development, private, or
broad-range dependent without forcing a public version bump. Bump never
installs, packs, runs lifecycle scripts, or performs registry mutations. Retain
publication dry-run as the final availability and release-set validation:
flog publish --recursive --dry-run
For workspace-only version and range edits, bump validates the existing lock, updates workspace versions and importer specifiers across every represented target, and validates the transformed graph without re-resolving unrelated registry packages. If the lock is missing, stale in any other way, or cannot safely preserve peer and resolution contexts, an applying bump falls back to full resolution where possible and shows that phase; invalid or incompatible locks fail closed with a clear diagnostic. Dry runs remain bounded and read-only by leaving such fallback validation pending. JSON reports the lock status and strategy explicitly. Registry publication baselines remain authoritative and may still depend on cold network latency. Baseline checks are bounded to 30 seconds and full fallback resolution to two minutes, after which bump fails with a phase-specific timeout diagnostic.
The JSON plan records seed and required releases, dependency chains, registry baselines, proposed versions, exact field edits, and release-set diagnostics.
Inspect the complete plan without mutation:
flog publish --recursive --dry-run
flog publish --recursive --dry-run --json
If author intent requires versions other than bump's minimum proposal, edit them deliberately and rebuild the plan. If external knowledge proves a publication blocker acceptable, use the dedicated publish override:
flog publish --recursive --allow-incomplete-release-set
Neither --yes nor a git override bypasses release-set checks. The dedicated
override remains visible in the plan and final summary. Registry baselines for
omitted affected packages are revalidated during execution; a change aborts
publication rather than applying a stale decision.
Relationships visible through workspace dependencies need no configuration.
Explicit release groups may be added later for packages coupled outside that
graph. Safe publication does not depend on using flog bump; the publish
preflight remains authoritative.