@codyswann/lisa 2.334.1 → 2.336.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/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +32 -9
- package/dist/core/upstream-evidence-manifest.js +5 -5
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/surfaces.mjs +42 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +33 -6
- package/plugins/lisa/skills/lisa-secrets-access/scripts/surfaces.mjs +42 -2
- package/plugins/lisa/skills/lisa-setup-remote-env/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +33 -6
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/surfaces.mjs +42 -2
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +33 -6
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/surfaces.mjs +42 -2
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +33 -6
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/surfaces.mjs +42 -2
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +33 -6
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/skills/lisa-secrets-access/scripts/surfaces.mjs +42 -2
- package/plugins/src/base/skills/lisa-setup-remote-env/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +33 -6
- package/scripts/lisa-enforcement-fallback.sh +32 -9
|
@@ -24,16 +24,39 @@ payload="$(cat)"
|
|
|
24
24
|
repo_root="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null)}"
|
|
25
25
|
[ -n "$repo_root" ] || exit 0
|
|
26
26
|
|
|
27
|
-
#
|
|
28
|
-
# guard twice and print every refusal twice. Absence is the interesting case and
|
|
29
|
-
# the only one this exists for.
|
|
27
|
+
# There is deliberately no skip here, and that is the whole point.
|
|
30
28
|
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
# This used to stand down when `installed_plugins.json` mentioned `lisa@lisa`,
|
|
30
|
+
# to avoid running every guard twice on a developer machine. The question that
|
|
31
|
+
# has to be answered is "are the plugin's guards running in this session?" and
|
|
32
|
+
# the file being consulted answers "has this plugin ever been installed, for any
|
|
33
|
+
# project, on this machine?". Those come apart three ways, and in each one both
|
|
34
|
+
# layers were off:
|
|
35
|
+
#
|
|
36
|
+
# - Project-blind. The registry is keyed by plugin with an array of per-project
|
|
37
|
+
# entries, so the grep matched the key. One project installing Lisa disabled
|
|
38
|
+
# the fallback for every other project on the machine.
|
|
39
|
+
# - Enablement-blind. `enabledPlugins` can set a plugin to false without
|
|
40
|
+
# removing its registry entry, so the plugin guards were off while this file
|
|
41
|
+
# believed they were on.
|
|
42
|
+
# - Session-blind. Hooks load at session start; the registry is written on any
|
|
43
|
+
# install or update. A plugin updated four minutes into a session leaves the
|
|
44
|
+
# registry saying "installed" for the rest of it, with no plugin hooks
|
|
45
|
+
# loaded. That is the one that was caught in the wild: a write to AGENTS.md
|
|
46
|
+
# went through in a session where both guard copies exit 2 for that exact
|
|
47
|
+
# payload.
|
|
48
|
+
#
|
|
49
|
+
# The first two are fixable with a better lookup. The third is not: plugin-hook
|
|
50
|
+
# liveness is not observable from a repository hook. CLAUDE_PLUGIN_ROOT is set
|
|
51
|
+
# only for plugin hooks, and nothing on disk distinguishes "registered" from
|
|
52
|
+
# "loaded into this session". Any check against a file answers a different
|
|
53
|
+
# question and will drift from the real one again.
|
|
54
|
+
#
|
|
55
|
+
# So the guards run unconditionally. On a machine where the plugin hooks are also
|
|
56
|
+
# live that costs a duplicated sweep (~170ms) and a refusal printed twice, and
|
|
57
|
+
# that is the correct trade against enforcement silently switching itself off.
|
|
58
|
+
# Recovering it belongs in the guards — a marker keyed on session and payload, so
|
|
59
|
+
# whichever layer fires first does the work — not in a liveness guess here.
|
|
37
60
|
|
|
38
61
|
# Where the guards live depends on which repository this is.
|
|
39
62
|
#
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
4
4
|
"all/copy-contents/.gitattributes": "9d3831007e681186a3673e1037ef3fc82980cab2fc04e27c0868e562912c9e9f",
|
|
5
5
|
"all/copy-contents/gitignore": "2dbf7fd2f2020fc7824c432342002d9ca3ebb57b2872e761b14e942b23479a11",
|
|
6
|
-
"all/copy-overwrite/scripts/lisa-enforcement-fallback.sh": "
|
|
6
|
+
"all/copy-overwrite/scripts/lisa-enforcement-fallback.sh": "d7d88e44763694bed5eae998cd3663922c957e49f9f9621d9201f0417a4128ad",
|
|
7
7
|
"all/copy-overwrite/scripts/lisa-floor-collisions.mjs": "a612f172282d13ba9318fe5e03689d7c6ff42a0122d0c9d5d39051e1967b93dc",
|
|
8
8
|
"all/copy-overwrite/scripts/lisa-hooks/block-instruction-file-edits.sh": "8996e0bcbf1db085a5d99734e797c91f5025997bd967bc374efff8348dac14c2",
|
|
9
9
|
"all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh": "a6ed91576efebb6ba40cfa4e9d8a3e8566314909210ae8d5860be62a3feb4cff",
|
|
@@ -560,7 +560,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
|
560
560
|
"plugins/src/base/skills/lisa-secrets-access/scripts/read-secret-note.mjs": "1471d2108058f3059e242f9c71208c99fdbc212bde32de34b798eaa9a27ffbcc",
|
|
561
561
|
"plugins/src/base/skills/lisa-secrets-access/scripts/resolve-secret.mjs": "04ab89bc1f890526ba3b693cd3b022abc5a24e078b93c08fe7dfd586452b70b1",
|
|
562
562
|
"plugins/src/base/skills/lisa-secrets-access/scripts/rotate-secret.mjs": "546dc1c2f279cee6db56c0f55c01aabae0c316842f32d3219c5af6d638936a9c",
|
|
563
|
-
"plugins/src/base/skills/lisa-secrets-access/scripts/surfaces.mjs": "
|
|
563
|
+
"plugins/src/base/skills/lisa-secrets-access/scripts/surfaces.mjs": "21d3408de74f2691d61649862b086dfc37a5ce2553bcb17366fcd5d1c50a4ae8",
|
|
564
564
|
"plugins/src/base/skills/lisa-secrets-access/scripts/validate-config.mjs": "62d1b87d1b852dc00c00ea9d132d9d6953f4ef77beb5fa4b93652c4424f33274",
|
|
565
565
|
"plugins/src/base/skills/lisa-security-review/SKILL.md": "5a980eaf5efc4fcce66e75521ec5b1eda143a5b0d36e7157234a705dac94e3f5",
|
|
566
566
|
"plugins/src/base/skills/lisa-security-zap-scan/SKILL.md": "a5189442dbf970cc49fd089ab03c386c8a205b856e09501f6ad1966321e7e4b5",
|
|
@@ -578,10 +578,10 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
|
578
578
|
"plugins/src/base/skills/lisa-setup-local-env/scripts/local-env.mjs": "bff68aa66d6d4cd7cb9d0e39be691c6daa232edb097f8a601815432a32cca6a6",
|
|
579
579
|
"plugins/src/base/skills/lisa-setup-notion/SKILL.md": "f5a1e9290789fd1c33675168d30461fb24a11c98a433ef777c1f536bc2f905ef",
|
|
580
580
|
"plugins/src/base/skills/lisa-setup-remote-aws/SKILL.md": "80fbf157f9c562c033886c25a99b37356602edd9e61cd2d492f339769ddcf97e",
|
|
581
|
-
"plugins/src/base/skills/lisa-setup-remote-env/SKILL.md": "
|
|
581
|
+
"plugins/src/base/skills/lisa-setup-remote-env/SKILL.md": "b5993444364b361c7b365092ab424bc1d0eee61705a5a2471e4e1f443e30d78f",
|
|
582
582
|
"plugins/src/base/skills/lisa-setup-remote-env/assets/session-start.sh": "cb63d08b14ab7aa2d405e6770e0cf7db5d6588ae1dcb924ea6224b026fcff496",
|
|
583
583
|
"plugins/src/base/skills/lisa-setup-remote-env/assets/setup.sh": "c30d98a5645f033fc1d3a723043691b9ad997ae5666df539ff6aa19c563431b2",
|
|
584
|
-
"plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs": "
|
|
584
|
+
"plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs": "830a2c75fabb0069ebe1bf3f5ec1c1f4dd3437fea6c059b41b8ab4092277025f",
|
|
585
585
|
"plugins/src/base/skills/lisa-setup-remote-env/scripts/toolchain.mjs": "496de5aed034692fee421dc3a1fbad9f85ed9e1d0c83a1080f781a486d0274e6",
|
|
586
586
|
"plugins/src/base/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs": "82bc2a27a0a5afb2ff413a88365c619fd7f0eaada5de3ccabf2000938f0607a4",
|
|
587
587
|
"plugins/src/base/skills/lisa-setup-sonar/SKILL.md": "b18e07ae942f75aad5730c0535840ef5f7115072f1b6cc62afac83196b28d6a3",
|
|
@@ -1008,7 +1008,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
|
1008
1008
|
"scripts/lib/reusable-workflow-contract.d.mts": "791f01b55dd7a6b5d9a5f4cb9c44167caa146c2fc3c31a2ae4c2d8a350adc2f1",
|
|
1009
1009
|
"scripts/lib/reusable-workflow-contract.mjs": "134ee2a327290f066f1eb318b5ed53c711557c3e10ed462c00ff5c97cfb20863",
|
|
1010
1010
|
"scripts/lisa-commit-and-pr-local.sh": "605409c3ce6ec38ad3275604291a1ceae98f7807a605654263bc14f811c03903",
|
|
1011
|
-
"scripts/lisa-enforcement-fallback.sh": "
|
|
1011
|
+
"scripts/lisa-enforcement-fallback.sh": "d7d88e44763694bed5eae998cd3663922c957e49f9f9621d9201f0417a4128ad",
|
|
1012
1012
|
"scripts/lisa-github-environments.sh": "0a76e92f108519abaf3e29991299ec3b0db20ea533e69e6d2a53d802dba9c370",
|
|
1013
1013
|
"scripts/lisa-github-repo-settings.sh": "4afbccdfb08c62ba13afee42ec8561a28facf87c61f6f4b80000115328364d54",
|
|
1014
1014
|
"scripts/lisa-github-repo-setup.sh": "dc2f1c9d718aa34ba57161120d9319b5f78fe6b0b496d8e3c77226a08795aa36",
|
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.
|
|
118
|
+
"version": "2.336.0",
|
|
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": {
|
|
@@ -165,9 +165,19 @@ export function materializedPaths(namespace, env = process.env) {
|
|
|
165
165
|
* @param {string} [cwd] Directory to look in.
|
|
166
166
|
* @returns {object} Resolved configuration with defaults applied.
|
|
167
167
|
*/
|
|
168
|
-
export function readConfig(cwd = process.cwd()) {
|
|
168
|
+
export function readConfig(cwd = process.cwd(), env = process.env) {
|
|
169
169
|
const path = join(cwd, ".lisa.config.json");
|
|
170
|
-
|
|
170
|
+
// No repository is a real, supported state — not just a missing file.
|
|
171
|
+
//
|
|
172
|
+
// A Claude Tag channel session runs as the organization with no user account,
|
|
173
|
+
// and a repository "doesn't enter a session until a request names it". So a
|
|
174
|
+
// session can legitimately have no checkout and therefore no config, while
|
|
175
|
+
// still needing the credentials and profiles every other surface gets.
|
|
176
|
+
//
|
|
177
|
+
// The only values a config would supply here are the namespace and provider,
|
|
178
|
+
// so they can come from the environment instead. Everything else keeps its
|
|
179
|
+
// default, and an environment that sets neither still gets the old behaviour.
|
|
180
|
+
if (!existsSync(path)) return withSurface(fromEnvironment(env));
|
|
171
181
|
let cfg;
|
|
172
182
|
try {
|
|
173
183
|
cfg = JSON.parse(readFileSync(path, "utf8")).secrets;
|
|
@@ -186,6 +196,36 @@ export function readConfig(cwd = process.cwd()) {
|
|
|
186
196
|
});
|
|
187
197
|
}
|
|
188
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Build a configuration from the environment, for sessions with no checkout.
|
|
201
|
+
*
|
|
202
|
+
* `LISA_SECRETS_NAMESPACE` is the one value with no safe default: it names the
|
|
203
|
+
* directory secrets are written to and the tenant they belong to, so guessing
|
|
204
|
+
* it would write one tenant's credentials under another's name. Absent, this
|
|
205
|
+
* returns the ordinary defaults and the caller behaves exactly as before.
|
|
206
|
+
*
|
|
207
|
+
* The bootstrap key follows the namespace by convention
|
|
208
|
+
* (`BWS_ACCESS_TOKEN_<namespace>`) so a channel environment needs one variable
|
|
209
|
+
* set, not two.
|
|
210
|
+
* @param {object} env The environment to read.
|
|
211
|
+
* @returns {object} A configuration, defaulted where the environment is silent.
|
|
212
|
+
*/
|
|
213
|
+
function fromEnvironment(env) {
|
|
214
|
+
const namespace = (env.LISA_SECRETS_NAMESPACE ?? "").trim();
|
|
215
|
+
if (!namespace) return DEFAULTS;
|
|
216
|
+
|
|
217
|
+
const provider = (env.LISA_SECRETS_PROVIDER ?? "").trim() || "bitwarden";
|
|
218
|
+
return {
|
|
219
|
+
...DEFAULTS,
|
|
220
|
+
provider,
|
|
221
|
+
namespace: assertNamespace(namespace),
|
|
222
|
+
bootstrap: {
|
|
223
|
+
...DEFAULTS.bootstrap,
|
|
224
|
+
key: env.LISA_SECRETS_BOOTSTRAP_KEY ?? `BWS_ACCESS_TOKEN_${namespace}`,
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
189
229
|
/**
|
|
190
230
|
* Attach the resolved surface and its capabilities to a configuration.
|
|
191
231
|
* @param {object} cfg Configuration without surface resolution.
|
|
@@ -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 ]
|
|
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
|
|
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
|
|
package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs
CHANGED
|
@@ -559,9 +559,26 @@ export function installAssets(cwd = process.cwd()) {
|
|
|
559
559
|
* whenever cwd happens to be one of the roots.
|
|
560
560
|
*
|
|
561
561
|
* The status is the first failure and every checkout is still attempted: one
|
|
562
|
-
* broken repository must neither hide the others nor report success.
|
|
563
|
-
*
|
|
564
|
-
*
|
|
562
|
+
* broken repository must neither hide the others nor report success.
|
|
563
|
+
*
|
|
564
|
+
* Preparing nothing has two causes, and they are not the same failure:
|
|
565
|
+
*
|
|
566
|
+
* - A checkout is present but carries no entrypoint. That is a
|
|
567
|
+
* misconfiguration, and a `for` loop over a glob that matches nothing exits
|
|
568
|
+
* 0 on its own — the quiet success this has always guarded against. It
|
|
569
|
+
* still fails loudly, printing the layout it found rather than only the
|
|
570
|
+
* path it wanted.
|
|
571
|
+
* - There is NO checkout. A Claude Tag channel session runs as the
|
|
572
|
+
* organization with no user account, and a repository does not enter the
|
|
573
|
+
* session until a request names one, so this is an ordinary state rather
|
|
574
|
+
* than an error. Failing here would be severe: a setup script that exits
|
|
575
|
+
* non-zero stops the session from starting at all, so the old blanket
|
|
576
|
+
* `exit 1` would have killed every repo-less channel session.
|
|
577
|
+
*
|
|
578
|
+
* With no checkout, `LISA_SECRETS_NAMESPACE` decides whether there is anything
|
|
579
|
+
* to do: it names the tenant, which is the one value no default can supply.
|
|
580
|
+
* Given it, the machine itself is prepared — tools and credentials, no repo
|
|
581
|
+
* required. Without it there is nothing to prepare and nothing to fail about.
|
|
565
582
|
*
|
|
566
583
|
* Failure prints the layout it found rather than only the path it wanted. This
|
|
567
584
|
* field lives in a vendor settings box with a slow edit-and-retry loop, and a
|
|
@@ -580,9 +597,19 @@ export const SETUP_FIELD =
|
|
|
580
597
|
'do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); ' +
|
|
581
598
|
'case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; ' +
|
|
582
599
|
'n=$((n+1)); bash "$f" || rc=$?; done; ' +
|
|
583
|
-
'[ "$n" -gt 0 ]
|
|
584
|
-
'
|
|
585
|
-
'
|
|
600
|
+
'[ "$n" -gt 0 ] && exit "$rc"; ' +
|
|
601
|
+
'g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; ' +
|
|
602
|
+
'do [ -e "$c" ] && g=1; done; ' +
|
|
603
|
+
'if [ "$g" -eq 1 ]; then ' +
|
|
604
|
+
'echo "lisa-remote-env entrypoint not found, but a checkout is present. ' +
|
|
605
|
+
'PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; ' +
|
|
606
|
+
'if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then ' +
|
|
607
|
+
'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; " +
|
|
611
|
+
'else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; ' +
|
|
612
|
+
"exit 0";
|
|
586
613
|
|
|
587
614
|
/**
|
|
588
615
|
* Register the session-start hook at USER scope, so it fires wherever the
|
|
@@ -165,9 +165,19 @@ export function materializedPaths(namespace, env = process.env) {
|
|
|
165
165
|
* @param {string} [cwd] Directory to look in.
|
|
166
166
|
* @returns {object} Resolved configuration with defaults applied.
|
|
167
167
|
*/
|
|
168
|
-
export function readConfig(cwd = process.cwd()) {
|
|
168
|
+
export function readConfig(cwd = process.cwd(), env = process.env) {
|
|
169
169
|
const path = join(cwd, ".lisa.config.json");
|
|
170
|
-
|
|
170
|
+
// No repository is a real, supported state — not just a missing file.
|
|
171
|
+
//
|
|
172
|
+
// A Claude Tag channel session runs as the organization with no user account,
|
|
173
|
+
// and a repository "doesn't enter a session until a request names it". So a
|
|
174
|
+
// session can legitimately have no checkout and therefore no config, while
|
|
175
|
+
// still needing the credentials and profiles every other surface gets.
|
|
176
|
+
//
|
|
177
|
+
// The only values a config would supply here are the namespace and provider,
|
|
178
|
+
// so they can come from the environment instead. Everything else keeps its
|
|
179
|
+
// default, and an environment that sets neither still gets the old behaviour.
|
|
180
|
+
if (!existsSync(path)) return withSurface(fromEnvironment(env));
|
|
171
181
|
let cfg;
|
|
172
182
|
try {
|
|
173
183
|
cfg = JSON.parse(readFileSync(path, "utf8")).secrets;
|
|
@@ -186,6 +196,36 @@ export function readConfig(cwd = process.cwd()) {
|
|
|
186
196
|
});
|
|
187
197
|
}
|
|
188
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Build a configuration from the environment, for sessions with no checkout.
|
|
201
|
+
*
|
|
202
|
+
* `LISA_SECRETS_NAMESPACE` is the one value with no safe default: it names the
|
|
203
|
+
* directory secrets are written to and the tenant they belong to, so guessing
|
|
204
|
+
* it would write one tenant's credentials under another's name. Absent, this
|
|
205
|
+
* returns the ordinary defaults and the caller behaves exactly as before.
|
|
206
|
+
*
|
|
207
|
+
* The bootstrap key follows the namespace by convention
|
|
208
|
+
* (`BWS_ACCESS_TOKEN_<namespace>`) so a channel environment needs one variable
|
|
209
|
+
* set, not two.
|
|
210
|
+
* @param {object} env The environment to read.
|
|
211
|
+
* @returns {object} A configuration, defaulted where the environment is silent.
|
|
212
|
+
*/
|
|
213
|
+
function fromEnvironment(env) {
|
|
214
|
+
const namespace = (env.LISA_SECRETS_NAMESPACE ?? "").trim();
|
|
215
|
+
if (!namespace) return DEFAULTS;
|
|
216
|
+
|
|
217
|
+
const provider = (env.LISA_SECRETS_PROVIDER ?? "").trim() || "bitwarden";
|
|
218
|
+
return {
|
|
219
|
+
...DEFAULTS,
|
|
220
|
+
provider,
|
|
221
|
+
namespace: assertNamespace(namespace),
|
|
222
|
+
bootstrap: {
|
|
223
|
+
...DEFAULTS.bootstrap,
|
|
224
|
+
key: env.LISA_SECRETS_BOOTSTRAP_KEY ?? `BWS_ACCESS_TOKEN_${namespace}`,
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
189
229
|
/**
|
|
190
230
|
* Attach the resolved surface and its capabilities to a configuration.
|
|
191
231
|
* @param {object} cfg Configuration without surface resolution.
|
|
@@ -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 ]
|
|
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
|
|
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
|
|
|
@@ -559,9 +559,26 @@ export function installAssets(cwd = process.cwd()) {
|
|
|
559
559
|
* whenever cwd happens to be one of the roots.
|
|
560
560
|
*
|
|
561
561
|
* The status is the first failure and every checkout is still attempted: one
|
|
562
|
-
* broken repository must neither hide the others nor report success.
|
|
563
|
-
*
|
|
564
|
-
*
|
|
562
|
+
* broken repository must neither hide the others nor report success.
|
|
563
|
+
*
|
|
564
|
+
* Preparing nothing has two causes, and they are not the same failure:
|
|
565
|
+
*
|
|
566
|
+
* - A checkout is present but carries no entrypoint. That is a
|
|
567
|
+
* misconfiguration, and a `for` loop over a glob that matches nothing exits
|
|
568
|
+
* 0 on its own — the quiet success this has always guarded against. It
|
|
569
|
+
* still fails loudly, printing the layout it found rather than only the
|
|
570
|
+
* path it wanted.
|
|
571
|
+
* - There is NO checkout. A Claude Tag channel session runs as the
|
|
572
|
+
* organization with no user account, and a repository does not enter the
|
|
573
|
+
* session until a request names one, so this is an ordinary state rather
|
|
574
|
+
* than an error. Failing here would be severe: a setup script that exits
|
|
575
|
+
* non-zero stops the session from starting at all, so the old blanket
|
|
576
|
+
* `exit 1` would have killed every repo-less channel session.
|
|
577
|
+
*
|
|
578
|
+
* With no checkout, `LISA_SECRETS_NAMESPACE` decides whether there is anything
|
|
579
|
+
* to do: it names the tenant, which is the one value no default can supply.
|
|
580
|
+
* Given it, the machine itself is prepared — tools and credentials, no repo
|
|
581
|
+
* required. Without it there is nothing to prepare and nothing to fail about.
|
|
565
582
|
*
|
|
566
583
|
* Failure prints the layout it found rather than only the path it wanted. This
|
|
567
584
|
* field lives in a vendor settings box with a slow edit-and-retry loop, and a
|
|
@@ -580,9 +597,19 @@ export const SETUP_FIELD =
|
|
|
580
597
|
'do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); ' +
|
|
581
598
|
'case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; ' +
|
|
582
599
|
'n=$((n+1)); bash "$f" || rc=$?; done; ' +
|
|
583
|
-
'[ "$n" -gt 0 ]
|
|
584
|
-
'
|
|
585
|
-
'
|
|
600
|
+
'[ "$n" -gt 0 ] && exit "$rc"; ' +
|
|
601
|
+
'g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; ' +
|
|
602
|
+
'do [ -e "$c" ] && g=1; done; ' +
|
|
603
|
+
'if [ "$g" -eq 1 ]; then ' +
|
|
604
|
+
'echo "lisa-remote-env entrypoint not found, but a checkout is present. ' +
|
|
605
|
+
'PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; ' +
|
|
606
|
+
'if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then ' +
|
|
607
|
+
'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; " +
|
|
611
|
+
'else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; ' +
|
|
612
|
+
"exit 0";
|
|
586
613
|
|
|
587
614
|
/**
|
|
588
615
|
* Register the session-start hook at USER scope, so it fires wherever the
|
|
@@ -165,9 +165,19 @@ export function materializedPaths(namespace, env = process.env) {
|
|
|
165
165
|
* @param {string} [cwd] Directory to look in.
|
|
166
166
|
* @returns {object} Resolved configuration with defaults applied.
|
|
167
167
|
*/
|
|
168
|
-
export function readConfig(cwd = process.cwd()) {
|
|
168
|
+
export function readConfig(cwd = process.cwd(), env = process.env) {
|
|
169
169
|
const path = join(cwd, ".lisa.config.json");
|
|
170
|
-
|
|
170
|
+
// No repository is a real, supported state — not just a missing file.
|
|
171
|
+
//
|
|
172
|
+
// A Claude Tag channel session runs as the organization with no user account,
|
|
173
|
+
// and a repository "doesn't enter a session until a request names it". So a
|
|
174
|
+
// session can legitimately have no checkout and therefore no config, while
|
|
175
|
+
// still needing the credentials and profiles every other surface gets.
|
|
176
|
+
//
|
|
177
|
+
// The only values a config would supply here are the namespace and provider,
|
|
178
|
+
// so they can come from the environment instead. Everything else keeps its
|
|
179
|
+
// default, and an environment that sets neither still gets the old behaviour.
|
|
180
|
+
if (!existsSync(path)) return withSurface(fromEnvironment(env));
|
|
171
181
|
let cfg;
|
|
172
182
|
try {
|
|
173
183
|
cfg = JSON.parse(readFileSync(path, "utf8")).secrets;
|
|
@@ -186,6 +196,36 @@ export function readConfig(cwd = process.cwd()) {
|
|
|
186
196
|
});
|
|
187
197
|
}
|
|
188
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Build a configuration from the environment, for sessions with no checkout.
|
|
201
|
+
*
|
|
202
|
+
* `LISA_SECRETS_NAMESPACE` is the one value with no safe default: it names the
|
|
203
|
+
* directory secrets are written to and the tenant they belong to, so guessing
|
|
204
|
+
* it would write one tenant's credentials under another's name. Absent, this
|
|
205
|
+
* returns the ordinary defaults and the caller behaves exactly as before.
|
|
206
|
+
*
|
|
207
|
+
* The bootstrap key follows the namespace by convention
|
|
208
|
+
* (`BWS_ACCESS_TOKEN_<namespace>`) so a channel environment needs one variable
|
|
209
|
+
* set, not two.
|
|
210
|
+
* @param {object} env The environment to read.
|
|
211
|
+
* @returns {object} A configuration, defaulted where the environment is silent.
|
|
212
|
+
*/
|
|
213
|
+
function fromEnvironment(env) {
|
|
214
|
+
const namespace = (env.LISA_SECRETS_NAMESPACE ?? "").trim();
|
|
215
|
+
if (!namespace) return DEFAULTS;
|
|
216
|
+
|
|
217
|
+
const provider = (env.LISA_SECRETS_PROVIDER ?? "").trim() || "bitwarden";
|
|
218
|
+
return {
|
|
219
|
+
...DEFAULTS,
|
|
220
|
+
provider,
|
|
221
|
+
namespace: assertNamespace(namespace),
|
|
222
|
+
bootstrap: {
|
|
223
|
+
...DEFAULTS.bootstrap,
|
|
224
|
+
key: env.LISA_SECRETS_BOOTSTRAP_KEY ?? `BWS_ACCESS_TOKEN_${namespace}`,
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
189
229
|
/**
|
|
190
230
|
* Attach the resolved surface and its capabilities to a configuration.
|
|
191
231
|
* @param {object} cfg Configuration without surface resolution.
|
|
@@ -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 ]
|
|
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
|
|
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
|
|
|
@@ -559,9 +559,26 @@ export function installAssets(cwd = process.cwd()) {
|
|
|
559
559
|
* whenever cwd happens to be one of the roots.
|
|
560
560
|
*
|
|
561
561
|
* The status is the first failure and every checkout is still attempted: one
|
|
562
|
-
* broken repository must neither hide the others nor report success.
|
|
563
|
-
*
|
|
564
|
-
*
|
|
562
|
+
* broken repository must neither hide the others nor report success.
|
|
563
|
+
*
|
|
564
|
+
* Preparing nothing has two causes, and they are not the same failure:
|
|
565
|
+
*
|
|
566
|
+
* - A checkout is present but carries no entrypoint. That is a
|
|
567
|
+
* misconfiguration, and a `for` loop over a glob that matches nothing exits
|
|
568
|
+
* 0 on its own — the quiet success this has always guarded against. It
|
|
569
|
+
* still fails loudly, printing the layout it found rather than only the
|
|
570
|
+
* path it wanted.
|
|
571
|
+
* - There is NO checkout. A Claude Tag channel session runs as the
|
|
572
|
+
* organization with no user account, and a repository does not enter the
|
|
573
|
+
* session until a request names one, so this is an ordinary state rather
|
|
574
|
+
* than an error. Failing here would be severe: a setup script that exits
|
|
575
|
+
* non-zero stops the session from starting at all, so the old blanket
|
|
576
|
+
* `exit 1` would have killed every repo-less channel session.
|
|
577
|
+
*
|
|
578
|
+
* With no checkout, `LISA_SECRETS_NAMESPACE` decides whether there is anything
|
|
579
|
+
* to do: it names the tenant, which is the one value no default can supply.
|
|
580
|
+
* Given it, the machine itself is prepared — tools and credentials, no repo
|
|
581
|
+
* required. Without it there is nothing to prepare and nothing to fail about.
|
|
565
582
|
*
|
|
566
583
|
* Failure prints the layout it found rather than only the path it wanted. This
|
|
567
584
|
* field lives in a vendor settings box with a slow edit-and-retry loop, and a
|
|
@@ -580,9 +597,19 @@ export const SETUP_FIELD =
|
|
|
580
597
|
'do [ -f "$f" ] || continue; d=$(cd "$(dirname "$f")" && pwd -P); ' +
|
|
581
598
|
'case " $seen " in *" $d "*) continue;; esac; seen="$seen $d"; ' +
|
|
582
599
|
'n=$((n+1)); bash "$f" || rc=$?; done; ' +
|
|
583
|
-
'[ "$n" -gt 0 ]
|
|
584
|
-
'
|
|
585
|
-
'
|
|
600
|
+
'[ "$n" -gt 0 ] && exit "$rc"; ' +
|
|
601
|
+
'g=0; for c in ./.git ./*/.git "$HOME"/*/.git /workspace/*/.git; ' +
|
|
602
|
+
'do [ -e "$c" ] && g=1; done; ' +
|
|
603
|
+
'if [ "$g" -eq 1 ]; then ' +
|
|
604
|
+
'echo "lisa-remote-env entrypoint not found, but a checkout is present. ' +
|
|
605
|
+
'PWD=$PWD HOME=$HOME" >&2; ls -1 . "$HOME" /workspace 2>&1 | head -40 >&2; exit 1; fi; ' +
|
|
606
|
+
'if [ -n "${LISA_SECRETS_NAMESPACE:-}" ]; then ' +
|
|
607
|
+
'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; " +
|
|
611
|
+
'else echo "No checkout and no LISA_SECRETS_NAMESPACE; nothing to prepare."; fi; ' +
|
|
612
|
+
"exit 0";
|
|
586
613
|
|
|
587
614
|
/**
|
|
588
615
|
* Register the session-start hook at USER scope, so it fires wherever the
|