@msn-control/liftoff 0.6.2 → 0.8.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.
Files changed (111) hide show
  1. package/README.md +15 -1
  2. package/assets/governance/single-maintainer-gitflow/policy.md +705 -0
  3. package/assets/locks/frontend/package-lock.json +1012 -1694
  4. package/assets/locks/frontend/package.json +5 -6
  5. package/assets/locks/go-backend/go.mod +17 -0
  6. package/assets/locks/go-backend/go.sum +159 -0
  7. package/assets/locks/node-backend/package-lock.json +1473 -2320
  8. package/assets/locks/node-backend/package.json +8 -7
  9. package/assets/locks/opentofu-azure/.terraform.lock.hcl +39 -0
  10. package/assets/locks/opentofu-azure/versions.tf +10 -0
  11. package/assets/locks/python-genai/function-requirements.txt +1734 -0
  12. package/assets/locks/python-genai/liftoff_template_python_genai.egg-info/PKG-INFO +25 -0
  13. package/assets/locks/python-genai/liftoff_template_python_genai.egg-info/SOURCES.txt +6 -0
  14. package/assets/locks/python-genai/liftoff_template_python_genai.egg-info/dependency_links.txt +1 -0
  15. package/assets/locks/python-genai/liftoff_template_python_genai.egg-info/requires.txt +23 -0
  16. package/assets/locks/python-genai/liftoff_template_python_genai.egg-info/top_level.txt +1 -0
  17. package/assets/locks/python-genai/pyproject.toml +42 -0
  18. package/assets/locks/python-genai/uv.lock +2536 -0
  19. package/assets/locks/python-standard/pyproject.toml +36 -0
  20. package/assets/locks/python-standard/uv.lock +1780 -0
  21. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/catalog.json +4 -4
  22. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/package-lock.json +667 -1108
  23. package/assets/supported-stack.json +711 -0
  24. package/dist/args.js +26 -1
  25. package/dist/args.js.map +1 -1
  26. package/dist/catalogs.d.ts +3 -1
  27. package/dist/catalogs.js +29 -7
  28. package/dist/catalogs.js.map +1 -1
  29. package/dist/cli.js +2 -1
  30. package/dist/cli.js.map +1 -1
  31. package/dist/commands.d.ts +6 -0
  32. package/dist/commands.js +364 -172
  33. package/dist/commands.js.map +1 -1
  34. package/dist/container-validation.d.ts +2 -0
  35. package/dist/container-validation.js +26 -0
  36. package/dist/container-validation.js.map +1 -0
  37. package/dist/file-system.d.ts +1 -0
  38. package/dist/file-system.js +141 -7
  39. package/dist/file-system.js.map +1 -1
  40. package/dist/framework-adapters.js +1 -0
  41. package/dist/framework-adapters.js.map +1 -1
  42. package/dist/go-template-assets.d.ts +2 -0
  43. package/dist/go-template-assets.js +14 -0
  44. package/dist/go-template-assets.js.map +1 -0
  45. package/dist/init-filesystem.js +5 -4
  46. package/dist/init-filesystem.js.map +1 -1
  47. package/dist/interactive.d.ts +0 -5
  48. package/dist/interactive.js +11 -73
  49. package/dist/interactive.js.map +1 -1
  50. package/dist/opentofu-template-assets.d.ts +2 -0
  51. package/dist/opentofu-template-assets.js +10 -0
  52. package/dist/opentofu-template-assets.js.map +1 -0
  53. package/dist/package-identity.d.ts +8 -0
  54. package/dist/package-identity.js +16 -0
  55. package/dist/package-identity.js.map +1 -0
  56. package/dist/planner.js +42 -3
  57. package/dist/planner.js.map +1 -1
  58. package/dist/power-apps-templates.js +6 -0
  59. package/dist/power-apps-templates.js.map +1 -1
  60. package/dist/project-dependencies.d.ts +1 -1
  61. package/dist/project-dependencies.js +15 -34
  62. package/dist/project-dependencies.js.map +1 -1
  63. package/dist/published-verifier.js +11 -1
  64. package/dist/published-verifier.js.map +1 -1
  65. package/dist/python-template-assets.d.ts +4 -0
  66. package/dist/python-template-assets.js +34 -0
  67. package/dist/python-template-assets.js.map +1 -0
  68. package/dist/repository-governance.d.ts +17 -0
  69. package/dist/repository-governance.js +507 -0
  70. package/dist/repository-governance.js.map +1 -0
  71. package/dist/runtime.d.ts +1 -1
  72. package/dist/runtime.js +3 -1
  73. package/dist/runtime.js.map +1 -1
  74. package/dist/self-upgrade.d.ts +77 -0
  75. package/dist/self-upgrade.js +499 -0
  76. package/dist/self-upgrade.js.map +1 -0
  77. package/dist/stable-release.d.ts +18 -0
  78. package/dist/stable-release.js +66 -0
  79. package/dist/stable-release.js.map +1 -0
  80. package/dist/standard-templates.js +28 -97
  81. package/dist/standard-templates.js.map +1 -1
  82. package/dist/supported-stack.d.ts +115 -0
  83. package/dist/supported-stack.js +439 -0
  84. package/dist/supported-stack.js.map +1 -0
  85. package/dist/telemetry/contract.d.ts +1 -1
  86. package/dist/telemetry/contract.js +1 -0
  87. package/dist/telemetry/contract.js.map +1 -1
  88. package/dist/templates.js +216 -125
  89. package/dist/templates.js.map +1 -1
  90. package/dist/types.d.ts +18 -1
  91. package/dist/workstation-catalog.js +15 -12
  92. package/dist/workstation-catalog.js.map +1 -1
  93. package/dist/workstation.js +16 -6
  94. package/dist/workstation.js.map +1 -1
  95. package/docs/cli-reference.md +99 -22
  96. package/docs/configuration-and-manifests.md +14 -7
  97. package/docs/existing-repositories.md +27 -6
  98. package/docs/getting-started.md +23 -7
  99. package/docs/prerequisites.md +30 -4
  100. package/docs/project-structure.md +20 -1
  101. package/docs/repository-governance.md +91 -0
  102. package/docs/safety-and-consent.md +42 -17
  103. package/docs/spec-workflows-and-agents.md +22 -8
  104. package/docs/supported-stack.md +89 -0
  105. package/docs/telemetry.md +6 -0
  106. package/docs/troubleshooting.md +84 -8
  107. package/docs/workloads.md +18 -5
  108. package/package.json +14 -6
  109. package/dist/update-impact.d.ts +0 -23
  110. package/dist/update-impact.js +0 -127
  111. package/dist/update-impact.js.map +0 -1
@@ -5,6 +5,7 @@ Run `liftoff help` or command-specific help for the authoritative syntax:
5
5
  ```bash
6
6
  liftoff init --help
7
7
  liftoff migrate --help
8
+ liftoff upgrade --help
8
9
  liftoff update --help
9
10
  ```
10
11
 
@@ -14,7 +15,7 @@ duplicates, and extra positional arguments fail before generation.
14
15
  ## Lifecycle
15
16
 
16
17
  ```text
17
- plan -> init or migrate -> validate and doctor -> update -> dev and infra helpers
18
+ install -> upgrade CLI -> plan -> init or migrate -> validate and doctor -> update project -> dev and infra helpers
18
19
  ```
19
20
 
20
21
  | Command | Behavior |
@@ -24,8 +25,11 @@ plan -> init or migrate -> validate and doctor -> update -> dev and infra helper
24
25
  | `liftoff migrate <source>` | Creates a new sibling scaffold and filtered source copy without changing the source |
25
26
  | `liftoff validate [project]` | Validates manifest identity, durable files, workload metadata, and framework markers |
26
27
  | `liftoff doctor [project]` | Runs read-only workload-derived project and workstation diagnostics |
27
- | `liftoff update [project]` | Reports drift and, in an interactive terminal, explains impact and asks before applying |
28
- | `liftoff update --apply` | Applies safe changes, preserves unforced conflicts, and records the resulting manifest |
28
+ | `liftoff upgrade` | Replaces a verified global npm installation with the exact canonical stable release exposed by the configured registry |
29
+ | `liftoff upgrade --check` | Checks installation origin and registry parity without installing; exits 2 when an installable update exists |
30
+ | `liftoff update [project]` | Applies safe managed drift immediately, preserves unforced conflicts and orphans, and records the resulting manifest |
31
+ | `liftoff update --check` | Reports drift without preflight or mutation; exits 0 when clean and 2 when drift exists |
32
+ | `liftoff update --force` | Applies safe changes and overwrites only the exact guarded conflicts reported by update |
29
33
  | `liftoff dev` | Prints workload-appropriate local development commands; it does not execute them |
30
34
  | `liftoff infra` | Prints OpenTofu guidance for API workloads and reports infrastructure as not applicable for Power Apps |
31
35
  | `liftoff patterns` | Lists GenAI patterns |
@@ -37,6 +41,11 @@ plan -> init or migrate -> validate and doctor -> update -> dev and infra helper
37
41
  The former `liftoff create` command is intentionally rejected with guidance to
38
42
  use `liftoff init`; there is no compatibility alias.
39
43
 
44
+ Generation, validation, doctor, and update consume the packaged
45
+ [supported-stack baseline](supported-stack.md). The current contract uses
46
+ Node.js 24 LTS, Python 3.14, Go 1.27, OpenTofu 1.12, OpenSpec 1.11, and Spec Kit
47
+ 1.0 release lines; these commands never resolve mutable latest versions.
48
+
40
49
  ## Planning and initialization options
41
50
 
42
51
  Common noninteractive inputs include:
@@ -52,6 +61,7 @@ Common noninteractive inputs include:
52
61
  --spec openspec|spec-kit
53
62
  --agents copilot,claude
54
63
  --default-agent copilot|claude
64
+ --governance single-maintainer-gitflow|none
55
65
  --code-apps-plugin | --no-code-apps-plugin
56
66
  ```
57
67
 
@@ -59,35 +69,96 @@ Power Apps rejects API, pattern, cloud, region, frontend, and API environment
59
69
  options rather than ignoring them.
60
70
 
61
71
  Consent options are documented in [safety and consent](safety-and-consent.md).
72
+ Repository governance defaults to `single-maintainer-gitflow`. It generates a
73
+ local policy handoff only; `none` omits it. See
74
+ [repository governance](repository-governance.md).
75
+
76
+ ## CLI upgrade modes
77
+
78
+ ```bash
79
+ liftoff upgrade
80
+ liftoff upgrade --check
81
+ liftoff upgrade --json
82
+ liftoff upgrade --check --json
83
+ ```
84
+
85
+ `liftoff upgrade` is an imperative request to replace the supported global npm
86
+ installation of `@msn-control/liftoff`; it does not prompt or accept `--yes`,
87
+ `--force`, `--install-tools`, project paths, or project dependency flags.
88
+ Automatic replacement is refused for local dependencies, `npx` execution-cache
89
+ copies, linked checkouts, unknown package-manager stores, ambiguous roots, or
90
+ unsafe paths.
91
+
92
+ Canonical npm's stable `latest` metadata selects one exact target. The effective
93
+ configured npm registry remains the delivery path and must expose that exact
94
+ version. Liftoff never edits `.npmrc`, embeds registry credentials, forces a
95
+ canonical bypass around a stale mirror, invokes elevation, installs a
96
+ prerelease, or performs a downgrade.
97
+
98
+ `--check` performs the same origin, target, and parity checks without invoking
99
+ installation. Apply uses one shell-free exact npm command with lifecycle scripts,
100
+ audit, and funding prompts disabled, then verifies installed metadata, the
101
+ confined binary, and exact `Liftoff <version>` output. A failed install or
102
+ verification is not automatically rolled back; use the exact-version repair
103
+ command printed by Liftoff.
104
+
105
+ JSON results use schema version 1 and expose only `mode`, `status`,
106
+ `currentVersion`, applicable `targetVersion`, applicable `registryKind`, and a
107
+ stable `reasonCode`. Status is one of `current`, `update-available`, `upgraded`,
108
+ `blocked`, or `failed`. Child progress goes to stderr so stdout remains one JSON
109
+ object.
62
110
 
63
111
  ## Update modes
64
112
 
65
113
  ```bash
66
114
  liftoff update
115
+ liftoff update --force
67
116
  liftoff update --json
68
- liftoff update --apply
69
- liftoff update --apply --force
117
+ liftoff update --check
118
+ liftoff update --check --json
70
119
  ```
71
120
 
72
- With interactive input and output, plain `liftoff update` first reports drift
73
- and its impact. Safe managed changes use a default-No confirmation. Local or
74
- user-owned conflicts are listed separately and require another default-No
75
- confirmation before replacement. Liftoff collects both decisions before any
76
- preflight or write.
121
+ Plain `liftoff update` is imperative and prompt-free. It applies safe new,
122
+ missing, untouched-upgrade, clean-move, and recorded-state changes in
123
+ interactive terminals, redirected streams, and automation. Local or user-owned
124
+ conflicts are skipped and reported. Orphans are reported without deletion.
125
+ During legacy governance adoption, preserved unrecorded conflicts remain
126
+ outside manifest ownership and set local state to `handoff-partial` until a
127
+ later update can write or byte-identically adopt every required artifact.
77
128
 
78
- With redirected input or output, plain update remains a read-only check and
79
- prints the explicit apply command. `--json` also remains prompt-free and
80
- read-only unless combined with `--apply`. Explicit `--apply` and
81
- `--apply --force` bypass prompts for automation.
129
+ Use `--check` whenever no project bytes may change. Human check mode prints each
130
+ drift state and recommends plain update for safe changes or a reviewed
131
+ `--force` invocation for conflicts. `--check --force` is invalid because check
132
+ mode never authorizes writes.
82
133
 
83
- The impact summary identifies affected dependency definitions, but update does
84
- not install dependencies. Orphans are reported without deletion. Transaction
85
- snapshots restore a failed update, but Liftoff retains no backup after a
86
- successful overwrite; commit or copy local work first.
134
+ `--json` selects output format, not safety. `liftoff update --json` applies safe
135
+ changes and emits the versioned apply result. `liftoff update --check --json`
136
+ is the read-only automation gate.
137
+
138
+ Update never installs dependencies. Transaction snapshots restore a failed
139
+ update, but Liftoff retains no backup after a successful overwrite; commit or
140
+ copy local work before using `--force`. Force does not permit workload, API
141
+ stack, GenAI pattern, framework, selected-agent, or user-supplied Power Apps
142
+ starter identity changes, and it cannot bypass project-boundary, symlink,
143
+ structural-collision, or manifest guards.
144
+
145
+ For a breaking supported-stack release, inspect `liftoff update --check` before
146
+ plain update. Restore an unwanted applied migration through version control;
147
+ running an older CLI is not a supported automatic downgrade.
148
+
149
+ ### Migration from 0.6.x
150
+
151
+ The `--apply` flag was removed in 0.7.0. These are historical 0.6.x commands,
152
+ not current syntax:
153
+
154
+ | Historical 0.6.x command | 0.7.0 replacement |
155
+ | --- | --- |
156
+ | `liftoff update` when used as a read-only check | `liftoff update --check` |
157
+ | `liftoff update --apply` | `liftoff update` |
158
+ | `liftoff update --apply --force` | `liftoff update --force` |
87
159
 
88
- `--force` is valid only with `--apply`. It overwrites reported file conflicts;
89
- it does not permit workload, API stack, GenAI pattern, framework, selected
90
- agent, or user-supplied Power Apps starter identity changes.
160
+ Invoking removed syntax fails during argument parsing, before project discovery
161
+ or filesystem access.
91
162
 
92
163
  ## JSON and exit codes
93
164
 
@@ -96,16 +167,22 @@ Machine-readable maintenance contracts bypass decorative presentation:
96
167
  ```bash
97
168
  liftoff validate --json
98
169
  liftoff doctor --json
170
+ liftoff upgrade --json
171
+ liftoff upgrade --check --json
99
172
  liftoff update --json
173
+ liftoff update --check --json
100
174
  ```
101
175
 
102
176
  Each JSON object has a top-level numeric `schemaVersion`.
177
+ Operational warnings, such as a dirty-worktree warning before JSON apply, are
178
+ written to stderr so stdout remains one parseable JSON object.
103
179
 
104
180
  Exit codes:
105
181
 
106
182
  - `0`: success or a clean check.
107
183
  - `1`: invalid input, unsafe state, or command failure.
108
- - `2`: a read-only check or declined interactive update found drift.
184
+ - `2`: an explicit update check found project drift, or upgrade check found an
185
+ installable CLI release.
109
186
 
110
187
  Raw installer, framework, and dependency child stdout and stderr are forwarded
111
188
  unchanged.
@@ -24,6 +24,7 @@ A Power Apps configuration contains only applicable fields:
24
24
  "projectType": "power-apps-code-app",
25
25
  "specWorkflow": "openspec",
26
26
  "agents": ["github-copilot"],
27
+ "governanceProfile": "single-maintainer-gitflow",
27
28
  "codeAppsPlugin": false
28
29
  }
29
30
  ```
@@ -33,7 +34,7 @@ workload rather than silently ignored.
33
34
 
34
35
  ## `liftoff.manifest.json`: CLI-owned compatibility record
35
36
 
36
- New projects use manifest schema v4. Its common project identity includes the
37
+ New projects use manifest schema v5. Its common project identity includes the
37
38
  name, spec workflow, selected agents, and applicable Spec Kit default. A
38
39
  discriminated `project.workload` object contains only fields valid for one
39
40
  workload:
@@ -50,6 +51,8 @@ The manifest also records:
50
51
  - Durable artifact logical names.
51
52
  - OS-neutral path-part arrays.
52
53
  - `sha256:` content hashes.
54
+ - Repository governance profile, policy version, and local
55
+ `handoff-generated`, `handoff-partial`, or disabled state.
53
56
 
54
57
  Power Apps source identity uses explicit repository, path, and 40-character
55
58
  commit fields. It is not inferred from mutable URLs or generated file paths.
@@ -60,17 +63,21 @@ paths, or hashes.
60
63
 
61
64
  ## Compatibility
62
65
 
63
- Readers support schemas v2, v3, and v4:
66
+ Readers support schemas v2, v3, v4, and v5:
64
67
 
65
68
  - V2 normalizes the legacy flat API identity and records framework state as
66
69
  uncertain without inventing agents.
67
70
  - V3 normalizes flat GenAI or API identity plus framework and agent metadata.
68
71
  - V4 represents the discriminated workload model, including Power Apps.
72
+ - V5 adds repository-governance handoff identity without claiming live
73
+ enforcement.
69
74
 
70
- A non-interactive or JSON check, or a declined interactive update, leaves an
71
- old manifest byte-for-byte unchanged. A successful explicit or interactively
72
- accepted apply writes v4 only after the file transaction succeeds. Skipped
73
- conflicts retain their recorded hashes.
75
+ `liftoff update --check`, including `--check --json`, leaves an old manifest
76
+ byte-for-byte unchanged. A successful plain update writes v5 only after the
77
+ file transaction succeeds. Previously recorded skipped conflicts retain their
78
+ hashes. A preserved unrecorded governance conflict has no artifact entry and
79
+ sets the update-written manifest to `handoff-partial`; resolving every such
80
+ conflict promotes the next manifest to `handoff-generated`.
74
81
 
75
82
  ## Artifact ownership
76
83
 
@@ -89,7 +96,7 @@ can follow their own lifecycle.
89
96
 
90
97
  ## Contract conventions
91
98
 
92
- - Writers use `artifactVersion` 4; readers support v2, v3, and v4.
99
+ - Writers use `artifactVersion` 5; readers support v2, v3, v4, and v5.
93
100
  - Artifact logical names and catalog identifiers are append-only.
94
101
  - Rendering is deterministic and does not depend on timestamps, host versions,
95
102
  or network state.
@@ -64,15 +64,36 @@ Use:
64
64
 
65
65
  ```bash
66
66
  liftoff validate
67
+ liftoff update --check
67
68
  liftoff update
68
- liftoff update --apply
69
69
  ```
70
70
 
71
- In an interactive terminal, plain update reports drift and impact, then asks
72
- with a default of No before applying safe managed changes. Local or user-owned
73
- conflicts require a separate default-No overwrite decision. Redirected and
74
- JSON checks remain read-only and prompt-free; use `--apply` for explicit
75
- automation consent.
71
+ Use `--check` first when the invocation must be read-only. Plain update applies
72
+ safe managed changes immediately and without prompting in terminals and
73
+ automation, while preserving conflicts and orphans. Review every reported
74
+ conflict and commit or copy local work before choosing `liftoff update --force`.
75
+ For CI drift gates, use `liftoff update --check --json`.
76
+
77
+ Projects created before manifest schema v5 automatically preview the default
78
+ repository-governance handoff as new named drift. Plain update safely adopts
79
+ collision-free policy, context, guide, and selected-agent launchers without
80
+ rewriting a configuration that omitted `governanceProfile`. Existing different
81
+ files remain unowned conflicts and the v5 manifest records `handoff-partial`.
82
+ Resolving every conflict promotes a later update to `handoff-generated`.
83
+ Selecting `none` leaves previously managed handoff files as undeleted orphans
84
+ while unrecorded conflicts remain user-owned. No update mode runs an agent or
85
+ activates GitHub settings.
86
+
87
+ Major supported-stack releases can report many runtime, lock, Docker, provider,
88
+ and framework artifact changes at once. Treat those releases as breaking:
89
+ commit or copy local work, inspect `liftoff update --check`, and apply only after
90
+ reviewing all upgrades and conflicts. Plain update preserves conflicting local
91
+ bytes and never requires `--force` as the default migration path.
92
+
93
+ If an applied baseline migration must be reversed, restore the project and
94
+ manifest through version control and reinstall from the restored locks. Liftoff
95
+ does not automatically downgrade generated dependencies and retains no backup
96
+ after a successful update.
76
97
 
77
98
  ## Existing non-Liftoff application
78
99
 
@@ -5,8 +5,8 @@ standard APIs, and Power Apps code apps.
5
5
 
6
6
  ## 1. Install the CLI
7
7
 
8
- Liftoff requires Node.js 20.19 or newer. Power Apps code app projects require
9
- Node.js 22.12 or newer for their generated framework.
8
+ Liftoff and generated Node.js workloads require Node.js 24.20 or newer.
9
+ Python workloads use Python 3.14 with frozen `uv` dependency locks.
10
10
 
11
11
  The canonical release registry is `https://registry.npmjs.org`:
12
12
 
@@ -23,6 +23,18 @@ canonical npm. Stop if the mirror is older or rejects the explicit current
23
23
  version; ask the mirror owner to synchronize or approve the release. Liftoff
24
24
  does not modify `.npmrc` or bypass registry policy.
25
25
 
26
+ Versions predating the self-upgrade command require that manual global install
27
+ once. After a capable version is installed globally with npm, use:
28
+
29
+ ```bash
30
+ liftoff upgrade --check
31
+ liftoff upgrade
32
+ ```
33
+
34
+ `upgrade` replaces only the supported global CLI installation. It does not read
35
+ or update a generated project; inspect project template changes separately with
36
+ `liftoff update --check`.
37
+
26
38
  See [prerequisites](prerequisites.md) for the complete plan-derived tool model.
27
39
 
28
40
  ## 2. Start interactive initialization
@@ -37,16 +49,20 @@ The guided flow asks for:
37
49
 
38
50
  1. Project identity and workload: GenAI, API, or Power Apps code app.
39
51
  2. Only the architecture choices applicable to that workload.
40
- 3. OpenSpec or Spec Kit.
41
- 4. One or both coding agents. On a real TTY, Space toggles agents and Enter
52
+ 3. Whether to generate the default single-maintainer GitFlow repository-
53
+ governance handoff. Accepting it creates local files only.
54
+ 4. OpenSpec or Spec Kit.
55
+ 5. One or both coding agents. On a real TTY, Space toggles agents and Enter
42
56
  confirms the selection.
43
- 5. A Spec Kit default agent when both agents are selected.
44
- 6. The optional Preview Code Apps plugin preference for Power Apps projects.
45
- 7. Plan confirmation, workstation readiness, and any separate install or
57
+ 6. A Spec Kit default agent when both agents are selected.
58
+ 7. The optional Preview Code Apps plugin preference for Power Apps projects.
59
+ 8. Plan confirmation, workstation readiness, and any separate install or
46
60
  overwrite permissions that are needed.
47
61
 
48
62
  Liftoff renders into temporary staging, runs the official framework initializer
49
63
  there, validates the complete result, and only then merges it into the target.
64
+ Governance activation is a later selected-agent action after commit and push;
65
+ see [repository governance](repository-governance.md).
50
66
 
51
67
  ## 3. Understand the target
52
68
 
@@ -6,13 +6,21 @@ and a Go API is not asked to install Python.
6
6
 
7
7
  ## Baseline
8
8
 
9
- - Liftoff CLI: Node.js 20.19 or newer.
10
- - Power Apps code app: Node.js 22.12 or newer.
11
- - Selected framework: the Liftoff-tested OpenSpec or Spec Kit contract.
9
+ - Liftoff CLI and generated Node.js workloads: Node.js 24.20 or newer.
10
+ - Python projects: Python 3.14 and `uv` 0.12.7 or newer.
11
+ - Go projects: Go 1.27 or newer.
12
+ - Generated Azure infrastructure: OpenTofu 1.12.6 or newer.
13
+ - Selected framework: OpenSpec 1.11.0 or Spec Kit 1.0.1 exactly.
12
14
  - Selected agents: GitHub Copilot, Claude Code, or both.
13
15
 
16
+ Automatic `liftoff upgrade` additionally requires that the running canonical
17
+ `@msn-control/liftoff` package is a normal global npm installation beneath
18
+ `npm root --global`. Local dependencies, `npx` cache copies, linked checkouts,
19
+ and other package-manager stores use the documented manual global npm command
20
+ instead. Liftoff never requests elevation.
21
+
14
22
  API workloads additionally require their selected Python, Node.js, or Go
15
- runtime. GenAI uses Python 3.12 and the Python/FastAPI/PydanticAI stack.
23
+ runtime. GenAI uses Python 3.14 and the Python/FastAPI/PydanticAI stack.
16
24
 
17
25
  ## Blocking and advisory checks
18
26
 
@@ -32,6 +40,11 @@ Advisory checks describe useful but deferrable capabilities:
32
40
  Authentication checks are read-only. Liftoff never stores credentials or signs
33
41
  in to a cloud or agent on your behalf.
34
42
 
43
+ The default repository-governance handoff has no additional initialization
44
+ prerequisite. `gh`, a remote, licensed GitHub security features, private runners,
45
+ Slack, and deployment access are discovered only during post-push Phase 0 and
46
+ may be reported as gaps; they do not block local generation.
47
+
35
48
  ## Preview requirements without writes
36
49
 
37
50
  `liftoff plan` shows both generated artifacts and workstation requirements
@@ -76,6 +89,19 @@ the project is ready.
76
89
  GenAI and API projects use their generated stack-native locked dependency
77
90
  commands.
78
91
 
92
+ Python projects use the generated lock without resolving new versions:
93
+
94
+ ```bash
95
+ uv sync --frozen --project backend --extra test
96
+ ```
97
+
98
+ Worker-enabled GenAI projects add `--extra functions`. Node.js projects use
99
+ `npm ci`, and Go projects use `go mod download`.
100
+
101
+ Liftoff's npm locks are generated with npm 12.0.2 and verified in the supported
102
+ compatibility lanes. Do not replace a committed lock with an install from
103
+ open-ended manifest ranges.
104
+
79
105
  ## Power Apps local CLI
80
106
 
81
107
  The Power Apps CLI is supplied by the generated project dependency graph.
@@ -14,7 +14,13 @@ project/
14
14
  |-- .env.example
15
15
  |-- Dockerfile
16
16
  |-- docker-compose.yml
17
+ |-- .liftoff/
18
+ | `-- governance/ # durable local handoff when enabled
19
+ | |-- policy.md
20
+ | |-- context.json
21
+ | `-- README.md
17
22
  |-- backend/
23
+ | `-- uv.lock # Python stacks only
18
24
  |-- database/
19
25
  | |-- alembic.ini or stack-native migration config
20
26
  | |-- migrations/
@@ -26,7 +32,10 @@ project/
26
32
  |-- infrastructure/
27
33
  | `-- opentofu/
28
34
  | `-- azure/
35
+ | `-- .terraform.lock.hcl
29
36
  |-- openspec/ or .specify/
37
+ |-- .github/prompts/liftoff-repository-governance.prompt.md
38
+ | or .claude/commands/liftoff-repository-governance.md
30
39
  |-- frontend/ # only when selected
31
40
  |-- functions/<worker-name>/ # only for worker-enabled GenAI patterns
32
41
  `-- migration/legacy/ # only after liftoff migrate
@@ -45,7 +54,11 @@ project/
45
54
  Functions settings when a worker is generated.
46
55
  - `docker-compose.yml` starts the selected backend, PostgreSQL, Redis,
47
56
  Azurite, and Mailpit. GenAI projects use pgvector where needed and include an
48
- optional Langfuse profile.
57
+ optional Langfuse v4 web/worker profile backed by ClickHouse, dedicated Redis,
58
+ and MinIO.
59
+ - Python Docker builds export the committed `uv.lock` in frozen mode and install
60
+ only hash-verified requirements. `UV_DEFAULT_INDEX` can select a
61
+ credential-free managed mirror without changing the lock.
49
62
  - `infrastructure/opentofu/azure` contains modules, environment tfvars, local
50
63
  state configuration, and a remote-state example.
51
64
  - `openspec` is created for OpenSpec. `.specify` and `specs` are created for
@@ -87,6 +100,12 @@ project/
87
100
  `-- openspec/ or .specify/
88
101
  ```
89
102
 
103
+ The exact selected-agent governance launcher is generated only when the
104
+ repository-governance profile is enabled. It is Liftoff-owned; neighboring
105
+ framework files remain framework-owned. Agent-created governance changes and
106
+ `governance/activation-baseline.json` remain user-owned and are not listed in
107
+ the manifest.
108
+
90
109
  This root follows the pinned official Microsoft starter. It includes the
91
110
  Power Apps SDK, Vite plugin, and project-local CLI through locked npm
92
111
  dependencies.
@@ -0,0 +1,91 @@
1
+ # Repository governance handoff
2
+
3
+ Repository governance is a common Liftoff project choice. The default
4
+ `single-maintainer-gitflow` profile generates a deterministic local handoff;
5
+ `none` opts out:
6
+
7
+ **Local handoff generated; live enforcement is not active.**
8
+
9
+ ```bash
10
+ liftoff plan --governance single-maintainer-gitflow
11
+ liftoff init --governance none
12
+ ```
13
+
14
+ Accepting the default or passing `--yes` authorizes only local project files. It
15
+ does not run an agent, mutate Git, contact GitHub, configure security, install a
16
+ ruleset, deploy, or create monitoring.
17
+
18
+ ## Generated files
19
+
20
+ An enabled profile adds durable, hash-managed artifacts:
21
+
22
+ ```text
23
+ .liftoff/governance/policy.md
24
+ .liftoff/governance/context.json
25
+ .liftoff/governance/README.md
26
+ .github/prompts/liftoff-repository-governance.prompt.md # Copilot selected
27
+ .claude/commands/liftoff-repository-governance.md # Claude selected
28
+ ```
29
+
30
+ The complete canonical policy is also packaged with Liftoff at
31
+ [`assets/governance/single-maintainer-gitflow/policy.md`](../assets/governance/single-maintainer-gitflow/policy.md).
32
+ It covers GitFlow, zero-human-approval repository rules, designated security
33
+ tools, fail-closed checks, immutable release evidence, build-once promotion,
34
+ deployment and rollback, monitoring and health, DORA metrics, ruleset
35
+ sequencing, negative tests, documentation, and workload adaptation.
36
+
37
+ `context.json` contains generated project facts only. GitHub repository state,
38
+ runner access, licensed features, deployments, monitoring, alert routes,
39
+ traffic, and rollout capabilities remain `undiscovered`. Power Apps context
40
+ explicitly marks Liftoff backend, Docker, OpenTofu, custom container promotion,
41
+ and API DAST as inapplicable.
42
+
43
+ ## Activate after commit and push
44
+
45
+ 1. Review the policy and context.
46
+ 2. Commit the project and push it to the intended GitHub repository.
47
+ 3. Run `/liftoff-repository-governance` with a selected agent.
48
+ 4. The agent performs read-only Phase 0 and reports repository identity,
49
+ artifacts, working commands, refs, workflows and exact checks, rulesets,
50
+ releases, environments, security, runners, deployments, monitoring, alerts,
51
+ health depth, platform capabilities, gaps, and inapplicable controls.
52
+ 5. The agent proposes the current `main` SHA as the activation baseline,
53
+ presents an ordered plan, and stops.
54
+ 6. Explicitly approve or revise the conversational plan. This is not a human
55
+ merge or deployment approval gate.
56
+ 7. After approval, the agent creates a new OpenSpec or Spec Kit governance
57
+ change, proves required contexts green and deliberately red, applies
58
+ repository-scoped rulesets last, and reads live enforcement back.
59
+
60
+ The user-owned `governance/activation-baseline.json` is created only after
61
+ approval. Liftoff never owns or recreates it or the agent-created governance
62
+ change. Complete local handoffs say `handoff-generated`, partial adoptions say
63
+ `handoff-partial`, and neither state means `active`.
64
+
65
+ ## Existing projects
66
+
67
+ Configurations without `governanceProfile` normalize to the enabled default
68
+ without rewriting `liftoff.config.json`:
69
+
70
+ ```bash
71
+ liftoff update --check
72
+ liftoff update
73
+ ```
74
+
75
+ Check mode previews the schema-v5 manifest and new named artifacts without
76
+ writing. Plain update applies collision-free files; differing existing files
77
+ remain conflicts unless individually reviewed with `--force`. An unrecorded
78
+ conflict remains outside Liftoff ownership and produces `handoff-partial`.
79
+ After every conflict is removed or matches the current artifact, the next
80
+ update records the full artifact set as `handoff-generated`.
81
+
82
+ Setting `"governanceProfile": "none"` stops future rendering. Previously managed
83
+ handoff files are reported once as orphans and left on disk; Liftoff never
84
+ deletes them automatically or changes live repository settings.
85
+
86
+ ## Capability gaps
87
+
88
+ Phase 0 must report missing GitHub licenses, private runners, staging access,
89
+ monitoring routes, parallel-version mechanisms, or statistically meaningful
90
+ canary traffic. It must mark controls inapplicable or blocked rather than
91
+ creating a skipped, hanging, duplicate, or success-shaped placeholder.
@@ -8,12 +8,35 @@ project dependencies. No one permission implies another.
8
8
  | Flag | Authorizes | Does not authorize |
9
9
  | --- | --- | --- |
10
10
  | `--yes` | Project defaults and plan confirmation | File replacement, machine installs, or project dependencies |
11
- | `--force` | Only listed and validated regular-file replacements | Manifest guards, symlinks, structural collisions, tools, dependencies, or non-empty migration targets |
11
+ | `--force` | During init, listed regular-file replacements; during update, exact reported conflicts | Manifest guards, symlinks, structural collisions, tools, dependencies, or non-empty migration targets |
12
12
  | `--install-tools` | Allowlisted workstation installation commands | Project decisions, overwrites, or project dependencies |
13
13
  | `--install-dependencies` | Locked project-local dependency commands after a successful merge | Machine tools, project decisions, or overwrites |
14
14
 
15
15
  Interactive sessions ask separately at the point each permission is needed.
16
16
 
17
+ Selecting repository governance or passing `--yes` authorizes only deterministic
18
+ local handoff files. It never authorizes agent execution, Git mutation, GitHub
19
+ APIs, rulesets, security configuration, deployment, monitoring, file
20
+ replacement, machine tools, or project dependencies. Live activation begins
21
+ only after commit, push, read-only Phase 0, and explicit plan approval.
22
+
23
+ ## CLI self-upgrade boundary
24
+
25
+ `liftoff upgrade` is itself the narrow authorization to replace a supported
26
+ global npm installation with one exact stable version. It accepts no project
27
+ path, `--yes`, `--force`, tool-install, or dependency-install permission.
28
+ `liftoff upgrade --check` is read-only and invokes no npm installation.
29
+
30
+ Both modes operate from a temporary neutral directory so a project `.npmrc`
31
+ cannot redirect machine-level discovery. Canonical npm selects the target while
32
+ the configured registry must provide that exact release. Liftoff does not expose
33
+ registry credentials, rewrite npm configuration, bypass a stale mirror, invoke
34
+ `sudo` or another elevation mechanism, or touch project files.
35
+
36
+ npm replacement is not a Liftoff file transaction. If npm or post-install
37
+ verification fails, Liftoff reports an exact-version repair command and does not
38
+ claim automatic rollback.
39
+
17
40
  ## Staged initialization
18
41
 
19
42
  Initialization does not write generated files directly into the destination.
@@ -50,11 +73,10 @@ Individual project files use temporary-file replacement. Initialization keeps
50
73
  backups for replaced files and records created files and directories. A handled
51
74
  merge failure restores or removes those entries in reverse order.
52
75
 
53
- An accepted interactive update or `liftoff update --apply` preflights all
54
- affected paths and applies generated file, move, delete, and manifest mutations
55
- as one rollback-capable transaction. Schema upgrades are committed only after
56
- the other mutations succeed. A corrected retry converges from the restored
57
- state.
76
+ Plain `liftoff update` preflights all affected paths and applies generated file,
77
+ move, delete, and manifest mutations as one rollback-capable transaction.
78
+ Schema upgrades are committed only after the other mutations succeed. A
79
+ corrected retry converges from the restored state.
58
80
 
59
81
  If automatic rollback itself cannot safely restore a path because another
60
82
  process changed it, Liftoff reports the incomplete rollback rather than
@@ -65,24 +87,27 @@ does not retain them as backups after success.
65
87
 
66
88
  ## Update ownership
67
89
 
68
- Plain `liftoff update` always reports drift before any write:
90
+ Update mode is selected explicitly rather than from terminal interactivity:
69
91
 
70
92
  - Clean generated files remain unchanged.
71
- - In an interactive terminal, new, missing, untouched-upgrade, clean-move, and
72
- recorded-state changes are summarized and offered through a default-No
73
- confirmation.
74
- - With redirected input or output, or with `--json`, update remains a
75
- prompt-free read-only check unless `--apply` is explicitly supplied.
93
+ - Plain `liftoff update` immediately applies safe new, missing,
94
+ untouched-upgrade, clean-move, and recorded-state changes without prompting,
95
+ including with redirected input or output.
96
+ - `liftoff update --check` is read-only and performs no preflight or mutation.
97
+ - `liftoff update --json` applies safe changes and returns an apply result;
98
+ `liftoff update --check --json` is the read-only machine drift gate.
76
99
  - Developer edits that also differ from the current template are conflicts.
77
- - Safe-update consent does not authorize conflicts. Interactive conflicts are
78
- listed by portable relative path and require a separate default-No overwrite
79
- confirmation; automation uses `--apply --force`.
100
+ - Default update skips conflicts and lists them by portable relative path.
101
+ After reviewing every listed overwrite, `liftoff update --force` extends the
102
+ transaction only to those guarded conflicts.
103
+ - Unrecorded governance conflicts remain outside manifest ownership and produce
104
+ `handoff-partial` until a later update safely writes or adopts every artifact.
80
105
  - Orphans are reported and left on disk for manual review.
81
106
  - Dependency definitions may be updated, but update never installs
82
107
  dependencies.
83
108
 
84
- All interactive decisions are collected before preflight or mutation.
85
- Declining the safe update changes nothing and leaves drift exit code 2.
109
+ `--force` cannot be combined with `--check` and cannot weaken project-boundary,
110
+ symlink, collision, manifest, or transaction guards.
86
111
 
87
112
  Power Apps reconciliation reads only the packaged immutable starter. It does
88
113
  not fetch the upstream repository. Workload kind and user-edited starter