@msn-control/liftoff 0.10.4 → 0.11.1

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 (643) hide show
  1. package/DEVELOPER.md +220 -77
  2. package/README.md +28 -28
  3. package/assets/supported-stack.json +3 -136
  4. package/dist/adapters/azure/governance-assessment.d.ts +2 -0
  5. package/dist/adapters/azure/governance-assessment.js +21 -0
  6. package/dist/adapters/azure/governance-assessment.js.map +1 -0
  7. package/dist/adapters/filesystem/atomic-write.d.ts +2 -0
  8. package/dist/adapters/filesystem/atomic-write.js +74 -0
  9. package/dist/adapters/filesystem/atomic-write.js.map +1 -0
  10. package/dist/adapters/filesystem/errors.d.ts +2 -0
  11. package/dist/adapters/filesystem/errors.js +8 -0
  12. package/dist/adapters/filesystem/errors.js.map +1 -0
  13. package/dist/adapters/filesystem/manifest-file.d.ts +1 -0
  14. package/dist/adapters/filesystem/manifest-file.js +21 -0
  15. package/dist/adapters/filesystem/manifest-file.js.map +1 -0
  16. package/dist/adapters/filesystem/project-config.d.ts +4 -0
  17. package/dist/adapters/filesystem/project-config.js +157 -0
  18. package/dist/adapters/filesystem/project-config.js.map +1 -0
  19. package/dist/adapters/filesystem/project-discovery.d.ts +2 -0
  20. package/dist/adapters/filesystem/project-discovery.js +30 -0
  21. package/dist/adapters/filesystem/project-discovery.js.map +1 -0
  22. package/dist/adapters/filesystem/project-files.d.ts +6 -0
  23. package/dist/adapters/filesystem/project-files.js +68 -0
  24. package/dist/adapters/filesystem/project-files.js.map +1 -0
  25. package/dist/adapters/filesystem/project-lock.d.ts +8 -0
  26. package/dist/adapters/filesystem/project-lock.js +164 -0
  27. package/dist/adapters/filesystem/project-lock.js.map +1 -0
  28. package/dist/adapters/filesystem/project-paths.d.ts +2 -0
  29. package/dist/adapters/filesystem/project-paths.js +60 -0
  30. package/dist/adapters/filesystem/project-paths.js.map +1 -0
  31. package/dist/adapters/filesystem/project-transaction.d.ts +23 -0
  32. package/dist/adapters/filesystem/project-transaction.js +158 -0
  33. package/dist/adapters/filesystem/project-transaction.js.map +1 -0
  34. package/dist/adapters/git/governance-assessment.d.ts +22 -0
  35. package/dist/adapters/git/governance-assessment.js +161 -0
  36. package/dist/adapters/git/governance-assessment.js.map +1 -0
  37. package/dist/adapters/github/governance-assessment.d.ts +2 -0
  38. package/dist/adapters/github/governance-assessment.js +18 -0
  39. package/dist/adapters/github/governance-assessment.js.map +1 -0
  40. package/dist/adapters/packaged-assets/package-root.d.ts +3 -0
  41. package/dist/adapters/packaged-assets/package-root.js +21 -0
  42. package/dist/adapters/packaged-assets/package-root.js.map +1 -0
  43. package/dist/adapters/packaged-assets/supported-stack.d.ts +4 -0
  44. package/dist/adapters/packaged-assets/supported-stack.js +18 -0
  45. package/dist/adapters/packaged-assets/supported-stack.js.map +1 -0
  46. package/dist/adapters/packaged-assets/template-assets.d.ts +23 -0
  47. package/dist/adapters/packaged-assets/template-assets.js +36 -0
  48. package/dist/adapters/packaged-assets/template-assets.js.map +1 -0
  49. package/dist/adapters/process/shell-command.d.ts +5 -0
  50. package/dist/adapters/process/shell-command.js +21 -0
  51. package/dist/adapters/process/shell-command.js.map +1 -0
  52. package/dist/application/context.d.ts +20 -0
  53. package/dist/application/context.js +2 -0
  54. package/dist/application/context.js.map +1 -0
  55. package/dist/application/diagnose/doctor.d.ts +21 -0
  56. package/dist/application/diagnose/doctor.js +586 -0
  57. package/dist/application/diagnose/doctor.js.map +1 -0
  58. package/dist/application/diagnose/generated-project.d.ts +1 -0
  59. package/dist/application/diagnose/generated-project.js +105 -0
  60. package/dist/application/diagnose/generated-project.js.map +1 -0
  61. package/dist/application/diagnose/validate.d.ts +6 -0
  62. package/dist/application/diagnose/validate.js +27 -0
  63. package/dist/application/diagnose/validate.js.map +1 -0
  64. package/dist/application/initialize/fixture.d.ts +2 -0
  65. package/dist/application/initialize/fixture.js +39 -0
  66. package/dist/application/initialize/fixture.js.map +1 -0
  67. package/dist/application/initialize/inputs.d.ts +3 -0
  68. package/dist/application/initialize/inputs.js +35 -0
  69. package/dist/application/initialize/inputs.js.map +1 -0
  70. package/dist/application/initialize/use-case.d.ts +23 -0
  71. package/dist/application/initialize/use-case.js +360 -0
  72. package/dist/application/initialize/use-case.js.map +1 -0
  73. package/dist/application/migrate/use-case.d.ts +7 -0
  74. package/dist/application/migrate/use-case.js +378 -0
  75. package/dist/application/migrate/use-case.js.map +1 -0
  76. package/dist/application/project/catalog.d.ts +46 -0
  77. package/dist/application/project/catalog.js +12 -0
  78. package/dist/application/project/catalog.js.map +1 -0
  79. package/dist/application/project/manifest.d.ts +2 -0
  80. package/dist/application/project/manifest.js +29 -0
  81. package/dist/application/project/manifest.js.map +1 -0
  82. package/dist/application/project/planning.d.ts +6 -0
  83. package/dist/application/project/planning.js +12 -0
  84. package/dist/application/project/planning.js.map +1 -0
  85. package/dist/application/update/planning.d.ts +40 -0
  86. package/dist/application/update/planning.js +293 -0
  87. package/dist/application/update/planning.js.map +1 -0
  88. package/dist/application/update/reporting.d.ts +42 -0
  89. package/dist/application/update/reporting.js +325 -0
  90. package/dist/application/update/reporting.js.map +1 -0
  91. package/dist/application/update/use-case.d.ts +8 -0
  92. package/dist/application/update/use-case.js +600 -0
  93. package/dist/application/update/use-case.js.map +1 -0
  94. package/dist/application/upgrade/use-case.d.ts +6 -0
  95. package/dist/application/upgrade/use-case.js +82 -0
  96. package/dist/application/upgrade/use-case.js.map +1 -0
  97. package/dist/args.d.ts +5 -65
  98. package/dist/args.js +4 -472
  99. package/dist/args.js.map +1 -1
  100. package/dist/artifact-lifecycle.d.ts +1 -21
  101. package/dist/artifact-lifecycle.js +1 -75
  102. package/dist/artifact-lifecycle.js.map +1 -1
  103. package/dist/catalogs.d.ts +1 -50
  104. package/dist/catalogs.js +1 -472
  105. package/dist/catalogs.js.map +1 -1
  106. package/dist/cli/args/contracts.d.ts +51 -0
  107. package/dist/cli/args/contracts.js +2 -0
  108. package/dist/cli/args/contracts.js.map +1 -0
  109. package/dist/cli/args/definitions.d.ts +6 -0
  110. package/dist/cli/args/definitions.js +187 -0
  111. package/dist/cli/args/definitions.js.map +1 -0
  112. package/dist/cli/args/help.d.ts +5 -0
  113. package/dist/cli/args/help.js +130 -0
  114. package/dist/cli/args/help.js.map +1 -0
  115. package/dist/cli/args/parser.d.ts +5 -0
  116. package/dist/cli/args/parser.js +145 -0
  117. package/dist/cli/args/parser.js.map +1 -0
  118. package/dist/cli/args/readers.d.ts +4 -0
  119. package/dist/cli/args/readers.js +19 -0
  120. package/dist/cli/args/readers.js.map +1 -0
  121. package/dist/cli/commands/diagnose.d.ts +4 -0
  122. package/dist/cli/commands/diagnose.js +12 -0
  123. package/dist/cli/commands/diagnose.js.map +1 -0
  124. package/dist/cli/commands/dispatch.d.ts +3 -0
  125. package/dist/cli/commands/dispatch.js +94 -0
  126. package/dist/cli/commands/dispatch.js.map +1 -0
  127. package/dist/cli/commands/help.d.ts +3 -0
  128. package/dist/cli/commands/help.js +32 -0
  129. package/dist/cli/commands/help.js.map +1 -0
  130. package/dist/cli/commands/helpers.d.ts +8 -0
  131. package/dist/cli/commands/helpers.js +97 -0
  132. package/dist/cli/commands/helpers.js.map +1 -0
  133. package/dist/cli/commands/initialize.d.ts +3 -0
  134. package/dist/cli/commands/initialize.js +7 -0
  135. package/dist/cli/commands/initialize.js.map +1 -0
  136. package/dist/cli/commands/migrate.d.ts +3 -0
  137. package/dist/cli/commands/migrate.js +8 -0
  138. package/dist/cli/commands/migrate.js.map +1 -0
  139. package/dist/cli/commands/plan.d.ts +3 -0
  140. package/dist/cli/commands/plan.js +34 -0
  141. package/dist/cli/commands/plan.js.map +1 -0
  142. package/dist/cli/commands/reference.d.ts +5 -0
  143. package/dist/cli/commands/reference.js +43 -0
  144. package/dist/cli/commands/reference.js.map +1 -0
  145. package/dist/cli/commands/update.d.ts +3 -0
  146. package/dist/cli/commands/update.js +9 -0
  147. package/dist/cli/commands/update.js.map +1 -0
  148. package/dist/cli/commands/upgrade.d.ts +3 -0
  149. package/dist/cli/commands/upgrade.js +7 -0
  150. package/dist/cli/commands/upgrade.js.map +1 -0
  151. package/dist/cli/context.d.ts +1 -0
  152. package/dist/cli/context.js +2 -0
  153. package/dist/cli/context.js.map +1 -0
  154. package/dist/cli/project-options.d.ts +3 -0
  155. package/dist/cli/project-options.js +41 -0
  156. package/dist/cli/project-options.js.map +1 -0
  157. package/dist/cli.d.ts +3 -3
  158. package/dist/cli.js +2 -2
  159. package/dist/cli.js.map +1 -1
  160. package/dist/commands.d.ts +4 -35
  161. package/dist/commands.js +3 -2969
  162. package/dist/commands.js.map +1 -1
  163. package/dist/container-validation.d.ts +1 -1
  164. package/dist/domain/governance/activation/approvals.d.ts +351 -0
  165. package/dist/domain/governance/activation/approvals.js +528 -0
  166. package/dist/domain/governance/activation/approvals.js.map +1 -0
  167. package/dist/domain/governance/activation/canonical-json.d.ts +4 -0
  168. package/dist/domain/governance/activation/canonical-json.js +39 -0
  169. package/dist/domain/governance/activation/canonical-json.js.map +1 -0
  170. package/dist/domain/governance/activation/capabilities.d.ts +7 -0
  171. package/dist/domain/governance/activation/capabilities.js +33 -0
  172. package/dist/domain/governance/activation/capabilities.js.map +1 -0
  173. package/dist/domain/governance/activation/evidence.d.ts +63 -0
  174. package/dist/domain/governance/activation/evidence.js +444 -0
  175. package/dist/domain/governance/activation/evidence.js.map +1 -0
  176. package/dist/domain/governance/activation/graph.d.ts +397 -0
  177. package/dist/domain/governance/activation/graph.js +441 -0
  178. package/dist/domain/governance/activation/graph.js.map +1 -0
  179. package/dist/domain/governance/activation/inputs.d.ts +25 -0
  180. package/dist/domain/governance/activation/inputs.js +63 -0
  181. package/dist/domain/governance/activation/inputs.js.map +1 -0
  182. package/dist/domain/governance/activation/operations.d.ts +19 -0
  183. package/dist/domain/governance/activation/operations.js +181 -0
  184. package/dist/domain/governance/activation/operations.js.map +1 -0
  185. package/dist/domain/governance/activation/readiness.d.ts +27 -0
  186. package/dist/domain/governance/activation/readiness.js +269 -0
  187. package/dist/domain/governance/activation/readiness.js.map +1 -0
  188. package/dist/domain/governance/activation/types.d.ts +399 -0
  189. package/dist/domain/governance/activation/types.js +109 -0
  190. package/dist/domain/governance/activation/types.js.map +1 -0
  191. package/dist/domain/governance/activation/validators.d.ts +22 -0
  192. package/dist/domain/governance/activation/validators.js +1347 -0
  193. package/dist/domain/governance/activation/validators.js.map +1 -0
  194. package/dist/domain/governance/assessment/catalog.d.ts +14 -0
  195. package/dist/domain/governance/assessment/catalog.js +105 -0
  196. package/dist/domain/governance/assessment/catalog.js.map +1 -0
  197. package/dist/domain/governance/assessment/errors.d.ts +10 -0
  198. package/dist/domain/governance/assessment/errors.js +22 -0
  199. package/dist/domain/governance/assessment/errors.js.map +1 -0
  200. package/dist/domain/governance/assessment/index.d.ts +8 -0
  201. package/dist/domain/governance/assessment/index.js +9 -0
  202. package/dist/domain/governance/assessment/index.js.map +1 -0
  203. package/dist/domain/governance/assessment/live-normalize.d.ts +19 -0
  204. package/dist/domain/governance/assessment/live-normalize.js +403 -0
  205. package/dist/domain/governance/assessment/live-normalize.js.map +1 -0
  206. package/dist/domain/governance/assessment/predicates.d.ts +36 -0
  207. package/dist/domain/governance/assessment/predicates.js +545 -0
  208. package/dist/domain/governance/assessment/predicates.js.map +1 -0
  209. package/dist/domain/governance/assessment/report.d.ts +23 -0
  210. package/dist/domain/governance/assessment/report.js +266 -0
  211. package/dist/domain/governance/assessment/report.js.map +1 -0
  212. package/dist/domain/governance/assessment/sanitize.d.ts +8 -0
  213. package/dist/domain/governance/assessment/sanitize.js +60 -0
  214. package/dist/domain/governance/assessment/sanitize.js.map +1 -0
  215. package/dist/domain/governance/assessment/types.d.ts +174 -0
  216. package/dist/domain/governance/assessment/types.js +13 -0
  217. package/dist/domain/governance/assessment/types.js.map +1 -0
  218. package/dist/domain/governance/assessment/yaml.d.ts +6 -0
  219. package/dist/domain/governance/assessment/yaml.js +30 -0
  220. package/dist/domain/governance/assessment/yaml.js.map +1 -0
  221. package/dist/domain/governance/policy/identity.d.ts +64 -0
  222. package/dist/domain/governance/policy/identity.js +112 -0
  223. package/dist/domain/governance/policy/identity.js.map +1 -0
  224. package/dist/domain/migration/dependencies.d.ts +7 -0
  225. package/dist/domain/migration/dependencies.js +221 -0
  226. package/dist/domain/migration/dependencies.js.map +1 -0
  227. package/dist/domain/migration/inventory.d.ts +3 -0
  228. package/dist/domain/migration/inventory.js +15 -0
  229. package/dist/domain/migration/inventory.js.map +1 -0
  230. package/dist/domain/project/artifact-lifecycle.d.ts +69 -0
  231. package/dist/domain/project/artifact-lifecycle.js +137 -0
  232. package/dist/domain/project/artifact-lifecycle.js.map +1 -0
  233. package/dist/domain/project/catalog.d.ts +48 -0
  234. package/dist/domain/project/catalog.js +507 -0
  235. package/dist/domain/project/catalog.js.map +1 -0
  236. package/dist/domain/project/contracts.d.ts +247 -0
  237. package/dist/domain/project/contracts.js +2 -0
  238. package/dist/domain/project/contracts.js.map +1 -0
  239. package/dist/domain/project/errors.d.ts +3 -0
  240. package/dist/domain/project/errors.js +7 -0
  241. package/dist/domain/project/errors.js.map +1 -0
  242. package/dist/domain/project/infrastructure-layout.d.ts +26 -0
  243. package/dist/domain/project/infrastructure-layout.js +124 -0
  244. package/dist/domain/project/infrastructure-layout.js.map +1 -0
  245. package/dist/domain/project/inputs.d.ts +21 -0
  246. package/dist/domain/project/inputs.js +41 -0
  247. package/dist/domain/project/inputs.js.map +1 -0
  248. package/dist/domain/project/manifest/artifacts.d.ts +8 -0
  249. package/dist/domain/project/manifest/artifacts.js +150 -0
  250. package/dist/domain/project/manifest/artifacts.js.map +1 -0
  251. package/dist/domain/project/manifest/context.d.ts +13 -0
  252. package/dist/domain/project/manifest/context.js +2 -0
  253. package/dist/domain/project/manifest/context.js.map +1 -0
  254. package/dist/domain/project/manifest/fields.d.ts +6 -0
  255. package/dist/domain/project/manifest/fields.js +36 -0
  256. package/dist/domain/project/manifest/fields.js.map +1 -0
  257. package/dist/domain/project/manifest/governance.d.ts +8 -0
  258. package/dist/domain/project/manifest/governance.js +161 -0
  259. package/dist/domain/project/manifest/governance.js.map +1 -0
  260. package/dist/domain/project/manifest/project-identity.d.ts +6 -0
  261. package/dist/domain/project/manifest/project-identity.js +273 -0
  262. package/dist/domain/project/manifest/project-identity.js.map +1 -0
  263. package/dist/domain/project/manifest/reader.d.ts +9 -0
  264. package/dist/domain/project/manifest/reader.js +141 -0
  265. package/dist/domain/project/manifest/reader.js.map +1 -0
  266. package/dist/domain/project/paths.d.ts +2 -0
  267. package/dist/domain/project/paths.js +29 -0
  268. package/dist/domain/project/paths.js.map +1 -0
  269. package/dist/domain/project/planning.d.ts +19 -0
  270. package/dist/domain/project/planning.js +329 -0
  271. package/dist/domain/project/planning.js.map +1 -0
  272. package/dist/domain/project/retired-workload.d.ts +4 -0
  273. package/dist/domain/project/retired-workload.js +18 -0
  274. package/dist/domain/project/retired-workload.js.map +1 -0
  275. package/dist/domain/project/supported-stack.d.ts +113 -0
  276. package/dist/domain/project/supported-stack.js +426 -0
  277. package/dist/domain/project/supported-stack.js.map +1 -0
  278. package/dist/domain/workstation/constraints.d.ts +6 -0
  279. package/dist/domain/workstation/constraints.js +8 -0
  280. package/dist/domain/workstation/constraints.js.map +1 -0
  281. package/dist/file-system.d.ts +10 -44
  282. package/dist/file-system.js +9 -1245
  283. package/dist/file-system.js.map +1 -1
  284. package/dist/framework-adapters.d.ts +1 -1
  285. package/dist/framework-validation.d.ts +1 -1
  286. package/dist/framework-validation.js +1 -1
  287. package/dist/framework-validation.js.map +1 -1
  288. package/dist/genai-templates.d.ts +2 -9
  289. package/dist/genai-templates.js +4 -5
  290. package/dist/genai-templates.js.map +1 -1
  291. package/dist/generators/common/artifacts.d.ts +6 -0
  292. package/dist/generators/common/artifacts.js +30 -0
  293. package/dist/generators/common/artifacts.js.map +1 -0
  294. package/dist/generators/common/base.d.ts +17 -0
  295. package/dist/generators/common/base.js +421 -0
  296. package/dist/generators/common/base.js.map +1 -0
  297. package/dist/generators/common/dotenv-validation.d.ts +2 -0
  298. package/dist/generators/common/dotenv-validation.js +80 -0
  299. package/dist/generators/common/dotenv-validation.js.map +1 -0
  300. package/dist/generators/common/environments.d.ts +3 -0
  301. package/dist/generators/common/environments.js +15 -0
  302. package/dist/generators/common/environments.js.map +1 -0
  303. package/dist/generators/common/frontend.d.ts +15 -0
  304. package/dist/generators/common/frontend.js +166 -0
  305. package/dist/generators/common/frontend.js.map +1 -0
  306. package/dist/generators/common/python-settings.d.ts +2 -0
  307. package/dist/generators/common/python-settings.js +70 -0
  308. package/dist/generators/common/python-settings.js.map +1 -0
  309. package/dist/generators/common/spec-workflow.d.ts +28 -0
  310. package/dist/generators/common/spec-workflow.js +567 -0
  311. package/dist/generators/common/spec-workflow.js.map +1 -0
  312. package/dist/generators/common/values.d.ts +13 -0
  313. package/dist/generators/common/values.js +16 -0
  314. package/dist/generators/common/values.js.map +1 -0
  315. package/dist/generators/containers/compose.d.ts +7 -0
  316. package/dist/generators/containers/compose.js +196 -0
  317. package/dist/generators/containers/compose.js.map +1 -0
  318. package/dist/generators/containers/context.d.ts +1 -0
  319. package/dist/generators/containers/context.js +43 -0
  320. package/dist/generators/containers/context.js.map +1 -0
  321. package/dist/generators/containers/images.d.ts +7 -0
  322. package/dist/generators/containers/images.js +119 -0
  323. package/dist/generators/containers/images.js.map +1 -0
  324. package/dist/generators/context.d.ts +42 -0
  325. package/dist/generators/context.js +38 -0
  326. package/dist/generators/context.js.map +1 -0
  327. package/dist/generators/genai/backend.d.ts +20 -0
  328. package/dist/generators/genai/backend.js +667 -0
  329. package/dist/generators/genai/backend.js.map +1 -0
  330. package/dist/generators/genai/configuration.d.ts +3 -0
  331. package/dist/generators/genai/configuration.js +43 -0
  332. package/dist/generators/genai/configuration.js.map +1 -0
  333. package/dist/generators/genai/database.d.ts +7 -0
  334. package/dist/generators/genai/database.js +71 -0
  335. package/dist/generators/genai/database.js.map +1 -0
  336. package/dist/generators/genai/functions.d.ts +15 -0
  337. package/dist/generators/genai/functions.js +156 -0
  338. package/dist/generators/genai/functions.js.map +1 -0
  339. package/dist/generators/genai/index.d.ts +8 -0
  340. package/dist/generators/genai/index.js +11 -0
  341. package/dist/generators/genai/index.js.map +1 -0
  342. package/dist/generators/genai/patterns.d.ts +9 -0
  343. package/dist/generators/genai/patterns.js +309 -0
  344. package/dist/generators/genai/patterns.js.map +1 -0
  345. package/dist/generators/infrastructure/azure.d.ts +18 -0
  346. package/dist/generators/infrastructure/azure.js +655 -0
  347. package/dist/generators/infrastructure/azure.js.map +1 -0
  348. package/dist/generators/infrastructure/names.d.ts +23 -0
  349. package/dist/generators/infrastructure/names.js +51 -0
  350. package/dist/generators/infrastructure/names.js.map +1 -0
  351. package/dist/generators/standard/configuration.d.ts +3 -0
  352. package/dist/generators/standard/configuration.js +26 -0
  353. package/dist/generators/standard/configuration.js.map +1 -0
  354. package/dist/generators/standard/go.d.ts +17 -0
  355. package/dist/generators/standard/go.js +338 -0
  356. package/dist/generators/standard/go.js.map +1 -0
  357. package/dist/generators/standard/index.d.ts +12 -0
  358. package/dist/generators/standard/index.js +12 -0
  359. package/dist/generators/standard/index.js.map +1 -0
  360. package/dist/generators/standard/node.d.ts +20 -0
  361. package/dist/generators/standard/node.js +314 -0
  362. package/dist/generators/standard/node.js.map +1 -0
  363. package/dist/generators/standard/python.d.ts +18 -0
  364. package/dist/generators/standard/python.js +191 -0
  365. package/dist/generators/standard/python.js.map +1 -0
  366. package/dist/go-template-assets.js +3 -3
  367. package/dist/go-template-assets.js.map +1 -1
  368. package/dist/governance-activation/activation-state.d.ts +1 -1
  369. package/dist/governance-activation/activation-state.js +46 -9
  370. package/dist/governance-activation/activation-state.js.map +1 -1
  371. package/dist/governance-activation/approvals.d.ts +1 -188
  372. package/dist/governance-activation/approvals.js +1 -507
  373. package/dist/governance-activation/approvals.js.map +1 -1
  374. package/dist/governance-activation/canonical-json.d.ts +1 -3
  375. package/dist/governance-activation/canonical-json.js +1 -35
  376. package/dist/governance-activation/canonical-json.js.map +1 -1
  377. package/dist/governance-activation/commands.d.ts +1 -1
  378. package/dist/governance-activation/commands.js +72 -106
  379. package/dist/governance-activation/commands.js.map +1 -1
  380. package/dist/governance-activation/compatibility.d.ts +11 -3
  381. package/dist/governance-activation/compatibility.js +31 -4
  382. package/dist/governance-activation/compatibility.js.map +1 -1
  383. package/dist/governance-activation/credentials.d.ts +3 -3
  384. package/dist/governance-activation/credentials.js +5 -5
  385. package/dist/governance-activation/credentials.js.map +1 -1
  386. package/dist/governance-activation/doctor.d.ts +1 -1
  387. package/dist/governance-activation/doctor.js +28 -96
  388. package/dist/governance-activation/doctor.js.map +1 -1
  389. package/dist/governance-activation/evidence.d.ts +1 -49
  390. package/dist/governance-activation/evidence.js +1 -245
  391. package/dist/governance-activation/evidence.js.map +1 -1
  392. package/dist/governance-activation/git-ignore.d.ts +9 -0
  393. package/dist/governance-activation/git-ignore.js +76 -0
  394. package/dist/governance-activation/git-ignore.js.map +1 -0
  395. package/dist/governance-activation/graph.d.ts +1 -397
  396. package/dist/governance-activation/graph.js +1 -440
  397. package/dist/governance-activation/graph.js.map +1 -1
  398. package/dist/governance-activation/identity.d.ts +1 -35
  399. package/dist/governance-activation/identity.js +1 -88
  400. package/dist/governance-activation/identity.js.map +1 -1
  401. package/dist/governance-activation/index.d.ts +3 -0
  402. package/dist/governance-activation/index.js +3 -0
  403. package/dist/governance-activation/index.js.map +1 -1
  404. package/dist/governance-activation/inputs.d.ts +8 -0
  405. package/dist/governance-activation/inputs.js +146 -0
  406. package/dist/governance-activation/inputs.js.map +1 -0
  407. package/dist/governance-activation/migration.d.ts +4 -3
  408. package/dist/governance-activation/migration.js +14 -6
  409. package/dist/governance-activation/migration.js.map +1 -1
  410. package/dist/governance-activation/phase-bootstrap-state.d.ts +3 -0
  411. package/dist/governance-activation/phase-bootstrap-state.js +128 -0
  412. package/dist/governance-activation/phase-bootstrap-state.js.map +1 -0
  413. package/dist/governance-activation/phase-discovery.d.ts +2 -0
  414. package/dist/governance-activation/phase-discovery.js +88 -0
  415. package/dist/governance-activation/phase-discovery.js.map +1 -0
  416. package/dist/governance-activation/phase-governance.d.ts +4 -0
  417. package/dist/governance-activation/phase-governance.js +141 -0
  418. package/dist/governance-activation/phase-governance.js.map +1 -0
  419. package/dist/governance-activation/phase-publication.d.ts +8 -0
  420. package/dist/governance-activation/phase-publication.js +318 -0
  421. package/dist/governance-activation/phase-publication.js.map +1 -0
  422. package/dist/governance-activation/read-only.d.ts +30 -0
  423. package/dist/governance-activation/read-only.js +93 -0
  424. package/dist/governance-activation/read-only.js.map +1 -0
  425. package/dist/governance-activation/readiness.d.ts +1 -25
  426. package/dist/governance-activation/readiness.js +1 -222
  427. package/dist/governance-activation/readiness.js.map +1 -1
  428. package/dist/governance-activation/reconciliation.d.ts +1 -1
  429. package/dist/governance-activation/reconciliation.js +3 -3
  430. package/dist/governance-activation/reconciliation.js.map +1 -1
  431. package/dist/governance-activation/release-integrity.d.ts +1 -1
  432. package/dist/governance-activation/release-integrity.js +2 -2
  433. package/dist/governance-activation/release-integrity.js.map +1 -1
  434. package/dist/governance-activation/seed-lifecycle.d.ts +9 -1
  435. package/dist/governance-activation/seed-lifecycle.js +197 -63
  436. package/dist/governance-activation/seed-lifecycle.js.map +1 -1
  437. package/dist/governance-activation/source-of-truth.d.ts +5 -3
  438. package/dist/governance-activation/source-of-truth.js +32 -52
  439. package/dist/governance-activation/source-of-truth.js.map +1 -1
  440. package/dist/governance-activation/spec-kit-seed.d.ts +9 -0
  441. package/dist/governance-activation/spec-kit-seed.js +43 -0
  442. package/dist/governance-activation/spec-kit-seed.js.map +1 -0
  443. package/dist/governance-activation/task-projection.d.ts +1 -1
  444. package/dist/governance-activation/transition-planning.d.ts +15 -0
  445. package/dist/governance-activation/transition-planning.js +250 -0
  446. package/dist/governance-activation/transition-planning.js.map +1 -0
  447. package/dist/governance-activation/transition-ports.d.ts +150 -0
  448. package/dist/governance-activation/transition-ports.js +2 -0
  449. package/dist/governance-activation/transition-ports.js.map +1 -0
  450. package/dist/governance-activation/transition-process.d.ts +7 -0
  451. package/dist/governance-activation/transition-process.js +21 -0
  452. package/dist/governance-activation/transition-process.js.map +1 -0
  453. package/dist/governance-activation/transition-records.d.ts +56 -0
  454. package/dist/governance-activation/transition-records.js +208 -0
  455. package/dist/governance-activation/transition-records.js.map +1 -0
  456. package/dist/governance-activation/transitions.d.ts +6 -165
  457. package/dist/governance-activation/transitions.js +142 -2055
  458. package/dist/governance-activation/transitions.js.map +1 -1
  459. package/dist/governance-activation/types.d.ts +1 -390
  460. package/dist/governance-activation/types.js +1 -107
  461. package/dist/governance-activation/types.js.map +1 -1
  462. package/dist/governance-activation/validators.d.ts +1 -17
  463. package/dist/governance-activation/validators.js +1 -1304
  464. package/dist/governance-activation/validators.js.map +1 -1
  465. package/dist/governance-assessment/catalog.d.ts +1 -2
  466. package/dist/governance-assessment/catalog.js +18 -85
  467. package/dist/governance-assessment/catalog.js.map +1 -1
  468. package/dist/governance-assessment/command.d.ts +1 -1
  469. package/dist/governance-assessment/command.js +8 -12
  470. package/dist/governance-assessment/command.js.map +1 -1
  471. package/dist/governance-assessment/engine.d.ts +6 -11
  472. package/dist/governance-assessment/engine.js +463 -114
  473. package/dist/governance-assessment/engine.js.map +1 -1
  474. package/dist/governance-assessment/live-normalize.d.ts +1 -19
  475. package/dist/governance-assessment/live-normalize.js +1 -402
  476. package/dist/governance-assessment/live-normalize.js.map +1 -1
  477. package/dist/governance-assessment/live-transport.d.ts +2 -6
  478. package/dist/governance-assessment/live-transport.js +10 -22
  479. package/dist/governance-assessment/live-transport.js.map +1 -1
  480. package/dist/governance-assessment/live.js +55 -5
  481. package/dist/governance-assessment/live.js.map +1 -1
  482. package/dist/governance-assessment/predicates.d.ts +1 -27
  483. package/dist/governance-assessment/predicates.js +1 -329
  484. package/dist/governance-assessment/predicates.js.map +1 -1
  485. package/dist/governance-assessment/project.d.ts +13 -17
  486. package/dist/governance-assessment/project.js +59 -149
  487. package/dist/governance-assessment/project.js.map +1 -1
  488. package/dist/governance-assessment/readers.d.ts +1 -5
  489. package/dist/governance-assessment/readers.js +5 -13
  490. package/dist/governance-assessment/readers.js.map +1 -1
  491. package/dist/governance-assessment/report.d.ts +1 -23
  492. package/dist/governance-assessment/report.js +1 -265
  493. package/dist/governance-assessment/report.js.map +1 -1
  494. package/dist/governance-assessment/sanitize.d.ts +1 -8
  495. package/dist/governance-assessment/sanitize.js +1 -56
  496. package/dist/governance-assessment/sanitize.js.map +1 -1
  497. package/dist/governance-assessment/types.d.ts +1 -173
  498. package/dist/governance-assessment/types.js +1 -12
  499. package/dist/governance-assessment/types.js.map +1 -1
  500. package/dist/governance-assessment/yaml.d.ts +1 -6
  501. package/dist/governance-assessment/yaml.js +1 -29
  502. package/dist/governance-assessment/yaml.js.map +1 -1
  503. package/dist/init-filesystem.d.ts +1 -1
  504. package/dist/init-filesystem.js +126 -174
  505. package/dist/init-filesystem.js.map +1 -1
  506. package/dist/interactive.d.ts +2 -2
  507. package/dist/interactive.js +42 -41
  508. package/dist/interactive.js.map +1 -1
  509. package/dist/migrate-plan.d.ts +1 -1
  510. package/dist/migrate-plan.js +14 -8
  511. package/dist/migrate-plan.js.map +1 -1
  512. package/dist/npm-template-assets.js +5 -4
  513. package/dist/npm-template-assets.js.map +1 -1
  514. package/dist/openspec-profile.d.ts +1 -1
  515. package/dist/opentofu-template-assets.js +3 -3
  516. package/dist/opentofu-template-assets.js.map +1 -1
  517. package/dist/package-identity.d.ts +3 -0
  518. package/dist/package-identity.js +13 -2
  519. package/dist/package-identity.js.map +1 -1
  520. package/dist/planner.d.ts +1 -19
  521. package/dist/planner.js +1 -565
  522. package/dist/planner.js.map +1 -1
  523. package/dist/process-runner.d.ts +1 -1
  524. package/dist/project-dependencies.d.ts +5 -3
  525. package/dist/project-dependencies.js +74 -63
  526. package/dist/project-dependencies.js.map +1 -1
  527. package/dist/published-verifier.js +61 -30
  528. package/dist/published-verifier.js.map +1 -1
  529. package/dist/python-template-assets.js +6 -9
  530. package/dist/python-template-assets.js.map +1 -1
  531. package/dist/reconcile.d.ts +1 -1
  532. package/dist/reconcile.js +2 -2
  533. package/dist/reconcile.js.map +1 -1
  534. package/dist/repository-governance.d.ts +5 -2
  535. package/dist/repository-governance.js +126 -112
  536. package/dist/repository-governance.js.map +1 -1
  537. package/dist/runtime.js +1 -1
  538. package/dist/runtime.js.map +1 -1
  539. package/dist/scan.d.ts +6 -2
  540. package/dist/scan.js +78 -30
  541. package/dist/scan.js.map +1 -1
  542. package/dist/self-upgrade.d.ts +1 -1
  543. package/dist/self-upgrade.js +20 -7
  544. package/dist/self-upgrade.js.map +1 -1
  545. package/dist/stable-release.js +7 -1
  546. package/dist/stable-release.js.map +1 -1
  547. package/dist/standard-templates.d.ts +2 -2
  548. package/dist/standard-templates.js +6 -841
  549. package/dist/standard-templates.js.map +1 -1
  550. package/dist/supported-stack.d.ts +3 -115
  551. package/dist/supported-stack.js +4 -438
  552. package/dist/supported-stack.js.map +1 -1
  553. package/dist/telemetry/index.d.ts +1 -1
  554. package/dist/templates.d.ts +10 -20
  555. package/dist/templates.js +52 -3261
  556. package/dist/templates.js.map +1 -1
  557. package/dist/types.d.ts +1 -263
  558. package/dist/types.js +1 -1
  559. package/dist/types.js.map +1 -1
  560. package/dist/version.js +2 -6
  561. package/dist/version.js.map +1 -1
  562. package/dist/workstation-catalog.d.ts +5 -2
  563. package/dist/workstation-catalog.js +33 -2
  564. package/dist/workstation-catalog.js.map +1 -1
  565. package/dist/workstation.d.ts +4 -3
  566. package/dist/workstation.js +86 -32
  567. package/dist/workstation.js.map +1 -1
  568. package/docs/assets/liftoff-terminal.svg +3 -3
  569. package/docs/azure-deployment.md +107 -10
  570. package/docs/cli-reference.md +49 -13
  571. package/docs/configuration-and-manifests.md +139 -34
  572. package/docs/existing-repositories.md +33 -6
  573. package/docs/getting-started.md +44 -31
  574. package/docs/prerequisites.md +34 -35
  575. package/docs/project-structure.md +39 -46
  576. package/docs/repository-governance.md +90 -24
  577. package/docs/safety-and-consent.md +65 -12
  578. package/docs/spec-workflows-and-agents.md +31 -28
  579. package/docs/supported-stack.md +11 -9
  580. package/docs/troubleshooting.md +107 -49
  581. package/docs/workloads.md +46 -62
  582. package/package.json +4 -7
  583. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/UPSTREAM_LICENSE.txt +0 -21
  584. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/catalog.json +0 -520
  585. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/packaged/gitignore +0 -27
  586. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/README.md +0 -25
  587. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/components.json +0 -22
  588. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/eslint.config.js +0 -23
  589. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/index.html +0 -13
  590. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/package-lock.json +0 -6156
  591. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/package.json +0 -60
  592. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/public/power-apps.svg +0 -55
  593. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/App.tsx +0 -17
  594. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/assets/react.svg +0 -1
  595. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/mode-toggle.tsx +0 -37
  596. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/badge.tsx +0 -46
  597. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/button.tsx +0 -60
  598. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/calendar.tsx +0 -211
  599. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/card.tsx +0 -92
  600. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/chart.tsx +0 -355
  601. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/checkbox.tsx +0 -32
  602. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/command.tsx +0 -184
  603. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/dialog.tsx +0 -141
  604. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/dropdown-menu.tsx +0 -257
  605. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/input.tsx +0 -21
  606. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/label.tsx +0 -22
  607. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/popover.tsx +0 -46
  608. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/progress.tsx +0 -29
  609. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/select.tsx +0 -185
  610. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/separator.tsx +0 -26
  611. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/skeleton.tsx +0 -13
  612. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/table.tsx +0 -114
  613. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/tabs.tsx +0 -66
  614. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/textarea.tsx +0 -18
  615. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/tooltip.tsx +0 -61
  616. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/hooks/use-theme.ts +0 -11
  617. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/index.css +0 -131
  618. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/lib/utils.ts +0 -6
  619. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/main.tsx +0 -10
  620. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/pages/_layout.tsx +0 -31
  621. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/pages/home.tsx +0 -59
  622. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/pages/not-found.tsx +0 -14
  623. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/providers/query-provider.tsx +0 -26
  624. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/providers/sonner-provider.tsx +0 -23
  625. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/providers/theme-provider.tsx +0 -64
  626. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/router.tsx +0 -24
  627. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/tsconfig.app.json +0 -34
  628. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/tsconfig.json +0 -13
  629. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/tsconfig.node.json +0 -26
  630. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/vite.config.ts +0 -19
  631. package/assets/power-apps-code-app/README.md +0 -27
  632. package/dist/code-apps-plugin.d.ts +0 -13
  633. package/dist/code-apps-plugin.js +0 -69
  634. package/dist/code-apps-plugin.js.map +0 -1
  635. package/dist/power-apps-assets.d.ts +0 -30
  636. package/dist/power-apps-assets.js +0 -131
  637. package/dist/power-apps-assets.js.map +0 -1
  638. package/dist/power-apps-templates.d.ts +0 -3
  639. package/dist/power-apps-templates.js +0 -177
  640. package/dist/power-apps-templates.js.map +0 -1
  641. package/dist/power-apps-validation.d.ts +0 -1
  642. package/dist/power-apps-validation.js +0 -79
  643. package/dist/power-apps-validation.js.map +0 -1
@@ -1,23 +1,39 @@
1
- import { canonicalJson, canonicalSha256, sha256Hex } from '../governance-activation/canonical-json.js';
2
- import { currentActivationIdentity, canonicalPhaseGraph } from '../governance-activation/graph.js';
3
- import { evidenceContextForPhase, requiredLiveReadbackProviders, selectLatestPhaseEvidence } from '../governance-activation/evidence.js';
4
- import { canonicalApprovalEnvelopeHash, evaluateApprovalForTransitionPlan, transitionPlanForPhase } from '../governance-activation/approvals.js';
5
- import { planDigestFor } from '../governance-activation/transitions.js';
1
+ import { canonicalJson, canonicalSha256, sha256Hex } from '../domain/governance/activation/canonical-json.js';
2
+ import { currentActivationIdentity, canonicalPhaseGraph } from '../domain/governance/activation/graph.js';
3
+ import { canonicalApprovalEnvelopeHash, evaluateApprovalForTransitionPlan, transitionPlanForPhase } from '../domain/governance/activation/approvals.js';
4
+ import { inspectCurrentActivationEvidence } from '../governance-activation/read-only.js';
6
5
  import { governanceChangeMetadataFileName, validateGovernanceChangeMetadata } from '../governance-activation/source-of-truth.js';
6
+ import { phaseIds } from '../domain/governance/activation/types.js';
7
7
  import { loadAssessmentCatalog } from './catalog.js';
8
- import { inspectAssessmentGit, inspectAssessmentProject, repositoryName } from './project.js';
8
+ import { inspectAssessmentProject, ordinaryGitAssessmentProject } from './project.js';
9
+ import { inspectAssessmentGit, repositoryName } from '../adapters/git/governance-assessment.js';
9
10
  import { AssessmentFiles, AssessmentInputError, parseAssessmentJson } from './readers.js';
10
11
  import { parseAssessmentWorkflow } from './yaml.js';
11
12
  import { collectLiveAssessment } from './live.js';
12
- import { classifyFinding, assembleAssessmentReport } from './report.js';
13
- import { actionReferences, failOpenFlags, pinnedActions, protectedRefs, requiredCheckContexts, requiredContextBindings, securityPipeline, singleMaintainer, tagControls, workflowPermissions, observedRequiredContexts } from './predicates.js';
14
- import { isRecord, jsonValue, notObserved, observed, sanitizeAssessmentText, source } from './sanitize.js';
13
+ import { classifyFinding, assembleAssessmentReport } from '../domain/governance/assessment/report.js';
14
+ import { actionReferences, effectiveProtectedRefs, effectiveRequiredContextBindings, failOpenFlags, pinnedActions, protectedRefs, requiredCheckContexts, requiredContextBindings, runnerAlignment, securityPipeline, singleMaintainer, tagControls, workflowPermissions, observedRequiredContexts } from '../domain/governance/assessment/predicates.js';
15
+ import { isRecord, jsonValue, notObserved, observed, sanitizeAssessmentText, source } from '../domain/governance/assessment/sanitize.js';
15
16
  const documentationPaths = [
16
17
  ['CONTRIBUTING.md'], ['docs', 'operations', 'github-governance.md'],
17
18
  ['docs', 'security', 'scanning.md'], ['docs', 'operations', 'alerting.md'],
18
19
  ['docs', 'operations', 'service-health.md'], ['docs', 'security', 'audit-evidence.md'],
19
20
  ['docs', 'ai-acceptable-use.md']
20
21
  ];
22
+ function activationAuthorityFingerprint(inspection) {
23
+ if (inspection.status === 'not-started') {
24
+ return canonicalSha256({ status: inspection.status });
25
+ }
26
+ const firstContext = inspection.contexts[phaseIds[0]];
27
+ const stable = JSON.parse(JSON.stringify({
28
+ status: inspection.status,
29
+ state: inspection.state,
30
+ snapshot: inspection.snapshot,
31
+ records: inspection.records,
32
+ reviewedPlans: firstContext.reviewedPlans ?? [],
33
+ selections: inspection.selections
34
+ }));
35
+ return canonicalSha256(stable);
36
+ }
21
37
  async function localFacts(files, project, capturedAt) {
22
38
  const workflowParts = await files.list(['.github', 'workflows'], ['.yml', '.yaml']);
23
39
  const workflows = [];
@@ -76,6 +92,15 @@ async function localFacts(files, project, capturedAt) {
76
92
  throw new Error('Active governance metadata does not match the recorded change and identity.');
77
93
  }
78
94
  baseline = metadata.baselineSha === '0'.repeat(64) ? null : metadata.baselineSha;
95
+ if (baseline && project.inputSnapshot && baseline !== project.inputSnapshot.baselineSha) {
96
+ project.diagnostics.push({
97
+ code: 'current-input-mismatch',
98
+ severity: 'warning',
99
+ source: parts.join('/'),
100
+ message: 'The recorded governance baseline does not match the independently recomputed current input snapshot; evidence-backed scope is withheld.'
101
+ });
102
+ baseline = null;
103
+ }
79
104
  }
80
105
  catch (error) {
81
106
  project.diagnostics.push({
@@ -97,58 +122,45 @@ async function localFacts(files, project, capturedAt) {
97
122
  };
98
123
  }
99
124
  function boundPlan(project, phaseId, now) {
100
- if (!project.state || !project.bindingBaseline || project.identity.availability !== 'known')
125
+ const currentContext = project.evidenceContexts?.[phaseId];
126
+ const selection = project.activationSelections?.[phaseId];
127
+ const selected = selection?.issues.length === 0 ? selection.selected : null;
128
+ const payload = selected?.payload;
129
+ if (!project.state || !currentContext || !selected ||
130
+ !isRecord(payload) || typeof payload.planDigest !== 'string' ||
131
+ typeof payload.savedPlanDigest !== 'string' ||
132
+ project.identity.availability !== 'known')
101
133
  return null;
102
- const candidates = project.plans.filter((plan) => plan.phaseId === phaseId && plan.baselineDigest === project.bindingBaseline &&
134
+ const candidates = (currentContext.reviewedPlans ?? []).filter((plan) => plan.phaseId === phaseId &&
135
+ plan.planDigest === payload.planDigest &&
136
+ canonicalSha256(plan) === payload.savedPlanDigest &&
137
+ plan.baselineDigest === currentContext.baselineSha &&
103
138
  canonicalJson(plan.identity) === canonicalJson(currentActivationIdentity) &&
104
139
  Date.parse(plan.createdAt) <= now.getTime() &&
105
140
  Date.parse(plan.createdAt) <= Date.parse(project.state.phases[phaseId].updatedAt)).sort((a, b) => Date.parse(b.createdAt) - Date.parse(a.createdAt));
106
141
  const plan = candidates[0];
107
142
  if (!plan || plan.baselineDigest === '0'.repeat(64) || plan.inputDigest === '1'.repeat(64) ||
143
+ plan.baselineDigest !== currentContext.baselineSha ||
144
+ plan.inputDigest !== currentContext.inputDigest ||
145
+ plan.transitionDigest !== currentContext.transition.transitionDigest ||
108
146
  candidates.some((candidate) => candidate.createdAt === plan.createdAt && candidate.planDigest !== plan.planDigest))
109
147
  return null;
110
- const phase = canonicalPhaseGraph.phases.find((entry) => entry.id === phaseId);
111
- if (!phase)
112
- return null;
113
- const authority = transitionPlanForPhase(phase, project.state, {
114
- phaseId, baselineSha: plan.baselineDigest, inputDigest: plan.inputDigest, transitionDigest: plan.transitionDigest
115
- });
116
- if (plan.planDigest !== planDigestFor({
117
- phase, transitionDigest: plan.transitionDigest, operations: plan.operations, approvalPlanDigest: authority.planDigest
118
- }))
119
- return null;
120
148
  return plan;
121
149
  }
122
150
  export function selectBoundAssessmentEvidence(project, phaseId, now) {
123
151
  const plan = boundPlan(project, phaseId, now);
124
- if (!plan || !project.state)
152
+ const selection = project.activationSelections?.[phaseId];
153
+ const selected = selection?.issues.length === 0 ? selection.selected : null;
154
+ if (!plan || !project.state || !selected ||
155
+ selected.header.result !== project.state.phases[phaseId].state)
125
156
  return null;
126
- if (new Set(project.evidence.map((record) => record.evidenceId)).size !== project.evidence.length)
127
- return null;
128
- const phase = canonicalPhaseGraph.phases.find((entry) => entry.id === phaseId);
129
- const references = project.state.phases[phaseId].evidence;
130
- const candidates = project.evidence.filter((record) => record.header.phaseId === phaseId &&
131
- references.some((reference) => reference.phaseId === phaseId && reference.evidenceId === record.evidenceId &&
132
- reference.headerDigest === canonicalSha256(record.header) && reference.result === record.header.result));
133
- const selected = selectLatestPhaseEvidence(candidates, evidenceContextForPhase(phaseId, {
134
- repositoryId: project.state.repository.id, identity: currentActivationIdentity,
135
- phaseGraphHash: currentActivationIdentity.phaseGraphHash, now,
136
- baselineSha: plan.baselineDigest, inputDigest: plan.inputDigest, transitionDigest: plan.transitionDigest,
137
- liveReadbackProviders: phase ? requiredLiveReadbackProviders(phase) : []
138
- })).selected;
139
- if (!selected || selected.header.result !== project.state.phases[phaseId].state)
140
- return null;
141
- const record = candidates.find((entry) => entry.evidenceId === selected.evidenceId &&
142
- canonicalSha256(entry.header) === selected.headerDigest);
143
- return record ? { ...selected, record } : null;
157
+ return selected;
144
158
  }
145
159
  function applicability(control, project, now) {
146
160
  if (control.applicability === 'always')
147
161
  return 'applicable';
148
- if (project.project.workload.kind === 'power-apps-code-app')
149
- return 'inapplicable';
150
162
  if (control.applicability === 'api')
151
- return 'applicable';
163
+ return project.kind === 'liftoff' ? 'applicable' : 'unknown';
152
164
  const discovery = selectBoundAssessmentEvidence(project, 'phase-0-complete', now);
153
165
  if (!project.state || discovery?.header.result !== 'verified')
154
166
  return 'unknown';
@@ -156,41 +168,81 @@ function applicability(control, project, now) {
156
168
  ? project.state.applicability.privateStagingDast
157
169
  : project.state.applicability.statePath === 'bootstrap-local') ? 'applicable' : 'inapplicable';
158
170
  }
171
+ function approvalBindsRepository(project, approval, repository, now) {
172
+ const currentBaseline = project.inputSnapshot?.baselineSha ??
173
+ project.bindingBaseline;
174
+ if (!project.state || !currentBaseline)
175
+ return false;
176
+ const plan = boundPlan(project, approval.phaseId, now);
177
+ const phase = canonicalPhaseGraph.phases.find((entry) => entry.id === approval.phaseId);
178
+ const authority = plan && phase ? transitionPlanForPhase(phase, project.state, {
179
+ phaseId: phase.id,
180
+ baselineSha: plan.baselineDigest,
181
+ inputDigest: plan.inputDigest,
182
+ transitionDigest: plan.transitionDigest
183
+ }) : null;
184
+ return approval.baselineSha === currentBaseline &&
185
+ project.identity.availability === 'known' &&
186
+ Date.parse(approval.approvedAt) <= now.getTime() &&
187
+ Date.parse(approval.expiresAt) > now.getTime() &&
188
+ project.state.phases[approval.phaseId].approvals.includes(approval.id) &&
189
+ Boolean(plan && authority && phase?.approvalGate.required) &&
190
+ authority?.planDigest === approval.planDigest &&
191
+ !evaluateApprovalForTransitionPlan(authority, [approval], { now }).approvalRequired &&
192
+ plan.approval.envelopeId === approval.id &&
193
+ plan.approval.envelopeHash === canonicalApprovalEnvelopeHash(approval) &&
194
+ approval.destinations.some((destination) => destination.type === 'repository' &&
195
+ (destination.repository ?? destination.identity).toLowerCase() === repository.toLowerCase());
196
+ }
159
197
  export function resolveAssessmentLiveScope(project, git, now) {
160
- const stateRepo = project.state ? repositoryName(project.state.repository.name, project.state.repository.id) : null;
161
- let repository = git.originState === 'unavailable' ? null : git.repository ?? stateRepo;
162
- if (git.repository && stateRepo) {
163
- if (`${git.repository.owner}/${git.repository.name}`.toLowerCase() !== `${stateRepo.owner}/${stateRepo.name}`.toLowerCase()) {
164
- repository = null;
165
- project.diagnostics.push({ code: 'repository-binding-conflict', severity: 'warning', source: 'Git/activation state', message: 'Git origin and recorded repository disagree; live collection is withheld.' });
198
+ let repository = git.originState === 'verified' ? git.repository : null;
199
+ let remoteBindingVerified = false;
200
+ if (git.repository && project.state?.remoteBinding) {
201
+ const remote = project.state.remoteBinding;
202
+ const bound = repositoryName(remote.name, remote.id);
203
+ const matchingPush = git.pushUrls.length === 1 &&
204
+ git.pushUrls[0] === remote.pushUrl &&
205
+ project.inputSnapshot?.git.pushUrls.length === 1 &&
206
+ project.inputSnapshot.git.pushUrls[0] === remote.pushUrl;
207
+ if (!bound ||
208
+ `${git.repository.owner}/${git.repository.name}`.toLowerCase() !==
209
+ `${bound.owner}/${bound.name}`.toLowerCase() ||
210
+ !matchingPush) {
211
+ project.diagnostics.push({
212
+ code: 'repository-binding-conflict',
213
+ severity: 'warning',
214
+ source: 'Git/activation state',
215
+ message: 'Git fetch/push origin and the verified remote repository binding disagree; evidence-backed provider scope is withheld.'
216
+ });
217
+ }
218
+ else {
219
+ repository = { ...git.repository, id: bound.id };
220
+ remoteBindingVerified = true;
166
221
  }
167
- else
168
- repository = { ...git.repository, id: stateRepo.id };
169
222
  }
170
223
  const scope = {
171
- repository, refs: ['develop', 'main'],
172
- environments: project.project.workload.kind === 'power-apps-code-app' ? [] : [...project.project.workload.environments],
224
+ repository,
225
+ refs: repository ? ['develop', 'main'] : [],
226
+ ...(repository ? { refPrefixes: ['release/', 'hotfix/'] } : {}),
227
+ environments: project.project ? [...project.project.workload.environments] : [],
173
228
  runner: null, azure: []
174
229
  };
175
230
  if (!repository || !project.state)
176
231
  return scope;
232
+ if (!remoteBindingVerified) {
233
+ project.diagnostics.push({
234
+ code: 'remote-binding-unavailable',
235
+ severity: 'warning',
236
+ source: 'activation state',
237
+ message: 'No matching verified remote repository binding is available; evidence-backed runner and Azure reads are withheld.'
238
+ });
239
+ return scope;
240
+ }
177
241
  const fullName = `${repository.owner}/${repository.name}`;
242
+ const azureBindings = new Map();
243
+ const conflictingAzureBindings = new Set();
178
244
  for (const approval of project.approvals) {
179
- const plan = boundPlan(project, approval.phaseId, now);
180
- const phase = canonicalPhaseGraph.phases.find((entry) => entry.id === approval.phaseId);
181
- const authority = plan && phase ? transitionPlanForPhase(phase, project.state, {
182
- phaseId: phase.id, baselineSha: plan.baselineDigest, inputDigest: plan.inputDigest, transitionDigest: plan.transitionDigest
183
- }) : null;
184
- if (!project.bindingBaseline || approval.baselineSha !== project.bindingBaseline ||
185
- project.identity.availability !== 'known' ||
186
- Date.parse(approval.approvedAt) > now.getTime() ||
187
- Date.parse(approval.expiresAt) <= now.getTime() ||
188
- !project.state.phases[approval.phaseId].approvals.includes(approval.id) ||
189
- !plan || !authority || !phase?.approvalGate.required || authority.planDigest !== approval.planDigest ||
190
- evaluateApprovalForTransitionPlan(authority, [approval], { now }).approvalRequired ||
191
- plan.approval.envelopeId !== approval.id ||
192
- plan.approval.envelopeHash !== canonicalApprovalEnvelopeHash(approval) ||
193
- !approval.destinations.some((destination) => destination.type === 'repository' && (destination.repository ?? destination.identity).toLowerCase() === fullName.toLowerCase()))
245
+ if (!approvalBindsRepository(project, approval, fullName, now))
194
246
  continue;
195
247
  const environments = approval.destinations.filter((destination) => destination.type === 'environment' &&
196
248
  ['dev', 'staging', 'prod'].includes(destination.identity)).map((destination) => destination.identity);
@@ -199,22 +251,79 @@ export function resolveAssessmentLiveScope(project, git, now) {
199
251
  const environment = environments[0];
200
252
  if (environment !== 'dev' && environment !== 'staging' && environment !== 'prod')
201
253
  continue;
202
- for (const resource of approval.resources) {
203
- const match = resource.identity.match(/^\/subscriptions\/([a-f0-9-]{36})\/resourceGroups\/[^/]+\/providers\/([A-Za-z0-9.]+)\/([A-Za-z0-9]+)\/[^/]+(?:\/[A-Za-z0-9]+\/[^/]+)*$/iu);
204
- if (!match || !approval.destinations.some((destination) => destination.type === 'subscription' && (destination.subscriptionId ?? destination.identity).toLowerCase() === match[1].toLowerCase()))
254
+ const selected = selectBoundAssessmentEvidence(project, approval.phaseId, now);
255
+ const payload = selected?.payload;
256
+ const assessmentScope = isRecord(payload) && isRecord(payload.assessmentScope)
257
+ ? payload.assessmentScope
258
+ : null;
259
+ if (!assessmentScope || !Array.isArray(assessmentScope.azure)) {
260
+ if (approval.resources.some((resource) => resource.identity.startsWith('/subscriptions/')) &&
261
+ !project.diagnostics.some((entry) => entry.code === 'unbound-resource-role' && entry.source === approval.phaseId)) {
262
+ project.diagnostics.push({
263
+ code: 'unbound-resource-role',
264
+ severity: 'warning',
265
+ source: approval.phaseId,
266
+ message: 'Approved ARM resources lacked a current body-committed evidence payload with explicit assessment environment and role; Azure reads were withheld.'
267
+ });
268
+ }
269
+ continue;
270
+ }
271
+ for (const value of assessmentScope.azure) {
272
+ if (!isRecord(value) ||
273
+ Object.keys(value).some((key) => ![
274
+ 'subscriptionId', 'environment', 'resourceId', 'resourceType', 'role'
275
+ ].includes(key)) ||
276
+ typeof value.subscriptionId !== 'string' ||
277
+ value.environment !== environment ||
278
+ typeof value.resourceId !== 'string' ||
279
+ typeof value.resourceType !== 'string' ||
280
+ !['state', 'application', 'runner-network'].includes(String(value.role))) {
205
281
  continue;
206
- const role = ['remote-ready', 'remote-import-verified'].includes(approval.phaseId) ? 'state'
207
- : ['bootstrap-local', 'runner-ready', 'private-backend-proof'].includes(approval.phaseId) ? 'runner-network' : 'application';
208
- const resourceSegments = resource.identity.split('/').slice(6);
209
- scope.azure.push({
210
- subscriptionId: match[1], environment, resourceId: resource.identity,
211
- resourceType: [resourceSegments[0], ...resourceSegments.slice(1).filter((_, index) => index % 2 === 0)].join('/'), role
212
- });
282
+ }
283
+ const subscriptionId = value.subscriptionId;
284
+ const resourceId = value.resourceId;
285
+ const resourceType = value.resourceType;
286
+ const match = resourceId.match(/^\/subscriptions\/([a-f0-9-]{36})\/resourceGroups\/[^/]+\/providers\/([A-Za-z0-9.]+)\/([A-Za-z0-9]+)\/[^/]+(?:\/[A-Za-z0-9]+\/[^/]+)*$/iu);
287
+ if (!match ||
288
+ match[1].toLowerCase() !== subscriptionId.toLowerCase() ||
289
+ !approval.resources.some((resource) => resource.identity.toLowerCase() === resourceId.toLowerCase()) ||
290
+ !approval.destinations.some((destination) => destination.type === 'subscription' &&
291
+ (destination.subscriptionId ?? destination.identity).toLowerCase() === subscriptionId.toLowerCase())) {
292
+ continue;
293
+ }
294
+ const binding = {
295
+ subscriptionId,
296
+ environment: environment,
297
+ resourceId,
298
+ resourceType,
299
+ role: value.role
300
+ };
301
+ const key = binding.resourceId.toLowerCase();
302
+ const previous = azureBindings.get(key);
303
+ if (conflictingAzureBindings.has(key) ||
304
+ previous && (previous.environment !== binding.environment ||
305
+ previous.role !== binding.role ||
306
+ previous.resourceType.toLowerCase() !== binding.resourceType.toLowerCase())) {
307
+ azureBindings.delete(key);
308
+ conflictingAzureBindings.add(key);
309
+ project.diagnostics.push({
310
+ code: 'conflicting-resource-binding',
311
+ severity: 'warning',
312
+ source: binding.resourceId,
313
+ message: 'Conflicting body-committed ARM environment, role, or resource-type bindings were excluded before live scope deduplication.'
314
+ });
315
+ continue;
316
+ }
317
+ if (!previous)
318
+ azureBindings.set(key, binding);
213
319
  }
214
320
  }
215
321
  const runnerRecord = selectBoundAssessmentEvidence(project, 'runner-ready', now);
216
- const rawRunner = runnerRecord?.record.payload;
217
- if (runnerRecord?.header.result === 'verified' && isRecord(rawRunner) && rawRunner.kind === 'runner-ready.v1' &&
322
+ const rawRunner = runnerRecord?.payload;
323
+ const runnerApproval = project.approvals.some((approval) => approval.phaseId === 'runner-ready' &&
324
+ approvalBindsRepository(project, approval, fullName, now));
325
+ if (runnerApproval && runnerRecord?.header.result === 'verified' &&
326
+ isRecord(rawRunner) && rawRunner.kind === 'runner-ready.v1' &&
218
327
  rawRunner.organization === repository.owner && Number.isInteger(rawRunner.runnerId) && Number(rawRunner.runnerId) > 0 &&
219
328
  (rawRunner.groupId === null || Number.isInteger(rawRunner.groupId)) &&
220
329
  (rawRunner.networkConfigurationId === null || typeof rawRunner.networkConfigurationId === 'string')) {
@@ -224,7 +333,7 @@ export function resolveAssessmentLiveScope(project, git, now) {
224
333
  networkConfigurationId: typeof rawRunner.networkConfigurationId === 'string' ? rawRunner.networkConfigurationId : null
225
334
  };
226
335
  }
227
- scope.azure = [...new Map(scope.azure.map((binding) => [binding.resourceId.toLowerCase(), binding])).values()]
336
+ scope.azure = [...azureBindings.values()]
228
337
  .sort((a, b) => a.resourceId.localeCompare(b.resourceId, 'en'));
229
338
  return scope;
230
339
  }
@@ -252,6 +361,34 @@ function livePredicate(live, key, evaluate) {
252
361
  converted.facts = observation.value;
253
362
  return converted;
254
363
  }
364
+ function partialLivePredicate(live, key, evaluate) {
365
+ const observation = live.observations[key];
366
+ if (!observation) {
367
+ return {
368
+ observation: notObserved(`Live ${key} was not collected.`),
369
+ provenDifference: false
370
+ };
371
+ }
372
+ if (observation.availability === 'observed') {
373
+ return {
374
+ observation: livePredicate(live, key, evaluate),
375
+ provenDifference: false
376
+ };
377
+ }
378
+ if (observation.facts !== undefined) {
379
+ const evaluated = evaluate(observation.facts);
380
+ if (evaluated.value === false) {
381
+ return {
382
+ observation: {
383
+ ...observation,
384
+ reason: `${observation.reason ?? 'Live collection was incomplete.'} Independently observed facts prove a difference: ${evaluated.reason}`
385
+ },
386
+ provenDifference: true
387
+ };
388
+ }
389
+ }
390
+ return { observation, provenDifference: false };
391
+ }
255
392
  function bool(value, reason) { return { value, reason }; }
256
393
  function rows(value) {
257
394
  return Array.isArray(value) && value.every(isRecord) ? value : null;
@@ -268,6 +405,18 @@ export function findAssessmentException(control, approvals, scope, baseline, res
268
405
  (scope.environment === null || approval.destinations.some((entry) => entry.type === 'environment' && entry.identity === scope.environment)));
269
406
  return found ? { id: found.id, expiresAt: found.expiresAt, envelopeDigest: canonicalApprovalEnvelopeHash(found) } : null;
270
407
  }
408
+ export function rejectedAssessmentExceptionDiagnostic(control, approvals, exception) {
409
+ if (exception !== null ||
410
+ !approvals.some((approval) => approval.policyExceptions.includes(control.id))) {
411
+ return null;
412
+ }
413
+ return {
414
+ code: 'rejected-exception',
415
+ severity: 'warning',
416
+ source: control.id,
417
+ message: 'A recorded exception was rejected because its current identity, baseline, scope, resource, approval time, or expiry did not match this finding.'
418
+ };
419
+ }
271
420
  function evidenceObservation(project, git, capturedAt) {
272
421
  if (!project.state)
273
422
  return notObserved('No compatible activation state is available.');
@@ -288,14 +437,78 @@ function evidenceObservation(project, git, capturedAt) {
288
437
  return notObserved('Baseline/setup progress, approvals, applicability and current readback are not all established.');
289
438
  return observed(true, source('evidence', 'governance/evidence', capturedAt, project.evidence.map((record) => record.header.phaseId)));
290
439
  }
440
+ function invalidateUnstableObservations(findings, kinds, reason) {
441
+ for (const finding of findings) {
442
+ if (finding.applicability === 'inapplicable')
443
+ continue;
444
+ let invalidated = false;
445
+ for (const layer of finding.requiredProof) {
446
+ const observation = finding.observations[layer];
447
+ if (observation?.source && kinds.has(observation.source.kind)) {
448
+ finding.observations[layer] = notObserved(reason);
449
+ invalidated = true;
450
+ }
451
+ }
452
+ if (!invalidated)
453
+ continue;
454
+ finding.exception = null;
455
+ finding.missingProof = finding.requiredProof.filter((layer) => finding.observations[layer]?.availability === 'not-observed');
456
+ const remaining = finding.requiredProof
457
+ .map((layer) => finding.observations[layer])
458
+ .filter((observation) => observation !== undefined);
459
+ const absent = remaining.some((observation) => observation.availability === 'missing');
460
+ const differs = remaining.some((observation) => observation.availability === 'observed' &&
461
+ canonicalJson(observation.value) !== canonicalJson(finding.expected));
462
+ finding.classification = differs
463
+ ? 'conflicting'
464
+ : absent
465
+ ? 'missing'
466
+ : 'not-observed';
467
+ finding.reasons.push(reason);
468
+ }
469
+ }
470
+ function invalidateChangedActivationAuthority(findings, controls) {
471
+ const controlsById = new Map(controls.map((control) => [
472
+ control.id,
473
+ control
474
+ ]));
475
+ for (const finding of findings) {
476
+ const control = controlsById.get(finding.controlId);
477
+ const evidenceDerivedApplicability = control?.applicability === 'private-dast' ||
478
+ control?.applicability === 'state-path';
479
+ if (finding.applicability === 'inapplicable' &&
480
+ !evidenceDerivedApplicability ||
481
+ !(evidenceDerivedApplicability ||
482
+ finding.requiredProof.includes('evidence') ||
483
+ finding.controlId.startsWith('azure.') ||
484
+ finding.controlId.startsWith('runner.') ||
485
+ finding.controlId.startsWith('evidence.'))) {
486
+ continue;
487
+ }
488
+ if (evidenceDerivedApplicability) {
489
+ finding.applicability = 'unknown';
490
+ }
491
+ finding.classification = 'not-observed';
492
+ finding.exception = null;
493
+ finding.missingProof = [...finding.requiredProof];
494
+ finding.reasons.push('Current activation inputs, evidence references, evidence bodies, or reviewed plans changed during collection; evidence-backed scope and results were withheld.');
495
+ for (const layer of finding.requiredProof) {
496
+ finding.observations[layer] = notObserved('Activation authority changed during collection.');
497
+ }
498
+ }
499
+ }
291
500
  async function managedFindings(control, project, files, scope, capturedAt) {
292
501
  const findings = [];
293
502
  if (project.renderedCore.length === 0) {
294
503
  return [classifyFinding({
295
504
  control, scope, applicability: 'applicable',
296
505
  observations: {
297
- recorded: notObserved('Historical agent selection is not recorded.'),
298
- declared: notObserved('The current handoff cannot be rendered without inferring agent configuration.')
506
+ recorded: notObserved(project.kind === 'git'
507
+ ? 'Ordinary Git repositories have no recorded Liftoff ownership inventory.'
508
+ : 'Historical agent selection is not recorded.'),
509
+ declared: notObserved(project.kind === 'git'
510
+ ? 'No Liftoff managed handoff is inferred for an ordinary Git repository.'
511
+ : 'The current handoff cannot be rendered without inferring agent configuration.')
299
512
  }
300
513
  })];
301
514
  }
@@ -349,7 +562,22 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
349
562
  const branch = repository?.availability === 'observed' && isRecord(repository.value) && typeof repository.value.defaultBranch === 'string'
350
563
  ? repository.value.defaultBranch : null;
351
564
  observations.declared = declaredRules((value) => protectedRefs(value, project.state?.repository.defaultBranch ?? null));
352
- observations.live = livePredicate(live, 'github.rulesets', (value) => protectedRefs(value, branch));
565
+ const rules = live.observations['github.rulesets'];
566
+ const branches = live.observations['github.branches'];
567
+ const families = live.observations['github.ref-families'];
568
+ if (rules?.availability === 'observed' &&
569
+ branches?.availability === 'observed' &&
570
+ families?.availability === 'observed') {
571
+ observations.live = predicateObservation(effectiveProtectedRefs(rules.value, branches.value, families.value, branch), rules.source);
572
+ observations.live.facts = jsonValue({
573
+ rulesets: rules.value,
574
+ branches: branches.value,
575
+ refFamilies: families.value
576
+ });
577
+ }
578
+ else {
579
+ observations.live = notObserved('Complete repository/inherited rulesets, classic/effective branch protection, and bounded release/hotfix enumeration are required.');
580
+ }
353
581
  break;
354
582
  }
355
583
  case 'single-maintainer':
@@ -381,14 +609,27 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
381
609
  : contexts.length ? predicateObservation(bool(true, `Declared contexts: ${contexts.map((entry) => entry.name).join(', ')}`), facts.ruleSource)
382
610
  : absent('No required status check contexts were declared.', facts.ruleSource);
383
611
  const rules = live.observations['github.rulesets'];
612
+ const branches = live.observations['github.branches'];
613
+ const families = live.observations['github.ref-families'];
384
614
  const repository = live.observations['github.repository'];
385
615
  const branch = repository?.availability === 'observed' && isRecord(repository.value) && typeof repository.value.defaultBranch === 'string'
386
616
  ? repository.value.defaultBranch : null;
387
- const declaredBindings = requiredContextBindings(facts.rulesets, liveScope.refs, branch);
388
- const enforcedBindings = rules?.availability === 'observed' ? requiredContextBindings(rules.value, liveScope.refs, branch) : null;
617
+ const familyRefs = families?.availability === 'observed' && isRecord(families.value) &&
618
+ Array.isArray(families.value.refs)
619
+ ? families.value.refs.filter((value) => typeof value === 'string')
620
+ : [];
621
+ const assessedRefs = [...new Set([...liveScope.refs, ...familyRefs])].sort();
622
+ const comparisonRefs = assessedRefs.length ? assessedRefs : ['develop', 'main'];
623
+ const declaredBindings = requiredContextBindings(facts.rulesets, comparisonRefs, branch);
624
+ const rulesetBindings = rules?.availability === 'observed'
625
+ ? requiredContextBindings(rules.value, comparisonRefs, branch)
626
+ : null;
627
+ const enforcedBindings = rules?.availability === 'observed' && branches?.availability === 'observed'
628
+ ? effectiveRequiredContextBindings(rules.value, branches.value, comparisonRefs, branch)
629
+ : rulesetBindings;
389
630
  observations.declared.facts = jsonValue(declaredBindings);
390
- const bindingsDiffer = Boolean(contexts?.length && declaredBindings && enforcedBindings &&
391
- canonicalJson(declaredBindings) !== canonicalJson(enforcedBindings));
631
+ const bindingsDiffer = Boolean(contexts?.length && declaredBindings && rulesetBindings &&
632
+ canonicalJson(declaredBindings) !== canonicalJson(rulesetBindings));
392
633
  if (bindingsDiffer) {
393
634
  difference = 'conflicting';
394
635
  const checks = live.observations['github.checks'];
@@ -398,8 +639,11 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
398
639
  : notObserved(`${reason} Check-run proof remains unobserved: ${checks?.reason ?? 'not collected'}`, rules?.source ?? null);
399
640
  }
400
641
  else {
401
- observations.live = rules?.availability === 'observed' && declaredBindings && enforcedBindings
402
- ? livePredicate(live, 'github.checks', (value) => observedRequiredContexts(rules.value, value, branch))
642
+ observations.live = rules?.availability === 'observed' &&
643
+ families?.availability === 'observed' &&
644
+ declaredBindings &&
645
+ enforcedBindings
646
+ ? livePredicate(live, 'github.checks', (value) => observedRequiredContexts(rules.value, value, branch, branches?.value))
403
647
  : notObserved('Live rule and exact commit-bound check observations are required.');
404
648
  }
405
649
  observations.live.facts = jsonValue({
@@ -457,19 +701,22 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
457
701
  break;
458
702
  case 'runner': {
459
703
  observations.recorded = liveScope.runner ? observed(true, source('evidence', 'runner-ready repository binding', capturedAt, jsonValue(liveScope.runner))) : notObserved('No current, exact runner/group/network binding is available.');
460
- observations.live = livePredicate(live, 'github.runner', (value) => bool(isRecord(value) && value.repositoryAssigned === true
461
- && value.groupId === liveScope.runner?.groupId && value.runnerId === liveScope.runner?.runnerId ? true : null, 'Exact repository/group/network assignment, labels and runner capacity must be observed.'));
704
+ observations.live = livePredicate(live, 'github.runner', (value) => runnerAlignment(value, scope.repository));
462
705
  break;
463
706
  }
464
- case 'providers':
465
- observations.live = livePredicate(live, 'azure.providers', (value) => {
707
+ case 'providers': {
708
+ const evaluation = partialLivePredicate(live, 'azure.providers', (value) => {
466
709
  const providers = rows(value);
467
710
  return bool(!providers?.length ? null : providers.every((entry) => entry.registrationState === 'Registered'), 'Every explicitly required namespace must have terminal Registered readback.');
468
711
  });
712
+ observations.live = evaluation.observation;
713
+ if (evaluation.provenDifference)
714
+ difference = 'conflicting';
469
715
  expected = true;
470
716
  break;
471
- case 'storage':
472
- observations.live = livePredicate(live, 'azure.resources', (value) => {
717
+ }
718
+ case 'storage': {
719
+ const evaluation = partialLivePredicate(live, 'azure.resources', (value) => {
473
720
  const storage = rows(value)?.filter((entry) => String(entry.resourceType).toLowerCase() === 'microsoft.storage/storageaccounts');
474
721
  if (!storage?.length)
475
722
  return bool(null, 'No explicit environment/role-bound storage observation is available.');
@@ -481,11 +728,15 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
481
728
  });
482
729
  return bool(values.includes(false) ? false : values.includes(null) ? null : true, 'State storage requires ZRS; application storage uses Dev LRS and Staging/Production ZRS.');
483
730
  });
731
+ observations.live = evaluation.observation;
732
+ if (evaluation.provenDifference)
733
+ difference = 'conflicting';
484
734
  expected = true;
485
735
  break;
486
- case 'network':
736
+ }
737
+ case 'network': {
487
738
  observations.recorded = liveScope.azure.some((entry) => entry.role === 'runner-network') ? observed(true, source('evidence', 'approved Staging network bindings', capturedAt, jsonValue(liveScope.azure))) : notObserved('No approved Staging network bindings were available.');
488
- observations.live = livePredicate(live, 'azure.resources', (value) => {
739
+ const evaluation = partialLivePredicate(live, 'azure.resources', (value) => {
489
740
  const network = rows(value)?.filter((entry) => entry.role === 'runner-network');
490
741
  if (!network?.length)
491
742
  return bool(null, 'No bound runner-network readback is available.');
@@ -494,7 +745,11 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
494
745
  return bool(false, 'A runner subnet still enables implicit default outbound access.');
495
746
  return bool(null, 'Full subnet, route, DNS and exclusive NAT/Firewall proof is required; observed metadata alone is insufficient.');
496
747
  });
748
+ observations.live = evaluation.observation;
749
+ if (evaluation.provenDifference)
750
+ difference = 'conflicting';
497
751
  break;
752
+ }
498
753
  case 'evidence':
499
754
  observations.evidence = evidenceObservation(project, git, capturedAt);
500
755
  break;
@@ -505,9 +760,15 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
505
760
  for (const layer of control.proofLayers)
506
761
  observations[layer] = notObserved(`No supported evaluator exists for ${control.id}; the required proof is not inferred.`);
507
762
  }
763
+ const exception = findAssessmentException(control, project.approvals, scope, facts.baseline, exceptionResource, now);
764
+ const exceptionDiagnostic = rejectedAssessmentExceptionDiagnostic(control, project.approvals, exception);
765
+ if (exceptionDiagnostic &&
766
+ !project.diagnostics.some((entry) => entry.code === 'rejected-exception' && entry.source === control.id)) {
767
+ project.diagnostics.push(exceptionDiagnostic);
768
+ }
508
769
  return classifyFinding({
509
770
  control, scope, expected, applicability: applicability(control, project, now), observations, difference,
510
- exception: findAssessmentException(control, project.approvals, scope, facts.baseline, exceptionResource, now)
771
+ exception
511
772
  });
512
773
  }
513
774
  export async function assessGovernance(projectRoot, options = {}) {
@@ -522,7 +783,77 @@ export async function assessGovernance(projectRoot, options = {}) {
522
783
  try {
523
784
  const loaded = loadAssessmentCatalog();
524
785
  target = loaded.target;
525
- const project = await inspectAssessmentProject(files);
786
+ let project;
787
+ let git;
788
+ let initialActivationInspection = null;
789
+ let initialActivationFingerprint = null;
790
+ try {
791
+ project = await inspectAssessmentProject(files);
792
+ git = await inspectAssessmentGit(projectRoot, options.runner);
793
+ }
794
+ catch (error) {
795
+ if (!(error instanceof AssessmentInputError) || error.code !== 'project-not-found') {
796
+ throw error;
797
+ }
798
+ git = await inspectAssessmentGit(projectRoot, options.runner);
799
+ if (!git.isRepository) {
800
+ throw new AssessmentInputError('project-not-found', 'No Liftoff manifest or valid Git worktree was found at the selected boundary.');
801
+ }
802
+ project = ordinaryGitAssessmentProject();
803
+ }
804
+ if (project.manifest) {
805
+ try {
806
+ const activation = await inspectCurrentActivationEvidence(projectRoot, project.manifest, {
807
+ ...(options.runner ? { runner: options.runner } : {}),
808
+ now: captured
809
+ });
810
+ initialActivationInspection = activation;
811
+ initialActivationFingerprint = activationAuthorityFingerprint(activation);
812
+ if (activation.status === 'inspected') {
813
+ project.state = activation.state;
814
+ project.stateIdentity = jsonValue(activation.state.identity);
815
+ project.identity.stateSource = 'user';
816
+ project.inputSnapshot = activation.snapshot;
817
+ project.evidenceContexts = activation.contexts;
818
+ project.evidence = activation.records;
819
+ project.plans = activation.contexts[phaseIds[0]].reviewedPlans
820
+ ? [...activation.contexts[phaseIds[0]].reviewedPlans]
821
+ : [];
822
+ project.activationSelections = activation.selections;
823
+ for (const [phaseId, selection] of Object.entries(activation.selections)) {
824
+ if (selection.selected && selection.historicalIssues?.length) {
825
+ project.diagnostics.push({
826
+ code: 'historical-evidence-ignored',
827
+ severity: 'info',
828
+ source: phaseId,
829
+ message: sanitizeAssessmentText(selection.historicalIssues.map((issue) => issue.message).join('; '))
830
+ });
831
+ }
832
+ if (selection.issues.length === 0)
833
+ continue;
834
+ project.invalidEvidence = true;
835
+ project.diagnostics.push({
836
+ code: 'invalid-current-evidence',
837
+ severity: 'warning',
838
+ source: phaseId,
839
+ message: sanitizeAssessmentText(selection.issues.map((issue) => issue.message).join('; '))
840
+ });
841
+ }
842
+ }
843
+ }
844
+ catch (error) {
845
+ project.identity.availability = 'unsupported';
846
+ project.identity.stateSource = 'unsupported';
847
+ project.diagnostics.push({
848
+ code: 'activation-history-diagnostic-only',
849
+ severity: 'warning',
850
+ source: 'activation read-only inspection',
851
+ message: sanitizeAssessmentText(error instanceof Error
852
+ ? error.message
853
+ : 'Activation history could not be interpreted as current executable proof.')
854
+ });
855
+ }
856
+ }
526
857
  projectIdentity = project.identity;
527
858
  const disabled = project.identity.profile === 'none';
528
859
  if (disabled)
@@ -531,7 +862,6 @@ export async function assessGovernance(projectRoot, options = {}) {
531
862
  snapshot: { capturedAt: captured.toISOString(), repository: null, localHead: null, worktreeDigest: files.digest(), inputsStable: await files.stable() },
532
863
  findings: [], diagnostics: project.diagnostics, disabled: true
533
864
  });
534
- const git = await inspectAssessmentGit(projectRoot, options.runner);
535
865
  project.diagnostics.push(...git.issues.map((message) => ({
536
866
  code: 'git-not-observed', severity: 'warning', message, source: 'Git metadata'
537
867
  })));
@@ -549,21 +879,40 @@ export async function assessGovernance(projectRoot, options = {}) {
549
879
  findings.push(evaluateControl(control, project, facts, live, git, scope, captured));
550
880
  }
551
881
  const worktreeDigest = files.digest();
552
- const finalGit = await inspectAssessmentGit(projectRoot, options.runner);
553
- const inputsStable = await files.stable() && live.refsStable &&
554
- canonicalJson(git) === canonicalJson(finalGit);
555
- if (!inputsStable) {
556
- for (const finding of findings) {
557
- if (finding.applicability === 'inapplicable')
558
- continue;
559
- finding.classification = 'not-observed';
560
- finding.exception = null;
561
- finding.missingProof = [...finding.requiredProof];
562
- finding.reasons.push('Relevant files or refs changed during collection; rerun assessment for a consistent snapshot.');
563
- for (const layer of finding.requiredProof)
564
- finding.observations[layer] = notObserved('Inputs changed during collection.');
882
+ let activationStable = true;
883
+ if (project.manifest && initialActivationInspection && initialActivationFingerprint) {
884
+ try {
885
+ const finalActivation = await inspectCurrentActivationEvidence(projectRoot, project.manifest, {
886
+ ...(options.runner ? { runner: options.runner } : {}),
887
+ now: captured
888
+ });
889
+ activationStable =
890
+ activationAuthorityFingerprint(finalActivation) ===
891
+ initialActivationFingerprint;
892
+ }
893
+ catch {
894
+ activationStable = false;
565
895
  }
566
896
  }
897
+ const finalGit = await inspectAssessmentGit(projectRoot, options.runner);
898
+ const filesStable = await files.stable();
899
+ const gitStable = canonicalJson(git) === canonicalJson(finalGit);
900
+ const inputsStable = filesStable && gitStable && activationStable;
901
+ if (!filesStable) {
902
+ invalidateUnstableObservations(findings, new Set(['file', 'evidence']), 'Relevant local files changed during collection; rerun assessment for current local proof.');
903
+ }
904
+ if (!gitStable) {
905
+ invalidateUnstableObservations(findings, new Set(['git']), 'Relevant Git metadata changed during collection; rerun assessment for current Git proof.');
906
+ }
907
+ if (!activationStable) {
908
+ invalidateChangedActivationAuthority(findings, loaded.catalog.controls);
909
+ project.diagnostics.push({
910
+ code: 'activation-authority-changed',
911
+ severity: 'warning',
912
+ source: 'activation read-only inspection',
913
+ message: 'Current activation inputs, evidence, state references, or reviewed plans changed during collection; dependent proof was withheld.'
914
+ });
915
+ }
567
916
  return assembleAssessmentReport({
568
917
  projectRoot, mode: options.live ? 'live' : 'local', target, projectIdentity,
569
918
  snapshot: { capturedAt: captured.toISOString(), repository, localHead: git.head, worktreeDigest, inputsStable },