@guidanti/duet 1.6.0 → 1.8.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/NOTICE.md CHANGED
@@ -18,7 +18,7 @@ duet runs external programs. It installs none of them, bundles none of them, red
18
18
  | Git | duet asks it where the project is, creates the implementation worktree with it and integrates through it | the Git project's |
19
19
  | Codex CLI (`codex`) | launched as a subprocess, per turn | OpenAI's |
20
20
  | Claude Code (`claude`) | launched as a subprocess, per turn | Anthropic's |
21
- | Node and npm | install and update duet, and nothing afterwards; no duet command invokes either | the Node.js project's and npm's |
21
+ | Node and npm | install and update duet, and nothing afterwards; the only duet command that invokes npm is `duet upgrade`, which is that install command run on request | the Node.js project's and npm's |
22
22
 
23
23
  Your use of those programs, and what your provider accounts permit, is between you and them. duet starts no sign-in, opens no credential file and makes no claim about which account a CLI would run as.
24
24
 
package/README.md CHANGED
@@ -2,23 +2,49 @@
2
2
 
3
3
  An automated Codex <-> Claude research, planning and implementation loop.
4
4
 
5
- npm installs and updates duet. It does not run it: the `duet` on your PATH is a shell script that execs the managed dispatcher, and every invocation after that is Python. Nothing duet runs invokes Node, npm or a source checkout.
5
+ npm installs and updates duet. It does not run it: the `duet` on your PATH is a shell script that execs the managed dispatcher, and every invocation after that is Python. Nothing duet does with a project, a run or a version reads Node, npm or a source checkout; the one command that invokes npm is `duet upgrade`, which runs the install below for you and then reports what it left.
6
6
 
7
7
  ## Prerequisite: a Python you already have
8
8
 
9
9
  duet needs CPython >=3.9 on macOS (arm64) and does not install one. Installation finds an interpreter already on the machine, checks its version, architecture and ability to create a virtual environment, and fails with instructions when nothing usable is there. The official installers are at https://www.python.org/downloads/macos/.
10
10
 
11
+ ## Prerequisite: an npm that can allow this package's install script
12
+
13
+ The install command below carries `--allow-scripts=@guidanti/duet`, and that allowance is not optional: the one install script it allows is the whole of duet's setup, and an install that runs none of it installs no runtime and selects nothing. `allow-scripts` is npm's own config and arrived in **npm 11.16.0**, documented for exactly the contexts that have no project to write a policy into -- `npm exec`, `npx` and `npm install -g` -- so for a global install it is npm's own route rather than a preference. In npm 11.x the policy is advisory and install scripts still run; npm 12.0.0 blocks unreviewed dependency install scripts, which is what makes the allowance load-bearing rather than defensive. Any npm that installs a global package installs this one; npm 11.16.0 or newer is what the allowance itself needs. `duet upgrade` reads one bounded `npm --version` before it installs anything: an npm established to be older refuses with the version it read, the boundary and npm's own sources, and duet neither drops the allowance nor writes npm's configuration to work around it. An npm whose version it could not read is reported as *unverified* rather than unsupported, and the install runs with the allowance in it.
14
+
11
15
  ## Install, update, retry
12
16
 
13
17
  ```sh
14
- npm install --global @guidanti/duet
18
+ npm install --global @guidanti/duet --allow-scripts=@guidanti/duet
19
+ ```
20
+
21
+ Once duet is installed, `duet upgrade` runs exactly that command for you -- npm's own global install with this package's install-script allowance -- shows npm's output and its failures unchanged, and then reads the installation root to say which release is installed, whether it is still the build it says it is, and whether it is the default. It reports an activation only where `default.json` says so and that release is intact: a zero npm status is not one. It takes no version or tag, so installing a named release stays the npm command above with `@<version>` in it.
22
+
23
+ **What it can and cannot tell you about setup.** It reads this record before the install and again afterwards, and reports the comparison as what it is. The read afterwards is one read, and both questions about the record -- which artifact it names and whether its bytes are the ones from before -- are answered from those same bytes, so they are answered about one record rather than about two a setup of another release could have published between. A record that names the installed release's artifact and whose bytes changed while the command ran is evidence that a setup completed during it -- not proof of which process ran that setup, since nothing duet can read records that, and a concurrent setup or `duet select` is an ordinary thing. A record that is unchanged, that names another artifact, or that is absent is the absence of that evidence and not proof that no setup ran: npm runs no install script for a package it decides is already up to date, each record names the single artifact its own setup installed, and the record is written last. A read that could not open the record is not a reading of it either: the read before the install keeps its own state, so a record that was there and would not open is held as unreadable rather than as the absent record it is not, and where either read failed to open the file the comparison is reported as not established -- neither a setup during the command nor an unchanged record -- because a historical record of this release that was unreadable before the install and readable afterwards would otherwise read as one written during it. This record and `default.json` are two files, read one after the other and not under one lock, so the pair is reported as two observations rather than as a history: a record that changed under a default naming another release is not reported as a selection that replaced this release after it was activated, because that is an order of writes duet did not observe. A failing or interrupted install is read the same way -- npm's non-zero status is not evidence that nothing was installed or activated, because the install script is where setup happens and it can have got anywhere before the failure. An interruption signals the process group npm led, by the group id duet read while npm was running and for as long as anything is still in that group -- so npm's own exit, which is usually an interrupt's first effect, neither ends the cleanup nor takes the group's name away with it -- and then says which signals were delivered, how npm ended, whether anything outlived a signal and whether anything is left in that group, never reporting a cleanup it did not establish. `duet --version` and `duet select --json` are the read-only answers afterwards.
24
+
25
+ **An interrupted or unfinished install is finished by either route below, and the second is the reason there are two:** another install, or `duet upgrade`, may run no install script at all once npm has unpacked a package it decides is already up to date, and so may finish nothing. This package's own setup script always runs setup, for the release this package carries:
26
+
27
+ ```sh
28
+ /bin/sh "$(npm root -g)/@guidanti/duet/lib/setup.sh"
15
29
  ```
16
30
 
17
- Setup runs in this package's install script: it verifies the bundled artifact, installs it as an immutable managed runtime under `~/.duet/installations/`, self-checks that runtime, writes the dispatcher and selects the new build when the default is this distribution's own or there is none. Running the same command again is the retry and the upgrade; it installs beside what is there and removes nothing.
31
+ Setup runs in this package's install script: it verifies the bundled artifact, installs it as an immutable managed runtime under `~/.duet/installations/<version>/`, self-checks that runtime, writes the dispatcher, and then makes that release the default for new runs -- on a first install, on an upgrade, on an explicit downgrade to an older version, and whatever was selected before. A run that already exists keeps the build it was started on, and `duet select <version>` changes the default again at any time -- as does `duet select` with no version on a terminal, which lists the installed releases, marks the default and selects the one you move to with the arrow keys and confirm with Enter. Escape, Ctrl-C and an end of input leave the default exactly as it was. A new version installs beside what is there and removes nothing.
32
+
33
+ Running the same command again is the retry and the upgrade -- but a reinstall is npm's decision, not duet's: npm runs no install script for a package it decides is already up to date, and nothing then installs or selects anything. The two routes that always do are `duet select <version>`, which moves the default by hand, and `/bin/sh <package>/lib/setup.sh`, which runs this package's own setup for the release it carries. Installing another version or tag (`@guidanti/duet@<version>`) is a change npm does perform, and it activates that release.
34
+
35
+ **npm does not show what the install script printed.** `foreground-scripts` defaults to false for an install, and setting it runs install scripts in npm's own process with its standard output and error -- so what setup prints, the release it activated as much as a reason it failed, is visible only under `--foreground-scripts`. Afterwards, `duet --version` and `duet select --json` say which release is installed and which one is the default, and neither installs or selects anything.
18
36
 
19
37
  Setup also creates six starter instruction files under `~/.duet/instructions/`, one for each research, plan and execute manager/implementer role. Existing files are never overwritten, including on upgrades. Edit these files to customize your guidance across projects; keep a file empty to opt out of its starter text. Setup does not create or change `~/.duet/config.json`.
20
38
 
21
- `DUET_SETUP_PYTHON=/path/to/python3` names the interpreter yourself. `--foreground-scripts` shows the setup output. If npm is configured with `ignore-scripts`, no setup runs and the launcher says so.
39
+ `DUET_SETUP_PYTHON=/path/to/python3` names the interpreter yourself. `--foreground-scripts` shows the setup output. If npm is configured with `ignore-scripts`, or holds this package's install script back until it is allowed, no setup runs -- nothing is installed and nothing is selected -- and the launcher says so with the retry above.
40
+
41
+ ## What your runtimes are called
42
+
43
+ A managed runtime is named by the version it publishes: `~/.duet/installations/1.8.0/`. That name is what `duet select`, `duet remove` and every report use, and `duet --version` prints the version alone. The build identity -- a digest of the exact bytes installed -- is kept where it is load-bearing instead of in the name: the runtime's own manifest, every run's pin, and the reports whose job is to say which build this is (`duet self-check`, `duet status --installations`, and `duet select` listing what is there, interactively on a terminal and read-only under `--json`).
44
+
45
+ Runtimes installed before this release are named `<version>+<build id>`, and they keep that name: they stay listed, stay selectable and stay runnable, nothing is renamed, and no run is repinned. Select one by its full name. A bare version that *is* the name of a runtime selects that runtime; a bare version that is not a name, and that two older runtimes share, is ambiguous and refuses with both names printed for you to choose from. `duet remove` takes an exact name only.
46
+
47
+ One version-only name holds one build, so installing a **different** build of a version you already have is refused rather than resolved for you: both identities and the runtime that is there are named. Nothing is overwritten and no other build is substituted, because a managed runtime is immutable and a run pinned to the build under that name has to go on reaching exactly it. Remove the one you have with `duet remove <name> --yes`, or install into a root of its own with `DUET_INSTALL_ROOT=/path/to/root`. Ordinary upgrades are unaffected: a new release has a new version and therefore a new name.
22
48
 
23
49
  ## Uninstalling is not removing your runtimes
24
50
 
@@ -30,9 +56,9 @@ That removes this package and the `duet` npm linked onto your PATH. It removes n
30
56
 
31
57
  ## This build
32
58
 
33
- - version `1.6.0`, build `3223e2d99afa5a8f`
34
- - artifact `duet-1.6.0-py3-none-any.whl`
35
- - `sha256=12dc1234c7223113b3448976d9b6c3efd962a033fa8692262ab39cd48535f458`
59
+ - version `1.8.0`, build `646869928c864ea4`
60
+ - artifact `duet-1.8.0-py3-none-any.whl`
61
+ - `sha256=41b3258715af0b49865c4b4151eac320019abf3dae66815e9626ab571c9bfe96`
36
62
 
37
63
  ## Permission to use duet
38
64
 
@@ -0,0 +1,15 @@
1
+ {
2
+ "build_id": "646869928c864ea4",
3
+ "name": "duet",
4
+ "schema": 1,
5
+ "source": {
6
+ "clean": true,
7
+ "commit": "5d13ae499990e613e949e7501c13d3aad8808426"
8
+ },
9
+ "verification": {
10
+ "contract": 2
11
+ },
12
+ "version": "1.8.0",
13
+ "wheel": "duet-1.8.0-py3-none-any.whl",
14
+ "wheel_sha256": "41b3258715af0b49865c4b4151eac320019abf3dae66815e9626ab571c9bfe96"
15
+ }
package/bin/duet CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/bin/sh
2
- # Generated by duet.npm for @guidanti/duet 1.6.0.
2
+ # Generated by duet.npm for @guidanti/duet 1.8.0.
3
3
  #
4
4
  # This is the whole of what npm puts on your PATH. It invokes no
5
5
  # Node, no npm and no source checkout: it finds the managed
@@ -22,43 +22,71 @@ root=${DUET_INSTALL_ROOT:-$HOME/.duet/installations}
22
22
  dispatcher=$root/.dispatch/duet
23
23
  if [ ! -x "$dispatcher" ]; then
24
24
  cat >&2 <<SETUP
25
- duet: this installation of @guidanti/duet has no managed runtime yet.
26
- There is no dispatcher at $dispatcher.
27
- Setup runs in this package's install script, so if npm was run
28
- with --ignore-scripts, or that script failed, nothing was
29
- installed and nothing was selected.
30
- Install or retry: npm install --global @guidanti/duet
31
- See why it failed: npm install --global @guidanti/duet --foreground-scripts
32
- Run setup by hand: /bin/sh $here/lib/setup.sh
33
- duet installs no software by itself: nothing has been downloaded,
34
- installed or selected here.
25
+ duet: there is no executable duet dispatcher at $dispatcher.
26
+ That is the program this command runs, and it runs nothing else:
27
+ this launcher execs the dispatcher and performs no setup of its
28
+ own. All this message knows is that the file is not there, or is
29
+ not executable.
30
+ Setup writes it, and setup runs in this package's install script.
31
+ npm run with --ignore-scripts runs no install script; an npm that
32
+ holds this package's script back until it is allowed runs none
33
+ either; and a script that ran and failed can stop before this
34
+ file is written. This message cannot tell you which of those
35
+ happened, and it says nothing about what is installed under
36
+ $root or which release is selected there.
37
+ Install or retry: npm install --global @guidanti/duet@1.8.0 --allow-scripts=@guidanti/duet
38
+ See why it failed: npm install --global @guidanti/duet@1.8.0 --allow-scripts=@guidanti/duet --foreground-scripts
39
+ If scripts are off: npm config get ignore-scripts
40
+ Run setup by hand: /bin/sh "$here/lib/setup.sh"
41
+ A successful setup installs this package's release and makes it
42
+ the default for new runs. duet installs no software by itself:
43
+ this message has downloaded, installed and selected nothing.
35
44
  SETUP
36
45
  exit 1
37
46
  fi
38
- # Whether a finished setup under this root installed the artifact
39
- # *this* package carries. One digest, matched in the record setup
40
- # writes last, with shell builtins and no interpreter: the launcher
41
- # is on the path of every duet invocation.
47
+ # Whether the setup record under this root names the artifact *this*
48
+ # package carries. One digest, matched in the record setup writes
49
+ # last, with shell builtins and no interpreter: the launcher is on
50
+ # the path of every duet invocation. A record names one artifact --
51
+ # the one its own setup installed -- so a failure here is a record
52
+ # that is absent, or one some other setup wrote, and the message
53
+ # below claims nothing beyond that.
42
54
  set_up_here() {
43
55
  [ -f "$1" ] || return 1
44
56
  while IFS= read -r line; do
45
57
  case "$line" in
46
- *'"wheel_sha256": "12dc1234c7223113b3448976d9b6c3efd962a033fa8692262ab39cd48535f458"'*) return 0 ;;
58
+ *'"wheel_sha256": "41b3258715af0b49865c4b4151eac320019abf3dae66815e9626ab571c9bfe96"'*) return 0 ;;
47
59
  esac
48
60
  done < "$1"
49
61
  return 1
50
62
  }
51
63
  if ! set_up_here "$root/npm.json"; then
52
64
  cat >&2 <<INCOMPLETE
53
- duet: @guidanti/duet 1.6.0 is installed and its setup did not finish.
54
- The runtime this package carries is not under $root, so this
55
- command runs the managed runtime that is already there. Every run
56
- still reaches the build it was started on, and nothing has been
57
- downloaded, installed or selected -- including by this message.
58
- Retry the setup: npm install --global @guidanti/duet
59
- See why it failed: npm install --global @guidanti/duet --foreground-scripts
65
+ duet: @guidanti/duet 1.8.0 is installed and no setup record under
66
+ $root names the artifact it carries.
67
+ That record names the one artifact its own setup installed, so
68
+ this reads the same whether none has been written here, a setup
69
+ stopped before writing one, or another setup wrote one for a
70
+ different release over it. It is not a statement that this
71
+ package's install script never ran or never finished, that its
72
+ runtime is not installed, or that nothing was activated.
73
+ Nor does it say which runtimes are installed, which one is
74
+ selected, or which one this command is about to run -- the
75
+ dispatcher decides that from the pin of the run you named and the
76
+ selected default, and every run still reaches the build it was
77
+ started on.
78
+ Retry the setup: npm install --global @guidanti/duet@1.8.0 --allow-scripts=@guidanti/duet
79
+ See why it failed: npm install --global @guidanti/duet@1.8.0 --allow-scripts=@guidanti/duet --foreground-scripts
60
80
  If scripts are off: npm config get ignore-scripts
61
- Run setup by hand: /bin/sh $here/lib/setup.sh
81
+ Run setup by hand: /bin/sh "$here/lib/setup.sh"
82
+ npm runs no install script for a package it decides is already up
83
+ to date, so an install of this same version may do nothing at all.
84
+ The line above always runs setup for the release this package
85
+ carries: it installs nothing twice, removes nothing, and ends with
86
+ that release as the default for new runs.
87
+ This message has downloaded, installed and selected nothing.
88
+ \`duet select --json\` prints which runtime is the default; it
89
+ changes nothing either.
62
90
  INCOMPLETE
63
91
  fi
64
92
  exec "$dispatcher" "$@"
package/duet-npm.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "artifact": {
3
- "build_id": "3223e2d99afa5a8f",
4
- "sidecar": "duet-1.6.0.artifact.json",
3
+ "build_id": "646869928c864ea4",
4
+ "sidecar": "duet-1.8.0.artifact.json",
5
5
  "verification": {
6
- "contract": 1
6
+ "contract": 2
7
7
  },
8
- "wheel": "duet-1.6.0-py3-none-any.whl",
9
- "wheel_sha256": "12dc1234c7223113b3448976d9b6c3efd962a033fa8692262ab39cd48535f458"
8
+ "wheel": "duet-1.8.0-py3-none-any.whl",
9
+ "wheel_sha256": "41b3258715af0b49865c4b4151eac320019abf3dae66815e9626ab571c9bfe96"
10
10
  },
11
11
  "contents": {
12
12
  "LICENSE.md": "cbc7853b308655c45a049a2c8c53c0a5e556cee29229d80209cbe82a896b1d0e",
13
- "NOTICE.md": "95e6b3212b7a907e59befdca37999fd683cf02c94cc2d487df62b77c7c3ef2ba",
14
- "README.md": "de73c22b8dbf9eec85608a839255a2949b0683868ac1060711163384c95eae1a",
15
- "artifact/duet-1.6.0-py3-none-any.whl": "12dc1234c7223113b3448976d9b6c3efd962a033fa8692262ab39cd48535f458",
16
- "artifact/duet-1.6.0.artifact.json": "8e5aa680c0b82fa568e6e682618260ebc8e47fd5ab4184378860c47ac3eefaa4",
17
- "bin/duet": "be950b7cddd09ce4d657d89660c69f7bf4f68a57ad9c064966feb3dadbd0f3ab",
18
- "lib/setup.py": "712a06709cff24615bb3fa6de7b296d38e53ec9caceeb569b9fa7adb1ee15a07",
19
- "lib/setup.sh": "86df8dc71fb6ef276c7c986ee307b5208a4455a0905f8e0782cbccbe2e84242a",
20
- "package.json": "4c3e8068b7adb44276f7cd6ab4f02e28e194a3410d1712205fd817766efbcc0a"
13
+ "NOTICE.md": "8cf095fd1e5abc0c29634b010890189a9a8a340f96358db93635650dbdf5ed89",
14
+ "README.md": "d6dfb6578fcc618c5e0f16287cffcf59c395b7092b3065ea755be912da641a40",
15
+ "artifact/duet-1.8.0-py3-none-any.whl": "41b3258715af0b49865c4b4151eac320019abf3dae66815e9626ab571c9bfe96",
16
+ "artifact/duet-1.8.0.artifact.json": "a9ab64af12e028b13f910bc6d3be7a15d78faa1390252a89b4145b9482d9642c",
17
+ "bin/duet": "95a9762078fd565fa00d42a0cb5d2b4ca07e2fcd591facdb6e7b575517e79d8a",
18
+ "lib/setup.py": "d5a541812753e0d4fd395a8d3cbe6a7ecebeefb2b0b8cac92745a60070935e49",
19
+ "lib/setup.sh": "36d67424731e66c34333f0873dd3851563a2dc2c2890696f55ee9a4f4781f7de",
20
+ "package.json": "d80756c675be0a36ac2ad4759c86261eb404b70c1d461e7631a93657791554d9"
21
21
  },
22
22
  "notices": [
23
23
  "LICENSE.md",
@@ -27,7 +27,7 @@
27
27
  "schema": 1,
28
28
  "source": {
29
29
  "clean": true,
30
- "commit": "3763f555bc641d2669ddb9301aee1b456f27cd9a"
30
+ "commit": "5d13ae499990e613e949e7501c13d3aad8808426"
31
31
  },
32
- "version": "1.6.0"
32
+ "version": "1.8.0"
33
33
  }
package/lib/setup.py CHANGED
@@ -1,4 +1,4 @@
1
- """Generated by duet.npm for @guidanti/duet 1.6.0.
1
+ """Generated by duet.npm for @guidanti/duet 1.8.0.
2
2
 
3
3
  The install script's Python half: check the bundled artifact against
4
4
  the digest this file was generated with, import the installer out of
@@ -10,11 +10,12 @@ import os
10
10
  import sys
11
11
 
12
12
  PACKAGE = '@guidanti/duet'
13
- PACKAGE_VERSION = '1.6.0'
13
+ PACKAGE_VERSION = '1.8.0'
14
14
  HERE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
15
- WHEEL = os.path.join(HERE, 'artifact', 'duet-1.6.0-py3-none-any.whl')
16
- SIDECAR = os.path.join(HERE, 'artifact', 'duet-1.6.0.artifact.json')
17
- WHEEL_SHA256 = '12dc1234c7223113b3448976d9b6c3efd962a033fa8692262ab39cd48535f458'
15
+ WHEEL = os.path.join(HERE, 'artifact', 'duet-1.8.0-py3-none-any.whl')
16
+ SIDECAR = os.path.join(HERE, 'artifact', 'duet-1.8.0.artifact.json')
17
+ WHEEL_SHA256 = '41b3258715af0b49865c4b4151eac320019abf3dae66815e9626ab571c9bfe96'
18
+ REINSTALL = ('The files in this installed package are not the ones it was published with, and npm runs nothing for a package it decides is already up to date. Remove it and install it again:', ' npm uninstall --global @guidanti/duet', ' npm install --global @guidanti/duet@1.8.0 --allow-scripts=@guidanti/duet', "That install names this package's own version, so a release you installed deliberately is the release you get back.", 'That uninstall takes this package and the duet npm linked onto your PATH. It takes nothing under ~/.duet: every managed runtime, every run and every piece of evidence stays where it is.')
18
19
 
19
20
 
20
21
  def refuse(message, *lines):
@@ -33,7 +34,7 @@ def main():
33
34
  'the artifact this package carries could not be read ('
34
35
  + str(exc) + ')',
35
36
  'Nothing was installed and nothing was selected.',
36
- 'Install the package again: npm install --global @guidanti/duet')
37
+ *REINSTALL)
37
38
  found = hashlib.sha256(data).hexdigest()
38
39
  if found != WHEEL_SHA256:
39
40
  return refuse(
@@ -45,7 +46,7 @@ def main():
45
46
  'duet will not install bytes that are not the bytes this'
46
47
  ' package records.',
47
48
  'Nothing was installed and nothing was selected.',
48
- 'Install the package again: npm install --global @guidanti/duet')
49
+ *REINSTALL)
49
50
  # Those bytes, and nothing else, are what the installer is read
50
51
  # out of. A wheel is a zip and an interpreter imports from one
51
52
  # directly, so there is no temporary environment to clean up.
@@ -58,7 +59,7 @@ def main():
58
59
  ' a duet (' + type(exc).__name__ + ': ' + str(exc)
59
60
  + ')',
60
61
  'Nothing was installed and nothing was selected.',
61
- 'Install the package again: npm install --global @guidanti/duet')
62
+ *REINSTALL)
62
63
  return npm.setup_main(wheel=WHEEL, sidecar=SIDECAR, here=HERE,
63
64
  package=PACKAGE,
64
65
  package_version=PACKAGE_VERSION,
package/lib/setup.sh CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/bin/sh
2
- # Generated by duet.npm for @guidanti/duet 1.6.0.
2
+ # Generated by duet.npm for @guidanti/duet 1.8.0.
3
3
  #
4
4
  # npm runs this once, after it has unpacked the package. It finds an
5
5
  # interpreter that can run the installer and hands over to it; the
@@ -66,7 +66,9 @@ duet: DUET_SETUP_PYTHON names $DUET_SETUP_PYTHON, which duet will not run as an
66
66
  Install Python from https://www.python.org/downloads/macos/
67
67
  An explicit interpreter is an instruction, so duet does not look elsewhere when it is unusable.
68
68
  Nothing was installed and nothing was selected. Unset it or name another, then run:
69
- npm install --global @guidanti/duet
69
+ npm install --global @guidanti/duet@1.8.0 --allow-scripts=@guidanti/duet
70
+ npm runs no install script for a package it decides is already up to date, so that install can do nothing at all. While this package is installed, its own setup script always runs setup, for the release it carries:
71
+ /bin/sh "$here/lib/setup.sh"
70
72
  OVERRIDE
71
73
  exit 1
72
74
  fi
@@ -107,8 +109,10 @@ if [ -z "$found" ]; then
107
109
  duet: no usable Python was found, and duet does not install one.
108
110
  duet needs CPython >=3.9 on macOS (arm64), able to create a virtual environment.
109
111
  Install Python from https://www.python.org/downloads/macos/
110
- Then run: npm install --global @guidanti/duet
111
- Or name one yourself: DUET_SETUP_PYTHON=/path/to/python3 npm install --global @guidanti/duet
112
+ Then run: npm install --global @guidanti/duet@1.8.0 --allow-scripts=@guidanti/duet
113
+ Or name one yourself: DUET_SETUP_PYTHON=/path/to/python3 npm install --global @guidanti/duet@1.8.0 --allow-scripts=@guidanti/duet
114
+ npm runs no install script for a package it decides is already up to date, so that install can do nothing at all. While this package is installed, its own setup script always runs setup, for the release it carries:
115
+ /bin/sh "$(npm root -g)/@guidanti/duet/lib/setup.sh"
112
116
  Nothing was installed, nothing was selected, and no existing duet installation was changed.
113
117
  NOPYTHON
114
118
  exit 1
package/package.json CHANGED
@@ -23,5 +23,5 @@
23
23
  "scripts": {
24
24
  "postinstall": "/bin/sh lib/setup.sh"
25
25
  },
26
- "version": "1.6.0"
26
+ "version": "1.8.0"
27
27
  }
@@ -1,15 +0,0 @@
1
- {
2
- "build_id": "3223e2d99afa5a8f",
3
- "name": "duet",
4
- "schema": 1,
5
- "source": {
6
- "clean": true,
7
- "commit": "3763f555bc641d2669ddb9301aee1b456f27cd9a"
8
- },
9
- "verification": {
10
- "contract": 1
11
- },
12
- "version": "1.6.0",
13
- "wheel": "duet-1.6.0-py3-none-any.whl",
14
- "wheel_sha256": "12dc1234c7223113b3448976d9b6c3efd962a033fa8692262ab39cd48535f458"
15
- }