@monosmith/plugin-sdk 0.6.0 → 0.7.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.
@@ -38,6 +38,33 @@ export declare const ERROR_CODES: {
38
38
  readonly RequestCancelled: -32800;
39
39
  };
40
40
  export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];
41
+ /** APISurfaceParams asks a plugin for the public API names of one project. */
42
+ export interface APISurfaceParams {
43
+ project: Project;
44
+ /**
45
+ * Ref is the git revision to read the project at (the tag of its last release). Empty means the
46
+ * working tree.
47
+ */
48
+ ref?: string;
49
+ }
50
+ /**
51
+ * APISurfaceResult is the public API of a project: the names its entry points export. A host
52
+ * compares the names of two revisions; it never reads their meaning, so a plugin chooses its own
53
+ * spelling and keeps it stable.
54
+ */
55
+ export interface APISurfaceResult {
56
+ /**
57
+ * Names are the exported names, sorted. A name an entry point other than the main one exports is
58
+ * prefixed with that entry point and a colon ("./cli:run"). An empty list is an answer: the
59
+ * project exports nothing.
60
+ */
61
+ names: string[];
62
+ /**
63
+ * Unreadable says why the API could not be listed (no entry point, no source at the revision).
64
+ * When set, Names is empty and the host skips the project without a warning.
65
+ */
66
+ unreadable?: string;
67
+ }
41
68
  /**
42
69
  * ActionStep is a provider-native step: a GitHub action or an Azure task, with its inputs in the
43
70
  * order they are written.
@@ -150,6 +177,13 @@ export interface Capabilities {
150
177
  published?: boolean;
151
178
  /** Dependencies installs and uninstalls packages in its projects. */
152
179
  dependencies?: boolean;
180
+ /**
181
+ * Link makes a project depend on a library of the same workspace in the ecosystem's own form (a
182
+ * workspace dependency, a path dependency, a project reference), and takes it out again. A plugin
183
+ * without it is refused by the host with one sentence that tells the user to add the dependency
184
+ * by hand.
185
+ */
186
+ link?: boolean;
153
187
  /** Declarations lists and rewrites declared dependency specs (sync, up). */
154
188
  declarations?: boolean;
155
189
  /** Latest reports the newest releases of dependencies and pinned tools. */
@@ -162,6 +196,34 @@ export interface Capabilities {
162
196
  cancel?: boolean;
163
197
  /** Components lists a project's dependencies for its SBOM. */
164
198
  components?: boolean;
199
+ /** Derive says which files the plugin derives from facts and the project graph (smith derive). */
200
+ derive?: boolean;
201
+ /**
202
+ * APISurface lists the names a project exports, at a git revision, so a release can warn when the
203
+ * commits ask for a smaller bump than the API change needs.
204
+ */
205
+ apiSurface?: boolean;
206
+ /**
207
+ * Channels says a prerelease version the plugin publishes never takes the place of the stable
208
+ * one: the plugin publishes under PublishParams.Tag, a release channel's name, without moving the
209
+ * registry's stable pointer (npm's latest), or its registry orders a prerelease below the release
210
+ * (PyPI, NuGet) and needs no tag. A host does not publish a package of a release channel with a
211
+ * plugin that lacks it.
212
+ */
213
+ channels?: boolean;
214
+ /**
215
+ * Packs says publish honours PublishParams.PackDir: it writes the package file and publishes
216
+ * nowhere (registry = "github-release"). A host never calls publish with the setting on a plugin
217
+ * that lacks it, since the plugin would publish to the public registry.
218
+ */
219
+ packs?: boolean;
220
+ /**
221
+ * Declared says the plugin describes the projects smith.toml declares for its language
222
+ * (DiscoverParams.declared): folders with no manifest of their own. A plugin without it finds a
223
+ * project by its manifest only, and the host refuses a declaration for its language with a
224
+ * message that says so.
225
+ */
226
+ declared?: boolean;
165
227
  }
166
228
  /**
167
229
  * ChangeKindParams asks a plugin what changing a project's kind edits. The plugin writes nothing:
@@ -205,6 +267,68 @@ export interface ChangeKindResult {
205
267
  */
206
268
  warnings?: string[];
207
269
  }
270
+ /**
271
+ * Choice is one option on an axis of a project's make-up: a framework, a test runner, a style
272
+ * library. A plugin publishes the choices it owns in InitializeResult.Choices; the host checks a
273
+ * selection of them (smith add --with react,vitest,bootstrap) and turns it into a stack. What a
274
+ * choice writes (dependencies, tasks, files) stays with the plugin: the host never sees it.
275
+ */
276
+ export interface Choice {
277
+ /**
278
+ * Axis is the question the choice answers: "framework", "test", "style", "lint". The plugins
279
+ * agree on the name; the host only compares it.
280
+ */
281
+ axis: string;
282
+ /**
283
+ * Name identifies the choice in a selection and is unique among the choices of all loaded
284
+ * plugins.
285
+ */
286
+ name: string;
287
+ description?: string;
288
+ /** Title is the name shown to a person ("Electron" for electron). Without it the name is shown. */
289
+ title?: string;
290
+ /**
291
+ * Aliases are words that find the choice when a person searches the catalogue (smith compose):
292
+ * "desktop", "serverless", "web".
293
+ */
294
+ aliases?: string[];
295
+ /**
296
+ * Layer is where the choice sits in the stack of a project: "framework", "shell" (a desktop
297
+ * shell), "host" (where cloud code runs), "test", "lint", "style" or a layer of the plugin's own.
298
+ * Without it the layer is the axis. It is for display and grouping: the axis decides conflicts.
299
+ */
300
+ layer?: string;
301
+ /** Language is the language plugin the choice applies to ("node"). */
302
+ language: string;
303
+ /**
304
+ * Roles are the roles the choice's plugin plays in a stack built from it: scaffold (it writes the
305
+ * project) and/or toolchain (it joins the toolchain). Empty means it only adds to what a plugin
306
+ * of the selection already writes, as a style does.
307
+ */
308
+ roles?: Role[];
309
+ /**
310
+ * Needs are axes that the selection must have a choice on. An axis the person leaves out is
311
+ * filled with the default of the axis.
312
+ */
313
+ needs?: string[];
314
+ /** Default marks the choice the host adds when a selection needs its axis and has no choice on it. */
315
+ default?: boolean;
316
+ /**
317
+ * Suggested marks the choice an asker pre-selects on its axis. The solver never adds it by
318
+ * itself: an axis that a choice needs and that has no Default is asked, and the person answers
319
+ * (ADR 0072).
320
+ */
321
+ suggested?: boolean;
322
+ /**
323
+ * Many allows the choice next to other choices of its axis that are Many too. By default a
324
+ * selection has one choice per axis.
325
+ */
326
+ many?: boolean;
327
+ /** Requires are choices that must be in the selection. */
328
+ requires?: string[];
329
+ /** Conflicts are choices that must not be in the selection. */
330
+ conflicts?: string[];
331
+ }
208
332
  /** Component is one dependency of a project. */
209
333
  export interface Component {
210
334
  name: string;
@@ -266,6 +390,13 @@ export interface Contribution {
266
390
  * sets wins.
267
391
  */
268
392
  release?: ReleaseDefaults;
393
+ /**
394
+ * Facts are the plugin's default facts for the project: typed values under namespaced keys
395
+ * ({"source.roots": ["src"]}) that other settings and plugins read through the merged
396
+ * Project.Facts. They are the lowest scope: a [facts] table in smith.toml wins over them, and two
397
+ * plugins that publish different values for one key are an error that names both.
398
+ */
399
+ facts?: Record<string, unknown>;
269
400
  }
270
401
  /** Credential is a secret the release phase needs. */
271
402
  export interface Credential {
@@ -314,6 +445,15 @@ export interface Declaration {
314
445
  export interface DeclaredParams {
315
446
  projects: Project[];
316
447
  }
448
+ /** DeclaredProject is a project smith.toml declares: a folder with no manifest. */
449
+ export interface DeclaredProject {
450
+ /** Name is the project's name, the key of its [projects.<name>] table. */
451
+ name: string;
452
+ /** Root is the workspace-relative folder. */
453
+ root: string;
454
+ /** Kind is "app", "lib" or "package", or empty for the plugin's choice. */
455
+ kind?: ProjectKind;
456
+ }
317
457
  /**
318
458
  * DeclaredResult is every declaration, and the version installed of each name where the plugin can
319
459
  * tell.
@@ -327,6 +467,77 @@ export interface DependencyResult {
327
467
  files?: string[];
328
468
  notes?: string[];
329
469
  }
470
+ /**
471
+ * DeriveParams asks a plugin for the files it can derive from facts and the project graph. The
472
+ * plugin writes nothing: it answers with the content, and the host decides, from its ownership
473
+ * record, whether to write it.
474
+ */
475
+ export interface DeriveParams {
476
+ /** Projects are the projects the plugin serves. */
477
+ projects: Project[];
478
+ /**
479
+ * Graph maps a project name to the names of the projects it depends on inside the workspace,
480
+ * sorted. The host resolved these edges: a plugin does not repeat that work.
481
+ */
482
+ graph?: Record<string, string[]>;
483
+ /**
484
+ * Owned are the workspace-relative paths the host's ownership record says smith owns. A plugin
485
+ * proposes such a file again even when it is missing on disk, so deleting a derived file and
486
+ * deriving restores it. A file that is not owned and not on disk is not proposed.
487
+ */
488
+ owned?: string[];
489
+ }
490
+ /** DeriveResult carries the files a plugin derives. */
491
+ export interface DeriveResult {
492
+ files: DerivedFile[];
493
+ /**
494
+ * Diverging are files a renderer looked at and left alone because they differ from the shape
495
+ * their siblings share. They are not drift: the project owns them. The host shows them in `smith
496
+ * derive --explain` and in the doctor, and never writes them.
497
+ */
498
+ diverging?: DivergentFile[];
499
+ }
500
+ /** DerivedFile is the content one renderer derives for one file. */
501
+ export interface DerivedFile {
502
+ /** Project is the project the file belongs to. */
503
+ project: string;
504
+ /** Path is workspace-relative, with forward slashes. */
505
+ path: string;
506
+ /** Mode is DeriveFile, DeriveRegion or DeriveKeys. */
507
+ mode: string;
508
+ /**
509
+ * Renderer is the stable id of the renderer, for example "node.tsconfig.references". It names the
510
+ * region markers.
511
+ */
512
+ renderer: string;
513
+ /**
514
+ * Version is the renderer's version. A new version means new output for the same inputs, so the
515
+ * host rewrites an unedited file.
516
+ */
517
+ version: number;
518
+ /**
519
+ * Content is the whole file (DeriveFile) or the lines of the region (DeriveRegion), without the
520
+ * markers. Unused for DeriveKeys.
521
+ */
522
+ content?: string;
523
+ /**
524
+ * Comment is the line comment leader of the file ("//", "#"): the host writes a generated header
525
+ * after it in a DeriveFile. Empty for a format without comments, then the file has no header.
526
+ */
527
+ comment?: string;
528
+ /** Format is "json" or "toml" for DeriveKeys. */
529
+ format?: string;
530
+ /**
531
+ * Table is the TOML table that holds the keys ("tool.smith"); required for "toml", unused for
532
+ * "json", whose keys are the top-level ones.
533
+ */
534
+ table?: string;
535
+ /**
536
+ * Keys are the owned keys and their values (DeriveKeys). A TOML value is a string, a number, a
537
+ * boolean or an array of those.
538
+ */
539
+ keys?: Record<string, unknown>;
540
+ }
330
541
  /** DevcontainerFeature is a dev container feature and its options (https://containers.dev/features). */
331
542
  export interface DevcontainerFeature {
332
543
  /** ID is the feature reference, e.g. "ghcr.io/devcontainers/features/go:1". */
@@ -339,6 +550,20 @@ export interface DevcontainerFeature {
339
550
  */
340
551
  export interface DiscoverParams {
341
552
  manifests: string[];
553
+ /**
554
+ * Declared are the projects smith.toml declares for this plugin's language ([projects.<name>]
555
+ * with a root and a language): folders with no manifest of their own, such as a program that is a
556
+ * package of the Go module above it. The plugin describes each one in its result, or answers with
557
+ * an error saying why it cannot.
558
+ */
559
+ declared?: DeclaredProject[];
560
+ /**
561
+ * Settings are this plugin's settings for projects, by project name, from smith.toml
562
+ * [projects.<project>.settings.<plugin>]. They reach the plugin here because the tasks it
563
+ * describes may depend on them (the Go plugin's build tags). A project with no settings is
564
+ * absent.
565
+ */
566
+ settings?: Record<string, Record<string, unknown>>;
342
567
  }
343
568
  /**
344
569
  * DiscoverResult describes every manifest that is a project of this plugin. A manifest the plugin
@@ -347,6 +572,20 @@ export interface DiscoverParams {
347
572
  export interface DiscoverResult {
348
573
  projects: Project[];
349
574
  }
575
+ /**
576
+ * DivergentFile is a file a renderer does not derive because the project made it differ from its
577
+ * siblings.
578
+ */
579
+ export interface DivergentFile {
580
+ /** Project is the project the file belongs to. */
581
+ project: string;
582
+ /** Path is workspace-relative, with forward slashes. */
583
+ path: string;
584
+ /** Renderer is the stable id of the renderer that compared the file. */
585
+ renderer: string;
586
+ /** Detail says in a sentence how the file differs from its siblings. */
587
+ detail: string;
588
+ }
350
589
  /** DoctorParams gives the plugin its projects to check. */
351
590
  export interface DoctorParams {
352
591
  projects: Project[];
@@ -363,10 +602,31 @@ export interface FileEdit {
363
602
  content?: string;
364
603
  delete?: boolean;
365
604
  }
366
- /** Finding is one check. Every failed finding names its remedy. */
605
+ /** Finding is one check. Every failed finding names its problem and its remedy. */
367
606
  export interface Finding {
607
+ /**
608
+ * Check is the rule, stated as it should hold ("golangci-lint is 2.15.0, as in CI"). A passing
609
+ * finding is listed by it.
610
+ */
368
611
  check: string;
369
612
  ok: boolean;
613
+ /**
614
+ * Problem is what is wrong, in one line ("golangci-lint is 2.14.0, CI uses 2.15.0"). A failed
615
+ * finding is listed by it; one without it is listed by its Check.
616
+ */
617
+ problem?: string;
618
+ /**
619
+ * Project is the project the finding is about, as the workspace names it ("web"); empty for a
620
+ * finding about the workspace itself. The host files a finding under its project, so the Check,
621
+ * Problem and Detail need not name it.
622
+ */
623
+ project?: string;
624
+ /**
625
+ * Area is the part of the workspace a workspace-wide finding is about, in one lowercase word:
626
+ * "toolchain", "ci", "lint", "dependencies", "release", "git" or "config". A finding with a
627
+ * Project has none.
628
+ */
629
+ area?: string;
370
630
  detail?: string;
371
631
  remedy?: string;
372
632
  /** Warning true reports a problem without failing doctor. */
@@ -426,6 +686,11 @@ export interface FixChoice {
426
686
  export interface FixChoiceOption {
427
687
  label: string;
428
688
  fix: Fix;
689
+ /**
690
+ * Disabled, when not empty, is the reason the option cannot be picked: an interface shows the
691
+ * option greyed with the reason, and picking it is an error.
692
+ */
693
+ disabled?: string;
429
694
  }
430
695
  /** FixStep is a command to run in the workspace. */
431
696
  export interface FixStep {
@@ -435,6 +700,11 @@ export interface FixStep {
435
700
  argv: string[];
436
701
  /** Dir is where it runs, workspace-relative; empty is the workspace root. */
437
702
  dir?: string;
703
+ /**
704
+ * Env are KEY=VALUE entries added to the environment of the command (GOBIN=<folder> makes go
705
+ * install write there). Absent adds none.
706
+ */
707
+ env?: string[];
438
708
  }
439
709
  /**
440
710
  * GenerateParams asks a plugin to scaffold a project. The host chooses the directory from the kind
@@ -464,6 +734,25 @@ export interface GenerateParams {
464
734
  * Project.Settings. Nil when there are none.
465
735
  */
466
736
  settings?: Record<string, unknown>;
737
+ /**
738
+ * Facts are the shared facts that hold for the new project, from smith.toml:
739
+ * [projects.<name>.facts] over [facts]. A key that is absent was set by no one: the plugin
740
+ * scaffolds its own default. Set by the host; read only.
741
+ */
742
+ facts?: Record<string, unknown>;
743
+ /**
744
+ * Shape is the dialect the new project should have: the facts (see Project.Shape) that most
745
+ * projects of its kind and language agree on, as the host counted them. A plugin applies the keys
746
+ * it follows (see InitializeResult.Follows) and ignores the rest. Nil when there is nothing to
747
+ * follow, or the person asked for a fresh project.
748
+ */
749
+ shape?: Record<string, string>;
750
+ /**
751
+ * Choices are the choices (see Choice) the new project is built from, the stack's Choices, in the
752
+ * order they apply: a choice comes after those it requires. A plugin applies the choices it owns
753
+ * and ignores the rest. Absent when the stack is not a selection. Set by the host; read only.
754
+ */
755
+ choices?: string[];
467
756
  }
468
757
  /** GenerateResult lists what the plugin wrote, workspace-relative. */
469
758
  export interface GenerateResult {
@@ -535,6 +824,24 @@ export interface InitializeResult {
535
824
  * just those.
536
825
  */
537
826
  kinds?: ProjectKind[];
827
+ /**
828
+ * Follows are the shape keys (see Project.Shape) the plugin applies when it generates a project
829
+ * with GenerateParams.Shape. Where siblings split on a key, the host asks the person only for a
830
+ * key that a plugin of the stack follows. Absent means the plugin follows none.
831
+ */
832
+ follows?: string[];
833
+ /**
834
+ * Choices are the options on an axis (framework, test, style) the plugin owns. The host lists
835
+ * them (smith choices) and checks a selection of them (smith add --with). Absent means the plugin
836
+ * owns none.
837
+ */
838
+ choices?: Choice[];
839
+ /**
840
+ * Tools are the programs the plugin needs on the person's machine. The host detects them and,
841
+ * when one is missing, presents the ways to get it (smith tools). Absent means the plugin
842
+ * declares none.
843
+ */
844
+ tools?: ToolNeed[];
538
845
  }
539
846
  /**
540
847
  * Input is one input of an ActionStep. Values are written as quoted YAML strings, except true and
@@ -587,6 +894,62 @@ export interface LatestResult {
587
894
  unreachable?: Record<string, string>;
588
895
  tools?: ToolPin[];
589
896
  }
897
+ /**
898
+ * LinkOption is one way to write the dependency, with its consequence in words a person who read no
899
+ * manual can follow.
900
+ */
901
+ export interface LinkOption {
902
+ /** Spec is the value passed back in LinkParams.Spec. */
903
+ spec: string;
904
+ /** Label is the option in a few words. */
905
+ label: string;
906
+ /** Meaning says what happens with this option. */
907
+ meaning: string;
908
+ }
909
+ /**
910
+ * LinkParams asks a plugin to make Project depend on Library, a lib or package of the same
911
+ * workspace and language, in the ecosystem's own form, and to install or lock as that needs. The
912
+ * host has checked that both exist, that the languages match, that Library is not an app, and that
913
+ * the link makes no cycle; the plugin answers with an error that names the file when it cannot
914
+ * write the dependency.
915
+ */
916
+ export interface LinkParams {
917
+ /** Project is the project that gains the dependency. */
918
+ project: Project;
919
+ /** Library is the project it depends on. */
920
+ library: Project;
921
+ /** Quiet keeps the package manager's output unless it fails. */
922
+ quiet?: boolean;
923
+ /**
924
+ * Plan asks for the plan only: the plugin writes nothing and answers with the manifest, the line
925
+ * it would write and the choices the user has.
926
+ */
927
+ plan?: boolean;
928
+ /**
929
+ * Spec is the version range the user chose from LinkResult.Options; empty means the plugin's
930
+ * default, or the form the workspace already uses.
931
+ */
932
+ spec?: string;
933
+ }
934
+ /** LinkResult is what a link wrote, or with LinkParams.Plan would write. */
935
+ export interface LinkResult {
936
+ /** Files are the workspace-relative files changed (or to be changed). */
937
+ files?: string[];
938
+ /** Notes are for the user. */
939
+ notes?: string[];
940
+ /** Manifest is the file the dependency goes into, workspace-relative. */
941
+ manifest?: string;
942
+ /**
943
+ * Line is the dependency as it is written there, for the plan shown before anything is written
944
+ * ("@acme/core": "*").
945
+ */
946
+ line?: string;
947
+ /**
948
+ * Options are the real choices of the range written, with the default first. Empty when the
949
+ * ecosystem has none, or the workspace already follows a convention (then Line shows it).
950
+ */
951
+ options?: LinkOption[];
952
+ }
590
953
  /**
591
954
  * PackageStore is where a package manager keeps what it downloaded (npm's ~/.npm, Go's module
592
955
  * cache). A generated pipeline restores it before setup and saves it after a run, keyed on Files,
@@ -694,6 +1057,14 @@ export interface Project {
694
1057
  * [projects.<project>.<name>] on top. Set by the host; a plugin reads its own entry.
695
1058
  */
696
1059
  settings?: Record<string, Record<string, unknown>>;
1060
+ /**
1061
+ * Shape is the dialect of the project: named facts about how it is made ("build.tool": "esbuild",
1062
+ * "test.runner": "@swc/jest", "exports.target": "dist"), each a short string, read from the
1063
+ * manifest and files the plugin already reads in discovery. The host counts the shapes of the
1064
+ * projects of one kind and language to let a new project follow what they do, and knows no key
1065
+ * itself. Nil when the plugin does not describe shapes.
1066
+ */
1067
+ shape?: Record<string, string>;
697
1068
  /**
698
1069
  * Registries are the private registries the project installs from and publishes to, from
699
1070
  * smith.toml [registries]; nil means the public ones. Set by the host.
@@ -705,6 +1076,14 @@ export interface Project {
705
1076
  * a project that has no release files. Set by the host.
706
1077
  */
707
1078
  releaseAssets?: AssetSpec;
1079
+ /**
1080
+ * Facts are the shared facts that hold for the project, merged by the host, narrowest scope
1081
+ * first: [projects.<name>.facts], then [facts], then the defaults plugins published through
1082
+ * Contribution.Facts. A key that is absent was set by no one: the plugin uses its own default. A
1083
+ * request made before every plugin has contributed carries the smith.toml facts and the defaults
1084
+ * published so far. Set by the host; read only.
1085
+ */
1086
+ facts?: Record<string, unknown>;
708
1087
  }
709
1088
  /**
710
1089
  * ProjectKind is the universal kind vocabulary.
@@ -742,6 +1121,33 @@ export interface PublishParams {
742
1121
  */
743
1122
  commit?: string;
744
1123
  branch?: string;
1124
+ /**
1125
+ * Tag is the name of the release channel the version belongs to (npm's dist-tag "beta"). When
1126
+ * set, the plugin publishes under it and leaves the registry's stable pointer where it is, or
1127
+ * ignores it when its registry has no such pointer. Only sent to a plugin with the channels
1128
+ * capability.
1129
+ */
1130
+ tag?: string;
1131
+ /**
1132
+ * PropagationWait is the longest time a plugin waits, in a Finalize call, for the packages of the
1133
+ * release to be fetchable from the registry: a duration such as "15m", "0" to not wait. Empty
1134
+ * means the default. Only npm has such a wait. A publish never waits.
1135
+ */
1136
+ propagationWait?: string;
1137
+ /**
1138
+ * PackDir, when set, turns the call into a pack: the plugin writes the package file of the
1139
+ * project's ecosystem (npm tarball, wheel and sdist, .nupkg, .gem, .crate) and returns the files
1140
+ * in PublishResult.Assets, and publishes nothing anywhere. A workspace-relative folder. The host
1141
+ * sends it only to a plugin with the packs capability. In a dry run the plugin lists the files it
1142
+ * would write, writes none, and reads no registry.
1143
+ */
1144
+ packDir?: string;
1145
+ /**
1146
+ * Finalize turns the call into the last phase of a release: nothing is published; for each move
1147
+ * the plugin waits until its packages are fetchable, then moves the dist-tag. The host sends it
1148
+ * after every project has published, so a wait never blocks another publish.
1149
+ */
1150
+ finalize?: TagMove[];
745
1151
  }
746
1152
  /**
747
1153
  * PublishResult reports what happened. Skipped with a reason is a success: an already-published
@@ -751,6 +1157,20 @@ export interface PublishResult {
751
1157
  published: boolean;
752
1158
  skipped?: string;
753
1159
  registry?: string;
1160
+ /**
1161
+ * Notes are things the person must know about a publish that succeeded, such as a dist-tag that
1162
+ * was not moved; the host prints them and the report keeps them.
1163
+ */
1164
+ notes?: string[];
1165
+ /**
1166
+ * PendingMoves are the dist-tags the call did not move, because the packages the release needs
1167
+ * were not fetchable yet. A publish returns them for the host to move at the end of the release;
1168
+ * a Finalize call returns the ones still waiting when its time ran out. The release then ends
1169
+ * with a warning, never silently.
1170
+ */
1171
+ pendingMoves?: TagMove[];
1172
+ /** Moved names the dist-tags a Finalize call moved ("name@version tag"). */
1173
+ moved?: string[];
754
1174
  /**
755
1175
  * Assets are the workspace-relative files built for the release, in upload order; in a dry run,
756
1176
  * the files that would be built.
@@ -815,6 +1235,13 @@ export interface Registries {
815
1235
  * rest).
816
1236
  */
817
1237
  noPublish?: boolean;
1238
+ /**
1239
+ * PackToRelease means smith.toml says registry = "github-release": the release packs the project
1240
+ * into its ecosystem's package file and attaches it to the project's GitHub Release, publishing
1241
+ * to no registry. The host sends PublishParams.PackDir to a plugin with the packs capability and
1242
+ * never calls publish on one without it.
1243
+ */
1244
+ packToRelease?: boolean;
818
1245
  }
819
1246
  /**
820
1247
  * Registry is a package registry smith.toml names in [registries.<name>]: a private feed (Azure
@@ -931,6 +1358,12 @@ export interface Stack {
931
1358
  /** Scaffold generates new projects; empty means the language plugin does. */
932
1359
  scaffold?: string;
933
1360
  deploy?: string[];
1361
+ /**
1362
+ * Choices make the stack a saved selection (see Choice). When they are set, the host derives the
1363
+ * language, the scaffold and the toolchain from them, and Toolchain lists only the plugins to add
1364
+ * after those. The plugins of the stack get the choices in GenerateParams.Choices.
1365
+ */
1366
+ choices?: string[];
934
1367
  }
935
1368
  /** Step is one command a CI phase runs. */
936
1369
  export interface Step {
@@ -948,6 +1381,19 @@ export interface Step {
948
1381
  */
949
1382
  cacheFiles?: string[];
950
1383
  }
1384
+ /**
1385
+ * TagMove is a dist-tag a publish left where it was, because the packages the release needs were
1386
+ * not fetchable yet.
1387
+ */
1388
+ export interface TagMove {
1389
+ /** Package and Version name the package that carries the tag. */
1390
+ package: string;
1391
+ version: string;
1392
+ /** Tag is the dist-tag to move to Version. */
1393
+ tag: string;
1394
+ /** Awaits are the packages that must be fetchable first. */
1395
+ awaits: string[];
1396
+ }
951
1397
  /** Task is a command the host can run, hash and cache. */
952
1398
  export interface Task {
953
1399
  /** Command is an argv array; it is never passed through a shell. */
@@ -991,6 +1437,101 @@ export interface Task {
991
1437
  /** ServeTimeout is how long to wait for ServeURL, as a Go duration ("60s"); empty means 60s. */
992
1438
  serveTimeout?: string;
993
1439
  }
1440
+ /**
1441
+ * ToolInstall is one way to get a tool with a package manager. Manager is one of: "winget", "brew",
1442
+ * "brew-cask", "apt", "dnf", "pacman", "npm", "uv", "fnm", "rustup", "cargo" and "go" (go install,
1443
+ * for a tool published as a Go module). The host builds the exact command from the manager and
1444
+ * Package; Package may hold {major}, {major.minor} and {version} (the whole version), which the
1445
+ * pinned or suggested version fills. The language's own installers (uv, fnm, rustup, cargo) are
1446
+ * offered only when they are already on the machine.
1447
+ */
1448
+ export interface ToolInstall {
1449
+ manager: string;
1450
+ package: string;
1451
+ /** Note adds a sentence the person needs before choosing ("a new terminal is needed"). */
1452
+ note?: string;
1453
+ }
1454
+ /**
1455
+ * ToolNeed is a program on the person's machine that a plugin needs to build, test or run its
1456
+ * projects (Python, the .NET SDK, Docker). A plugin publishes the tools it needs in
1457
+ * InitializeResult.Tools. The host detects them, and when one is missing it presents the ways to
1458
+ * get it (ADR 0077): it never installs in silence. The plugin writes facts only (what the tool is,
1459
+ * how to detect it, how each system gets it); the host decides how to ask.
1460
+ */
1461
+ export interface ToolNeed {
1462
+ /**
1463
+ * Name identifies the tool across plugins and in commands (smith tools install python). Two
1464
+ * plugins that need the same tool use the same Name.
1465
+ */
1466
+ name: string;
1467
+ /**
1468
+ * Title is what the tool is called in text: "Python", "the .NET SDK". Doctor words the check
1469
+ * "<Title> is installed".
1470
+ */
1471
+ title: string;
1472
+ /** Why says in plain words what smith needs the tool for. */
1473
+ why: string;
1474
+ /**
1475
+ * Consequence says what stops working while the tool is missing, as the end of a sentence that
1476
+ * starts "If you skip it, ": "smith test and smith build fail for the python projects".
1477
+ */
1478
+ consequence: string;
1479
+ /** Program is the program that carries the tool on PATH ("python3"). */
1480
+ program: string;
1481
+ /** Alternatives are other programs that also count ("python", "py"). */
1482
+ alternatives?: string[];
1483
+ /** VersionArgs are the arguments that make Program print its version. Absent means --version. */
1484
+ versionArgs?: string[];
1485
+ /**
1486
+ * Pins are the files where a workspace pins the version it wants. The first pin the host finds
1487
+ * gives the version range. Absent means any version counts.
1488
+ */
1489
+ pins?: ToolVersionPin[];
1490
+ /**
1491
+ * Choice limits the tool to stacks that have this choice ("azure-functions"): the tool is not
1492
+ * needed by a project built without it. Absent means every project of the plugin needs it.
1493
+ */
1494
+ choice?: string;
1495
+ /**
1496
+ * Files limit the tool to projects that hold one of these files in their folder
1497
+ * ("build.gradle.kts"): a Gradle build needs gradle, a Maven build does not. A tool that the
1498
+ * tasks of a project run (gradle, mvn) is declared this way. Absent means every project of the
1499
+ * plugin needs it.
1500
+ */
1501
+ files?: string[];
1502
+ /**
1503
+ * Systems limits the tool to these systems, named as Go names them ("windows", "darwin",
1504
+ * "linux"): the Xcode Command Line Tools exist only on "darwin". Absent means every system.
1505
+ */
1506
+ systems?: string[];
1507
+ /**
1508
+ * Suggested is the version smith installs when no pin says one: "3.13". It fills {major} and
1509
+ * {major.minor} in the install entries.
1510
+ */
1511
+ suggested?: string;
1512
+ /**
1513
+ * Optional marks a tool whose absence only costs a feature (running a function app locally).
1514
+ * Doctor reports it as a warning, not a failure.
1515
+ */
1516
+ optional?: boolean;
1517
+ /**
1518
+ * Exact says Suggested is the one version the workspace wants, such as the version CI pins: an
1519
+ * installed version that differs, older or newer, is reported as different, and an install
1520
+ * fetches that version.
1521
+ */
1522
+ exact?: boolean;
1523
+ /** Install are the ways to get the tool, per package manager and system. */
1524
+ install?: ToolInstall[];
1525
+ /**
1526
+ * Download is the official page of the tool, for the person who installs it by hand or has no
1527
+ * package manager.
1528
+ */
1529
+ download: string;
1530
+ /** Source is the address of the page the Install entries were checked against. */
1531
+ source: string;
1532
+ /** Checked is the date (YYYY-MM-DD) the entries were last checked. */
1533
+ checked: string;
1534
+ }
994
1535
  /**
995
1536
  * ToolPin is a tool the plugin installs at a pinned version (in CI, the dev container, the venv)
996
1537
  * against the newest release; informational.
@@ -1003,6 +1544,20 @@ export interface ToolPin {
1003
1544
  /** Newer is true when Latest is a release the pin does not cover. */
1004
1545
  newer?: boolean;
1005
1546
  }
1547
+ /**
1548
+ * ToolVersionPin names a file that pins the version of a tool and how to read it. Format is one of:
1549
+ * "text" (the first word of the file, as in .nvmrc and .python-version), "go-mod" (the toolchain
1550
+ * line, else the go line), "pyproject" (requires-python), "global-json" (sdk.version) and
1551
+ * "rust-toolchain" (the channel).
1552
+ */
1553
+ export interface ToolVersionPin {
1554
+ /**
1555
+ * File is the base name of the file, looked up at the workspace root and in the folders of the
1556
+ * projects that use the tool.
1557
+ */
1558
+ file: string;
1559
+ format: string;
1560
+ }
1006
1561
  /**
1007
1562
  * Toolchain is a runtime the pipeline must install, and how. Plugins asking for the same name share
1008
1563
  * one setup step (the first plugin's).
@@ -1030,6 +1585,14 @@ export interface UninstallParams {
1030
1585
  project: Project;
1031
1586
  packages: string[];
1032
1587
  }
1588
+ /**
1589
+ * UnlinkParams asks a plugin to remove the dependency of Project on Library. Notes of the result
1590
+ * say so when the manifest held no such dependency.
1591
+ */
1592
+ export interface UnlinkParams {
1593
+ project: Project;
1594
+ library: Project;
1595
+ }
1033
1596
  /** VersionParams asks a plugin to record a new version in a project manifest. */
1034
1597
  export interface VersionParams {
1035
1598
  project: Project;
@@ -1166,6 +1729,21 @@ export interface ProtocolMethods {
1166
1729
  result: DependencyResult;
1167
1730
  capability: 'dependencies';
1168
1731
  };
1732
+ /**
1733
+ * Makes a project depend on a library of the same workspace and language, in the ecosystem's own
1734
+ * form, then installs or locks as that needs.
1735
+ */
1736
+ 'dependencies/link': {
1737
+ params: LinkParams;
1738
+ result: LinkResult;
1739
+ capability: 'link';
1740
+ };
1741
+ /** Removes the dependency of a project on a library of the same workspace. */
1742
+ 'dependencies/unlink': {
1743
+ params: UnlinkParams;
1744
+ result: DependencyResult;
1745
+ capability: 'link';
1746
+ };
1169
1747
  /** Lists the dependencies the manifests of the plugin's projects declare. */
1170
1748
  'dependencies/declared': {
1171
1749
  params: DeclaredParams;
@@ -1197,6 +1775,25 @@ export interface ProtocolMethods {
1197
1775
  result: ComponentsResult;
1198
1776
  capability: 'components';
1199
1777
  };
1778
+ /**
1779
+ * Asks which files a plugin derives from facts and the project graph (a tsconfig's references, a
1780
+ * test config's display name). The plugin writes nothing: it answers with the content, and the
1781
+ * host rewrites a file only when its ownership record allows.
1782
+ */
1783
+ derive: {
1784
+ params: DeriveParams;
1785
+ result: DeriveResult;
1786
+ capability: 'derive';
1787
+ };
1788
+ /**
1789
+ * Asks for the public API names of a project, at the working tree or at a git revision (its last
1790
+ * release tag), so a release can compare them and say what bump the change needs.
1791
+ */
1792
+ 'api/surface': {
1793
+ params: APISurfaceParams;
1794
+ result: APISurfaceResult;
1795
+ capability: 'apiSurface';
1796
+ };
1200
1797
  }
1201
1798
  export type MethodName = keyof ProtocolMethods;
1202
1799
  export type ParamsOf<M extends MethodName> = ProtocolMethods[M]['params'];