@codyswann/lisa 2.333.2 → 2.334.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +4 -2
- 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-drive-pr-to-merge/SKILL.md +12 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +113 -3
- package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +12 -3
- package/plugins/lisa/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +113 -3
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +12 -3
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +113 -3
- 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-drive-pr-to-merge/SKILL.md +12 -3
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +113 -3
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +12 -3
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +113 -3
- 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-drive-pr-to-merge/SKILL.md +12 -3
- package/plugins/src/base/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +113 -3
|
@@ -191,6 +191,38 @@ export function installProfileSourcing(valuesFile, options = {}) {
|
|
|
191
191
|
* @param {object} [options] Home directory and file seams, for tests.
|
|
192
192
|
* @returns {string[]} The profile names written.
|
|
193
193
|
*/
|
|
194
|
+
/**
|
|
195
|
+
* Profile names already defined OUTSIDE this module's managed block.
|
|
196
|
+
*
|
|
197
|
+
* Only what lies outside the block counts: our own previous output is meant to
|
|
198
|
+
* be replaced, and treating it as a collision would make the second run fail.
|
|
199
|
+
* @param {string} dir The `.aws` directory.
|
|
200
|
+
* @param {string[]} names Profile names about to be written.
|
|
201
|
+
* @param {object} io `exists` and `read` seams.
|
|
202
|
+
* @returns {string[]} Colliding names, in the order given.
|
|
203
|
+
*/
|
|
204
|
+
export function collidingProfiles(dir, names, io = {}) {
|
|
205
|
+
const { exists = existsSync, read = readFileSync } = io;
|
|
206
|
+
const file = join(dir, "config");
|
|
207
|
+
if (!exists(file)) return [];
|
|
208
|
+
|
|
209
|
+
const text = String(read(file, "utf8"));
|
|
210
|
+
const start = text.indexOf(MANAGED_MARKER);
|
|
211
|
+
const endAt = start === -1 ? -1 : text.indexOf(MANAGED_END, start);
|
|
212
|
+
const outside =
|
|
213
|
+
start === -1
|
|
214
|
+
? text
|
|
215
|
+
: text.slice(0, start) +
|
|
216
|
+
(endAt === -1 ? "" : text.slice(endAt + MANAGED_END.length));
|
|
217
|
+
|
|
218
|
+
return names.filter(name =>
|
|
219
|
+
new RegExp(
|
|
220
|
+
`^\\s*\\[profile\\s+${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*\\]`,
|
|
221
|
+
"m"
|
|
222
|
+
).test(outside)
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
194
226
|
export function installAwsProfiles(bundle, options = {}) {
|
|
195
227
|
const {
|
|
196
228
|
home = process.env.HOME || homedir(),
|
|
@@ -205,6 +237,33 @@ export function installAwsProfiles(bundle, options = {}) {
|
|
|
205
237
|
if (!rendered) return [];
|
|
206
238
|
|
|
207
239
|
const dir = join(home, ".aws");
|
|
240
|
+
|
|
241
|
+
// Refuse to write a profile name the operator already uses outside our block.
|
|
242
|
+
//
|
|
243
|
+
// AWS does not error on a duplicate `[profile x]` — it resolves one and
|
|
244
|
+
// ignores the other. So writing `tunnl-dev` next to an operator's existing SSO
|
|
245
|
+
// `tunnl-dev` would silently run some calls as the wrong identity, which is
|
|
246
|
+
// worse than either winning outright. Merging protects their sections from
|
|
247
|
+
// being deleted; this protects them from being shadowed.
|
|
248
|
+
//
|
|
249
|
+
// Deliberately not resolved by renaming theirs: this module writes its own
|
|
250
|
+
// block and nothing else. The operator renames (conventionally to `-sso`) and
|
|
251
|
+
// re-runs.
|
|
252
|
+
const collisions = collidingProfiles(dir, rendered.profiles, {
|
|
253
|
+
exists,
|
|
254
|
+
read,
|
|
255
|
+
});
|
|
256
|
+
if (collisions.length > 0) {
|
|
257
|
+
throw new Error(
|
|
258
|
+
`~/.aws/config already defines ${collisions.map(n => `"${n}"`).join(", ")} ` +
|
|
259
|
+
`outside the lisa-managed block.\n` +
|
|
260
|
+
`Writing them would create duplicate sections, and AWS resolves only ` +
|
|
261
|
+
`one — some calls would silently use the wrong identity.\n` +
|
|
262
|
+
`Rename the existing entries (for example to "${collisions[0]}-sso") ` +
|
|
263
|
+
`and run this again.`
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
208
267
|
mkdir(dir, { recursive: true, mode: 0o700 });
|
|
209
268
|
chmod(dir, 0o700);
|
|
210
269
|
|
|
@@ -297,6 +356,47 @@ export function materialize(cfg = readConfig()) {
|
|
|
297
356
|
|
|
298
357
|
function main() {
|
|
299
358
|
const cfg = readConfig();
|
|
359
|
+
|
|
360
|
+
// `--aws-profiles-only` writes ~/.aws and NOTHING else, on any surface.
|
|
361
|
+
//
|
|
362
|
+
// A laptop refuses to materialize secrets to disk, deliberately: read-through
|
|
363
|
+
// to the provider adds no drift and leaves no copy. That rule is about the
|
|
364
|
+
// thirteen values in secrets.env, and it stays exactly as it was here.
|
|
365
|
+
//
|
|
366
|
+
// The AWS profiles are a different bargain, requested explicitly. Agents
|
|
367
|
+
// working on a developer's machine should act as RemoteAgent rather than
|
|
368
|
+
// borrowing the human's SSO identity — separate attribution in CloudTrail,
|
|
369
|
+
// the role's blast radius instead of a person's, and the same `agent-*`
|
|
370
|
+
// profile names as a container so a script does not need two vocabularies.
|
|
371
|
+
//
|
|
372
|
+
// The cost is real and belongs in the open: `source_profile` needs a
|
|
373
|
+
// long-lived key pair, so this writes one to a machine that is not
|
|
374
|
+
// disposable, which is the thing the local surface otherwise prevents. It is
|
|
375
|
+
// therefore opt-in per run, never automatic, and never part of a normal
|
|
376
|
+
// materialize.
|
|
377
|
+
if (process.argv.includes("--aws-profiles-only")) {
|
|
378
|
+
const selected = fetchAll(cfg);
|
|
379
|
+
const bundle = parseBootstrap(selected.get(BOOTSTRAP_KEY)?.value);
|
|
380
|
+
const written = installAwsProfiles(bundle);
|
|
381
|
+
|
|
382
|
+
if (written.length === 0) {
|
|
383
|
+
console.log(
|
|
384
|
+
`no AWS profiles written — ${BOOTSTRAP_KEY} is absent, unparseable, ` +
|
|
385
|
+
`or declares no profile carrying a roleArn.`
|
|
386
|
+
);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
console.log(
|
|
390
|
+
`wrote ${written.length} AWS profile(s): ${written.join(", ")}`
|
|
391
|
+
);
|
|
392
|
+
console.log(
|
|
393
|
+
` Sourced from a long-lived key pair in ~/.aws/credentials. Existing\n` +
|
|
394
|
+
` sections were preserved — only the lisa-managed block was replaced.\n` +
|
|
395
|
+
` Use them explicitly: aws --profile ${written[0]} ...`
|
|
396
|
+
);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
300
400
|
if (process.argv.includes("--dry-run")) {
|
|
301
401
|
const selected = fetchAll(cfg);
|
|
302
402
|
// Derive here too, or the preview lies in the one place it matters most:
|
|
@@ -314,10 +414,20 @@ function main() {
|
|
|
314
414
|
const { count, derived, dir } = materialize(cfg);
|
|
315
415
|
console.log(`materialized ${count} secret(s) and their notes into ${dir}`);
|
|
316
416
|
if (derived > 0) {
|
|
317
|
-
//
|
|
417
|
+
// Do not claim an override this does not perform.
|
|
418
|
+
//
|
|
419
|
+
// This line used to end "overriding any ambient value". That was true when
|
|
420
|
+
// the key pair was exported and stopped being true when the pair moved into
|
|
421
|
+
// ~/.aws and AWS_PROFILE took its place — AWS_PROFILE loses to ambient
|
|
422
|
+
// environment credentials, it does not beat them. The stale sentence sent
|
|
423
|
+
// two separate investigations after a credential problem that did not
|
|
424
|
+
// exist, while the real fault was that nothing sourced the file. A message
|
|
425
|
+
// that overclaims costs more than no message.
|
|
318
426
|
console.log(
|
|
319
|
-
` ${derived} AWS variable(s) derived from the bootstrap bundle
|
|
320
|
-
`
|
|
427
|
+
` ${derived} AWS variable(s) derived from the bootstrap bundle. ` +
|
|
428
|
+
`These take\n effect only in a shell that sourced the materialized ` +
|
|
429
|
+
`env file; ambient\n credentials outrank AWS_PROFILE, so prefer an ` +
|
|
430
|
+
`explicit --profile.`
|
|
321
431
|
);
|
|
322
432
|
}
|
|
323
433
|
}
|
|
@@ -14,9 +14,18 @@ merges" loop. Other skills delegate here instead of re-implementing it. Runs
|
|
|
14
14
|
|
|
15
15
|
- `pr=<number|url>` — the PR to drive. Default: the PR for the current branch
|
|
16
16
|
(`gh pr view --json number,url,baseRefName,headRefName,state`).
|
|
17
|
-
- `merge_method=<merge
|
|
18
|
-
fallback. Default
|
|
19
|
-
`chore(release): X.Y.Z [skip ci]`
|
|
17
|
+
- `merge_method=<merge>` — strategy for both auto-merge and the direct-merge
|
|
18
|
+
fallback. Default and only accepted value: `merge`.
|
|
19
|
+
- **Never squash** — squashing flattens `chore(release): X.Y.Z [skip ci]`
|
|
20
|
+
commits and breaks release promotion detection.
|
|
21
|
+
- **Never rebase.** REJECT `merge_method=rebase` up front with a clear message
|
|
22
|
+
rather than accepting it and verifying it wrongly. GitHub's rebase-and-merge
|
|
23
|
+
rewrites the commits — new SHAs — and creates no merge commit, so the
|
|
24
|
+
shipped-verification in section 3 cannot succeed: `verify_commit` is the
|
|
25
|
+
pre-rebase SHA and is not an ancestor of the base branch afterwards, and the
|
|
26
|
+
merge-parent assertion has nothing to assert against. A successful merge
|
|
27
|
+
would then report as a FAILED verification and drive a false fix-forward,
|
|
28
|
+
which is worse than refusing the input. See CodySwannGT/lisa#2316.
|
|
20
29
|
- `verify_commit=<sha>` — the commit that MUST end up in the merged base (for the
|
|
21
30
|
ancestry check). Default: the PR head at the time this skill starts.
|
|
22
31
|
- `auto_merge=<true|false>` — whether this skill is allowed to merge the PR at
|
|
@@ -191,6 +191,38 @@ export function installProfileSourcing(valuesFile, options = {}) {
|
|
|
191
191
|
* @param {object} [options] Home directory and file seams, for tests.
|
|
192
192
|
* @returns {string[]} The profile names written.
|
|
193
193
|
*/
|
|
194
|
+
/**
|
|
195
|
+
* Profile names already defined OUTSIDE this module's managed block.
|
|
196
|
+
*
|
|
197
|
+
* Only what lies outside the block counts: our own previous output is meant to
|
|
198
|
+
* be replaced, and treating it as a collision would make the second run fail.
|
|
199
|
+
* @param {string} dir The `.aws` directory.
|
|
200
|
+
* @param {string[]} names Profile names about to be written.
|
|
201
|
+
* @param {object} io `exists` and `read` seams.
|
|
202
|
+
* @returns {string[]} Colliding names, in the order given.
|
|
203
|
+
*/
|
|
204
|
+
export function collidingProfiles(dir, names, io = {}) {
|
|
205
|
+
const { exists = existsSync, read = readFileSync } = io;
|
|
206
|
+
const file = join(dir, "config");
|
|
207
|
+
if (!exists(file)) return [];
|
|
208
|
+
|
|
209
|
+
const text = String(read(file, "utf8"));
|
|
210
|
+
const start = text.indexOf(MANAGED_MARKER);
|
|
211
|
+
const endAt = start === -1 ? -1 : text.indexOf(MANAGED_END, start);
|
|
212
|
+
const outside =
|
|
213
|
+
start === -1
|
|
214
|
+
? text
|
|
215
|
+
: text.slice(0, start) +
|
|
216
|
+
(endAt === -1 ? "" : text.slice(endAt + MANAGED_END.length));
|
|
217
|
+
|
|
218
|
+
return names.filter(name =>
|
|
219
|
+
new RegExp(
|
|
220
|
+
`^\\s*\\[profile\\s+${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*\\]`,
|
|
221
|
+
"m"
|
|
222
|
+
).test(outside)
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
194
226
|
export function installAwsProfiles(bundle, options = {}) {
|
|
195
227
|
const {
|
|
196
228
|
home = process.env.HOME || homedir(),
|
|
@@ -205,6 +237,33 @@ export function installAwsProfiles(bundle, options = {}) {
|
|
|
205
237
|
if (!rendered) return [];
|
|
206
238
|
|
|
207
239
|
const dir = join(home, ".aws");
|
|
240
|
+
|
|
241
|
+
// Refuse to write a profile name the operator already uses outside our block.
|
|
242
|
+
//
|
|
243
|
+
// AWS does not error on a duplicate `[profile x]` — it resolves one and
|
|
244
|
+
// ignores the other. So writing `tunnl-dev` next to an operator's existing SSO
|
|
245
|
+
// `tunnl-dev` would silently run some calls as the wrong identity, which is
|
|
246
|
+
// worse than either winning outright. Merging protects their sections from
|
|
247
|
+
// being deleted; this protects them from being shadowed.
|
|
248
|
+
//
|
|
249
|
+
// Deliberately not resolved by renaming theirs: this module writes its own
|
|
250
|
+
// block and nothing else. The operator renames (conventionally to `-sso`) and
|
|
251
|
+
// re-runs.
|
|
252
|
+
const collisions = collidingProfiles(dir, rendered.profiles, {
|
|
253
|
+
exists,
|
|
254
|
+
read,
|
|
255
|
+
});
|
|
256
|
+
if (collisions.length > 0) {
|
|
257
|
+
throw new Error(
|
|
258
|
+
`~/.aws/config already defines ${collisions.map(n => `"${n}"`).join(", ")} ` +
|
|
259
|
+
`outside the lisa-managed block.\n` +
|
|
260
|
+
`Writing them would create duplicate sections, and AWS resolves only ` +
|
|
261
|
+
`one — some calls would silently use the wrong identity.\n` +
|
|
262
|
+
`Rename the existing entries (for example to "${collisions[0]}-sso") ` +
|
|
263
|
+
`and run this again.`
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
208
267
|
mkdir(dir, { recursive: true, mode: 0o700 });
|
|
209
268
|
chmod(dir, 0o700);
|
|
210
269
|
|
|
@@ -297,6 +356,47 @@ export function materialize(cfg = readConfig()) {
|
|
|
297
356
|
|
|
298
357
|
function main() {
|
|
299
358
|
const cfg = readConfig();
|
|
359
|
+
|
|
360
|
+
// `--aws-profiles-only` writes ~/.aws and NOTHING else, on any surface.
|
|
361
|
+
//
|
|
362
|
+
// A laptop refuses to materialize secrets to disk, deliberately: read-through
|
|
363
|
+
// to the provider adds no drift and leaves no copy. That rule is about the
|
|
364
|
+
// thirteen values in secrets.env, and it stays exactly as it was here.
|
|
365
|
+
//
|
|
366
|
+
// The AWS profiles are a different bargain, requested explicitly. Agents
|
|
367
|
+
// working on a developer's machine should act as RemoteAgent rather than
|
|
368
|
+
// borrowing the human's SSO identity — separate attribution in CloudTrail,
|
|
369
|
+
// the role's blast radius instead of a person's, and the same `agent-*`
|
|
370
|
+
// profile names as a container so a script does not need two vocabularies.
|
|
371
|
+
//
|
|
372
|
+
// The cost is real and belongs in the open: `source_profile` needs a
|
|
373
|
+
// long-lived key pair, so this writes one to a machine that is not
|
|
374
|
+
// disposable, which is the thing the local surface otherwise prevents. It is
|
|
375
|
+
// therefore opt-in per run, never automatic, and never part of a normal
|
|
376
|
+
// materialize.
|
|
377
|
+
if (process.argv.includes("--aws-profiles-only")) {
|
|
378
|
+
const selected = fetchAll(cfg);
|
|
379
|
+
const bundle = parseBootstrap(selected.get(BOOTSTRAP_KEY)?.value);
|
|
380
|
+
const written = installAwsProfiles(bundle);
|
|
381
|
+
|
|
382
|
+
if (written.length === 0) {
|
|
383
|
+
console.log(
|
|
384
|
+
`no AWS profiles written — ${BOOTSTRAP_KEY} is absent, unparseable, ` +
|
|
385
|
+
`or declares no profile carrying a roleArn.`
|
|
386
|
+
);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
console.log(
|
|
390
|
+
`wrote ${written.length} AWS profile(s): ${written.join(", ")}`
|
|
391
|
+
);
|
|
392
|
+
console.log(
|
|
393
|
+
` Sourced from a long-lived key pair in ~/.aws/credentials. Existing\n` +
|
|
394
|
+
` sections were preserved — only the lisa-managed block was replaced.\n` +
|
|
395
|
+
` Use them explicitly: aws --profile ${written[0]} ...`
|
|
396
|
+
);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
300
400
|
if (process.argv.includes("--dry-run")) {
|
|
301
401
|
const selected = fetchAll(cfg);
|
|
302
402
|
// Derive here too, or the preview lies in the one place it matters most:
|
|
@@ -314,10 +414,20 @@ function main() {
|
|
|
314
414
|
const { count, derived, dir } = materialize(cfg);
|
|
315
415
|
console.log(`materialized ${count} secret(s) and their notes into ${dir}`);
|
|
316
416
|
if (derived > 0) {
|
|
317
|
-
//
|
|
417
|
+
// Do not claim an override this does not perform.
|
|
418
|
+
//
|
|
419
|
+
// This line used to end "overriding any ambient value". That was true when
|
|
420
|
+
// the key pair was exported and stopped being true when the pair moved into
|
|
421
|
+
// ~/.aws and AWS_PROFILE took its place — AWS_PROFILE loses to ambient
|
|
422
|
+
// environment credentials, it does not beat them. The stale sentence sent
|
|
423
|
+
// two separate investigations after a credential problem that did not
|
|
424
|
+
// exist, while the real fault was that nothing sourced the file. A message
|
|
425
|
+
// that overclaims costs more than no message.
|
|
318
426
|
console.log(
|
|
319
|
-
` ${derived} AWS variable(s) derived from the bootstrap bundle
|
|
320
|
-
`
|
|
427
|
+
` ${derived} AWS variable(s) derived from the bootstrap bundle. ` +
|
|
428
|
+
`These take\n effect only in a shell that sourced the materialized ` +
|
|
429
|
+
`env file; ambient\n credentials outrank AWS_PROFILE, so prefer an ` +
|
|
430
|
+
`explicit --profile.`
|
|
321
431
|
);
|
|
322
432
|
}
|
|
323
433
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.334.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.334.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.334.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.334.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.334.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|