rcf-lite 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/bin/view-supervisor-child.mjs +0 -0
- package/blueprints/delivery-ci-workflows/README.md +4 -0
- package/blueprints/delivery-ci-workflows/assets/bootstrap/README.md +26 -0
- package/blueprints/delivery-ci-workflows/assets/bootstrap/adr-bootstrap-coverage-supersession.template.json +28 -0
- package/blueprints/delivery-ci-workflows/assets/ci-provider-examples/github-actions/default-branch-checks.yml +12 -6
- package/blueprints/delivery-ci-workflows/assets/ci-provider-examples/github-actions/pull-request-checks.yml +16 -7
- package/blueprints/delivery-ci-workflows/assets/ci-provider-examples/github-actions/release.yml +4 -0
- package/blueprints/delivery-ci-workflows/assets/ci-provider-examples/github-actions/scheduled-audit.yml +4 -0
- package/blueprints/delivery-ci-workflows/assets/ci-provider-examples/notes.md +5 -5
- package/blueprints/delivery-ci-workflows/assets/report-samples/per-gate.json +1 -1
- package/blueprints/delivery-ci-workflows/blueprint.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/adrs/adr-702-delivery-ci-workflows-strict-coverage-gate.json +2 -2
- package/blueprints/delivery-ci-workflows/contributions/tacs/tac-701-delivery-ci-workflows-gate-runner.json +2 -2
- package/blueprints/delivery-ci-workflows/contributions/tacs/tac-704-delivery-ci-workflows-workflow-materialiser.json +7 -4
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6111.json +2 -2
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6114.json +6 -6
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6115.json +6 -6
- package/blueprints/delivery-ci-workflows/guide/delivery-ci-workflows.md +39 -1
- package/fixtures/canary-manifest.json +101 -1
- package/guidance/harness-template.md +9 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +9 -0
- package/package.json +13 -15
- package/releases/releases.yaml +21 -1
- package/src/blueprint/apply.js +15 -6
- package/src/blueprint/index.js +22 -0
- package/src/blueprint/library-cache.js +143 -0
- package/src/blueprint/library-fetcher-git.js +347 -0
- package/src/blueprint/library-fetcher-tarball.js +379 -0
- package/src/blueprint/library-loader.js +21 -0
- package/src/blueprint/shelf-resolver.js +100 -7
- package/src/blueprint/supersede.js +56 -13
- package/src/cli/blueprint-library.js +427 -82
- package/src/cli/blueprint.js +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,38 @@ All notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Pre-1.0, breaking changes are signalled by a minor version bump.
|
|
6
6
|
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.16.0] - 2026-09-03
|
|
10
|
+
|
|
11
|
+
External blueprint libraries complete. Phase 2c lands git and tarball fetchers with a checked-in on-disk cache so a fresh clone lists library blueprints without a re-fetch, and a refresh path that re-resolves annotated-tag or tarball digest and refuses on drift. Amendment A2 makes plain-path adds library-aware so an author's local edit loop stamps the same effective slug and identity a qualified add would. Amendment A3 adds a blueprint paragraph to the managed agent-instructions block so the agent conversationally offers blueprints and registered libraries and the operator chooses. A library-authoring standard doc plus a worked-example fixture binds the doc against the shipped tooling.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **External blueprint libraries phase 2c: git and tarball fetchers + on-disk cache.** `rcf define blueprint library add` now accepts `git+<url>#<annotated-tag-or-sha>` and tarball URLs (with `--sha256 <hex>` for the pin). Fetched content lands under `rcf/.blueprint-libraries/<libraryPrefix>/<libraryRef>/`, checked into git as ordinary tree content so a fresh clone can `rcf define blueprint list` without a re-fetch (spec section 4.4). Floating branches (`main`, `master`, `HEAD`, `latest`, `develop`, `trunk`) refuse categorically; lightweight tags refuse with a diagnostic pointing at annotation as the fix; a tarball digest mismatch refuses the fetch and writes nothing. `rcf define blueprint library refresh <prefix>` re-resolves the tag's peeled commit (git) or re-downloads and re-verifies the digest (tarball) and refuses on drift per spec sections 6.4 / 9.12. `rcf define blueprint library remove <prefix>` now drops the on-disk cache for network sources. Zero new runtime dependencies: the git side shells out to the ambient `git` CLI; the tarball side uses built-in `fetch()`, `zlib`, and a bundled minimal POSIX-ustar parser. Auth remains out of scope for v1 (spec section 9.4): ambient git access is the model, no-access is definitive.
|
|
16
|
+
- **Amendment A2: library-aware local path (2026-09-03).** `rcf define blueprint add <path>` now walks up from the target directory looking for `library.json`; on a hit the resolver requires the target to sit at `<library-root>/blueprints/<slug>` and stamps the same effective slug and identity a qualified `<prefix>:<slug>` add would after registration. Library-qualified addressing and plain-path addressing now produce identical slugs and stamped ids. A path with no `library.json` in any ancestor keeps the phase-1 route unchanged, byte-for-byte. The trade-off (spec: an unregistered local library bypasses review-on-add) is accepted because the alternative kills the "author now, test now" loop; the `local` provenance warning on apply is the mitigation.
|
|
17
|
+
- **Amendment A3: blueprint paragraph in the managed agent-instructions block (2026-09-03).** New paragraph inside the "How to talk to your operator" section teaches the plain-language shape: agent enumerates blueprints and registered libraries and offers one that fits; the operator chooses, the agent never picks; qualified names and command lines belong in files and `rcf` output, not in the conversation. Hash regenerated via `scripts/gen-managed-artefacts.mjs`; harness template mirrored automatically.
|
|
18
|
+
- **Library authoring standard doc.** `packages/rcf-lite/docs/library-authoring.md` documents the library shape, `library.json` field contract, prefix and band rules, the local-path authoring loop (A2), registration, refresh / drift, and interaction with core. Ships with a minimum-viable worked-example library at `test/fixtures/library-authoring-example/` (prefix `wla`, one blueprint with one REQ and one ADR) that doubles as the fixture body for `test/blueprint/library-authoring-example.test.js`; the fixture binds the doc against the shipped tooling so a drift in either trips the suite.
|
|
19
|
+
|
|
20
|
+
## [0.15.0] - 2026-08-31
|
|
21
|
+
|
|
22
|
+
Same-evening fix wave on top of 0.14.0. Four PRs closing off the WSD-handover surface: durable library-ownership stamping on applied records (paired with `@stravica-ai/rcf-schemas` 0.5.1), `blueprint supersede --incoming` accepting the same source forms as `add`, the review-on-add card gaining its section 8.1 global-topics and prefix-check lines, and the `delivery-ci-workflows` v2.1 additive shape resolving the four P1 findings from the second dogfood run.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **`libraryPrefix` stamped on library-applied records** (#131, paired with `@stravica-ai/rcf-schemas` 0.5.1). `manifest.blueprints[]` records that resolved through a registered external library now carry the additive `libraryPrefix` field. `rcf define blueprint library remove` reads it as the authoritative ownership signal, with a source-prefix fallback for pre-0.5.1 records, so a library re-registered on this project under a different prefix (rename, split, publisher change) no longer orphans its previously applied records. Shelf and path applies still write no `libraryPrefix`.
|
|
27
|
+
- **Review-on-add renders section 8.1 lines** (#134, `w-2026-08-31-dave-026`). `rcf define blueprint library add` (interactive review) now prints a "Global topics these blueprints claim" section listing every `<libraryPrefix>:<blueprintSlug>` on the library that carries a `scope:global` ADR contribution, one topic per line, suppressed entirely when no blueprint claims a topic. A new unconditional "Prefix check" line reports the collision-gate outcome alongside the existing "Band check" line. Companion loader change attaches a deduped `globalTopics[]` per blueprint entry under `validateBlueprints: true`; the resolver-time hot path stays cheap.
|
|
28
|
+
- **`delivery-ci-workflows` v2.1 (additive workflowShape)** (#135). Blueprint version bumped from 2.0.0 to 2.1.0. Three new optional `workflowShape` fields land: `packageManager` (elicited, `pnpm` default, `pnpm` / `npm` / `yarn` / `bun` recognised) and `defaultBranch` + `trunkBranch` (both default `main`). The `rcf define blueprint add delivery-ci-workflows` guide teaches the per-manager setup and install blocks; the shipped GHA assets under `assets/ci-provider-examples/github-actions/` carry paired `# @@RCF-SUB-*@@` markers so the materialiser can substitute per project. A new "Bootstrap posture (the guaranteed-red first run)" section in the guide and README, plus a shipped `assets/bootstrap/adr-bootstrap-coverage-supersession.template.json` starting-point ADR, name and demote the coverage-strict bootstrap trap.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **`rcf define blueprint supersede --incoming` accepts every source form `add` accepts** (#133). Persona re-run arc-4 H2 showed `@stock/<slug>` and bare kebab slugs both hit `--incoming @stock/security-auth-magic-link: no blueprint.json found` because the verb fed the raw string to `loadBlueprint` (paths only) and skipped `resolveBlueprintSource`. `supersede` now routes `--incoming` through the shared resolver, so path, `@stock/<slug>`, bare kebab slug, and colon-qualified `<libraryPrefix>:<slug>` all work verbatim. Library-qualified sources record `effectiveSlug` in the supersedes[] entry, matching `apply.js`'s identity rewiring.
|
|
33
|
+
- **`delivery-ci-workflows` v2.1 four P1 dogfood-2 findings** (#135). F-3: TAC-701 interface descriptor + `assets/report-samples/per-gate.json` synced to the runnable grouped-verb form (`rcf define validate`, `rcf audit coverage --strict`). F-1: package manager is elicited and observable in the material output; alternate-provider notes teach the substitution. F-2: the branch-model AC property (branch model determines which branch triggers the workflow) is now observable in the material output rather than masked by a hard-coded `main`. F-4: the guaranteed-red-first-run trap is named at the guide, README, ADR-702 consequences, and a shipped bootstrap template. Ride-along F-5: TAC-704 responsibilities now name the source-resolution path (`manifest.blueprints[].source` -> `<source>/assets/ci-provider-examples/<providerHint>/`) so a first-time realiser is not left to invent it.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- **`@stravica-ai/rcf-schemas` bumped from `0.5.0` to `0.5.1`, exact-pinned.** The additive `libraryPrefix` field on applied records requires the paired schema. Per the packaging registry runbook's version-skew doctrine, the dependency is an exact pin (`"0.5.1"`, never a caret or tilde); the caret introduced mid-cycle in #131 is corrected in this release.
|
|
38
|
+
|
|
7
39
|
## [0.14.0] - 2026-08-31
|
|
8
40
|
|
|
9
41
|
The WSD-handover release. Nine PRs on top of 0.13.0 covering update-awareness end-to-end (feed source-of-truth + validator, `rcf version --check`, RULE 14), the `ci-pipeline` rename to `delivery-ci-workflows`, external-blueprint-library resolution (phase 2b), scoped deep links in the live docs viewer, product-identity rename to "RCF Lite", and one integration-review fix batch.
|
|
File without changes
|
|
@@ -44,6 +44,10 @@ ADR-709-delivery-ci-workflows-release-artefacts ships `scope: global` on topic `
|
|
|
44
44
|
|
|
45
45
|
See `docs/topics.md` for the exact strings, the expected resolutions, the delineation from the application-api-rest blueprint's `logging` topic, and the AC id band allocation (delivery-ci-workflows owns 6101-6899).
|
|
46
46
|
|
|
47
|
+
## Bootstrap posture (loud)
|
|
48
|
+
|
|
49
|
+
A fresh apply of this blueprint alongside its usual companions contributes tens to hundreds of ACs and zero TCs. The mandatory tier's `coverage-strict` gate refuses when any AC lacks a resolving TC (ADR-702), so the FIRST commit-triggered workflow the materialiser produces is guaranteed to refuse until the project either authors every TC or ships a project-level ADR demoting the gate. The guide's "Bootstrap posture" section names the two ratified paths and points at the starting-point ADR at `assets/bootstrap/adr-bootstrap-coverage-supersession.template.json`. Choose a path at apply time; discovering the trap at the first PR is a real cost this warning exists to save.
|
|
50
|
+
|
|
47
51
|
## Quality bar
|
|
48
52
|
|
|
49
53
|
The workflow-materialiser reads `.rcf/config/delivery-ci-workflows.json` and refuses to run when the three required fields are missing or when any field carries an unrecognised value; the required check set runs on every commit-triggered workflow the branch model defines; the mandatory tier runs first in order (`validate` then `coverage-strict`); the elicited tier runs after the mandatory tier in stable but non-load-bearing order; per-gate JSON reports at stable paths carry the v1 fixed key set plus the v2 `checkKind` field; distinct workflows write to distinct aggregate paths (`.rcf/reports/ci/pipeline.json` for commit-triggered, `.rcf/reports/ci/release.json` for release, `.rcf/reports/ci/scheduled-audit.json` for scheduled); a missing required gate report is recorded as `outcome: missing` and flips the aggregate to `failed`; the release workflow shape scales across four discrete modes with the `none` semantic reached either by explicit value or by absent field; the `deployHandoff:<slug>` mode invokes the named deploy blueprint's `promote` workflow with the `versionId` input and refuses at boot when the deploy blueprint is absent; the applied blueprint's source path carries one illustrative GHA workflow file per workflow in the matrix and a notes file mapping four points to alternate providers. Every bar is carried by ACs in the doc set, not by this README.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Bootstrap assets
|
|
2
|
+
|
|
3
|
+
Templates the operator copies into their project during the bootstrap window
|
|
4
|
+
of a fresh delivery-ci-workflows apply. Nothing here is imported automatically
|
|
5
|
+
by the blueprint; every file is a starting point the operator adapts and
|
|
6
|
+
registers on the project tree.
|
|
7
|
+
|
|
8
|
+
## `adr-bootstrap-coverage-supersession.template.json`
|
|
9
|
+
|
|
10
|
+
Project-level ADR template that demotes the mandatory-tier `coverage-strict`
|
|
11
|
+
gate to advisory-only during the bootstrap window (see the guide's "Bootstrap
|
|
12
|
+
posture" section for the problem statement).
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
|
|
16
|
+
1. Copy this file into the project's ADR directory (typically `rcf/adrs/`).
|
|
17
|
+
2. Rename the file and its `adrId` from the `ADR-XXX-...` placeholder to the
|
|
18
|
+
next free project-level ADR id.
|
|
19
|
+
3. Replace the two `TEMPLATE-*ISO8601` timestamps with the current wall-clock.
|
|
20
|
+
4. Register the ADR on the project as `scope: global` on topic
|
|
21
|
+
`strictCoverageGate` so it competes with ADR-702 through the resolutions
|
|
22
|
+
mechanism.
|
|
23
|
+
5. Amend the exit criterion in the `decision` section if `N = 5` consecutive
|
|
24
|
+
passes is not the right threshold for the project.
|
|
25
|
+
6. When the exit criterion is met, flip `status` to `superseded` and leave
|
|
26
|
+
the file in place for audit trail.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-XXX-bootstrap-coverage-supersession",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "During bootstrap the coverage-strict gate runs advisory-only until a stated exit criterion is met",
|
|
8
|
+
"context": "A fresh apply of the delivery-ci-workflows blueprint set (application-*, persistence-*, delivery-ci-workflows) contributes tens to hundreds of REQs and ACs and zero test cases. The mandatory-tier coverage-strict gate runs `rcf audit coverage --strict` which refuses when any AC lacks a resolving TC (ADR-702). On a fresh apply the very first commit-triggered workflow is therefore guaranteed to refuse until the project has authored a TC for every AC the blueprint set contributed. That is a real cost the operator either accepts up-front (author every TC before turning CI green) or defers behind a project-level supersession of ADR-702. This project accepts the deferral posture and states the exit criterion here.",
|
|
9
|
+
"decision": "During bootstrap the required-gate coverage invocation is demoted to advisory-only: the coverage-strict gate still runs on every commit-triggered workflow, its per-gate report still lands at the stable path, and the aggregate still records its outcome; but a `failed` outcome on coverage-strict does NOT flip the aggregate verdict to `failed` and does NOT block merge. Every other required gate (validate, and the elicited tier the project turned on) retains its merge-blocking semantics. This ADR supersedes ADR-702-delivery-ci-workflows-strict-coverage-gate on the `strictCoverageGate` topic for this project only. The demotion is bounded by a stated exit criterion: this ADR is retired (status flipped to superseded) when the mandatory-tier coverage-strict outcome has been `passed` on the default branch for N consecutive commits (recommended: N = 5) OR when the project's own audit shows every AC in the applied blueprint set has a resolving TC, whichever comes first. On retirement the coverage-strict gate reverts to merge-blocking per ADR-702's default posture, and this ADR's file is left in place with `status: superseded` for audit trail.",
|
|
10
|
+
"consequences": "The bootstrap window is a knowingly-relaxed CI posture; a reviewer merging during it MUST inspect the aggregate's coverage-strict per-gate report themselves rather than trusting the aggregate verdict alone. Every AC the blueprint set contributed still owes a TC; the exit criterion enforces the debt is repaid rather than allowed to accrue silently. A composing blueprint that ships its own coverage-mode opinion (a hypothetical `delivery-ci-workflows-shallow` or `delivery-ci-workflows-grace-window`) conflicts with this ADR the same way it would with ADR-702; the project-level resolver still picks the winner. Retiring this ADR is a one-line status change; the exit criterion is a checklist the retiring commit records.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Author every TC before turning CI green",
|
|
14
|
+
"summary": "Do not demote the gate; author the ~N hundred TCs before the first CI run.",
|
|
15
|
+
"reasonNotChosen": "The blueprint set is large and TC authoring is a real cost; front-loading it delays every other CI signal the project needs from day one. The demote-with-exit-criterion posture keeps every OTHER gate merge-blocking from day one and pays the coverage debt on a stated schedule."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Demote coverage-strict permanently to shallow-any",
|
|
19
|
+
"summary": "Retire ADR-702 without an exit criterion; run shallow-any as the project's coverage floor forever.",
|
|
20
|
+
"reasonNotChosen": "ADR-702's own consequences section names the failure mode shallow-any hides (an AC bound but no TC resolves it, REQ reads as covered because a sibling AC's TC resolves). The bootstrap posture is a stated deferral, not a permanent policy change; retiring the deferral is a one-line change the exit criterion drives."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"relatedAdrs": [
|
|
24
|
+
"ADR-702-delivery-ci-workflows-strict-coverage-gate"
|
|
25
|
+
],
|
|
26
|
+
"createdAt": "TEMPLATE-createdAt-ISO8601",
|
|
27
|
+
"updatedAt": "TEMPLATE-updatedAt-ISO8601"
|
|
28
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Illustrative default-branch-checks workflow for the delivery-ci-workflows blueprint.
|
|
2
|
-
# Copy this file into the host project as `.github/workflows/default-branch-checks.yml
|
|
3
|
-
#
|
|
4
|
-
#
|
|
2
|
+
# Copy this file into the host project as `.github/workflows/default-branch-checks.yml`.
|
|
3
|
+
# The file below is the pnpm+main default the materialiser writes when
|
|
4
|
+
# workflowShape.packageManager, workflowShape.defaultBranch and
|
|
5
|
+
# workflowShape.trunkBranch are absent.
|
|
5
6
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
7
|
+
# The file carries paired RCF substitution markers the materialiser
|
|
8
|
+
# rewrites from workflowShape (see guide/delivery-ci-workflows.md for
|
|
9
|
+
# marker names, replacement blocks, and the substitution table).
|
|
9
10
|
#
|
|
10
11
|
# The workflow runs the same required check set as pull-request-checks and
|
|
11
12
|
# writes to the same aggregate report path `.rcf/reports/ci/pipeline.json`.
|
|
@@ -17,6 +18,7 @@ name: default-branch-checks
|
|
|
17
18
|
|
|
18
19
|
on:
|
|
19
20
|
push:
|
|
21
|
+
# @@RCF-SUB-BRANCH-NAME@@
|
|
20
22
|
branches: [main]
|
|
21
23
|
|
|
22
24
|
jobs:
|
|
@@ -28,6 +30,7 @@ jobs:
|
|
|
28
30
|
- name: checkout
|
|
29
31
|
uses: actions/checkout@v4
|
|
30
32
|
|
|
33
|
+
# @@RCF-SUB-PKG-MGR-SETUP-BEGIN@@
|
|
31
34
|
- name: setup pnpm
|
|
32
35
|
uses: pnpm/action-setup@v4
|
|
33
36
|
with:
|
|
@@ -38,9 +41,12 @@ jobs:
|
|
|
38
41
|
with:
|
|
39
42
|
node-version: 24
|
|
40
43
|
cache: pnpm
|
|
44
|
+
# @@RCF-SUB-PKG-MGR-SETUP-END@@
|
|
41
45
|
|
|
46
|
+
# @@RCF-SUB-PKG-MGR-INSTALL-BEGIN@@
|
|
42
47
|
- name: install dependencies
|
|
43
48
|
run: pnpm install --frozen-lockfile
|
|
49
|
+
# @@RCF-SUB-PKG-MGR-INSTALL-END@@
|
|
44
50
|
|
|
45
51
|
- name: run rcf check set
|
|
46
52
|
run: node scripts/rcf-ci.js
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
# Illustrative pull-request-checks workflow for the delivery-ci-workflows blueprint.
|
|
2
|
-
# Copy this file into the host project as `.github/workflows/pull-request-checks.yml
|
|
3
|
-
#
|
|
4
|
-
#
|
|
2
|
+
# Copy this file into the host project as `.github/workflows/pull-request-checks.yml`.
|
|
3
|
+
# The file below is the pnpm+main default the materialiser writes when
|
|
4
|
+
# workflowShape.packageManager and workflowShape.defaultBranch are absent.
|
|
5
|
+
#
|
|
6
|
+
# The file carries paired RCF substitution markers the materialiser rewrites
|
|
7
|
+
# from workflowShape (see guide/delivery-ci-workflows.md, "Within-provider
|
|
8
|
+
# package-manager substitution" and "Trigger branch-name substitution" for
|
|
9
|
+
# marker names, replacement blocks, and the substitution table). A
|
|
10
|
+
# hand-copier on the default (pnpm + main) keeps the file as-is; a project
|
|
11
|
+
# on npm/yarn/bun or a non-main branch either runs the materialiser or
|
|
12
|
+
# applies the substitution table from the guide by hand.
|
|
5
13
|
#
|
|
6
14
|
# The workflow runs one CI-provider-neutral Node entry point that invokes the
|
|
7
15
|
# required check set (the mandatory tier plus the elicited subset the project
|
|
@@ -9,10 +17,6 @@
|
|
|
9
17
|
# reports under `.rcf/reports/ci/`, and uploads the report directory as a
|
|
10
18
|
# workflow artefact for downstream readers.
|
|
11
19
|
#
|
|
12
|
-
# Feature-branch shape: pull requests targeting the default branch.
|
|
13
|
-
# Trunk-based shape (trunkPullRequests: sometimes): pull requests targeting
|
|
14
|
-
# the trunk branch. Adjust the branch name on the `on: pull_request:` block.
|
|
15
|
-
#
|
|
16
20
|
# See `guide/delivery-ci-workflows.md` (four-point mapping) for translating
|
|
17
21
|
# this workflow to GitLab CI, CircleCI, Buildkite, or Jenkins.
|
|
18
22
|
|
|
@@ -20,6 +24,7 @@ name: pull-request-checks
|
|
|
20
24
|
|
|
21
25
|
on:
|
|
22
26
|
pull_request:
|
|
27
|
+
# @@RCF-SUB-BRANCH-NAME@@
|
|
23
28
|
branches: [main]
|
|
24
29
|
|
|
25
30
|
jobs:
|
|
@@ -31,6 +36,7 @@ jobs:
|
|
|
31
36
|
- name: checkout
|
|
32
37
|
uses: actions/checkout@v4
|
|
33
38
|
|
|
39
|
+
# @@RCF-SUB-PKG-MGR-SETUP-BEGIN@@
|
|
34
40
|
- name: setup pnpm
|
|
35
41
|
uses: pnpm/action-setup@v4
|
|
36
42
|
with:
|
|
@@ -41,9 +47,12 @@ jobs:
|
|
|
41
47
|
with:
|
|
42
48
|
node-version: 24
|
|
43
49
|
cache: pnpm
|
|
50
|
+
# @@RCF-SUB-PKG-MGR-SETUP-END@@
|
|
44
51
|
|
|
52
|
+
# @@RCF-SUB-PKG-MGR-INSTALL-BEGIN@@
|
|
45
53
|
- name: install dependencies
|
|
46
54
|
run: pnpm install --frozen-lockfile
|
|
55
|
+
# @@RCF-SUB-PKG-MGR-INSTALL-END@@
|
|
47
56
|
|
|
48
57
|
# Single-line invocation of the project's realised gate runner.
|
|
49
58
|
# The runner spawns the mandatory tier (`rcf define validate` then
|
package/blueprints/delivery-ci-workflows/assets/ci-provider-examples/github-actions/release.yml
CHANGED
|
@@ -35,6 +35,7 @@ jobs:
|
|
|
35
35
|
- name: checkout
|
|
36
36
|
uses: actions/checkout@v4
|
|
37
37
|
|
|
38
|
+
# @@RCF-SUB-PKG-MGR-SETUP-BEGIN@@
|
|
38
39
|
- name: setup pnpm
|
|
39
40
|
uses: pnpm/action-setup@v4
|
|
40
41
|
with:
|
|
@@ -45,9 +46,12 @@ jobs:
|
|
|
45
46
|
with:
|
|
46
47
|
node-version: 24
|
|
47
48
|
cache: pnpm
|
|
49
|
+
# @@RCF-SUB-PKG-MGR-SETUP-END@@
|
|
48
50
|
|
|
51
|
+
# @@RCF-SUB-PKG-MGR-INSTALL-BEGIN@@
|
|
49
52
|
- name: install dependencies
|
|
50
53
|
run: pnpm install --frozen-lockfile
|
|
54
|
+
# @@RCF-SUB-PKG-MGR-INSTALL-END@@
|
|
51
55
|
|
|
52
56
|
# The release orchestrator reads the releaseMode from its environment
|
|
53
57
|
# (RCF_RELEASE_MODE) and runs the appropriate step sequence:
|
|
@@ -31,6 +31,7 @@ jobs:
|
|
|
31
31
|
- name: checkout
|
|
32
32
|
uses: actions/checkout@v4
|
|
33
33
|
|
|
34
|
+
# @@RCF-SUB-PKG-MGR-SETUP-BEGIN@@
|
|
34
35
|
- name: setup pnpm
|
|
35
36
|
uses: pnpm/action-setup@v4
|
|
36
37
|
with:
|
|
@@ -41,9 +42,12 @@ jobs:
|
|
|
41
42
|
with:
|
|
42
43
|
node-version: 24
|
|
43
44
|
cache: pnpm
|
|
45
|
+
# @@RCF-SUB-PKG-MGR-SETUP-END@@
|
|
44
46
|
|
|
47
|
+
# @@RCF-SUB-PKG-MGR-INSTALL-BEGIN@@
|
|
45
48
|
- name: install dependencies
|
|
46
49
|
run: pnpm install --frozen-lockfile
|
|
50
|
+
# @@RCF-SUB-PKG-MGR-INSTALL-END@@
|
|
47
51
|
|
|
48
52
|
# The scheduled runner is a thin wrapper around the gate-runner
|
|
49
53
|
# (TAC-701) that overrides the aggregate report path to the
|
|
@@ -15,7 +15,7 @@ Which workflow files exist depends on `workflowShape`:
|
|
|
15
15
|
|
|
16
16
|
1. Job trigger. Fire the workflow's job on the trigger set defined for that workflow (see the corresponding GHA file's `on:` block for the reference shape).
|
|
17
17
|
2. Node setup. Install Node 24 or later on the runner.
|
|
18
|
-
3. Package-manager setup and install. Install the project's dependencies with the frozen-lockfile discipline of whichever manager the project uses.
|
|
18
|
+
3. Package-manager setup and install. Install the project's dependencies with the frozen-lockfile discipline of whichever manager the project uses. The manager is a project decision recorded on `workflowShape.packageManager` (default `pnpm`; recognised set `pnpm`, `npm`, `yarn`, `bun`); the per-manager setup and install blocks are named in the guide's "Within-provider package-manager substitution" table. Alternate providers translate the block to the provider's own action/command; the manager choice stays project-controlled.
|
|
19
19
|
4. Node entry-point invocation and artefact upload. Run `node <path>` (or a package-manager script that resolves to the same) for the workflow's entry point (gate-runner for `pull-request-checks` and `default-branch-checks`, release orchestrator for `release`, scheduled-audit runner for `scheduled-audit`); upload the aggregate report directory as a run artefact for downstream readers.
|
|
20
20
|
|
|
21
21
|
The blueprint does not ship provider-specific configuration files for the providers below at v2.0.0. A project hand-authors the first three points in the provider's own runner language and keeps the fourth unchanged per the workflow's entry point.
|
|
@@ -24,7 +24,7 @@ The blueprint does not ship provider-specific configuration files for the provid
|
|
|
24
24
|
|
|
25
25
|
- Triggers: for `pull-request-checks` use `rules: { if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main" }`; for `default-branch-checks` use `rules: { if: $CI_COMMIT_BRANCH == "main" }`; for `release` use `rules: { if: $CI_COMMIT_TAG }` plus a `workflow_dispatch`-equivalent through GitLab's manual jobs; for `scheduled-audit` use a scheduled pipeline.
|
|
26
26
|
- Node setup: use a `node:24` image or install through the runner's setup hook.
|
|
27
|
-
- Install: `pnpm install --frozen-lockfile`
|
|
27
|
+
- Install: the install line from the guide's substitution table for the project's `workflowShape.packageManager` (default `pnpm install --frozen-lockfile`).
|
|
28
28
|
- Invoke: `node scripts/rcf-ci.js` for check-set workflows; `node scripts/rcf-release.js` for release; `node scripts/rcf-scheduled-audit.js --report-path .rcf/reports/ci/scheduled-audit.json` for scheduled-audit.
|
|
29
29
|
- Artefact upload: `artifacts: { when: always, paths: [.rcf/reports/ci/] }`.
|
|
30
30
|
|
|
@@ -32,7 +32,7 @@ The blueprint does not ship provider-specific configuration files for the provid
|
|
|
32
32
|
|
|
33
33
|
- Triggers: `workflows:` with branch and PR filters for the two check-set workflows; scheduled workflows for `scheduled-audit`; the release workflow fires from tag-triggered pipelines.
|
|
34
34
|
- Node setup: `cimg/node:24.19` or the `node/install` orb command.
|
|
35
|
-
- Install:
|
|
35
|
+
- Install: the install line from the guide's substitution table for the project's `workflowShape.packageManager`.
|
|
36
36
|
- Invoke: as above.
|
|
37
37
|
- Artefact upload: `store_artifacts: { path: .rcf/reports/ci }`.
|
|
38
38
|
|
|
@@ -40,7 +40,7 @@ The blueprint does not ship provider-specific configuration files for the provid
|
|
|
40
40
|
|
|
41
41
|
- Triggers: pipeline-level branch conditions or per-step `branches: main` for check-set workflows; separate pipelines for release (tag-triggered) and scheduled-audit (Buildkite scheduled builds).
|
|
42
42
|
- Node setup: install Node 24 in the queue's setup hook or use a Docker plugin (`docker#v5.0.0`).
|
|
43
|
-
- Install:
|
|
43
|
+
- Install: the install line from the guide's substitution table for the project's `workflowShape.packageManager`.
|
|
44
44
|
- Invoke: as above.
|
|
45
45
|
- Artefact upload: `artifact_paths: [".rcf/reports/ci/**"]`.
|
|
46
46
|
|
|
@@ -48,7 +48,7 @@ The blueprint does not ship provider-specific configuration files for the provid
|
|
|
48
48
|
|
|
49
49
|
- Triggers: `triggers { githubPush() }` plus a multibranch pipeline configured to build pull requests against the default branch; a separate tag-triggered pipeline for release; `triggers { cron('H 6 * * *') }` for scheduled-audit.
|
|
50
50
|
- Node setup: install Node 24 via `tools { nodejs '24' }` or provision the agent with Node preinstalled.
|
|
51
|
-
- Install: `sh
|
|
51
|
+
- Install: `sh` invocation of the install line from the guide's substitution table for the project's `workflowShape.packageManager`.
|
|
52
52
|
- Invoke: `sh 'node scripts/rcf-ci.js'` (or the appropriate script per workflow).
|
|
53
53
|
- Artefact upload: `archiveArtifacts artifacts: '.rcf/reports/ci/**', allowEmptyArchive: true`.
|
|
54
54
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"title": "Coverage runs as per-AC strict; shallow-any is not accepted as a substitute in the required gate set",
|
|
8
8
|
"context": "The `rcf audit coverage` CLI runs in two modes: the default `shallow-any` (a REQ counts as covered when any AC on any US has any resolving TC) and the opt-in `--strict` (per-AC: every AC on every US must have a resolving TC). Shallow-any is useful for author-time exploration; it is the wrong mode for a merge-blocking gate because it hides the failure mode watchpost run4 caught in categories 5, 6, and 11 (an AC bound but no TC resolves it, and the REQ still reads as covered because some other AC's TC resolved). Choosing which coverage mode the pipeline runs is a policy decision distinct from choosing whether coverage runs at all.",
|
|
9
9
|
"decision": "The required-gate coverage invocation is `rcf audit coverage --strict`. Every AC on every US must resolve to a TC whose testPointer points at a real test; a `covered-unresolved` or uncovered AC fails the gate. Shallow-any is not accepted as a substitute in the required-gate set. A project that needs an author-time shallow-any view for exploration runs `rcf audit coverage` locally without `--strict`; the pipeline's gate is unaffected. Composing blueprints that ship a coverage gate hold this topic (`strictCoverageGate`) and conflict here by design: a hypothetical `delivery-ci-workflows-shallow` blueprint or a project that wants the shallow-any mode as its floor supersedes this ADR with a project-level ADR stating the reasoning.",
|
|
10
|
-
"consequences": "Every AC the RCF chain contributes must have a TC bound in the project's own build cycle before the pipeline turns green. That is the mechanism-reach discipline the strict mode enforces: shipping an AC without a TC is caught here, not in production. Composing blueprints (this one and any coverage-shipping blueprint the ecosystem grows) conflict on `strictCoverageGate` for one project-level ADR to fix. A project that thoughtfully accepts a shallow-any floor (small project, exploration phase, no operator-facing surface yet) authors that ADR and the pipeline follows.",
|
|
10
|
+
"consequences": "Every AC the RCF chain contributes must have a TC bound in the project's own build cycle before the pipeline turns green. That is the mechanism-reach discipline the strict mode enforces: shipping an AC without a TC is caught here, not in production. Composing blueprints (this one and any coverage-shipping blueprint the ecosystem grows) conflict on `strictCoverageGate` for one project-level ADR to fix. A project that thoughtfully accepts a shallow-any floor (small project, exploration phase, no operator-facing surface yet) authors that ADR and the pipeline follows.\n\nBootstrap consequence (loud): a fresh apply of the delivery-ci-workflows blueprint alongside any doc-heavy companion (an application-* blueprint plus a persistence-* blueprint contributes tens to hundreds of ACs and zero TCs) means the very first commit-triggered workflow the materialiser produces is guaranteed to refuse on this gate until either every AC has a resolving TC OR a project-level ADR demotes the gate. The guide's \"Bootstrap posture\" section names the two ratified paths (author-every-TC-first, or demote-to-advisory-with-exit-criterion) and points at the template ADR at `assets/bootstrap/adr-bootstrap-coverage-supersession.template.json` that expresses the demotion posture. A first-time operator who reaches this ADR through the aggregate-report refusal at their first PR has hit the trap; a first-time operator who reads the guide's bootstrap section before running the materialiser makes the posture choice at apply time.",
|
|
11
11
|
"alternativesConsidered": [
|
|
12
12
|
{
|
|
13
13
|
"name": "Run shallow-any as the required mode with strict as a warning gate",
|
|
@@ -21,5 +21,5 @@
|
|
|
21
21
|
}
|
|
22
22
|
],
|
|
23
23
|
"createdAt": "2026-08-24T00:00:00Z",
|
|
24
|
-
"updatedAt": "2026-08-
|
|
24
|
+
"updatedAt": "2026-08-31T12:00:00Z"
|
|
25
25
|
}
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
{
|
|
27
27
|
"name": "gate-descriptor",
|
|
28
28
|
"kind": "value",
|
|
29
|
-
"description": "{ name: string, command: string[] } where `command[0]` is the executable (typically `rcf`) and the rest are argv. The
|
|
29
|
+
"description": "{ name: string, command: string[] } where `command[0]` is the executable (typically `rcf`) and the rest are argv. The rcf CLI groups verbs by RCF stage; the mandatory tier for v1.0.0 uses the grouped forms this TAC's responsibilities section names: `[{ name: 'validate', command: ['rcf', 'define', 'validate'] }, { name: 'coverage-strict', command: ['rcf', 'audit', 'coverage', '--strict'] }]`. A descriptor whose `command` array omits the group (`['rcf', 'validate']`, `['rcf', 'coverage', '--strict']`) does not resolve on any shipped rcf CLI and refuses at gate spawn; the gate-runner does not paper over the difference."
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
"name": "entry-point CLI",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
],
|
|
56
56
|
"tradeoffs": "Running every gate as a separate child process costs Node startup for each; that cost buys a stable exit-code contract and a stable stream capture surface that a library-mode invocation would obscure. Continuing past a failing gate costs a slightly longer pipeline; that cost buys the reviewer seeing every failure on one run instead of chasing them one at a time. The runner does not run gates in parallel: gate ordering is a stable property the aggregate report depends on, and the small gate count at v1.0.0 does not motivate a parallel-and-serialise design.",
|
|
57
57
|
"createdAt": "2026-08-24T00:00:00Z",
|
|
58
|
-
"updatedAt": "2026-08-
|
|
58
|
+
"updatedAt": "2026-08-31T00:00:00Z"
|
|
59
59
|
}
|
|
@@ -11,9 +11,12 @@
|
|
|
11
11
|
"Perform the boot-check: refuse missing required fields (`branchModel`, `checkSet`, `providerHint`), refuse unrecognised values on any field, refuse `deployHandoff:<slug>` when the deploy blueprint is absent from the manifest; exit non-zero with a stable-coded error naming the offending field (AC-6112-1, AC-6112-2, AC-6122-3).",
|
|
12
12
|
"Expand a profile alias to the four-field composed form before any downstream reads it; refuse an unrecognised alias (AC-6113-1, AC-6113-2).",
|
|
13
13
|
"Compute the workflow set from `workflowShape` per the matrix in the spec (§3.2): the two commit-triggered workflows per branch model, the release workflow per `releaseMode`, the scheduled-audit workflow per `scheduledAudit` (AC-6114-1, AC-6114-2, AC-6115-1, AC-6115-2, AC-6121-1, AC-6121-2, AC-6123-1, AC-6123-2).",
|
|
14
|
-
"
|
|
14
|
+
"Read the applied blueprint source from `rcf/manifest.json`'s `blueprints[].source` field (the path recorded when `rcf define blueprint add` ran) and resolve the provider asset directory as `<source>/assets/ci-provider-examples/<providerHint>/`; do not hard-code the source path against `node_modules/` or any other convention.",
|
|
15
|
+
"Write one workflow file per workflow in the set to the provider's workflow path (v2.0.0: `.github/workflows/` for GHA); alternate providers translate per the four-point mapping doc.",
|
|
16
|
+
"Substitute the trigger branch name into the produced commit-triggered workflows: on `branchModel: feature`, the `pull-request-checks` and `default-branch-checks` triggers name `workflowShape.defaultBranch` (default `main`); on `branchModel: trunk`, they name `workflowShape.trunkBranch` (default `main`). The substitution is applied against the `# @@RCF-SUB-BRANCH-NAME@@` marker that the illustrative assets carry immediately above their `branches:` line; the marker's next line (the `branches: [...]` list) is rewritten to name the configured branch, so the property AC-6114/6115 binds to (the branch model determines which branch triggers the workflow) is observable in the materialised output rather than being masked by a hard-coded `main`.",
|
|
17
|
+
"Substitute the package-manager setup and install steps into every produced workflow: read `workflowShape.packageManager` (default `pnpm`; recognised values `pnpm`, `npm`, `yarn`, `bun`); replace every line fenced between `# @@RCF-SUB-PKG-MGR-SETUP-BEGIN@@` and `# @@RCF-SUB-PKG-MGR-SETUP-END@@` (exclusive) with the per-manager setup block, and every line fenced between `# @@RCF-SUB-PKG-MGR-INSTALL-BEGIN@@` and `# @@RCF-SUB-PKG-MGR-INSTALL-END@@` (exclusive) with the per-manager install block, per the substitution table in `guide/delivery-ci-workflows.md`. Refuse an unrecognised `packageManager` with the same boot-check error path the enumerated fields use.",
|
|
15
18
|
"Materialisation is idempotent: re-running with the same `workflowShape` writes the same files byte-for-byte; changing the shape overwrites the workflow files atomically (temp file + rename).",
|
|
16
|
-
"Emit a materialiser-run summary to stdout naming the workflow files produced
|
|
19
|
+
"Emit a materialiser-run summary to stdout naming the workflow files produced, the elicited-check set they carry, and the substituted branch name and package manager."
|
|
17
20
|
],
|
|
18
21
|
"internalStructure": "One Node module exporting `materialise({ configPath, providerAssetDir, workflowOutDir })` and a shebang entry point invocable as `node <path>` with no required argv. The reader parses the config; the boot-check module validates each field against the recognised enumeration; the matrix module computes the workflow set from the composed shape; the writer module reads the provider asset templates, substitutes the required check set into the gate-runner invocation line, and writes the workflow files atomically.",
|
|
19
22
|
"interfaces": [
|
|
@@ -25,7 +28,7 @@
|
|
|
25
28
|
{
|
|
26
29
|
"name": "workflow-shape",
|
|
27
30
|
"kind": "value",
|
|
28
|
-
"description": "The parsed and composed `workflowShape`: `{ branchModel, checkSet, releaseMode, providerHint, scheduledAudit, trunkPullRequests }` with alias expansion applied
|
|
31
|
+
"description": "The parsed and composed `workflowShape`: `{ branchModel, checkSet, releaseMode, providerHint, scheduledAudit, trunkPullRequests, defaultBranch, trunkBranch, packageManager }` with alias expansion applied, `releaseMode` defaulted to `none` when absent, `defaultBranch` and `trunkBranch` defaulted to `main` when absent, and `packageManager` defaulted to `pnpm` when absent."
|
|
29
32
|
},
|
|
30
33
|
{
|
|
31
34
|
"name": "entry-point CLI",
|
|
@@ -60,5 +63,5 @@
|
|
|
60
63
|
],
|
|
61
64
|
"tradeoffs": "A build-time materialiser costs an extra step in the project's onboarding (running `node <entryPointPath>` after editing the config) but buys byte-identical workflow files across two runs of the same shape, which is the property downstream tools (a diff-review, a CI-config-verifier) depend on. Writing to the provider workflow path (not a `dist/` directory) means the workflow files are committed and reviewable; the shape declaration and the materialised output are both under source control.",
|
|
62
65
|
"createdAt": "2026-08-31T00:00:00Z",
|
|
63
|
-
"updatedAt": "2026-08-
|
|
66
|
+
"updatedAt": "2026-08-31T12:00:00Z"
|
|
64
67
|
}
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"id": "AC-6111-2",
|
|
23
|
-
"description": "The three required fields (`branchModel`, `checkSet`, `providerHint`), the optional `releaseMode` field (absent has the same effect as `releaseMode: none`, per Q6-B ratification), the optional `scheduledAudit`
|
|
23
|
+
"description": "The three required fields (`branchModel`, `checkSet`, `providerHint`), the optional `releaseMode` field (absent has the same effect as `releaseMode: none`, per Q6-B ratification), the optional `scheduledAudit` field, the optional `trunkPullRequests` sub-field, and the optional substitution-surface fields `defaultBranch` (default `main`), `trunkBranch` (default `main`), and `packageManager` (default `pnpm`; recognised set `pnpm`, `npm`, `yarn`, `bun`) are the complete surface the workflow-materialiser reads. No other field the file carries is interpreted at this version; unknown fields are ignored (forward-compatibility).",
|
|
24
24
|
"given": "a `workflowShape` declaration carrying the three required fields, the optional fields, and additional unknown fields",
|
|
25
25
|
"when": "the workflow-materialiser reads the file",
|
|
26
|
-
"then": "the materialiser processes the recognised fields and ignores the unknown fields without failing the boot-check",
|
|
26
|
+
"then": "the materialiser processes the recognised fields (including the substitution-surface trio) and ignores the unknown fields without failing the boot-check",
|
|
27
27
|
"testable": true,
|
|
28
28
|
"scope": "runtime"
|
|
29
29
|
}
|
|
@@ -11,19 +11,19 @@
|
|
|
11
11
|
"acceptanceCriteria": [
|
|
12
12
|
{
|
|
13
13
|
"id": "AC-6114-1",
|
|
14
|
-
"description": "With `workflowShape.branchModel: feature`, the materialiser produces a `pull-request-checks` workflow triggered by pull requests targeting the default branch. The workflow invokes the Node gate-runner entry point (TAC-701) with the required check set (mandatory tier plus every `checkSet` flag set true).",
|
|
15
|
-
"given": "a `workflowShape` with `branchModel: feature` and every `checkSet` flag true",
|
|
14
|
+
"description": "With `workflowShape.branchModel: feature`, the materialiser produces a `pull-request-checks` workflow triggered by pull requests targeting the configured default branch (`workflowShape.defaultBranch`, default `main`). The workflow invokes the Node gate-runner entry point (TAC-701) with the required check set (mandatory tier plus every `checkSet` flag set true).",
|
|
15
|
+
"given": "a `workflowShape` with `branchModel: feature`, `defaultBranch: develop`, and every `checkSet` flag true",
|
|
16
16
|
"when": "the workflow-materialiser runs",
|
|
17
|
-
"then": "a `pull-request-checks` workflow file lands at the provider's workflow path, its trigger
|
|
17
|
+
"then": "a `pull-request-checks` workflow file lands at the provider's workflow path, its trigger's branch list names `develop` (the configured default branch, not the placeholder marker and not a hard-coded `main`), and its command line invokes the Node gate-runner entry point with the required check set",
|
|
18
18
|
"testable": true,
|
|
19
19
|
"scope": "runtime"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"id": "AC-6114-2",
|
|
23
|
-
"description": "With `branchModel: feature`, the materialiser additionally produces a `default-branch-checks` workflow triggered by pushes to the default branch. The workflow invokes the same Node gate-runner entry point on the same required check set.",
|
|
24
|
-
"given": "the same `workflowShape`",
|
|
23
|
+
"description": "With `branchModel: feature`, the materialiser additionally produces a `default-branch-checks` workflow triggered by pushes to the configured default branch. The workflow invokes the same Node gate-runner entry point on the same required check set.",
|
|
24
|
+
"given": "the same `workflowShape` (`branchModel: feature`, `defaultBranch: develop`)",
|
|
25
25
|
"when": "the workflow-materialiser runs",
|
|
26
|
-
"then": "a `default-branch-checks` workflow file lands at the provider's workflow path, its trigger
|
|
26
|
+
"then": "a `default-branch-checks` workflow file lands at the provider's workflow path, its trigger's branch list names `develop`, and its command line invokes the Node gate-runner entry point with the required check set",
|
|
27
27
|
"testable": true,
|
|
28
28
|
"scope": "runtime"
|
|
29
29
|
},
|
|
@@ -11,19 +11,19 @@
|
|
|
11
11
|
"acceptanceCriteria": [
|
|
12
12
|
{
|
|
13
13
|
"id": "AC-6115-1",
|
|
14
|
-
"description": "With `workflowShape.branchModel: trunk` and `trunkPullRequests` absent or `never`, the materialiser produces `default-branch-checks` only. The `pull-request-checks` workflow does not ship in this shape.",
|
|
15
|
-
"given": "a `workflowShape` with `branchModel: trunk` and no `trunkPullRequests` field",
|
|
14
|
+
"description": "With `workflowShape.branchModel: trunk` and `trunkPullRequests` absent or `never`, the materialiser produces `default-branch-checks` only, triggered by pushes to the configured trunk branch (`workflowShape.trunkBranch`, default `main`). The `pull-request-checks` workflow does not ship in this shape.",
|
|
15
|
+
"given": "a `workflowShape` with `branchModel: trunk`, `trunkBranch: trunk`, and no `trunkPullRequests` field",
|
|
16
16
|
"when": "the workflow-materialiser runs",
|
|
17
|
-
"then": "a `default-branch-checks` workflow file lands at the provider's workflow path, no `pull-request-checks` workflow file lands, and the merge-policy AC binds to the trunk-branch push-protection property",
|
|
17
|
+
"then": "a `default-branch-checks` workflow file lands at the provider's workflow path, its trigger's branch list names `trunk` (the configured trunk branch), no `pull-request-checks` workflow file lands, and the merge-policy AC binds to the trunk-branch push-protection property",
|
|
18
18
|
"testable": true,
|
|
19
19
|
"scope": "runtime"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"id": "AC-6115-2",
|
|
23
|
-
"description": "With `branchModel: trunk` and `trunkPullRequests: sometimes`, the materialiser additionally produces `pull-request-checks` on the same required check set as `default-branch-checks
|
|
24
|
-
"given": "a `workflowShape` with `branchModel: trunk` and `trunkPullRequests: sometimes`",
|
|
23
|
+
"description": "With `branchModel: trunk` and `trunkPullRequests: sometimes`, the materialiser additionally produces `pull-request-checks` on the same required check set as `default-branch-checks`, both triggered against the configured trunk branch.",
|
|
24
|
+
"given": "a `workflowShape` with `branchModel: trunk`, `trunkBranch: trunk`, and `trunkPullRequests: sometimes`",
|
|
25
25
|
"when": "the workflow-materialiser runs",
|
|
26
|
-
"then": "both workflow files land at the provider's workflow path
|
|
26
|
+
"then": "both workflow files land at the provider's workflow path with their trigger branch lists naming `trunk`, and the merge-policy AC binds to the trunk-branch protection property that admits only PRs whose `pull-request-checks` aggregate passed",
|
|
27
27
|
"testable": true,
|
|
28
28
|
"scope": "runtime"
|
|
29
29
|
}
|
|
@@ -67,7 +67,9 @@ The project ships `.rcf/config/delivery-ci-workflows.json` at the project root.
|
|
|
67
67
|
},
|
|
68
68
|
"releaseMode": "tagPlusArtefact",
|
|
69
69
|
"providerHint": "githubActions",
|
|
70
|
-
"scheduledAudit": false
|
|
70
|
+
"scheduledAudit": false,
|
|
71
|
+
"defaultBranch": "main",
|
|
72
|
+
"packageManager": "pnpm"
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
```
|
|
@@ -78,11 +80,25 @@ The project ships `.rcf/config/delivery-ci-workflows.json` at the project root.
|
|
|
78
80
|
- `releaseMode` (OPTIONAL, Q6-B ratification): `none`, `tagOnly`, `tagPlusArtefact`, or `deployHandoff:<slug>`. An absent field is treated the same as `none` (no release workflow ships). Not having a release path yet is a common scenario when starting a project; the ratification chose ergonomics over an explicit `none`.
|
|
79
81
|
- `scheduledAudit` (optional): boolean; default `false`.
|
|
80
82
|
- `trunkPullRequests` (optional; qualifies `branchModel: trunk`): `never` or `sometimes`; default `never`.
|
|
83
|
+
- `defaultBranch` (optional; qualifies `branchModel: feature`): the branch name the commit-triggered workflows fire against; default `main`. The materialiser substitutes this value into the trigger's branch list; a project on `develop`, `master`, or any other convention names it here rather than hand-editing the workflow files.
|
|
84
|
+
- `trunkBranch` (optional; qualifies `branchModel: trunk`): the trunk branch name the commit-triggered workflows fire against; default `main`. Same substitution semantics as `defaultBranch`.
|
|
85
|
+
- `packageManager` (optional): `pnpm`, `npm`, `yarn`, or `bun`; default `pnpm`. Selects the within-provider package-manager substitution the materialiser applies to every produced workflow (see the substitution table below).
|
|
81
86
|
|
|
82
87
|
### Profile aliases
|
|
83
88
|
|
|
84
89
|
Named profile aliases (`smallLibrary`, `smallService`, `internalPackage`, `trunkLibrary`) compose the four-field form. The materialiser expands the alias to the four-field form at boot; every AC binds to the four-field form. Adding an alias is a minor bump; renaming or removing an alias is a minor bump.
|
|
85
90
|
|
|
91
|
+
## Bootstrap posture (the guaranteed-red first run)
|
|
92
|
+
|
|
93
|
+
A fresh apply of this blueprint alongside its usual companions (an `application-*` blueprint plus a `persistence-*` blueprint, for example) contributes tens to hundreds of REQs and ACs and zero test cases. The mandatory tier's `coverage-strict` gate runs `rcf audit coverage --strict` which refuses when any AC lacks a resolving TC (ADR-702). That means the very first commit-triggered workflow the materialiser produces is guaranteed to refuse until either every AC has a TC OR a project-level ADR demotes the gate. This is a cost the operator either accepts up-front or defers behind a stated exit criterion; either way, name the posture at apply time rather than discovering it when the first PR is refused.
|
|
94
|
+
|
|
95
|
+
Two ratified bootstrap postures:
|
|
96
|
+
|
|
97
|
+
- **Author every TC before turning CI green.** Every AC the blueprint set contributed gets a TC before the first push; the coverage-strict gate stays merge-blocking from day one. Right when the AC count is small or the project's engineering standards refuse any advisory-only CI window.
|
|
98
|
+
- **Demote coverage-strict to advisory-only for a bounded window.** Ship a project-level ADR that supersedes ADR-702 on the `strictCoverageGate` topic for the project only, demoting the gate to advisory (its per-gate report still lands; its `failed` outcome no longer flips the aggregate). Bind the ADR to a stated exit criterion (recommended: `N` consecutive `passed` outcomes on the default branch, e.g. `N = 5`, or an audit confirming every AC has a resolving TC, whichever comes first). Retire the ADR by flipping its status to `superseded` when the criterion is met; the coverage-strict gate reverts to merge-blocking without further action.
|
|
99
|
+
|
|
100
|
+
The blueprint ships a starting-point ADR for the demotion posture at `assets/bootstrap/adr-bootstrap-coverage-supersession.template.json` (see the sibling `README.md` for the copy-adapt-register steps). Copy it, rename the id, fill the timestamps, register it as `scope: global` on topic `strictCoverageGate`, and the CI's first run turns green on every non-coverage gate on day one. The debt is real; the exit criterion keeps it visible.
|
|
101
|
+
|
|
86
102
|
## The check catalogue
|
|
87
103
|
|
|
88
104
|
Two tiers:
|
|
@@ -118,6 +134,28 @@ Every mainstream CI provider ships the same four ingredients under a different r
|
|
|
118
134
|
|
|
119
135
|
See `assets/ci-provider-examples/notes.md` for the per-provider translation.
|
|
120
136
|
|
|
137
|
+
## Within-provider package-manager substitution
|
|
138
|
+
|
|
139
|
+
The four-point mapping covers translation across providers; a project stays on one provider and picks its package manager. The illustrative GHA assets carry paired substitution markers fencing the setup step(s) and the install step; the materialiser replaces every line between the two fence markers (exclusive) with the per-manager block. The markers are YAML comments so the illustrative file is valid YAML on its own and reviewable as a diff after materialisation:
|
|
140
|
+
|
|
141
|
+
- `# @@RCF-SUB-PKG-MGR-SETUP-BEGIN@@` and `# @@RCF-SUB-PKG-MGR-SETUP-END@@` fence the manager's setup step(s).
|
|
142
|
+
- `# @@RCF-SUB-PKG-MGR-INSTALL-BEGIN@@` and `# @@RCF-SUB-PKG-MGR-INSTALL-END@@` fence the manager's install step.
|
|
143
|
+
|
|
144
|
+
The four recognised managers map to these blocks (GHA reference; alternate providers use the equivalent action or command in the provider's own runner language):
|
|
145
|
+
|
|
146
|
+
| `packageManager` | setup step | install line |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| `pnpm` (default) | `- uses: pnpm/action-setup@v4` followed by `with: { version: 9 }`; then `- uses: actions/setup-node@v4` with `node-version: 24` and `cache: pnpm` | `pnpm install --frozen-lockfile` |
|
|
149
|
+
| `npm` | `- uses: actions/setup-node@v4` with `node-version: 24` and `cache: npm` | `npm ci` |
|
|
150
|
+
| `yarn` | `- uses: actions/setup-node@v4` with `node-version: 24` and `cache: yarn` (yarn v1 or `enable-corepack` for berry) | `yarn install --frozen-lockfile` (v1) or `yarn install --immutable` (berry) |
|
|
151
|
+
| `bun` | `- uses: oven-sh/setup-bun@v2` with `bun-version: latest` | `bun install --frozen-lockfile` |
|
|
152
|
+
|
|
153
|
+
An unrecognised `packageManager` value refuses at the same boot-check exit path the enumerated fields use (AC-6112-2 shape).
|
|
154
|
+
|
|
155
|
+
## Trigger branch-name substitution
|
|
156
|
+
|
|
157
|
+
The commit-triggered assets (`pull-request-checks.yml`, `default-branch-checks.yml`) carry `# @@RCF-SUB-BRANCH-NAME@@` on the line immediately above the `branches:` list. The materialiser rewrites that one `branches:` line from `workflowShape.defaultBranch` (feature model) or `workflowShape.trunkBranch` (trunk model) so the branch-model AC (AC-6114/6115) is observable in the materialised output rather than being masked by a hard-coded `main`. Both fields default to `main`, so a project on the default keeps the current behaviour without touching the fields.
|
|
158
|
+
|
|
121
159
|
## Operator decisions that remain open after apply
|
|
122
160
|
|
|
123
161
|
- The workflow shape declaration (`.rcf/config/delivery-ci-workflows.json` populated).
|