@codyswann/lisa 4.82.4 → 4.83.1

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 (131) hide show
  1. package/dist/configs/eslint/slow-expo.d.ts +17 -0
  2. package/dist/configs/eslint/slow-expo.d.ts.map +1 -0
  3. package/dist/configs/eslint/slow-expo.js +54 -0
  4. package/dist/configs/eslint/slow-expo.js.map +1 -0
  5. package/dist/configs/eslint/slow.d.ts.map +1 -1
  6. package/dist/configs/eslint/slow.js +3 -0
  7. package/dist/configs/eslint/slow.js.map +1 -1
  8. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  9. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  10. package/dist/core/upstream-evidence-manifest.js +14 -9
  11. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  12. package/expo/copy-overwrite/eslint.slow.config.ts +2 -2
  13. package/expo/package-lisa/package.lisa.json +1 -0
  14. package/package.json +7 -5
  15. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  17. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/validate-config.mjs +4 -1
  18. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-setup.mjs +7 -6
  19. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-usage.mjs +4 -3
  20. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/config.mjs +8 -4
  21. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/repo-detect.mjs +40 -2
  22. package/plugins/lisa/.codex-plugin/skills/lisa-setup-session-manager/SKILL.md +7 -5
  23. package/plugins/lisa/rules/reference/config-resolution.md +3 -2
  24. package/plugins/lisa/skills/lisa-secrets-access/scripts/validate-config.mjs +4 -1
  25. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-setup.mjs +7 -6
  26. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-usage.mjs +4 -3
  27. package/plugins/lisa/skills/lisa-session-manager/scripts/config.mjs +8 -4
  28. package/plugins/lisa/skills/lisa-session-manager/scripts/repo-detect.mjs +40 -2
  29. package/plugins/lisa/skills/lisa-setup-session-manager/SKILL.md +7 -5
  30. package/plugins/lisa-agy/plugin.json +1 -1
  31. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/validate-config.mjs +4 -1
  32. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-setup.mjs +7 -6
  33. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-usage.mjs +4 -3
  34. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/config.mjs +8 -4
  35. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/repo-detect.mjs +40 -2
  36. package/plugins/lisa-agy/skills/lisa-setup-session-manager/SKILL.md +7 -5
  37. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  40. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-cdk-devin/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +1 -1
  44. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-copilot/rules/reference/config-resolution.md +3 -2
  46. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/validate-config.mjs +4 -1
  47. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-setup.mjs +7 -6
  48. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-usage.mjs +4 -3
  49. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/config.mjs +8 -4
  50. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/repo-detect.mjs +40 -2
  51. package/plugins/lisa-copilot/skills/lisa-setup-session-manager/SKILL.md +7 -5
  52. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +3 -2
  54. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/validate-config.mjs +4 -1
  55. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-setup.mjs +7 -6
  56. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-usage.mjs +4 -3
  57. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/config.mjs +8 -4
  58. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/repo-detect.mjs +40 -2
  59. package/plugins/lisa-cursor/skills/lisa-setup-session-manager/SKILL.md +7 -5
  60. package/plugins/lisa-devin/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-devin/.devin-plugin/plugin.json +1 -1
  62. package/plugins/lisa-devin/rules/reference/config-resolution.md +3 -2
  63. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/validate-config.mjs +4 -1
  64. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-setup.mjs +7 -6
  65. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-usage.mjs +4 -3
  66. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/config.mjs +8 -4
  67. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/repo-detect.mjs +40 -2
  68. package/plugins/lisa-devin/skills/lisa-setup-session-manager/SKILL.md +7 -5
  69. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  71. package/plugins/lisa-expo-agy/plugin.json +1 -1
  72. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-expo-devin/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +1 -1
  76. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  78. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  79. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-harper-fabric-devin/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +1 -1
  83. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  85. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  86. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-nestjs-devin/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +1 -1
  90. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  92. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  93. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  95. package/plugins/lisa-openclaw-devin/.claude-plugin/plugin.json +1 -1
  96. package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +1 -1
  97. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  98. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  99. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  100. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  101. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  102. package/plugins/lisa-phaser-devin/.claude-plugin/plugin.json +1 -1
  103. package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +1 -1
  104. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  105. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  106. package/plugins/lisa-rails-agy/plugin.json +1 -1
  107. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  108. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  109. package/plugins/lisa-rails-devin/.claude-plugin/plugin.json +1 -1
  110. package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +1 -1
  111. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  112. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  113. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  114. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  115. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  116. package/plugins/lisa-typescript-devin/.claude-plugin/plugin.json +1 -1
  117. package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +1 -1
  118. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  119. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  120. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  121. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  122. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  123. package/plugins/lisa-wiki-devin/.claude-plugin/plugin.json +1 -1
  124. package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +1 -1
  125. package/plugins/src/base/rules/reference/config-resolution.md +3 -2
  126. package/plugins/src/base/skills/lisa-secrets-access/scripts/validate-config.mjs +4 -1
  127. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-setup.mjs +7 -6
  128. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-usage.mjs +4 -3
  129. package/plugins/src/base/skills/lisa-session-manager/scripts/config.mjs +8 -4
  130. package/plugins/src/base/skills/lisa-session-manager/scripts/repo-detect.mjs +40 -2
  131. package/plugins/src/base/skills/lisa-setup-session-manager/SKILL.md +7 -5
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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": "4.82.4",
3
+ "version": "4.83.1",
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"
@@ -696,7 +696,8 @@ claims Ready leaf items and runs each one as `/lisa:implement` in a fresh backgr
696
696
  session. It is **opt-in**: an absent block means no manager, and `lisa sync` never populates it
697
697
  (it is deliberately not in the sync registry, because the manager starts sessions with permissions
698
698
  bypassed). `/lisa:setup:session-manager` writes it, detecting a multi-repo layout from
699
- `projects/*/.lisa.config.json`.
699
+ `projects/*/.lisa.config.json`, or, when `projects/` holds none, from the root's own children that
700
+ have a `.lisa.config.json` and their own `.git` (written as `"root": "."`).
700
701
 
701
702
  ```json
702
703
  "sessionManager": {
@@ -720,7 +721,7 @@ bypassed). `/lisa:setup:session-manager` writes it, detecting a multi-repo layou
720
721
  | `sessionManager.name` | **yes** | — | Manager session name: lowercase letters, digits, `-` or `_`, at most 64 characters. It names the tmux session and the session workers `SendMessage` to. Setup writes `<project>-manager`. |
721
722
  | `sessionManager.interval` | no | `5m` | `/loop` cadence: a positive integer plus `s`, `m`, `h` or `d`. |
722
723
  | `sessionManager.repos` | no | — | Omit for a single-repo project: every item routes to the project root. When present, `entries` must name at least one repo. |
723
- | `sessionManager.repos.root` | no | `projects` | Relative directory holding the child repos. It must stay inside the project. |
724
+ | `sessionManager.repos.root` | no | `projects` | Relative directory holding the child repos. It must stay inside the project. `.` means the repos are direct children of the project root. |
724
725
  | `sessionManager.repos.entries.<key>.hints` | **yes** (per entry) | — | Non-empty list of words the manager matches a work item against to choose the repo. `<key>` is the child directory name (one safe path segment). |
725
726
  | `sessionManager.capacity.maxWorkers` | no | `6` | Hard cap on concurrent workers (a positive integer). Telegram `cap N` overrides it at runtime through the manager's ledger, not config. |
726
727
  | `sessionManager.capacity.gbPerWorker` | no | `3` | Memory budgeted per worker, in GB (positive). |
@@ -552,13 +552,16 @@ function isPlainObject(value) {
552
552
  */
553
553
  function validateReposRoot(root) {
554
554
  if (root === undefined) return [];
555
+ // `.` means the repos are direct children of the project root.
556
+ if (root === ".") return [];
555
557
  const segments = typeof root === "string" ? root.split("/") : [];
556
558
  if (segments.length && segments.every(part => SAFE_SEGMENT.test(part))) {
557
559
  return [];
558
560
  }
559
561
  return [
560
562
  `sessionManager.repos.root ${JSON.stringify(root)} must be a relative ` +
561
- `path inside the project, such as "projects". Workers start there with ` +
563
+ `path inside the project, such as "projects" (or "." for repos at the ` +
564
+ `project root). Workers start there with ` +
562
565
  `permissions bypassed.`,
563
566
  ];
564
567
  }
@@ -19,7 +19,7 @@ import {
19
19
  } from "./cli-runtime.mjs";
20
20
  import {
21
21
  buildDefaultBlock,
22
- detectRepos,
22
+ detectRepoLayout,
23
23
  draftHints,
24
24
  resolveRepoDir,
25
25
  } from "./config.mjs";
@@ -37,8 +37,9 @@ import {
37
37
  * `init-config [--slug <slug>] [--write]`: the default block for this
38
38
  * project, written to `.lisa.config.json` only with `--write` and only when
39
39
  * no block exists. Non-secret fields only; the token never goes here. Repos
40
- * are the routable children `detectRepos` finds (linked worktrees and second
41
- * clones of one remote left out), each with drafted hints.
40
+ * are the routable children `detectRepoLayout` finds under `projects/`, else
41
+ * directly under the root (linked worktrees and second clones of one remote
42
+ * left out), each with drafted hints.
42
43
  * @param {object} ctx - CLI context
43
44
  * @returns {{ json: object }} `{written,block,...}`
44
45
  */
@@ -51,15 +52,15 @@ export function initConfig(ctx) {
51
52
  }
52
53
  const slug =
53
54
  ctx.values.slug ?? defaultProjectSlug(ctx.root, global?.github?.repo);
54
- const detectedRepos = detectRepos(ctx.root);
55
+ const { reposRoot, repos: detectedRepos } = detectRepoLayout(ctx.root);
55
56
  const hints = Object.fromEntries(
56
57
  detectedRepos.map(name => [
57
58
  name,
58
- draftHints(path.join(ctx.root, "projects", name), name),
59
+ draftHints(path.join(ctx.root, reposRoot, name), name),
59
60
  ])
60
61
  );
61
62
  const block = asSetupError(() =>
62
- buildDefaultBlock({ projectSlug: slug, detectedRepos, hints })
63
+ buildDefaultBlock({ projectSlug: slug, detectedRepos, hints, reposRoot })
63
64
  );
64
65
  if (!ctx.values.write) return { json: { written: false, block } };
65
66
 
@@ -82,9 +82,10 @@ Config and routing
82
82
  validate stdout {valid,errors}; exit 2 when invalid or absent.
83
83
  init-config [--slug <slug>] [--write]
84
84
  stdout {written,block[,reason:"exists"][,path]}. Detects
85
- projects/*/.lisa.config.json, skipping linked worktrees (.git is
86
- a file) and keeping one child per origin remote (the one named
87
- after the repo, else the first by name). Each repo's hints are a
85
+ projects/*/.lisa.config.json, else root children with their own
86
+ .lisa.config.json and .git (repos.root "."), skipping linked
87
+ worktrees (.git is a file) and keeping one child per origin
88
+ remote (the one named after the repo, else the first by name). Each repo's hints are a
88
89
  draft: its name, then one per well-known package.json dependency
89
90
  (e.g. @nestjs/* -> NestJS, expo -> Expo, aws-cdk-lib -> AWS CDK).
90
91
  Default slug: <github.repo or folder name>-<first 6 hex of
@@ -25,7 +25,7 @@ import {
25
25
  } from "../../lisa-secrets-access/scripts/validate-config.mjs";
26
26
 
27
27
  export { parseLoopInterval, validateSessionManager };
28
- export { detectRepos, draftHints } from "./repo-detect.mjs";
28
+ export { detectRepoLayout, detectRepos, draftHints } from "./repo-detect.mjs";
29
29
 
30
30
  /**
31
31
  * Documented defaults for every optional key.
@@ -157,15 +157,19 @@ function normalizeSlug(projectSlug) {
157
157
  * no `repos` key, which is what makes a project single-repo. Each detected
158
158
  * repo's hints are its drafted hints when given (`draftHints`), else its own
159
159
  * name: valid either way, and setup asks the operator to review them.
160
+ * `reposRoot` is where the repos were found (`detectRepoLayout`): `projects`
161
+ * by default, or `.` when they sit directly under the project root.
160
162
  * @param {{ projectSlug: string, detectedRepos?: string[],
161
- * hints?: Record<string, string[]> }} input Project slug, the output of
162
- * `detectRepos`, and drafted hints per repo.
163
+ * hints?: Record<string, string[]>, reposRoot?: string }} input Project
164
+ * slug, the output of `detectRepos`, drafted hints per repo, and the repos
165
+ * root they were found under.
163
166
  * @returns {SessionManagerBlock} A block `validateSessionManager` accepts.
164
167
  */
165
168
  export function buildDefaultBlock({
166
169
  projectSlug,
167
170
  detectedRepos = [],
168
171
  hints = {},
172
+ reposRoot = DEFAULT_REPOS_ROOT,
169
173
  }) {
170
174
  const slug = normalizeSlug(projectSlug);
171
175
  const repos = [...detectedRepos].sort();
@@ -175,7 +179,7 @@ export function buildDefaultBlock({
175
179
  ...(repos.length > 0
176
180
  ? {
177
181
  repos: {
178
- root: DEFAULT_REPOS_ROOT,
182
+ root: reposRoot,
179
183
  entries: Object.fromEntries(
180
184
  repos.map(name => [
181
185
  name,
@@ -11,6 +11,13 @@
11
11
  * ticket worktree builds on the wrong branch, so the detector keeps one
12
12
  * checkout per remote: the one named after the repo when there is one.
13
13
  *
14
+ * Not every multi-repo host has a `projects/` dir: some keep each repo as a
15
+ * direct child of the project root (`api/`, `web/`, `infra/`). Setup checks
16
+ * `projects/` first and falls back to the root's own children. At the root a
17
+ * child must also be its own checkout (it has a `.git`): a folder of a
18
+ * single-repo project that happens to hold a `.lisa.config.json` is part of
19
+ * that repo, not a repo to route workers into.
20
+ *
14
21
  * Every filesystem call goes through an injectable seam.
15
22
  * @module session-manager/repo-detect
16
23
  */
@@ -152,8 +159,9 @@ function onePerRemote(children) {
152
159
  * run `/lisa:implement` inside it, which needs that file), is not a linked
153
160
  * worktree, and is the chosen checkout of its remote.
154
161
  * @param {string} root - Project root
155
- * @param {{ reposRoot?: string, fs?: Partial<typeof NODE_FS> }} [options] -
156
- * Repos root (default `projects`) and filesystem seam
162
+ * @param {{ reposRoot?: string, requireGit?: boolean,
163
+ * fs?: Partial<typeof NODE_FS> }} [options] - Repos root (default
164
+ * `projects`), whether a child needs its own `.git`, and filesystem seam
157
165
  * @returns {string[]} Child directory names, sorted
158
166
  */
159
167
  export function detectRepos(root, options = {}) {
@@ -165,6 +173,9 @@ export function detectRepos(root, options = {}) {
165
173
  .filter(entry => entry.isDirectory() && SAFE_SEGMENT.test(entry.name))
166
174
  .map(entry => ({ name: entry.name, dir: join(base, entry.name) }))
167
175
  .filter(child => fs.existsSync(join(child.dir, ".lisa.config.json")))
176
+ .filter(
177
+ child => !options.requireGit || fs.existsSync(join(child.dir, ".git"))
178
+ )
168
179
  .filter(child => !isLinkedWorktree(child.dir, fs))
169
180
  .map(child => ({
170
181
  name: child.name,
@@ -174,6 +185,33 @@ export function detectRepos(root, options = {}) {
174
185
  return onePerRemote(children);
175
186
  }
176
187
 
188
+ /**
189
+ * Where setup looks for child repos, in order. `.` is the root itself, where
190
+ * only children with their own `.git` count.
191
+ */
192
+ const LAYOUT_CANDIDATES = Object.freeze([
193
+ { reposRoot: "projects", requireGit: false },
194
+ { reposRoot: ".", requireGit: true },
195
+ ]);
196
+
197
+ /**
198
+ * Find where a multi-repo project keeps its repos and which ones are routable.
199
+ * The first candidate that yields any repo wins: `projects/`, then the
200
+ * project root's direct children that are their own checkouts. A project
201
+ * where neither yields one is single-repo, reported with the default
202
+ * `projects` root and no repos.
203
+ * @param {string} root - Project root
204
+ * @param {{ fs?: Partial<typeof NODE_FS> }} [options] - Filesystem seam
205
+ * @returns {{ reposRoot: string, repos: string[] }} Repos root and names
206
+ */
207
+ export function detectRepoLayout(root, options = {}) {
208
+ for (const { reposRoot, requireGit } of LAYOUT_CANDIDATES) {
209
+ const repos = detectRepos(root, { ...options, reposRoot, requireGit });
210
+ if (repos.length > 0) return { reposRoot, repos };
211
+ }
212
+ return { reposRoot: LAYOUT_CANDIDATES[0].reposRoot, repos: [] };
213
+ }
214
+
177
215
  /**
178
216
  * Draft routing hints for one child: its name, then a hint per well-known
179
217
  * dependency in its `package.json`. Only a draft; setup asks the operator to
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lisa-setup-session-manager
3
- description: "Set up the local session manager for this project: writes the non-secret `sessionManager` block to `.lisa.config.json` (detecting a multi-repo `projects/*` layout), stores the project's own Telegram bot token outside the repo, checks the Telegram plugin is installed but not enabled at user scope, keeps the manager's state out of git, seeds the checked-in runbook, starts the manager in tmux, walks the operator through pairing, and finishes with doctor's session-manager check. Idempotent."
3
+ description: "Set up the local session manager for this project: writes the non-secret `sessionManager` block to `.lisa.config.json` (detecting a multi-repo layout: repos under `projects/`, or directly under the project root), stores the project's own Telegram bot token outside the repo, checks the Telegram plugin is installed but not enabled at user scope, keeps the manager's state out of git, seeds the checked-in runbook, starts the manager in tmux, walks the operator through pairing, and finishes with doctor's session-manager check. Idempotent."
4
4
  allowed-tools: ["Bash", "Read", "Write", "Skill", "AskUserQuestion"]
5
5
  ---
6
6
 
@@ -41,10 +41,12 @@ writes `$SM`, and pass `--project-root "$ROOT"` (the absolute project root) on e
41
41
  ## Step 2: Write the config block
42
42
 
43
43
  1. Preview: `node "$SM/session-manager.mjs" init-config --project-root "$ROOT"`. It detects
44
- `projects/*/.lisa.config.json` and proposes `name`, `interval`, `repos`, `capacity`, `stall` and a
45
- per-project `notify.stateDir`. Repo detection leaves out linked worktrees and keeps one checkout
46
- per remote, so ticket worktrees and second clones under `projects/` are not proposed. Show the
47
- block to the operator and ask whether any repo is missing or should not be routed.
44
+ `projects/*/.lisa.config.json`, or, when `projects/` holds none, the root's own children that
45
+ have a `.lisa.config.json` and their own `.git` (written as `repos.root: "."`). It proposes
46
+ `name`, `interval`, `repos`, `capacity`, `stall` and a per-project `notify.stateDir`. Repo
47
+ detection leaves out linked worktrees and keeps one checkout per remote, so ticket worktrees and
48
+ second clones are not proposed. Show the block to the operator and ask whether any repo is
49
+ missing or should not be routed.
48
50
  2. Write it: the same command with `--write`. It adds only non-secret fields and never overwrites an
49
51
  existing block (`reason: "exists"` means keep it).
50
52
  3. Each repo's `hints` are a draft: its name plus one per well-known dependency (`NestJS`, `Expo`,