@codyswann/lisa 2.336.2 → 2.336.4

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.
Files changed (79) hide show
  1. package/dist/cli/index.d.ts.map +1 -1
  2. package/dist/cli/index.js +2 -0
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/cli/remote-env-cmd.d.ts +63 -0
  5. package/dist/cli/remote-env-cmd.d.ts.map +1 -0
  6. package/dist/cli/remote-env-cmd.js +94 -0
  7. package/dist/cli/remote-env-cmd.js.map +1 -0
  8. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  9. package/dist/core/upstream-evidence-manifest.js +5 -3
  10. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  11. package/package.json +1 -1
  12. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  14. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +6 -0
  15. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/SKILL.md +1 -1
  16. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +50 -3
  17. package/plugins/lisa/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +6 -0
  18. package/plugins/lisa/skills/lisa-setup-remote-env/SKILL.md +1 -1
  19. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +50 -3
  20. package/plugins/lisa-agy/plugin.json +1 -1
  21. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +6 -0
  22. package/plugins/lisa-agy/skills/lisa-setup-remote-env/SKILL.md +1 -1
  23. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +50 -3
  24. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  26. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  27. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +6 -0
  31. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/SKILL.md +1 -1
  32. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +50 -3
  33. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +6 -0
  35. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/SKILL.md +1 -1
  36. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +50 -3
  37. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-expo-agy/plugin.json +1 -1
  40. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  45. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  50. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  55. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  60. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  64. package/plugins/lisa-rails-agy/plugin.json +1 -1
  65. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  69. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  70. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  74. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  75. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  77. package/plugins/src/base/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +6 -0
  78. package/plugins/src/base/skills/lisa-setup-remote-env/SKILL.md +1 -1
  79. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +50 -3
package/package.json CHANGED
@@ -115,7 +115,7 @@
115
115
  "brace-expansion": ">=5.0.9"
116
116
  },
117
117
  "name": "@codyswann/lisa",
118
- "version": "2.336.2",
118
+ "version": "2.336.4",
119
119
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
120
120
  "main": "dist/index.js",
121
121
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.336.2",
3
+ "version": "2.336.4",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.336.2",
3
+ "version": "2.336.4",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -151,6 +151,12 @@ export function installProfileSourcing(valuesFile, options = {}) {
151
151
  // poison beats out-shouting it, and it is what lets `--profile agent-dev`
152
152
  // behave here exactly as it does on a developer's machine.
153
153
  `unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN`,
154
+ // The pinned toolchain installs into ~/.local/bin, which is not on PATH in
155
+ // every base image. Without this the tools are present and unfindable:
156
+ // `command -v bws` fails and anything spawning it gets ENOENT, which reads
157
+ // as "nothing was installed" when everything was.
158
+ `case ":$PATH:" in *":$HOME/.local/bin:"*) ;; ` +
159
+ `*) PATH="$HOME/.local/bin:$PATH"; export PATH;; esac`,
154
160
  `if [ -f "${valuesFile}" ]; then`,
155
161
  ` set -a`,
156
162
  ` . "${valuesFile}"`,
@@ -13,7 +13,7 @@ Prepare a remote surface so a host project can execute there. Today that means *
13
13
  The remote environment's own configuration fields stay **one line into the repository**. Nothing else is pasted into a vendor UI.
14
14
 
15
15
  ```text
16
- setup: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] && exit "$rc"; g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; do [ -e "$c" ] && g=1; done; if [ "$g" -eq 1 ]; then echo "lisa-remote-env entrypoint not found, but a checkout is present. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; npx -y @codyswann/lisa@latest workstation --provider "${LISA_SECRETS_PROVIDER:-bitwarden}" --yes || true; npx -y @codyswann/lisa@latest remote-env --phase=secrets || true; else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; exit 0
16
+ setup: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] && exit "$rc"; g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; do [ -e "$c" ] && g=1; done; if [ "$g" -eq 1 ]; then echo "lisa-remote-env entrypoint not found, but a checkout is present. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; tw=0; ts=0; npx -y @codyswann/lisa@2.336.3 workstation --install --provider="${LISA_SECRETS_PROVIDER:-bitwarden}" || tw=$?; export PATH="$HOME/.local/bin:$PATH"; npx -y @codyswann/lisa@2.336.3 remote-env --phase=secrets || ts=$?; [ "$tw" -eq 0 ] || echo "SETUP INCOMPLETE: tool install failed (exit $tw). The session will start WITHOUT the pinned tools." >&2; [ "$ts" -eq 0 ] || echo "SETUP INCOMPLETE: secrets did not materialize (exit $ts). The session will start WITHOUT credentials." >&2; else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; exit 0
17
17
  maintenance: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] || { echo "lisa-remote-env entrypoint not found. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; }; exit "$rc"
18
18
  ```
19
19
 
@@ -580,6 +580,17 @@ export function installAssets(cwd = process.cwd()) {
580
580
  * Given it, the machine itself is prepared — tools and credentials, no repo
581
581
  * required. Without it there is nothing to prepare and nothing to fail about.
582
582
  *
583
+ * Those two preparation steps report their failures and do not propagate them,
584
+ * which is deliberate and is NOT the same as hiding them. A setup script that
585
+ * exits non-zero stops the session from starting at all, so propagating turns
586
+ * "no credentials this session" into "no session" — strictly worse, and the
587
+ * exact regression that killed every repo-less channel session once already.
588
+ * What was wrong before was the silence: a bare `|| true` let a container come
589
+ * up with a bootstrap token and nothing able to use it, looking identical to
590
+ * success. Each phase's status is now captured and named on stderr, which the
591
+ * vendor surfaces, so the session still starts and the operator can see which
592
+ * half is missing.
593
+ *
583
594
  * Failure prints the layout it found rather than only the path it wanted. This
584
595
  * field lives in a vendor settings box with a slow edit-and-retry loop, and a
585
596
  * miss that reports nothing costs a whole round trip to learn one fact; the
@@ -589,6 +600,33 @@ export function installAssets(cwd = process.cwd()) {
589
600
  * had to get right, in a settings box with no review, no version history and no
590
601
  * test — and the logic it encoded belongs in a file that has all three.
591
602
  */
603
+ /**
604
+ * The exact Lisa the emitted field runs, pinned to the version that emitted it.
605
+ *
606
+ * `@latest` in a field that executes with `npx -y` is remote code execution
607
+ * against a moving target: whatever is newest when the session starts, run as
608
+ * root before Claude launches. That contradicts the rule this project applies
609
+ * to everything else — `assertPinned` refuses a tool whose version is not fixed
610
+ * and checksummed, and it would be strange to hold third-party binaries to a
611
+ * standard Lisa exempts itself from.
612
+ *
613
+ * Pinning to the emitting version keeps the field honest without freezing it:
614
+ * regenerating the field after an upgrade produces a new pin, which is the same
615
+ * "a version bump moves in one reviewed commit" contract as the toolchain.
616
+ * Falling back to `latest` only when the version cannot be read keeps a broken
617
+ * install from turning into an unrunnable field.
618
+ */
619
+ const SELF_SPEC = (() => {
620
+ try {
621
+ const pkg = JSON.parse(
622
+ readFileSync(resolve(HERE, "../../../../../../package.json"), "utf8")
623
+ );
624
+ return pkg.version ? `@codyswann/lisa@${pkg.version}` : "@codyswann/lisa";
625
+ } catch {
626
+ return "@codyswann/lisa";
627
+ }
628
+ })();
629
+
592
630
  export const SETUP_FIELD =
593
631
  'n=0; rc=0; seen=""; ' +
594
632
  "for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh " +
@@ -605,9 +643,18 @@ export const SETUP_FIELD =
605
643
  'PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; ' +
606
644
  'if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then ' +
607
645
  'echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; ' +
608
- "npx -y @codyswann/lisa@latest workstation " +
609
- '--provider "${LISA_SECRETS_PROVIDER:-bitwarden}" --yes || true; ' +
610
- "npx -y @codyswann/lisa@latest remote-env --phase=secrets || true; " +
646
+ "tw=0; ts=0; " +
647
+ `npx -y ${SELF_SPEC} workstation --install ` +
648
+ '--provider="${LISA_SECRETS_PROVIDER:-bitwarden}" || tw=$?; ' +
649
+ // Exported BEFORE the secrets phase, not after: the toolchain installs into
650
+ // ~/.local/bin, and materialization spawns the provider CLI by name. Ordered
651
+ // the other way it gets ENOENT on a binary that is sitting right there.
652
+ 'export PATH="$HOME/.local/bin:$PATH"; ' +
653
+ `npx -y ${SELF_SPEC} remote-env --phase=secrets || ts=$?; ` +
654
+ '[ "$tw" -eq 0 ] || echo "SETUP INCOMPLETE: tool install failed ' +
655
+ '(exit $tw). The session will start WITHOUT the pinned tools." >&2; ' +
656
+ '[ "$ts" -eq 0 ] || echo "SETUP INCOMPLETE: secrets did not materialize ' +
657
+ '(exit $ts). The session will start WITHOUT credentials." >&2; ' +
611
658
  'else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; ' +
612
659
  "exit 0";
613
660
 
@@ -151,6 +151,12 @@ export function installProfileSourcing(valuesFile, options = {}) {
151
151
  // poison beats out-shouting it, and it is what lets `--profile agent-dev`
152
152
  // behave here exactly as it does on a developer's machine.
153
153
  `unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN`,
154
+ // The pinned toolchain installs into ~/.local/bin, which is not on PATH in
155
+ // every base image. Without this the tools are present and unfindable:
156
+ // `command -v bws` fails and anything spawning it gets ENOENT, which reads
157
+ // as "nothing was installed" when everything was.
158
+ `case ":$PATH:" in *":$HOME/.local/bin:"*) ;; ` +
159
+ `*) PATH="$HOME/.local/bin:$PATH"; export PATH;; esac`,
154
160
  `if [ -f "${valuesFile}" ]; then`,
155
161
  ` set -a`,
156
162
  ` . "${valuesFile}"`,
@@ -13,7 +13,7 @@ Prepare a remote surface so a host project can execute there. Today that means *
13
13
  The remote environment's own configuration fields stay **one line into the repository**. Nothing else is pasted into a vendor UI.
14
14
 
15
15
  ```text
16
- setup: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] && exit "$rc"; g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; do [ -e "$c" ] && g=1; done; if [ "$g" -eq 1 ]; then echo "lisa-remote-env entrypoint not found, but a checkout is present. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; npx -y @codyswann/lisa@latest workstation --provider "${LISA_SECRETS_PROVIDER:-bitwarden}" --yes || true; npx -y @codyswann/lisa@latest remote-env --phase=secrets || true; else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; exit 0
16
+ setup: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] && exit "$rc"; g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; do [ -e "$c" ] && g=1; done; if [ "$g" -eq 1 ]; then echo "lisa-remote-env entrypoint not found, but a checkout is present. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; tw=0; ts=0; npx -y @codyswann/lisa@2.336.3 workstation --install --provider="${LISA_SECRETS_PROVIDER:-bitwarden}" || tw=$?; export PATH="$HOME/.local/bin:$PATH"; npx -y @codyswann/lisa@2.336.3 remote-env --phase=secrets || ts=$?; [ "$tw" -eq 0 ] || echo "SETUP INCOMPLETE: tool install failed (exit $tw). The session will start WITHOUT the pinned tools." >&2; [ "$ts" -eq 0 ] || echo "SETUP INCOMPLETE: secrets did not materialize (exit $ts). The session will start WITHOUT credentials." >&2; else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; exit 0
17
17
  maintenance: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] || { echo "lisa-remote-env entrypoint not found. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; }; exit "$rc"
18
18
  ```
19
19
 
@@ -580,6 +580,17 @@ export function installAssets(cwd = process.cwd()) {
580
580
  * Given it, the machine itself is prepared — tools and credentials, no repo
581
581
  * required. Without it there is nothing to prepare and nothing to fail about.
582
582
  *
583
+ * Those two preparation steps report their failures and do not propagate them,
584
+ * which is deliberate and is NOT the same as hiding them. A setup script that
585
+ * exits non-zero stops the session from starting at all, so propagating turns
586
+ * "no credentials this session" into "no session" — strictly worse, and the
587
+ * exact regression that killed every repo-less channel session once already.
588
+ * What was wrong before was the silence: a bare `|| true` let a container come
589
+ * up with a bootstrap token and nothing able to use it, looking identical to
590
+ * success. Each phase's status is now captured and named on stderr, which the
591
+ * vendor surfaces, so the session still starts and the operator can see which
592
+ * half is missing.
593
+ *
583
594
  * Failure prints the layout it found rather than only the path it wanted. This
584
595
  * field lives in a vendor settings box with a slow edit-and-retry loop, and a
585
596
  * miss that reports nothing costs a whole round trip to learn one fact; the
@@ -589,6 +600,33 @@ export function installAssets(cwd = process.cwd()) {
589
600
  * had to get right, in a settings box with no review, no version history and no
590
601
  * test — and the logic it encoded belongs in a file that has all three.
591
602
  */
603
+ /**
604
+ * The exact Lisa the emitted field runs, pinned to the version that emitted it.
605
+ *
606
+ * `@latest` in a field that executes with `npx -y` is remote code execution
607
+ * against a moving target: whatever is newest when the session starts, run as
608
+ * root before Claude launches. That contradicts the rule this project applies
609
+ * to everything else — `assertPinned` refuses a tool whose version is not fixed
610
+ * and checksummed, and it would be strange to hold third-party binaries to a
611
+ * standard Lisa exempts itself from.
612
+ *
613
+ * Pinning to the emitting version keeps the field honest without freezing it:
614
+ * regenerating the field after an upgrade produces a new pin, which is the same
615
+ * "a version bump moves in one reviewed commit" contract as the toolchain.
616
+ * Falling back to `latest` only when the version cannot be read keeps a broken
617
+ * install from turning into an unrunnable field.
618
+ */
619
+ const SELF_SPEC = (() => {
620
+ try {
621
+ const pkg = JSON.parse(
622
+ readFileSync(resolve(HERE, "../../../../../../package.json"), "utf8")
623
+ );
624
+ return pkg.version ? `@codyswann/lisa@${pkg.version}` : "@codyswann/lisa";
625
+ } catch {
626
+ return "@codyswann/lisa";
627
+ }
628
+ })();
629
+
592
630
  export const SETUP_FIELD =
593
631
  'n=0; rc=0; seen=""; ' +
594
632
  "for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh " +
@@ -605,9 +643,18 @@ export const SETUP_FIELD =
605
643
  'PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; ' +
606
644
  'if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then ' +
607
645
  'echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; ' +
608
- "npx -y @codyswann/lisa@latest workstation " +
609
- '--provider "${LISA_SECRETS_PROVIDER:-bitwarden}" --yes || true; ' +
610
- "npx -y @codyswann/lisa@latest remote-env --phase=secrets || true; " +
646
+ "tw=0; ts=0; " +
647
+ `npx -y ${SELF_SPEC} workstation --install ` +
648
+ '--provider="${LISA_SECRETS_PROVIDER:-bitwarden}" || tw=$?; ' +
649
+ // Exported BEFORE the secrets phase, not after: the toolchain installs into
650
+ // ~/.local/bin, and materialization spawns the provider CLI by name. Ordered
651
+ // the other way it gets ENOENT on a binary that is sitting right there.
652
+ 'export PATH="$HOME/.local/bin:$PATH"; ' +
653
+ `npx -y ${SELF_SPEC} remote-env --phase=secrets || ts=$?; ` +
654
+ '[ "$tw" -eq 0 ] || echo "SETUP INCOMPLETE: tool install failed ' +
655
+ '(exit $tw). The session will start WITHOUT the pinned tools." >&2; ' +
656
+ '[ "$ts" -eq 0 ] || echo "SETUP INCOMPLETE: secrets did not materialize ' +
657
+ '(exit $ts). The session will start WITHOUT credentials." >&2; ' +
611
658
  'else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; ' +
612
659
  "exit 0";
613
660
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.336.2",
3
+ "version": "2.336.4",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -151,6 +151,12 @@ export function installProfileSourcing(valuesFile, options = {}) {
151
151
  // poison beats out-shouting it, and it is what lets `--profile agent-dev`
152
152
  // behave here exactly as it does on a developer's machine.
153
153
  `unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN`,
154
+ // The pinned toolchain installs into ~/.local/bin, which is not on PATH in
155
+ // every base image. Without this the tools are present and unfindable:
156
+ // `command -v bws` fails and anything spawning it gets ENOENT, which reads
157
+ // as "nothing was installed" when everything was.
158
+ `case ":$PATH:" in *":$HOME/.local/bin:"*) ;; ` +
159
+ `*) PATH="$HOME/.local/bin:$PATH"; export PATH;; esac`,
154
160
  `if [ -f "${valuesFile}" ]; then`,
155
161
  ` set -a`,
156
162
  ` . "${valuesFile}"`,
@@ -13,7 +13,7 @@ Prepare a remote surface so a host project can execute there. Today that means *
13
13
  The remote environment's own configuration fields stay **one line into the repository**. Nothing else is pasted into a vendor UI.
14
14
 
15
15
  ```text
16
- setup: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] && exit "$rc"; g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; do [ -e "$c" ] && g=1; done; if [ "$g" -eq 1 ]; then echo "lisa-remote-env entrypoint not found, but a checkout is present. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; npx -y @codyswann/lisa@latest workstation --provider "${LISA_SECRETS_PROVIDER:-bitwarden}" --yes || true; npx -y @codyswann/lisa@latest remote-env --phase=secrets || true; else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; exit 0
16
+ setup: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] && exit "$rc"; g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; do [ -e "$c" ] && g=1; done; if [ "$g" -eq 1 ]; then echo "lisa-remote-env entrypoint not found, but a checkout is present. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; tw=0; ts=0; npx -y @codyswann/lisa@2.336.3 workstation --install --provider="${LISA_SECRETS_PROVIDER:-bitwarden}" || tw=$?; export PATH="$HOME/.local/bin:$PATH"; npx -y @codyswann/lisa@2.336.3 remote-env --phase=secrets || ts=$?; [ "$tw" -eq 0 ] || echo "SETUP INCOMPLETE: tool install failed (exit $tw). The session will start WITHOUT the pinned tools." >&2; [ "$ts" -eq 0 ] || echo "SETUP INCOMPLETE: secrets did not materialize (exit $ts). The session will start WITHOUT credentials." >&2; else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; exit 0
17
17
  maintenance: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] || { echo "lisa-remote-env entrypoint not found. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; }; exit "$rc"
18
18
  ```
19
19
 
@@ -580,6 +580,17 @@ export function installAssets(cwd = process.cwd()) {
580
580
  * Given it, the machine itself is prepared — tools and credentials, no repo
581
581
  * required. Without it there is nothing to prepare and nothing to fail about.
582
582
  *
583
+ * Those two preparation steps report their failures and do not propagate them,
584
+ * which is deliberate and is NOT the same as hiding them. A setup script that
585
+ * exits non-zero stops the session from starting at all, so propagating turns
586
+ * "no credentials this session" into "no session" — strictly worse, and the
587
+ * exact regression that killed every repo-less channel session once already.
588
+ * What was wrong before was the silence: a bare `|| true` let a container come
589
+ * up with a bootstrap token and nothing able to use it, looking identical to
590
+ * success. Each phase's status is now captured and named on stderr, which the
591
+ * vendor surfaces, so the session still starts and the operator can see which
592
+ * half is missing.
593
+ *
583
594
  * Failure prints the layout it found rather than only the path it wanted. This
584
595
  * field lives in a vendor settings box with a slow edit-and-retry loop, and a
585
596
  * miss that reports nothing costs a whole round trip to learn one fact; the
@@ -589,6 +600,33 @@ export function installAssets(cwd = process.cwd()) {
589
600
  * had to get right, in a settings box with no review, no version history and no
590
601
  * test — and the logic it encoded belongs in a file that has all three.
591
602
  */
603
+ /**
604
+ * The exact Lisa the emitted field runs, pinned to the version that emitted it.
605
+ *
606
+ * `@latest` in a field that executes with `npx -y` is remote code execution
607
+ * against a moving target: whatever is newest when the session starts, run as
608
+ * root before Claude launches. That contradicts the rule this project applies
609
+ * to everything else — `assertPinned` refuses a tool whose version is not fixed
610
+ * and checksummed, and it would be strange to hold third-party binaries to a
611
+ * standard Lisa exempts itself from.
612
+ *
613
+ * Pinning to the emitting version keeps the field honest without freezing it:
614
+ * regenerating the field after an upgrade produces a new pin, which is the same
615
+ * "a version bump moves in one reviewed commit" contract as the toolchain.
616
+ * Falling back to `latest` only when the version cannot be read keeps a broken
617
+ * install from turning into an unrunnable field.
618
+ */
619
+ const SELF_SPEC = (() => {
620
+ try {
621
+ const pkg = JSON.parse(
622
+ readFileSync(resolve(HERE, "../../../../../../package.json"), "utf8")
623
+ );
624
+ return pkg.version ? `@codyswann/lisa@${pkg.version}` : "@codyswann/lisa";
625
+ } catch {
626
+ return "@codyswann/lisa";
627
+ }
628
+ })();
629
+
592
630
  export const SETUP_FIELD =
593
631
  'n=0; rc=0; seen=""; ' +
594
632
  "for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh " +
@@ -605,9 +643,18 @@ export const SETUP_FIELD =
605
643
  'PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; ' +
606
644
  'if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then ' +
607
645
  'echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; ' +
608
- "npx -y @codyswann/lisa@latest workstation " +
609
- '--provider "${LISA_SECRETS_PROVIDER:-bitwarden}" --yes || true; ' +
610
- "npx -y @codyswann/lisa@latest remote-env --phase=secrets || true; " +
646
+ "tw=0; ts=0; " +
647
+ `npx -y ${SELF_SPEC} workstation --install ` +
648
+ '--provider="${LISA_SECRETS_PROVIDER:-bitwarden}" || tw=$?; ' +
649
+ // Exported BEFORE the secrets phase, not after: the toolchain installs into
650
+ // ~/.local/bin, and materialization spawns the provider CLI by name. Ordered
651
+ // the other way it gets ENOENT on a binary that is sitting right there.
652
+ 'export PATH="$HOME/.local/bin:$PATH"; ' +
653
+ `npx -y ${SELF_SPEC} remote-env --phase=secrets || ts=$?; ` +
654
+ '[ "$tw" -eq 0 ] || echo "SETUP INCOMPLETE: tool install failed ' +
655
+ '(exit $tw). The session will start WITHOUT the pinned tools." >&2; ' +
656
+ '[ "$ts" -eq 0 ] || echo "SETUP INCOMPLETE: secrets did not materialize ' +
657
+ '(exit $ts). The session will start WITHOUT credentials." >&2; ' +
611
658
  'else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; ' +
612
659
  "exit 0";
613
660
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.336.2",
3
+ "version": "2.336.4",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.336.2",
3
+ "version": "2.336.4",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.336.2",
3
+ "version": "2.336.4",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.336.2",
3
+ "version": "2.336.4",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.336.2",
3
+ "version": "2.336.4",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.336.2",
3
+ "version": "2.336.4",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -151,6 +151,12 @@ export function installProfileSourcing(valuesFile, options = {}) {
151
151
  // poison beats out-shouting it, and it is what lets `--profile agent-dev`
152
152
  // behave here exactly as it does on a developer's machine.
153
153
  `unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN`,
154
+ // The pinned toolchain installs into ~/.local/bin, which is not on PATH in
155
+ // every base image. Without this the tools are present and unfindable:
156
+ // `command -v bws` fails and anything spawning it gets ENOENT, which reads
157
+ // as "nothing was installed" when everything was.
158
+ `case ":$PATH:" in *":$HOME/.local/bin:"*) ;; ` +
159
+ `*) PATH="$HOME/.local/bin:$PATH"; export PATH;; esac`,
154
160
  `if [ -f "${valuesFile}" ]; then`,
155
161
  ` set -a`,
156
162
  ` . "${valuesFile}"`,
@@ -13,7 +13,7 @@ Prepare a remote surface so a host project can execute there. Today that means *
13
13
  The remote environment's own configuration fields stay **one line into the repository**. Nothing else is pasted into a vendor UI.
14
14
 
15
15
  ```text
16
- setup: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] && exit "$rc"; g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; do [ -e "$c" ] && g=1; done; if [ "$g" -eq 1 ]; then echo "lisa-remote-env entrypoint not found, but a checkout is present. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; npx -y @codyswann/lisa@latest workstation --provider "${LISA_SECRETS_PROVIDER:-bitwarden}" --yes || true; npx -y @codyswann/lisa@latest remote-env --phase=secrets || true; else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; exit 0
16
+ setup: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] && exit "$rc"; g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; do [ -e "$c" ] && g=1; done; if [ "$g" -eq 1 ]; then echo "lisa-remote-env entrypoint not found, but a checkout is present. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; tw=0; ts=0; npx -y @codyswann/lisa@2.336.3 workstation --install --provider="${LISA_SECRETS_PROVIDER:-bitwarden}" || tw=$?; export PATH="$HOME/.local/bin:$PATH"; npx -y @codyswann/lisa@2.336.3 remote-env --phase=secrets || ts=$?; [ "$tw" -eq 0 ] || echo "SETUP INCOMPLETE: tool install failed (exit $tw). The session will start WITHOUT the pinned tools." >&2; [ "$ts" -eq 0 ] || echo "SETUP INCOMPLETE: secrets did not materialize (exit $ts). The session will start WITHOUT credentials." >&2; else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; exit 0
17
17
  maintenance: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] || { echo "lisa-remote-env entrypoint not found. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; }; exit "$rc"
18
18
  ```
19
19
 
@@ -580,6 +580,17 @@ export function installAssets(cwd = process.cwd()) {
580
580
  * Given it, the machine itself is prepared — tools and credentials, no repo
581
581
  * required. Without it there is nothing to prepare and nothing to fail about.
582
582
  *
583
+ * Those two preparation steps report their failures and do not propagate them,
584
+ * which is deliberate and is NOT the same as hiding them. A setup script that
585
+ * exits non-zero stops the session from starting at all, so propagating turns
586
+ * "no credentials this session" into "no session" — strictly worse, and the
587
+ * exact regression that killed every repo-less channel session once already.
588
+ * What was wrong before was the silence: a bare `|| true` let a container come
589
+ * up with a bootstrap token and nothing able to use it, looking identical to
590
+ * success. Each phase's status is now captured and named on stderr, which the
591
+ * vendor surfaces, so the session still starts and the operator can see which
592
+ * half is missing.
593
+ *
583
594
  * Failure prints the layout it found rather than only the path it wanted. This
584
595
  * field lives in a vendor settings box with a slow edit-and-retry loop, and a
585
596
  * miss that reports nothing costs a whole round trip to learn one fact; the
@@ -589,6 +600,33 @@ export function installAssets(cwd = process.cwd()) {
589
600
  * had to get right, in a settings box with no review, no version history and no
590
601
  * test — and the logic it encoded belongs in a file that has all three.
591
602
  */
603
+ /**
604
+ * The exact Lisa the emitted field runs, pinned to the version that emitted it.
605
+ *
606
+ * `@latest` in a field that executes with `npx -y` is remote code execution
607
+ * against a moving target: whatever is newest when the session starts, run as
608
+ * root before Claude launches. That contradicts the rule this project applies
609
+ * to everything else — `assertPinned` refuses a tool whose version is not fixed
610
+ * and checksummed, and it would be strange to hold third-party binaries to a
611
+ * standard Lisa exempts itself from.
612
+ *
613
+ * Pinning to the emitting version keeps the field honest without freezing it:
614
+ * regenerating the field after an upgrade produces a new pin, which is the same
615
+ * "a version bump moves in one reviewed commit" contract as the toolchain.
616
+ * Falling back to `latest` only when the version cannot be read keeps a broken
617
+ * install from turning into an unrunnable field.
618
+ */
619
+ const SELF_SPEC = (() => {
620
+ try {
621
+ const pkg = JSON.parse(
622
+ readFileSync(resolve(HERE, "../../../../../../package.json"), "utf8")
623
+ );
624
+ return pkg.version ? `@codyswann/lisa@${pkg.version}` : "@codyswann/lisa";
625
+ } catch {
626
+ return "@codyswann/lisa";
627
+ }
628
+ })();
629
+
592
630
  export const SETUP_FIELD =
593
631
  'n=0; rc=0; seen=""; ' +
594
632
  "for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh " +
@@ -605,9 +643,18 @@ export const SETUP_FIELD =
605
643
  'PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; ' +
606
644
  'if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then ' +
607
645
  'echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; ' +
608
- "npx -y @codyswann/lisa@latest workstation " +
609
- '--provider "${LISA_SECRETS_PROVIDER:-bitwarden}" --yes || true; ' +
610
- "npx -y @codyswann/lisa@latest remote-env --phase=secrets || true; " +
646
+ "tw=0; ts=0; " +
647
+ `npx -y ${SELF_SPEC} workstation --install ` +
648
+ '--provider="${LISA_SECRETS_PROVIDER:-bitwarden}" || tw=$?; ' +
649
+ // Exported BEFORE the secrets phase, not after: the toolchain installs into
650
+ // ~/.local/bin, and materialization spawns the provider CLI by name. Ordered
651
+ // the other way it gets ENOENT on a binary that is sitting right there.
652
+ 'export PATH="$HOME/.local/bin:$PATH"; ' +
653
+ `npx -y ${SELF_SPEC} remote-env --phase=secrets || ts=$?; ` +
654
+ '[ "$tw" -eq 0 ] || echo "SETUP INCOMPLETE: tool install failed ' +
655
+ '(exit $tw). The session will start WITHOUT the pinned tools." >&2; ' +
656
+ '[ "$ts" -eq 0 ] || echo "SETUP INCOMPLETE: secrets did not materialize ' +
657
+ '(exit $ts). The session will start WITHOUT credentials." >&2; ' +
611
658
  'else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; ' +
612
659
  "exit 0";
613
660
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.336.2",
3
+ "version": "2.336.4",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -151,6 +151,12 @@ export function installProfileSourcing(valuesFile, options = {}) {
151
151
  // poison beats out-shouting it, and it is what lets `--profile agent-dev`
152
152
  // behave here exactly as it does on a developer's machine.
153
153
  `unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN`,
154
+ // The pinned toolchain installs into ~/.local/bin, which is not on PATH in
155
+ // every base image. Without this the tools are present and unfindable:
156
+ // `command -v bws` fails and anything spawning it gets ENOENT, which reads
157
+ // as "nothing was installed" when everything was.
158
+ `case ":$PATH:" in *":$HOME/.local/bin:"*) ;; ` +
159
+ `*) PATH="$HOME/.local/bin:$PATH"; export PATH;; esac`,
154
160
  `if [ -f "${valuesFile}" ]; then`,
155
161
  ` set -a`,
156
162
  ` . "${valuesFile}"`,
@@ -13,7 +13,7 @@ Prepare a remote surface so a host project can execute there. Today that means *
13
13
  The remote environment's own configuration fields stay **one line into the repository**. Nothing else is pasted into a vendor UI.
14
14
 
15
15
  ```text
16
- setup: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] && exit "$rc"; g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; do [ -e "$c" ] && g=1; done; if [ "$g" -eq 1 ]; then echo "lisa-remote-env entrypoint not found, but a checkout is present. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; npx -y @codyswann/lisa@latest workstation --provider "${LISA_SECRETS_PROVIDER:-bitwarden}" --yes || true; npx -y @codyswann/lisa@latest remote-env --phase=secrets || true; else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; exit 0
16
+ setup: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] && exit "$rc"; g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; do [ -e "$c" ] && g=1; done; if [ "$g" -eq 1 ]; then echo "lisa-remote-env entrypoint not found, but a checkout is present. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then echo "No checkout; preparing tools and credentials for $LISA_SECRETS_NAMESPACE."; tw=0; ts=0; npx -y @codyswann/lisa@2.336.3 workstation --install --provider="${LISA_SECRETS_PROVIDER:-bitwarden}" || tw=$?; export PATH="$HOME/.local/bin:$PATH"; npx -y @codyswann/lisa@2.336.3 remote-env --phase=secrets || ts=$?; [ "$tw" -eq 0 ] || echo "SETUP INCOMPLETE: tool install failed (exit $tw). The session will start WITHOUT the pinned tools." >&2; [ "$ts" -eq 0 ] || echo "SETUP INCOMPLETE: secrets did not materialize (exit $ts). The session will start WITHOUT credentials." >&2; else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; exit 0
17
17
  maintenance: n=0; rc=0; seen=""; for f in scripts/lisa-remote-env/setup.sh */scripts/lisa-remote-env/setup.sh "$HOME"/scripts/lisa-remote-env/setup.sh "$HOME"/*/scripts/lisa-remote-env/setup.sh /workspace/scripts/lisa-remote-env/setup.sh /workspace/*/scripts/lisa-remote-env/setup.sh; do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; n=$((n+1)); bash "$f" || rc=$?; done; [ "$n" -gt 0 ] || { echo "lisa-remote-env entrypoint not found. PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; }; exit "$rc"
18
18
  ```
19
19