opencode-ship 1.1.7 → 1.1.8

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.
package/CHANGELOG.md CHANGED
@@ -2,7 +2,21 @@
2
2
 
3
3
  All notable changes to `opencode-ship` are recorded here.
4
4
 
5
- ## 1.1.7Stabilization and self-hosting (unreleased)
5
+ ## 1.1.8Durable self-host routing correction (unreleased)
6
+
7
+ - **Deterministic controller entrypoint.** Build calls `ship_deliver` to
8
+ dispatch one `ship-controller` session per issue. Schema-v2 worktrees
9
+ refuse implementation until the durable workflow is linked.
10
+ - **Linked-worktree execution.** Builder, task review, commit verification,
11
+ verifier/CI binding, and dual-axis final review run in the registered
12
+ feature worktree while durable state stays in the Git common directory.
13
+ - **Audited abandon.** `delivery_abandon` records immutable intent and
14
+ completion around CAS-safe cleanup of a closed, unmerged attempt. It
15
+ never closes a PR and never marks Ready.
16
+ - Automated install, qualification, and rollout continue to pin exact
17
+ `opencode-ship@<X.Y.Z>` and never resolve `@latest`.
18
+
19
+ ## 1.1.7 — Stabilization and self-hosting
6
20
 
7
21
  > Baseline: https://github.com/Viktorxyz/opencode-ship/issues/70.
8
22
  > Corrective package: https://github.com/Viktorxyz/opencode-ship/issues/72.
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  > npm-distributed OpenCode installer and delivery plugin: a single command materialises the lifecycle plugin, reviewer/verifier agents, and skills into any consumer repository, with a recoverable lock and never silently overwrites managed files.
4
4
  >
5
- > **Status:** `1.1.5` is the current `npm dist-tag latest`. It makes the `ship-plan` primary planning agent product-only: the agent asks about the product, writes `.opencode/plans/*.md`, and stops without leaking delivery-workflow choices into the planning conversation. The immutable tag `1.1.6` failed in `pack` before npm publish or GitHub Release; no npm package or GitHub Release was created. `1.1.7` is the active unpublished correction, tracked by the authoritative [`docs/release/1.1.6-correction-plan.md`](docs/release/1.1.6-correction-plan.md).
5
+ > **Status:** `1.1.7` is the published stabilization and self-hosting correction. The immutable tag `1.1.6` failed in `pack` before npm publish or GitHub Release; no npm package or GitHub Release was created. `1.1.8` is the unpublished durable-routing correction: Build dispatches `ship_deliver`, schema-v2 execution binds to the linked worktree, and closed unmerged attempts can be abandoned with `delivery_abandon`. See [`docs/release/1.1.6-correction-plan.md`](docs/release/1.1.6-correction-plan.md).
6
6
  >
7
- > Use an exact package version for reproducible installs and all self-hosting work. Until `1.1.7` is published and qualified, the verified stable pin is `opencode-ship@1.1.5`; never resolve `@latest` inside an automated release or self-host update.
7
+ > Use an exact package version for reproducible installs and all self-hosting work. Never resolve `@latest` inside an automated release or self-host update. Prerelease candidates publish under `npm dist-tag next` until qualification promotes a stable pin.
8
8
 
9
9
  ---
10
10
 
@@ -158,7 +158,7 @@ The shipped artifact is built by esbuild (`scripts/build.mjs`); self-contained `
158
158
  ## Status and licensing
159
159
 
160
160
  - **License:** MIT. See `LICENSE`.
161
- - **Versioning:** SemVer. v0.2.0 is the first npm-distributed release. v0.3.0 is the installer foundation. v0.4.0 adds the profile-aware installer foundation (`--profile` flag, lock schema v2, profile precedence) that issue #18 requires. v0.5.0 ships the engineering profile content (triage + grill-with-docs SKILL.md placeholders) required by issue #20. v0.6.0 ships the durable plan artifact + Plan Mode permission integration required by issue #21. v0.7.0 ships the M3 task loop contract (run store, task brief, Spec/Quality verdicts, 3-round breaker, commit binding, compaction context) required by issue #22. v0.8.0 ships the Ready gate contract (parallel Standards/Spec + verifier + CI on one HEAD) required by issue #23. v0.9.0 ships the transition matrix smoke (engineering installs all assets, lock tracks the active profile) required by issue #24. v1.0.0 promotes the dogfooded 0.10.0 to stable. v1.1.0 removes the legacy core profile and ships the one-liner init + setup-ship-workflow skill. v1.1.1 began the self-hosting correction line; the immutable `1.1.6` failed before publication and `1.1.7` is the planned unpublished correction (see `docs/release/1.1.6-correction-plan.md`).
161
+ - **Versioning:** SemVer. v0.2.0 is the first npm-distributed release. v0.3.0 is the installer foundation. v0.4.0 adds the profile-aware installer foundation (`--profile` flag, lock schema v2, profile precedence) that issue #18 requires. v0.5.0 ships the engineering profile content (triage + grill-with-docs SKILL.md placeholders) required by issue #20. v0.6.0 ships the durable plan artifact + Plan Mode permission integration required by issue #21. v0.7.0 ships the M3 task loop contract (run store, task brief, Spec/Quality verdicts, 3-round breaker, commit binding, compaction context) required by issue #22. v0.8.0 ships the Ready gate contract (parallel Standards/Spec + verifier + CI on one HEAD) required by issue #23. v0.9.0 ships the transition matrix smoke (engineering installs all assets, lock tracks the active profile) required by issue #24. v1.0.0 promotes the dogfooded 0.10.0 to stable. v1.1.0 removes the legacy core profile and ships the one-liner init + setup-ship-workflow skill. v1.1.1 began the self-hosting correction line; the immutable `1.1.6` failed before publication, `1.1.7` is the published stabilization correction, and `1.1.8` is the unpublished durable-routing correction (see `docs/release/1.1.6-correction-plan.md`).
162
162
  - **Compatibility:** the bundled plugin targets `@opencode-ai/plugin >= 1.15.5 < 2` and OpenCode `>= 1.15.5`.
163
163
 
164
164
  ## FAQ
@@ -1,6 +1,6 @@
1
1
  # Third-Party Notices
2
2
 
3
- `opencode-ship@1.1.7` includes the complete Matt Pocock and Superpowers
3
+ `opencode-ship@1.1.8` includes the complete Matt Pocock and Superpowers
4
4
  methodology under the MIT license, plus the Ship-owned installer,
5
5
  plugin, agents, and skills. The complete immutable pin list is in
6
6
  `vendor/sources.json`; the upstream snapshots are under
@@ -75,6 +75,7 @@ permission:
75
75
  delivery_issue_labels: allow
76
76
  delivery_issue_link: allow
77
77
  delivery_issue_close: ask
78
+ delivery_abandon: ask
78
79
  delivery_sync: allow
79
80
  delivery_publish: allow
80
81
  ship_plan_start: allow
@@ -89,7 +90,7 @@ permission:
89
90
  ship_final_review: deny
90
91
  ship_resume: allow
91
92
  ship_status: allow
92
- ship_deliver: allow
93
+ ship_deliver: deny
93
94
  ship_skill_discover: allow
94
95
  ship_skill_install: allow
95
96
  ship_skill_audit: allow
@@ -118,11 +119,13 @@ strong planner and task reviewer child sessions.
118
119
  5. On the final task, dispatch the parallel Standards + Spec
119
120
  final reviewers against the same HEAD, run the verifier
120
121
  in an independent session, and bind every gate to one HEAD.
121
- 6. On explicit user request, run the merge with a fresh gate
122
- recheck.
123
- 7. On resume, reconcile the durable state with the live Git
124
- state and never duplicate work already recorded in a
125
- commit trailer.
122
+ 6. On explicit user request, run the merge with a fresh gate
123
+ recheck.
124
+ 7. On resume, reconcile the durable state with the live Git
125
+ state and never duplicate work already recorded in a
126
+ commit trailer.
127
+ 8. After the user explicitly closes an unmerged PR and requests
128
+ abandon, call `delivery_abandon`. Never close the PR yourself.
126
129
 
127
130
  ## What you never do
128
131
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Start a delivery workflow. First checks the setup-pending marker, runs skill discovery, then triggers planning with the same-HEAD Ready and merge gates.
2
+ description: Start a delivery workflow. First checks the setup-pending marker, then dispatches the durable ship-controller through ship_deliver.
3
3
  ---
4
4
 
5
5
  # ship-deliver
@@ -25,31 +25,23 @@ If the marker is present:
25
25
 
26
26
  If the marker is absent, continue.
27
27
 
28
- ### 1. Skill discovery (mandatory)
28
+ ### 1. Dispatch the controller
29
29
 
30
- Before dispatching the planner, run the `skill-discovery` skill:
30
+ Call `ship_deliver` with the issue number. Do not implement the issue through the legacy `delivery_issue` / `delivery_worktree` / `delivery_pr` path.
31
31
 
32
- ```text
33
- npx skills find "<query from issue/plan>"
34
- ```
35
-
36
- Auto-install trusted sources (see `ship.config.json#skillDiscovery.trustedOwners`); present non-trusted candidates to the user. Limit to 5 auto-installs per dispatch.
32
+ 1. Check setup-pending.
33
+ 2. Call `ship_deliver(issueNumber)`.
34
+ 3. Surface the controller session and `wf-<issue>` workflow id.
35
+ 4. Await the explicit plan approval prompt.
36
+ 5. Resume only through `ship-controller`.
37
37
 
38
38
  ### 2. Plan + approve
39
39
 
40
- 1. Resolve or restore workflow state from `<git-common-dir>/opencode-ship/`.
41
- 2. Dispatch the strong planner (`openai/gpt-5.6-sol` by default) to produce a PlanV2 contract.
42
- 3. Wait for `ship_plan_approve` from the user. Never auto-approve.
43
- 4. Mirror the plan to the issue.
40
+ The controller starts or resumes durable workflow state, dispatches the planner, and waits for `ship_plan_approve`. Never auto-approve.
44
41
 
45
42
  ### 3. Execute
46
43
 
47
- Drive each task through:
48
-
49
- - cheap builder (`minimax/MiniMax-M3` by default) — implement + report
50
- - task reviewer (Spec + Quality) — verdict
51
- - controller commit + push
52
- - same-HEAD gate: Standards + Spec final reviews, verifier, required CI
44
+ The controller drives each task through the cheap builder, task reviewer, commit binding, and same-HEAD Standards + Spec + verifier + required CI gates.
53
45
 
54
46
  ### 4. Ready
55
47
 
@@ -57,27 +49,20 @@ Stop at Ready. Surface PR URL, worktree path, verifier SHA, and the explicit-mer
57
49
 
58
50
  ### 5. Merge
59
51
 
60
- On explicit `merge it`: fresh gate recheck, squash merge, cleanup, core downgrade, uninstall, root-config byte restoration.
52
+ On explicit `merge it`: fresh gate recheck, squash merge, and cleanup.
61
53
 
62
54
  ## Hard rules
63
55
 
64
56
  - **Never skip the setup gate.** If the marker is present, refuse to plan.
65
- - **Never skip skill discovery.** The discovery is part of the autonomous-uplift contract.
66
57
  - **Never auto-approve a plan.** The user always reviews the plan.
67
58
  - **Never mark Ready or merge without a passing Standards review, a passing Spec review, a passing verifier run, and a passing required-CI check, all bound to one HEAD.**
68
59
  - **Never force-push, hard-reset, stash, or `git worktree remove`.**
69
60
  - **Never use `gh api` or raw shell on GitHub.** Use the typed `delivery_*` tools.
70
-
71
- ## Single-shot research checkpoint
72
-
73
- If you decide the task is non-trivial, pause once and **ask the user** whether to run Deep Research before generating any prompt. The default save-tokens path is "no research, continue with the plan as written". Only on explicit "yes" do you generate a draft Deep Research prompt and run the research; summarize the relevant findings inline and continue. Do not write to `docs/research/` unless the findings materially shape an ADR; ADR storage is the project's call, not yours. Continue only after the user confirms or declines.
74
-
75
- The full procedure lives in the `planning-research-checkpoint` skill. Do not duplicate the prompt-generation logic here — just trigger the skill and respect its ask-first policy.
61
+ - **Never abandon an attempt without an explicit user request after the PR is closed unmerged.** The controller may then call `delivery_abandon`.
76
62
 
77
63
  ## Stop conditions
78
64
 
79
65
  - Setup pending: stop, run setup, then re-dispatch.
80
66
  - Ready reached: stop. Surface the PR URL, the worktree path, the recorded verifier SHA, and the explicit-merge instruction.
81
- - `merge it` requested and gates are fresh: perform the squash merge. Surface the merge SHA. The plugin will queue immediate cleanup; if cleanup fails it is recorded as `cleanupPending` and retried on the next Build task.
67
+ - `merge it` requested and gates are fresh: perform the squash merge. Surface the merge SHA.
82
68
  - Any gate fails after one re-run: stop. Surface the failing tool, the failing input, and the recorded evidence.
83
- - Unexpected lifecycle error (missing-manifest, head-changed, ci-failing): stop. Surface the error envelope.
@@ -5,7 +5,7 @@ description: Orchestrates the canonical delivery lifecycle from issue creation t
5
5
 
6
6
  # delivery-workflow
7
7
 
8
- You drive the opencode-ship package from a one-line user request to a green, conflict-free, ready-to-merge pull request.
8
+ You drive the opencode-ship package from a one-line user request to a green, conflict-free, ready-to-merge pull request by dispatching the durable controller.
9
9
 
10
10
  ## When you trigger
11
11
 
@@ -17,6 +17,7 @@ You drive the opencode-ship package from a one-line user request to a green, con
17
17
  - "Clean up my worktree" / "Tidy old worktrees" — entry point for next-task cleanup
18
18
 
19
19
  Do **not** trigger on:
20
+
20
21
  - Read-only questions ("explain issue N")
21
22
  - Plain chat about the project's domain model
22
23
  - Typo / doc one-liners that do not deserve a PR
@@ -25,40 +26,32 @@ Do **not** trigger on:
25
26
 
26
27
  | Step | Tool | Notes |
27
28
  |---|---|---|
28
- | 1. Cleanup old worktrees | `delivery_inspect` for each manifest, recovery scan, `delivery_cleanup` for provably-merged ones | Runs immediately after a successful merge; retries on next Build task if interrupted |
29
- | 2. Offer research checkpoint | (this skill) | Single-shot per session; offer only if the plan is non-trivial |
30
- | 3. Find or create the issue | `delivery_issue` | Always idempotent; never create a duplicate |
31
- | 4. Create a worktree | `delivery_worktree` | Refuse overwrites; refuse dirty tree |
32
- | 5. Implement | (consumer-owned) | Stay inside the worktree |
33
- | 6. Commit + push | (consumer-owned `git`) | Use Conventional Commits |
34
- | 7. Open draft PR | `delivery_pr` | `Closes #N` is added automatically |
35
- | 8. Sync with default branch | (consumer-owned `git`) | Merge `origin/main` into the feature branch; never rebase a published branch |
36
- | 9. Review | `task reviewer:delivery-reviewer` | Re-run if HEAD changed |
37
- | 10. Verify | `task verifier:delivery-verifier` | Same final HEAD required |
38
- | 11. Mark Ready | `delivery_ready` | Refreshes checks; refuses if any gate is stale |
39
- | 12. Stop at Ready | (this skill) | Do not merge without an explicit user request |
40
- | 13. Merge (only on explicit request) | `delivery_merge` | Re-checks base, head, and mergeability |
41
- | 14. Immediate cleanup | `delivery_cleanup` | Runs automatically right after a successful merge |
29
+ | 1. Cleanup merged worktrees | `delivery_inspect` / `delivery_cleanup` | Only for provably merged attempts |
30
+ | 2. Setup gate | `/ship-deliver` | Refuse if `.opencode/ship.setup-pending.json` exists |
31
+ | 3. Dispatch controller | `ship_deliver` | Canonical Build-to-controller entrypoint |
32
+ | 4. Plan + approve | controller / `ship_plan_approve` | Never auto-approve |
33
+ | 5. Execute in linked worktree | controller | Builder, task review, commit, verifier, CI, dual-axis final review |
34
+ | 6. Ready | `delivery_ready` | Controller-owned; same-HEAD gates required |
35
+ | 7. Stop at Ready | (this skill) | Do not merge without an explicit user request |
36
+ | 8. Merge | `delivery_merge` | Explicit user request only |
37
+ | 9. Cleanup | `delivery_cleanup` | After a successful merge |
38
+ | 10. Abandon closed unmerged attempts | `delivery_abandon` | Only after the user explicitly closes the PR and requests abandon |
39
+
40
+ Do not call `delivery_worktree`, `delivery_pr`, `delivery_ready`, or `delivery_merge` from Build to implement an issue. Those mutations belong to `ship-controller` after `ship_deliver`.
42
41
 
43
42
  ## Hard rules
44
43
 
45
- 1. Every PR carries a `Closes #N` reference. If the issue does not exist, create it first.
44
+ 1. Every PR carries a `Closes #N` reference. If the issue does not exist, the controller creates it first.
46
45
  2. The lifecycle stops at Ready by default. An explicit "merge it" is the only thing that triggers `delivery_merge`.
47
- 3. Force-push, hard-reset, stash, and `git worktree remove` are denied to you. Use `delivery_worktree` and `delivery_cleanup` instead.
46
+ 3. Force-push, hard-reset, stash, and `git worktree remove` are denied. Use typed cleanup/abandon tools.
48
47
  4. You never edit `main` directly. You never bypass the reviewer/verifier gates.
49
- 5. The typed `delivery_*` tools are the only sanctioned way to mutate GitHub state. Do not invoke `gh pr merge`, `gh api`, or raw Git plumbing directly.
48
+ 5. The typed tools are the only sanctioned way to mutate GitHub state. Do not invoke `gh pr merge`, `gh api`, or raw Git plumbing directly.
50
49
  6. When a gate fails, fix the cause and re-run only the failed gate; never skip.
51
50
  7. If `delivery_merge` returns a `MergeError`, surface it verbatim. Do not invent a workaround.
52
51
 
53
- ## Single-shot research checkpoint
54
-
55
- If you decide the task is non-trivial, pause once and **ask the user** whether to run Deep Research before generating any prompt. The default save-tokens path is "no research, continue with the plan as written". Only on explicit "yes" do you generate a draft Deep Research prompt and run the research; summarize the relevant findings inline and continue. Do not write to `docs/research/` unless the findings materially shape an ADR; ADR storage is the project's call, not yours. Continue only after the user confirms or declines.
56
-
57
- The full procedure lives in the `planning-research-checkpoint` skill. Do not duplicate the prompt-generation logic here — just trigger the skill and respect its ask-first policy.
58
-
59
52
  ## Stop conditions
60
53
 
61
54
  - Ready reached: stop. Surface the PR URL, the worktree path, the recorded verifier SHA, and the explicit-merge instruction.
62
- - `merge it` requested and gates are fresh: perform the squash merge. Surface the merge SHA. The plugin will queue immediate cleanup; if cleanup fails it is recorded as `cleanupPending` and retried on the next Build task.
55
+ - `merge it` requested and gates are fresh: perform the squash merge. Surface the merge SHA.
63
56
  - Any gate fails after one re-run: stop. Surface the failing tool, the failing input, and the recorded evidence.
64
- - Unexpected lifecycle error (missing-manifest, head-changed, ci-failing): stop. Surface the error envelope.
57
+ - Unexpected lifecycle error (missing-manifest, missing-workflow-link, head-changed, ci-failing): stop. Surface the error envelope.
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // opencode-ship CLI v1.1.7
2
+ // opencode-ship CLI v1.1.8
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __esm = (fn, res) => function __init() {
@@ -110,7 +110,7 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
110
110
  var PACKAGE_VERSION, TEMPLATE_SET;
111
111
  var init_version = __esm({
112
112
  "src/version.js"() {
113
- PACKAGE_VERSION = "1.1.7";
113
+ PACKAGE_VERSION = "1.1.8";
114
114
  TEMPLATE_SET = `v${PACKAGE_VERSION}`;
115
115
  }
116
116
  });
@@ -1769,6 +1769,7 @@ var CONTROLLER_TASK_ALLOW = [
1769
1769
  "delivery-verifier"
1770
1770
  ];
1771
1771
  var PUBLIC_TOOL_IDS = [
1772
+ "delivery_abandon",
1772
1773
  "delivery_cleanup",
1773
1774
  "delivery_github_read",
1774
1775
  "delivery_inspect",
@@ -1785,6 +1786,7 @@ var PUBLIC_TOOL_IDS = [
1785
1786
  "delivery_sync",
1786
1787
  "delivery_verify",
1787
1788
  "delivery_worktree",
1789
+ "ship_deliver",
1788
1790
  "ship_final_review",
1789
1791
  "ship_plan_approve",
1790
1792
  "ship_plan_start",
@@ -1809,6 +1811,7 @@ var BUILD_TOOL_ALLOW = [
1809
1811
  "delivery_pr",
1810
1812
  "delivery_ready",
1811
1813
  "delivery_worktree",
1814
+ "ship_deliver",
1812
1815
  "ship_status",
1813
1816
  "ship_resume"
1814
1817
  ];
@@ -1816,6 +1819,7 @@ var BUILD_TOOL_ASK = [
1816
1819
  "ship_plan_approve",
1817
1820
  "delivery_merge",
1818
1821
  "delivery_issue_close",
1822
+ "delivery_abandon",
1819
1823
  "ship_skill_install"
1820
1824
  ];
1821
1825
  var CONTROLLER_TOOL_ALLOW = [
@@ -1846,7 +1850,8 @@ var CONTROLLER_TOOL_ALLOW = [
1846
1850
  var CONTROLLER_TOOL_ASK = [
1847
1851
  "ship_plan_approve",
1848
1852
  "delivery_merge",
1849
- "delivery_issue_close"
1853
+ "delivery_issue_close",
1854
+ "delivery_abandon"
1850
1855
  ];
1851
1856
  var H = "git";
1852
1857
  var RESET = "--hard";
@@ -5251,7 +5256,7 @@ async function assembleLock({ repoRoot, plan, lock, configPlan, rootPlan, profil
5251
5256
  manager: {
5252
5257
  schemaVersion: CURRENT_LOCK_SCHEMA,
5253
5258
  name: "opencode-ship",
5254
- version: "1.1.7",
5259
+ version: "1.1.8",
5255
5260
  templateSet: TEMPLATE_SET_ID,
5256
5261
  profile: resolvedProfile,
5257
5262
  appliedAt: (/* @__PURE__ */ new Date()).toISOString(),
package/dist/core.d.ts CHANGED
@@ -100,6 +100,7 @@ export interface PullRequestSummary {
100
100
  draft: boolean;
101
101
  mergeable: "MERGEABLE" | "CONFLICTING" | "UNKNOWN";
102
102
  mergeStateStatus: string;
103
+ state: "OPEN" | "CLOSED" | "MERGED" | "UNKNOWN";
103
104
  merged: boolean;
104
105
  mergedAt: string | null;
105
106
  }
@@ -330,6 +331,12 @@ export interface CleanupToolInput {
330
331
  taskId: string;
331
332
  }
332
333
 
334
+ export interface AbandonToolInput {
335
+ taskId: string;
336
+ subject: string;
337
+ operationId?: string;
338
+ }
339
+
333
340
  export type Envelope<TKind extends string, TData> = { kind: TKind } & TData;
334
341
 
335
342
  // ---------------------------------------------------------------------------
@@ -581,3 +588,14 @@ export declare function createCleanupTool(deps: BaseToolDeps): (input: CleanupTo
581
588
  | Envelope<"branch-delete-failed", { stderr: string }>
582
589
  | Envelope<"unsafe-cleanup", { signals: readonly string[] }>
583
590
  >;
591
+
592
+ export declare function createAbandonTool(deps: BaseToolDeps): (input: AbandonToolInput) => Promise<
593
+ | { contractVersion: 2; ok: true; kind: "abandon"; operationId: string; idempotent: boolean; data: {
594
+ taskId: string;
595
+ intentHash: string;
596
+ removedWorktree: boolean;
597
+ deletedBranch: boolean;
598
+ deletedManifest: boolean;
599
+ } }
600
+ | { contractVersion: 2; ok: false; kind: "abandon"; operationId: string; retryable: boolean; message: string; details: { kind: string } }
601
+ >;