@codyswann/lisa 3.26.0 → 3.26.2
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/check-state-classification.mjs +31 -0
- package/all/copy-overwrite/scripts/lisa-gates.mjs +10 -1
- package/all/copy-overwrite/scripts/lisa-hooks/block-managed-file-edits.sh +136 -15
- package/dist/cli/doctor-lisa-owned-artifacts.d.ts.map +1 -1
- package/dist/cli/doctor-lisa-owned-artifacts.js +13 -2
- package/dist/cli/doctor-lisa-owned-artifacts.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +6 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +24 -23
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- 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-atlassian-access/scripts/markdown-to-adf.mjs +23 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +31 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-remote-dispatch/scripts/dispatch.mjs +30 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +25 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/inspect-vault.mjs +23 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +24 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/read-secret-note.mjs +25 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/resolve-secret.mjs +25 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/rotate-secret.mjs +25 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/sync-secret-to-ci.mjs +25 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/validate-config.mjs +25 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-automations/scripts/generate-workflow.mjs +31 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-local-env/scripts/local-env.mjs +24 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +23 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +25 -2
- package/plugins/lisa/hooks/block-managed-file-edits.sh +136 -15
- package/plugins/lisa/skills/lisa-atlassian-access/scripts/markdown-to-adf.mjs +23 -1
- package/plugins/lisa/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +31 -2
- package/plugins/lisa/skills/lisa-remote-dispatch/scripts/dispatch.mjs +30 -2
- package/plugins/lisa/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +25 -1
- package/plugins/lisa/skills/lisa-secrets-access/scripts/inspect-vault.mjs +23 -1
- package/plugins/lisa/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +24 -1
- package/plugins/lisa/skills/lisa-secrets-access/scripts/read-secret-note.mjs +25 -2
- package/plugins/lisa/skills/lisa-secrets-access/scripts/resolve-secret.mjs +25 -2
- package/plugins/lisa/skills/lisa-secrets-access/scripts/rotate-secret.mjs +25 -2
- package/plugins/lisa/skills/lisa-secrets-access/scripts/sync-secret-to-ci.mjs +25 -1
- package/plugins/lisa/skills/lisa-secrets-access/scripts/validate-config.mjs +25 -2
- package/plugins/lisa/skills/lisa-setup-automations/scripts/generate-workflow.mjs +31 -2
- package/plugins/lisa/skills/lisa-setup-local-env/scripts/local-env.mjs +24 -2
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +23 -1
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +25 -2
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-atlassian-access/scripts/markdown-to-adf.mjs +23 -1
- package/plugins/lisa-agy/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +31 -2
- package/plugins/lisa-agy/skills/lisa-remote-dispatch/scripts/dispatch.mjs +30 -2
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +25 -1
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/inspect-vault.mjs +23 -1
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +24 -1
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/read-secret-note.mjs +25 -2
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/resolve-secret.mjs +25 -2
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/rotate-secret.mjs +25 -2
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/sync-secret-to-ci.mjs +25 -1
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/validate-config.mjs +25 -2
- package/plugins/lisa-agy/skills/lisa-setup-automations/scripts/generate-workflow.mjs +31 -2
- package/plugins/lisa-agy/skills/lisa-setup-local-env/scripts/local-env.mjs +24 -2
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +23 -1
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +25 -2
- 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/hooks/block-managed-file-edits.sh +136 -15
- package/plugins/lisa-copilot/skills/lisa-atlassian-access/scripts/markdown-to-adf.mjs +23 -1
- package/plugins/lisa-copilot/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +31 -2
- package/plugins/lisa-copilot/skills/lisa-remote-dispatch/scripts/dispatch.mjs +30 -2
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +25 -1
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/inspect-vault.mjs +23 -1
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +24 -1
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/read-secret-note.mjs +25 -2
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/resolve-secret.mjs +25 -2
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/rotate-secret.mjs +25 -2
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/sync-secret-to-ci.mjs +25 -1
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/validate-config.mjs +25 -2
- package/plugins/lisa-copilot/skills/lisa-setup-automations/scripts/generate-workflow.mjs +31 -2
- package/plugins/lisa-copilot/skills/lisa-setup-local-env/scripts/local-env.mjs +24 -2
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +23 -1
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +25 -2
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/block-managed-file-edits.sh +136 -15
- package/plugins/lisa-cursor/skills/lisa-atlassian-access/scripts/markdown-to-adf.mjs +23 -1
- package/plugins/lisa-cursor/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +31 -2
- package/plugins/lisa-cursor/skills/lisa-remote-dispatch/scripts/dispatch.mjs +30 -2
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +25 -1
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/inspect-vault.mjs +23 -1
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +24 -1
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/read-secret-note.mjs +25 -2
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/resolve-secret.mjs +25 -2
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/rotate-secret.mjs +25 -2
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/sync-secret-to-ci.mjs +25 -1
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/validate-config.mjs +25 -2
- package/plugins/lisa-cursor/skills/lisa-setup-automations/scripts/generate-workflow.mjs +31 -2
- package/plugins/lisa-cursor/skills/lisa-setup-local-env/scripts/local-env.mjs +24 -2
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +23 -1
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +25 -2
- 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/hooks/block-managed-file-edits.sh +136 -15
- package/plugins/src/base/skills/lisa-atlassian-access/scripts/markdown-to-adf.mjs +23 -1
- package/plugins/src/base/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +31 -2
- package/plugins/src/base/skills/lisa-remote-dispatch/scripts/dispatch.mjs +30 -2
- package/plugins/src/base/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +25 -1
- package/plugins/src/base/skills/lisa-secrets-access/scripts/inspect-vault.mjs +23 -1
- package/plugins/src/base/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +24 -1
- package/plugins/src/base/skills/lisa-secrets-access/scripts/read-secret-note.mjs +25 -2
- package/plugins/src/base/skills/lisa-secrets-access/scripts/resolve-secret.mjs +25 -2
- package/plugins/src/base/skills/lisa-secrets-access/scripts/rotate-secret.mjs +25 -2
- package/plugins/src/base/skills/lisa-secrets-access/scripts/sync-secret-to-ci.mjs +25 -1
- package/plugins/src/base/skills/lisa-secrets-access/scripts/validate-config.mjs +25 -2
- package/plugins/src/base/skills/lisa-setup-automations/scripts/generate-workflow.mjs +31 -2
- package/plugins/src/base/skills/lisa-setup-local-env/scripts/local-env.mjs +24 -2
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +23 -1
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +25 -2
- package/scripts/generate-agy-plugin-artifacts.mjs +2 -1
- package/scripts/generate-copilot-plugin-artifacts.mjs +2 -1
- package/scripts/generate-cursor-plugin-artifacts.mjs +2 -1
- package/typescript/copy-overwrite/scripts/check-skipped-required-checks.mjs +14 -3
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# PreToolUse hook: refuse agent writes to files Lisa overwrites on every apply.
|
|
3
3
|
#
|
|
4
|
-
# Lisa ships templates in three modes, and only one of them
|
|
4
|
+
# Lisa ships templates in three modes, and only one of them is unsafe to edit:
|
|
5
5
|
#
|
|
6
|
-
# copy-overwrite —
|
|
7
|
-
# gone at the next `bun install`, silently.
|
|
6
|
+
# copy-overwrite — see below; the harm depends on the file.
|
|
8
7
|
# copy-contents — Lisa APPENDS its lines; host content survives.
|
|
9
8
|
# create-only — skipped when the file exists; the host owns it outright.
|
|
10
9
|
#
|
|
@@ -12,6 +11,21 @@
|
|
|
12
11
|
# would stop agents editing files they are supposed to own, which is worse than
|
|
13
12
|
# the problem being solved.
|
|
14
13
|
#
|
|
14
|
+
# WITHIN copy-overwrite there are two populations with OPPOSITE consequences,
|
|
15
|
+
# and an earlier version of this guard described only one of them:
|
|
16
|
+
#
|
|
17
|
+
# hash-tracked guards (the `.mjs` scripts, listed in the Lisa-owned ledger)
|
|
18
|
+
# — an edit classifies as `host-modified` and `lisa apply` PRESERVES it.
|
|
19
|
+
# The file silently forks and stops receiving upstream fixes while looking
|
|
20
|
+
# current. Nothing is deleted; that is what makes it hard to notice.
|
|
21
|
+
# everything else (`.json` configs and friends)
|
|
22
|
+
# — replaced wholesale on the next apply, which runs on every install.
|
|
23
|
+
# The edit vanishes.
|
|
24
|
+
#
|
|
25
|
+
# The refusal branches on ledger membership so it states the consequence that
|
|
26
|
+
# actually applies, rather than describing both and leaving the reader to work
|
|
27
|
+
# out which they are in.
|
|
28
|
+
#
|
|
15
29
|
# Measured, not hypothetical. Nothing enforced this, so downstream copies were
|
|
16
30
|
# edited and then silently diverged: `classify-maestro-failures.mjs` reached
|
|
17
31
|
# 36,061 bytes in one fleet repo against 29,586 shipped, and five gate files in
|
|
@@ -67,6 +81,71 @@ if [ -f "$project_root/package.json" ] &&
|
|
|
67
81
|
exit 0
|
|
68
82
|
fi
|
|
69
83
|
|
|
84
|
+
# Whether the project has claimed a path in `.lisaignore`.
|
|
85
|
+
#
|
|
86
|
+
# THIS IS THE OWNERSHIP QUESTION, and it decides whether blocking is right at
|
|
87
|
+
# all. `lisa apply` skips an ignored path — it logs `Kept (.lisaignore)` and
|
|
88
|
+
# counts it as ignored rather than overwritten — so the file is the project's,
|
|
89
|
+
# its edits survive, and refusing them would be refusing someone access to their
|
|
90
|
+
# own file. `doctor-lisa-owned-artifacts` already consults this list; this guard
|
|
91
|
+
# did not, which would have blocked deliberate forks.
|
|
92
|
+
#
|
|
93
|
+
# The real matcher is minimatch in `src/utils/ignore-patterns.ts` and cannot be
|
|
94
|
+
# reproduced faithfully in shell. This covers the common shapes — exact path,
|
|
95
|
+
# directory prefix, glob, and a bare pattern matching any segment — and where it
|
|
96
|
+
# is unsure it ALLOWS. Wrongly allowing costs an edit that apply may overwrite,
|
|
97
|
+
# which is the behaviour before this guard existed; wrongly blocking locks
|
|
98
|
+
# someone out of a file they own.
|
|
99
|
+
lisaignored() {
|
|
100
|
+
local rel="$1"
|
|
101
|
+
local list="$project_root/.lisaignore"
|
|
102
|
+
[ -f "$list" ] || return 1
|
|
103
|
+
local pattern
|
|
104
|
+
while IFS= read -r pattern || [ -n "$pattern" ]; do
|
|
105
|
+
pattern="${pattern#"${pattern%%[![:space:]]*}"}"
|
|
106
|
+
pattern="${pattern%"${pattern##*[![:space:]]}"}"
|
|
107
|
+
[ -n "$pattern" ] || continue
|
|
108
|
+
case "$pattern" in \#*) continue ;; esac
|
|
109
|
+
# A leading `!` is not gitignore negation here. The real matcher passes
|
|
110
|
+
# patterns to minimatch, which negates by default, and it combines them with
|
|
111
|
+
# `.some()` — so a single `!scripts/a.mjs` line reports EVERY OTHER PATH as
|
|
112
|
+
# ignored. Measured:
|
|
113
|
+
#
|
|
114
|
+
# patterns=["!scripts/a.mjs"] path=scripts/a.mjs -> ignored=false
|
|
115
|
+
# patterns=["!scripts/a.mjs"] path=scripts/b.mjs -> ignored=TRUE
|
|
116
|
+
#
|
|
117
|
+
# Reproducing that faithfully would mean disabling this guard on a typo.
|
|
118
|
+
# Reproducing the intuitive gitignore reading would mean blocking files the
|
|
119
|
+
# matcher considers ignored. Both are wrong, so the file is treated as
|
|
120
|
+
# claimed and the write is allowed — the same direction this function errs
|
|
121
|
+
# everywhere else. Filed upstream; when the matcher stops negating, delete
|
|
122
|
+
# this branch rather than teaching it a second wrong answer.
|
|
123
|
+
case "$pattern" in !*) return 0 ;; esac
|
|
124
|
+
case "$pattern" in
|
|
125
|
+
*/)
|
|
126
|
+
case "$rel" in "${pattern%/}"/* | "${pattern%/}") return 0 ;; esac
|
|
127
|
+
;;
|
|
128
|
+
esac
|
|
129
|
+
# shellcheck disable=SC2254 -- the pattern is a glob on purpose.
|
|
130
|
+
case "$rel" in $pattern) return 0 ;; esac
|
|
131
|
+
case "$pattern" in
|
|
132
|
+
*/*) ;;
|
|
133
|
+
*)
|
|
134
|
+
# shellcheck disable=SC2254 -- ditto, matched against the basename.
|
|
135
|
+
case "${rel##*/}" in $pattern) return 0 ;; esac
|
|
136
|
+
;;
|
|
137
|
+
esac
|
|
138
|
+
done <"$list"
|
|
139
|
+
return 1
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
# A candidate rewritten relative to the project, so an absolute target from a
|
|
143
|
+
# tool payload and a relative one from a shell command classify identically.
|
|
144
|
+
relative_path() {
|
|
145
|
+
local rel="${1#"$project_root"/}"
|
|
146
|
+
printf '%s' "${rel#./}"
|
|
147
|
+
}
|
|
148
|
+
|
|
70
149
|
# Whether a host-relative path is shipped as a copy-overwrite template.
|
|
71
150
|
#
|
|
72
151
|
# A few stat calls rather than an enumeration: the same relative path is probed
|
|
@@ -77,10 +156,11 @@ managed_source() {
|
|
|
77
156
|
case "$candidate" in
|
|
78
157
|
*/node_modules/* | node_modules/* | */dist/* | dist/*) return 1 ;;
|
|
79
158
|
esac
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
rel="${rel#./}"
|
|
159
|
+
local rel
|
|
160
|
+
rel="$(relative_path "$candidate")"
|
|
83
161
|
[ -n "$rel" ] || return 1
|
|
162
|
+
# Claimed by the project, so not ours to refuse.
|
|
163
|
+
lisaignored "$rel" && return 1
|
|
84
164
|
local stack
|
|
85
165
|
for stack in "$package_root"/*/copy-overwrite; do
|
|
86
166
|
[ -d "$stack" ] || continue
|
|
@@ -92,19 +172,44 @@ managed_source() {
|
|
|
92
172
|
return 1
|
|
93
173
|
}
|
|
94
174
|
|
|
175
|
+
# Whether a destination is a ledger-tracked Lisa-owned guard.
|
|
176
|
+
#
|
|
177
|
+
# The two populations behind this guard have OPPOSITE consequences, so the
|
|
178
|
+
# refusal has to know which one it is looking at rather than describing both and
|
|
179
|
+
# leaving the reader to guess. A guard in the content-hash ledger classifies as
|
|
180
|
+
# `host-modified` once edited and `lisa apply` PRESERVES it; anything else is
|
|
181
|
+
# replaced wholesale. Both are bad, for different reasons, and the right next
|
|
182
|
+
# step differs too.
|
|
183
|
+
ledger_tracked() {
|
|
184
|
+
local rel="$1"
|
|
185
|
+
local ledger="$package_root/dist/core/lisa-owned-hash-ledger.js"
|
|
186
|
+
[ -f "$ledger" ] || return 1
|
|
187
|
+
grep -q "\"$rel\"" "$ledger" 2>/dev/null
|
|
188
|
+
}
|
|
189
|
+
|
|
95
190
|
refuse() {
|
|
96
191
|
local target="$1"
|
|
97
192
|
local source="$2"
|
|
193
|
+
local rel="$3"
|
|
194
|
+
local consequence
|
|
195
|
+
if ledger_tracked "$rel"; then
|
|
196
|
+
consequence="This is a Lisa-owned guard, tracked by content hash. \`lisa apply\`
|
|
197
|
+
will PRESERVE your edit rather than overwrite it — and that is the trap. The
|
|
198
|
+
file silently forks: it keeps looking current while every upstream fix stops
|
|
199
|
+
reaching it. One repository in this fleet is carrying 243 lines of divergence
|
|
200
|
+
nobody knew about, in a guard that had quietly stopped receiving fixes."
|
|
201
|
+
else
|
|
202
|
+
consequence="This template is not hash-tracked, so \`lisa apply\` REPLACES it
|
|
203
|
+
wholesale — and apply runs on every \`bun install\`. Your edit survives until the
|
|
204
|
+
next install and then vanishes, with nothing reporting that it had."
|
|
205
|
+
fi
|
|
98
206
|
cat >&2 <<EOF
|
|
99
207
|
BLOCKED: refusing to write \`$target\`.
|
|
100
208
|
|
|
101
|
-
WHY: this file is Lisa-managed
|
|
102
|
-
(\`$source\` in the installed package)
|
|
103
|
-
\`lisa apply\` — which runs on every \`bun install\`. Your edit would survive
|
|
104
|
-
until the next install and then vanish, with nothing reporting that it had.
|
|
209
|
+
WHY: this file is Lisa-managed, shipped as a **copy-overwrite** template
|
|
210
|
+
(\`$source\` in the installed package).
|
|
105
211
|
|
|
106
|
-
|
|
107
|
-
until they stopped receiving upstream fixes entirely.
|
|
212
|
+
$consequence
|
|
108
213
|
|
|
109
214
|
WHERE IT GOES INSTEAD — take the first one that fits:
|
|
110
215
|
|
|
@@ -122,7 +227,23 @@ WHERE IT GOES INSTEAD — take the first one that fits:
|
|
|
122
227
|
proves each one, so a project can substitute its own task without touching a
|
|
123
228
|
shipped file.
|
|
124
229
|
|
|
125
|
-
4.
|
|
230
|
+
4. This project has deliberately FORKED this file and means to keep its own
|
|
231
|
+
version. What to do depends on which population it is, and \`.lisaignore\` is
|
|
232
|
+
the WRONG answer for a hash-tracked guard:
|
|
233
|
+
|
|
234
|
+
- **A Lisa-owned guard (hash-tracked).** Do NOT add it to \`.lisaignore\`. The
|
|
235
|
+
ledger already preserves your version, so ignoring it buys nothing — and it
|
|
236
|
+
silences the standoff \`lisa doctor\` reports on every run, replacing a true
|
|
237
|
+
warning with the line "Enforcement guards match the installed Lisa
|
|
238
|
+
version", which is then false. A visible, resolvable fork becomes a silent
|
|
239
|
+
permanent one. Keep the warning and resolve the fork: upstream what is
|
|
240
|
+
general, or accept the standoff knowingly. To make this one edit, use the
|
|
241
|
+
override below.
|
|
242
|
+
- **Any other template.** \`.lisaignore\` is the right answer. Nothing else
|
|
243
|
+
preserves it, and the entry declares the divergence where the next person
|
|
244
|
+
can see it.
|
|
245
|
+
|
|
246
|
+
5. You believe this file should not be Lisa-managed at all. That is a real
|
|
126
247
|
argument and it belongs upstream, not in a local edit that will be erased.
|
|
127
248
|
|
|
128
249
|
If a human explicitly asked for this edit, they can re-run with
|
|
@@ -142,7 +263,7 @@ case "$tool_name" in
|
|
|
142
263
|
while IFS= read -r candidate; do
|
|
143
264
|
[ -n "$candidate" ] || continue
|
|
144
265
|
if source_path="$(managed_source "$candidate")"; then
|
|
145
|
-
refuse "$candidate" "$source_path"
|
|
266
|
+
refuse "$candidate" "$source_path" "$(relative_path "$candidate")"
|
|
146
267
|
fi
|
|
147
268
|
done <<EOF
|
|
148
269
|
$paths
|
|
@@ -157,7 +278,7 @@ EOF
|
|
|
157
278
|
while IFS= read -r token; do
|
|
158
279
|
[ -n "$token" ] || continue
|
|
159
280
|
if source_path="$(managed_source "$token")"; then
|
|
160
|
-
refuse "$token" "$source_path"
|
|
281
|
+
refuse "$token" "$source_path" "$(relative_path "$token")"
|
|
161
282
|
fi
|
|
162
283
|
done <<EOF
|
|
163
284
|
$(printf '%s' "$command_str" |
|
|
@@ -202,7 +202,29 @@ function parseInline(text) {
|
|
|
202
202
|
return nodes.length > 0 ? nodes : [{ type: "text", text: "" }];
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Whether this module is the one node was asked to run.
|
|
207
|
+
*
|
|
208
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
209
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
210
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
211
|
+
*
|
|
212
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
213
|
+
* with no `lib/` sibling to import from once installed.
|
|
214
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
215
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
216
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
217
|
+
*/
|
|
218
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
219
|
+
if (!argv1) return false;
|
|
220
|
+
try {
|
|
221
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
222
|
+
} catch {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (invokedAsScript(import.meta.url)) {
|
|
206
228
|
let input = "";
|
|
207
229
|
process.stdin.setEncoding("utf8");
|
|
208
230
|
process.stdin.on("data", chunk => {
|
|
@@ -22,7 +22,14 @@
|
|
|
22
22
|
* @module detect-tooling
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
existsSync,
|
|
27
|
+
readFileSync,
|
|
28
|
+
readdirSync,
|
|
29
|
+
statSync,
|
|
30
|
+
realpathSync,
|
|
31
|
+
} from "node:fs";
|
|
32
|
+
import { fileURLToPath } from "node:url";
|
|
26
33
|
import { join } from "node:path";
|
|
27
34
|
|
|
28
35
|
import { commandsIn } from "./commands.mjs";
|
|
@@ -583,7 +590,29 @@ export function proposedEntries(proposal) {
|
|
|
583
590
|
};
|
|
584
591
|
}
|
|
585
592
|
|
|
586
|
-
|
|
593
|
+
/**
|
|
594
|
+
* Whether this module is the one node was asked to run.
|
|
595
|
+
*
|
|
596
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
597
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
598
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
599
|
+
*
|
|
600
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
601
|
+
* with no `lib/` sibling to import from once installed.
|
|
602
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
603
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
604
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
605
|
+
*/
|
|
606
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
607
|
+
if (!argv1) return false;
|
|
608
|
+
try {
|
|
609
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
610
|
+
} catch {
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
if (invokedAsScript(import.meta.url)) {
|
|
587
616
|
const proposals = detectTooling();
|
|
588
617
|
if (process.argv.includes("--json")) {
|
|
589
618
|
console.log(JSON.stringify(proposals, null, 2));
|
|
@@ -20,7 +20,13 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import { execFileSync } from "node:child_process";
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
existsSync,
|
|
25
|
+
mkdirSync,
|
|
26
|
+
readFileSync,
|
|
27
|
+
writeFileSync,
|
|
28
|
+
realpathSync,
|
|
29
|
+
} from "node:fs";
|
|
24
30
|
import { dirname, join, resolve } from "node:path";
|
|
25
31
|
import { fileURLToPath } from "node:url";
|
|
26
32
|
|
|
@@ -495,7 +501,29 @@ async function main() {
|
|
|
495
501
|
console.log(`recorded in ${LEDGER}; not polling — this process is done.`);
|
|
496
502
|
}
|
|
497
503
|
|
|
498
|
-
|
|
504
|
+
/**
|
|
505
|
+
* Whether this module is the one node was asked to run.
|
|
506
|
+
*
|
|
507
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
508
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
509
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
510
|
+
*
|
|
511
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
512
|
+
* with no `lib/` sibling to import from once installed.
|
|
513
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
514
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
515
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
516
|
+
*/
|
|
517
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
518
|
+
if (!argv1) return false;
|
|
519
|
+
try {
|
|
520
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
521
|
+
} catch {
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (invokedAsScript(import.meta.url)) {
|
|
499
527
|
// Awaited rather than called bare: one dispatch path is async, so a synchronous
|
|
500
528
|
// try/catch would let a rejection escape as an unhandled rejection and exit 0 —
|
|
501
529
|
// reporting dispatched work that was never accepted.
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { createHash } from "node:crypto";
|
|
21
|
+
import { fileURLToPath } from "node:url";
|
|
22
|
+
import { realpathSync } from "node:fs";
|
|
21
23
|
|
|
22
24
|
import { validateNote } from "./note-format.mjs";
|
|
23
25
|
import { fetchAll, fetchRotatable } from "./providers.mjs";
|
|
@@ -239,7 +241,29 @@ function main() {
|
|
|
239
241
|
if (errors) throw new Error(`${errors} secrets configuration error(s)`);
|
|
240
242
|
}
|
|
241
243
|
|
|
242
|
-
|
|
244
|
+
/**
|
|
245
|
+
* Whether this module is the one node was asked to run.
|
|
246
|
+
*
|
|
247
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
248
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
249
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
250
|
+
*
|
|
251
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
252
|
+
* with no `lib/` sibling to import from once installed.
|
|
253
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
254
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
255
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
256
|
+
*/
|
|
257
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
258
|
+
if (!argv1) return false;
|
|
259
|
+
try {
|
|
260
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
261
|
+
} catch {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (invokedAsScript(import.meta.url)) {
|
|
243
267
|
try {
|
|
244
268
|
main();
|
|
245
269
|
} catch (err) {
|
|
@@ -115,6 +115,28 @@ function main() {
|
|
|
115
115
|
console.log(`\n${rows.length} secret(s). Values are never printed.`);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Whether this module is the one node was asked to run.
|
|
120
|
+
*
|
|
121
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
122
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
123
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
124
|
+
*
|
|
125
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
126
|
+
* with no `lib/` sibling to import from once installed.
|
|
127
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
128
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
129
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
130
|
+
*/
|
|
131
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
132
|
+
if (!argv1) return false;
|
|
133
|
+
try {
|
|
134
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
135
|
+
} catch {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (invokedAsScript(import.meta.url)) {
|
|
119
141
|
main();
|
|
120
142
|
}
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
} from "node:fs";
|
|
31
31
|
import { homedir } from "node:os";
|
|
32
32
|
import { join } from "node:path";
|
|
33
|
+
import { fileURLToPath } from "node:url";
|
|
33
34
|
|
|
34
35
|
import {
|
|
35
36
|
BOOTSTRAP_KEY,
|
|
@@ -454,7 +455,29 @@ function main() {
|
|
|
454
455
|
}
|
|
455
456
|
}
|
|
456
457
|
|
|
457
|
-
|
|
458
|
+
/**
|
|
459
|
+
* Whether this module is the one node was asked to run.
|
|
460
|
+
*
|
|
461
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
462
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
463
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
464
|
+
*
|
|
465
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
466
|
+
* with no `lib/` sibling to import from once installed.
|
|
467
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
468
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
469
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
470
|
+
*/
|
|
471
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
472
|
+
if (!argv1) return false;
|
|
473
|
+
try {
|
|
474
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
475
|
+
} catch {
|
|
476
|
+
return false;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (invokedAsScript(import.meta.url)) {
|
|
458
481
|
try {
|
|
459
482
|
main();
|
|
460
483
|
} catch (err) {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* @module read-secret-note
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
16
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
17
|
+
import { fileURLToPath } from "node:url";
|
|
17
18
|
|
|
18
19
|
import { materializedPaths, readConfig } from "./surfaces.mjs";
|
|
19
20
|
|
|
@@ -72,7 +73,29 @@ function main() {
|
|
|
72
73
|
console.log(noteFor(name, loadNotes(notesFile)));
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Whether this module is the one node was asked to run.
|
|
78
|
+
*
|
|
79
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
80
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
81
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
82
|
+
*
|
|
83
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
84
|
+
* with no `lib/` sibling to import from once installed.
|
|
85
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
86
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
87
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
88
|
+
*/
|
|
89
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
90
|
+
if (!argv1) return false;
|
|
91
|
+
try {
|
|
92
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (invokedAsScript(import.meta.url)) {
|
|
76
99
|
try {
|
|
77
100
|
main();
|
|
78
101
|
} catch (err) {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
* @module resolve-secret
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
30
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
31
|
+
import { fileURLToPath } from "node:url";
|
|
31
32
|
|
|
32
33
|
import { parseEnv } from "./envfile.mjs";
|
|
33
34
|
import { validateNote } from "./note-format.mjs";
|
|
@@ -252,7 +253,29 @@ function main() {
|
|
|
252
253
|
);
|
|
253
254
|
}
|
|
254
255
|
|
|
255
|
-
|
|
256
|
+
/**
|
|
257
|
+
* Whether this module is the one node was asked to run.
|
|
258
|
+
*
|
|
259
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
260
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
261
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
262
|
+
*
|
|
263
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
264
|
+
* with no `lib/` sibling to import from once installed.
|
|
265
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
266
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
267
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
268
|
+
*/
|
|
269
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
270
|
+
if (!argv1) return false;
|
|
271
|
+
try {
|
|
272
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
273
|
+
} catch {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (invokedAsScript(import.meta.url)) {
|
|
256
279
|
try {
|
|
257
280
|
main();
|
|
258
281
|
} catch (err) {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
* @module rotate-secret
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import { readFileSync } from "node:fs";
|
|
30
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
31
|
+
import { fileURLToPath } from "node:url";
|
|
31
32
|
import { hostname } from "node:os";
|
|
32
33
|
|
|
33
34
|
import {
|
|
@@ -264,7 +265,29 @@ function main() {
|
|
|
264
265
|
);
|
|
265
266
|
}
|
|
266
267
|
|
|
267
|
-
|
|
268
|
+
/**
|
|
269
|
+
* Whether this module is the one node was asked to run.
|
|
270
|
+
*
|
|
271
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
272
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
273
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
274
|
+
*
|
|
275
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
276
|
+
* with no `lib/` sibling to import from once installed.
|
|
277
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
278
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
279
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
280
|
+
*/
|
|
281
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
282
|
+
if (!argv1) return false;
|
|
283
|
+
try {
|
|
284
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
285
|
+
} catch {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (invokedAsScript(import.meta.url)) {
|
|
268
291
|
try {
|
|
269
292
|
main();
|
|
270
293
|
} catch (err) {
|
|
@@ -48,6 +48,8 @@
|
|
|
48
48
|
*/
|
|
49
49
|
|
|
50
50
|
import { execFileSync } from "node:child_process";
|
|
51
|
+
import { fileURLToPath } from "node:url";
|
|
52
|
+
import { realpathSync } from "node:fs";
|
|
51
53
|
|
|
52
54
|
import { ENV_KEY, fetchAll } from "./providers.mjs";
|
|
53
55
|
import { readConfig } from "./surfaces.mjs";
|
|
@@ -471,7 +473,29 @@ function main() {
|
|
|
471
473
|
);
|
|
472
474
|
}
|
|
473
475
|
|
|
474
|
-
|
|
476
|
+
/**
|
|
477
|
+
* Whether this module is the one node was asked to run.
|
|
478
|
+
*
|
|
479
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
480
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
481
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
482
|
+
*
|
|
483
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
484
|
+
* with no `lib/` sibling to import from once installed.
|
|
485
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
486
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
487
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
488
|
+
*/
|
|
489
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
490
|
+
if (!argv1) return false;
|
|
491
|
+
try {
|
|
492
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
493
|
+
} catch {
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (invokedAsScript(import.meta.url)) {
|
|
475
499
|
try {
|
|
476
500
|
main();
|
|
477
501
|
} catch (err) {
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
* @module validate-config
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
19
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
20
|
+
import { fileURLToPath } from "node:url";
|
|
20
21
|
import { join } from "node:path";
|
|
21
22
|
|
|
22
23
|
import { SURFACES as SURFACE_CAPABILITIES } from "./surfaces.mjs";
|
|
@@ -517,7 +518,29 @@ function main() {
|
|
|
517
518
|
throw new Error(`${problems.length} configuration problem(s)`);
|
|
518
519
|
}
|
|
519
520
|
|
|
520
|
-
|
|
521
|
+
/**
|
|
522
|
+
* Whether this module is the one node was asked to run.
|
|
523
|
+
*
|
|
524
|
+
* Both sides are realpath'd: a raw URL comparison answers "no" through a
|
|
525
|
+
* symlinked checkout, a git worktree, or a /tmp path on macOS, so the module
|
|
526
|
+
* loads, runs nothing and exits 0 — a silent no-op that reads as success.
|
|
527
|
+
*
|
|
528
|
+
* A local copy rather than an import: plugin payload scripts ship standalone,
|
|
529
|
+
* with no `lib/` sibling to import from once installed.
|
|
530
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
531
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
532
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
533
|
+
*/
|
|
534
|
+
function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
535
|
+
if (!argv1) return false;
|
|
536
|
+
try {
|
|
537
|
+
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
|
|
538
|
+
} catch {
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
if (invokedAsScript(import.meta.url)) {
|
|
521
544
|
try {
|
|
522
545
|
main();
|
|
523
546
|
} catch (err) {
|