opencode-swarm 7.78.7 → 7.78.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.
@@ -142,6 +142,42 @@ Build a complete feedback ledger before editing. Include every available source:
142
142
  If a source is unavailable, record that limitation. Do not treat missing access as
143
143
  evidence that no feedback exists.
144
144
 
145
+ ### CI matrix cascade check (do this before fixing)
146
+
147
+ When the PR's `unit` job is a matrix across multiple OSes and downstream jobs
148
+ (`integration`, `smoke`) have `needs: unit`, an OS leg failure blocks the
149
+ entire pipeline. Before triaging, check:
150
+
151
+ 1. Are `integration` or `smoke` jobs in `skipped` or `cancelled` state rather
152
+ than `failed`? That signals a unit matrix cascade — the unit job failed
153
+ on one OS leg, blocking the downstream jobs from running on the current
154
+ HEAD.
155
+ 2. If a unit OS leg is the blocker, classify the failure:
156
+ - **Code issue** — the test itself fails. Reproduce locally; if the
157
+ test passes locally, the runner is the problem.
158
+ - **Runner performance** — the test step exceeds the configured timeout.
159
+ Run all files in the step locally with per-file timing; if cumulative
160
+ local runtime is <10 min and the runner can't complete in 60+ min, the
161
+ issue is runner performance. Bump the CI timeout as a stopgap and file
162
+ a follow-up issue for parallelization. Do not loop bumping the timeout
163
+ past 90 min without filing the follow-up.
164
+ 3. Surface cascade failures to the user explicitly. The downstream jobs'
165
+ results don't exist; the code's coverage of the current HEAD cannot be
166
+ confirmed by CI alone.
167
+
168
+ ### PR body claim verification
169
+
170
+ PR body text like "PHASE 2 council APPROVED (5/5, round 2)" or "Final council
171
+ APPROVED" must be backed by an evidence file in `.swarm/evidence/`
172
+ (typically `phase-council.json` or `final-council.json`). Bot-generated PR
173
+ bodies commonly auto-fill these claims without real review. Before accepting
174
+ such a claim as part of triage:
175
+
176
+ 1. Check whether the corresponding evidence file exists with `verdict:APPROVED`.
177
+ 2. If the claim is unsupported, mark the closure ledger item as
178
+ `NEEDS_MORE_EVIDENCE` rather than `CONFIRMED`. Do not silently drop the
179
+ claim — it indicates the PR body was generated without a real review.
180
+
145
181
  ## Feedback Ledger
146
182
 
147
183
  Normalize each item before triage:
@@ -163,6 +199,59 @@ Rules:
163
199
  `CONFLICT-001` for merge/base drift and `CI-001` for check failures, so PR
164
200
  bodies can show exactly how operational blockers were closed.
165
201
 
202
+ ### Mandatory: integrate all PR comments with feedback or findings before validation
203
+
204
+ **Before the Verification step begins, every PR comment that contains feedback
205
+ or findings MUST be integrated into the total feedback ledger as a
206
+ `FB-###` item.** This is a hard requirement, not a best-effort step.
207
+
208
+ What counts as "feedback or findings":
209
+ - A reviewer request for a code change ("please rename this", "add a test for
210
+ X", "this should call `_internals.foo`")
211
+ - A reviewer claim about correctness, security, or style ("this is
212
+ incorrect", "X will leak")
213
+ - A bot reviewer's findings table entries
214
+ - A CI failure with a specific file:line root cause
215
+ - A reviewer question that implies a code change is needed ("why is this
216
+ static?")
217
+ - PR review summaries or aggregate comments
218
+
219
+ What does NOT count (and is therefore not required to be a ledger item):
220
+ - Pure acknowledgements ("LGTM", "looks good")
221
+ - PR-level metadata changes (title, label, milestone)
222
+ - Force-push acknowledgements
223
+
224
+ Rules:
225
+ - **No finding may be addressed outside the ledger.** If you fix something a
226
+ reviewer mentioned, the corresponding `FB-###` item MUST be in the ledger
227
+ before the fix. If you skip the fix, the `FB-###` item MUST be in the
228
+ ledger with a `DISPROVED`, `PRE_EXISTING`, `NEEDS_MORE_EVIDENCE`, or
229
+ `NEEDS_USER_DECISION` status before validation can begin.
230
+ - **Status semantics for unaddressed items:**
231
+ - `CONFIRMED` and `PARTIAL` items must be addressed (fixed or
232
+ disproved) before validation can begin. A `CONFIRMED` item that is
233
+ left unaddressed is a regression against the review.
234
+ - `DISPROVED`, `PRE_EXISTING`, `NEEDS_MORE_EVIDENCE`, and
235
+ `NEEDS_USER_DECISION` items may remain open at validation time, but
236
+ each must be explicitly justified in the closure ledger.
237
+ - **The closure ledger at the end of the run must account for every `FB-###`
238
+ item** with a final status (fixed / disproved / pre-existing / needs user
239
+ decision / needs more evidence).
240
+ - **Comments from the latest bot round take precedence over earlier rounds**
241
+ for the same finding; the earlier-round `FB-###` item is updated with the
242
+ new evidence rather than a new item being created.
243
+ - **Multi-round pattern continues to apply** (see "Multi-Round Bot Reviews"
244
+ section). A new bot round adds new `FB-###` items for findings that
245
+ weren't in the prior round; the prior round's items are carried forward
246
+ and updated with the new evidence.
247
+
248
+ Rationale: silently addressing a review comment without a corresponding
249
+ ledger item means the closure summary at the end of the run cannot
250
+ demonstrate that every review comment was considered. The closure summary
251
+ is the only artifact the user/maintainer reads to confirm the PR is ready
252
+ to merge. Missing items in the ledger = missing items in the closure = a
253
+ PR that ships with unreviewed feedback.
254
+
166
255
  ## Verification
167
256
 
168
257
  Classify every ledger item before fixing:
@@ -173,6 +262,7 @@ Classify every ledger item before fixing:
173
262
  | `PARTIAL` | The comment points at a real concern, but the framing, severity, or requested fix is incomplete. |
174
263
  | `DISPROVED` | Source, tests, or execution context prove the claim is false, unreachable, or already mitigated. |
175
264
  | `PRE_EXISTING` | The issue exists on the base branch and is not materially worsened by the PR. |
265
+ | `NEEDS_MORE_EVIDENCE` | The claim (e.g., "council APPROVED") is unsupported by stored evidence (e.g., a missing or failed `.swarm/evidence/` artifact); more information is required before triage. |
176
266
  | `NEEDS_USER_DECISION` | The item requires a product, UX, compatibility, or scope choice that cannot be inferred. |
177
267
 
178
268
  Verification checklist:
@@ -184,6 +274,26 @@ Verification checklist:
184
274
  - Check related tests and whether a failing/proposed test would prove the item.
185
275
  - Check whether multiple feedback items share one root cause.
186
276
 
277
+ ### DI seam migration validation
278
+
279
+ When a test file mutates a DI seam object (e.g., `_internals.foo = mock`),
280
+ verify that the production source reads from the seam at call time. A common
281
+ anti-pattern: the test mutates the seam object, but the production code
282
+ imports the named function (`import { foo } from './module'`) which is bound
283
+ at module load. The seam mutation has no effect on the named reference,
284
+ so the test fails even though the seam object's `foo === mock`.
285
+
286
+ Verification: open the source file and grep for call sites. If you see
287
+ `import { foo } from '...'` followed by `foo(...)` in the production code,
288
+ and the test does `_internals.foo = mock`, the test will fail. The fix is
289
+ to change the production code to call `_internals.foo(...)` (or equivalent
290
+ active-seam pattern) so the seam mutation is read at call time.
291
+
292
+ If only a few call sites exist, fix them in the source. If many call sites
293
+ exist, consider whether the migration should use `mock.module()` instead,
294
+ which replaces the entire module object (including the named export
295
+ reference).
296
+
187
297
  ## Fix Planning
188
298
 
189
299
  Cluster ledger items by root cause before coding. Fix in this order unless a user
@@ -251,6 +361,7 @@ FB-001 | fixed | commit/test evidence
251
361
  FB-002 | disproved | code evidence
252
362
  FB-003 | pre-existing | base-branch evidence
253
363
  FB-004 | needs user decision | decision required
364
+ FB-005 | needs more evidence | .swarm/evidence/phase-council.json missing
254
365
  CONFLICT-001 | fixed | remote mergeability is MERGEABLE/CLEAN
255
366
  CI-001 | fixed | current-head check/run evidence
256
367
  ```
package/README.md CHANGED
@@ -1107,7 +1107,7 @@ Control how tool outputs are summarized for LLM context.
1107
1107
  | `/swarm deep-dive <scope> [--profile <name>] [--max-explorers <n>]` | Read-only codebase audit with parallel explorers, dual reviewers, and critic challenge |
1108
1108
  | `/swarm design-docs <description> [--out <dir>] [--lang <name>] [--update]` | Generate or sync language-agnostic design docs (requires `design_docs.enabled`) |
1109
1109
  | `/swarm dark-matter` | Detect hidden file couplings from co-change history |
1110
- | `/swarm finalize [--prune-branches] [--skill-review]` | Idempotent session close-out: retrospectives, lesson curation, evidence archive, context.md reset, config-backup cleanup, optional branch pruning, optional skill-improver proposal |
1110
+ | `/swarm finalize [--prune-branches] [--skill-review]` | Idempotent session close-out: retrospectives, lesson curation, evidence archive, git reset --hard + clean to align with remote branch (discards uncommitted changes), optional branch pruning, optional skill-improver proposal |
1111
1111
  | `/swarm close [--prune-branches] [--skill-review]` | Deprecated alias for `/swarm finalize [--prune-branches] [--skill-review]` |
1112
1112
  | `/swarm write-retro` | Write a phase retrospective manually |
1113
1113
  | `/swarm handoff` | Generate a handoff summary for context-budget-critical sessions |
package/dist/cli/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "opencode-swarm",
55
- version: "7.78.7",
55
+ version: "7.78.8",
56
56
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
57
57
  main: "dist/index.js",
58
58
  types: "dist/index.d.ts",
@@ -37020,15 +37020,19 @@ function writeCheckpointLog(log2, directory) {
37020
37020
  fs9.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
37021
37021
  fs9.renameSync(tempPath, logPath);
37022
37022
  }
37023
- function gitExec(args) {
37023
+ function gitExec(args, cwd) {
37024
37024
  const result = child_process.spawnSync("git", args, {
37025
+ cwd,
37025
37026
  encoding: "utf-8",
37026
37027
  timeout: GIT_TIMEOUT_MS,
37027
- stdio: ["pipe", "pipe", "pipe"]
37028
+ stdio: ["ignore", "pipe", "pipe"],
37029
+ windowsHide: true
37028
37030
  });
37031
+ if (result.error) {
37032
+ throw new Error(`git failed to start: ${result.error.code ?? "unknown"} \u2014 ${result.error.message}`);
37033
+ }
37029
37034
  if (result.status !== 0) {
37030
- const err = new Error(result.stderr?.trim() || `git exited with code ${result.status}`);
37031
- throw err;
37035
+ throw new Error(result.stderr?.trim() || `git exited with code ${result.status}`);
37032
37036
  }
37033
37037
  return result.stdout;
37034
37038
  }
@@ -37040,13 +37044,13 @@ function appendRetentionEvent(directory, event) {
37040
37044
  fs9.appendFileSync(eventsPath, line);
37041
37045
  } catch {}
37042
37046
  }
37043
- function getCurrentSha() {
37044
- const output = gitExec(["rev-parse", "HEAD"]);
37047
+ function getCurrentSha(directory) {
37048
+ const output = gitExec(["rev-parse", "HEAD"], directory);
37045
37049
  return output.trim();
37046
37050
  }
37047
- function isGitRepo() {
37051
+ function isGitRepo(directory) {
37048
37052
  try {
37049
- gitExec(["rev-parse", "--git-dir"]);
37053
+ gitExec(["rev-parse", "--git-dir"], directory);
37050
37054
  return true;
37051
37055
  } catch {
37052
37056
  return false;
@@ -37071,21 +37075,21 @@ function handleSave(label, directory) {
37071
37075
  }, null, 2);
37072
37076
  }
37073
37077
  const timestamp = new Date().toISOString();
37074
- gitExec(["add", "--all", "--", ":!.swarm/"]);
37078
+ gitExec(["add", "--all", "--", ":!.swarm/"], directory);
37075
37079
  const hasStagedChanges = (() => {
37076
37080
  try {
37077
- gitExec(["diff", "--cached", "--quiet"]);
37081
+ gitExec(["diff", "--cached", "--quiet"], directory);
37078
37082
  return false;
37079
37083
  } catch {
37080
37084
  return true;
37081
37085
  }
37082
37086
  })();
37083
37087
  if (hasStagedChanges) {
37084
- gitExec(["commit", "-m", `checkpoint: ${label}`]);
37088
+ gitExec(["commit", "-m", `checkpoint: ${label}`], directory);
37085
37089
  } else if (allowEmptyCommits) {
37086
- gitExec(["commit", "--allow-empty", "-m", `checkpoint: ${label}`]);
37090
+ gitExec(["commit", "--allow-empty", "-m", `checkpoint: ${label}`], directory);
37087
37091
  }
37088
- const newSha = getCurrentSha();
37092
+ const newSha = getCurrentSha(directory);
37089
37093
  log2.checkpoints.push({
37090
37094
  label,
37091
37095
  sha: newSha,
@@ -37130,7 +37134,7 @@ function handleRestore(label, directory) {
37130
37134
  error: `checkpoint not found: "${label}"`
37131
37135
  }, null, 2);
37132
37136
  }
37133
- gitExec(["reset", "--soft", checkpoint.sha]);
37137
+ gitExec(["reset", "--soft", checkpoint.sha], directory);
37134
37138
  return JSON.stringify({
37135
37139
  action: "restore",
37136
37140
  success: true,
@@ -37201,7 +37205,7 @@ var init_checkpoint = __esm(() => {
37201
37205
  label: exports_external.string().optional().describe("Checkpoint label (required for save, restore, delete)")
37202
37206
  },
37203
37207
  execute: async (args, directory) => {
37204
- if (!isGitRepo()) {
37208
+ if (!isGitRepo(directory)) {
37205
37209
  return JSON.stringify({
37206
37210
  action: "unknown",
37207
37211
  success: false,
@@ -67722,7 +67726,7 @@ var init_registry = __esm(() => {
67722
67726
  sessionID: ctx.sessionID
67723
67727
  }),
67724
67728
  description: "Use /swarm finalize to finalize the swarm project and archive evidence",
67725
- details: "Idempotent 4-stage terminal finalization: (1) finalize writes retrospectives for in-progress phases, (2) archive creates timestamped bundle of swarm artifacts and evidence, (3) clean removes active-state files for a clean slate, (4) align performs safe git ff-only to main. Resets agent sessions and delegation chains. Reads .swarm/close-lessons.md for explicit lessons and runs curation. Use --skill-review to run the quota-bounded skill_improver in proposal mode.",
67729
+ details: "Idempotent 4-stage terminal finalization: (1) finalize writes retrospectives for in-progress phases, (2) archive creates timestamped bundle of swarm artifacts and evidence, (3) clean removes active-state files for a clean slate, (4) align performs aggressive git reset --hard to the default remote branch, discarding uncommitted changes and untracked files; falls back to a cautious reset that preserves uncommitted changes when the aggressive path cannot proceed. WARNING: alignment discards local changes and untracked files. Resets agent sessions and delegation chains. Reads .swarm/close-lessons.md for explicit lessons and runs curation. Use --skill-review to run the quota-bounded skill_improver in proposal mode.",
67726
67730
  args: "--prune-branches, --skill-review",
67727
67731
  category: "core",
67728
67732
  toolPolicy: "none"
@@ -312,7 +312,7 @@ export declare const COMMAND_REGISTRY: {
312
312
  readonly finalize: {
313
313
  readonly handler: (ctx: CommandContext) => Promise<string>;
314
314
  readonly description: "Use /swarm finalize to finalize the swarm project and archive evidence";
315
- readonly details: "Idempotent 4-stage terminal finalization: (1) finalize writes retrospectives for in-progress phases, (2) archive creates timestamped bundle of swarm artifacts and evidence, (3) clean removes active-state files for a clean slate, (4) align performs safe git ff-only to main. Resets agent sessions and delegation chains. Reads .swarm/close-lessons.md for explicit lessons and runs curation. Use --skill-review to run the quota-bounded skill_improver in proposal mode.";
315
+ readonly details: "Idempotent 4-stage terminal finalization: (1) finalize writes retrospectives for in-progress phases, (2) archive creates timestamped bundle of swarm artifacts and evidence, (3) clean removes active-state files for a clean slate, (4) align performs aggressive git reset --hard to the default remote branch, discarding uncommitted changes and untracked files; falls back to a cautious reset that preserves uncommitted changes when the aggressive path cannot proceed. WARNING: alignment discards local changes and untracked files. Resets agent sessions and delegation chains. Reads .swarm/close-lessons.md for explicit lessons and runs curation. Use --skill-review to run the quota-bounded skill_improver in proposal mode.";
316
316
  readonly args: "--prune-branches, --skill-review";
317
317
  readonly category: "core";
318
318
  readonly toolPolicy: "none";
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ var package_default;
69
69
  var init_package = __esm(() => {
70
70
  package_default = {
71
71
  name: "opencode-swarm",
72
- version: "7.78.7",
72
+ version: "7.78.8",
73
73
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
74
74
  main: "dist/index.js",
75
75
  types: "dist/index.d.ts",
@@ -58440,15 +58440,19 @@ function writeCheckpointLog(log2, directory) {
58440
58440
  fs19.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
58441
58441
  fs19.renameSync(tempPath, logPath);
58442
58442
  }
58443
- function gitExec(args2) {
58443
+ function gitExec(args2, cwd) {
58444
58444
  const result = child_process.spawnSync("git", args2, {
58445
+ cwd,
58445
58446
  encoding: "utf-8",
58446
58447
  timeout: GIT_TIMEOUT_MS,
58447
- stdio: ["pipe", "pipe", "pipe"]
58448
+ stdio: ["ignore", "pipe", "pipe"],
58449
+ windowsHide: true
58448
58450
  });
58451
+ if (result.error) {
58452
+ throw new Error(`git failed to start: ${result.error.code ?? "unknown"} — ${result.error.message}`);
58453
+ }
58449
58454
  if (result.status !== 0) {
58450
- const err2 = new Error(result.stderr?.trim() || `git exited with code ${result.status}`);
58451
- throw err2;
58455
+ throw new Error(result.stderr?.trim() || `git exited with code ${result.status}`);
58452
58456
  }
58453
58457
  return result.stdout;
58454
58458
  }
@@ -58460,13 +58464,13 @@ function appendRetentionEvent(directory, event) {
58460
58464
  fs19.appendFileSync(eventsPath, line);
58461
58465
  } catch {}
58462
58466
  }
58463
- function getCurrentSha() {
58464
- const output = gitExec(["rev-parse", "HEAD"]);
58467
+ function getCurrentSha(directory) {
58468
+ const output = gitExec(["rev-parse", "HEAD"], directory);
58465
58469
  return output.trim();
58466
58470
  }
58467
- function isGitRepo() {
58471
+ function isGitRepo(directory) {
58468
58472
  try {
58469
- gitExec(["rev-parse", "--git-dir"]);
58473
+ gitExec(["rev-parse", "--git-dir"], directory);
58470
58474
  return true;
58471
58475
  } catch {
58472
58476
  return false;
@@ -58491,21 +58495,21 @@ function handleSave(label, directory) {
58491
58495
  }, null, 2);
58492
58496
  }
58493
58497
  const timestamp = new Date().toISOString();
58494
- gitExec(["add", "--all", "--", ":!.swarm/"]);
58498
+ gitExec(["add", "--all", "--", ":!.swarm/"], directory);
58495
58499
  const hasStagedChanges = (() => {
58496
58500
  try {
58497
- gitExec(["diff", "--cached", "--quiet"]);
58501
+ gitExec(["diff", "--cached", "--quiet"], directory);
58498
58502
  return false;
58499
58503
  } catch {
58500
58504
  return true;
58501
58505
  }
58502
58506
  })();
58503
58507
  if (hasStagedChanges) {
58504
- gitExec(["commit", "-m", `checkpoint: ${label}`]);
58508
+ gitExec(["commit", "-m", `checkpoint: ${label}`], directory);
58505
58509
  } else if (allowEmptyCommits) {
58506
- gitExec(["commit", "--allow-empty", "-m", `checkpoint: ${label}`]);
58510
+ gitExec(["commit", "--allow-empty", "-m", `checkpoint: ${label}`], directory);
58507
58511
  }
58508
- const newSha = getCurrentSha();
58512
+ const newSha = getCurrentSha(directory);
58509
58513
  log2.checkpoints.push({
58510
58514
  label,
58511
58515
  sha: newSha,
@@ -58550,9 +58554,9 @@ function saveCheckpointRecord(label, directory) {
58550
58554
  return { success: false, error: `duplicate label: "${label}"` };
58551
58555
  }
58552
58556
  let sha = "";
58553
- if (isGitRepo()) {
58557
+ if (isGitRepo(directory)) {
58554
58558
  try {
58555
- sha = getCurrentSha();
58559
+ sha = getCurrentSha(directory);
58556
58560
  } catch {
58557
58561
  sha = "";
58558
58562
  }
@@ -58582,7 +58586,7 @@ function handleRestore(label, directory) {
58582
58586
  error: `checkpoint not found: "${label}"`
58583
58587
  }, null, 2);
58584
58588
  }
58585
- gitExec(["reset", "--soft", checkpoint.sha]);
58589
+ gitExec(["reset", "--soft", checkpoint.sha], directory);
58586
58590
  return JSON.stringify({
58587
58591
  action: "restore",
58588
58592
  success: true,
@@ -58653,7 +58657,7 @@ var init_checkpoint = __esm(() => {
58653
58657
  label: exports_external.string().optional().describe("Checkpoint label (required for save, restore, delete)")
58654
58658
  },
58655
58659
  execute: async (args2, directory) => {
58656
- if (!isGitRepo()) {
58660
+ if (!isGitRepo(directory)) {
58657
58661
  return JSON.stringify({
58658
58662
  action: "unknown",
58659
58663
  success: false,
@@ -92941,7 +92945,7 @@ var init_registry = __esm(() => {
92941
92945
  sessionID: ctx.sessionID
92942
92946
  }),
92943
92947
  description: "Use /swarm finalize to finalize the swarm project and archive evidence",
92944
- details: "Idempotent 4-stage terminal finalization: (1) finalize writes retrospectives for in-progress phases, (2) archive creates timestamped bundle of swarm artifacts and evidence, (3) clean removes active-state files for a clean slate, (4) align performs safe git ff-only to main. Resets agent sessions and delegation chains. Reads .swarm/close-lessons.md for explicit lessons and runs curation. Use --skill-review to run the quota-bounded skill_improver in proposal mode.",
92948
+ details: "Idempotent 4-stage terminal finalization: (1) finalize writes retrospectives for in-progress phases, (2) archive creates timestamped bundle of swarm artifacts and evidence, (3) clean removes active-state files for a clean slate, (4) align performs aggressive git reset --hard to the default remote branch, discarding uncommitted changes and untracked files; falls back to a cautious reset that preserves uncommitted changes when the aggressive path cannot proceed. WARNING: alignment discards local changes and untracked files. Resets agent sessions and delegation chains. Reads .swarm/close-lessons.md for explicit lessons and runs curation. Use --skill-review to run the quota-bounded skill_improver in proposal mode.",
92945
92949
  args: "--prune-branches, --skill-review",
92946
92950
  category: "core",
92947
92951
  toolPolicy: "none"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.78.7",
3
+ "version": "7.78.8",
4
4
  "description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",