@mc-and-his-agents/loom-installer 0.1.111 → 0.1.113

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 (213) hide show
  1. package/package.json +1 -1
  2. package/payload/manifest.json +425 -425
  3. package/payload/plugin/loom/skills/loom-adopt/.loom-runtime/loom-adopt/SKILL.md +1 -0
  4. package/payload/plugin/loom/skills/loom-adopt/.loom-runtime/loom-init/SKILL.md +2 -0
  5. package/payload/plugin/loom/skills/loom-adopt/.loom-runtime/loom-init/contract.json +4 -0
  6. package/payload/plugin/loom/skills/loom-adopt/.loom-runtime/loom-init/references/output-contract.md +13 -1
  7. package/payload/plugin/loom/skills/loom-adopt/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  8. package/payload/plugin/loom/skills/loom-adopt/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  9. package/payload/plugin/loom/skills/loom-adopt/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  10. package/payload/plugin/loom/skills/loom-adopt/.loom-runtime/shared/scripts/loom_check.py +148 -0
  11. package/payload/plugin/loom/skills/loom-adopt/.loom-runtime/shared/scripts/loom_init.py +523 -215
  12. package/payload/plugin/loom/skills/loom-adopt/SKILL.md +1 -0
  13. package/payload/plugin/loom/skills/loom-build/.loom-runtime/loom-adopt/SKILL.md +1 -0
  14. package/payload/plugin/loom/skills/loom-build/.loom-runtime/loom-init/SKILL.md +2 -0
  15. package/payload/plugin/loom/skills/loom-build/.loom-runtime/loom-init/contract.json +4 -0
  16. package/payload/plugin/loom/skills/loom-build/.loom-runtime/loom-init/references/output-contract.md +13 -1
  17. package/payload/plugin/loom/skills/loom-build/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  18. package/payload/plugin/loom/skills/loom-build/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  19. package/payload/plugin/loom/skills/loom-build/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  20. package/payload/plugin/loom/skills/loom-build/.loom-runtime/shared/scripts/loom_check.py +148 -0
  21. package/payload/plugin/loom/skills/loom-build/.loom-runtime/shared/scripts/loom_init.py +523 -215
  22. package/payload/plugin/loom/skills/loom-handoff/.loom-runtime/loom-adopt/SKILL.md +1 -0
  23. package/payload/plugin/loom/skills/loom-handoff/.loom-runtime/loom-init/SKILL.md +2 -0
  24. package/payload/plugin/loom/skills/loom-handoff/.loom-runtime/loom-init/contract.json +4 -0
  25. package/payload/plugin/loom/skills/loom-handoff/.loom-runtime/loom-init/references/output-contract.md +13 -1
  26. package/payload/plugin/loom/skills/loom-handoff/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  27. package/payload/plugin/loom/skills/loom-handoff/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  28. package/payload/plugin/loom/skills/loom-handoff/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  29. package/payload/plugin/loom/skills/loom-handoff/.loom-runtime/shared/scripts/loom_check.py +148 -0
  30. package/payload/plugin/loom/skills/loom-handoff/.loom-runtime/shared/scripts/loom_init.py +523 -215
  31. package/payload/plugin/loom/skills/loom-init/.loom-runtime/loom-adopt/SKILL.md +1 -0
  32. package/payload/plugin/loom/skills/loom-init/.loom-runtime/loom-init/SKILL.md +2 -0
  33. package/payload/plugin/loom/skills/loom-init/.loom-runtime/loom-init/contract.json +4 -0
  34. package/payload/plugin/loom/skills/loom-init/.loom-runtime/loom-init/references/output-contract.md +13 -1
  35. package/payload/plugin/loom/skills/loom-init/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  36. package/payload/plugin/loom/skills/loom-init/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  37. package/payload/plugin/loom/skills/loom-init/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  38. package/payload/plugin/loom/skills/loom-init/.loom-runtime/shared/scripts/loom_check.py +148 -0
  39. package/payload/plugin/loom/skills/loom-init/.loom-runtime/shared/scripts/loom_init.py +523 -215
  40. package/payload/plugin/loom/skills/loom-init/SKILL.md +2 -0
  41. package/payload/plugin/loom/skills/loom-init/contract.json +4 -0
  42. package/payload/plugin/loom/skills/loom-init/references/output-contract.md +13 -1
  43. package/payload/plugin/loom/skills/loom-merge-ready/.loom-runtime/loom-adopt/SKILL.md +1 -0
  44. package/payload/plugin/loom/skills/loom-merge-ready/.loom-runtime/loom-init/SKILL.md +2 -0
  45. package/payload/plugin/loom/skills/loom-merge-ready/.loom-runtime/loom-init/contract.json +4 -0
  46. package/payload/plugin/loom/skills/loom-merge-ready/.loom-runtime/loom-init/references/output-contract.md +13 -1
  47. package/payload/plugin/loom/skills/loom-merge-ready/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  48. package/payload/plugin/loom/skills/loom-merge-ready/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  49. package/payload/plugin/loom/skills/loom-merge-ready/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  50. package/payload/plugin/loom/skills/loom-merge-ready/.loom-runtime/shared/scripts/loom_check.py +148 -0
  51. package/payload/plugin/loom/skills/loom-merge-ready/.loom-runtime/shared/scripts/loom_init.py +523 -215
  52. package/payload/plugin/loom/skills/loom-pre-review/.loom-runtime/loom-adopt/SKILL.md +1 -0
  53. package/payload/plugin/loom/skills/loom-pre-review/.loom-runtime/loom-init/SKILL.md +2 -0
  54. package/payload/plugin/loom/skills/loom-pre-review/.loom-runtime/loom-init/contract.json +4 -0
  55. package/payload/plugin/loom/skills/loom-pre-review/.loom-runtime/loom-init/references/output-contract.md +13 -1
  56. package/payload/plugin/loom/skills/loom-pre-review/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  57. package/payload/plugin/loom/skills/loom-pre-review/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  58. package/payload/plugin/loom/skills/loom-pre-review/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  59. package/payload/plugin/loom/skills/loom-pre-review/.loom-runtime/shared/scripts/loom_check.py +148 -0
  60. package/payload/plugin/loom/skills/loom-pre-review/.loom-runtime/shared/scripts/loom_init.py +523 -215
  61. package/payload/plugin/loom/skills/loom-resume/.loom-runtime/loom-adopt/SKILL.md +1 -0
  62. package/payload/plugin/loom/skills/loom-resume/.loom-runtime/loom-init/SKILL.md +2 -0
  63. package/payload/plugin/loom/skills/loom-resume/.loom-runtime/loom-init/contract.json +4 -0
  64. package/payload/plugin/loom/skills/loom-resume/.loom-runtime/loom-init/references/output-contract.md +13 -1
  65. package/payload/plugin/loom/skills/loom-resume/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  66. package/payload/plugin/loom/skills/loom-resume/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  67. package/payload/plugin/loom/skills/loom-resume/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  68. package/payload/plugin/loom/skills/loom-resume/.loom-runtime/shared/scripts/loom_check.py +148 -0
  69. package/payload/plugin/loom/skills/loom-resume/.loom-runtime/shared/scripts/loom_init.py +523 -215
  70. package/payload/plugin/loom/skills/loom-retire/.loom-runtime/loom-adopt/SKILL.md +1 -0
  71. package/payload/plugin/loom/skills/loom-retire/.loom-runtime/loom-init/SKILL.md +2 -0
  72. package/payload/plugin/loom/skills/loom-retire/.loom-runtime/loom-init/contract.json +4 -0
  73. package/payload/plugin/loom/skills/loom-retire/.loom-runtime/loom-init/references/output-contract.md +13 -1
  74. package/payload/plugin/loom/skills/loom-retire/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  75. package/payload/plugin/loom/skills/loom-retire/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  76. package/payload/plugin/loom/skills/loom-retire/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  77. package/payload/plugin/loom/skills/loom-retire/.loom-runtime/shared/scripts/loom_check.py +148 -0
  78. package/payload/plugin/loom/skills/loom-retire/.loom-runtime/shared/scripts/loom_init.py +523 -215
  79. package/payload/plugin/loom/skills/loom-review/.loom-runtime/loom-adopt/SKILL.md +1 -0
  80. package/payload/plugin/loom/skills/loom-review/.loom-runtime/loom-init/SKILL.md +2 -0
  81. package/payload/plugin/loom/skills/loom-review/.loom-runtime/loom-init/contract.json +4 -0
  82. package/payload/plugin/loom/skills/loom-review/.loom-runtime/loom-init/references/output-contract.md +13 -1
  83. package/payload/plugin/loom/skills/loom-review/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  84. package/payload/plugin/loom/skills/loom-review/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  85. package/payload/plugin/loom/skills/loom-review/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  86. package/payload/plugin/loom/skills/loom-review/.loom-runtime/shared/scripts/loom_check.py +148 -0
  87. package/payload/plugin/loom/skills/loom-review/.loom-runtime/shared/scripts/loom_init.py +523 -215
  88. package/payload/plugin/loom/skills/loom-spec-review/.loom-runtime/loom-adopt/SKILL.md +1 -0
  89. package/payload/plugin/loom/skills/loom-spec-review/.loom-runtime/loom-init/SKILL.md +2 -0
  90. package/payload/plugin/loom/skills/loom-spec-review/.loom-runtime/loom-init/contract.json +4 -0
  91. package/payload/plugin/loom/skills/loom-spec-review/.loom-runtime/loom-init/references/output-contract.md +13 -1
  92. package/payload/plugin/loom/skills/loom-spec-review/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  93. package/payload/plugin/loom/skills/loom-spec-review/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  94. package/payload/plugin/loom/skills/loom-spec-review/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  95. package/payload/plugin/loom/skills/loom-spec-review/.loom-runtime/shared/scripts/loom_check.py +148 -0
  96. package/payload/plugin/loom/skills/loom-spec-review/.loom-runtime/shared/scripts/loom_init.py +523 -215
  97. package/payload/plugin/loom/skills/loom-story/.loom-runtime/loom-adopt/SKILL.md +1 -0
  98. package/payload/plugin/loom/skills/loom-story/.loom-runtime/loom-init/SKILL.md +2 -0
  99. package/payload/plugin/loom/skills/loom-story/.loom-runtime/loom-init/contract.json +4 -0
  100. package/payload/plugin/loom/skills/loom-story/.loom-runtime/loom-init/references/output-contract.md +13 -1
  101. package/payload/plugin/loom/skills/loom-story/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  102. package/payload/plugin/loom/skills/loom-story/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  103. package/payload/plugin/loom/skills/loom-story/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  104. package/payload/plugin/loom/skills/loom-story/.loom-runtime/shared/scripts/loom_check.py +148 -0
  105. package/payload/plugin/loom/skills/loom-story/.loom-runtime/shared/scripts/loom_init.py +523 -215
  106. package/payload/plugin/loom/skills/shared/references/adoption/deep-existing-repo-default.md +4 -0
  107. package/payload/plugin/loom/skills/shared/references/adoption/repo-companion-contract.md +3 -1
  108. package/payload/plugin/loom/skills/shared/scripts/governance_surface.py +1 -0
  109. package/payload/plugin/loom/skills/shared/scripts/loom_check.py +148 -0
  110. package/payload/plugin/loom/skills/shared/scripts/loom_init.py +523 -215
  111. package/payload/skills/loom-adopt/.loom-runtime/loom-adopt/SKILL.md +1 -0
  112. package/payload/skills/loom-adopt/.loom-runtime/loom-init/SKILL.md +2 -0
  113. package/payload/skills/loom-adopt/.loom-runtime/loom-init/contract.json +4 -0
  114. package/payload/skills/loom-adopt/.loom-runtime/loom-init/references/output-contract.md +13 -1
  115. package/payload/skills/loom-adopt/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  116. package/payload/skills/loom-adopt/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  117. package/payload/skills/loom-adopt/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  118. package/payload/skills/loom-adopt/.loom-runtime/shared/scripts/loom_check.py +148 -0
  119. package/payload/skills/loom-adopt/.loom-runtime/shared/scripts/loom_init.py +523 -215
  120. package/payload/skills/loom-adopt/SKILL.md +1 -0
  121. package/payload/skills/loom-build/.loom-runtime/loom-adopt/SKILL.md +1 -0
  122. package/payload/skills/loom-build/.loom-runtime/loom-init/SKILL.md +2 -0
  123. package/payload/skills/loom-build/.loom-runtime/loom-init/contract.json +4 -0
  124. package/payload/skills/loom-build/.loom-runtime/loom-init/references/output-contract.md +13 -1
  125. package/payload/skills/loom-build/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  126. package/payload/skills/loom-build/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  127. package/payload/skills/loom-build/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  128. package/payload/skills/loom-build/.loom-runtime/shared/scripts/loom_check.py +148 -0
  129. package/payload/skills/loom-build/.loom-runtime/shared/scripts/loom_init.py +523 -215
  130. package/payload/skills/loom-handoff/.loom-runtime/loom-adopt/SKILL.md +1 -0
  131. package/payload/skills/loom-handoff/.loom-runtime/loom-init/SKILL.md +2 -0
  132. package/payload/skills/loom-handoff/.loom-runtime/loom-init/contract.json +4 -0
  133. package/payload/skills/loom-handoff/.loom-runtime/loom-init/references/output-contract.md +13 -1
  134. package/payload/skills/loom-handoff/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  135. package/payload/skills/loom-handoff/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  136. package/payload/skills/loom-handoff/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  137. package/payload/skills/loom-handoff/.loom-runtime/shared/scripts/loom_check.py +148 -0
  138. package/payload/skills/loom-handoff/.loom-runtime/shared/scripts/loom_init.py +523 -215
  139. package/payload/skills/loom-init/.loom-runtime/loom-adopt/SKILL.md +1 -0
  140. package/payload/skills/loom-init/.loom-runtime/loom-init/SKILL.md +2 -0
  141. package/payload/skills/loom-init/.loom-runtime/loom-init/contract.json +4 -0
  142. package/payload/skills/loom-init/.loom-runtime/loom-init/references/output-contract.md +13 -1
  143. package/payload/skills/loom-init/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  144. package/payload/skills/loom-init/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  145. package/payload/skills/loom-init/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  146. package/payload/skills/loom-init/.loom-runtime/shared/scripts/loom_check.py +148 -0
  147. package/payload/skills/loom-init/.loom-runtime/shared/scripts/loom_init.py +523 -215
  148. package/payload/skills/loom-init/SKILL.md +2 -0
  149. package/payload/skills/loom-init/contract.json +4 -0
  150. package/payload/skills/loom-init/references/output-contract.md +13 -1
  151. package/payload/skills/loom-merge-ready/.loom-runtime/loom-adopt/SKILL.md +1 -0
  152. package/payload/skills/loom-merge-ready/.loom-runtime/loom-init/SKILL.md +2 -0
  153. package/payload/skills/loom-merge-ready/.loom-runtime/loom-init/contract.json +4 -0
  154. package/payload/skills/loom-merge-ready/.loom-runtime/loom-init/references/output-contract.md +13 -1
  155. package/payload/skills/loom-merge-ready/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  156. package/payload/skills/loom-merge-ready/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  157. package/payload/skills/loom-merge-ready/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  158. package/payload/skills/loom-merge-ready/.loom-runtime/shared/scripts/loom_check.py +148 -0
  159. package/payload/skills/loom-merge-ready/.loom-runtime/shared/scripts/loom_init.py +523 -215
  160. package/payload/skills/loom-pre-review/.loom-runtime/loom-adopt/SKILL.md +1 -0
  161. package/payload/skills/loom-pre-review/.loom-runtime/loom-init/SKILL.md +2 -0
  162. package/payload/skills/loom-pre-review/.loom-runtime/loom-init/contract.json +4 -0
  163. package/payload/skills/loom-pre-review/.loom-runtime/loom-init/references/output-contract.md +13 -1
  164. package/payload/skills/loom-pre-review/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  165. package/payload/skills/loom-pre-review/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  166. package/payload/skills/loom-pre-review/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  167. package/payload/skills/loom-pre-review/.loom-runtime/shared/scripts/loom_check.py +148 -0
  168. package/payload/skills/loom-pre-review/.loom-runtime/shared/scripts/loom_init.py +523 -215
  169. package/payload/skills/loom-resume/.loom-runtime/loom-adopt/SKILL.md +1 -0
  170. package/payload/skills/loom-resume/.loom-runtime/loom-init/SKILL.md +2 -0
  171. package/payload/skills/loom-resume/.loom-runtime/loom-init/contract.json +4 -0
  172. package/payload/skills/loom-resume/.loom-runtime/loom-init/references/output-contract.md +13 -1
  173. package/payload/skills/loom-resume/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  174. package/payload/skills/loom-resume/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  175. package/payload/skills/loom-resume/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  176. package/payload/skills/loom-resume/.loom-runtime/shared/scripts/loom_check.py +148 -0
  177. package/payload/skills/loom-resume/.loom-runtime/shared/scripts/loom_init.py +523 -215
  178. package/payload/skills/loom-retire/.loom-runtime/loom-adopt/SKILL.md +1 -0
  179. package/payload/skills/loom-retire/.loom-runtime/loom-init/SKILL.md +2 -0
  180. package/payload/skills/loom-retire/.loom-runtime/loom-init/contract.json +4 -0
  181. package/payload/skills/loom-retire/.loom-runtime/loom-init/references/output-contract.md +13 -1
  182. package/payload/skills/loom-retire/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  183. package/payload/skills/loom-retire/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  184. package/payload/skills/loom-retire/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  185. package/payload/skills/loom-retire/.loom-runtime/shared/scripts/loom_check.py +148 -0
  186. package/payload/skills/loom-retire/.loom-runtime/shared/scripts/loom_init.py +523 -215
  187. package/payload/skills/loom-review/.loom-runtime/loom-adopt/SKILL.md +1 -0
  188. package/payload/skills/loom-review/.loom-runtime/loom-init/SKILL.md +2 -0
  189. package/payload/skills/loom-review/.loom-runtime/loom-init/contract.json +4 -0
  190. package/payload/skills/loom-review/.loom-runtime/loom-init/references/output-contract.md +13 -1
  191. package/payload/skills/loom-review/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  192. package/payload/skills/loom-review/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  193. package/payload/skills/loom-review/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  194. package/payload/skills/loom-review/.loom-runtime/shared/scripts/loom_check.py +148 -0
  195. package/payload/skills/loom-review/.loom-runtime/shared/scripts/loom_init.py +523 -215
  196. package/payload/skills/loom-spec-review/.loom-runtime/loom-adopt/SKILL.md +1 -0
  197. package/payload/skills/loom-spec-review/.loom-runtime/loom-init/SKILL.md +2 -0
  198. package/payload/skills/loom-spec-review/.loom-runtime/loom-init/contract.json +4 -0
  199. package/payload/skills/loom-spec-review/.loom-runtime/loom-init/references/output-contract.md +13 -1
  200. package/payload/skills/loom-spec-review/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  201. package/payload/skills/loom-spec-review/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  202. package/payload/skills/loom-spec-review/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  203. package/payload/skills/loom-spec-review/.loom-runtime/shared/scripts/loom_check.py +148 -0
  204. package/payload/skills/loom-spec-review/.loom-runtime/shared/scripts/loom_init.py +523 -215
  205. package/payload/skills/loom-story/.loom-runtime/loom-adopt/SKILL.md +1 -0
  206. package/payload/skills/loom-story/.loom-runtime/loom-init/SKILL.md +2 -0
  207. package/payload/skills/loom-story/.loom-runtime/loom-init/contract.json +4 -0
  208. package/payload/skills/loom-story/.loom-runtime/loom-init/references/output-contract.md +13 -1
  209. package/payload/skills/loom-story/.loom-runtime/shared/references/adoption/deep-existing-repo-default.md +4 -0
  210. package/payload/skills/loom-story/.loom-runtime/shared/references/adoption/repo-companion-contract.md +3 -1
  211. package/payload/skills/loom-story/.loom-runtime/shared/scripts/governance_surface.py +1 -0
  212. package/payload/skills/loom-story/.loom-runtime/shared/scripts/loom_check.py +148 -0
  213. package/payload/skills/loom-story/.loom-runtime/shared/scripts/loom_init.py +523 -215
@@ -38,6 +38,63 @@ ADOPTION_INTENTS = (
38
38
  )
39
39
  UNSPECIFIED_ADOPTION_INTENT = "unspecified"
40
40
  NON_WRITABLE_ADOPTION_PATHS = {"defer", "skill-install-only"}
41
+ SCAFFOLD_PROFILES = (
42
+ "observe-only",
43
+ "skill-install-only",
44
+ "attach-only",
45
+ "light-governance",
46
+ "execution-control",
47
+ "strong-governance",
48
+ )
49
+ ATTACH_ONLY_FORBIDDEN_AUTHORED_CARRIERS = (
50
+ {
51
+ "path": ".loom/work-items/**",
52
+ "reason": "attach-only preserves host-owned work item truth",
53
+ "remediation": "migrate the item to a host truth locator, delete the competing Loom carrier, or rerun with --intent execution-control",
54
+ },
55
+ {
56
+ "path": ".loom/progress/**",
57
+ "reason": "attach-only preserves host-owned recovery/progress truth",
58
+ "remediation": "migrate recovery state to a host truth locator, delete the competing Loom carrier, or rerun with --intent execution-control",
59
+ },
60
+ {
61
+ "path": ".loom/status/current.md",
62
+ "reason": "attach-only preserves host-owned project status truth",
63
+ "remediation": "migrate status to a host truth locator, delete the competing Loom carrier, or rerun with --intent execution-control",
64
+ },
65
+ {
66
+ "path": ".loom/reviews/**",
67
+ "reason": "attach-only preserves host-owned PR review or guardian truth",
68
+ "remediation": "migrate review truth to a host truth locator, delete the competing Loom carrier, or rerun with --intent execution-control",
69
+ },
70
+ {
71
+ "path": ".loom/specs/**",
72
+ "reason": "attach-only does not author Loom spec truth unless the repo explicitly upgrades intent",
73
+ "remediation": "migrate spec truth to a host locator, delete the competing Loom carrier, or rerun with --intent execution-control",
74
+ },
75
+ )
76
+ ATTACH_ONLY_HOST_TRUTH_LOCATORS = {
77
+ "work_item": {
78
+ "host_surface": "github_issue",
79
+ "locator": "repo-owned issue tracker",
80
+ "mode": "host_truth_locator",
81
+ },
82
+ "project_status": {
83
+ "host_surface": "github_project",
84
+ "locator": "repo-owned project board or status system",
85
+ "mode": "host_truth_locator",
86
+ },
87
+ "review": {
88
+ "host_surface": "pull_request_review_or_guardian",
89
+ "locator": "repo-owned PR review, guardian, or review gate",
90
+ "mode": "host_truth_locator",
91
+ },
92
+ "closeout": {
93
+ "host_surface": "pull_request_metadata_and_issue_state",
94
+ "locator": "repo-owned PR metadata plus issue state",
95
+ "mode": "host_truth_locator",
96
+ },
97
+ }
41
98
 
42
99
  RUNTIME_ARTIFACT_SOURCES = {
43
100
  ".loom/bin/loom_init.py": RUNTIME_SOURCE,
@@ -720,6 +777,183 @@ def is_heavy_execution_path(adoption_path: str) -> bool:
720
777
  return adoption_path == "full-bootstrap"
721
778
 
722
779
 
780
+ def scaffold_profile_key(adoption_path: str, intake: dict[str, object]) -> str:
781
+ requested = str(intake.get("adoption_intent", UNSPECIFIED_ADOPTION_INTENT))
782
+ if requested in SCAFFOLD_PROFILES:
783
+ return requested
784
+ if adoption_path == "defer":
785
+ return "observe-only"
786
+ if adoption_path == "skill-install-only":
787
+ return "skill-install-only"
788
+ if uses_attach_only_path(adoption_path):
789
+ return "attach-only"
790
+ if adoption_path == "full-bootstrap":
791
+ return "execution-control"
792
+ return "light-governance"
793
+
794
+
795
+ def profile_has_work_item_carriers(profile: str) -> bool:
796
+ return profile in {"execution-control", "strong-governance"}
797
+
798
+
799
+ def profile_writes_artifacts(profile: str) -> bool:
800
+ return profile not in {"observe-only", "skill-install-only"}
801
+
802
+
803
+ def forbidden_authored_carriers(profile: str) -> list[dict[str, str]]:
804
+ if profile != "attach-only":
805
+ return []
806
+ return [dict(carrier) for carrier in ATTACH_ONLY_FORBIDDEN_AUTHORED_CARRIERS]
807
+
808
+
809
+ def required_carriers_for_profile(artifacts: list[dict[str, str]], profile: str) -> list[dict[str, str]]:
810
+ if profile in {"observe-only", "skill-install-only"}:
811
+ return []
812
+ return [
813
+ {
814
+ "path": artifact["path"],
815
+ "kind": artifact["kind"],
816
+ "owner": write_owner_for_path(artifact["path"]),
817
+ }
818
+ for artifact in artifacts
819
+ if isinstance(artifact.get("path"), str) and isinstance(artifact.get("kind"), str)
820
+ ]
821
+
822
+
823
+ def normalize_relative_path(raw_path: object) -> str | None:
824
+ if not isinstance(raw_path, str) or not raw_path:
825
+ return None
826
+ normalized = raw_path.replace("\\", "/")
827
+ while normalized.startswith("./"):
828
+ normalized = normalized[2:]
829
+ if normalized.startswith("/") or normalized.startswith("../") or "/../" in normalized:
830
+ return None
831
+ return normalized
832
+
833
+
834
+ def matches_forbidden_authored_carrier(relative_path: str, pattern: str) -> bool:
835
+ if pattern.endswith("/**"):
836
+ prefix = pattern[:-3]
837
+ return relative_path == prefix or relative_path.startswith(prefix + "/")
838
+ return relative_path == pattern
839
+
840
+
841
+ def forbidden_authored_carrier_for_path(relative_path: str) -> dict[str, str] | None:
842
+ for carrier in ATTACH_ONLY_FORBIDDEN_AUTHORED_CARRIERS:
843
+ pattern = carrier["path"]
844
+ if matches_forbidden_authored_carrier(relative_path, pattern):
845
+ return carrier
846
+ return None
847
+
848
+
849
+ def collect_forbidden_authored_carrier_declarations(result: dict[str, object]) -> list[dict[str, str]]:
850
+ declarations: list[dict[str, str]] = []
851
+
852
+ def add(raw_path: object, source: str) -> None:
853
+ relative = normalize_relative_path(raw_path)
854
+ if relative is None:
855
+ return
856
+ carrier = forbidden_authored_carrier_for_path(relative)
857
+ if carrier is not None:
858
+ declarations.append({"path": relative, "pattern": carrier["path"], "source": source})
859
+
860
+ for key in ("initial_artifacts", "planned_writes"):
861
+ entries = result.get(key)
862
+ if isinstance(entries, list):
863
+ for entry in entries:
864
+ if isinstance(entry, dict):
865
+ add(entry.get("path"), key)
866
+ work_items = result.get("initial_work_items")
867
+ if isinstance(work_items, list):
868
+ for work_item in work_items:
869
+ if not isinstance(work_item, dict):
870
+ continue
871
+ artifacts = work_item.get("artifacts")
872
+ if isinstance(artifacts, list):
873
+ for artifact in artifacts:
874
+ add(artifact, "initial_work_items.artifacts")
875
+ write = result.get("write")
876
+ if isinstance(write, dict):
877
+ touched = write.get("touched")
878
+ if isinstance(touched, list):
879
+ for path in touched:
880
+ add(path, "write.touched")
881
+ return declarations
882
+
883
+
884
+ def collect_forbidden_authored_carrier_files(target_root: Path) -> list[dict[str, str]]:
885
+ found: list[dict[str, str]] = []
886
+ for carrier in ATTACH_ONLY_FORBIDDEN_AUTHORED_CARRIERS:
887
+ pattern = carrier["path"]
888
+ if pattern.endswith("/**"):
889
+ prefix = pattern[:-3]
890
+ base = target_root / prefix
891
+ if not base.exists():
892
+ continue
893
+ if base.is_file():
894
+ found.append({"path": prefix, "pattern": pattern, "source": "filesystem"})
895
+ continue
896
+ for path in sorted(candidate for candidate in base.rglob("*") if candidate.is_file()):
897
+ found.append(
898
+ {
899
+ "path": path.relative_to(target_root).as_posix(),
900
+ "pattern": pattern,
901
+ "source": "filesystem",
902
+ }
903
+ )
904
+ continue
905
+ exact = target_root / pattern
906
+ if exact.exists():
907
+ found.append({"path": pattern, "pattern": pattern, "source": "filesystem"})
908
+ return found
909
+
910
+
911
+ def collect_forbidden_manifest_declarations(target_root: Path) -> list[dict[str, str]]:
912
+ manifest_path = target_root / ".loom/bootstrap/manifest.json"
913
+ if not manifest_path.exists():
914
+ return []
915
+ try:
916
+ manifest = read_json(manifest_path)
917
+ except json.JSONDecodeError:
918
+ return []
919
+ artifacts = manifest.get("artifacts")
920
+ declarations: list[dict[str, str]] = []
921
+ if not isinstance(artifacts, list):
922
+ return declarations
923
+ for artifact in artifacts:
924
+ if not isinstance(artifact, dict):
925
+ continue
926
+ relative = normalize_relative_path(artifact.get("path"))
927
+ if relative is None:
928
+ continue
929
+ carrier = forbidden_authored_carrier_for_path(relative)
930
+ if carrier is not None:
931
+ declarations.append({"path": relative, "pattern": carrier["path"], "source": "manifest.artifacts"})
932
+ return declarations
933
+
934
+
935
+ def attach_only_forbidden_carrier_errors(target_root: Path, result: dict[str, object]) -> list[str]:
936
+ findings = (
937
+ collect_forbidden_authored_carrier_declarations(result)
938
+ + collect_forbidden_manifest_declarations(target_root)
939
+ + collect_forbidden_authored_carrier_files(target_root)
940
+ )
941
+ errors: list[str] = []
942
+ seen: set[tuple[str, str, str]] = set()
943
+ for finding in findings:
944
+ key = (finding["source"], finding["path"], finding["pattern"])
945
+ if key in seen:
946
+ continue
947
+ seen.add(key)
948
+ errors.append(
949
+ "attach-only forbidden authored carrier detected in "
950
+ f"{finding['source']}: `{finding['path']}` matches `{finding['pattern']}`; "
951
+ "this would create a second truth chain. Migrate it to the host truth locator, delete it, "
952
+ "or explicitly rerun bootstrap with `--intent execution-control`."
953
+ )
954
+ return errors
955
+
956
+
723
957
  def adoption_intent_payload(adoption_path: str, intake: dict[str, object]) -> dict[str, object]:
724
958
  requested = str(intake.get("adoption_intent", UNSPECIFIED_ADOPTION_INTENT))
725
959
  source = str(intake.get("adoption_intent_source", "unspecified"))
@@ -795,7 +1029,28 @@ def rule_refs_for_capabilities(scenario: str, adoption_path: str) -> list[dict[s
795
1029
  return common
796
1030
 
797
1031
 
798
- def deferred_capabilities(scenario: str, adoption_path: str) -> list[dict[str, str]]:
1032
+ def deferred_capabilities(scenario: str, adoption_path: str, profile: str) -> list[dict[str, str]]:
1033
+ if profile == "light-governance":
1034
+ return [
1035
+ {
1036
+ "name": "loom-owned-work-item-progress-status",
1037
+ "reason": "light-governance keeps first-round adoption to a companion, review/spec, and PR-template loop",
1038
+ "upgrade_trigger": "the repo explicitly opts into execution-control or needs Loom-owned recovery/status carriers",
1039
+ },
1040
+ {
1041
+ "name": "host-gate-merge-closeout-control",
1042
+ "reason": "light-governance does not claim host merge, release, or closeout control",
1043
+ "upgrade_trigger": "required checks, merge-ready, or closeout must be consumed as Loom-owned gates",
1044
+ },
1045
+ ]
1046
+ if profile == "execution-control":
1047
+ return [
1048
+ {
1049
+ "name": "strong-governance-host-gates",
1050
+ "reason": "execution-control writes Loom-owned execution carriers but does not require host merge and closeout gates as a profile precondition",
1051
+ "upgrade_trigger": "host required checks, controlled merge, or closeout reconciliation become part of the adoption contract",
1052
+ }
1053
+ ]
799
1054
  if scenario == "new":
800
1055
  return [
801
1056
  {
@@ -844,6 +1099,97 @@ def deferred_capabilities(scenario: str, adoption_path: str) -> list[dict[str, s
844
1099
  ]
845
1100
 
846
1101
 
1102
+ def upgrade_triggers(deferred: list[dict[str, str]], profile: str) -> list[dict[str, str]]:
1103
+ return [
1104
+ {
1105
+ "from_profile": profile,
1106
+ "capability": item["name"],
1107
+ "trigger": item["upgrade_trigger"],
1108
+ }
1109
+ for item in deferred
1110
+ if item.get("upgrade_trigger")
1111
+ ]
1112
+
1113
+
1114
+ def profile_common_artifacts() -> list[dict[str, str]]:
1115
+ artifacts: list[dict[str, str]] = [
1116
+ {"path": ".loom/README.md", "kind": "rule-entry", "source": "generated"},
1117
+ {"path": ".loom/bootstrap/intake.snapshot.json", "kind": "intake", "source": "generated"},
1118
+ {"path": ".loom/bootstrap/init-result.json", "kind": "init-result", "source": "generated"},
1119
+ {"path": ".loom/bootstrap/manifest.json", "kind": "manifest", "source": "generated"},
1120
+ {"path": ".loom/bootstrap/capability-map.md", "kind": "capability-map", "source": "generated"},
1121
+ {"path": ".loom/companion/README.md", "kind": "repo-companion-entry", "source": "generated"},
1122
+ {"path": ".loom/companion/manifest.json", "kind": "repo-companion-manifest", "source": "generated"},
1123
+ {"path": ".loom/companion/repo-interface.json", "kind": "repo-companion-interface", "source": "generated"},
1124
+ {"path": ".loom/companion/interop.json", "kind": "repo-interop-contract", "source": "generated"},
1125
+ {"path": ".loom/companion/checkpoints.md", "kind": "repo-companion-doc", "source": "generated"},
1126
+ {"path": ".loom/companion/review.md", "kind": "repo-companion-doc", "source": "generated"},
1127
+ {"path": ".loom/companion/merge-ready.md", "kind": "repo-companion-doc", "source": "generated"},
1128
+ {"path": ".loom/companion/closeout.md", "kind": "repo-companion-doc", "source": "generated"},
1129
+ {"path": ".loom/companion/releases/changelog.md", "kind": "repo-release-surface", "source": "generated"},
1130
+ {"path": ".loom/companion/releases/release-notes.md", "kind": "repo-release-surface", "source": "generated"},
1131
+ {"path": ".loom/companion/releases/migration-notes.md", "kind": "repo-release-surface", "source": "generated"},
1132
+ {"path": ".loom/companion/releases/rollback.md", "kind": "repo-release-surface", "source": "generated"},
1133
+ {"path": ".loom/companion/releases/catalog.json", "kind": "repo-release-surface", "source": "generated"},
1134
+ {"path": ".loom/companion/releases/current.json", "kind": "repo-release-surface", "source": "generated"},
1135
+ {"path": ".loom/companion/releases/status.json", "kind": "repo-release-surface", "source": "generated"},
1136
+ {"path": ".loom/shadow/admission-loom.json", "kind": "shadow-parity-surface", "source": "generated"},
1137
+ {"path": ".loom/shadow/admission-repo.json", "kind": "shadow-parity-surface", "source": "generated"},
1138
+ {"path": ".loom/shadow/review-loom.json", "kind": "shadow-parity-surface", "source": "generated"},
1139
+ {"path": ".loom/shadow/review-repo.json", "kind": "shadow-parity-surface", "source": "generated"},
1140
+ {"path": ".loom/shadow/merge-ready-loom.json", "kind": "shadow-parity-surface", "source": "generated"},
1141
+ {"path": ".loom/shadow/merge-ready-repo.json", "kind": "shadow-parity-surface", "source": "generated"},
1142
+ {"path": ".loom/shadow/closeout-loom.json", "kind": "shadow-parity-surface", "source": "generated"},
1143
+ {"path": ".loom/shadow/closeout-repo.json", "kind": "shadow-parity-surface", "source": "generated"},
1144
+ {"path": ".gitignore", "kind": "gitignore", "source": "generated"},
1145
+ runtime_artifact(".loom/bin/loom_init.py", "loom-tool", RUNTIME_SOURCE),
1146
+ runtime_artifact(".loom/bin/fact_chain_support.py", "loom-tool-support", FACT_CHAIN_RUNTIME_SOURCE),
1147
+ runtime_artifact(".loom/bin/governance_surface.py", "loom-tool-support", GOVERNANCE_RUNTIME_SOURCE),
1148
+ runtime_artifact(".loom/bin/loom_flow.py", "loom-tool", FLOW_RUNTIME_SOURCE),
1149
+ runtime_artifact(".loom/bin/loom_status.py", "loom-tool", STATUS_RUNTIME_SOURCE),
1150
+ runtime_artifact(".loom/bin/runtime_paths.py", "loom-tool-support", "skills/shared/scripts/runtime_paths.py"),
1151
+ runtime_artifact(".loom/bin/runtime_state.py", "loom-tool-support", "skills/shared/scripts/runtime_state.py"),
1152
+ runtime_artifact(".loom/bin/loom_check.py", "loom-tool", CHECK_RUNTIME_SOURCE),
1153
+ ]
1154
+ return artifacts
1155
+
1156
+
1157
+ def profile_light_artifacts(target_root: Path) -> list[dict[str, str]]:
1158
+ artifacts: list[dict[str, str]] = []
1159
+ if not (target_root / "AGENTS.md").exists():
1160
+ artifacts.append({"path": "AGENTS.md", "kind": "root-entry", "source": "generated"})
1161
+ artifacts.extend(
1162
+ [
1163
+ {"path": ".loom/reviews/INIT-0001.json", "kind": "review-entry", "source": "generated"},
1164
+ {"path": ".loom/reviews/INIT-0001.spec.json", "kind": "review-entry", "source": "generated"},
1165
+ {"path": ".loom/specs/INIT-0001/spec.md", "kind": "spec", "source": "skills/shared/assets/templates/scaffold/spec.md"},
1166
+ {"path": ".loom/specs/INIT-0001/plan.md", "kind": "plan", "source": "skills/shared/assets/templates/scaffold/plan.md"},
1167
+ {
1168
+ "path": ".loom/specs/INIT-0001/implementation-contract.md",
1169
+ "kind": "implementation-contract",
1170
+ "source": "skills/shared/assets/templates/scaffold/implementation-contract.md",
1171
+ },
1172
+ ]
1173
+ )
1174
+ return artifacts
1175
+
1176
+
1177
+ def profile_execution_artifacts(target_root: Path) -> list[dict[str, str]]:
1178
+ artifacts = profile_light_artifacts(target_root)
1179
+ artifacts.extend(
1180
+ [
1181
+ {"path": ".loom/work-items/INIT-0001.md", "kind": "work-item", "source": "generated"},
1182
+ {"path": ".loom/progress/INIT-0001.md", "kind": "progress", "source": "generated"},
1183
+ {"path": ".loom/status/current.md", "kind": "status-surface", "source": "generated"},
1184
+ ]
1185
+ )
1186
+ return artifacts
1187
+
1188
+
1189
+ def artifact_paths(artifacts: list[dict[str, str]]) -> list[str]:
1190
+ return [artifact["path"] for artifact in artifacts]
1191
+
1192
+
847
1193
  def attach_only_artifact_paths(target_root: Path, install_pr_template: bool) -> list[str]:
848
1194
  artifacts = [
849
1195
  ".loom/README.md",
@@ -869,7 +1215,13 @@ def attach_only_artifact_paths(target_root: Path, install_pr_template: bool) ->
869
1215
  return artifacts
870
1216
 
871
1217
 
872
- def initial_work_items(scenario: str, target_root: Path, adoption_path: str, install_pr_template: bool) -> list[dict[str, object]]:
1218
+ def initial_work_items(
1219
+ scenario: str,
1220
+ target_root: Path,
1221
+ adoption_path: str,
1222
+ install_pr_template: bool,
1223
+ profile: str,
1224
+ ) -> list[dict[str, object]]:
873
1225
  if adoption_path in NON_WRITABLE_ADOPTION_PATHS:
874
1226
  return []
875
1227
  if uses_attach_only_path(adoption_path):
@@ -889,26 +1241,7 @@ def initial_work_items(scenario: str, target_root: Path, adoption_path: str, ins
889
1241
  "owner_for_checkpoint_lite": "repository owner or current attach operator",
890
1242
  }
891
1243
  ]
892
- artifacts = [
893
- ".loom/bootstrap/init-result.json",
894
- ".loom/work-items/INIT-0001.md",
895
- ".loom/progress/INIT-0001.md",
896
- ".loom/reviews/INIT-0001.json",
897
- ".loom/reviews/INIT-0001.spec.json",
898
- ".loom/status/current.md",
899
- ".loom/bin/loom_init.py",
900
- ".loom/bin/fact_chain_support.py",
901
- ".loom/bin/governance_surface.py",
902
- ".loom/bin/loom_flow.py",
903
- ".loom/bin/loom_status.py",
904
- ".loom/bin/runtime_paths.py",
905
- ".loom/bin/loom_check.py",
906
- ".loom/specs/INIT-0001/spec.md",
907
- ".loom/specs/INIT-0001/plan.md",
908
- ".loom/specs/INIT-0001/implementation-contract.md",
909
- ]
910
- if not (target_root / ".github/PULL_REQUEST_TEMPLATE.md").exists():
911
- artifacts.append(".github/PULL_REQUEST_TEMPLATE.md")
1244
+ artifacts = artifact_paths(initial_artifacts(target_root, install_pr_template, adoption_path, profile))
912
1245
  return [
913
1246
  {
914
1247
  "id": WORK_ITEM_ID,
@@ -927,125 +1260,15 @@ def initial_work_items(scenario: str, target_root: Path, adoption_path: str, ins
927
1260
  ]
928
1261
 
929
1262
 
930
- def initial_artifacts(target_root: Path, install_pr_template: bool, adoption_path: str) -> list[dict[str, str]]:
931
- if adoption_path in NON_WRITABLE_ADOPTION_PATHS:
1263
+ def initial_artifacts(target_root: Path, install_pr_template: bool, adoption_path: str, profile: str) -> list[dict[str, str]]:
1264
+ if not profile_writes_artifacts(profile):
932
1265
  return []
933
1266
 
934
- artifacts = [
935
- {
936
- "path": ".loom/README.md",
937
- "kind": "rule-entry",
938
- "source": "generated",
939
- },
940
- {
941
- "path": ".loom/bootstrap/intake.snapshot.json",
942
- "kind": "intake",
943
- "source": "generated",
944
- },
945
- {
946
- "path": ".loom/bootstrap/init-result.json",
947
- "kind": "init-result",
948
- "source": "generated",
949
- },
950
- {
951
- "path": ".loom/bootstrap/manifest.json",
952
- "kind": "manifest",
953
- "source": "generated",
954
- },
955
- {
956
- "path": ".loom/bootstrap/capability-map.md",
957
- "kind": "capability-map",
958
- "source": "generated",
959
- },
960
- runtime_artifact(".loom/bin/loom_init.py", "loom-tool", RUNTIME_SOURCE),
961
- runtime_artifact(".loom/bin/fact_chain_support.py", "loom-tool-support", FACT_CHAIN_RUNTIME_SOURCE),
962
- runtime_artifact(".loom/bin/governance_surface.py", "loom-tool-support", GOVERNANCE_RUNTIME_SOURCE),
963
- runtime_artifact(".loom/bin/loom_flow.py", "loom-tool", FLOW_RUNTIME_SOURCE),
964
- runtime_artifact(".loom/bin/loom_status.py", "loom-tool", STATUS_RUNTIME_SOURCE),
965
- runtime_artifact(".loom/bin/runtime_paths.py", "loom-tool-support", "skills/shared/scripts/runtime_paths.py"),
966
- runtime_artifact(".loom/bin/runtime_state.py", "loom-tool-support", "skills/shared/scripts/runtime_state.py"),
967
- runtime_artifact(".loom/bin/loom_check.py", "loom-tool", CHECK_RUNTIME_SOURCE),
968
- ]
969
- if uses_attach_only_path(adoption_path):
970
- artifacts.extend(
971
- [
972
- {
973
- "path": ".loom/companion/README.md",
974
- "kind": "repo-companion-entry",
975
- "source": "generated",
976
- },
977
- {
978
- "path": ".loom/companion/checkpoints.md",
979
- "kind": "repo-companion-doc",
980
- "source": "generated",
981
- },
982
- {
983
- "path": ".loom/companion/review.md",
984
- "kind": "repo-companion-doc",
985
- "source": "generated",
986
- },
987
- {
988
- "path": ".loom/companion/merge-ready.md",
989
- "kind": "repo-companion-doc",
990
- "source": "generated",
991
- },
992
- {
993
- "path": ".loom/companion/closeout.md",
994
- "kind": "repo-companion-doc",
995
- "source": "generated",
996
- },
997
- ]
998
- )
999
- else:
1000
- artifacts.extend(
1001
- [
1002
- {
1003
- "path": "AGENTS.md",
1004
- "kind": "root-entry",
1005
- "source": "generated",
1006
- },
1007
- {
1008
- "path": ".loom/work-items/INIT-0001.md",
1009
- "kind": "work-item",
1010
- "source": "generated",
1011
- },
1012
- {
1013
- "path": ".loom/progress/INIT-0001.md",
1014
- "kind": "progress",
1015
- "source": "generated",
1016
- },
1017
- {
1018
- "path": ".loom/reviews/INIT-0001.json",
1019
- "kind": "review-entry",
1020
- "source": "generated",
1021
- },
1022
- {
1023
- "path": ".loom/reviews/INIT-0001.spec.json",
1024
- "kind": "review-entry",
1025
- "source": "generated",
1026
- },
1027
- {
1028
- "path": ".loom/status/current.md",
1029
- "kind": "status-surface",
1030
- "source": "generated",
1031
- },
1032
- {
1033
- "path": ".loom/specs/INIT-0001/spec.md",
1034
- "kind": "spec",
1035
- "source": "skills/shared/assets/templates/scaffold/spec.md",
1036
- },
1037
- {
1038
- "path": ".loom/specs/INIT-0001/plan.md",
1039
- "kind": "plan",
1040
- "source": "skills/shared/assets/templates/scaffold/plan.md",
1041
- },
1042
- {
1043
- "path": ".loom/specs/INIT-0001/implementation-contract.md",
1044
- "kind": "implementation-contract",
1045
- "source": "skills/shared/assets/templates/scaffold/implementation-contract.md",
1046
- },
1047
- ]
1048
- )
1267
+ artifacts = profile_common_artifacts()
1268
+ if profile == "light-governance":
1269
+ artifacts.extend(profile_light_artifacts(target_root))
1270
+ elif profile in {"execution-control", "strong-governance"}:
1271
+ artifacts.extend(profile_execution_artifacts(target_root))
1049
1272
  if install_pr_template or not (target_root / ".github/PULL_REQUEST_TEMPLATE.md").exists():
1050
1273
  artifacts.append(
1051
1274
  {
@@ -1144,18 +1367,25 @@ def planned_write_targets(result: dict[str, object], adoption_path: str) -> list
1144
1367
  return planned
1145
1368
 
1146
1369
 
1147
- def intentionally_absent_targets(adoption_path: str) -> list[dict[str, str]]:
1148
- if uses_attach_only_path(adoption_path):
1370
+ def intentionally_absent_targets(adoption_path: str, profile: str) -> list[dict[str, str]]:
1371
+ if profile == "attach-only":
1149
1372
  return [
1150
1373
  {"path": ".loom/work-items/**", "reason": "attach-only preserves host-owned work item truth"},
1151
1374
  {"path": ".loom/progress/**", "reason": "attach-only preserves host-owned recovery truth"},
1152
1375
  {"path": ".loom/status/current.md", "reason": "attach-only does not author Loom status truth"},
1376
+ {"path": ".loom/reviews/**", "reason": "attach-only preserves host-owned review truth"},
1153
1377
  {"path": ".loom/specs/**", "reason": "attach-only does not author Loom execution specs"},
1154
1378
  ]
1155
1379
  if adoption_path == "defer":
1156
1380
  return [{"path": "*", "reason": "observe-only intent is read-only"}]
1157
1381
  if adoption_path == "skill-install-only":
1158
1382
  return [{"path": ".loom/work-items/**", "reason": "skill install does not adopt execution governance"}]
1383
+ if profile == "light-governance":
1384
+ return [
1385
+ {"path": ".loom/work-items/**", "reason": "light-governance does not author Loom work item truth"},
1386
+ {"path": ".loom/progress/**", "reason": "light-governance does not author Loom recovery truth"},
1387
+ {"path": ".loom/status/current.md", "reason": "light-governance does not author Loom status truth"},
1388
+ ]
1159
1389
  return []
1160
1390
 
1161
1391
 
@@ -1180,8 +1410,10 @@ def risk_summary(adoption_path: str, intake: dict[str, object], planned: list[di
1180
1410
 
1181
1411
  def build_result(target_root: Path, scenario: str, intake: dict[str, object], install_pr_template: bool) -> dict[str, object]:
1182
1412
  adoption_path = recommended_adoption_path(scenario, intake)
1413
+ profile = scaffold_profile_key(adoption_path, intake)
1183
1414
  attach_only = uses_attach_only_path(adoption_path)
1184
1415
  read_only_adoption = adoption_path in NON_WRITABLE_ADOPTION_PATHS
1416
+ has_work_item_carriers = profile_has_work_item_carriers(profile)
1185
1417
  main_problem = {
1186
1418
  "new": "the repository has no controlled Loom entry yet",
1187
1419
  "small-existing": "the repo has a baseline but still lacks a stable Loom adoption entry and explicit first artifacts",
@@ -1207,6 +1439,7 @@ def build_result(target_root: Path, scenario: str, intake: dict[str, object], in
1207
1439
  bootstrap_mode=True,
1208
1440
  scenario_override=scenario,
1209
1441
  )
1442
+ initial_artifact_list = initial_artifacts(target_root, install_pr_template, adoption_path, profile)
1210
1443
  result = {
1211
1444
  "schema_version": "loom-init-output/v1",
1212
1445
  "generator": {
@@ -1235,7 +1468,20 @@ def build_result(target_root: Path, scenario: str, intake: dict[str, object], in
1235
1468
  "recovery_mode": recovery_mode(scenario),
1236
1469
  "capabilities": rule_refs_for_capabilities(scenario, adoption_path),
1237
1470
  },
1238
- "deferred_capabilities": deferred_capabilities(scenario, adoption_path),
1471
+ "scaffold_profile": {
1472
+ "name": profile,
1473
+ "writes_artifacts": profile_writes_artifacts(profile),
1474
+ "writes_work_item_carriers": has_work_item_carriers,
1475
+ "description": {
1476
+ "observe-only": "read-only repository observation; no Loom adoption carriers are written",
1477
+ "skill-install-only": "skill/runtime installation intent without repository governance adoption carriers",
1478
+ "attach-only": "companion/read-surface attachment that preserves repo-owned execution truth",
1479
+ "light-governance": "companion, review/spec, and PR-template loop without Loom-owned work item/progress/status carriers",
1480
+ "execution-control": "Loom-owned work item, progress, review, status, and spec carriers",
1481
+ "strong-governance": "execution-control surface prepared for host gates, required checks, merge, and closeout consumption",
1482
+ }[profile],
1483
+ },
1484
+ "deferred_capabilities": deferred_capabilities(scenario, adoption_path, profile),
1239
1485
  "fact_chain": (
1240
1486
  {
1241
1487
  "mode": "intent-only dry-run",
@@ -1259,6 +1505,17 @@ def build_result(target_root: Path, scenario: str, intake: dict[str, object], in
1259
1505
  },
1260
1506
  }
1261
1507
  if attach_only
1508
+ else {
1509
+ "mode": "profile-guided light-governance",
1510
+ "read_entry": "not_applicable",
1511
+ "entry_points": {
1512
+ "current_item_id": WORK_ITEM_ID,
1513
+ "work_item": "not_applicable",
1514
+ "recovery_entry": "not_applicable",
1515
+ "status_surface": "not_applicable",
1516
+ },
1517
+ }
1518
+ if not has_work_item_carriers
1262
1519
  else {
1263
1520
  "mode": "work-item + recovery-entry + derived status-surface",
1264
1521
  "read_entry": "python3 .loom/bin/loom_init.py fact-chain --target .",
@@ -1270,8 +1527,8 @@ def build_result(target_root: Path, scenario: str, intake: dict[str, object], in
1270
1527
  },
1271
1528
  }
1272
1529
  ),
1273
- "initial_artifacts": initial_artifacts(target_root, install_pr_template, adoption_path),
1274
- "initial_work_items": initial_work_items(scenario, target_root, adoption_path, install_pr_template),
1530
+ "initial_artifacts": initial_artifact_list,
1531
+ "initial_work_items": initial_work_items(scenario, target_root, adoption_path, install_pr_template, profile),
1275
1532
  "validation_and_closing": {
1276
1533
  "validation_entry": "python3 .loom/bin/loom_init.py verify --target .",
1277
1534
  "checkpoint_relationship": (
@@ -1281,6 +1538,12 @@ def build_result(target_root: Path, scenario: str, intake: dict[str, object], in
1281
1538
  "merge checkpoint should only pass after downstream repo truth, companion extensions, and release judgment align",
1282
1539
  ]
1283
1540
  if attach_only
1541
+ else [
1542
+ "admission checkpoint confirms the companion entry, review record, spec suite, and PR template are readable",
1543
+ "build checkpoint confirms generated light-governance surfaces are internally consistent",
1544
+ "merge checkpoint remains repo-owned until the intent upgrades to execution-control or strong-governance",
1545
+ ]
1546
+ if profile == "light-governance"
1284
1547
  else [
1285
1548
  "admission checkpoint confirms the bootstrap work item and first artifacts are readable",
1286
1549
  "build checkpoint confirms generated carriers and templates are internally consistent",
@@ -1288,17 +1551,25 @@ def build_result(target_root: Path, scenario: str, intake: dict[str, object], in
1288
1551
  ]
1289
1552
  ),
1290
1553
  "clean_state": (
1291
- "all generated attach-only Loom artifacts are readable, verified, and do not introduce Loom-owned recovery/status placeholders"
1554
+ "all generated attach-only Loom artifacts are readable, verified, and do not introduce Loom-authored work/progress/status/review/spec truth carriers"
1292
1555
  if attach_only
1556
+ else "all generated light-governance artifacts are readable, verified, and do not introduce Loom-owned work/progress/status carriers"
1557
+ if profile == "light-governance"
1293
1558
  else "all generated Loom artifacts are readable, verified, and free of conflicting duplicates"
1294
1559
  ),
1295
1560
  "close_when": (
1296
1561
  [
1297
1562
  "the target repo has a readable root rule entry and attached repo companion entry",
1298
1563
  "the attach-only bootstrap metadata and repo-local validation path are verifiable",
1299
- "the bootstrap manifest does not declare Loom-owned recovery/status carriers for this path",
1564
+ "the bootstrap manifest, init-result, planned writes, and filesystem do not expose forbidden Loom-authored truth carriers",
1300
1565
  ]
1301
1566
  if attach_only
1567
+ else [
1568
+ "the target repo has a readable Loom companion entry",
1569
+ "the review record, spec suite, and PR template exist",
1570
+ "the bootstrap manifest and init-result are verifiable",
1571
+ ]
1572
+ if profile == "light-governance"
1302
1573
  else [
1303
1574
  "the target repo has a readable root or companion Loom entry",
1304
1575
  "the first work item, progress carrier, and spec/plan artifacts exist",
@@ -1312,6 +1583,7 @@ def build_result(target_root: Path, scenario: str, intake: dict[str, object], in
1312
1583
  "maturity_upgrade_path": init_maturity_upgrade_path(governance_surface),
1313
1584
  }
1314
1585
  planned = planned_write_targets(result, adoption_path)
1586
+ deferred = result["deferred_capabilities"]
1315
1587
  result["detected_repository_mode"] = {
1316
1588
  "repository_type": intake.get("repository_type"),
1317
1589
  "scenario_key": scenario,
@@ -1319,7 +1591,14 @@ def build_result(target_root: Path, scenario: str, intake: dict[str, object], in
1319
1591
  }
1320
1592
  result["adoption_intent"] = adoption_intent_payload(adoption_path, intake)
1321
1593
  result["planned_writes"] = planned
1322
- result["intentionally_absent"] = intentionally_absent_targets(adoption_path)
1594
+ result["required_carriers"] = required_carriers_for_profile(initial_artifact_list, profile)
1595
+ result["intentionally_absent"] = intentionally_absent_targets(adoption_path, profile)
1596
+ result["forbidden_authored_carriers"] = forbidden_authored_carriers(profile)
1597
+ scaffold_profile = result.get("scaffold_profile")
1598
+ if isinstance(scaffold_profile, dict):
1599
+ scaffold_profile["required_carriers"] = result["required_carriers"]
1600
+ scaffold_profile["forbidden_authored_carriers"] = result["forbidden_authored_carriers"]
1601
+ result["upgrade_triggers"] = upgrade_triggers(deferred if isinstance(deferred, list) else [], profile)
1323
1602
  result["risk_summary"] = risk_summary(adoption_path, intake, planned)
1324
1603
  return result
1325
1604
 
@@ -1445,16 +1724,26 @@ def bootstrap_write_blockers(result: dict[str, object]) -> list[str]:
1445
1724
 
1446
1725
  def render_loom_readme(result: dict[str, object]) -> str:
1447
1726
  run = result["run"]
1448
- attach_only = uses_attach_only_path(str(result["recommended_adoption"]["path"]))
1449
- path_lines = (
1450
- "- Repo companion entry: `.loom/companion/README.md`\n"
1451
- "- Companion checkpoints: `.loom/companion/checkpoints.md`\n"
1452
- "- Companion review surface: `.loom/companion/review.md`\n"
1453
- if attach_only
1454
- else "- First work item: `.loom/work-items/INIT-0001.md`\n"
1455
- "- Progress carrier: `.loom/progress/INIT-0001.md`\n"
1456
- "- Status surface: `.loom/status/current.md`\n"
1457
- )
1727
+ profile = result.get("scaffold_profile")
1728
+ profile_name = str(profile.get("name")) if isinstance(profile, dict) else "execution-control"
1729
+ if profile_name == "attach-only":
1730
+ path_lines = (
1731
+ "- Repo companion entry: `.loom/companion/README.md`\n"
1732
+ "- Companion checkpoints: `.loom/companion/checkpoints.md`\n"
1733
+ "- Companion review surface: `.loom/companion/review.md`\n"
1734
+ )
1735
+ elif profile_name == "light-governance":
1736
+ path_lines = (
1737
+ "- Repo companion entry: `.loom/companion/README.md`\n"
1738
+ "- Review record: `.loom/reviews/INIT-0001.json`\n"
1739
+ "- Spec suite: `.loom/specs/INIT-0001/`\n"
1740
+ )
1741
+ else:
1742
+ path_lines = (
1743
+ "- First work item: `.loom/work-items/INIT-0001.md`\n"
1744
+ "- Progress carrier: `.loom/progress/INIT-0001.md`\n"
1745
+ "- Status surface: `.loom/status/current.md`\n"
1746
+ )
1458
1747
  return (
1459
1748
  "# Loom Bootstrap\n\n"
1460
1749
  f"This directory was generated by `{RUNTIME_SOURCE}`.\n\n"
@@ -1548,8 +1837,8 @@ def companion_manifest_payload() -> dict[str, object]:
1548
1837
  }
1549
1838
 
1550
1839
 
1551
- def repo_interface_payload() -> dict[str, object]:
1552
- return {
1840
+ def repo_interface_payload(profile_name: str = "execution-control") -> dict[str, object]:
1841
+ payload: dict[str, object] = {
1553
1842
  "schema_version": "loom-repo-interface/v2",
1554
1843
  "companion_entry": ".loom/companion/README.md",
1555
1844
  "repo_specific_requirements": {"review": [], "merge_ready": [], "closeout": []},
@@ -1570,6 +1859,9 @@ def repo_interface_payload() -> dict[str, object]:
1570
1859
  "status_locator": ".loom/companion/releases/status.json",
1571
1860
  },
1572
1861
  }
1862
+ if profile_name == "attach-only":
1863
+ payload["host_truth_locators"] = ATTACH_ONLY_HOST_TRUTH_LOCATORS
1864
+ return payload
1573
1865
 
1574
1866
 
1575
1867
  def repo_interop_payload() -> dict[str, object]:
@@ -1842,7 +2134,14 @@ def scaffold_target(
1842
2134
  ) -> tuple[int, list[str]]:
1843
2135
  written = 0
1844
2136
  touched: list[str] = []
1845
- attach_only = uses_attach_only_path(str(result["recommended_adoption"]["path"]))
2137
+ profile = result.get("scaffold_profile")
2138
+ profile_name = str(profile.get("name")) if isinstance(profile, dict) else "execution-control"
2139
+ writes_light_loop = profile_name in {"light-governance", "execution-control", "strong-governance"}
2140
+ writes_work_item_carriers = profile_has_work_item_carriers(profile_name)
2141
+ if profile_name == "attach-only":
2142
+ forbidden_errors = attach_only_forbidden_carrier_errors(target_root, result)
2143
+ if forbidden_errors:
2144
+ raise RuntimeError("; ".join(forbidden_errors))
1846
2145
 
1847
2146
  writes: list[tuple[Path, str | dict[str, object], str]] = [
1848
2147
  (target_root / ".loom/README.md", render_loom_readme(result), "text"),
@@ -1852,7 +2151,7 @@ def scaffold_target(
1852
2151
  (target_root / ".loom/bootstrap/capability-map.md", render_capability_map(result), "text"),
1853
2152
  (target_root / ".loom/companion/README.md", render_companion_readme(result), "text"),
1854
2153
  (target_root / ".loom/companion/manifest.json", companion_manifest_payload(), "json"),
1855
- (target_root / ".loom/companion/repo-interface.json", repo_interface_payload(), "json"),
2154
+ (target_root / ".loom/companion/repo-interface.json", repo_interface_payload(profile_name), "json"),
1856
2155
  (target_root / ".loom/companion/interop.json", repo_interop_payload(), "json"),
1857
2156
  (target_root / ".loom/companion/checkpoints.md", render_companion_checkpoints(), "text"),
1858
2157
  (target_root / ".loom/companion/review.md", render_companion_review(), "text"),
@@ -1912,15 +2211,18 @@ def scaffold_target(
1912
2211
  "json",
1913
2212
  ),
1914
2213
  ]
1915
- if attach_only:
1916
- pass
1917
- else:
2214
+ if writes_light_loop:
1918
2215
  writes.extend(
1919
2216
  [
1920
- (target_root / ".loom/work-items/INIT-0001.md", render_work_item(result), "text"),
1921
- (target_root / ".loom/progress/INIT-0001.md", render_progress(result), "text"),
1922
2217
  (target_root / ".loom/reviews/INIT-0001.json", render_review_entry(result), "text"),
1923
2218
  (target_root / ".loom/reviews/INIT-0001.spec.json", render_spec_review_entry(result), "text"),
2219
+ ]
2220
+ )
2221
+ if writes_work_item_carriers:
2222
+ writes.extend(
2223
+ [
2224
+ (target_root / ".loom/work-items/INIT-0001.md", render_work_item(result), "text"),
2225
+ (target_root / ".loom/progress/INIT-0001.md", render_progress(result), "text"),
1924
2226
  (target_root / ".loom/status/current.md", render_status(result), "text"),
1925
2227
  ]
1926
2228
  )
@@ -1957,7 +2259,7 @@ def scaffold_target(
1957
2259
  if copy_file(source, destination, force=force):
1958
2260
  written += 1
1959
2261
  touched.append(str(destination.relative_to(target_root)))
1960
- if not attach_only:
2262
+ if writes_light_loop:
1961
2263
  for source, destination in (
1962
2264
  (shared_asset(__file__, "templates/scaffold/spec.md"), target_root / ".loom/specs/INIT-0001/spec.md"),
1963
2265
  (shared_asset(__file__, "templates/scaffold/plan.md"), target_root / ".loom/specs/INIT-0001/plan.md"),
@@ -1977,7 +2279,7 @@ def scaffold_target(
1977
2279
  touched.append(str(pr_template_target.relative_to(target_root)))
1978
2280
 
1979
2281
  root_agents = target_root / "AGENTS.md"
1980
- if not attach_only and not root_agents.exists():
2282
+ if writes_light_loop and not root_agents.exists():
1981
2283
  if write_text(root_agents, render_root_agents(), force=force):
1982
2284
  written += 1
1983
2285
  touched.append(str(root_agents.relative_to(target_root)))
@@ -2007,59 +2309,38 @@ def verify_target(target_root: Path, output_path: Path) -> list[str]:
2007
2309
  adoption = result.get("recommended_adoption")
2008
2310
  if isinstance(adoption, dict):
2009
2311
  attach_only = uses_attach_only_path(str(adoption.get("path", "")))
2010
- required_paths = [
2011
- ".loom/README.md",
2012
- ".loom/bootstrap/intake.snapshot.json",
2013
- str(output_path.relative_to(target_root)),
2014
- ".loom/bootstrap/manifest.json",
2015
- ".loom/bootstrap/capability-map.md",
2016
- ".loom/bin/loom_init.py",
2017
- ".loom/bin/fact_chain_support.py",
2018
- ".loom/bin/governance_surface.py",
2019
- ".loom/bin/loom_flow.py",
2020
- ".loom/bin/runtime_paths.py",
2021
- ".loom/bin/runtime_state.py",
2022
- ".loom/bin/loom_check.py",
2023
- ".loom/companion/README.md",
2024
- ".loom/companion/manifest.json",
2025
- ".loom/companion/repo-interface.json",
2026
- ".loom/companion/interop.json",
2027
- ".loom/companion/checkpoints.md",
2028
- ".loom/companion/review.md",
2029
- ".loom/companion/merge-ready.md",
2030
- ".loom/companion/closeout.md",
2031
- ".loom/shadow/admission-loom.json",
2032
- ".loom/shadow/admission-repo.json",
2033
- ".loom/shadow/review-loom.json",
2034
- ".loom/shadow/review-repo.json",
2035
- ".loom/shadow/merge-ready-loom.json",
2036
- ".loom/shadow/merge-ready-repo.json",
2037
- ".loom/shadow/closeout-loom.json",
2038
- ".loom/shadow/closeout-repo.json",
2039
- ]
2040
- if attach_only:
2041
- pass
2312
+ scaffold_profile = result.get("scaffold_profile")
2313
+ profile_name = str(scaffold_profile.get("name")) if isinstance(scaffold_profile, dict) else (
2314
+ "attach-only" if attach_only else "execution-control"
2315
+ )
2316
+ initial_artifact_list = result.get("initial_artifacts")
2317
+ planned_writes = result.get("planned_writes")
2318
+ if isinstance(initial_artifact_list, list):
2319
+ required_paths = [
2320
+ str(item.get("path"))
2321
+ for item in initial_artifact_list
2322
+ if isinstance(item, dict) and isinstance(item.get("path"), str)
2323
+ ]
2324
+ elif isinstance(planned_writes, list):
2325
+ required_paths = [
2326
+ str(item.get("path"))
2327
+ for item in planned_writes
2328
+ if isinstance(item, dict) and isinstance(item.get("path"), str)
2329
+ ]
2042
2330
  else:
2043
- required_paths.extend(
2044
- [
2045
- "AGENTS.md",
2046
- ".loom/work-items/INIT-0001.md",
2047
- ".loom/progress/INIT-0001.md",
2048
- ".loom/reviews/INIT-0001.json",
2049
- ".loom/status/current.md",
2050
- ".loom/specs/INIT-0001/spec.md",
2051
- ".loom/specs/INIT-0001/plan.md",
2052
- ".loom/specs/INIT-0001/implementation-contract.md",
2053
- ]
2054
- )
2331
+ required_paths = []
2055
2332
  for key in (
2056
2333
  "project_judgment",
2057
2334
  "recommended_adoption",
2335
+ "scaffold_profile",
2058
2336
  "adoption_intent",
2059
2337
  "detected_repository_mode",
2060
2338
  "risk_summary",
2339
+ "required_carriers",
2061
2340
  "planned_writes",
2341
+ "forbidden_authored_carriers",
2062
2342
  "deferred_capabilities",
2343
+ "upgrade_triggers",
2063
2344
  "fact_chain",
2064
2345
  "initial_artifacts",
2065
2346
  "initial_work_items",
@@ -2127,12 +2408,39 @@ def verify_target(target_root: Path, output_path: Path) -> list[str]:
2127
2408
  for forbidden in (".loom/work-items/INIT-0001.md", ".loom/progress/INIT-0001.md", ".loom/status/current.md"):
2128
2409
  if forbidden in declared_generated:
2129
2410
  errors.append(f"deep-existing-repo bootstrap must not declare generated carrier `{forbidden}`")
2411
+ forbidden_profile = result.get("forbidden_authored_carriers")
2412
+ if not isinstance(forbidden_profile, list) or {
2413
+ str(item.get("path")) for item in forbidden_profile if isinstance(item, dict)
2414
+ } != {carrier["path"] for carrier in ATTACH_ONLY_FORBIDDEN_AUTHORED_CARRIERS}:
2415
+ errors.append("attach-only init-result must declare the full `forbidden_authored_carriers` profile list")
2416
+ errors.extend(attach_only_forbidden_carrier_errors(target_root, result))
2417
+ if profile_name == "light-governance":
2418
+ declared_generated = {
2419
+ artifact.get("path")
2420
+ for artifact in result.get("initial_artifacts", [])
2421
+ if isinstance(artifact, dict) and isinstance(artifact.get("path"), str)
2422
+ }
2423
+ for forbidden in (".loom/work-items/INIT-0001.md", ".loom/progress/INIT-0001.md", ".loom/status/current.md"):
2424
+ if forbidden in declared_generated:
2425
+ errors.append(f"light-governance bootstrap must not declare execution-control carrier `{forbidden}`")
2130
2426
 
2131
2427
  for relative in required_paths:
2132
2428
  if not (target_root / relative).exists():
2133
2429
  errors.append(f"missing required artifact: {relative}")
2134
2430
 
2135
- if not attach_only:
2431
+ profile_writes_work_items = False
2432
+ if output_path.exists():
2433
+ try:
2434
+ result_for_profile = read_json(output_path)
2435
+ scaffold_profile = result_for_profile.get("scaffold_profile")
2436
+ profile_name = str(scaffold_profile.get("name")) if isinstance(scaffold_profile, dict) else (
2437
+ "attach-only" if attach_only else "execution-control"
2438
+ )
2439
+ profile_writes_work_items = profile_has_work_item_carriers(profile_name)
2440
+ except json.JSONDecodeError:
2441
+ profile_writes_work_items = not attach_only
2442
+
2443
+ if profile_writes_work_items:
2136
2444
  fact_chain_report, fact_chain_errors = inspect_fact_chain(
2137
2445
  target_root,
2138
2446
  str(output_path.relative_to(target_root)),
@@ -2192,7 +2500,7 @@ def verify_target(target_root: Path, output_path: Path) -> list[str]:
2192
2500
  {"pass"},
2193
2501
  ),
2194
2502
  ]
2195
- if not attach_only:
2503
+ if profile_writes_work_items:
2196
2504
  commands.extend(
2197
2505
  [
2198
2506
  (
@@ -2207,7 +2515,7 @@ def verify_target(target_root: Path, output_path: Path) -> list[str]:
2207
2515
  ),
2208
2516
  ]
2209
2517
  )
2210
- if current_item_id and not attach_only:
2518
+ if current_item_id and profile_writes_work_items:
2211
2519
  commands.extend(
2212
2520
  [
2213
2521
  (