@msn-control/liftoff 0.9.8 → 0.10.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 (107) hide show
  1. package/DEVELOPER.md +142 -0
  2. package/README.md +26 -18
  3. package/assets/governance/single-maintainer-gitflow/policy.md +62 -13
  4. package/dist/args.js +21 -0
  5. package/dist/args.js.map +1 -1
  6. package/dist/artifact-lifecycle.d.ts +1 -1
  7. package/dist/artifact-lifecycle.js +5 -0
  8. package/dist/artifact-lifecycle.js.map +1 -1
  9. package/dist/commands.js +355 -13
  10. package/dist/commands.js.map +1 -1
  11. package/dist/file-system.js +100 -13
  12. package/dist/file-system.js.map +1 -1
  13. package/dist/governance-activation/activation-state.d.ts +32 -0
  14. package/dist/governance-activation/activation-state.js +165 -0
  15. package/dist/governance-activation/activation-state.js.map +1 -0
  16. package/dist/governance-activation/approvals.d.ts +188 -0
  17. package/dist/governance-activation/approvals.js +508 -0
  18. package/dist/governance-activation/approvals.js.map +1 -0
  19. package/dist/governance-activation/canonical-json.d.ts +3 -0
  20. package/dist/governance-activation/canonical-json.js +36 -0
  21. package/dist/governance-activation/canonical-json.js.map +1 -0
  22. package/dist/governance-activation/commands.d.ts +10 -0
  23. package/dist/governance-activation/commands.js +1023 -0
  24. package/dist/governance-activation/commands.js.map +1 -0
  25. package/dist/governance-activation/compatibility.d.ts +68 -0
  26. package/dist/governance-activation/compatibility.js +447 -0
  27. package/dist/governance-activation/compatibility.js.map +1 -0
  28. package/dist/governance-activation/credentials.d.ts +160 -0
  29. package/dist/governance-activation/credentials.js +403 -0
  30. package/dist/governance-activation/credentials.js.map +1 -0
  31. package/dist/governance-activation/doctor.d.ts +10 -0
  32. package/dist/governance-activation/doctor.js +379 -0
  33. package/dist/governance-activation/doctor.js.map +1 -0
  34. package/dist/governance-activation/evidence.d.ts +49 -0
  35. package/dist/governance-activation/evidence.js +246 -0
  36. package/dist/governance-activation/evidence.js.map +1 -0
  37. package/dist/governance-activation/graph.d.ts +397 -0
  38. package/dist/governance-activation/graph.js +441 -0
  39. package/dist/governance-activation/graph.js.map +1 -0
  40. package/dist/governance-activation/identity.d.ts +35 -0
  41. package/dist/governance-activation/identity.js +89 -0
  42. package/dist/governance-activation/identity.js.map +1 -0
  43. package/dist/governance-activation/index.d.ts +18 -0
  44. package/dist/governance-activation/index.js +19 -0
  45. package/dist/governance-activation/index.js.map +1 -0
  46. package/dist/governance-activation/migration.d.ts +44 -0
  47. package/dist/governance-activation/migration.js +268 -0
  48. package/dist/governance-activation/migration.js.map +1 -0
  49. package/dist/governance-activation/readiness.d.ts +23 -0
  50. package/dist/governance-activation/readiness.js +158 -0
  51. package/dist/governance-activation/readiness.js.map +1 -0
  52. package/dist/governance-activation/reconciliation.d.ts +11 -0
  53. package/dist/governance-activation/reconciliation.js +58 -0
  54. package/dist/governance-activation/reconciliation.js.map +1 -0
  55. package/dist/governance-activation/release-integrity.d.ts +11 -0
  56. package/dist/governance-activation/release-integrity.js +49 -0
  57. package/dist/governance-activation/release-integrity.js.map +1 -0
  58. package/dist/governance-activation/seed-lifecycle.d.ts +116 -0
  59. package/dist/governance-activation/seed-lifecycle.js +609 -0
  60. package/dist/governance-activation/seed-lifecycle.js.map +1 -0
  61. package/dist/governance-activation/source-of-truth.d.ts +164 -0
  62. package/dist/governance-activation/source-of-truth.js +986 -0
  63. package/dist/governance-activation/source-of-truth.js.map +1 -0
  64. package/dist/governance-activation/task-projection.d.ts +21 -0
  65. package/dist/governance-activation/task-projection.js +75 -0
  66. package/dist/governance-activation/task-projection.js.map +1 -0
  67. package/dist/governance-activation/transitions.d.ts +163 -0
  68. package/dist/governance-activation/transitions.js +2128 -0
  69. package/dist/governance-activation/transitions.js.map +1 -0
  70. package/dist/governance-activation/type-contract.d.ts +1 -0
  71. package/dist/governance-activation/type-contract.js +27 -0
  72. package/dist/governance-activation/type-contract.js.map +1 -0
  73. package/dist/governance-activation/types.d.ts +390 -0
  74. package/dist/governance-activation/types.js +108 -0
  75. package/dist/governance-activation/types.js.map +1 -0
  76. package/dist/governance-activation/validators.d.ts +17 -0
  77. package/dist/governance-activation/validators.js +1305 -0
  78. package/dist/governance-activation/validators.js.map +1 -0
  79. package/dist/init-filesystem.js +5 -1
  80. package/dist/init-filesystem.js.map +1 -1
  81. package/dist/planner.js +3 -3
  82. package/dist/planner.js.map +1 -1
  83. package/dist/power-apps-templates.js +14 -1
  84. package/dist/power-apps-templates.js.map +1 -1
  85. package/dist/process-runner.d.ts +3 -0
  86. package/dist/process-runner.js +68 -10
  87. package/dist/process-runner.js.map +1 -1
  88. package/dist/repository-governance.d.ts +13 -3
  89. package/dist/repository-governance.js +385 -52
  90. package/dist/repository-governance.js.map +1 -1
  91. package/dist/telemetry/contract.d.ts +1 -1
  92. package/dist/telemetry/contract.js +6 -0
  93. package/dist/telemetry/contract.js.map +1 -1
  94. package/dist/templates.js +320 -25
  95. package/dist/templates.js.map +1 -1
  96. package/dist/types.d.ts +14 -6
  97. package/docs/cli-reference.md +60 -12
  98. package/docs/configuration-and-manifests.md +40 -16
  99. package/docs/existing-repositories.md +22 -11
  100. package/docs/getting-started.md +46 -10
  101. package/docs/prerequisites.md +5 -0
  102. package/docs/project-structure.md +34 -5
  103. package/docs/repository-governance.md +200 -203
  104. package/docs/safety-and-consent.md +29 -2
  105. package/docs/troubleshooting.md +74 -4
  106. package/docs/workloads.md +1 -1
  107. package/package.json +2 -1
@@ -38,12 +38,14 @@ a reviewed project change.
38
38
 
39
39
  See [prerequisites](prerequisites.md) for the complete plan-derived tool model.
40
40
 
41
- ## 2. Start interactive initialization
41
+ ## 2. Start the primary path
42
42
 
43
43
  From the directory that should contain the project, run:
44
44
 
45
- ```bash
46
- liftoff init
45
+ ```text
46
+ liftoff init my-project
47
+ cd my-project
48
+ /liftoff-setup
47
49
  ```
48
50
 
49
51
  The guided flow asks for:
@@ -69,8 +71,15 @@ there, validates the complete result, and only then merges it into the target.
69
71
  OpenSpec projects use all 12 OpenSpec 1.11 workflows as both skills and commands.
70
72
  If the global OpenSpec profile differs, Liftoff displays the exact global change
71
73
  and asks separately before staging.
72
- Governance activation is a later selected-agent action after commit and push;
73
- see [repository governance](repository-governance.md).
74
+
75
+ When governance is enabled, `/liftoff-setup` is the next selected-agent action.
76
+ It has no model-selection requirement: safety comes from the Liftoff CLI phase
77
+ graph, local evidence, approval envelopes, and readback. Setup first completes,
78
+ syncs, and archives the generated `bootstrap-<project>` seed. Only then does it
79
+ reach explicit authority gates for repository commit/push, credentials, billed
80
+ infrastructure or policy exceptions, final enforcement, destructive cleanup, and
81
+ external blockers. Commit and push are never implicit in `liftoff init`, `--yes`,
82
+ or read-only checks.
74
83
 
75
84
  For deterministic generic generation, use `--type genai --pattern generic`.
76
85
 
@@ -86,26 +95,53 @@ a project name creates a named child directory.
86
95
  Read [existing repositories](existing-repositories.md) before initializing a
87
96
  non-empty target.
88
97
 
89
- ## 4. Validate the result
98
+ ## 4. Local baseline setup verifies
99
+
100
+ `/liftoff-setup` runs only local, project-applicable baseline checks before it
101
+ archives the seed:
102
+
103
+ ```bash
104
+ liftoff validate
105
+ # backend tests from the generated README when a backend exists
106
+ # frontend build from the generated README when a frontend exists
107
+ docker compose config -q
108
+ tofu fmt -check -recursive
109
+ tofu init -backend=false
110
+ tofu validate
111
+ openspec validate --strict
112
+ ```
113
+
114
+ Absent components are inapplicable: a Power Apps project does not fabricate
115
+ backend, Docker, or OpenTofu success, and an API project without a frontend skips
116
+ frontend build evidence. The baseline does not run `tofu plan`, `tofu apply`,
117
+ start containers, deploy, mutate GitHub, or require cloud credentials. If a check
118
+ fails, the seed remains active and `/liftoff-setup` resumes idempotently after
119
+ you fix the blocker; verified phases are not repeated.
90
120
 
91
- Run maintenance commands from the generated project root:
121
+ You can run read-only maintenance at any time:
92
122
 
93
123
  ```bash
94
124
  liftoff validate
95
125
  liftoff doctor
126
+ liftoff governance status --json
127
+ liftoff governance plan --json
128
+ liftoff governance verify --json
96
129
  ```
97
130
 
98
131
  `validate` checks durable generated artifacts and framework markers. `doctor`
99
- adds read-only workstation, runtime, authentication, dependency, and
100
- workload-specific diagnostics.
132
+ adds read-only workstation, runtime, authentication, dependency,
133
+ workload-specific, and governance-state diagnostics.
101
134
 
102
- Next steps depend on the selected workload:
135
+ After setup archives the seed and you explicitly approve repository publication,
136
+ normal development follows your selected workflow:
103
137
 
104
138
  - GenAI and API projects: copy `.env.example` to `.env`, install the generated
105
139
  stack dependencies, then use `liftoff dev` and `liftoff infra` to print local
106
140
  development and infrastructure commands.
107
141
  - Power Apps projects: run `npm ci`, then `npm run dev`. Environment binding,
108
142
  connector addition, and `power-apps push` are deliberately deferred.
143
+ - OpenSpec or Spec Kit changes drive normal feature work; release and hotfix
144
+ flows follow the governed GitFlow plan after activation evidence is green.
109
145
 
110
146
  See [workloads](workloads.md) for exact generated outputs and deferred actions.
111
147
 
@@ -52,6 +52,11 @@ discovers an existing private management path or proposes the policy's bounded
52
52
  encrypted local-state bootstrap. Liftoff itself neither creates nor transfers
53
53
  state.
54
54
 
55
+ Azure governance plans also inspect the AzureRM provider-registration mode,
56
+ derive the minimal required namespace set, and verify subscription registration
57
+ permission. Disabled auto-registration is not a blocker when the approved plan
58
+ can register each missing namespace explicitly before dependent resources.
59
+
55
60
  ## Preview requirements without writes
56
61
 
57
62
  `liftoff plan` shows both generated artifacts and workstation requirements
@@ -23,7 +23,15 @@ project/
23
23
  | `-- governance/ # managed-core local handoff when enabled
24
24
  | |-- policy.md
25
25
  | |-- context.json
26
- | `-- README.md
26
+ | |-- README.md
27
+ | |-- phase-graph.json
28
+ | |-- compatibility.json
29
+ | `-- credential-policy.schema.json
30
+ |-- governance/ # user-owned activation state after setup starts
31
+ | |-- activation-state.json
32
+ | |-- approvals/
33
+ | |-- evidence/
34
+ | `-- credentials/
27
35
  |-- backend/
28
36
  | `-- uv.lock # Python stacks only
29
37
  |-- database/
@@ -43,8 +51,10 @@ project/
43
51
  |-- .claude/skills/openspec-*/ and .claude/commands/opsx/ # OpenSpec + Claude
44
52
  |-- .github/workflows/copilot-setup-steps.yml # optional hosted agent
45
53
  |-- .github/agents/openspec.agent.md # optional hosted agent
46
- |-- .github/prompts/liftoff-repository-governance.prompt.md
47
- | or .claude/commands/liftoff-repository-governance.md
54
+ |-- .github/prompts/liftoff-setup.prompt.md
55
+ |-- .github/prompts/liftoff-repository-governance.prompt.md # compatibility alias
56
+ | or .claude/commands/liftoff-setup.md
57
+ | and .claude/commands/liftoff-repository-governance.md
48
58
  |-- frontend/ # only when selected
49
59
  |-- functions/<worker-name>/ # only for worker-enabled GenAI patterns
50
60
  `-- migration/legacy/ # only after liftoff migrate
@@ -77,6 +87,10 @@ project/
77
87
  - OpenSpec projects receive all 12 pinned workflows as both skills and commands
78
88
  for supported selected-agent surfaces. The two hosted Copilot agent files are
79
89
  generated only after explicit opt-in.
90
+ - `/liftoff-setup` is generated when repository governance is enabled. It calls
91
+ `liftoff governance status|plan|apply-next|resume|verify` and has no model
92
+ selection or separate setup-skill version. `/liftoff-repository-governance` is
93
+ a compatibility alias for the same state.
80
94
 
81
95
  ### Conditional areas
82
96
 
@@ -111,14 +125,16 @@ project/
111
125
  | |-- hooks/
112
126
  | |-- pages/
113
127
  | `-- providers/
128
+ |-- .liftoff/governance/ # managed-core setup files when enabled
129
+ |-- governance/ # user-owned activation state after setup starts
114
130
  `-- openspec/ or .specify/
115
131
  ```
116
132
 
117
133
  The exact selected-agent governance launcher is generated only when the
118
134
  repository-governance profile is enabled. It is Liftoff-owned; neighboring
119
135
  framework files remain framework-owned. Agent-created governance changes and
120
- `governance/activation-baseline.json` remain user-owned and are not listed in
121
- the manifest.
136
+ `governance/activation-state.json`, approvals, evidence, credentials, and
137
+ supersession records remain user-owned and are not listed as managed artifacts.
122
138
 
123
139
  This root follows the pinned official Microsoft starter. It includes the
124
140
  Power Apps SDK, Vite plugin, and project-local CLI through locked npm
@@ -128,6 +144,19 @@ Liftoff intentionally does not generate `backend/`, `database/`,
128
144
  `docker-compose.yml`, `environments/`, `infrastructure/`, or
129
145
  `power.config.json` for this workload.
130
146
 
147
+ ## Managed versus user-owned governance artifacts
148
+
149
+ `liftoff.manifest.json` v7 records managed-core hashes for the governance policy,
150
+ context, guide, phase graph, compatibility metadata, credential-policy schema,
151
+ setup integrations, and compatibility aliases. `liftoff update` may reconcile
152
+ only those managed-core paths. It preserves user-owned activation state,
153
+ immutable evidence, approvals, credential policies, active OpenSpec changes, and
154
+ project source.
155
+
156
+ Manifest paths are stored as path-part arrays and validated on Windows, macOS,
157
+ and Linux. Generated setup content is identified by managed content hashes; the
158
+ activation version vector and graph hash describe the behavior contract.
159
+
131
160
  ## GenAI integration configuration
132
161
 
133
162
  Generated GenAI projects expose real configuration boundaries instead of
@@ -1,227 +1,224 @@
1
- # Repository governance handoff
1
+ # Repository governance and deterministic setup
2
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:
3
+ Repository governance is enabled by default through the
4
+ `single-maintainer-gitflow` profile; `--governance none` opts out. Initialization
5
+ writes local managed-core artifacts only. It does not run an agent, mutate Git,
6
+ contact GitHub or Azure, configure rulesets, provision runners, deploy, or start
7
+ monitoring.
6
8
 
7
- **Local handoff generated; live enforcement is not active.**
9
+ Primary path after initialization:
8
10
 
9
- ```bash
10
- liftoff plan --governance single-maintainer-gitflow
11
- liftoff init --governance none
11
+ ```text
12
+ liftoff init my-project
13
+ cd my-project
14
+ /liftoff-setup
12
15
  ```
13
16
 
14
- Accepting the default or passing `--yes` authorizes only local project files. It
15
- does not run an agent, mutate Git, contact GitHub or Azure, configure security,
16
- install a ruleset, deploy, provision a runner, or create monitoring.
17
+ `/liftoff-setup` completes the generated bootstrap seed, then enters the
18
+ deterministic Liftoff governance engine and its read-only Phase 0 discovery. The older
19
+ `/liftoff-repository-governance` launcher is a compatibility alias for the same
20
+ engine and user-owned activation state; it is not a separate activation path.
17
21
 
18
- ## Generated files
22
+ ## Managed files and user-owned state
19
23
 
20
- An enabled profile adds durable, hash-managed artifacts:
24
+ Enabled governance adds managed-core files:
21
25
 
22
26
  ```text
23
27
  .liftoff/governance/policy.md
24
28
  .liftoff/governance/context.json
25
29
  .liftoff/governance/README.md
26
- .github/prompts/liftoff-repository-governance.prompt.md # Copilot selected
27
- .claude/commands/liftoff-repository-governance.md # Claude selected
30
+ .liftoff/governance/phase-graph.json
31
+ .liftoff/governance/compatibility.json
32
+ .liftoff/governance/credential-policy.schema.json
33
+ .github/prompts/liftoff-setup.prompt.md # Copilot selected
34
+ .github/prompts/liftoff-repository-governance.prompt.md # compatibility alias
35
+ .claude/commands/liftoff-setup.md # Claude selected
36
+ .claude/commands/liftoff-repository-governance.md # compatibility alias
28
37
  ```
29
38
 
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
- Policy version 4 also fixes platform decisions that generated projects should
38
- not repeatedly ask users to make:
39
-
40
- - Dev storage uses LRS; Staging and Production use ZRS. IaC state uses ZRS in
41
- every environment.
42
- - Database HA is off in Dev and Staging and zone-redundant in Production.
43
- - CI uses one user-assigned managed identity with OIDC federation per repository
44
- and environment, without app registrations or long-lived credentials.
45
- - The default workload is small and cost-optimised with production safeguards.
46
- Runtimes remain on Active LTS majors, with grouped dependency updates and
47
- non-LTS major updates ignored.
48
- - Slack webhooks are required environment-level GitHub Actions secrets so the
49
- alert path does not depend on private-vault connectivity.
50
- - Encrypted local bootstrap state is retained read-only for 30 days after
51
- verified remote import, then securely deleted with dated evidence.
52
-
53
- These are applicable defaults, not reasons to create unused resources. A
54
- managed service is included only when application code consumes it, after its
55
- cost and known service limits are stated. When live infrastructure differs from
56
- IaC, activation planning adapts the IaC and imports the live resource rather
57
- than creating a parallel stack or forcing replacement.
58
-
59
- ## Private Staging qualification
60
-
61
- DAST for a privately networked Staging environment uses an ephemeral
62
- GitHub-hosted larger runner with Azure VNet injection. Activation reuses a
63
- suitable existing repository assignment. If none exists, policy version 4
64
- permits one narrow post-approval exception to provision the Azure network
65
- setting, organisation hosted-compute network configuration, selected-access
66
- runner group, and bounded larger runner required by that repository.
67
-
68
- Phase 0 first proves that private Staging DAST applies. It then discovers the
69
- repository's Staging subscription and tenant, existing runner resources, Azure
70
- and GitHub write authority, enterprise network policy, billing, state, names,
71
- address space, DNS, routing, costs, limits, and teardown ownership. Missing
72
- authority or an unresolved input blocks provisioning without partial mutation.
73
- No self-hosted runner is substituted.
74
-
75
- Every Azure runner-network resource, its state, egress cost, and teardown owner
76
- remain inside the repository's Staging subscription. The design cannot share a
77
- firewall, hub, route, state, or lifecycle with another repository or
78
- subscription. GitHub resources exist at organisation level but grant selected
79
- access only to the target repository and required workflows.
80
-
81
- The delegated runner subnet disables implicit default outbound access, denies
82
- unsolicited inbound connectivity, and uses exactly one egress mode:
83
-
84
- - Azure Firewall Basic only when an applicable policy requires domain-restricted
85
- egress. Its HTTPS rules use a current GitHub meta domain set without the
86
- retired static-IP template or TLS interception.
87
- - Azure NAT Gateway otherwise, with required protocols constrained by an NSG.
88
- NAT and NSG controls do not filter HTTPS by domain.
89
-
90
- NAT Gateway cannot be attached to a firewall-routed runner subnet because it
91
- takes precedence and would bypass the firewall. The approved topology must also
92
- prove non-overlapping address space, same-subscription routing or peering,
93
- private DNS, security rules, and live private Staging reachability.
94
-
95
- A standard hosted preflight verifies the assignment and labels before scheduling
96
- DAST. Azure and GitHub resources, associations, egress, DNS, and reachability
97
- must all be read back successfully. Missing or partial evidence blocks
98
- qualification rather than leaving a required job queued or reporting success.
99
- Teardown reverses those dependencies and removes the Azure network only after
100
- GitHub scheduling, assignment, and service associations are gone.
101
-
102
- ### Private state bootstrap and retention
103
-
104
- Phase 0 prefers an existing approved private execution path to the
105
- repository-owned ZRS backend. When public access is disabled and no such path
106
- exists, an approved governance change may use encrypted local OpenTofu state for
107
- only the minimum networking, private endpoint, DNS, network setting, and
108
- restricted runner resources needed to establish access. This
109
- `bootstrap-local` phase is not remote-ready and cannot authorize application
110
- provisioning.
111
-
112
- The local state remains gitignored, single-writer, encrypted on the approved
113
- workstation, and is never transferred through GitHub artifacts, repository
114
- secrets, or ordinary messages. From the exact private runner, reviewed import
115
- declarations adopt the resources into an empty ZRS backend without copying the
116
- local state file.
117
-
118
- Remote import is complete only after private Blob access, exact live-to-state
119
- resource identity, state locking, Blob versioning, and a clean-checkout
120
- no-change plan are verified. Failure starts no retention clock and keeps normal
121
- provisioning blocked.
122
-
123
- At successful verification, the local state becomes evidence-only and read-only
124
- for exactly 30 days. It cannot run plan or apply. At expiry, its encryption key
125
- and encrypted files are removed, along with every approved temporary copy. A
126
- dated record captures the state identity or checksum, verification evidence,
127
- scheduled and actual deletion, operator, method, and outcome without containing
128
- state data or secrets.
129
-
130
- ## Release identity and automated completion
131
-
132
- Staging qualifies the release or hotfix candidate commit and binds it to the
133
- version, artifact digest, and evidence-bundle digest. A later true merge into
134
- `main` necessarily has a different SHA. Production verifies that the merge
135
- incorporates the exact qualified candidate, promotes the identical artifact,
136
- and records both identities:
39
+ User-owned execution state is separate and is never advanced by
40
+ `liftoff update`:
137
41
 
138
42
  ```text
139
- candidate SHA -> qualification -> artifact digest
140
- | |
141
- +---------- main merge SHA ----+
142
- |
143
- +-> deployment -> tag and GitHub Release
43
+ governance/activation-state.json
44
+ governance/approvals/
45
+ governance/evidence/
46
+ governance/credentials/preflight-policy.json
144
47
  ```
145
48
 
146
- Package formats may require embedded version metadata, but that value must
147
- match the authoritative `release/X.Y.Z` or `hotfix/X.Y.Z` branch name.
148
-
149
- Release and hotfix back-merges remain pull-request-only and require successful
150
- checks. Because `GITHUB_TOKEN`-created events do not normally start more
151
- workflows, the coordinating workflow explicitly dispatches validation for the
152
- back-merge head and any required post-merge work for the resulting SHA. It does
153
- not push directly to a protected branch or rely on a tag push. Tag creation,
154
- Release publication, and durable evidence stay in the successful production
155
- workflow.
156
-
157
- `context.json` contains generated project facts only. GitHub repository state,
158
- runner access, licensed features, deployments, monitoring, alert routes,
159
- traffic, and rollout capabilities remain `undiscovered`. Power Apps context
160
- explicitly marks Liftoff backend, Docker, OpenTofu, custom container promotion,
161
- and API DAST as inapplicable.
162
-
163
- ## Activate after commit and push
164
-
165
- 1. Review the policy and context.
166
- 2. Commit the project and push it to the intended GitHub repository.
167
- 3. Run `/liftoff-repository-governance` with a selected agent.
168
- 4. The agent performs read-only Phase 0 and reports repository identity,
169
- artifacts, working commands, refs, workflows and exact checks, rulesets,
170
- releases, environments, security, runners, deployments, monitoring, alerts,
171
- health depth, platform capabilities, gaps, and inapplicable controls. When
172
- private Staging DAST applies without a suitable runner, it also reports the
173
- complete subscription-local topology, one explicit egress mode, authority,
174
- costs, limits, verification, and teardown plan.
175
- 5. The agent proposes the current `main` SHA as the activation baseline,
176
- presents an ordered plan, and stops.
177
- 6. Explicitly approve or revise the conversational plan. This is not a human
178
- merge or deployment approval gate.
179
- 7. After approval, the agent creates a new OpenSpec or Spec Kit governance
180
- change, proves required contexts green and deliberately red, applies
181
- repository-scoped rulesets last, and reads live enforcement back.
182
-
183
- The user-owned `governance/activation-baseline.json` is created only after
184
- approval. Liftoff never owns or recreates it or the agent-created governance
185
- change. Complete local handoffs say `handoff-generated`, partial adoptions say
186
- `handoff-partial`, and neither state means `active`.
49
+ The complete policy is packaged at
50
+ [`assets/governance/single-maintainer-gitflow/policy.md`](../assets/governance/single-maintainer-gitflow/policy.md).
51
+ Policy version 6 treats numbered policy sections as capability chapters, not
52
+ execution order. The managed phase graph is the sole execution-order authority.
187
53
 
188
- ## Existing projects
54
+ ## Canonical phase graph
55
+
56
+ The activation graph is packaged as `.liftoff/governance/phase-graph.json` and
57
+ records phase IDs, dependencies, applicability, allowed mutations, evidence,
58
+ approvals, rollback boundaries, and terminal states:
189
59
 
190
- Configurations without `governanceProfile` normalize to the enabled default
191
- without rewriting `liftoff.config.json`:
60
+ ```text
61
+ seed-valid
62
+ -> seed-verified
63
+ -> seed-archived
64
+ -> committed
65
+ -> pushed
66
+ -> phase-0-complete
67
+ -> activation-approved
68
+ -> credential-ready
69
+ -> provider-ready
70
+ -> state-path-selected
71
+ |-> existing-private-path ----------------------|
72
+ `-> bootstrap-local -> runner-ready |
73
+ -> private-backend-proof |
74
+ -> remote-import-verified --|
75
+ -> remote-ready
76
+ -> application-foundation
77
+ -> workflow-source-ready
78
+ -> dev-proof
79
+ -> staging-qualified
80
+ -> production-rehearsed
81
+ -> green-red-proof
82
+ -> enforcement-approved
83
+ -> rulesets-applied
84
+ -> live-readback
85
+ -> bootstrap-state-disposed
86
+ ```
87
+
88
+ If policy prose, generated tasks, or an agent response orders a transition
89
+ differently, the graph wins. Provider readiness precedes `bootstrap-local`;
90
+ restricted runner readiness precedes private backend proof; private backend proof
91
+ precedes declarative remote import; and only an existing private path or verified
92
+ remote import can satisfy `remote-ready`.
93
+
94
+ ## Bootstrap seed and local baseline
95
+
96
+ Before commit/push or Phase 0, setup completes, syncs, and archives the generated
97
+ `bootstrap-<project>` OpenSpec seed. It runs only local, applicable checks:
98
+
99
+ - `liftoff validate`
100
+ - backend tests from the generated README
101
+ - frontend build when a frontend exists
102
+ - `docker compose config -q` when Compose exists
103
+ - `tofu fmt -check -recursive`
104
+ - `tofu init -backend=false`
105
+ - `tofu validate`
106
+ - strict OpenSpec validation
107
+
108
+ Absent components are recorded as inapplicable. The baseline never starts
109
+ containers, runs a live `tofu plan` or `tofu apply`, deploys, mutates GitHub, or
110
+ requires cloud credentials. A failed check keeps the seed active; rerun
111
+ `/liftoff-setup` after remediation and verified phases are not repeated.
112
+
113
+ ## Questions and approval envelopes
114
+
115
+ Deterministic defaults and discovered facts do not become conversational
116
+ questions. Setup may ask only at these authority gates:
117
+
118
+ 1. repository creation, initial commit, remote, or push;
119
+ 2. credential enrollment;
120
+ 3. billed infrastructure, policy exceptions, and cost ceiling;
121
+ 4. final ruleset enforcement;
122
+ 5. destructive cleanup, including day-30 bootstrap-state disposal;
123
+ 6. external platform blockers that require changed authority or design.
124
+
125
+ Every approval envelope records the reviewed plan digest, allowed resource
126
+ types, destinations, permissions, cost ceiling, destructive scope, policy
127
+ exceptions, expiry, and baseline SHA. Retries inside the same envelope do not
128
+ ask again; expanded resources, destinations, permissions, cost, exceptions, or
129
+ destructive effects require a new approval.
130
+
131
+ ## Credentials for runner preflight
132
+
133
+ When `GITHUB_TOKEN` cannot read required hosted-runner metadata, setup first
134
+ prefers an existing verified selected-repository GitHub App installation with the
135
+ required read permissions. Liftoff does not install or broaden an App.
136
+
137
+ If no approved App is available, setup guides one fine-grained PAT with exactly:
138
+
139
+ | Field | Value |
140
+ | --- | --- |
141
+ | Display name | `<repo>-runner-preflight-read` |
142
+ | Repository secret | `RUNNER_CONFIGURATION_READ_TOKEN` |
143
+ | Lifetime | 30 days |
144
+ | Repository scope | current repository only |
145
+ | Repository permission | metadata read |
146
+ | Organization permissions | hosted-runner read and network-configuration read |
147
+ | Writes | none |
148
+ | Workflow/job allowlist | `.github/workflows/bootstrap-import-preflight.yml` job `bootstrap-import-preflight`; `.github/workflows/private-dast-preflight.yml` job `private-dast-preflight` |
149
+
150
+ Enter the value only through Liftoff's masked input. Never paste or show the
151
+ value in chat, argv, command arguments, logs, evidence, files, or screenshots. A value
152
+ that appears in any of those places is compromised and must be manually revoked
153
+ and rotated before setup can continue.
154
+
155
+ The recorded credential policy is payload-free: it stores auth kind, display
156
+ name, secret name, owner, repository, expiry, rotation lead, permissions,
157
+ allowed workflows/jobs, non-forwarding rules, and readback evidence, never the
158
+ secret value.
159
+
160
+ ## Evidence authority and active changes
161
+
162
+ Task checkboxes are a projection of phase state, not authority. Evidence
163
+ documents carry repository identity, activation version vector, graph hash, phase
164
+ contract digest, input digest, baseline SHA, phase ID, timestamp, producer, and
165
+ result. Setup and `liftoff governance verify` reject missing, stale,
166
+ contradictory, future-version, or graph-incompatible evidence.
167
+
168
+ There may be only one active governance source of truth. An unfinished bootstrap
169
+ seed blocks Phase 0. Exactly one compatible active governance change is resumed.
170
+ Multiple overlapping changes require a schema-valid supersession or archive
171
+ record before any phase advances.
172
+
173
+ Managed updates install new policy, graph, schema, compatibility metadata, setup
174
+ integrations, and aliases without touching user-owned state. When a policy,
175
+ activation-contract, schema, or graph-hash change affects active work, status
176
+ reports `reconciliation-required`, invalidates only affected descendants, and
177
+ waits for explicit acknowledgement of the current compatible identity and exact
178
+ graph hash.
179
+
180
+ ## Private staging and bootstrap retention
181
+
182
+ Private Staging DAST uses an ephemeral GitHub-hosted larger runner with Azure
183
+ VNet injection only when genuinely applicable. Phase 0 discovers repository,
184
+ subscription, authority, billing, network, DNS, cost, teardown, and capability
185
+ facts read-only. If DAST is inapplicable, no runner networking is provisioned.
186
+
187
+ When a private ZRS backend cannot be reached and no existing private management
188
+ path is approved, the bounded `bootstrap-local` branch may create only the
189
+ access-establishing resources needed to reach the backend. Local bootstrap state
190
+ is encrypted, gitignored, single-writer, never uploaded or copied through GitHub
191
+ artifacts or secrets, and cannot authorize application provisioning.
192
+
193
+ After verified declarative import, backend identity parity, state locking, Blob
194
+ versioning, and a clean-checkout no-change plan, local state becomes read-only
195
+ evidence for exactly 30 days. Disposal deletes the encryption key and approved
196
+ temporary copies and records a dated non-secret outcome. Provider registrations
197
+ remain retained subscription capabilities and are not unregistered during
198
+ teardown.
199
+
200
+ ## Commands
201
+
202
+ The generated setup integrations call only strict, project-aware CLI commands:
192
203
 
193
204
  ```bash
194
- liftoff update --check
195
- liftoff update
205
+ liftoff governance status --json
206
+ liftoff governance plan --json
207
+ liftoff governance apply-next --json --execute
208
+ liftoff governance resume --json
209
+ liftoff governance verify --json
196
210
  ```
197
211
 
198
- Check mode previews the schema-v6 manifest and new named core artifacts without
199
- writing. Plain update applies collision-free files; differing existing files
200
- remain managed-core conflicts unless individually reviewed with `--force`. An unrecorded
201
- conflict remains outside Liftoff ownership and produces `handoff-partial`.
202
- After every conflict is removed or matches the current artifact, the next
203
- update records the full artifact set as `handoff-generated`.
204
-
205
- Projects generated with policy versions 2 or 3 review the version-4 managed-core drift
206
- before replacement. `liftoff update` changes only the local handoff; it never
207
- provisions Azure or GitHub resources. Any active downstream runner change based
208
- on an older contract must reconcile its plan and implementation with version 4
209
- before applying cloud or organisation resources.
210
-
211
- Setting `"governanceProfile": "none"` stops future rendering. Previously managed
212
- handoff files are reported once as orphans and left on disk; Liftoff never
213
- deletes them automatically or changes live repository settings.
214
-
215
- ## Capability gaps
216
-
217
- Phase 0 must report missing GitHub licenses, runner-provisioning authority,
218
- VNet-injected assignment or reachability, Staging access, monitoring routes,
219
- parallel-version mechanisms, or statistically meaningful canary traffic. It
220
- must mark controls inapplicable or blocked rather than creating a skipped,
221
- hanging, partial, duplicate, or success-shaped placeholder.
222
-
223
- The official SLSA L3 generator is the policy's only action SHA-pinning
224
- exception because its reusable workflow contains mutable internal references.
225
- The outer call is pinned as tightly as supported and the exact exception is
226
- narrow and expiring. It does not weaken pinning for any other action, create a
227
- second vulnerability allowlist, or make Grype a blocking gate.
212
+ `status`, `plan`, and `verify` are read-only. `apply-next` previews mutations
213
+ unless `--execute` is supplied, and even then executes at most one graph-ready,
214
+ evidence-ready, approved phase. Unknown subcommands, flags, or extra positionals
215
+ fail before project discovery or mutation.
216
+
217
+ ## Existing projects
218
+
219
+ Projects without `governanceProfile` normalize to the enabled default during
220
+ read, then `liftoff update --check` previews manifest v7 and managed-core drift.
221
+ Plain `liftoff update` writes v7 only after preflights pass. It never provisions
222
+ Azure or GitHub resources and never advances activation state. Setting
223
+ `"governanceProfile": "none"` stops future rendering; previously managed files
224
+ become reported orphans and remain on disk for manual review.