@codyswann/lisa 2.321.4 → 2.322.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.
Files changed (76) hide show
  1. package/dist/core/upstream-evidence-manifest.js +4 -4
  2. package/package.json +1 -1
  3. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  4. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  5. package/plugins/lisa/.codex-plugin/skills/lisa-setup-automations/scripts/generate-workflow.mjs +32 -13
  6. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/SKILL.md +15 -14
  7. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/assets/setup.sh +64 -5
  8. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +27 -67
  9. package/plugins/lisa/skills/lisa-setup-automations/scripts/generate-workflow.mjs +32 -13
  10. package/plugins/lisa/skills/lisa-setup-remote-env/SKILL.md +15 -14
  11. package/plugins/lisa/skills/lisa-setup-remote-env/assets/setup.sh +64 -5
  12. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +27 -67
  13. package/plugins/lisa-agy/plugin.json +1 -1
  14. package/plugins/lisa-agy/skills/lisa-setup-automations/scripts/generate-workflow.mjs +32 -13
  15. package/plugins/lisa-agy/skills/lisa-setup-remote-env/SKILL.md +15 -14
  16. package/plugins/lisa-agy/skills/lisa-setup-remote-env/assets/setup.sh +64 -5
  17. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +27 -67
  18. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  20. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  21. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-copilot/skills/lisa-setup-automations/scripts/generate-workflow.mjs +32 -13
  25. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/SKILL.md +15 -14
  26. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/assets/setup.sh +64 -5
  27. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +27 -67
  28. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-cursor/skills/lisa-setup-automations/scripts/generate-workflow.mjs +32 -13
  30. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/SKILL.md +15 -14
  31. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/assets/setup.sh +64 -5
  32. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +27 -67
  33. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  35. package/plugins/lisa-expo-agy/plugin.json +1 -1
  36. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  40. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  41. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  45. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  46. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  50. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  51. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  55. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  56. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  60. package/plugins/lisa-rails-agy/plugin.json +1 -1
  61. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  65. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  66. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  70. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  71. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  73. package/plugins/src/base/skills/lisa-setup-automations/scripts/generate-workflow.mjs +32 -13
  74. package/plugins/src/base/skills/lisa-setup-remote-env/SKILL.md +15 -14
  75. package/plugins/src/base/skills/lisa-setup-remote-env/assets/setup.sh +64 -5
  76. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +27 -67
@@ -298,6 +298,20 @@ export function installAssets(cwd = process.cwd()) {
298
298
  });
299
299
  }
300
300
 
301
+ /**
302
+ * The setup field, identical for every project.
303
+ *
304
+ * Names neither the repository nor its package manager. Claude Code web runs
305
+ * this field from `$HOME` while the checkout sits one level down, so the glob
306
+ * locates the script; the script then anchors itself on the repository root and
307
+ * installs dependencies from whichever lockfile the project commits.
308
+ *
309
+ * A field that named both was a string a human had to get right, in a settings
310
+ * box with no review, no version history and no test — and the logic it encoded
311
+ * belongs in a file that has all three.
312
+ */
313
+ const SETUP_FIELD = `bash "$HOME"/*/scripts/lisa-remote-env/setup.sh`;
314
+
301
315
  /**
302
316
  * The settings block that wires the session-start hook into a repository.
303
317
  *
@@ -366,12 +380,11 @@ export function pinEnvironment(environmentId, cwd = process.cwd()) {
366
380
  * settings page, no direct URL, and no endpoint. Emit is not a degraded option
367
381
  * here, it is the only one — so the read-back in `verify-remote-env.mjs` is
368
382
  * what makes the result trustworthy, exactly as it would be at any other tier.
369
- * @param {{bootstrapKey: string|null, install: string, repoDir?: string}} options Project details.
383
+ * @param {{bootstrapKey: string|null}} options Project details.
370
384
  * @returns {string} Text to show the operator.
371
385
  */
372
- export function emitClaudeWeb({ bootstrapKey, install, repoDir = "lisa" }) {
386
+ export function emitClaudeWeb({ bootstrapKey }) {
373
387
  const key = bootstrapKey ?? "<secrets.bootstrap.key is not configured>";
374
- const setup = `cd ${shellQuote(repoDir)} && ${install} && bash scripts/lisa-remote-env/setup.sh`;
375
388
  return [
376
389
  "Provisioning tier: EMIT — and for this surface that is the only tier.",
377
390
  " A Claude cloud environment is account-scoped configuration edited in the",
@@ -393,13 +406,17 @@ export function emitClaudeWeb({ bootstrapKey, install, repoDir = "lisa" }) {
393
406
  " is why exactly one value needs to live here.",
394
407
  "",
395
408
  " Setup script:",
396
- ` ${setup}`,
409
+ ` ${SETUP_FIELD}`,
410
+ "",
411
+ " This line is identical for every project — nothing in it names this",
412
+ " repository or its package manager. Claude runs the field from $HOME",
413
+ " while the checkout lives one level down, so the glob is what locates",
414
+ " it; the script then anchors itself and installs dependencies using",
415
+ " whichever lockfile the project actually commits.",
397
416
  "",
398
- ` Claude runs this field from $HOME, while the checkout is $HOME/${repoDir}.`,
399
- " The `cd` must come first, and the install must run before the setup",
400
- " script. On a fresh container node_modules is the only copy of the Lisa",
401
- " skills present, because Claude receives them as an installed plugin",
402
- " rather than as part of the clone.",
417
+ " Keeping it generic is the point. A field that named the repository and",
418
+ " the package manager was a string a human had to get right, in a box",
419
+ " with no review, no version history and no test.",
403
420
  "",
404
421
  "Commit to the repository",
405
422
  "------------------------",
@@ -478,57 +495,6 @@ async function detectSurface() {
478
495
  return { surface, materializeAt: mod.SURFACES[surface].materializeAt };
479
496
  }
480
497
 
481
- /**
482
- * Name the project's own install command rather than inventing one.
483
- *
484
- * The emitted setup line must begin with whatever this project already uses; a
485
- * guessed package manager produces a container that fails on its first command.
486
- * @param {string} [cwd] Repository root.
487
- * @returns {string} The install command to place before the setup script.
488
- */
489
- export function detectInstallCommand(cwd = process.cwd()) {
490
- const lockfiles = [
491
- ["bun.lockb", "bun install"],
492
- ["bun.lock", "bun install"],
493
- ["pnpm-lock.yaml", "pnpm install --frozen-lockfile"],
494
- ["yarn.lock", "yarn install --immutable"],
495
- ["package-lock.json", "npm ci"],
496
- ];
497
- for (const [file, command] of lockfiles) {
498
- if (existsSync(join(cwd, file))) return command;
499
- }
500
- return "<your install command>";
501
- }
502
-
503
- /**
504
- * Name the directory Claude creates under $HOME when it clones this repository.
505
- *
506
- * Claude cloud runs the environment setup field from $HOME, not from the
507
- * checkout. The setup line therefore has to `cd` into the clone before running
508
- * the project install. Prefer the configured GitHub repo name because it is the
509
- * thing Claude clones; fall back to the current directory for non-GitHub tests
510
- * and local dry runs.
511
- * @param {string} [cwd] Repository root.
512
- * @returns {string} Directory name to place after `cd`.
513
- */
514
- export function detectRepositoryDirectory(cwd = process.cwd()) {
515
- const path = join(cwd, ".lisa.config.json");
516
- if (existsSync(path)) {
517
- const repo = JSON.parse(readFileSync(path, "utf8")).github?.repo;
518
- if (repo && !repo.includes("/") && !repo.includes("\0")) return repo;
519
- }
520
- return basename(cwd);
521
- }
522
-
523
- /**
524
- * Quote a value for POSIX shell usage.
525
- * @param {string} value Raw value.
526
- * @returns {string} Single-quoted shell literal.
527
- */
528
- function shellQuote(value) {
529
- return "'" + String(value).replaceAll("'", "'\\''") + "'";
530
- }
531
-
532
498
  /**
533
499
  * Read the bootstrap key name, which is the one value the operator must paste.
534
500
  * @param {string} [cwd] Repository root.
@@ -577,13 +543,7 @@ async function main() {
577
543
  `Emitting is implemented for claude-web, which has no other tier.`
578
544
  );
579
545
  }
580
- console.log(
581
- emitClaudeWeb({
582
- bootstrapKey: readBootstrapKey(),
583
- install: detectInstallCommand(),
584
- repoDir: detectRepositoryDirectory(),
585
- })
586
- );
546
+ console.log(emitClaudeWeb({ bootstrapKey: readBootstrapKey() }));
587
547
  return;
588
548
  }
589
549
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.321.4",
3
+ "version": "2.322.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.321.4",
3
+ "version": "2.322.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.321.4",
3
+ "version": "2.322.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.321.4",
3
+ "version": "2.322.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.321.4",
3
+ "version": "2.322.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-phaser",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.321.4",
3
+ "version": "2.322.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -41,9 +41,20 @@ export function readAutomation(name, cwd = process.cwd()) {
41
41
  `Declare the loop before generating its workflow.`
42
42
  );
43
43
  }
44
+ const surface = cfg.remoteEnv?.surfaces?.[loop.executionEnv];
45
+ const github = cfg.github ?? {};
44
46
  return {
45
47
  ...loop,
46
- repository: cfg.remoteEnv?.surfaces?.[loop.executionEnv]?.repository,
48
+ // Only used for the fork guard, so it is a question about *this* repository
49
+ // rather than about the surface. Read from the surface where one records it
50
+ // — Codex Cloud binds an environment to a repository — and otherwise from
51
+ // the project's own GitHub config. A Claude cloud environment binds no
52
+ // repository at all, and demanding one there asked for a field that cannot
53
+ // exist, which refused to generate a workflow for a correctly configured
54
+ // loop.
55
+ repository:
56
+ surface?.repository ??
57
+ (github.org && github.repo ? `${github.org}/${github.repo}` : undefined),
47
58
  // Where this project keeps its bootstrap. A workstation serving several
48
59
  // tenants gives each its own name, so the generated workflow must template
49
60
  // it rather than assume the default.
@@ -81,12 +92,28 @@ export function renderWorkflow(name, loop) {
81
92
  const bootstrap = loop.bootstrapKey ?? "BWS_ACCESS_TOKEN";
82
93
  if (!loop.repository) {
83
94
  throw new Error(
84
- `automations["${name}"] targets executionEnv "${loop.executionEnv}", ` +
85
- `but no remoteEnv.surfaces["${loop.executionEnv}"].repository is set.\n` +
86
- `Run /lisa:setup:remote-env ${loop.executionEnv} first.`
95
+ `cannot determine which repository this loop belongs to.\n` +
96
+ `The generated workflow guards on it so a fork never dispatches. Set ` +
97
+ `github.org and github.repo in .lisa.config.json.`
87
98
  );
88
99
  }
89
100
 
101
+ // Always emitted, even for a surface whose dispatcher token is not consumed
102
+ // by use. Making it conditional on secrets.rotating would mean a project that
103
+ // later declares one, without regenerating its workflow, silently loses the
104
+ // persist step and strands the replacement. One inert step is the cheaper
105
+ // failure.
106
+ const rotation = `
107
+ # The dispatcher authenticates with a credential that rotates on use, so
108
+ # the replacement must be persisted even when the dispatch itself failed.
109
+ - name: Persist any credential rotation
110
+ if: \${{ always() }}
111
+ env:
112
+ ${bootstrap}: \${{ secrets.${bootstrap} }}
113
+ run: |
114
+ set -euo pipefail
115
+ node .claude/skills/lisa-secrets-access/scripts/rotate-secret.mjs leases`;
116
+
90
117
  const trigger = loop.enabled
91
118
  ? ` schedule:\n - cron: '${loop.schedule}'\n workflow_dispatch:`
92
119
  : ` # schedule: disabled until the production path is proven once for one\n` +
@@ -149,15 +176,7 @@ jobs:
149
176
  'executionEnv=${loop.executionEnv} ${loop.payload ?? ""}' \\
150
177
  --skill ${loop.skill ?? `lisa-${name}`}
151
178
 
152
- # The dispatcher authenticates with a credential that rotates on use, so
153
- # the replacement must be persisted even when the dispatch itself failed.
154
- - name: Persist any credential rotation
155
- if: \${{ always() }}
156
- env:
157
- ${bootstrap}: \${{ secrets.${bootstrap} }}
158
- run: |
159
- set -euo pipefail
160
- node .claude/skills/lisa-secrets-access/scripts/rotate-secret.mjs leases
179
+ ${rotation}
161
180
  `;
162
181
  }
163
182