@penvhq/launcher 0.10.0 → 0.12.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.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
- import { Environment, PenvError, ManifestEngine, PackageKind } from '@penvhq/core';
1
+ import { Environment, PenvError, ManifestEngine, PackageKind, Manifest } from '@penvhq/core';
2
+ import { InstallRuntime } from '@penvhq/cli/install';
2
3
 
3
4
  /**
4
5
  * Every byte penv downloads comes through here.
@@ -50,10 +51,13 @@ interface LauncherIo {
50
51
  * is two committed files with no runtime in them: the manifest entry, and a
51
52
  * type-only declaration.
52
53
  *
53
- * Because those two files are committed, `add` is a decision and needs a person:
54
- * `--no-download` and a run with nobody at it are both refused before the first
55
- * request, and CI gets `penv install`, which installs what the manifest already
56
- * pins rather than choosing what it should.
54
+ * `add` refuses a run with nobody at it only when it has something to ask. The
55
+ * questions are known from the package name before anything is fetched, and for
56
+ * `@penvhq/*` there are none so the gate used to refuse a run that would have
57
+ * been silent. What cannot be answered unattended is the trust ceremony, whose
58
+ * one field is a sentence about why a stranger's code is trusted; `--yes` says
59
+ * nobody is here to be asked, so it cannot answer that either. `--no-download`
60
+ * is refused whatever the package, because there is nothing to pin without it.
57
61
  *
58
62
  * `--local` is the one path with no release behind it: a repository that writes
59
63
  * a provider adds the package it already builds. Nothing is fetched and nothing
@@ -225,6 +229,10 @@ declare function bundledEngine(): Engine;
225
229
 
226
230
  /** The command that materializes everything the manifest pins. */
227
231
  declare const INSTALL_COMMAND = "penv install";
232
+ /** The command that moves the engine pin, with no version: whatever `latest` points at. */
233
+ declare const UPGRADE_COMMAND = "penv upgrade";
234
+ /** The flag that answers `upgrade`'s one question ahead of time. */
235
+ declare const YES_FLAG = "--yes";
228
236
  /** How long a package outside the official scope must have existed. */
229
237
  declare const MIN_PACKAGE_AGE_DAYS = 7;
230
238
  /** The flag that overrides {@link MIN_PACKAGE_AGE_DAYS}, and only that. */
@@ -323,10 +331,16 @@ declare class OfficialRegistryError extends PenvError {
323
331
  readonly name = "OfficialRegistryError";
324
332
  constructor(name: string, registry: string);
325
333
  }
326
- /** The registry could not be read at all. */
334
+ /**
335
+ * The registry could not be read at all.
336
+ *
337
+ * `retry` is the command that would repeat this resolution. Two commands read a
338
+ * release — `add` and `upgrade` — and a refusal that named the wrong one would
339
+ * send the reader to a command that answers a different question.
340
+ */
327
341
  declare class RegistryUnreadableError extends PenvError {
328
342
  readonly name = "RegistryUnreadableError";
329
- constructor(name: string, url: string, detail: string);
343
+ constructor(name: string, url: string, detail: string, retry?: string);
330
344
  }
331
345
  /** The registry has no such package. */
332
346
  declare class PackageUnknownError extends PenvError {
@@ -336,7 +350,7 @@ declare class PackageUnknownError extends PenvError {
336
350
  /** The package exists; the version asked for does not. */
337
351
  declare class VersionUnknownError extends PenvError {
338
352
  readonly name = "VersionUnknownError";
339
- constructor(name: string, version: string, url: string);
353
+ constructor(name: string, version: string, url: string, retry?: string);
340
354
  }
341
355
  /** The registry answered, but without a fact the manifest has to record. */
342
356
  declare class ReleaseIncompleteError extends PenvError {
@@ -354,17 +368,17 @@ declare class AddNoDownloadError extends PenvError {
354
368
  constructor(name: string);
355
369
  }
356
370
  /**
357
- * `penv add` on a machine with nobody at it.
371
+ * `penv add` with a question and nobody to answer it.
358
372
  *
359
- * It is refused everywhere, not only for the packages that pay the trust
360
- * ceremony: what `add` writes is two committed files, and a pipeline that
361
- * rewrites the manifest it was handed is a pipeline choosing which bytes the
362
- * project runs. `penv install` is the command CI has, and it installs exactly
363
- * what a person already decided.
373
+ * Only the trust ceremony reaches here. It used to refuse every unattended add,
374
+ * including an `@penvhq/*` one that asks nothing at all a gate stopping a run
375
+ * that would have been silent. What no flag can supply is the ceremony's one
376
+ * field: a sentence about why a stranger's code is trusted, which is why
377
+ * `--yes` does not answer it either.
364
378
  */
365
- declare class AddNotInteractiveError extends PenvError {
366
- readonly name = "AddNotInteractiveError";
367
- constructor(name: string);
379
+ declare class AddTrustUnattendedError extends PenvError {
380
+ readonly name = "AddTrustUnattendedError";
381
+ constructor(name: string, ceremony: string);
368
382
  }
369
383
  /** The trust ceremony was declined. Nothing was installed or recorded. */
370
384
  declare class TrustDeclinedError extends PenvError {
@@ -401,6 +415,50 @@ declare class EnginePinMismatchError extends PenvError {
401
415
  readonly name = "EnginePinMismatchError";
402
416
  constructor(pinned: string, ran: string);
403
417
  }
418
+ /** `penv upgrade` with something other than one optional version. */
419
+ declare class UpgradeSubjectError extends PenvError {
420
+ readonly name = "UpgradeSubjectError";
421
+ constructor();
422
+ }
423
+ /** A flag `penv upgrade` does not have. */
424
+ declare class UpgradeFlagError extends PenvError {
425
+ readonly name = "UpgradeFlagError";
426
+ constructor(flag: string);
427
+ }
428
+ /** `penv upgrade` needs the registry, and `--no-download` says this run has no network. */
429
+ declare class UpgradeNoDownloadError extends PenvError {
430
+ readonly name = "UpgradeNoDownloadError";
431
+ constructor();
432
+ }
433
+ /**
434
+ * `penv upgrade` on a machine with nobody at it.
435
+ *
436
+ * Unattended, penv will move the pin only to a version somebody named and only
437
+ * with the flag that says they meant it: what upgrade rewrites is two committed
438
+ * files, and a pipeline that picks the engine is a pipeline choosing which bytes
439
+ * the project runs.
440
+ */
441
+ declare class UpgradeUnattendedError extends PenvError {
442
+ readonly name = "UpgradeUnattendedError";
443
+ constructor();
444
+ }
445
+ /** The upgrade was shown and declined. Neither committed file was touched. */
446
+ declare class UpgradeDeclinedError extends PenvError {
447
+ readonly name = "UpgradeDeclinedError";
448
+ constructor(version: string);
449
+ }
450
+ /**
451
+ * The package manager refused, so the pin stayed where it was.
452
+ *
453
+ * The dependency moves before the manifest for exactly this reason: an upgrade
454
+ * that cannot finish leaves a project pinning the engine it was already running.
455
+ * The remedy is never the command that just failed — that is the one instruction
456
+ * known not to work. The manager printed why; that line is where to look.
457
+ */
458
+ declare class UpgradeInstallFailedError extends PenvError {
459
+ readonly name = "UpgradeInstallFailedError";
460
+ constructor(manager: string, version: string);
461
+ }
404
462
  /** An installed directory with nothing runnable in it. */
405
463
  declare class EngineEntryError extends PenvError {
406
464
  readonly name = "EngineEntryError";
@@ -548,6 +606,8 @@ interface ReleaseQuery {
548
606
  readonly version?: string;
549
607
  /** Only when the package comes from somewhere other than npmjs. */
550
608
  readonly registry?: string;
609
+ /** The command that would repeat this resolution. Absent means `penv add <name>`. */
610
+ readonly retry?: string;
551
611
  readonly fetcher: Fetcher;
552
612
  }
553
613
  /** The packument's address, which an exact name can be built rather than searched. */
@@ -621,4 +681,54 @@ interface ArchiveSubject {
621
681
  /** Every regular file in an npm tarball, `package/` stripped. */
622
682
  declare function readTarball(gzipped: Uint8Array, subject: ArchiveSubject): TarEntry[];
623
683
 
624
- export { AddFlagError, AddLocalFlagError, AddLocalInCiError, AddNoDownloadError, AddNotInteractiveError, type AddOptions, AddPackageNameError, AddRegistryError, type AddResult, AddSubjectError, ArchiveError, type ArchiveSubject, BUNDLED_ENGINE_PIN, DEFAULT_REGISTRY, DEV_PIN_INTEGRITY, DEV_PIN_VERSION, DeclarationMissingError, DeclarationNotSelfContainedError, type DeclarationSubject, type Delegation, DownloadFailedError, DownloadIntegrityError, ENGINE_BIN, type Engine, EngineEntryError, EnginePinMismatchError, EnginePinUnreleasedError, ExtensionNotImportableError, type ExtensionPackage, ExtensionUnloadableError, type Fetcher, HOME_META_FILE, INSTALL_COMMAND, INTEGRITY_FILE, InstallDeclinedError, type InstallOptions, type InstallState, type Installation, LOCAL_FLAG, type LauncherIo, type LauncherOptions, LocalExtensionUnresolvedError, MIN_PACKAGE_AGE_DAYS, NPM_UPDATE_COMMAND, NoProjectError, OfficialRegistryError, PackageCorruptError, PackageMissingError, PackageTooYoungError, PackageUnknownError, type Pin, type Project, type ProviderEntry, RegistryUnreadableError, type Release, ReleaseIncompleteError, type ReleaseQuery, type Spawner, TRUST_YOUNG_FLAG, type TarEntry, TrustDeclinedError, TrustPublisherMissingError, TrustReasonMissingError, VersionUnknownError, add, assertReleasePin, bundledEngine, declarationPath, engineAt, fetchRelease, findAdoptedRoot, findProject, httpFetcher, inspectInstall, installPin, integrityOf, launcherUpdateCommand, nodeSpawner, packumentUrl, readExtensionPackage, readProviderEntries, readTarball, releaseEnginePin, renderDeclaration, runLauncher, setProviderType, tarballUrl, writeDeclaration };
684
+ /**
685
+ * `penv upgrade [version]` — the one command that moves the engine pin.
686
+ *
687
+ * It belongs to the launcher for the same reason `add` does: everything it
688
+ * writes is the launcher's. An engine cannot compute the npm integrity of its
689
+ * own tarball, and the pin is a promise about bytes, so the integrity comes from
690
+ * the registry's `dist.integrity` and from nowhere else — never hashed here, and
691
+ * never typed by a person. Before this command existed, moving the pin meant
692
+ * hand-editing a version *and* an 88-character hash into the one file whose
693
+ * whole purpose is that its bytes are verified, and a mistyped character came
694
+ * back as a supply-chain check failing closed.
695
+ *
696
+ * The manifest's engine pin and the project's `@penvhq/penv` dependency move
697
+ * together, at the same exact version. In a workspace that dependency is plural
698
+ * — a package declaring its own `@penvhq/penv` is a second bridge running under
699
+ * the pin, and one repository ran the 0.8 one under a 0.11 manifest for three
700
+ * releases because `upgrade` looked only at the root. Every `package.json` that
701
+ * declares it is in the one diff, and they move together or not at all: the
702
+ * dependencies land first, so a package manager that refuses leaves a project
703
+ * still pinning the engine it was already running.
704
+ *
705
+ * Extensions are not touched. Each carries its own pin and its own trust
706
+ * decision, and re-pinning them because the engine moved would be penv choosing
707
+ * bytes nobody reviewed; `penv add <package>@<version>` moves one.
708
+ *
709
+ * A downgrade is an upgrade backwards and takes the same path — a pin is a pin,
710
+ * and a project that needs the engine it ran last week is not asking for
711
+ * something penv should argue with.
712
+ */
713
+
714
+ interface UpgradeOptions {
715
+ /** The tokens after `upgrade`. */
716
+ readonly argv: readonly string[];
717
+ /** The project root — the directory holding `.penv/`. */
718
+ readonly root: string;
719
+ readonly manifestFile: string;
720
+ /** The manifest as the launcher already parsed it. */
721
+ readonly manifest: Manifest;
722
+ readonly home: string;
723
+ readonly io: LauncherIo;
724
+ readonly fetcher: Fetcher;
725
+ /** The launcher's `--no-download`: this run reaches no registry at all. */
726
+ readonly noDownload?: boolean;
727
+ /** True on a CI runner, which may have a terminal and still have nobody at it. */
728
+ readonly ci?: boolean;
729
+ /** Injected in tests: how the project's dependency is installed. Never spawns there. */
730
+ readonly install?: InstallRuntime;
731
+ }
732
+ declare function upgrade(options: UpgradeOptions): Promise<void>;
733
+
734
+ export { AddFlagError, AddLocalFlagError, AddLocalInCiError, AddNoDownloadError, type AddOptions, AddPackageNameError, AddRegistryError, type AddResult, AddSubjectError, AddTrustUnattendedError, ArchiveError, type ArchiveSubject, BUNDLED_ENGINE_PIN, DEFAULT_REGISTRY, DEV_PIN_INTEGRITY, DEV_PIN_VERSION, DeclarationMissingError, DeclarationNotSelfContainedError, type DeclarationSubject, type Delegation, DownloadFailedError, DownloadIntegrityError, ENGINE_BIN, type Engine, EngineEntryError, EnginePinMismatchError, EnginePinUnreleasedError, ExtensionNotImportableError, type ExtensionPackage, ExtensionUnloadableError, type Fetcher, HOME_META_FILE, INSTALL_COMMAND, INTEGRITY_FILE, InstallDeclinedError, type InstallOptions, type InstallState, type Installation, LOCAL_FLAG, type LauncherIo, type LauncherOptions, LocalExtensionUnresolvedError, MIN_PACKAGE_AGE_DAYS, NPM_UPDATE_COMMAND, NoProjectError, OfficialRegistryError, PackageCorruptError, PackageMissingError, PackageTooYoungError, PackageUnknownError, type Pin, type Project, type ProviderEntry, RegistryUnreadableError, type Release, ReleaseIncompleteError, type ReleaseQuery, type Spawner, TRUST_YOUNG_FLAG, type TarEntry, TrustDeclinedError, TrustPublisherMissingError, TrustReasonMissingError, UPGRADE_COMMAND, UpgradeDeclinedError, UpgradeFlagError, UpgradeInstallFailedError, UpgradeNoDownloadError, type UpgradeOptions, UpgradeSubjectError, UpgradeUnattendedError, VersionUnknownError, YES_FLAG, add, assertReleasePin, bundledEngine, declarationPath, engineAt, fetchRelease, findAdoptedRoot, findProject, httpFetcher, inspectInstall, installPin, integrityOf, launcherUpdateCommand, nodeSpawner, packumentUrl, readExtensionPackage, readProviderEntries, readTarball, releaseEnginePin, renderDeclaration, runLauncher, setProviderType, tarballUrl, upgrade, writeDeclaration };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Environment, PenvError, ManifestEngine, PackageKind } from '@penvhq/core';
1
+ import { Environment, PenvError, ManifestEngine, PackageKind, Manifest } from '@penvhq/core';
2
+ import { InstallRuntime } from '@penvhq/cli/install';
2
3
 
3
4
  /**
4
5
  * Every byte penv downloads comes through here.
@@ -50,10 +51,13 @@ interface LauncherIo {
50
51
  * is two committed files with no runtime in them: the manifest entry, and a
51
52
  * type-only declaration.
52
53
  *
53
- * Because those two files are committed, `add` is a decision and needs a person:
54
- * `--no-download` and a run with nobody at it are both refused before the first
55
- * request, and CI gets `penv install`, which installs what the manifest already
56
- * pins rather than choosing what it should.
54
+ * `add` refuses a run with nobody at it only when it has something to ask. The
55
+ * questions are known from the package name before anything is fetched, and for
56
+ * `@penvhq/*` there are none so the gate used to refuse a run that would have
57
+ * been silent. What cannot be answered unattended is the trust ceremony, whose
58
+ * one field is a sentence about why a stranger's code is trusted; `--yes` says
59
+ * nobody is here to be asked, so it cannot answer that either. `--no-download`
60
+ * is refused whatever the package, because there is nothing to pin without it.
57
61
  *
58
62
  * `--local` is the one path with no release behind it: a repository that writes
59
63
  * a provider adds the package it already builds. Nothing is fetched and nothing
@@ -225,6 +229,10 @@ declare function bundledEngine(): Engine;
225
229
 
226
230
  /** The command that materializes everything the manifest pins. */
227
231
  declare const INSTALL_COMMAND = "penv install";
232
+ /** The command that moves the engine pin, with no version: whatever `latest` points at. */
233
+ declare const UPGRADE_COMMAND = "penv upgrade";
234
+ /** The flag that answers `upgrade`'s one question ahead of time. */
235
+ declare const YES_FLAG = "--yes";
228
236
  /** How long a package outside the official scope must have existed. */
229
237
  declare const MIN_PACKAGE_AGE_DAYS = 7;
230
238
  /** The flag that overrides {@link MIN_PACKAGE_AGE_DAYS}, and only that. */
@@ -323,10 +331,16 @@ declare class OfficialRegistryError extends PenvError {
323
331
  readonly name = "OfficialRegistryError";
324
332
  constructor(name: string, registry: string);
325
333
  }
326
- /** The registry could not be read at all. */
334
+ /**
335
+ * The registry could not be read at all.
336
+ *
337
+ * `retry` is the command that would repeat this resolution. Two commands read a
338
+ * release — `add` and `upgrade` — and a refusal that named the wrong one would
339
+ * send the reader to a command that answers a different question.
340
+ */
327
341
  declare class RegistryUnreadableError extends PenvError {
328
342
  readonly name = "RegistryUnreadableError";
329
- constructor(name: string, url: string, detail: string);
343
+ constructor(name: string, url: string, detail: string, retry?: string);
330
344
  }
331
345
  /** The registry has no such package. */
332
346
  declare class PackageUnknownError extends PenvError {
@@ -336,7 +350,7 @@ declare class PackageUnknownError extends PenvError {
336
350
  /** The package exists; the version asked for does not. */
337
351
  declare class VersionUnknownError extends PenvError {
338
352
  readonly name = "VersionUnknownError";
339
- constructor(name: string, version: string, url: string);
353
+ constructor(name: string, version: string, url: string, retry?: string);
340
354
  }
341
355
  /** The registry answered, but without a fact the manifest has to record. */
342
356
  declare class ReleaseIncompleteError extends PenvError {
@@ -354,17 +368,17 @@ declare class AddNoDownloadError extends PenvError {
354
368
  constructor(name: string);
355
369
  }
356
370
  /**
357
- * `penv add` on a machine with nobody at it.
371
+ * `penv add` with a question and nobody to answer it.
358
372
  *
359
- * It is refused everywhere, not only for the packages that pay the trust
360
- * ceremony: what `add` writes is two committed files, and a pipeline that
361
- * rewrites the manifest it was handed is a pipeline choosing which bytes the
362
- * project runs. `penv install` is the command CI has, and it installs exactly
363
- * what a person already decided.
373
+ * Only the trust ceremony reaches here. It used to refuse every unattended add,
374
+ * including an `@penvhq/*` one that asks nothing at all a gate stopping a run
375
+ * that would have been silent. What no flag can supply is the ceremony's one
376
+ * field: a sentence about why a stranger's code is trusted, which is why
377
+ * `--yes` does not answer it either.
364
378
  */
365
- declare class AddNotInteractiveError extends PenvError {
366
- readonly name = "AddNotInteractiveError";
367
- constructor(name: string);
379
+ declare class AddTrustUnattendedError extends PenvError {
380
+ readonly name = "AddTrustUnattendedError";
381
+ constructor(name: string, ceremony: string);
368
382
  }
369
383
  /** The trust ceremony was declined. Nothing was installed or recorded. */
370
384
  declare class TrustDeclinedError extends PenvError {
@@ -401,6 +415,50 @@ declare class EnginePinMismatchError extends PenvError {
401
415
  readonly name = "EnginePinMismatchError";
402
416
  constructor(pinned: string, ran: string);
403
417
  }
418
+ /** `penv upgrade` with something other than one optional version. */
419
+ declare class UpgradeSubjectError extends PenvError {
420
+ readonly name = "UpgradeSubjectError";
421
+ constructor();
422
+ }
423
+ /** A flag `penv upgrade` does not have. */
424
+ declare class UpgradeFlagError extends PenvError {
425
+ readonly name = "UpgradeFlagError";
426
+ constructor(flag: string);
427
+ }
428
+ /** `penv upgrade` needs the registry, and `--no-download` says this run has no network. */
429
+ declare class UpgradeNoDownloadError extends PenvError {
430
+ readonly name = "UpgradeNoDownloadError";
431
+ constructor();
432
+ }
433
+ /**
434
+ * `penv upgrade` on a machine with nobody at it.
435
+ *
436
+ * Unattended, penv will move the pin only to a version somebody named and only
437
+ * with the flag that says they meant it: what upgrade rewrites is two committed
438
+ * files, and a pipeline that picks the engine is a pipeline choosing which bytes
439
+ * the project runs.
440
+ */
441
+ declare class UpgradeUnattendedError extends PenvError {
442
+ readonly name = "UpgradeUnattendedError";
443
+ constructor();
444
+ }
445
+ /** The upgrade was shown and declined. Neither committed file was touched. */
446
+ declare class UpgradeDeclinedError extends PenvError {
447
+ readonly name = "UpgradeDeclinedError";
448
+ constructor(version: string);
449
+ }
450
+ /**
451
+ * The package manager refused, so the pin stayed where it was.
452
+ *
453
+ * The dependency moves before the manifest for exactly this reason: an upgrade
454
+ * that cannot finish leaves a project pinning the engine it was already running.
455
+ * The remedy is never the command that just failed — that is the one instruction
456
+ * known not to work. The manager printed why; that line is where to look.
457
+ */
458
+ declare class UpgradeInstallFailedError extends PenvError {
459
+ readonly name = "UpgradeInstallFailedError";
460
+ constructor(manager: string, version: string);
461
+ }
404
462
  /** An installed directory with nothing runnable in it. */
405
463
  declare class EngineEntryError extends PenvError {
406
464
  readonly name = "EngineEntryError";
@@ -548,6 +606,8 @@ interface ReleaseQuery {
548
606
  readonly version?: string;
549
607
  /** Only when the package comes from somewhere other than npmjs. */
550
608
  readonly registry?: string;
609
+ /** The command that would repeat this resolution. Absent means `penv add <name>`. */
610
+ readonly retry?: string;
551
611
  readonly fetcher: Fetcher;
552
612
  }
553
613
  /** The packument's address, which an exact name can be built rather than searched. */
@@ -621,4 +681,54 @@ interface ArchiveSubject {
621
681
  /** Every regular file in an npm tarball, `package/` stripped. */
622
682
  declare function readTarball(gzipped: Uint8Array, subject: ArchiveSubject): TarEntry[];
623
683
 
624
- export { AddFlagError, AddLocalFlagError, AddLocalInCiError, AddNoDownloadError, AddNotInteractiveError, type AddOptions, AddPackageNameError, AddRegistryError, type AddResult, AddSubjectError, ArchiveError, type ArchiveSubject, BUNDLED_ENGINE_PIN, DEFAULT_REGISTRY, DEV_PIN_INTEGRITY, DEV_PIN_VERSION, DeclarationMissingError, DeclarationNotSelfContainedError, type DeclarationSubject, type Delegation, DownloadFailedError, DownloadIntegrityError, ENGINE_BIN, type Engine, EngineEntryError, EnginePinMismatchError, EnginePinUnreleasedError, ExtensionNotImportableError, type ExtensionPackage, ExtensionUnloadableError, type Fetcher, HOME_META_FILE, INSTALL_COMMAND, INTEGRITY_FILE, InstallDeclinedError, type InstallOptions, type InstallState, type Installation, LOCAL_FLAG, type LauncherIo, type LauncherOptions, LocalExtensionUnresolvedError, MIN_PACKAGE_AGE_DAYS, NPM_UPDATE_COMMAND, NoProjectError, OfficialRegistryError, PackageCorruptError, PackageMissingError, PackageTooYoungError, PackageUnknownError, type Pin, type Project, type ProviderEntry, RegistryUnreadableError, type Release, ReleaseIncompleteError, type ReleaseQuery, type Spawner, TRUST_YOUNG_FLAG, type TarEntry, TrustDeclinedError, TrustPublisherMissingError, TrustReasonMissingError, VersionUnknownError, add, assertReleasePin, bundledEngine, declarationPath, engineAt, fetchRelease, findAdoptedRoot, findProject, httpFetcher, inspectInstall, installPin, integrityOf, launcherUpdateCommand, nodeSpawner, packumentUrl, readExtensionPackage, readProviderEntries, readTarball, releaseEnginePin, renderDeclaration, runLauncher, setProviderType, tarballUrl, writeDeclaration };
684
+ /**
685
+ * `penv upgrade [version]` — the one command that moves the engine pin.
686
+ *
687
+ * It belongs to the launcher for the same reason `add` does: everything it
688
+ * writes is the launcher's. An engine cannot compute the npm integrity of its
689
+ * own tarball, and the pin is a promise about bytes, so the integrity comes from
690
+ * the registry's `dist.integrity` and from nowhere else — never hashed here, and
691
+ * never typed by a person. Before this command existed, moving the pin meant
692
+ * hand-editing a version *and* an 88-character hash into the one file whose
693
+ * whole purpose is that its bytes are verified, and a mistyped character came
694
+ * back as a supply-chain check failing closed.
695
+ *
696
+ * The manifest's engine pin and the project's `@penvhq/penv` dependency move
697
+ * together, at the same exact version. In a workspace that dependency is plural
698
+ * — a package declaring its own `@penvhq/penv` is a second bridge running under
699
+ * the pin, and one repository ran the 0.8 one under a 0.11 manifest for three
700
+ * releases because `upgrade` looked only at the root. Every `package.json` that
701
+ * declares it is in the one diff, and they move together or not at all: the
702
+ * dependencies land first, so a package manager that refuses leaves a project
703
+ * still pinning the engine it was already running.
704
+ *
705
+ * Extensions are not touched. Each carries its own pin and its own trust
706
+ * decision, and re-pinning them because the engine moved would be penv choosing
707
+ * bytes nobody reviewed; `penv add <package>@<version>` moves one.
708
+ *
709
+ * A downgrade is an upgrade backwards and takes the same path — a pin is a pin,
710
+ * and a project that needs the engine it ran last week is not asking for
711
+ * something penv should argue with.
712
+ */
713
+
714
+ interface UpgradeOptions {
715
+ /** The tokens after `upgrade`. */
716
+ readonly argv: readonly string[];
717
+ /** The project root — the directory holding `.penv/`. */
718
+ readonly root: string;
719
+ readonly manifestFile: string;
720
+ /** The manifest as the launcher already parsed it. */
721
+ readonly manifest: Manifest;
722
+ readonly home: string;
723
+ readonly io: LauncherIo;
724
+ readonly fetcher: Fetcher;
725
+ /** The launcher's `--no-download`: this run reaches no registry at all. */
726
+ readonly noDownload?: boolean;
727
+ /** True on a CI runner, which may have a terminal and still have nobody at it. */
728
+ readonly ci?: boolean;
729
+ /** Injected in tests: how the project's dependency is installed. Never spawns there. */
730
+ readonly install?: InstallRuntime;
731
+ }
732
+ declare function upgrade(options: UpgradeOptions): Promise<void>;
733
+
734
+ export { AddFlagError, AddLocalFlagError, AddLocalInCiError, AddNoDownloadError, type AddOptions, AddPackageNameError, AddRegistryError, type AddResult, AddSubjectError, AddTrustUnattendedError, ArchiveError, type ArchiveSubject, BUNDLED_ENGINE_PIN, DEFAULT_REGISTRY, DEV_PIN_INTEGRITY, DEV_PIN_VERSION, DeclarationMissingError, DeclarationNotSelfContainedError, type DeclarationSubject, type Delegation, DownloadFailedError, DownloadIntegrityError, ENGINE_BIN, type Engine, EngineEntryError, EnginePinMismatchError, EnginePinUnreleasedError, ExtensionNotImportableError, type ExtensionPackage, ExtensionUnloadableError, type Fetcher, HOME_META_FILE, INSTALL_COMMAND, INTEGRITY_FILE, InstallDeclinedError, type InstallOptions, type InstallState, type Installation, LOCAL_FLAG, type LauncherIo, type LauncherOptions, LocalExtensionUnresolvedError, MIN_PACKAGE_AGE_DAYS, NPM_UPDATE_COMMAND, NoProjectError, OfficialRegistryError, PackageCorruptError, PackageMissingError, PackageTooYoungError, PackageUnknownError, type Pin, type Project, type ProviderEntry, RegistryUnreadableError, type Release, ReleaseIncompleteError, type ReleaseQuery, type Spawner, TRUST_YOUNG_FLAG, type TarEntry, TrustDeclinedError, TrustPublisherMissingError, TrustReasonMissingError, UPGRADE_COMMAND, UpgradeDeclinedError, UpgradeFlagError, UpgradeInstallFailedError, UpgradeNoDownloadError, type UpgradeOptions, UpgradeSubjectError, UpgradeUnattendedError, VersionUnknownError, YES_FLAG, add, assertReleasePin, bundledEngine, declarationPath, engineAt, fetchRelease, findAdoptedRoot, findProject, httpFetcher, inspectInstall, installPin, integrityOf, launcherUpdateCommand, nodeSpawner, packumentUrl, readExtensionPackage, readProviderEntries, readTarball, releaseEnginePin, renderDeclaration, runLauncher, setProviderType, tarballUrl, upgrade, writeDeclaration };
package/dist/index.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  AddLocalFlagError,
4
4
  AddLocalInCiError,
5
5
  AddNoDownloadError,
6
- AddNotInteractiveError,
7
6
  AddPackageNameError,
8
7
  AddRegistryError,
9
8
  AddSubjectError,
9
+ AddTrustUnattendedError,
10
10
  ArchiveError,
11
11
  BUNDLED_ENGINE_PIN,
12
12
  DEFAULT_REGISTRY,
@@ -42,7 +42,15 @@ import {
42
42
  TrustDeclinedError,
43
43
  TrustPublisherMissingError,
44
44
  TrustReasonMissingError,
45
+ UPGRADE_COMMAND,
46
+ UpgradeDeclinedError,
47
+ UpgradeFlagError,
48
+ UpgradeInstallFailedError,
49
+ UpgradeNoDownloadError,
50
+ UpgradeSubjectError,
51
+ UpgradeUnattendedError,
45
52
  VersionUnknownError,
53
+ YES_FLAG,
46
54
  add,
47
55
  assertReleasePin,
48
56
  bundledEngine,
@@ -66,17 +74,18 @@ import {
66
74
  runLauncher,
67
75
  setProviderType,
68
76
  tarballUrl,
77
+ upgrade,
69
78
  writeDeclaration
70
- } from "./chunk-BNUZ52VN.js";
79
+ } from "./chunk-A5LJQPYS.js";
71
80
  export {
72
81
  AddFlagError,
73
82
  AddLocalFlagError,
74
83
  AddLocalInCiError,
75
84
  AddNoDownloadError,
76
- AddNotInteractiveError,
77
85
  AddPackageNameError,
78
86
  AddRegistryError,
79
87
  AddSubjectError,
88
+ AddTrustUnattendedError,
80
89
  ArchiveError,
81
90
  BUNDLED_ENGINE_PIN,
82
91
  DEFAULT_REGISTRY,
@@ -112,7 +121,15 @@ export {
112
121
  TrustDeclinedError,
113
122
  TrustPublisherMissingError,
114
123
  TrustReasonMissingError,
124
+ UPGRADE_COMMAND,
125
+ UpgradeDeclinedError,
126
+ UpgradeFlagError,
127
+ UpgradeInstallFailedError,
128
+ UpgradeNoDownloadError,
129
+ UpgradeSubjectError,
130
+ UpgradeUnattendedError,
115
131
  VersionUnknownError,
132
+ YES_FLAG,
116
133
  add,
117
134
  assertReleasePin,
118
135
  bundledEngine,
@@ -136,6 +153,7 @@ export {
136
153
  runLauncher,
137
154
  setProviderType,
138
155
  tarballUrl,
156
+ upgrade,
139
157
  writeDeclaration
140
158
  };
141
159
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,8 +1,14 @@
1
1
  {
2
2
  "name": "@penvhq/launcher",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "The stable penv launcher: it verifies the engine your project pins and hands over the command.",
5
5
  "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Itzfeminisce/penvhq.git",
9
+ "directory": "packages/launcher"
10
+ },
11
+ "homepage": "https://github.com/Itzfeminisce/penvhq#readme",
6
12
  "type": "module",
7
13
  "main": "./dist/index.cjs",
8
14
  "module": "./dist/index.js",
@@ -22,8 +28,8 @@
22
28
  ],
23
29
  "dependencies": {
24
30
  "zod": "4.4.3",
25
- "@penvhq/cli": "0.10.0",
26
- "@penvhq/core": "0.10.0"
31
+ "@penvhq/cli": "0.12.0",
32
+ "@penvhq/core": "0.12.0"
27
33
  },
28
34
  "scripts": {
29
35
  "build": "tsup"