From 3793e2e1bd41ad994bb6949637a0471470d27ef7 Mon Sep 17 00:00:00 2001 From: MariusStorhaug Date: Sun, 26 Jul 2026 10:11:06 +0200 Subject: [PATCH 1/6] docs: add Module Bootstrap pattern page $Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../Process-PSModule/module-bootstrap.md | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/docs/Modules/Process-PSModule/module-bootstrap.md diff --git a/src/docs/Modules/Process-PSModule/module-bootstrap.md b/src/docs/Modules/Process-PSModule/module-bootstrap.md new file mode 100644 index 0000000..188994a --- /dev/null +++ b/src/docs/Modules/Process-PSModule/module-bootstrap.md @@ -0,0 +1,38 @@ +# Module Bootstrap + +A brand-new module often needs several interdependent functions before it is usable at all — for example a TOML module needs `ConvertFrom-Toml`, `ConvertTo-Toml`, `Import-Toml`, and `Export-Toml` together before any of them is meaningful on its own. A single feature PR cannot carry that much scope and still be small and focused, so bootstrap uses one integration branch instead. + +## Pattern + +1. Cut one long-lived branch from the default branch for the initial release, named for the outcome, e.g. `build-toml-module`. +2. Open one pull request per function (or small group of related functions) targeting that branch instead of `main`. These PRs can land in parallel — there is no strict order between them, unlike a [stacked pull request](https://msxorg.github.io/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests). +3. Once the foundational set of functions is coherent and complete, open the pull request that merges the integration branch into `main`. This becomes the module's first real release. +4. Smaller follow-up features (one more function, a formatter, an alias) can keep targeting the integration branch before it lands, the same way they targeted it during bootstrap. + +```mermaid +gitGraph + commit id: "main" + branch build-toml-module + checkout build-toml-module + commit id: "ConvertFrom-Toml" + commit id: "ConvertTo-Toml" + commit id: "Import-Toml / Export-Toml" + checkout main + merge build-toml-module id: "first release" +``` + +## Example + +[PSModule/Toml](https://github.com/PSModule/Toml) bootstrapped this way: + +| PR | Targets | Contents | +| --- | --- | --- | +| [#15](https://github.com/PSModule/Toml/pull/15) | `main` | `build-toml-module` branch, the foundational `ConvertFrom-Toml`, `ConvertTo-Toml`, `Import-Toml`, `Export-Toml` release | +| [#20](https://github.com/PSModule/Toml/pull/20) | `build-toml-module` | `Format-Toml`, a follow-up feature added before the integration branch merged | + +## When to use this + +- The module has no usable release yet, and no single function is meaningful without the others. +- Use this only for the initial bootstrap. Once `main` has a first release, ongoing feature work targets `main` directly with ordinary topic branches, or a [stacked pull request](https://msxorg.github.io/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) when changes genuinely depend on each other. + +For the general branching and merge model, see [MSX Branching and Merging](https://msxorg.github.io/docs/Ways-of-Working/Branching-and-Merging/). From f636ff34555507658a251045ca72f55303a6142c Mon Sep 17 00:00:00 2001 From: MariusStorhaug Date: Sun, 26 Jul 2026 10:11:11 +0200 Subject: [PATCH 2/6] docs: link Module Bootstrap into nav and quickstart $Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/docs/Modules/Process-PSModule/index.md | 1 + src/docs/Modules/Process-PSModule/template-quickstart.md | 2 ++ src/zensical.toml | 1 + 3 files changed, 4 insertions(+) diff --git a/src/docs/Modules/Process-PSModule/index.md b/src/docs/Modules/Process-PSModule/index.md index 3194648..e963bbe 100644 --- a/src/docs/Modules/Process-PSModule/index.md +++ b/src/docs/Modules/Process-PSModule/index.md @@ -10,5 +10,6 @@ This section documents how module repositories are formed and how they move from - [Module Anatomy](module-anatomy.md) - [Build, Test, Pack, Publish](build-test-pack-publish.md) - [Template Quickstart](template-quickstart.md) +- [Module Bootstrap](module-bootstrap.md) For broader framework context, see [MSX Frameworks / Process-PSModule](https://msxorg.github.io/docs/Frameworks/Process-PSModule/). diff --git a/src/docs/Modules/Process-PSModule/template-quickstart.md b/src/docs/Modules/Process-PSModule/template-quickstart.md index f144a61..0a0fad5 100644 --- a/src/docs/Modules/Process-PSModule/template-quickstart.md +++ b/src/docs/Modules/Process-PSModule/template-quickstart.md @@ -12,6 +12,8 @@ Start new modules from the PSModule template repository: 4. Validate `.github/PSModule.yml` defaults for your module. 5. Open a draft pull request and run the full pipeline. +If the module needs several interdependent commands before it is usable at all, see [Module Bootstrap](module-bootstrap.md) instead of shipping them as one command per step. + ## Expected outcomes - repository follows Process-PSModule structure diff --git a/src/zensical.toml b/src/zensical.toml index 5990c31..ad6c524 100644 --- a/src/zensical.toml +++ b/src/zensical.toml @@ -33,6 +33,7 @@ nav = [ {"Module Anatomy" = "Modules/Process-PSModule/module-anatomy.md"}, {"Build, Test, Pack, Publish" = "Modules/Process-PSModule/build-test-pack-publish.md"}, {"Template Quickstart" = "Modules/Process-PSModule/template-quickstart.md"}, + {"Module Bootstrap" = "Modules/Process-PSModule/module-bootstrap.md"}, ]}, ]}, {"Dictionary" = [ From 1ec031489cdf52cccdc3ec48ae3c62d16cc0e3e2 Mon Sep 17 00:00:00 2001 From: MariusStorhaug Date: Sun, 26 Jul 2026 10:14:25 +0200 Subject: [PATCH 3/6] docs: use placeholder data in Module Bootstrap example $Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../Process-PSModule/module-bootstrap.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/docs/Modules/Process-PSModule/module-bootstrap.md b/src/docs/Modules/Process-PSModule/module-bootstrap.md index 188994a..d3710e3 100644 --- a/src/docs/Modules/Process-PSModule/module-bootstrap.md +++ b/src/docs/Modules/Process-PSModule/module-bootstrap.md @@ -1,10 +1,10 @@ # Module Bootstrap -A brand-new module often needs several interdependent functions before it is usable at all — for example a TOML module needs `ConvertFrom-Toml`, `ConvertTo-Toml`, `Import-Toml`, and `Export-Toml` together before any of them is meaningful on its own. A single feature PR cannot carry that much scope and still be small and focused, so bootstrap uses one integration branch instead. +A brand-new module often needs several interdependent functions before it is usable at all — for example a module might need `ConvertFrom-Thing`, `ConvertTo-Thing`, `Import-Thing`, and `Export-Thing` together before any of them is meaningful on its own. A single feature PR cannot carry that much scope and still be small and focused, so bootstrap uses one integration branch instead. ## Pattern -1. Cut one long-lived branch from the default branch for the initial release, named for the outcome, e.g. `build-toml-module`. +1. Cut one long-lived branch from the default branch for the initial release, named for the outcome, e.g. `build-thing-module`. 2. Open one pull request per function (or small group of related functions) targeting that branch instead of `main`. These PRs can land in parallel — there is no strict order between them, unlike a [stacked pull request](https://msxorg.github.io/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests). 3. Once the foundational set of functions is coherent and complete, open the pull request that merges the integration branch into `main`. This becomes the module's first real release. 4. Smaller follow-up features (one more function, a formatter, an alias) can keep targeting the integration branch before it lands, the same way they targeted it during bootstrap. @@ -12,23 +12,23 @@ A brand-new module often needs several interdependent functions before it is usa ```mermaid gitGraph commit id: "main" - branch build-toml-module - checkout build-toml-module - commit id: "ConvertFrom-Toml" - commit id: "ConvertTo-Toml" - commit id: "Import-Toml / Export-Toml" + branch build-thing-module + checkout build-thing-module + commit id: "ConvertFrom-Thing" + commit id: "ConvertTo-Thing" + commit id: "Import-Thing / Export-Thing" checkout main - merge build-toml-module id: "first release" + merge build-thing-module id: "first release" ``` ## Example -[PSModule/Toml](https://github.com/PSModule/Toml) bootstrapped this way: +A module bootstrapped this way: | PR | Targets | Contents | | --- | --- | --- | -| [#15](https://github.com/PSModule/Toml/pull/15) | `main` | `build-toml-module` branch, the foundational `ConvertFrom-Toml`, `ConvertTo-Toml`, `Import-Toml`, `Export-Toml` release | -| [#20](https://github.com/PSModule/Toml/pull/20) | `build-toml-module` | `Format-Toml`, a follow-up feature added before the integration branch merged | +| #1 | `main` | `build-thing-module` branch, the foundational `ConvertFrom-Thing`, `ConvertTo-Thing`, `Import-Thing`, `Export-Thing` release | +| #2 | `build-thing-module` | `Format-Thing`, a follow-up feature added before the integration branch merged | ## When to use this From ea4a960c5f65fb9b5a1c4dd6b90d523220d2e3ee Mon Sep 17 00:00:00 2001 From: MariusStorhaug Date: Sun, 26 Jul 2026 10:23:55 +0200 Subject: [PATCH 4/6] docs: frame Module Bootstrap around the load-bearing core $Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../Process-PSModule/module-bootstrap.md | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/docs/Modules/Process-PSModule/module-bootstrap.md b/src/docs/Modules/Process-PSModule/module-bootstrap.md index d3710e3..0f8046e 100644 --- a/src/docs/Modules/Process-PSModule/module-bootstrap.md +++ b/src/docs/Modules/Process-PSModule/module-bootstrap.md @@ -1,24 +1,36 @@ # Module Bootstrap -A brand-new module often needs several interdependent functions before it is usable at all — for example a module might need `ConvertFrom-Thing`, `ConvertTo-Thing`, `Import-Thing`, and `Export-Thing` together before any of them is meaningful on its own. A single feature PR cannot carry that much scope and still be small and focused, so bootstrap uses one integration branch instead. +A brand-new module usually has a small **load-bearing core**: the piece(s) every other function will depend on, without which nothing else in the module can work at all. A single feature PR cannot carry that much scope and still be small and focused, so bootstrap uses one integration branch instead. + +## Identify the load-bearing core first + +What counts as "load-bearing" follows the module's archetype from [Module types](../Module-Types.md): + +- **Data modules** — the conversion pivot: `ConvertFrom-` / `ConvertTo-` (and whatever parser/serializer they wrap). Every other function (`Import-`, `Export-`, `Format-`, `Merge-`, ...) is built on top of this pivot and is meaningless without it. +- **Integration (API) modules** — a [`Context`](https://github.com/PSModule/Context)-backed credential/config store, the client setup that uses it, and at least one API function that consumes the context end to end. Every other API function needs the same context and client to do anything. + +Scope the integration branch to exactly that core, not to everything planned for v1. Keeping it to the minimum that "everyone needs" gets a usable release out faster, and lets independent follow-up functions be built in parallel — by different people or agents — as soon as the core is stable enough to build against, even before it merges. ## Pattern 1. Cut one long-lived branch from the default branch for the initial release, named for the outcome, e.g. `build-thing-module`. 2. Open one pull request per function (or small group of related functions) targeting that branch instead of `main`. These PRs can land in parallel — there is no strict order between them, unlike a [stacked pull request](https://msxorg.github.io/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests). -3. Once the foundational set of functions is coherent and complete, open the pull request that merges the integration branch into `main`. This becomes the module's first real release. +3. Once the load-bearing core is coherent and complete, open the pull request that merges the integration branch into `main`. This becomes the module's first real release (`v1.0.0`). 4. Smaller follow-up features (one more function, a formatter, an alias) can keep targeting the integration branch before it lands, the same way they targeted it during bootstrap. +## After the core lands + +Once the core has merged as `v1.0.0`, ordinary [SemVer](../Versioning.md) applies: a new function built on the stable core is a **minor** bump, a fix is a **patch** bump, and only a change to the core's own contract (signature, exported class shape, behavior) is a **major** bump. No special versioning exception is needed once the core is in place — the bootstrap phase exists only to get that core to a first release quickly. + ```mermaid gitGraph commit id: "main" branch build-thing-module checkout build-thing-module - commit id: "ConvertFrom-Thing" - commit id: "ConvertTo-Thing" - commit id: "Import-Thing / Export-Thing" + commit id: "load-bearing core" + commit id: "core, continued" checkout main - merge build-thing-module id: "first release" + merge build-thing-module id: "v1.0.0" ``` ## Example @@ -27,12 +39,12 @@ A module bootstrapped this way: | PR | Targets | Contents | | --- | --- | --- | -| #1 | `main` | `build-thing-module` branch, the foundational `ConvertFrom-Thing`, `ConvertTo-Thing`, `Import-Thing`, `Export-Thing` release | -| #2 | `build-thing-module` | `Format-Thing`, a follow-up feature added before the integration branch merged | +| #1 | `main` | `build-thing-module` branch, the load-bearing core (e.g. conversion pivot, or context + client + first API function) | +| #2 | `build-thing-module` | a follow-up function built on the core, added before the integration branch merged | ## When to use this -- The module has no usable release yet, and no single function is meaningful without the others. +- The module has no usable release yet, and the load-bearing core hasn't landed. - Use this only for the initial bootstrap. Once `main` has a first release, ongoing feature work targets `main` directly with ordinary topic branches, or a [stacked pull request](https://msxorg.github.io/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) when changes genuinely depend on each other. For the general branching and merge model, see [MSX Branching and Merging](https://msxorg.github.io/docs/Ways-of-Working/Branching-and-Merging/). From 08d668b6515d0f1381d0e4ee9daec667cd37746e Mon Sep 17 00:00:00 2001 From: MariusStorhaug Date: Sun, 26 Jul 2026 10:53:35 +0200 Subject: [PATCH 5/6] docs: fix natural-language lint (end-to-end, built-in wording) $Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/docs/Modules/Process-PSModule/module-bootstrap.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/docs/Modules/Process-PSModule/module-bootstrap.md b/src/docs/Modules/Process-PSModule/module-bootstrap.md index 0f8046e..0bb123e 100644 --- a/src/docs/Modules/Process-PSModule/module-bootstrap.md +++ b/src/docs/Modules/Process-PSModule/module-bootstrap.md @@ -7,9 +7,9 @@ A brand-new module usually has a small **load-bearing core**: the piece(s) every What counts as "load-bearing" follows the module's archetype from [Module types](../Module-Types.md): - **Data modules** — the conversion pivot: `ConvertFrom-` / `ConvertTo-` (and whatever parser/serializer they wrap). Every other function (`Import-`, `Export-`, `Format-`, `Merge-`, ...) is built on top of this pivot and is meaningless without it. -- **Integration (API) modules** — a [`Context`](https://github.com/PSModule/Context)-backed credential/config store, the client setup that uses it, and at least one API function that consumes the context end to end. Every other API function needs the same context and client to do anything. +- **Integration (API) modules** — a [`Context`](https://github.com/PSModule/Context)-backed credential/config store, the client setup that uses it, and at least one API function that consumes the context end-to-end. Every other API function needs the same context and client to do anything. -Scope the integration branch to exactly that core, not to everything planned for v1. Keeping it to the minimum that "everyone needs" gets a usable release out faster, and lets independent follow-up functions be built in parallel — by different people or agents — as soon as the core is stable enough to build against, even before it merges. +Scope the integration branch to exactly that core, not to everything planned for v1. Keeping it to the minimum that "everyone needs" gets a usable release out faster, and lets independent follow-up functions be developed in parallel — by different people or agents — as soon as the core is stable enough to build against, even before it merges. ## Pattern From 7209923ebd61f567450218abbd40e49db184edfc Mon Sep 17 00:00:00 2001 From: MariusStorhaug Date: Sun, 26 Jul 2026 11:04:32 +0200 Subject: [PATCH 6/6] docs: show parallel feature branches in bootstrap diagram $Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../Modules/Process-PSModule/module-bootstrap.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/docs/Modules/Process-PSModule/module-bootstrap.md b/src/docs/Modules/Process-PSModule/module-bootstrap.md index 0bb123e..143f793 100644 --- a/src/docs/Modules/Process-PSModule/module-bootstrap.md +++ b/src/docs/Modules/Process-PSModule/module-bootstrap.md @@ -28,11 +28,21 @@ gitGraph branch build-thing-module checkout build-thing-module commit id: "load-bearing core" - commit id: "core, continued" + branch function-a + branch function-b + checkout function-a + commit id: "PR: function A" + checkout function-b + commit id: "PR: function B" + checkout build-thing-module + merge function-a + merge function-b checkout main merge build-thing-module id: "v1.0.0" ``` +`function-a` and `function-b` are independent — both cut from `build-thing-module` and merged back in any order, unlike a stacked pull request where each layer depends on the one before it. + ## Example A module bootstrapped this way: