@manifest-network/manifest-agent-core 0.9.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 (99) hide show
  1. package/README.md +39 -0
  2. package/dist/close-lease.d.ts +33 -0
  3. package/dist/close-lease.d.ts.map +1 -0
  4. package/dist/close-lease.js +138 -0
  5. package/dist/close-lease.js.map +1 -0
  6. package/dist/deploy-app.d.ts +24 -0
  7. package/dist/deploy-app.d.ts.map +1 -0
  8. package/dist/deploy-app.js +446 -0
  9. package/dist/deploy-app.js.map +1 -0
  10. package/dist/index.d.ts +8 -0
  11. package/dist/index.js +7 -0
  12. package/dist/internals/classify-deploy-error.d.ts +41 -0
  13. package/dist/internals/classify-deploy-error.d.ts.map +1 -0
  14. package/dist/internals/classify-deploy-error.js +79 -0
  15. package/dist/internals/classify-deploy-error.js.map +1 -0
  16. package/dist/internals/classify-deploy-response.d.ts +56 -0
  17. package/dist/internals/classify-deploy-response.d.ts.map +1 -0
  18. package/dist/internals/classify-deploy-response.js +33 -0
  19. package/dist/internals/classify-deploy-response.js.map +1 -0
  20. package/dist/internals/connection.d.ts +76 -0
  21. package/dist/internals/connection.d.ts.map +1 -0
  22. package/dist/internals/connection.js +94 -0
  23. package/dist/internals/connection.js.map +1 -0
  24. package/dist/internals/evaluate-readiness.d.ts +55 -0
  25. package/dist/internals/evaluate-readiness.d.ts.map +1 -0
  26. package/dist/internals/evaluate-readiness.js +131 -0
  27. package/dist/internals/evaluate-readiness.js.map +1 -0
  28. package/dist/internals/find-sku-uuid.d.ts +40 -0
  29. package/dist/internals/find-sku-uuid.d.ts.map +1 -0
  30. package/dist/internals/find-sku-uuid.js +20 -0
  31. package/dist/internals/find-sku-uuid.js.map +1 -0
  32. package/dist/internals/format-success.d.ts +35 -0
  33. package/dist/internals/format-success.d.ts.map +1 -0
  34. package/dist/internals/format-success.js +80 -0
  35. package/dist/internals/format-success.js.map +1 -0
  36. package/dist/internals/guarded-fetch.d.ts +138 -0
  37. package/dist/internals/guarded-fetch.d.ts.map +1 -0
  38. package/dist/internals/guarded-fetch.js +242 -0
  39. package/dist/internals/guarded-fetch.js.map +1 -0
  40. package/dist/internals/humanize-denom.d.ts +45 -0
  41. package/dist/internals/humanize-denom.d.ts.map +1 -0
  42. package/dist/internals/humanize-denom.js +105 -0
  43. package/dist/internals/humanize-denom.js.map +1 -0
  44. package/dist/internals/inspect-image.d.ts +31 -0
  45. package/dist/internals/inspect-image.d.ts.map +1 -0
  46. package/dist/internals/inspect-image.js +345 -0
  47. package/dist/internals/inspect-image.js.map +1 -0
  48. package/dist/internals/lease-items.d.ts +46 -0
  49. package/dist/internals/lease-items.d.ts.map +1 -0
  50. package/dist/internals/lease-items.js +58 -0
  51. package/dist/internals/lease-items.js.map +1 -0
  52. package/dist/internals/lease-state.d.ts +32 -0
  53. package/dist/internals/lease-state.d.ts.map +1 -0
  54. package/dist/internals/lease-state.js +80 -0
  55. package/dist/internals/lease-state.js.map +1 -0
  56. package/dist/internals/render-deployment-plan.d.ts +22 -0
  57. package/dist/internals/render-deployment-plan.d.ts.map +1 -0
  58. package/dist/internals/render-deployment-plan.js +135 -0
  59. package/dist/internals/render-deployment-plan.js.map +1 -0
  60. package/dist/internals/render-intent-recap.d.ts +43 -0
  61. package/dist/internals/render-intent-recap.d.ts.map +1 -0
  62. package/dist/internals/render-intent-recap.js +136 -0
  63. package/dist/internals/render-intent-recap.js.map +1 -0
  64. package/dist/internals/render-partial-success-prompt.d.ts +26 -0
  65. package/dist/internals/render-partial-success-prompt.d.ts.map +1 -0
  66. package/dist/internals/render-partial-success-prompt.js +53 -0
  67. package/dist/internals/render-partial-success-prompt.js.map +1 -0
  68. package/dist/internals/save-manifest.d.ts +105 -0
  69. package/dist/internals/save-manifest.d.ts.map +1 -0
  70. package/dist/internals/save-manifest.js +122 -0
  71. package/dist/internals/save-manifest.js.map +1 -0
  72. package/dist/internals/secret-denylist.d.ts +42 -0
  73. package/dist/internals/secret-denylist.d.ts.map +1 -0
  74. package/dist/internals/secret-denylist.js +59 -0
  75. package/dist/internals/secret-denylist.js.map +1 -0
  76. package/dist/internals/spec-normalize.d.ts +84 -0
  77. package/dist/internals/spec-normalize.d.ts.map +1 -0
  78. package/dist/internals/spec-normalize.js +169 -0
  79. package/dist/internals/spec-normalize.js.map +1 -0
  80. package/dist/internals/verify-domain-state.d.ts +20 -0
  81. package/dist/internals/verify-domain-state.d.ts.map +1 -0
  82. package/dist/internals/verify-domain-state.js +63 -0
  83. package/dist/internals/verify-domain-state.js.map +1 -0
  84. package/dist/internals/verify-recover.d.ts +120 -0
  85. package/dist/internals/verify-recover.d.ts.map +1 -0
  86. package/dist/internals/verify-recover.js +91 -0
  87. package/dist/internals/verify-recover.js.map +1 -0
  88. package/dist/manage-domain.d.ts +36 -0
  89. package/dist/manage-domain.d.ts.map +1 -0
  90. package/dist/manage-domain.js +230 -0
  91. package/dist/manage-domain.js.map +1 -0
  92. package/dist/troubleshoot.d.ts +23 -0
  93. package/dist/troubleshoot.d.ts.map +1 -0
  94. package/dist/troubleshoot.js +124 -0
  95. package/dist/troubleshoot.js.map +1 -0
  96. package/dist/types.d.ts +294 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +0 -0
  99. package/package.json +56 -0
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # @manifest-network/manifest-agent-core
2
+
3
+ TypeScript orchestration surface for Manifest agent flows. This package owns the deploy / manage-domain / troubleshoot / close-lease orchestration that host surfaces consume in lockstep — a bug fix in the core's recovery branch fixes every host surface simultaneously.
4
+
5
+ > **Status.** All four orchestration functions have real implementations as of ENG-129 (PRs 1–4). The package remains `private: true` pending a publish decision; do not depend on it from external repos yet.
6
+
7
+ See [ENG-127](https://linear.app/liftedinit/issue/ENG-127) for the broader initiative and [ENG-128](https://linear.app/liftedinit/issue/ENG-128) for the bootstrap PR.
8
+
9
+ ## Layering
10
+
11
+ ```
12
+ manifest-mcp-mono — protocol-level tools (RPC over MCP)
13
+ manifest-agent-core — orchestration, verification, recovery, plans, journal (this package)
14
+ host surface(s) — chat / conversational / autonomous front-ends
15
+ ```
16
+
17
+ The core sits above MCP; host surfaces sit above the core. Callbacks are where surfaces differ — a chat surface emits chat output and `AskUserQuestion`; a conversational surface updates its UI; an autonomous daemon auto-picks recovery branches per policy.
18
+
19
+ ## Public surface
20
+
21
+ ```ts
22
+ import {
23
+ closeLease,
24
+ deployApp,
25
+ manageDomain,
26
+ troubleshootDeployment,
27
+ } from '@manifest-network/manifest-agent-core';
28
+ ```
29
+
30
+ Each function takes a typed args object plus a callbacks object with `onConfirm` / `onProgress` / `onComplete` / `onFailure` hooks. `deployApp` takes a `DeploySpec`; the other three take action-discriminated `*Args` types (e.g. `ManageDomainArgs` is `{ action: 'set' | 'clear' | 'lookup', ... }`). Only `deployApp` accepts `onPlan` and uses an enriched `onFailure` — `(failure: FailureEnvelope, options: RecoveryOption[]) => Promise<RecoveryChoice>` — to drive partial-success recovery: retry the set-domain step, salvage the lease without the custom domain, cancel a pending lease, or close an active one. See `RecoveryOptionId` in `src/types.ts` for the exact literal IDs (`retry_set_domain`, `salvage_without_domain`, `cancel_lease`, `close_lease`). The other three use the simpler `(failure: { reason: string }) => Promise<void>`. See `src/types.ts` for the frozen shapes.
31
+
32
+ ## Where each function lives
33
+
34
+ | Function | Home |
35
+ | --- | --- |
36
+ | `deployApp` | `src/deploy-app.ts` |
37
+ | `manageDomain` | `src/manage-domain.ts` |
38
+ | `troubleshootDeployment` | `src/troubleshoot.ts` |
39
+ | `closeLease` | `src/close-lease.ts` |
@@ -0,0 +1,33 @@
1
+ import { CloseLeaseArgs, CloseLeaseCallbacks, CloseLeaseOptions, CloseLeaseResult } from "./types.js";
2
+
3
+ //#region src/close-lease.d.ts
4
+ /**
5
+ * Close a lease and verify it reached a terminal on-chain state.
6
+ *
7
+ * @throws `ManifestMCPError(INVALID_CONFIG)` for args validation or when
8
+ * `onConfirm` returns `'no'`.
9
+ * @throws `ManifestMCPError` (typically `TX_FAILED`) propagated as-is
10
+ * from the `stopApp()` broadcast step. Broadcast errors do NOT invoke
11
+ * `onFailure` — that callback is reserved for post-broadcast
12
+ * verification failures. `stopApp` already raises a structured
13
+ * `ManifestMCPError` from the core package; wrapping it again at this
14
+ * layer would be redundant. Callers wanting to react to broadcast
15
+ * errors should catch them at the call site.
16
+ * @throws `ManifestMCPError(TX_FAILED)` when post-broadcast verification
17
+ * reaches one of two failure modes (both with `onFailure({ reason })`
18
+ * invoked first):
19
+ * - the lease is still non-terminal (`pending_drift` branch — state
20
+ * decoded as PENDING / ACTIVE / similar non-terminal); or
21
+ * - the chain returns `{ lease: null }` post-close, so the lease is
22
+ * not visible on-chain (`unclassified` branch).
23
+ * @throws `ManifestMCPError(QUERY_FAILED)` when the post-broadcast verify
24
+ * chain query (`billing.v1.lease`) raises a non-NotFound error
25
+ * (RPC / transport / decoding failure). Wrapped inside the verifier
26
+ * closure so the failure flows through `onFailure({ reason })` before
27
+ * the throw. Structured `ManifestMCPError`s raised by the chain client
28
+ * are re-thrown as-is (with `onFailure` invoked first).
29
+ */
30
+ declare function closeLease(args: CloseLeaseArgs, callbacks: CloseLeaseCallbacks, opts: CloseLeaseOptions): Promise<CloseLeaseResult>;
31
+ //#endregion
32
+ export { closeLease };
33
+ //# sourceMappingURL=close-lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-lease.d.ts","names":[],"sources":["../src/close-lease.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+EsB,UAAA,CACpB,IAAA,EAAM,cAAA,EACN,SAAA,EAAW,mBAAA,EACX,IAAA,EAAM,iBAAA,GACL,OAAA,CAAQ,gBAAA"}
@@ -0,0 +1,138 @@
1
+ import { decode, isTerminal } from "./internals/lease-state.js";
2
+ import { verifyAndRecover } from "./internals/verify-recover.js";
3
+ import { ManifestMCPError, ManifestMCPErrorCode, stopApp } from "@manifest-network/manifest-mcp-core";
4
+ //#region src/close-lease.ts
5
+ /**
6
+ * Public entry point: orchestrate closing an existing lease via the
7
+ * `close-lease` billing tx.
8
+ *
9
+ * Composition (mirrors `deploy-app.ts` / `manage-domain.ts`):
10
+ *
11
+ * 1. Validate args.
12
+ * 2. Render a confirmation block + optionally consult `onConfirm`.
13
+ * 3. Broadcast `stopApp` (which submits `MsgCloseLease`).
14
+ * 4. Verify the post-broadcast on-chain state via `verifyAndRecover`
15
+ * driving a direct `billing.v1.lease({ leaseUuid })` query +
16
+ * `lease-state.decode` + `isTerminal`. Terminal states (CLOSED /
17
+ * REJECTED / EXPIRED / INSUFFICIENT_FUNDS) count as success;
18
+ * PENDING / ACTIVE map to the `pending_drift` branch; a chain
19
+ * response with no lease (`{ lease: null }`) maps to the catch-all
20
+ * `unclassified` branch.
21
+ * 5. On verify-failure, invoke the simple-form `onFailure({ reason })`
22
+ * then throw `ManifestMCPError(TX_FAILED)`. On success, emit
23
+ * `onComplete` with the typed `CloseLeaseResult`.
24
+ */
25
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
26
+ /**
27
+ * Close a lease and verify it reached a terminal on-chain state.
28
+ *
29
+ * @throws `ManifestMCPError(INVALID_CONFIG)` for args validation or when
30
+ * `onConfirm` returns `'no'`.
31
+ * @throws `ManifestMCPError` (typically `TX_FAILED`) propagated as-is
32
+ * from the `stopApp()` broadcast step. Broadcast errors do NOT invoke
33
+ * `onFailure` — that callback is reserved for post-broadcast
34
+ * verification failures. `stopApp` already raises a structured
35
+ * `ManifestMCPError` from the core package; wrapping it again at this
36
+ * layer would be redundant. Callers wanting to react to broadcast
37
+ * errors should catch them at the call site.
38
+ * @throws `ManifestMCPError(TX_FAILED)` when post-broadcast verification
39
+ * reaches one of two failure modes (both with `onFailure({ reason })`
40
+ * invoked first):
41
+ * - the lease is still non-terminal (`pending_drift` branch — state
42
+ * decoded as PENDING / ACTIVE / similar non-terminal); or
43
+ * - the chain returns `{ lease: null }` post-close, so the lease is
44
+ * not visible on-chain (`unclassified` branch).
45
+ * @throws `ManifestMCPError(QUERY_FAILED)` when the post-broadcast verify
46
+ * chain query (`billing.v1.lease`) raises a non-NotFound error
47
+ * (RPC / transport / decoding failure). Wrapped inside the verifier
48
+ * closure so the failure flows through `onFailure({ reason })` before
49
+ * the throw. Structured `ManifestMCPError`s raised by the chain client
50
+ * are re-thrown as-is (with `onFailure` invoked first).
51
+ */
52
+ async function closeLease(args, callbacks, opts) {
53
+ validateArgs(args);
54
+ const block = renderConfirmationBlock(args);
55
+ if (callbacks.onConfirm) {
56
+ if (await callbacks.onConfirm(block) !== "yes") throw new ManifestMCPError(ManifestMCPErrorCode.INVALID_CONFIG, "User declined to proceed with close-lease.");
57
+ }
58
+ callbacks.onProgress?.({ kind: "user_confirmed" });
59
+ await stopApp(opts.clientManager, args.leaseUuid);
60
+ const verifyResult = await verifyAndRecover({
61
+ verifier: async () => {
62
+ let result;
63
+ try {
64
+ result = await (await opts.clientManager.getQueryClient()).liftedinit.billing.v1.lease({ leaseUuid: args.leaseUuid });
65
+ } catch (err) {
66
+ const reason = `Failed to query lease ${args.leaseUuid} during close-verify: ${err instanceof Error ? err.message : String(err)}`;
67
+ if (callbacks.onFailure) await callbacks.onFailure({ reason });
68
+ if (err instanceof ManifestMCPError) throw err;
69
+ throw new ManifestMCPError(ManifestMCPErrorCode.QUERY_FAILED, reason);
70
+ }
71
+ const lease = result?.lease;
72
+ if (lease === null || lease === void 0) return {
73
+ outcome: "not_found",
74
+ diagnostic: { reason: `lease ${args.leaseUuid} not visible on chain after close` }
75
+ };
76
+ const rawState = lease.state;
77
+ const stateName = decode(typeof rawState === "number" || typeof rawState === "string" ? rawState : void 0);
78
+ if (stateName === void 0) return {
79
+ outcome: "pending",
80
+ diagnostic: { reason: `lease ${args.leaseUuid} state could not be decoded (raw=${String(rawState)})` }
81
+ };
82
+ return {
83
+ outcome: isTerminal(stateName) ? "terminal" : "pending",
84
+ diagnostic: { stateName }
85
+ };
86
+ },
87
+ successValues: ["terminal"],
88
+ branches: {
89
+ pending: {
90
+ branchId: "pending_drift",
91
+ journalActionTags: ["close-lease-verify-pending"],
92
+ buildFailureEnvelope: (d) => ({
93
+ outcome: "failed",
94
+ reason: d.reason ?? `close_lease tx accepted but state is still ${d.stateName ?? "unknown"}.`
95
+ }),
96
+ buildRecoveryOptions: () => []
97
+ },
98
+ not_found: {
99
+ branchId: "unclassified",
100
+ journalActionTags: ["close-lease-verify-not-found"],
101
+ buildFailureEnvelope: (d) => ({
102
+ outcome: "failed",
103
+ reason: d.reason ?? `Lease ${args.leaseUuid} not visible on chain after close.`
104
+ }),
105
+ buildRecoveryOptions: () => []
106
+ }
107
+ }
108
+ }, void 0);
109
+ if (verifyResult.result !== "success") {
110
+ const reason = verifyResult.failure?.reason ?? "close-lease verification failed.";
111
+ if (callbacks.onFailure) await callbacks.onFailure({ reason });
112
+ throw new ManifestMCPError(ManifestMCPErrorCode.TX_FAILED, reason);
113
+ }
114
+ if (!verifyResult.diagnostic.stateName) throw new ManifestMCPError(ManifestMCPErrorCode.TX_FAILED, `close-lease verifier invariant violated: success outcome reached without diagnostic.stateName for lease ${args.leaseUuid}`);
115
+ const finalState = verifyResult.diagnostic.stateName;
116
+ const result = {
117
+ leaseUuid: args.leaseUuid,
118
+ finalState
119
+ };
120
+ callbacks.onComplete?.(result);
121
+ return result;
122
+ }
123
+ function validateArgs(args) {
124
+ if (typeof args.leaseUuid !== "string" || !args.leaseUuid.match(UUID_RE)) throw new ManifestMCPError(ManifestMCPErrorCode.INVALID_CONFIG, `closeLease: leaseUuid must be a UUID; got "${args.leaseUuid}".`);
125
+ }
126
+ function renderConfirmationBlock(args) {
127
+ return { text: [
128
+ `Close lease ${args.leaseUuid}.`,
129
+ " Image: (image not recorded)",
130
+ " This is permanent — the lease cannot be reopened.",
131
+ "",
132
+ "Proceed?"
133
+ ].join("\n") };
134
+ }
135
+ //#endregion
136
+ export { closeLease };
137
+
138
+ //# sourceMappingURL=close-lease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-lease.js","names":["decodeLeaseState"],"sources":["../src/close-lease.ts"],"sourcesContent":["/**\n * Public entry point: orchestrate closing an existing lease via the\n * `close-lease` billing tx.\n *\n * Composition (mirrors `deploy-app.ts` / `manage-domain.ts`):\n *\n * 1. Validate args.\n * 2. Render a confirmation block + optionally consult `onConfirm`.\n * 3. Broadcast `stopApp` (which submits `MsgCloseLease`).\n * 4. Verify the post-broadcast on-chain state via `verifyAndRecover`\n * driving a direct `billing.v1.lease({ leaseUuid })` query +\n * `lease-state.decode` + `isTerminal`. Terminal states (CLOSED /\n * REJECTED / EXPIRED / INSUFFICIENT_FUNDS) count as success;\n * PENDING / ACTIVE map to the `pending_drift` branch; a chain\n * response with no lease (`{ lease: null }`) maps to the catch-all\n * `unclassified` branch.\n * 5. On verify-failure, invoke the simple-form `onFailure({ reason })`\n * then throw `ManifestMCPError(TX_FAILED)`. On success, emit\n * `onComplete` with the typed `CloseLeaseResult`.\n */\n\nimport {\n ManifestMCPError,\n ManifestMCPErrorCode,\n stopApp,\n} from '@manifest-network/manifest-mcp-core';\nimport {\n decode as decodeLeaseState,\n isTerminal,\n} from './internals/lease-state.js';\nimport {\n type VerificationSpec,\n verifyAndRecover,\n} from './internals/verify-recover.js';\nimport type {\n CloseLeaseArgs,\n CloseLeaseCallbacks,\n CloseLeaseOptions,\n CloseLeaseResult,\n DeploymentPlanBlock,\n LeaseStateName,\n} from './types.js';\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\ntype CloseOutcome = 'terminal' | 'pending' | 'not_found';\n\ninterface CloseDiag {\n stateName?: LeaseStateName;\n reason?: string;\n}\n\n/**\n * Close a lease and verify it reached a terminal on-chain state.\n *\n * @throws `ManifestMCPError(INVALID_CONFIG)` for args validation or when\n * `onConfirm` returns `'no'`.\n * @throws `ManifestMCPError` (typically `TX_FAILED`) propagated as-is\n * from the `stopApp()` broadcast step. Broadcast errors do NOT invoke\n * `onFailure` — that callback is reserved for post-broadcast\n * verification failures. `stopApp` already raises a structured\n * `ManifestMCPError` from the core package; wrapping it again at this\n * layer would be redundant. Callers wanting to react to broadcast\n * errors should catch them at the call site.\n * @throws `ManifestMCPError(TX_FAILED)` when post-broadcast verification\n * reaches one of two failure modes (both with `onFailure({ reason })`\n * invoked first):\n * - the lease is still non-terminal (`pending_drift` branch — state\n * decoded as PENDING / ACTIVE / similar non-terminal); or\n * - the chain returns `{ lease: null }` post-close, so the lease is\n * not visible on-chain (`unclassified` branch).\n * @throws `ManifestMCPError(QUERY_FAILED)` when the post-broadcast verify\n * chain query (`billing.v1.lease`) raises a non-NotFound error\n * (RPC / transport / decoding failure). Wrapped inside the verifier\n * closure so the failure flows through `onFailure({ reason })` before\n * the throw. Structured `ManifestMCPError`s raised by the chain client\n * are re-thrown as-is (with `onFailure` invoked first).\n */\nexport async function closeLease(\n args: CloseLeaseArgs,\n callbacks: CloseLeaseCallbacks,\n opts: CloseLeaseOptions,\n): Promise<CloseLeaseResult> {\n validateArgs(args);\n\n const block = renderConfirmationBlock(args);\n if (callbacks.onConfirm) {\n const yesNo = await callbacks.onConfirm(block);\n if (yesNo !== 'yes') {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n 'User declined to proceed with close-lease.',\n );\n }\n }\n callbacks.onProgress?.({ kind: 'user_confirmed' });\n\n await stopApp(opts.clientManager, args.leaseUuid);\n\n // Direct single-lease query (Copilot review PR #60, comment 3275999624):\n // the previous `leasesByTenant` + page-1-only pagination would\n // false-`not_found` for tenants with >100 leases. `billing.v1.lease`\n // is the same query shape `troubleshoot.ts` already uses; it's\n // tenant-agnostic and bounded to a single lease.\n const spec: VerificationSpec<unknown, CloseOutcome, CloseDiag> = {\n verifier: async () => {\n // Wrap the chain call in try/catch (Copilot review PR #60,\n // comment 3276419264): if `billing.v1.lease` rejects (RPC down,\n // transport, structured `ManifestMCPError`), the error would\n // otherwise propagate OUT of `verifyAndRecover` and bypass the\n // post-verify `onFailure({ reason })` callback below. Mirror\n // the disambiguation pattern from `lookupDomain` (commit aaa5cc5)\n // and `troubleshootDeployment` (commit f1a4737): invoke\n // `onFailure` first, then re-throw `ManifestMCPError` as-is or\n // wrap plain errors as `QUERY_FAILED`.\n let result: unknown;\n try {\n const queryClient = await opts.clientManager.getQueryClient();\n result = await queryClient.liftedinit.billing.v1.lease({\n leaseUuid: args.leaseUuid,\n });\n } catch (err) {\n const reason = `Failed to query lease ${args.leaseUuid} during close-verify: ${\n err instanceof Error ? err.message : String(err)\n }`;\n if (callbacks.onFailure) {\n await callbacks.onFailure({ reason });\n }\n if (err instanceof ManifestMCPError) {\n throw err;\n }\n throw new ManifestMCPError(ManifestMCPErrorCode.QUERY_FAILED, reason);\n }\n const lease = (result as { lease?: unknown })?.lease;\n if (lease === null || lease === undefined) {\n return {\n outcome: 'not_found' as const,\n diagnostic: {\n reason: `lease ${args.leaseUuid} not visible on chain after close`,\n },\n };\n }\n const rawState = (lease as { state?: unknown }).state;\n const stateName = decodeLeaseState(\n typeof rawState === 'number' || typeof rawState === 'string'\n ? rawState\n : undefined,\n );\n if (stateName === undefined) {\n return {\n outcome: 'pending' as const,\n diagnostic: {\n reason: `lease ${args.leaseUuid} state could not be decoded (raw=${String(rawState)})`,\n },\n };\n }\n return {\n outcome: (isTerminal(stateName) ? 'terminal' : 'pending') as\n | 'terminal'\n | 'pending',\n diagnostic: { stateName },\n };\n },\n successValues: ['terminal'],\n branches: {\n pending: {\n branchId: 'pending_drift',\n journalActionTags: ['close-lease-verify-pending'],\n buildFailureEnvelope: (d) => ({\n outcome: 'failed',\n reason:\n d.reason ??\n `close_lease tx accepted but state is still ${d.stateName ?? 'unknown'}.`,\n }),\n buildRecoveryOptions: () => [],\n },\n not_found: {\n branchId: 'unclassified',\n journalActionTags: ['close-lease-verify-not-found'],\n buildFailureEnvelope: (d) => ({\n outcome: 'failed',\n reason:\n d.reason ??\n `Lease ${args.leaseUuid} not visible on chain after close.`,\n }),\n buildRecoveryOptions: () => [],\n },\n },\n };\n\n const verifyResult = await verifyAndRecover(spec, undefined);\n\n if (verifyResult.result !== 'success') {\n const reason =\n verifyResult.failure?.reason ?? 'close-lease verification failed.';\n if (callbacks.onFailure) {\n await callbacks.onFailure({ reason });\n }\n throw new ManifestMCPError(ManifestMCPErrorCode.TX_FAILED, reason);\n }\n\n // Invariant: when `verifyAndRecover` returns success, the matched\n // outcome was `'terminal'`, and the verifier's `terminal` branch\n // ALWAYS sets `diagnostic.stateName` (see the spec above). A missing\n // `stateName` on the success path means the verifier invariant is\n // broken — likely a future refactor regression. The previous\n // implementation fell back to `'LEASE_STATE_CLOSED'` silently, which\n // would lie to the caller (Copilot review PR #60, comment 3276719603).\n // Fail loudly with a typed error instead. `TX_FAILED` is the closest\n // available code in `ManifestMCPErrorCode` (no `INTERNAL_ERROR`\n // variant); the message names the invariant explicitly.\n if (!verifyResult.diagnostic.stateName) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.TX_FAILED,\n `close-lease verifier invariant violated: success outcome reached without diagnostic.stateName for lease ${args.leaseUuid}`,\n );\n }\n const finalState: LeaseStateName = verifyResult.diagnostic.stateName;\n const result: CloseLeaseResult = {\n leaseUuid: args.leaseUuid,\n finalState,\n };\n callbacks.onComplete?.(result);\n return result;\n}\n\n// --- Helpers --------------------------------------------------------\n\nfunction validateArgs(args: CloseLeaseArgs): void {\n if (typeof args.leaseUuid !== 'string' || !args.leaseUuid.match(UUID_RE)) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n `closeLease: leaseUuid must be a UUID; got \"${args.leaseUuid}\".`,\n );\n }\n}\n\nfunction renderConfirmationBlock(args: CloseLeaseArgs): DeploymentPlanBlock {\n // Image is not tracked in `CloseLeaseArgs` and `stopApp` doesn't return it;\n // surface the gap explicitly so reviewers/users see the missing context\n // rather than silently omitting an image field they'd expect.\n const text = [\n `Close lease ${args.leaseUuid}.`,\n ' Image: (image not recorded)',\n ' This is permanent — the lease cannot be reopened.',\n '',\n 'Proceed?',\n ].join('\\n');\n return { text };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA2CA,MAAM,UACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCF,eAAsB,WACpB,MACA,WACA,MAC2B;AAC3B,cAAa,KAAK;CAElB,MAAM,QAAQ,wBAAwB,KAAK;AAC3C,KAAI,UAAU;MACE,MAAM,UAAU,UAAU,MAAM,KAChC,MACZ,OAAM,IAAI,iBACR,qBAAqB,gBACrB,6CACD;;AAGL,WAAU,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAM,QAAQ,KAAK,eAAe,KAAK,UAAU;CA6FjD,MAAM,eAAe,MAAM,iBAtFsC;EAC/D,UAAU,YAAY;GAUpB,IAAI;AACJ,OAAI;AAEF,aAAS,OADW,MAAM,KAAK,cAAc,gBAAgB,EAClC,WAAW,QAAQ,GAAG,MAAM,EACrD,WAAW,KAAK,WACjB,CAAC;YACK,KAAK;IACZ,MAAM,SAAS,yBAAyB,KAAK,UAAU,wBACrD,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAElD,QAAI,UAAU,UACZ,OAAM,UAAU,UAAU,EAAE,QAAQ,CAAC;AAEvC,QAAI,eAAe,iBACjB,OAAM;AAER,UAAM,IAAI,iBAAiB,qBAAqB,cAAc,OAAO;;GAEvE,MAAM,QAAS,QAAgC;AAC/C,OAAI,UAAU,QAAQ,UAAU,KAAA,EAC9B,QAAO;IACL,SAAS;IACT,YAAY,EACV,QAAQ,SAAS,KAAK,UAAU,oCACjC;IACF;GAEH,MAAM,WAAY,MAA8B;GAChD,MAAM,YAAYA,OAChB,OAAO,aAAa,YAAY,OAAO,aAAa,WAChD,WACA,KAAA,EACL;AACD,OAAI,cAAc,KAAA,EAChB,QAAO;IACL,SAAS;IACT,YAAY,EACV,QAAQ,SAAS,KAAK,UAAU,mCAAmC,OAAO,SAAS,CAAC,IACrF;IACF;AAEH,UAAO;IACL,SAAU,WAAW,UAAU,GAAG,aAAa;IAG/C,YAAY,EAAE,WAAW;IAC1B;;EAEH,eAAe,CAAC,WAAW;EAC3B,UAAU;GACR,SAAS;IACP,UAAU;IACV,mBAAmB,CAAC,6BAA6B;IACjD,uBAAuB,OAAO;KAC5B,SAAS;KACT,QACE,EAAE,UACF,8CAA8C,EAAE,aAAa,UAAU;KAC1E;IACD,4BAA4B,EAAE;IAC/B;GACD,WAAW;IACT,UAAU;IACV,mBAAmB,CAAC,+BAA+B;IACnD,uBAAuB,OAAO;KAC5B,SAAS;KACT,QACE,EAAE,UACF,SAAS,KAAK,UAAU;KAC3B;IACD,4BAA4B,EAAE;IAC/B;GACF;EACF,EAEiD,KAAA,EAAU;AAE5D,KAAI,aAAa,WAAW,WAAW;EACrC,MAAM,SACJ,aAAa,SAAS,UAAU;AAClC,MAAI,UAAU,UACZ,OAAM,UAAU,UAAU,EAAE,QAAQ,CAAC;AAEvC,QAAM,IAAI,iBAAiB,qBAAqB,WAAW,OAAO;;AAapE,KAAI,CAAC,aAAa,WAAW,UAC3B,OAAM,IAAI,iBACR,qBAAqB,WACrB,2GAA2G,KAAK,YACjH;CAEH,MAAM,aAA6B,aAAa,WAAW;CAC3D,MAAM,SAA2B;EAC/B,WAAW,KAAK;EAChB;EACD;AACD,WAAU,aAAa,OAAO;AAC9B,QAAO;;AAKT,SAAS,aAAa,MAA4B;AAChD,KAAI,OAAO,KAAK,cAAc,YAAY,CAAC,KAAK,UAAU,MAAM,QAAQ,CACtE,OAAM,IAAI,iBACR,qBAAqB,gBACrB,8CAA8C,KAAK,UAAU,IAC9D;;AAIL,SAAS,wBAAwB,MAA2C;AAW1E,QAAO,EAAE,MAPI;EACX,eAAe,KAAK,UAAU;EAC9B;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK,EACG"}
@@ -0,0 +1,24 @@
1
+ import { DeployAppCallbacks, DeployAppOptions, DeployResult, DeploySpec } from "./types.js";
2
+
3
+ //#region src/deploy-app.d.ts
4
+ /**
5
+ * Orchestrate a deployment. See module-level docstring for the architect-
6
+ * locked composition + E-hybrid runtime-context contract.
7
+ *
8
+ * @throws `ManifestMCPError(INVALID_CONFIG)` for spec / wallet validation.
9
+ * @throws `ManifestMCPError(INVALID_CONFIG)` when `onConfirm` returns
10
+ * `'no'` or `onPlan` returns `'cancel'`.
11
+ *
12
+ * Errors from fred's broadcast or core's recovery primitives surface as
13
+ * typed `ManifestMCPError`s. Partial-success failures with applicable
14
+ * recovery options route through `onFailure(envelope, options)` — the
15
+ * callback's return value drives recovery dispatch via the inline
16
+ * closures in `dispatchRecovery`. Non-partial or inform-only failures
17
+ * (no recovery choices to present, per `handleBroadcastFailure`'s F3
18
+ * branch) throw directly as `ManifestMCPError(TX_FAILED)` without
19
+ * invoking `onFailure`.
20
+ */
21
+ declare function deployApp(spec: DeploySpec, callbacks: DeployAppCallbacks, opts: DeployAppOptions): Promise<DeployResult>;
22
+ //#endregion
23
+ export { deployApp };
24
+ //# sourceMappingURL=deploy-app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-app.d.ts","names":[],"sources":["../src/deploy-app.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;iBAoHsB,SAAA,CACpB,IAAA,EAAM,UAAA,EACN,SAAA,EAAW,kBAAA,EACX,IAAA,EAAM,gBAAA,GACL,OAAA,CAAQ,YAAA"}