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
22 changes: 22 additions & 0 deletions .github/workflows/canonical-versioning.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Canonical product versioning

on:
pull_request:
push:
branches: ['**']

permissions:
contents: read

jobs:
validate-version-source:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v5
with:
# Pull-request default checkout is a synthetic merge commit; qualification
# evidence must bind to the candidate that could actually be delivered.
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
fetch-depth: 2
- run: python3 scripts/advance_product_version.py --check
- run: python3 scripts/advance_product_version.py --verify-operation --candidate-head "${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}"
9 changes: 9 additions & 0 deletions .version-preparation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"contract_version": "1",
"product_id": "forge-platform",
"repository_id": "pcvantol/forge-platform",
"helper_path": "scripts/advance_product_version.py",
"receipt_directory": ".product-version-operations",
"allowed_projection_paths": ["product-version.json"],
"policy_revision": "FORGE_FAMILY_REPOSITORY_SEMVER_V1"
}
78 changes: 78 additions & 0 deletions docs/architecture/CANONICAL_PRODUCT_VERSIONING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Canonical product versioning

## Bootstrap release cadence V2

`forge-platform-bootstrap-release-cadence-v2` replaces push- and main-event
allocation for new operations. A bounded engineering increment defaults to one
`PATCH`; documentation-only work is explicit `NO_BUMP`; only an explicit
capability/release boundary is `MINOR`; `MAJOR` and `EXACT` require applicable
release authority. Repair, requalification and protected merge are evidence for
the same operation and cannot allocate a second version. V1 receipts remain
immutable historical evidence; CI validates but never writes versions.

**Status:** Adopted cross-product policy v1

Forge Platform owns this policy as the composition authority. Each product
repository remains authoritative for its own committed `product-version.json`;
Forge Platform does not rewrite another product's version.

The approved implementation baseline for the four repositories is `2.3.0`;
it is not evidence that any product was published. Each product can advance
independently. The product-local helper validates its only version source and
can apply an explicit patch/minor or exact release target with a stale-baseline
guard; it never decides compatibility, publication, or a major release.

- First qualifying feature-branch lineage events are allocated one patch, and
qualifying non-versioning main source events one minor with patch reset.
`release-X.Y.Z` is an explicit exact target; major requires an explicit
applicable release/architecture decision. Candidate numbering is not a
compatibility or release-GO decision.
- The current workflow is deliberately a read-only guard. A protected delivery
route invokes `scripts/advance_product_version.py --plan` and then `--apply`
with an explicit operation ID, event lineage and expected source HEAD. Apply
persists a repository-local operation receipt with policy revision, baseline,
target, allowed projection path and before/after manifest digests before a
delivery commit is made. The same ID and inputs recover the same target;
changed inputs conflict; a new operation at a stale HEAD fails closed.
The receipt and the one changed projection must be committed together and the
resulting commit recorded by the authorized delivery system once available.
Per-ref Actions concurrency and a commit subject are not that authority.
- A build reads the committed version and never allocates it. Publication binds
approved exact source, target version, artifact bytes/digest and qualification;
a repeated identity with different bytes is a conflict.

The policy governs Forge, Workspace and Forge Platform. Engineering Platform
uses the same event semantics with its richer multi-file package-version
projection. A Forge Platform release remains a separately qualified
composition of those independently versioned artifacts.

`--check` and `--plan` write nothing. `--apply` is interruption-safe only at
the per-file level: it records the allocation before atomically replacing the
single manifest, so a retry can complete or refuse the same operation without
allocating another version. It is not a multi-file Git transaction and it never
pushes, publishes, or turns a candidate number into release approval.

Engineering Platform PR [#105](https://github.com/pcvantol/engineering-platform/pull/105)
is the pending source-level bounded adapter for product-owned prepared
operations. It verifies declared helper identity, an isolated allowlisted
candidate and exact-head qualification evidence. It does not establish an
installed writer, an active authorization grant, merge authority, artifact
publication or universal-installer readiness.

## Candidate qualification and release boundary

This repository has protected-main pull-request gates but no authorized release
delivery API, GitHub App, or publication route. A delivery operator therefore
creates a dedicated version-preparation candidate from the recorded expected
source revision, commits only `product-version.json` and its receipt, and opens
that candidate for the ordinary protected route. The canonical-version workflow
checks out the exact PR head (never GitHub's synthetic merge ref) and runs
`--verify-operation --candidate-head <sha>`. It rejects a receipt whose parent,
projection digest, target, or changed paths differ. Thus the new candidate gets
its own qualification evidence; an older review/check cannot be repurposed.

`release-X.Y.Z` is parsed only as an explicit exact target by the helper; it is
not a branch authorization. No release workflow is configured here. Until an
authorized route can bind an approved exact candidate, compatibility decision,
artifact bytes/digest and publication identity, release preparation and
publication remain unsupported and fail closed by absence rather than a bypass.
2 changes: 1 addition & 1 deletion docs/architecture/COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

Forge Platform owns cross-product compatibility declarations: Forge version, Workspace version, Engineering Platform version, Agent version, and supported protocol versions. Product repositories remain authoritative for their own protocol implementation and compatibility guarantees.

A Forge Platform release is a tested composition of independently versioned artifacts, not a source-monorepo release. A future release may pair one qualified Forge Runtime version with independently qualified Workspace and Engineering Platform versions. This foundation intentionally chooses no release numbers.
A Forge Platform release is a tested composition of independently versioned artifacts, not a source-monorepo release. A future release may pair one qualified Forge Runtime version with independently qualified Workspace and Engineering Platform versions. Product version mutation is governed by [Canonical product versioning](CANONICAL_PRODUCT_VERSIONING.md); compatibility declarations remain a separate, explicit composition decision.
5 changes: 5 additions & 0 deletions docs/architecture/COMPONENT_MANIFEST_CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,8 @@ The same rule applies to Forge Server, Workspace Server, Workspace Client, Engin
The component manifest records a qualified release composition. It is not Forge's Living Mission Graph and does not carry the engineering execution DAG that produced the release. Action dependency and replanning authority remain Forge-owned; execution/admission evidence remains EP-owned.

The accompanying [JSON Schema](../../schemas/component-manifest.schema.json) is a structural contract, not a production manifest. It must preserve the distinction between source revision and artifact identity/digest.

Where a product version-preparation operation exists, its identity may be carried
as provenance but is not release authorization. Product version, API/protocol
version, policy version, source revision and artifact digest remain separate
identities; matching version strings are not compatibility or publication proof.
5 changes: 5 additions & 0 deletions product-version.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"product": "forge-platform",
"schema_version": 1,
"version": "2.3.0"
}
2 changes: 2 additions & 0 deletions schemas/component-manifest.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"identity": {"enum": ["forge-runtime", "workspace-server", "workspace-client", "engineering-platform-server", "engineering-platform-project-agent"]},
"version": {"type": "string", "minLength": 1},
"source_revision": {"type": "string", "minLength": 1},
"version_operation_id": {"type": "string", "minLength": 8},
"artifact": {
"type": "object",
"additionalProperties": false,
Expand All @@ -42,6 +43,7 @@
}
},
"protocol_compatibility": {"type": "object", "additionalProperties": {"type": "string"}},
"supported_contract_versions": {"type": "object", "additionalProperties": {"type": "string"}},
"dependencies": {
"type": "object",
"required": ["required", "optional"],
Expand Down
Loading