@intentius/chant 0.101.0 → 0.104.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (739) hide show
  1. package/dist/agents/checks.d.ts.map +1 -1
  2. package/dist/attrref.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +2 -0
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts.map +1 -1
  6. package/dist/audit/nginx.d.ts.map +1 -1
  7. package/dist/audit/prior-art.d.ts +48 -0
  8. package/dist/audit/prior-art.d.ts.map +1 -1
  9. package/dist/behaviour-kinds.d.ts.map +1 -1
  10. package/dist/builder.d.ts.map +1 -1
  11. package/dist/change-set.d.ts +232 -0
  12. package/dist/change-set.d.ts.map +1 -0
  13. package/dist/cli/commands/audit.d.ts +7 -0
  14. package/dist/cli/commands/audit.d.ts.map +1 -1
  15. package/dist/cli/commands/build.d.ts.map +1 -1
  16. package/dist/cli/commands/carve-emit.d.ts.map +1 -1
  17. package/dist/cli/commands/check-lexicon.d.ts +16 -0
  18. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  19. package/dist/cli/commands/import.d.ts +8 -0
  20. package/dist/cli/commands/import.d.ts.map +1 -1
  21. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  22. package/dist/cli/commands/init.d.ts +19 -0
  23. package/dist/cli/commands/init.d.ts.map +1 -1
  24. package/dist/cli/commands/onboard.d.ts +9 -0
  25. package/dist/cli/commands/onboard.d.ts.map +1 -1
  26. package/dist/cli/commands/pinned-upgrade.d.ts +19 -5
  27. package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -1
  28. package/dist/cli/handlers/build.d.ts.map +1 -1
  29. package/dist/cli/handlers/change-set.d.ts +11 -0
  30. package/dist/cli/handlers/change-set.d.ts.map +1 -0
  31. package/dist/cli/handlers/dev.d.ts.map +1 -1
  32. package/dist/cli/handlers/fan-out.d.ts +33 -0
  33. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  34. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  35. package/dist/cli/handlers/misc.d.ts.map +1 -1
  36. package/dist/cli/handlers/operator.d.ts +16 -0
  37. package/dist/cli/handlers/operator.d.ts.map +1 -1
  38. package/dist/cli/handlers/pr.d.ts +31 -0
  39. package/dist/cli/handlers/pr.d.ts.map +1 -0
  40. package/dist/cli/handlers/run.d.ts.map +1 -1
  41. package/dist/cli/lsp/server.d.ts.map +1 -1
  42. package/dist/cli/main.d.ts.map +1 -1
  43. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  44. package/dist/cli/mcp/server.d.ts.map +1 -1
  45. package/dist/cli/mcp/tools/build.d.ts.map +1 -1
  46. package/dist/cli/mcp/tools/composites.d.ts.map +1 -1
  47. package/dist/cli/mcp/tools/explain.d.ts.map +1 -1
  48. package/dist/cli/mcp/tools/import.d.ts.map +1 -1
  49. package/dist/cli/mcp/tools/lint.d.ts.map +1 -1
  50. package/dist/cli/mcp/tools/scaffold.d.ts.map +1 -1
  51. package/dist/cli/mcp/tools/search.d.ts.map +1 -1
  52. package/dist/cli/mcp/workspace-tools.d.ts +4 -3
  53. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  54. package/dist/cli/registry.d.ts +74 -3
  55. package/dist/cli/registry.d.ts.map +1 -1
  56. package/dist/codegen/fetch.d.ts.map +1 -1
  57. package/dist/codegen/naming.d.ts.map +1 -1
  58. package/dist/codegen/pinned-upgrade.d.ts +67 -3
  59. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  60. package/dist/codegen/registry.d.ts.map +1 -1
  61. package/dist/components/auto-release.d.ts +16 -0
  62. package/dist/components/auto-release.d.ts.map +1 -1
  63. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  64. package/dist/components/capability.d.ts +53 -0
  65. package/dist/components/capability.d.ts.map +1 -1
  66. package/dist/components/changed-files.d.ts +31 -0
  67. package/dist/components/changed-files.d.ts.map +1 -0
  68. package/dist/components/cli-support.d.ts +9 -1
  69. package/dist/components/cli-support.d.ts.map +1 -1
  70. package/dist/components/component.d.ts +24 -0
  71. package/dist/components/component.d.ts.map +1 -1
  72. package/dist/components/deploy-units.d.ts.map +1 -1
  73. package/dist/components/driver.d.ts +13 -0
  74. package/dist/components/driver.d.ts.map +1 -1
  75. package/dist/components/fan-out-output.d.ts +6 -0
  76. package/dist/components/fan-out-output.d.ts.map +1 -1
  77. package/dist/components/fan-out-record.d.ts +41 -0
  78. package/dist/components/fan-out-record.d.ts.map +1 -0
  79. package/dist/components/fan-out-run.d.ts +65 -0
  80. package/dist/components/fan-out-run.d.ts.map +1 -1
  81. package/dist/components/fan-out-support.d.ts +2 -0
  82. package/dist/components/fan-out-support.d.ts.map +1 -1
  83. package/dist/components/fan-out.d.ts +6 -0
  84. package/dist/components/fan-out.d.ts.map +1 -1
  85. package/dist/components/gated-wave-pipeline.d.ts +50 -0
  86. package/dist/components/gated-wave-pipeline.d.ts.map +1 -0
  87. package/dist/components/index.d.ts +1 -1
  88. package/dist/components/index.d.ts.map +1 -1
  89. package/dist/components/layers.d.ts +25 -0
  90. package/dist/components/layers.d.ts.map +1 -0
  91. package/dist/components/pr-pipeline.d.ts +61 -0
  92. package/dist/components/pr-pipeline.d.ts.map +1 -0
  93. package/dist/components/pr-run.d.ts +119 -0
  94. package/dist/components/pr-run.d.ts.map +1 -0
  95. package/dist/components/promote.d.ts.map +1 -1
  96. package/dist/components/starter-plugin.d.ts.map +1 -1
  97. package/dist/components/verbs/process-runner.d.ts.map +1 -1
  98. package/dist/components/verbs/r2-sync.d.ts.map +1 -1
  99. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  100. package/dist/components/verbs/sbom-generator.d.ts.map +1 -1
  101. package/dist/components/verbs/shell.d.ts.map +1 -1
  102. package/dist/components/verbs/sign.d.ts.map +1 -1
  103. package/dist/components/verbs/verify.d.ts.map +1 -1
  104. package/dist/components/verbs/vuln-gate.d.ts.map +1 -1
  105. package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
  106. package/dist/components/verbs/wrangler.d.ts.map +1 -1
  107. package/dist/components/wave-plan.d.ts +49 -0
  108. package/dist/components/wave-plan.d.ts.map +1 -0
  109. package/dist/composite.d.ts.map +1 -1
  110. package/dist/config.d.ts +19 -7
  111. package/dist/config.d.ts.map +1 -1
  112. package/dist/declarable.d.ts +16 -0
  113. package/dist/declarable.d.ts.map +1 -1
  114. package/dist/discovery/cache.d.ts.map +1 -1
  115. package/dist/discovery/fold-import.d.ts +15 -5
  116. package/dist/discovery/fold-import.d.ts.map +1 -1
  117. package/dist/discovery/param-deps.d.ts +16 -0
  118. package/dist/discovery/param-deps.d.ts.map +1 -1
  119. package/dist/discovery/sandbox/policy-wire.d.ts.map +1 -1
  120. package/dist/discovery/specifier-resolve.d.ts +37 -0
  121. package/dist/discovery/specifier-resolve.d.ts.map +1 -0
  122. package/dist/errors.d.ts.map +1 -1
  123. package/dist/fold/fold.d.ts +3 -1
  124. package/dist/fold/fold.d.ts.map +1 -1
  125. package/dist/gated-waves.d.ts +147 -0
  126. package/dist/gated-waves.d.ts.map +1 -0
  127. package/dist/graph-detail.d.ts.map +1 -1
  128. package/dist/graph-ir.d.ts.map +1 -1
  129. package/dist/graph-layout.d.ts.map +1 -1
  130. package/dist/import/base-parser.d.ts.map +1 -1
  131. package/dist/import/embedded.d.ts +7 -0
  132. package/dist/import/embedded.d.ts.map +1 -1
  133. package/dist/import/parser-options.d.ts +14 -0
  134. package/dist/import/parser-options.d.ts.map +1 -0
  135. package/dist/import/parser.d.ts +17 -0
  136. package/dist/import/parser.d.ts.map +1 -1
  137. package/dist/index.d.ts +1 -0
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/kubectl-context.d.ts.map +1 -1
  140. package/dist/lexicon-output.d.ts.map +1 -1
  141. package/dist/lexicon-schema.d.ts +3 -3
  142. package/dist/lexicon.d.ts +103 -3
  143. package/dist/lexicon.d.ts.map +1 -1
  144. package/dist/lifecycle/assert-live.d.ts.map +1 -1
  145. package/dist/lifecycle/gate-ledger.d.ts +22 -0
  146. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  147. package/dist/lifecycle/git.d.ts +46 -1
  148. package/dist/lifecycle/git.d.ts.map +1 -1
  149. package/dist/lifecycle/member-ledger.d.ts.map +1 -1
  150. package/dist/lifecycle/observe.d.ts.map +1 -1
  151. package/dist/lifecycle/plan-ledger.d.ts.map +1 -1
  152. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  153. package/dist/lifecycle/scenario.d.ts.map +1 -1
  154. package/dist/lifecycle/status.d.ts.map +1 -1
  155. package/dist/lifecycle/work-lease.d.ts +61 -2
  156. package/dist/lifecycle/work-lease.d.ts.map +1 -1
  157. package/dist/lint/config.d.ts +8 -8
  158. package/dist/lint/engine.d.ts +6 -0
  159. package/dist/lint/engine.d.ts.map +1 -1
  160. package/dist/lint/post-synth.d.ts +18 -0
  161. package/dist/lint/post-synth.d.ts.map +1 -1
  162. package/dist/lsp/lexicon-providers.d.ts.map +1 -1
  163. package/dist/op/activities/activity-contracts.d.ts +137 -11
  164. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  165. package/dist/op/activities/apply.d.ts +79 -9
  166. package/dist/op/activities/apply.d.ts.map +1 -1
  167. package/dist/op/activities/change-set.d.ts +62 -0
  168. package/dist/op/activities/change-set.d.ts.map +1 -0
  169. package/dist/op/activities/decide.d.ts +2 -0
  170. package/dist/op/activities/decide.d.ts.map +1 -1
  171. package/dist/op/activities/factory.d.ts +137 -0
  172. package/dist/op/activities/factory.d.ts.map +1 -0
  173. package/dist/op/activities/index.d.ts +5 -1
  174. package/dist/op/activities/index.d.ts.map +1 -1
  175. package/dist/op/activities/lexicon-upgrade.d.ts +44 -12
  176. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -1
  177. package/dist/op/activity-contract.d.ts +1 -1
  178. package/dist/op/activity-contract.d.ts.map +1 -1
  179. package/dist/op/activity-failure.d.ts.map +1 -1
  180. package/dist/op/activity-profiles.d.ts.map +1 -1
  181. package/dist/op/builders.d.ts +11 -0
  182. package/dist/op/builders.d.ts.map +1 -1
  183. package/dist/op/composites/apply-op.d.ts +12 -5
  184. package/dist/op/composites/apply-op.d.ts.map +1 -1
  185. package/dist/op/composites/lexicon-upgrade-op.d.ts +22 -6
  186. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -1
  187. package/dist/op/decide-backend.d.ts +5 -1
  188. package/dist/op/decide-backend.d.ts.map +1 -1
  189. package/dist/op/decide-read-inputs.d.ts +4 -2
  190. package/dist/op/decide-read-inputs.d.ts.map +1 -1
  191. package/dist/op/emulator-lifecycle.d.ts +21 -2
  192. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  193. package/dist/op/factory.d.ts +83 -0
  194. package/dist/op/factory.d.ts.map +1 -0
  195. package/dist/op/gate-approval.d.ts +5 -1
  196. package/dist/op/gate-approval.d.ts.map +1 -1
  197. package/dist/op/gate-wait.d.ts.map +1 -1
  198. package/dist/op/gate.d.ts +19 -3
  199. package/dist/op/gate.d.ts.map +1 -1
  200. package/dist/op/index.d.ts +6 -1
  201. package/dist/op/index.d.ts.map +1 -1
  202. package/dist/op/local-executor.d.ts +6 -0
  203. package/dist/op/local-executor.d.ts.map +1 -1
  204. package/dist/op/op-ir.d.ts +2 -0
  205. package/dist/op/op-ir.d.ts.map +1 -1
  206. package/dist/op/op-verb-class.d.ts.map +1 -1
  207. package/dist/op/operator.d.ts.map +1 -1
  208. package/dist/op/run-context.d.ts +39 -0
  209. package/dist/op/run-context.d.ts.map +1 -0
  210. package/dist/op/run-live.d.ts.map +1 -1
  211. package/dist/op/runtimes/local.d.ts.map +1 -1
  212. package/dist/op/source-archive.d.ts.map +1 -1
  213. package/dist/op/steward-beside.d.ts.map +1 -1
  214. package/dist/op/steward-points.d.ts.map +1 -1
  215. package/dist/op/steward.d.ts.map +1 -1
  216. package/dist/op/types.d.ts +16 -3
  217. package/dist/op/types.d.ts.map +1 -1
  218. package/dist/op/work-lease-run.d.ts +24 -4
  219. package/dist/op/work-lease-run.d.ts.map +1 -1
  220. package/dist/plan-summary.d.ts +207 -0
  221. package/dist/plan-summary.d.ts.map +1 -0
  222. package/dist/pr-forge.d.ts +105 -0
  223. package/dist/pr-forge.d.ts.map +1 -0
  224. package/dist/pr-loop.d.ts +178 -0
  225. package/dist/pr-loop.d.ts.map +1 -0
  226. package/dist/project-root.d.ts.map +1 -1
  227. package/dist/provenance.d.ts +21 -0
  228. package/dist/provenance.d.ts.map +1 -1
  229. package/dist/pseudo-parameter.d.ts.map +1 -1
  230. package/dist/reconcile.d.ts.map +1 -1
  231. package/dist/secret-materialization.d.ts.map +1 -1
  232. package/dist/telemetry-attribution.d.ts +31 -0
  233. package/dist/telemetry-attribution.d.ts.map +1 -1
  234. package/dist/terraform/emit-source.d.ts.map +1 -1
  235. package/dist/terraform/hcl2json.d.ts +45 -0
  236. package/dist/terraform/hcl2json.d.ts.map +1 -0
  237. package/dist/terraform/parse.d.ts +4 -40
  238. package/dist/terraform/parse.d.ts.map +1 -1
  239. package/dist/testing.d.ts.map +1 -1
  240. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
  241. package/dist/workspace/__fixtures__/decide-workspace.d.ts +1 -1
  242. package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -1
  243. package/dist/workspace/agent-cli.d.ts +5 -0
  244. package/dist/workspace/agent-cli.d.ts.map +1 -1
  245. package/dist/workspace/box-cli.d.ts +12 -0
  246. package/dist/workspace/box-cli.d.ts.map +1 -0
  247. package/dist/workspace/box-factory.d.ts +97 -0
  248. package/dist/workspace/box-factory.d.ts.map +1 -0
  249. package/dist/workspace/box-listing.d.ts +85 -0
  250. package/dist/workspace/box-listing.d.ts.map +1 -0
  251. package/dist/workspace/box-publish.d.ts +147 -0
  252. package/dist/workspace/box-publish.d.ts.map +1 -0
  253. package/dist/workspace/broker-protocol.d.ts +190 -0
  254. package/dist/workspace/broker-protocol.d.ts.map +1 -0
  255. package/dist/workspace/changes.d.ts.map +1 -1
  256. package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -1
  257. package/dist/workspace/checks/boxes.d.ts.map +1 -1
  258. package/dist/workspace/checks.d.ts +5 -0
  259. package/dist/workspace/checks.d.ts.map +1 -1
  260. package/dist/workspace/compose-graph.d.ts +10 -0
  261. package/dist/workspace/compose-graph.d.ts.map +1 -1
  262. package/dist/workspace/composites.d.ts +2 -2
  263. package/dist/workspace/composites.d.ts.map +1 -1
  264. package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts +17 -0
  265. package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts.map +1 -0
  266. package/dist/workspace/conformance/broker.d.ts +202 -0
  267. package/dist/workspace/conformance/broker.d.ts.map +1 -0
  268. package/dist/workspace/conformance/index.d.ts +68 -6
  269. package/dist/workspace/conformance/index.d.ts.map +1 -1
  270. package/dist/workspace/conformance/vitest.d.ts +19 -3
  271. package/dist/workspace/conformance/vitest.d.ts.map +1 -1
  272. package/dist/workspace/conformance/writer.d.ts +462 -0
  273. package/dist/workspace/conformance/writer.d.ts.map +1 -0
  274. package/dist/workspace/decide.d.ts +126 -12
  275. package/dist/workspace/decide.d.ts.map +1 -1
  276. package/dist/workspace/decision-points.schema.json +11 -4
  277. package/dist/workspace/declaration.d.ts +156 -4
  278. package/dist/workspace/declaration.d.ts.map +1 -1
  279. package/dist/workspace/declaration.schema.json +383 -5
  280. package/dist/workspace/environments.d.ts +36 -10
  281. package/dist/workspace/environments.d.ts.map +1 -1
  282. package/dist/workspace/factory-rules.d.ts +180 -0
  283. package/dist/workspace/factory-rules.d.ts.map +1 -0
  284. package/dist/workspace/generated-files.d.ts.map +1 -1
  285. package/dist/workspace/graph-cache.d.ts.map +1 -1
  286. package/dist/workspace/graph-cli.d.ts +2 -0
  287. package/dist/workspace/graph-cli.d.ts.map +1 -1
  288. package/dist/workspace/identity.d.ts +111 -0
  289. package/dist/workspace/identity.d.ts.map +1 -0
  290. package/dist/workspace/init.d.ts +21 -0
  291. package/dist/workspace/init.d.ts.map +1 -1
  292. package/dist/workspace/intent-cli.d.ts +7 -4
  293. package/dist/workspace/intent-cli.d.ts.map +1 -1
  294. package/dist/workspace/intent-record.d.ts +36 -2
  295. package/dist/workspace/intent-record.d.ts.map +1 -1
  296. package/dist/workspace/intent.d.ts +249 -8
  297. package/dist/workspace/intent.d.ts.map +1 -1
  298. package/dist/workspace/json-edit.d.ts +24 -0
  299. package/dist/workspace/json-edit.d.ts.map +1 -0
  300. package/dist/workspace/jsonc.d.ts +11 -0
  301. package/dist/workspace/jsonc.d.ts.map +1 -1
  302. package/dist/workspace/kinds.d.ts +66 -4
  303. package/dist/workspace/kinds.d.ts.map +1 -1
  304. package/dist/workspace/lexicon-symbols.d.ts +29 -0
  305. package/dist/workspace/lexicon-symbols.d.ts.map +1 -0
  306. package/dist/workspace/lineage-hash-index.d.ts.map +1 -1
  307. package/dist/workspace/lineage-lock.d.ts +2 -2
  308. package/dist/workspace/lineage-lock.d.ts.map +1 -1
  309. package/dist/workspace/lineage-upgrade.d.ts +31 -2
  310. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  311. package/dist/workspace/links.d.ts.map +1 -1
  312. package/dist/workspace/point-answer.schema.json +42 -2
  313. package/dist/workspace/points-cli.d.ts +10 -3
  314. package/dist/workspace/points-cli.d.ts.map +1 -1
  315. package/dist/workspace/points.d.ts +66 -5
  316. package/dist/workspace/points.d.ts.map +1 -1
  317. package/dist/workspace/principal-classes.d.ts +114 -0
  318. package/dist/workspace/principal-classes.d.ts.map +1 -0
  319. package/dist/workspace/reason-codes.d.ts +53 -4
  320. package/dist/workspace/reason-codes.d.ts.map +1 -1
  321. package/dist/workspace/record-assets.d.ts.map +1 -1
  322. package/dist/workspace/record-sessions.d.ts +5 -7
  323. package/dist/workspace/record-sessions.d.ts.map +1 -1
  324. package/dist/workspace/records-checkout.d.ts +54 -0
  325. package/dist/workspace/records-checkout.d.ts.map +1 -0
  326. package/dist/workspace/records-cli.d.ts +34 -1
  327. package/dist/workspace/records-cli.d.ts.map +1 -1
  328. package/dist/workspace/records-close.d.ts +7 -3
  329. package/dist/workspace/records-close.d.ts.map +1 -1
  330. package/dist/workspace/records-since.d.ts.map +1 -1
  331. package/dist/workspace/records-write.d.ts +68 -7
  332. package/dist/workspace/records-write.d.ts.map +1 -1
  333. package/dist/workspace/records.d.ts +43 -9
  334. package/dist/workspace/records.d.ts.map +1 -1
  335. package/dist/workspace/runs-cli.d.ts +296 -0
  336. package/dist/workspace/runs-cli.d.ts.map +1 -0
  337. package/dist/workspace/runs.d.ts +544 -0
  338. package/dist/workspace/runs.d.ts.map +1 -0
  339. package/dist/workspace/session-kinds.d.ts +1 -1
  340. package/dist/workspace/session-kinds.d.ts.map +1 -1
  341. package/dist/workspace/source-block.d.ts +1 -1
  342. package/dist/workspace/source-block.d.ts.map +1 -1
  343. package/dist/workspace/squash.d.ts +80 -0
  344. package/dist/workspace/squash.d.ts.map +1 -0
  345. package/dist/workspace/status-gates.d.ts +17 -3
  346. package/dist/workspace/status-gates.d.ts.map +1 -1
  347. package/dist/workspace/status.d.ts +64 -0
  348. package/dist/workspace/status.d.ts.map +1 -1
  349. package/dist/workspace/symbols.d.ts +63 -0
  350. package/dist/workspace/symbols.d.ts.map +1 -0
  351. package/dist/workspace/trailer-joins.d.ts +46 -0
  352. package/dist/workspace/trailer-joins.d.ts.map +1 -0
  353. package/dist/workspace/trailers.d.ts +89 -0
  354. package/dist/workspace/trailers.d.ts.map +1 -0
  355. package/dist/workspace/trust/attestor.d.ts.map +1 -1
  356. package/dist/workspace/trust/rotation.d.ts.map +1 -1
  357. package/dist/workspace/trust/run-commits.d.ts +46 -0
  358. package/dist/workspace/trust/run-commits.d.ts.map +1 -0
  359. package/dist/workspace/trust/run-statement.d.ts +128 -0
  360. package/dist/workspace/trust/run-statement.d.ts.map +1 -0
  361. package/dist/workspace/trust/seal.d.ts +38 -0
  362. package/dist/workspace/trust/seal.d.ts.map +1 -1
  363. package/dist/workspace/trust/test-repo.d.ts.map +1 -1
  364. package/dist/workspace/trust/verify-cli.d.ts +1 -1
  365. package/dist/workspace/trust/verify.d.ts +16 -2
  366. package/dist/workspace/trust/verify.d.ts.map +1 -1
  367. package/dist/workspace/wip-cli.d.ts +21 -0
  368. package/dist/workspace/wip-cli.d.ts.map +1 -0
  369. package/dist/workspace/wip.d.ts +268 -0
  370. package/dist/workspace/wip.d.ts.map +1 -0
  371. package/dist/workspace/work-cli.d.ts +39 -3
  372. package/dist/workspace/work-cli.d.ts.map +1 -1
  373. package/dist/workspace/work-evidence.d.ts +1 -1
  374. package/dist/workspace/work-evidence.d.ts.map +1 -1
  375. package/dist/workspace/work-size.d.ts +55 -0
  376. package/dist/workspace/work-size.d.ts.map +1 -0
  377. package/dist/workspace/work.d.ts +26 -1
  378. package/dist/workspace/work.d.ts.map +1 -1
  379. package/dist/workspace/workspace-kinds.schema.json +122 -0
  380. package/dist/workspace/workspace-principals.schema.json +60 -0
  381. package/dist/workspace/write-lock-cli.d.ts +60 -0
  382. package/dist/workspace/write-lock-cli.d.ts.map +1 -0
  383. package/dist/workspace/write-lock.d.ts +152 -0
  384. package/dist/workspace/write-lock.d.ts.map +1 -0
  385. package/dist/workspace/write-scope.d.ts +83 -19
  386. package/dist/workspace/write-scope.d.ts.map +1 -1
  387. package/dist/yaml.d.ts +21 -39
  388. package/dist/yaml.d.ts.map +1 -1
  389. package/package.json +7 -2
  390. package/src/__fixtures__/change-set/lifecycle-plan.floci.json +59 -0
  391. package/src/__fixtures__/change-set/lifecycle-v1.ts.txt +4 -0
  392. package/src/__fixtures__/change-set/lifecycle-v2.ts.txt +4 -0
  393. package/src/__fixtures__/change-set/lifecycle.change-set.golden.json +95 -0
  394. package/src/__fixtures__/change-set/warden.change-set.golden.json +106 -0
  395. package/src/__fixtures__/change-set/warden.plan.json +44 -0
  396. package/src/__fixtures__/plan-summary/normalization-vectors.json +1593 -0
  397. package/src/__fixtures__/pr-loop/pr-apply-applied.note.golden.md +31 -0
  398. package/src/__fixtures__/pr-loop/pr-apply-refused.note.golden.md +31 -0
  399. package/src/__fixtures__/pr-loop/pr-plan.golden.json +127 -0
  400. package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +37 -0
  401. package/src/audit/core.test.ts +15 -0
  402. package/src/audit/core.ts +8 -2
  403. package/src/audit/discover.test.ts +11 -0
  404. package/src/audit/discover.ts +7 -2
  405. package/src/audit/prior-art.ts +15 -0
  406. package/src/change-set-bundle.test.ts +57 -0
  407. package/src/change-set.test.ts +215 -0
  408. package/src/change-set.ts +445 -0
  409. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +1 -1
  410. package/src/cli/commands/audit-opt-in.test.ts +54 -0
  411. package/src/cli/commands/audit.ts +29 -2
  412. package/src/cli/commands/build.test.ts +19 -0
  413. package/src/cli/commands/build.ts +3 -2
  414. package/src/cli/commands/carve-emit-state.test.ts +4 -0
  415. package/src/cli/commands/carve-emit.ts +5 -19
  416. package/src/cli/commands/check-lexicon.test.ts +62 -1
  417. package/src/cli/commands/check-lexicon.ts +36 -6
  418. package/src/cli/commands/import-live.test.ts +18 -0
  419. package/src/cli/commands/import-parser-options.test.ts +133 -0
  420. package/src/cli/commands/import.ts +21 -3
  421. package/src/cli/commands/init-lexicon/templates/project.ts +1 -1
  422. package/src/cli/commands/init.test.ts +8 -1
  423. package/src/cli/commands/init.ts +23 -8
  424. package/src/cli/commands/lint.test.ts +37 -0
  425. package/src/cli/commands/onboard.test.ts +53 -3
  426. package/src/cli/commands/onboard.ts +52 -4
  427. package/src/cli/commands/pinned-upgrade.ts +73 -33
  428. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +2 -2
  429. package/src/cli/handlers/build.ts +13 -1
  430. package/src/cli/handlers/change-set.test.ts +56 -0
  431. package/src/cli/handlers/change-set.ts +44 -0
  432. package/src/cli/handlers/components.ts +2 -2
  433. package/src/cli/handlers/dev.ts +8 -6
  434. package/src/cli/handlers/fan-out.test.ts +221 -2
  435. package/src/cli/handlers/fan-out.ts +165 -75
  436. package/src/cli/handlers/graph.ts +3 -0
  437. package/src/cli/handlers/lifecycle.test.ts +67 -0
  438. package/src/cli/handlers/lifecycle.ts +6 -5
  439. package/src/cli/handlers/misc.ts +2 -0
  440. package/src/cli/handlers/operator.test.ts +21 -0
  441. package/src/cli/handlers/operator.ts +121 -6
  442. package/src/cli/handlers/pr.ts +373 -0
  443. package/src/cli/handlers/run.test.ts +111 -0
  444. package/src/cli/handlers/run.ts +86 -24
  445. package/src/cli/handlers/scenario.ts +2 -2
  446. package/src/cli/main.test.ts +21 -0
  447. package/src/cli/main.ts +246 -30
  448. package/src/cli/mcp/never-over-mcp.test.ts +101 -0
  449. package/src/cli/mcp/op-tools.ts +24 -2
  450. package/src/cli/mcp/workspace-tools.test.ts +5 -2
  451. package/src/cli/mcp/workspace-tools.ts +62 -7
  452. package/src/cli/registry.ts +74 -3
  453. package/src/codegen/pinned-upgrade-multi.test.ts +157 -0
  454. package/src/codegen/pinned-upgrade-tags.test.ts +112 -0
  455. package/src/codegen/pinned-upgrade.test.ts +104 -0
  456. package/src/codegen/pinned-upgrade.ts +250 -56
  457. package/src/codegen/testdata/postgres-tags.json +242 -0
  458. package/src/components/auto-release.ts +1 -1
  459. package/src/components/capability.ts +55 -0
  460. package/src/components/changed-files.ts +66 -0
  461. package/src/components/cli-support.ts +28 -5
  462. package/src/components/component.schema.json +17 -0
  463. package/src/components/component.ts +25 -0
  464. package/src/components/deploy-units.ts +3 -0
  465. package/src/components/driver.test.ts +52 -0
  466. package/src/components/driver.ts +31 -13
  467. package/src/components/fan-out-output.ts +42 -1
  468. package/src/components/fan-out-record.ts +69 -0
  469. package/src/components/fan-out-run.test.ts +17 -0
  470. package/src/components/fan-out-run.ts +304 -1
  471. package/src/components/fan-out-support.ts +3 -0
  472. package/src/components/fan-out-waves.test.ts +375 -0
  473. package/src/components/fan-out.ts +18 -17
  474. package/src/components/gated-wave-pipeline.ts +82 -0
  475. package/src/components/index.ts +1 -0
  476. package/src/components/layers.ts +30 -0
  477. package/src/components/pr-pipeline.ts +91 -0
  478. package/src/components/pr-run.test.ts +205 -0
  479. package/src/components/pr-run.ts +280 -0
  480. package/src/components/promote.ts +5 -0
  481. package/src/components/verbs/shell.test.ts +11 -0
  482. package/src/components/verbs/shell.ts +7 -3
  483. package/src/components/wave-plan.ts +124 -0
  484. package/src/config.test.ts +21 -0
  485. package/src/config.ts +15 -0
  486. package/src/declarable.test.ts +21 -0
  487. package/src/declarable.ts +19 -0
  488. package/src/discovery/fold-composite.test.ts +41 -5
  489. package/src/discovery/fold-import.test.ts +129 -0
  490. package/src/discovery/fold-import.ts +643 -131
  491. package/src/discovery/fold-package-composite.test.ts +264 -0
  492. package/src/discovery/fold-specifiers.test.ts +191 -0
  493. package/src/discovery/param-deps.test.ts +66 -1
  494. package/src/discovery/param-deps.ts +45 -0
  495. package/src/discovery/sandbox/bundle.ts +1 -1
  496. package/src/discovery/specifier-resolve.ts +344 -0
  497. package/src/fold/fold.test.ts +39 -1
  498. package/src/fold/fold.ts +83 -9
  499. package/src/fold-provenance.test.ts +140 -0
  500. package/src/gated-waves-bundle.test.ts +62 -0
  501. package/src/gated-waves.test.ts +118 -0
  502. package/src/gated-waves.ts +240 -0
  503. package/src/graph-ir.test.ts +83 -0
  504. package/src/graph-ir.ts +29 -0
  505. package/src/import/embedded.test.ts +20 -0
  506. package/src/import/embedded.ts +13 -0
  507. package/src/import/parser-options.ts +46 -0
  508. package/src/import/parser.ts +20 -0
  509. package/src/index.ts +1 -0
  510. package/src/lexicon.ts +106 -3
  511. package/src/lifecycle/gate-ledger.ts +23 -0
  512. package/src/lifecycle/git.ts +102 -16
  513. package/src/lifecycle/observe.test.ts +18 -0
  514. package/src/lifecycle/observe.ts +6 -4
  515. package/src/lifecycle/snapshot.ts +2 -2
  516. package/src/lifecycle/work-lease.test.ts +1 -1
  517. package/src/lifecycle/work-lease.ts +93 -2
  518. package/src/lint/engine.test.ts +55 -0
  519. package/src/lint/engine.ts +30 -4
  520. package/src/lint/output-docs.test.ts +59 -56
  521. package/src/lint/post-synth.test.ts +19 -0
  522. package/src/lint/post-synth.ts +19 -1
  523. package/src/meta/declared-imports.test.ts +1 -1
  524. package/src/op/activities/activity-contracts.ts +84 -0
  525. package/src/op/activities/apply.test.ts +189 -5
  526. package/src/op/activities/apply.ts +230 -8
  527. package/src/op/activities/change-set.ts +114 -0
  528. package/src/op/activities/decide.ts +3 -0
  529. package/src/op/activities/factory.ts +675 -0
  530. package/src/op/activities/index.ts +9 -0
  531. package/src/op/activities/lexicon-upgrade.test.ts +160 -6
  532. package/src/op/activities/lexicon-upgrade.ts +154 -51
  533. package/src/op/activity-contract.test.ts +21 -1
  534. package/src/op/activity-contract.ts +19 -9
  535. package/src/op/builders.ts +23 -0
  536. package/src/op/composites/apply-op.ts +12 -5
  537. package/src/op/composites/composites.test.ts +30 -3
  538. package/src/op/composites/lexicon-upgrade-op.test.ts +7 -2
  539. package/src/op/composites/lexicon-upgrade-op.ts +29 -8
  540. package/src/op/decide-backend.ts +5 -1
  541. package/src/op/decide-read-inputs.ts +33 -5
  542. package/src/op/emulator-lifecycle.test.ts +23 -0
  543. package/src/op/emulator-lifecycle.ts +52 -14
  544. package/src/op/factory.e2e.test.ts +232 -0
  545. package/src/op/factory.ts +118 -0
  546. package/src/op/gate-approval.test.ts +74 -0
  547. package/src/op/gate-approval.ts +5 -1
  548. package/src/op/gate.ts +31 -5
  549. package/src/op/index.ts +11 -1
  550. package/src/op/local-executor.test.ts +15 -0
  551. package/src/op/local-executor.ts +40 -12
  552. package/src/op/local-output.ts +1 -1
  553. package/src/op/op-ir.test.ts +9 -0
  554. package/src/op/op-ir.ts +4 -0
  555. package/src/op/op-verb-class.ts +3 -0
  556. package/src/op/operator.ts +4 -0
  557. package/src/op/run-context.test.ts +141 -0
  558. package/src/op/run-context.ts +51 -0
  559. package/src/op/runtimes/local.test.ts +14 -0
  560. package/src/op/runtimes/local.ts +2 -0
  561. package/src/op/steward-beside.ts +2 -0
  562. package/src/op/types.ts +16 -3
  563. package/src/op/work-lease-run.test.ts +47 -0
  564. package/src/op/work-lease-run.ts +76 -11
  565. package/src/plan-summary.test.ts +263 -0
  566. package/src/plan-summary.ts +845 -0
  567. package/src/pr-forge.test.ts +237 -0
  568. package/src/pr-forge.ts +332 -0
  569. package/src/pr-loop-bundle.test.ts +46 -0
  570. package/src/pr-loop.test.ts +171 -0
  571. package/src/pr-loop.ts +324 -0
  572. package/src/provenance.ts +35 -0
  573. package/src/telemetry-attribution.test.ts +23 -1
  574. package/src/telemetry-attribution.ts +51 -0
  575. package/src/terraform/hcl2json.test.ts +21 -0
  576. package/src/terraform/hcl2json.ts +81 -0
  577. package/src/terraform/parse.ts +11 -74
  578. package/src/workspace/agent-cli.ts +7 -3
  579. package/src/workspace/agent.schema.json +22 -0
  580. package/src/workspace/app-kind.test.ts +196 -0
  581. package/src/workspace/box-cli.ts +113 -0
  582. package/src/workspace/box-factory.test.ts +323 -0
  583. package/src/workspace/box-factory.ts +136 -0
  584. package/src/workspace/box-listing-write.schema.json +204 -0
  585. package/src/workspace/box-listing.test.ts +234 -0
  586. package/src/workspace/box-listing.ts +324 -0
  587. package/src/workspace/box-publish.schema.json +498 -0
  588. package/src/workspace/box-publish.test.ts +204 -0
  589. package/src/workspace/box-publish.ts +420 -0
  590. package/src/workspace/box-ship.test.ts +96 -0
  591. package/src/workspace/broker-protocol.schema.json +186 -0
  592. package/src/workspace/broker-protocol.test.ts +122 -0
  593. package/src/workspace/broker-protocol.ts +317 -0
  594. package/src/workspace/builder-tiers.test.ts +146 -0
  595. package/src/workspace/change-set.schema.json +460 -0
  596. package/src/workspace/changes.schema.json +12 -20
  597. package/src/workspace/changes.ts +4 -1
  598. package/src/workspace/chant-migrations.e2e.test.ts +17 -5
  599. package/src/workspace/checks/boxes.test.ts +5 -0
  600. package/src/workspace/checks.ts +39 -8
  601. package/src/workspace/component-environments.test.ts +105 -0
  602. package/src/workspace/compose-graph.ts +7 -0
  603. package/src/workspace/composites.schema.json +23 -4
  604. package/src/workspace/composites.test.ts +8 -8
  605. package/src/workspace/composites.ts +13 -2
  606. package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +2 -2
  607. package/src/workspace/conformance/__fixtures__/reference-broker.ts +207 -0
  608. package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
  609. package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
  610. package/src/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
  611. package/src/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
  612. package/src/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
  613. package/src/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
  614. package/src/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
  615. package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
  616. package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
  617. package/src/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  618. package/src/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  619. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
  620. package/src/workspace/conformance/broker.test.ts +122 -0
  621. package/src/workspace/conformance/broker.ts +792 -0
  622. package/src/workspace/conformance/conformance.e2e.test.ts +36 -3
  623. package/src/workspace/conformance/index.mjs +51 -3
  624. package/src/workspace/conformance/index.ts +107 -15
  625. package/src/workspace/conformance/vitest.ts +76 -2
  626. package/src/workspace/conformance/writer-conformance.e2e.test.ts +177 -0
  627. package/src/workspace/conformance/writer.test.ts +186 -0
  628. package/src/workspace/conformance/writer.ts +1191 -0
  629. package/src/workspace/decide.test.ts +208 -4
  630. package/src/workspace/decide.ts +433 -73
  631. package/src/workspace/decision-points.schema.json +11 -4
  632. package/src/workspace/declaration.schema.json +383 -5
  633. package/src/workspace/declaration.ts +315 -10
  634. package/src/workspace/environments.ts +66 -14
  635. package/src/workspace/factory-rules.test.ts +62 -0
  636. package/src/workspace/factory-rules.ts +218 -0
  637. package/src/workspace/graph-cli.ts +6 -3
  638. package/src/workspace/graph.schema.json +314 -0
  639. package/src/workspace/identity.test.ts +219 -0
  640. package/src/workspace/identity.ts +186 -0
  641. package/src/workspace/init.ts +82 -2
  642. package/src/workspace/intent-cli.ts +84 -13
  643. package/src/workspace/intent-patch-id.test.ts +162 -0
  644. package/src/workspace/intent-record.schema.json +336 -1
  645. package/src/workspace/intent-record.ts +96 -16
  646. package/src/workspace/intent-reviews.test.ts +76 -0
  647. package/src/workspace/intent-squash.test.ts +213 -0
  648. package/src/workspace/intent-why.test.ts +274 -0
  649. package/src/workspace/intent.schema.json +950 -9
  650. package/src/workspace/intent.test.ts +11 -2
  651. package/src/workspace/intent.ts +722 -65
  652. package/src/workspace/json-edit.test.ts +121 -0
  653. package/src/workspace/json-edit.ts +142 -0
  654. package/src/workspace/jsonc.ts +20 -0
  655. package/src/workspace/kinds.ts +201 -39
  656. package/src/workspace/lexicon-symbols.test.ts +148 -0
  657. package/src/workspace/lexicon-symbols.ts +125 -0
  658. package/src/workspace/lineage-upgrade.test.ts +63 -0
  659. package/src/workspace/lineage-upgrade.ts +146 -5
  660. package/src/workspace/plan-summary.schema.json +155 -0
  661. package/src/workspace/point-answer.schema.json +42 -2
  662. package/src/workspace/points-cli.ts +42 -16
  663. package/src/workspace/points-write.schema.json +163 -4
  664. package/src/workspace/points.schema.json +157 -2
  665. package/src/workspace/points.test.ts +13 -1
  666. package/src/workspace/points.ts +118 -12
  667. package/src/workspace/pr-report.schema.json +95 -0
  668. package/src/workspace/principal-classes.test.ts +175 -0
  669. package/src/workspace/principal-classes.ts +307 -0
  670. package/src/workspace/profiles.test.ts +159 -0
  671. package/src/workspace/read-contract.test.ts +2 -2
  672. package/src/workspace/reason-codes.test.ts +23 -3
  673. package/src/workspace/reason-codes.ts +61 -4
  674. package/src/workspace/record-sessions.ts +9 -8
  675. package/src/workspace/records-amend.schema.json +80 -0
  676. package/src/workspace/records-checkout.ts +106 -0
  677. package/src/workspace/records-cli.ts +123 -17
  678. package/src/workspace/records-close.schema.json +79 -0
  679. package/src/workspace/records-close.ts +31 -7
  680. package/src/workspace/records-concurrent.e2e.test.ts +135 -0
  681. package/src/workspace/records-concurrent.test.ts +145 -0
  682. package/src/workspace/records-formats.test.ts +46 -10
  683. package/src/workspace/records-new.schema.json +9 -0
  684. package/src/workspace/records-review.schema.json +80 -0
  685. package/src/workspace/records-sessions-write.test.ts +69 -0
  686. package/src/workspace/records-sessions.test.ts +22 -0
  687. package/src/workspace/records-uncommitted.test.ts +171 -0
  688. package/src/workspace/records-write.ts +219 -30
  689. package/src/workspace/records.schema.json +88 -1
  690. package/src/workspace/records.ts +76 -8
  691. package/src/workspace/reference-kinds/app/package.json +10 -0
  692. package/src/workspace/reference-kinds/app/workspace-kinds.json +45 -0
  693. package/src/workspace/run-statement.schema.json +622 -0
  694. package/src/workspace/runs-cli.ts +710 -0
  695. package/src/workspace/runs-statement.test.ts +239 -0
  696. package/src/workspace/runs-write.schema.json +994 -0
  697. package/src/workspace/runs.schema.json +1257 -0
  698. package/src/workspace/runs.test.ts +281 -0
  699. package/src/workspace/runs.ts +970 -0
  700. package/src/workspace/session-kinds.ts +3 -3
  701. package/src/workspace/squash.ts +198 -0
  702. package/src/workspace/status-contract.test.ts +10 -2
  703. package/src/workspace/status-gates.ts +25 -9
  704. package/src/workspace/status.schema.json +252 -4
  705. package/src/workspace/status.ts +110 -1
  706. package/src/workspace/symbols.ts +191 -0
  707. package/src/workspace/trailer-joins.test.ts +171 -0
  708. package/src/workspace/trailer-joins.ts +82 -0
  709. package/src/workspace/trailers.ts +148 -0
  710. package/src/workspace/trust/run-commits.ts +115 -0
  711. package/src/workspace/trust/run-statement.ts +226 -0
  712. package/src/workspace/trust/seal.ts +58 -1
  713. package/src/workspace/trust/verify-cli.ts +6 -5
  714. package/src/workspace/trust/verify.ts +39 -6
  715. package/src/workspace/wip-cli.ts +97 -0
  716. package/src/workspace/wip-write.schema.json +504 -0
  717. package/src/workspace/wip.schema.json +334 -0
  718. package/src/workspace/wip.test.ts +294 -0
  719. package/src/workspace/wip.ts +753 -0
  720. package/src/workspace/work-cli.e2e.test.ts +28 -1
  721. package/src/workspace/work-cli.ts +136 -8
  722. package/src/workspace/work-evidence.schema.json +5 -0
  723. package/src/workspace/work-history.schema.json +73 -1
  724. package/src/workspace/work-history.test.ts +48 -5
  725. package/src/workspace/work-kind-fields.test.ts +154 -0
  726. package/src/workspace/work-lease.schema.json +14 -1
  727. package/src/workspace/work-size.test.ts +77 -0
  728. package/src/workspace/work-size.ts +93 -0
  729. package/src/workspace/work.ts +82 -0
  730. package/src/workspace/workspace-kinds.schema.json +122 -0
  731. package/src/workspace/workspace-principals.schema.json +60 -0
  732. package/src/workspace/write-lock-cli.ts +131 -0
  733. package/src/workspace/write-lock.schema.json +172 -0
  734. package/src/workspace/write-lock.test.ts +189 -0
  735. package/src/workspace/write-lock.ts +474 -0
  736. package/src/workspace/write-scope.test.ts +144 -3
  737. package/src/workspace/write-scope.ts +192 -45
  738. package/src/yaml.test.ts +111 -1
  739. package/src/yaml.ts +141 -549
package/src/graph-ir.ts CHANGED
@@ -384,6 +384,23 @@ function refTarget(ref: AttrRef, reverse: Map<object, string>): string | undefin
384
384
  return ref.getLogicalName() ?? (parent ? reverse.get(parent) : undefined);
385
385
  }
386
386
 
387
+ /**
388
+ * The node id a whole declarable held in a config bag stands for, or undefined
389
+ * when it is not a node of this graph (an inlined property-kind resource, say,
390
+ * which is config of the holder and gets walked instead). An entity can name
391
+ * another entity directly rather than through an AttrRef, as the sql lexicon's
392
+ * enumerable `dependsOn` does with the tables, views and databases a statement
393
+ * mentions (#3257); that is a reference to the node, not a nested bag.
394
+ */
395
+ function nodeReference(
396
+ value: unknown,
397
+ reverse: Map<object, string>,
398
+ nodeIds: Set<string>,
399
+ ): string | undefined {
400
+ const id = reverse.get(value as object);
401
+ return id !== undefined && nodeIds.has(id) ? id : undefined;
402
+ }
403
+
387
404
  /** Project a value into a JSON-safe, scrubbed form. References become `{ $ref }`. */
388
405
  function project(value: unknown, seen: Set<unknown>, reverse: Map<object, string>, nodeIds: Set<string>): unknown {
389
406
  if (value === null) return null;
@@ -414,6 +431,9 @@ function project(value: unknown, seen: Set<unknown>, reverse: Map<object, string
414
431
  // Nested declarables (e.g. an inlined property-kind resource) keep their
415
432
  // config in a non-enumerable `props` bag, like top-level nodes — project that.
416
433
  if (isDeclarable(value)) {
434
+ // Another node held whole is a reference to it, not config to inline.
435
+ const to = nodeReference(value, reverse, nodeIds);
436
+ if (to) return { $ref: to } satisfies AttrRefEnvelope;
417
437
  const out = projectConfig(value, seen, reverse, nodeIds);
418
438
  seen.delete(value);
419
439
  return out;
@@ -518,6 +538,15 @@ function collectEdges(
518
538
  if (to && to !== from && nodeIds.has(to)) edges.push({ from, to, kind: "ref", viaAttr });
519
539
  return;
520
540
  }
541
+ // A whole node held in props or an enumerable field (the sql lexicon's
542
+ // `dependsOn`) is a reference to it: draw the edge, and do not walk its
543
+ // config, whose refs belong to that node's own edges (#3257). Checked
544
+ // before `seen` so the same node under two attributes yields both edges.
545
+ const held = nodeReference(value, reverse, nodeIds);
546
+ if (held) {
547
+ if (held !== from) edges.push({ from, to: held, kind: "ref", viaAttr });
548
+ return;
549
+ }
521
550
  if (seen.has(value)) return;
522
551
  seen.add(value);
523
552
  // A nested declarable (an inlined property-kind resource, e.g. a listener's
@@ -85,6 +85,26 @@ describe("EmbeddedImports", () => {
85
85
  ]);
86
86
  });
87
87
 
88
+ test("an importer that keeps matched content as written is not asked to import it, and its reason is the warning", () => {
89
+ let imported = 0;
90
+ const resolver = new EmbeddedImports([
91
+ {
92
+ lexicon: "acme",
93
+ importer: {
94
+ ...widgets,
95
+ keepsAsWritten: (c) => ((c.document as { size?: number }).size === 3 ? "a size-3 widget builds back as size 4" : undefined),
96
+ import: (c) => (imported++, widgets.import(c)),
97
+ },
98
+ },
99
+ ]);
100
+ expect(resolver.resolve(site())).toBeUndefined();
101
+ expect(imported).toBe(0);
102
+ expect(resolver.files).toEqual([]);
103
+ expect(resolver.warnings).toEqual(['ConfigMap agent data["config.yaml"] is a widget, kept as written: a size-3 widget builds back as size 4']);
104
+ expect(isEmbeddedReference(resolver.resolve(site({ text: "kind: widget\nsize: 2\n" })))).toBe(true);
105
+ expect(imported).toBe(1);
106
+ });
107
+
88
108
  test("when two lexicons match, the first imports it and the other is named", () => {
89
109
  const resolver = new EmbeddedImports([
90
110
  { lexicon: "acme", importer: widgets },
@@ -102,6 +102,13 @@ export interface EmbeddedContentImporter {
102
102
  readonly what: string;
103
103
  /** Whether this content is one it imports. Must not throw on content that is not. */
104
104
  matches(content: EmbeddedContent): boolean;
105
+ /**
106
+ * Why content it matches is kept as written instead of imported, or
107
+ * `undefined` to import it. Asked before `import`; the reason is the
108
+ * warning's. grafana keeps a v2 dashboard, which it reads but would build
109
+ * back as v1 JSON (#3031).
110
+ */
111
+ keepsAsWritten?(content: EmbeddedContent): string | undefined;
105
112
  /** Import it. A throw keeps the content as written, with a warning. */
106
113
  import(content: EmbeddedContent): EmbeddedImport;
107
114
  }
@@ -233,6 +240,12 @@ export class EmbeddedImports implements EmbeddedContentResolver {
233
240
  );
234
241
  }
235
242
 
243
+ const kept = chosen.importer.keepsAsWritten?.(content);
244
+ if (kept !== undefined) {
245
+ this.warnings.push(`${content.location} is ${chosen.importer.what}, kept as written: ${kept}`);
246
+ return undefined;
247
+ }
248
+
236
249
  let result: EmbeddedImport;
237
250
  try {
238
251
  result = chosen.importer.import(content);
@@ -0,0 +1,46 @@
1
+ import type { LexiconPlugin } from "../lexicon";
2
+ import type { ParserOptions, ParserOptionSpec } from "./parser";
3
+
4
+ /**
5
+ * Check `--parser-option` entries (`key` or `key=value`) against what the
6
+ * lexicon declares in `parserOptions()` and convert each value to its declared
7
+ * type (#2994). Returns the options, or an error message naming what is wrong
8
+ * and what the lexicon accepts. An empty list is always valid.
9
+ */
10
+ export function resolveParserOptions(
11
+ plugin: Pick<LexiconPlugin, "name" | "parserOptions">,
12
+ entries: readonly string[] | undefined,
13
+ ): { options: ParserOptions } | { error: string } {
14
+ const options: ParserOptions = {};
15
+ if (!entries || entries.length === 0) return { options };
16
+
17
+ const specs: ParserOptionSpec[] = plugin.parserOptions?.() ?? [];
18
+ const accepted =
19
+ specs.length === 0
20
+ ? `lexicon "${plugin.name}" declares no parser options`
21
+ : `${plugin.name} accepts: ${specs.map((s) => `${s.name} (${s.type}): ${s.description}`).join("; ")}`;
22
+
23
+ for (const entry of entries) {
24
+ const eq = entry.indexOf("=");
25
+ const name = eq === -1 ? entry : entry.slice(0, eq);
26
+ const raw = eq === -1 ? undefined : entry.slice(eq + 1);
27
+ const spec = specs.find((s) => s.name === name);
28
+ if (!spec) {
29
+ return { error: `Unknown parser option "${name}" for lexicon "${plugin.name}"; ${accepted}.` };
30
+ }
31
+ if (spec.type === "boolean") {
32
+ if (raw === undefined || raw === "true") options[name] = true;
33
+ else if (raw === "false") options[name] = false;
34
+ else return { error: `Parser option "${name}" is a boolean: use ${name}, ${name}=true or ${name}=false, got "${raw}".` };
35
+ } else if (raw === undefined) {
36
+ return { error: `Parser option "${name}" needs a value: --parser-option ${name}=<${spec.type}>.` };
37
+ } else if (spec.type === "number") {
38
+ const n = Number(raw);
39
+ if (raw.trim() === "" || !Number.isFinite(n)) return { error: `Parser option "${name}" is a number, got "${raw}".` };
40
+ options[name] = n;
41
+ } else {
42
+ options[name] = raw;
43
+ }
44
+ }
45
+ return { options };
46
+ }
@@ -78,6 +78,26 @@ export interface ParseContext {
78
78
  readonly embedded?: EmbeddedContentResolver;
79
79
  }
80
80
 
81
+ /** A value a parser option takes. */
82
+ export type ParserOptionValue = string | number | boolean;
83
+
84
+ /** The options `chant import --parser-option` hands a lexicon's parser, by name. */
85
+ export type ParserOptions = Record<string, ParserOptionValue>;
86
+
87
+ /**
88
+ * One option a lexicon's parser accepts, declared by `LexiconPlugin.parserOptions()`.
89
+ * `chant import --parser-option <name>[=<value>]` is checked against this list and
90
+ * the value is converted to `type` before `templateParser(options)` sees it.
91
+ */
92
+ export interface ParserOptionSpec {
93
+ /** The key after `--parser-option`, e.g. "acceptLossyV1". */
94
+ name: string;
95
+ /** `boolean` takes `true`/`false`, and a bare `--parser-option name` means true. */
96
+ type: "boolean" | "string" | "number";
97
+ /** One line, shown when the option is refused and in the docs. */
98
+ description: string;
99
+ }
100
+
81
101
  /**
82
102
  * Interface for template parsers that convert external formats to IR
83
103
  */
package/src/index.ts CHANGED
@@ -149,6 +149,7 @@ export * from "./resource-attributes";
149
149
  export * from "./stack-output";
150
150
  export * from "./child-project";
151
151
  export * from "./lsp/types";
152
+ export type { SymbolDeclaration, SymbolResolver } from "./workspace/symbols";
152
153
  export * from "./lsp/lexicon-providers";
153
154
  export * from "./mcp/types";
154
155
  export * from "./lifecycle/index";
package/src/lexicon.ts CHANGED
@@ -3,11 +3,13 @@ import type { Declarable } from "./declarable";
3
3
  import type { LintRule } from "./lint/rule";
4
4
  import type { RuleSpec } from "./lint/declarative";
5
5
  import type { PostSynthCheck } from "./lint/post-synth";
6
- import type { TemplateParser, TemplateIR, ParseContext } from "./import/parser";
6
+ import type { TemplateParser, TemplateIR, ParseContext, ParserOptions, ParserOptionSpec } from "./import/parser";
7
7
  import type { TypeScriptGenerator } from "./import/generator";
8
8
  import type { EmbeddedContentImporter } from "./import/embedded";
9
9
  import type { AgentConfigImporter } from "./agents/importer";
10
10
  import type { ArtifactIntegrity } from "./lexicon-integrity";
11
+ import type { GatedWavePipelineOptions } from "./components/gated-wave-pipeline";
12
+ import type { PrLoopPipelineOptions } from "./components/pr-pipeline";
11
13
  import type { OkfFile } from "./okf";
12
14
  import type { CompletionContext, CompletionItem, HoverContext, HoverInfo, CodeActionContext, CodeAction } from "./lsp/types";
13
15
  import type { McpToolContribution, McpResourceContribution } from "./mcp/types";
@@ -26,6 +28,7 @@ import type { DescribeIdentityOptions, DescribeIdentityResult } from "./identity
26
28
  import type { DeepNormalizationHooks, DeepObservationResult } from "./deep-observation";
27
29
  import type { BehaviourResult, PredictBehaviourOptions } from "./behaviour";
28
30
  import type { BehaviourKinds } from "./behaviour-kinds";
31
+ import type { SymbolResolver } from "./workspace/symbols";
29
32
  import type { DisruptionQuery, DisruptionVerdict } from "./lifecycle/disruption";
30
33
  import type { OwnerChainVerdict } from "./owner-chain";
31
34
  import type { CommandGroup } from "./cli/command-group";
@@ -426,12 +429,26 @@ export interface InitTemplateSet {
426
429
  * repos or version-constant locations. See ./codegen/pinned-upgrade.ts.
427
430
  */
428
431
  export interface UpstreamPin {
432
+ /**
433
+ * Short name for this pin (`clickhouse`, `postgres-17`), used to pick one
434
+ * pin of a plugin that declares several (`chant dev pinned-upgrade <dir>
435
+ * <label>`). Optional on a lone `upstreamPin`, where it defaults to the
436
+ * lexicon's name; required on every entry of `upstreamPins`.
437
+ */
438
+ readonly label?: string;
429
439
  /** Source file (relative to the lexicon package root) holding the pinned version constant. */
430
440
  readonly file: string;
431
441
  /** Regex whose first capture group is the current pinned version in `file`. */
432
442
  readonly pattern: RegExp;
433
443
  /** Rebuild a line that matched `pattern`, substituting the new version. */
434
444
  replace(newVersion: string, line: string): string;
445
+ /**
446
+ * Set when the version line is not the whole pin: other constants (an image
447
+ * digest, a checksum) move with it and `replace` cannot compute them. The
448
+ * upgrade tooling then reports the newer version and this text, and edits
449
+ * nothing. Say what to move and how.
450
+ */
451
+ readonly alsoMoves?: string;
435
452
  /** Where to query for the latest stable upstream tag. */
436
453
  readonly upstream: {
437
454
  readonly owner: string;
@@ -440,6 +457,25 @@ export interface UpstreamPin {
440
457
  readonly kind: "releases" | "tags";
441
458
  /** Only consider tags ending with this suffix (e.g. "-ee" for GitLab). */
442
459
  readonly tagSuffix?: string;
460
+ /**
461
+ * Map a raw tag to the version string the pin stores, or null to skip the
462
+ * tag. For upstreams whose tags are not versions: postgres/postgres tags
463
+ * are `REL_18_6`, `REL_18_BETA1`, `REL9_6_24`, so
464
+ * `(t) => /^REL_(\d+)_(\d+)$/.exec(t)?.slice(1).join(".") ?? null` gives
465
+ * `18.6` and drops betas, release candidates and the old spelling.
466
+ *
467
+ * When set, the tool reads every page of the tag list (not just the first
468
+ * 50), because such lists are not ordered by version, and the version this
469
+ * returns is what `replace` receives and what the report shows. The pinned
470
+ * constant may hold either the mapped version or the raw tag.
471
+ */
472
+ readonly tagVersion?: (tag: string) => string | null;
473
+ /**
474
+ * Only consider versions whose first numeric segment equals the pinned
475
+ * version's, so a pin on `17.9` reports `17.11` and never `18.6`. For
476
+ * lexicons that pin one snapshot per major line. Default false.
477
+ */
478
+ readonly trackMajor?: boolean;
443
479
  };
444
480
  }
445
481
 
@@ -503,6 +539,20 @@ export interface ComponentPipelineOptions {
503
539
  * `["chant", "components", "promote", "--from", <env>, "--to", <promoteTo>]`.
504
540
  */
505
541
  promoteCommand?: string[];
542
+ /**
543
+ * Gated waves (#3049): one job per wave instead of one per component. Job
544
+ * `wave-<k>` runs `chant components fan-out --wave-gate <gate> --wave <k>`
545
+ * and hands the attempt record to the next job. See
546
+ * `components/gated-wave-pipeline.ts`. Unset, the pipeline is unchanged.
547
+ */
548
+ gatedWaves?: GatedWavePipelineOptions;
549
+ /**
550
+ * The pull-request loop (#3183): a plan job on each pull request and an
551
+ * apply job on each push to the target branch, bound to the digest a
552
+ * reviewer approved, instead of one job per component. See
553
+ * `components/pr-pipeline.ts`. Unset, the pipeline is unchanged.
554
+ */
555
+ prLoop?: PrLoopPipelineOptions;
506
556
  /**
507
557
  * The workspace member this pipeline belongs to (#2542, #2524 D19). Core
508
558
  * sets it when the project sits in a member of a `chant.workspace.json`;
@@ -857,6 +907,16 @@ export interface StackStatusObservation {
857
907
  /**
858
908
  * Context for a lexicon's {@link LexiconPlugin.buildRoots} hook (#1548).
859
909
  */
910
+ /** What {@link LexiconPlugin.changedUnits} reads (#3183). */
911
+ export interface ChangedUnitsContext {
912
+ /** The directory `chant.config.*` lives in. Config paths resolve against it. */
913
+ projectRoot: string;
914
+ /** The resolved project configuration, for the lexicon's own namespace. */
915
+ config: Record<string, unknown>;
916
+ /** Files the change added, modified or deleted, relative to `projectRoot`, with `/` separators. */
917
+ changedFiles: string[];
918
+ }
919
+
860
920
  export interface BuildRootContext {
861
921
  /**
862
922
  * The directory the project configuration was loaded from (where
@@ -1160,8 +1220,19 @@ export interface LexiconPlugin {
1160
1220
  */
1161
1221
  detectTemplate?(data: unknown): boolean;
1162
1222
 
1163
- /** Return a parser for importing external templates into IR */
1164
- templateParser?(): TemplateParser;
1223
+ /**
1224
+ * Return a parser for importing external templates into IR. `options` holds
1225
+ * the `chant import --parser-option` values, already checked against
1226
+ * `parserOptions()` and converted to their declared types; it is empty when
1227
+ * none were given.
1228
+ */
1229
+ templateParser?(options?: ParserOptions): TemplateParser;
1230
+
1231
+ /**
1232
+ * The options `templateParser` accepts. `chant import --parser-option` refuses
1233
+ * any name not listed here, so a lexicon with no options leaves this out.
1234
+ */
1235
+ parserOptions?(): ParserOptionSpec[];
1165
1236
 
1166
1237
  /** Return a generator for converting IR to TypeScript */
1167
1238
  templateGenerator?(): TypeScriptGenerator;
@@ -1200,6 +1271,14 @@ export interface LexiconPlugin {
1200
1271
  /** How this lexicon pins its upstream schema version + where to check for a newer one (self-upgrade tooling — see ./codegen/pinned-upgrade.ts). Omit for lexicons with no pinned upstream. */
1201
1272
  readonly upstreamPin?: UpstreamPin;
1202
1273
 
1274
+ /**
1275
+ * Further pins, for a lexicon that pins more than one upstream (sql: the
1276
+ * ClickHouse pin in `upstreamPin` plus one Postgres server per major). Each
1277
+ * entry needs a unique `label`. The upgrade tooling checks `upstreamPin` and
1278
+ * every entry here, one report per pin. Omit when there is one pin.
1279
+ */
1280
+ readonly upstreamPins?: readonly (UpstreamPin & { readonly label: string })[];
1281
+
1203
1282
  /**
1204
1283
  * Generate a CI pipeline from the discovered component graph — the
1205
1284
  * `chant build --components --generate <name>` seam. Only CI-provider
@@ -1259,6 +1338,18 @@ export interface LexiconPlugin {
1259
1338
  */
1260
1339
  buildRoots?(ctx: BuildRootContext): Promise<BuildRootContribution>;
1261
1340
 
1341
+ /**
1342
+ * The units this lexicon owns that a change touched, judged from the
1343
+ * changed files alone (#3183). A unit is a name a component's deploy step
1344
+ * targets (`deploy-units.ts`): the terraform lexicon answers with the
1345
+ * `terraform.roots` entries whose directory, local modules or var files a
1346
+ * changed file sits in. `chant components fan-out --base` and `chant
1347
+ * components pr-plan` add these to the stacks `lifecycle affected` finds,
1348
+ * since a root that is not chant source never shows in an artifact diff.
1349
+ * Omit for lexicons whose units are chant source.
1350
+ */
1351
+ changedUnits?(ctx: ChangedUnitsContext): Promise<string[]>;
1352
+
1262
1353
  /**
1263
1354
  * Facts about the whole read that this lexicon's entities imply, for the
1264
1355
  * graph IR's `meta` bag (#2559). The otel lexicon answers
@@ -1285,6 +1376,18 @@ export interface LexiconPlugin {
1285
1376
  /** Provide code actions for LSP */
1286
1377
  codeActionProvider?(ctx: CodeActionContext): CodeAction[];
1287
1378
 
1379
+ /**
1380
+ * Symbol resolvers for the languages this lexicon's members are written in
1381
+ * (#3313), so `chant workspace graph --intent <path>#<symbol>` names a
1382
+ * declaration in such a file: a table in a `.sql` file, a resource in a
1383
+ * manifest. Each is `{ language, extensions, declarations(path, text) }`,
1384
+ * returning every declaration's dotted name, kind and 1-based line range.
1385
+ * The intent walk asks the lexicons a file's member configures, after
1386
+ * core's TypeScript and JavaScript resolver, which keeps `.ts` and `.js`.
1387
+ * Pure: no I/O, no network. Omit for a lexicon with no such language.
1388
+ */
1389
+ symbolResolvers?(): SymbolResolver[];
1390
+
1288
1391
  // Docs
1289
1392
  /** Generate documentation pages */
1290
1393
  docs?(options?: { verbose?: boolean }): Promise<void>;
@@ -117,6 +117,13 @@ export interface GateResolutionRecord {
117
117
  gate: string;
118
118
  /** Who resolved it — an actor name, the same convention `components release --actor` and `run approve --approver` use. */
119
119
  resolvedBy: string;
120
+ /**
121
+ * Who carried this approval to chant for `resolvedBy` (#3402): `chant
122
+ * approve --relayed-by`, such as a follower program relaying a person's
123
+ * approval. The approver is still `resolvedBy`; a seal covers this field
124
+ * too. Absent when the approver recorded it themselves.
125
+ */
126
+ relayedBy?: string;
120
127
  /** ISO-8601 timestamp, caller-supplied (library code never calls `Date.now()` internally). */
121
128
  timestamp: string;
122
129
  /** Optional free-text context. Before #2028 this was also where a PR link went by convention; put the link in {@link GateResolutionRecord.url} instead and leave this for prose. */
@@ -187,6 +194,22 @@ export interface GateResolutionRecord {
187
194
  * was recorded. Present only when the gate declared a policy.
188
195
  */
189
196
  policyDecision?: GatePolicyDecision;
197
+ /**
198
+ * An ssh signature over this approval by `resolvedBy` (#3163, ws-080):
199
+ * `chant approve --sign`, in the `chant-gate` namespace over the op, gate,
200
+ * environment, plan digest, approver and timestamp. It attests the approver
201
+ * only when the signers file at base lists a key for them. A gate the
202
+ * declaration's `identity.gates` names counts only approvals whose seal
203
+ * verifies. Absent on an unsigned approval.
204
+ */
205
+ seal?: GateApprovalSeal;
206
+ }
207
+
208
+ /** A gate approval's seal (#3163): who signed, the key's fingerprint (reported, never trusted), and the armored signature. */
209
+ export interface GateApprovalSeal {
210
+ signer: string;
211
+ key: string;
212
+ signature: string;
190
213
  }
191
214
 
192
215
  export type GateResolutionInput = Omit<GateResolutionRecord, "version" | "kind">;
@@ -660,44 +660,120 @@ export async function getRemoteLifecycleBranchSha(
660
660
  }
661
661
 
662
662
  /**
663
- * Push the state branch to remote with --force-with-lease.
663
+ * Why a push of the state branch did or did not reach the remote.
664
664
  *
665
- * If the remote chant/lifecycle ref has advanced past the local remote-tracking
666
- * SHA captured at the start of this push, the push is rejected and we throw
667
- * StaleLifecycleBranchError so the caller can surface a recovery hint.
665
+ * - `pushed` — the remote now holds the local tip.
666
+ * - `no-remote` — nothing to push to; local is the whole ledger.
667
+ * - `stale` — the remote moved past the tip this checkout last saw (another
668
+ * writer pushed); fetch, re-apply and retry.
669
+ * - `failed` — git refused for another reason (no network, no credentials,
670
+ * a protected branch); `stderr` is git's first words on it.
671
+ */
672
+ export type LifecyclePushStatus =
673
+ | { status: "pushed"; remote: string; commit: string }
674
+ | { status: "no-remote" }
675
+ | { status: "stale"; remote: string; expected: string | null; stderr: string }
676
+ | { status: "failed"; remote: string; stderr: string };
677
+
678
+ /**
679
+ * Point `refs/remotes/<remote>/chant/lifecycle` at `sha`, the remote tip this
680
+ * checkout has just seen (#3391).
668
681
  *
669
- * Returns false (without throwing) only when no remote is configured at all.
682
+ * The push's lease is that ref, and git only keeps it up to date when the
683
+ * remote's configured fetch refspec covers `chant/lifecycle`. A single-branch
684
+ * clone (`git clone --single-branch`, a CI checkout of one ref, a shallow
685
+ * clone) has a refspec for its one branch only, so neither the explicit
686
+ * `chant/lifecycle:chant/lifecycle` fetch nor a successful push touches the
687
+ * tracking ref. The first push of a new branch then succeeds against an empty
688
+ * lease, and every later one is refused as stale against a remote that holds
689
+ * exactly what this checkout last pushed. Recording the tip ourselves, only at
690
+ * the two moments it is known (a fetch that fast-forwarded or found the local
691
+ * branch ahead, and a push that landed), keeps the lease honest without
692
+ * widening the clone's refspec. It is never set from a diverged fetch: that is
693
+ * the case the lease exists to refuse.
670
694
  */
671
- export async function pushLifecycle(opts?: { cwd?: string }): Promise<boolean> {
695
+ async function trackRemoteLifecycle(remote: string, sha: string, cwd?: string): Promise<void> {
672
696
  const rt = getRuntime();
673
- const remoteResult = await rt.spawn(["git", "remote"], { cwd: opts?.cwd });
674
- if (remoteResult.exitCode !== 0 || !remoteResult.stdout.trim()) return false;
697
+ await rt.spawn(["git", "update-ref", `refs/remotes/${remote}/${STATE_BRANCH}`, sha], { cwd, env: C_LOCALE_ENV });
698
+ }
675
699
 
676
- const remote = remoteResult.stdout.trim().split("\n")[0];
700
+ /**
701
+ * Push the state branch to the ledger remote with --force-with-lease and say
702
+ * what happened (#3391). Never throws for a git refusal; {@link pushLifecycle}
703
+ * is the throwing form most callers use.
704
+ */
705
+ export async function pushLifecycleStatus(opts?: { cwd?: string }): Promise<LifecyclePushStatus> {
706
+ const rt = getRuntime();
707
+ const cwd = opts?.cwd;
708
+ const found = await ledgerRemote(cwd);
709
+ if (found === null) return { status: "no-remote" };
710
+ if ("failed" in found) return { status: "failed", remote: "(unknown)", stderr: found.stderr };
711
+ const { remote } = found;
677
712
 
678
713
  // Capture the lease SHA — if null, the remote ref doesn't exist yet
679
714
  // (first-time push) and we send `--force-with-lease=ref:` (empty SHA),
680
715
  // which git interprets as "ref does not exist on remote".
681
716
  const expected = await getRemoteLifecycleBranchSha(remote, opts);
682
717
  const lease = `refs/heads/${STATE_BRANCH}:${expected ?? ""}`;
718
+ const tip = await getStateBranchTip(cwd);
683
719
 
684
720
  const pushResult = await rt.spawn(
685
721
  ["git", "push", `--force-with-lease=${lease}`, remote, `${STATE_BRANCH}:${STATE_BRANCH}`],
686
- { cwd: opts?.cwd },
722
+ { cwd, env: C_LOCALE_ENV },
687
723
  );
688
724
 
689
725
  if (pushResult.exitCode !== 0) {
690
- const stderr = pushResult.stderr ?? "";
726
+ const stderr = (pushResult.stderr ?? "").trim();
691
727
  if (
692
728
  stderr.includes("stale info") ||
693
729
  stderr.includes("rejected") ||
694
730
  stderr.includes("non-fast-forward")
695
731
  ) {
696
- throw new StaleLifecycleBranchError(expected, stderr);
732
+ return { status: "stale", remote, expected, stderr };
697
733
  }
698
- return false;
734
+ return { status: "failed", remote, stderr };
735
+ }
736
+ if (tip) await trackRemoteLifecycle(remote, tip, cwd);
737
+ return { status: "pushed", remote, commit: tip ?? "" };
738
+ }
739
+
740
+ /**
741
+ * Push the state branch to remote with --force-with-lease.
742
+ *
743
+ * If the remote chant/lifecycle ref has advanced past the local remote-tracking
744
+ * SHA captured at the start of this push, the push is rejected and we throw
745
+ * StaleLifecycleBranchError so the caller can surface a recovery hint.
746
+ *
747
+ * Returns false (without throwing) when no remote is configured, or when git
748
+ * refused the push for a reason other than a stale lease.
749
+ *
750
+ * The remote is the ledger's ({@link ledgerRemote}: `origin` when there is one),
751
+ * the same one {@link fetchLifecycleStatus} reads, and a push that lands
752
+ * records the tip it pushed as the remote-tracking ref, so the next push's
753
+ * lease is right in a single-branch clone too (#3391).
754
+ */
755
+ export async function pushLifecycle(opts?: { cwd?: string }): Promise<boolean> {
756
+ const result = await pushLifecycleStatus(opts);
757
+ if (result.status === "stale") throw new StaleLifecycleBranchError(result.expected, result.stderr);
758
+ return result.status === "pushed";
759
+ }
760
+
761
+ /**
762
+ * One line on why a push did not land, for a write document's `notPushed`
763
+ * (#3391), or null when it did.
764
+ */
765
+ export function describeLifecyclePush(result: LifecyclePushStatus): string | null {
766
+ const said = (stderr: string) => (stderr ? `; git said: ${stderr.split("\n").find((l) => l.trim()) ?? stderr}` : "");
767
+ switch (result.status) {
768
+ case "pushed":
769
+ return null;
770
+ case "no-remote":
771
+ return `this repository has no remote, so ${STATE_BRANCH} stays local`;
772
+ case "stale":
773
+ return `"${result.remote}" holds ${STATE_BRANCH} commits this checkout has not fetched, so the push was refused; fetch ${STATE_BRANCH} and write again${said(result.stderr)}`;
774
+ case "failed":
775
+ return `the push of ${STATE_BRANCH} to "${result.remote}" failed${said(result.stderr)}`;
699
776
  }
700
- return true;
701
777
  }
702
778
 
703
779
  /**
@@ -814,7 +890,12 @@ export async function fetchLifecycleStatus(opts?: { cwd?: string }): Promise<Lif
814
890
  ["git", "fetch", remote, `${STATE_BRANCH}:${STATE_BRANCH}`],
815
891
  { cwd, env: C_LOCALE_ENV },
816
892
  );
817
- if (fetchResult.exitCode === 0) return { status: "fetched" };
893
+ if (fetchResult.exitCode === 0) {
894
+ // The local branch is now the remote's tip; record it for the push's lease (#3391).
895
+ const tip = await getStateBranchTip(cwd);
896
+ if (tip) await trackRemoteLifecycle(remote, tip, cwd);
897
+ return { status: "fetched" };
898
+ }
818
899
 
819
900
  const stderr = (fetchResult.stderr ?? "").trim();
820
901
  if (NO_SUCH_REMOTE_REF_RE.test(stderr)) return { status: "absent", remote };
@@ -834,8 +915,13 @@ export async function fetchLifecycleStatus(opts?: { cwd?: string }): Promise<Lif
834
915
  ["git", "merge-base", "--is-ancestor", PROBE_REF, `refs/heads/${STATE_BRANCH}`],
835
916
  { cwd, env: C_LOCALE_ENV },
836
917
  );
918
+ const remoteTip = contains.exitCode === 0 ? (await rt.spawn(["git", "rev-parse", "--verify", PROBE_REF], { cwd, env: C_LOCALE_ENV })).stdout.trim() : "";
837
919
  await rt.spawn(["git", "update-ref", "-d", PROBE_REF], { cwd, env: C_LOCALE_ENV });
838
- if (contains.exitCode === 0) return { status: "ahead", remote };
920
+ if (contains.exitCode === 0) {
921
+ // Ahead of the remote: its tip is in our history, so it is the right lease (#3391).
922
+ if (remoteTip) await trackRemoteLifecycle(remote, remoteTip, cwd);
923
+ return { status: "ahead", remote };
924
+ }
839
925
  return { status: "diverged", remote, stderr };
840
926
  }
841
927
 
@@ -97,6 +97,24 @@ describe("observeResources", () => {
97
97
  expect(names).toEqual(["web-vpc"]);
98
98
  });
99
99
 
100
+ it("keeps property-kind declarables out of the observation universe (#3001)", async () => {
101
+ // A property-kind declarable (a grafana panel, an aws SecurityGroup_Ingress
102
+ // const) carries props but lives only inside the resource holding it.
103
+ // Asked about on its own, a reader can only say "absent" or "not observed".
104
+ const buildResult = {
105
+ outputs: new Map<string, string>([["aws", "{}"]]),
106
+ entities: new Map<string, unknown>([
107
+ ["web-sg", { lexicon: "aws", entityType: "AWS::EC2::SecurityGroup", kind: "resource", props: {} }],
108
+ ["ingress", { lexicon: "aws", entityType: "AWS::EC2::SecurityGroup.Ingress", kind: "property", props: { FromPort: 443 } }],
109
+ ]),
110
+ errors: [],
111
+ } as unknown as BuildResult;
112
+ let names: string[] = [];
113
+ const plugins = [awsPlugin(({ entityNames }) => { names = entityNames; return {}; })];
114
+ await observeResources("prod", plugins, buildResult);
115
+ expect(names).toEqual(["web-sg"]);
116
+ });
117
+
100
118
  it("collects a throwing plugin into errors instead of failing the whole graph, and reports its entities unobserved (#1089)", async () => {
101
119
  const plugins = [
102
120
  awsPlugin(() => { throw new Error("access denied"); }),
@@ -25,7 +25,7 @@ import {
25
25
  } from "../observation";
26
26
  import { zeroResourcesWarning } from "../live-endpoint";
27
27
  import { unqualifiedKey } from "./identity";
28
- import { isResourceDeclarable } from "../declarable";
28
+ import { isObservableDeclarable } from "../declarable";
29
29
 
30
30
  export interface ObserveResult {
31
31
  observations: LiveObservation[];
@@ -150,8 +150,10 @@ export async function observeResources(
150
150
  // parameters and serializer directives (gcp's `defaultAnnotations`) are
151
151
  // build-time inputs — declared, but with nothing in any cloud to compare
152
152
  // against, so keeping them in the universe makes every diff report a
153
- // hole (or worse, a deletion) for a resource that cannot exist.
154
- if (!isResourceDeclarable(entity)) continue;
153
+ // hole (or worse, a deletion) for a resource that cannot exist. A
154
+ // property-kind declarable is read as part of the resource holding it,
155
+ // never on its own (#3001).
156
+ if (!isObservableDeclarable(entity)) continue;
155
157
  entityNames.push(name);
156
158
  entities.set(name, {
157
159
  entityType: entity.entityType,
@@ -174,7 +176,7 @@ export async function observeResources(
174
176
  stackEntityNames = [];
175
177
  stackEntities = new Map();
176
178
  for (const [name, entity] of sb.entities) {
177
- if (entity.lexicon !== plugin.name || !isResourceDeclarable(entity)) continue;
179
+ if (entity.lexicon !== plugin.name || !isObservableDeclarable(entity)) continue;
178
180
  stackEntityNames.push(name);
179
181
  stackEntities.set(name, {
180
182
  entityType: entity.entityType,
@@ -18,7 +18,7 @@ import { formatUnobserved, normalizeObservation, unobservedAll, type UnobservedE
18
18
  // property tree is ever rendered or committed. Two lists would eventually
19
19
  // disagree about what counts as a secret.
20
20
  import { isSensitiveKey } from "../deep-observation";
21
- import { isResourceDeclarable } from "../declarable";
21
+ import { isObservableDeclarable } from "../declarable";
22
22
 
23
23
  /**
24
24
  * Check for potential sensitive data in resource attributes and return warnings.
@@ -128,7 +128,7 @@ export async function takeSnapshot(
128
128
  for (const [name, entity] of buildResult.entities) {
129
129
  // Resource declarables only — outputs, parameters and serializer
130
130
  // directives have no live counterpart (see lifecycle/observe.ts).
131
- if (entity.lexicon === plugin.name && isResourceDeclarable(entity)) {
131
+ if (entity.lexicon === plugin.name && isObservableDeclarable(entity)) {
132
132
  entityNames.push(name);
133
133
  entities.set(name, {
134
134
  entityType: entity.entityType,