@nemus-cli/nemus 0.2.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 (320) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/LICENSE +21 -0
  3. package/README.md +275 -0
  4. package/assets/README.md +53 -0
  5. package/assets/banner.png +0 -0
  6. package/assets/banner.svg +66 -0
  7. package/assets/favicon-32.png +0 -0
  8. package/assets/favicon-64.png +0 -0
  9. package/assets/icon-256.png +0 -0
  10. package/assets/icon.svg +23 -0
  11. package/assets/logo-256.png +0 -0
  12. package/assets/logo-512.png +0 -0
  13. package/assets/logo-wordmark.svg +35 -0
  14. package/assets/logo.svg +32 -0
  15. package/bin/workspace.js +130 -0
  16. package/dist/cli/ai-prompt.js +421 -0
  17. package/dist/cli/dashboard/AgentList.js +61 -0
  18. package/dist/cli/dashboard/DashboardSidebar.js +280 -0
  19. package/dist/cli/dashboard/HelpFooter.js +73 -0
  20. package/dist/cli/dashboard/StatusBadge.js +50 -0
  21. package/dist/cli/dashboard/index.js +11 -0
  22. package/dist/cli/dashboard/types.js +2 -0
  23. package/dist/cli/tui.js +48 -0
  24. package/dist/commands/ai-prompt.js +22 -0
  25. package/dist/commands/analyze-deps.js +138 -0
  26. package/dist/commands/archive.js +113 -0
  27. package/dist/commands/branch/create.js +119 -0
  28. package/dist/commands/branch/index.js +104 -0
  29. package/dist/commands/branch/merge.js +90 -0
  30. package/dist/commands/branch/rebase.js +84 -0
  31. package/dist/commands/branch/switch.js +165 -0
  32. package/dist/commands/cache/index.js +80 -0
  33. package/dist/commands/cache/manager.js +198 -0
  34. package/dist/commands/cleanup.js +153 -0
  35. package/dist/commands/configure-claude.js +55 -0
  36. package/dist/commands/configure.js +231 -0
  37. package/dist/commands/create.js +204 -0
  38. package/dist/commands/dashboard/hook-handler.js +162 -0
  39. package/dist/commands/dashboard/index.js +258 -0
  40. package/dist/commands/dashboard/launcher.js +40 -0
  41. package/dist/commands/dashboard/session-picker.js +106 -0
  42. package/dist/commands/dashboard/sidebar.js +39 -0
  43. package/dist/commands/dashboard/workspace-picker.js +95 -0
  44. package/dist/commands/delete.js +194 -0
  45. package/dist/commands/deprecated-aliases.js +44 -0
  46. package/dist/commands/diff.js +129 -0
  47. package/dist/commands/doctor.js +141 -0
  48. package/dist/commands/generate-docs.js +77 -0
  49. package/dist/commands/ghq-status.js +72 -0
  50. package/dist/commands/go.js +154 -0
  51. package/dist/commands/history.js +124 -0
  52. package/dist/commands/list.js +191 -0
  53. package/dist/commands/mcp/index.js +69 -0
  54. package/dist/commands/migrate.js +296 -0
  55. package/dist/commands/remove-repo.js +217 -0
  56. package/dist/commands/report-bug.js +112 -0
  57. package/dist/commands/run.js +147 -0
  58. package/dist/commands/save-context.js +171 -0
  59. package/dist/commands/sessions.js +129 -0
  60. package/dist/commands/status.js +138 -0
  61. package/dist/commands/suite/create.js +212 -0
  62. package/dist/commands/suite/delete.js +64 -0
  63. package/dist/commands/suite/export.js +126 -0
  64. package/dist/commands/suite/import.js +128 -0
  65. package/dist/commands/suite/index.js +94 -0
  66. package/dist/commands/suite/list.js +49 -0
  67. package/dist/commands/suite/use.js +227 -0
  68. package/dist/commands/sync.js +117 -0
  69. package/dist/commands/update.js +203 -0
  70. package/dist/mcp/install.js +550 -0
  71. package/dist/mcp/server.js +398 -0
  72. package/dist/mcp/tools.js +922 -0
  73. package/dist/pi-extensions/permission-sync.ts.template +41 -0
  74. package/dist/pi-extensions/permissions-gate.ts.template +69 -0
  75. package/dist/pi-extensions/pr-fix-trigger.ts.template +124 -0
  76. package/dist/pi-extensions/review-reminder.ts.template +58 -0
  77. package/dist/pi-extensions/workspace-input-status.ts.template +919 -0
  78. package/dist/program.js +136 -0
  79. package/dist/scripts/workspace-table.py +394 -0
  80. package/dist/types/dashboard.js +11 -0
  81. package/dist/types/index.js +2 -0
  82. package/dist/utils/agent-config.js +263 -0
  83. package/dist/utils/agent-state.js +178 -0
  84. package/dist/utils/banner.js +24 -0
  85. package/dist/utils/branch-operations.js +232 -0
  86. package/dist/utils/bug-report.js +355 -0
  87. package/dist/utils/cache.js +168 -0
  88. package/dist/utils/claude-integration.js +617 -0
  89. package/dist/utils/claude-sessions.js +260 -0
  90. package/dist/utils/cleanup-operations.js +120 -0
  91. package/dist/utils/colors.js +26 -0
  92. package/dist/utils/command-helpers.js +44 -0
  93. package/dist/utils/config.js +150 -0
  94. package/dist/utils/context-file.js +33 -0
  95. package/dist/utils/dashboard-hooks.js +172 -0
  96. package/dist/utils/dependency-analyzer.js +234 -0
  97. package/dist/utils/diff-operations.js +80 -0
  98. package/dist/utils/doc-generator.js +184 -0
  99. package/dist/utils/ghq-integration.js +332 -0
  100. package/dist/utils/git-operations.js +237 -0
  101. package/dist/utils/git-status.js +187 -0
  102. package/dist/utils/github.js +68 -0
  103. package/dist/utils/health-checks.js +345 -0
  104. package/dist/utils/history.js +150 -0
  105. package/dist/utils/hooks.js +100 -0
  106. package/dist/utils/logger.js +40 -0
  107. package/dist/utils/permission-sync.js +681 -0
  108. package/dist/utils/pi-extensions.js +224 -0
  109. package/dist/utils/progress.js +92 -0
  110. package/dist/utils/prompts.js +279 -0
  111. package/dist/utils/repo-resolver.js +260 -0
  112. package/dist/utils/retry.js +65 -0
  113. package/dist/utils/run-operations.js +30 -0
  114. package/dist/utils/suite.js +159 -0
  115. package/dist/utils/sync-operations.js +107 -0
  116. package/dist/utils/tmux-dashboard.js +184 -0
  117. package/dist/utils/validation.js +153 -0
  118. package/dist/utils/version-check.js +121 -0
  119. package/dist/utils/workspace-meta.js +185 -0
  120. package/install-shell-integration.sh +532 -0
  121. package/install.sh +401 -0
  122. package/package.json +90 -0
  123. package/remove-shell-block.awk +44 -0
  124. package/scripts/postinstall.js +85 -0
  125. package/skills/analyze-deps.md +23 -0
  126. package/skills/archive-workspace.md +26 -0
  127. package/skills/branch-create.md +18 -0
  128. package/skills/create-workspace.md +39 -0
  129. package/skills/delete-workspace.md +37 -0
  130. package/skills/list-org-repos.md +26 -0
  131. package/skills/list-suites.md +24 -0
  132. package/skills/list-workspaces.md +27 -0
  133. package/skills/refresh-workspace-docs.md +89 -0
  134. package/skills/remove-repo.md +25 -0
  135. package/skills/run-command.md +23 -0
  136. package/skills/save-context.md +68 -0
  137. package/skills/search-repos.md +31 -0
  138. package/skills/snapshot-list.md +18 -0
  139. package/skills/snapshot-save.md +12 -0
  140. package/skills/switch-branch.md +18 -0
  141. package/skills/update-cache.md +21 -0
  142. package/skills/update-workspace.md +66 -0
  143. package/skills/workspace-cleanup.md +18 -0
  144. package/skills/workspace-diff.md +23 -0
  145. package/skills/workspace-doctor.md +23 -0
  146. package/skills/workspace-info.md +45 -0
  147. package/skills/workspace-manager/SKILL.md +201 -0
  148. package/skills/workspace-manager/references/ai-prompt.md +44 -0
  149. package/skills/workspace-manager/references/analyze-deps.md +45 -0
  150. package/skills/workspace-manager/references/archive-workspace.md +38 -0
  151. package/skills/workspace-manager/references/branch-create.md +31 -0
  152. package/skills/workspace-manager/references/branch-merge.md +22 -0
  153. package/skills/workspace-manager/references/branch-rebase.md +22 -0
  154. package/skills/workspace-manager/references/cache-clear.md +18 -0
  155. package/skills/workspace-manager/references/cache-info.md +22 -0
  156. package/skills/workspace-manager/references/configure-claude.md +31 -0
  157. package/skills/workspace-manager/references/configure.md +35 -0
  158. package/skills/workspace-manager/references/create-workspace.md +45 -0
  159. package/skills/workspace-manager/references/dashboard.md +61 -0
  160. package/skills/workspace-manager/references/delete-workspace.md +33 -0
  161. package/skills/workspace-manager/references/generate-docs.md +36 -0
  162. package/skills/workspace-manager/references/ghq-status.md +28 -0
  163. package/skills/workspace-manager/references/go.md +33 -0
  164. package/skills/workspace-manager/references/history.md +41 -0
  165. package/skills/workspace-manager/references/list-org-repos.md +26 -0
  166. package/skills/workspace-manager/references/list-suites.md +21 -0
  167. package/skills/workspace-manager/references/list-workspaces.md +27 -0
  168. package/skills/workspace-manager/references/mcp.md +49 -0
  169. package/skills/workspace-manager/references/remove-repo.md +26 -0
  170. package/skills/workspace-manager/references/run-command.md +44 -0
  171. package/skills/workspace-manager/references/search-repos.md +24 -0
  172. package/skills/workspace-manager/references/sessions.md +27 -0
  173. package/skills/workspace-manager/references/suite-create.md +22 -0
  174. package/skills/workspace-manager/references/suite-delete.md +21 -0
  175. package/skills/workspace-manager/references/suite-export.md +19 -0
  176. package/skills/workspace-manager/references/suite-import.md +19 -0
  177. package/skills/workspace-manager/references/suite-use.md +27 -0
  178. package/skills/workspace-manager/references/switch-branch.md +25 -0
  179. package/skills/workspace-manager/references/update-cache.md +22 -0
  180. package/skills/workspace-manager/references/update-workspace.md +50 -0
  181. package/skills/workspace-manager/references/workspace-cleanup.md +33 -0
  182. package/skills/workspace-manager/references/workspace-diff.md +27 -0
  183. package/skills/workspace-manager/references/workspace-doctor.md +27 -0
  184. package/skills/workspace-manager/references/workspace-info.md +33 -0
  185. package/skills/workspace-manager/references/workspace-status.md +43 -0
  186. package/skills/workspace-manager/references/workspace-sync.md +26 -0
  187. package/skills/workspace-status.md +26 -0
  188. package/skills/workspace-sync.md +23 -0
  189. package/src/cli/ai-prompt.test.ts +667 -0
  190. package/src/cli/ai-prompt.ts +421 -0
  191. package/src/cli/dashboard/AgentList.tsx +44 -0
  192. package/src/cli/dashboard/DashboardSidebar.tsx +291 -0
  193. package/src/cli/dashboard/HelpFooter.tsx +22 -0
  194. package/src/cli/dashboard/StatusBadge.tsx +23 -0
  195. package/src/cli/dashboard/index.ts +5 -0
  196. package/src/cli/dashboard/types.ts +16 -0
  197. package/src/cli/tui.tsx +51 -0
  198. package/src/cli/workspace-cli.test.ts +30 -0
  199. package/src/commands/ai-prompt.ts +21 -0
  200. package/src/commands/analyze-deps.ts +119 -0
  201. package/src/commands/archive.ts +114 -0
  202. package/src/commands/branch/create.ts +94 -0
  203. package/src/commands/branch/index.ts +74 -0
  204. package/src/commands/branch/merge.ts +61 -0
  205. package/src/commands/branch/rebase.ts +54 -0
  206. package/src/commands/branch/switch.ts +150 -0
  207. package/src/commands/cache/index.ts +51 -0
  208. package/src/commands/cache/manager.ts +168 -0
  209. package/src/commands/cleanup.ts +132 -0
  210. package/src/commands/configure-claude.ts +55 -0
  211. package/src/commands/configure.ts +204 -0
  212. package/src/commands/create.ts +196 -0
  213. package/src/commands/dashboard/hook-handler.ts +138 -0
  214. package/src/commands/dashboard/index.ts +248 -0
  215. package/src/commands/dashboard/launcher.ts +42 -0
  216. package/src/commands/dashboard/session-picker.ts +73 -0
  217. package/src/commands/dashboard/sidebar.js +39 -0
  218. package/src/commands/dashboard/workspace-picker.ts +62 -0
  219. package/src/commands/delete.test.ts +250 -0
  220. package/src/commands/delete.ts +171 -0
  221. package/src/commands/deprecated-aliases.ts +55 -0
  222. package/src/commands/diff.ts +106 -0
  223. package/src/commands/doctor.ts +110 -0
  224. package/src/commands/generate-docs.ts +45 -0
  225. package/src/commands/ghq-status.ts +70 -0
  226. package/src/commands/go.ts +125 -0
  227. package/src/commands/history.ts +136 -0
  228. package/src/commands/list.test.ts +219 -0
  229. package/src/commands/list.ts +176 -0
  230. package/src/commands/mcp/index.ts +39 -0
  231. package/src/commands/migrate.ts +277 -0
  232. package/src/commands/remove-repo.ts +194 -0
  233. package/src/commands/report-bug.ts +88 -0
  234. package/src/commands/run.ts +125 -0
  235. package/src/commands/save-context.test.ts +113 -0
  236. package/src/commands/save-context.ts +141 -0
  237. package/src/commands/sessions.ts +99 -0
  238. package/src/commands/status.ts +111 -0
  239. package/src/commands/suite/create.ts +240 -0
  240. package/src/commands/suite/delete.ts +65 -0
  241. package/src/commands/suite/export.ts +97 -0
  242. package/src/commands/suite/import.ts +100 -0
  243. package/src/commands/suite/index.ts +66 -0
  244. package/src/commands/suite/list.ts +54 -0
  245. package/src/commands/suite/use.ts +232 -0
  246. package/src/commands/sync.ts +97 -0
  247. package/src/commands/update.ts +197 -0
  248. package/src/mcp/install.ts +529 -0
  249. package/src/mcp/server.ts +579 -0
  250. package/src/mcp/tools.test.ts +545 -0
  251. package/src/mcp/tools.ts +1019 -0
  252. package/src/mcp/update-workspace.test.ts +220 -0
  253. package/src/pi-extensions/permission-sync.ts.template +41 -0
  254. package/src/pi-extensions/permissions-gate.ts.template +69 -0
  255. package/src/pi-extensions/pr-fix-trigger.ts.template +124 -0
  256. package/src/pi-extensions/review-reminder.ts.template +58 -0
  257. package/src/pi-extensions/workspace-input-status.ts.template +919 -0
  258. package/src/program.ts +112 -0
  259. package/src/scripts/workspace-table.py +394 -0
  260. package/src/types/dashboard.ts +29 -0
  261. package/src/types/index.ts +109 -0
  262. package/src/types/ink.d.ts +171 -0
  263. package/src/utils/agent-config.test.ts +303 -0
  264. package/src/utils/agent-config.ts +264 -0
  265. package/src/utils/agent-state.test.ts +166 -0
  266. package/src/utils/agent-state.ts +135 -0
  267. package/src/utils/banner.ts +24 -0
  268. package/src/utils/branch-operations.ts +237 -0
  269. package/src/utils/bug-report.test.ts +174 -0
  270. package/src/utils/bug-report.ts +355 -0
  271. package/src/utils/cache.ts +150 -0
  272. package/src/utils/claude-integration.test.ts +381 -0
  273. package/src/utils/claude-integration.ts +649 -0
  274. package/src/utils/claude-sessions.test.ts +262 -0
  275. package/src/utils/claude-sessions.ts +251 -0
  276. package/src/utils/cleanup-operations.ts +94 -0
  277. package/src/utils/colors.ts +25 -0
  278. package/src/utils/command-helpers.ts +46 -0
  279. package/src/utils/config.test.ts +203 -0
  280. package/src/utils/config.ts +133 -0
  281. package/src/utils/context-file.ts +36 -0
  282. package/src/utils/dashboard-hooks.test.ts +168 -0
  283. package/src/utils/dashboard-hooks.ts +163 -0
  284. package/src/utils/dependency-analyzer.ts +243 -0
  285. package/src/utils/diff-operations.ts +59 -0
  286. package/src/utils/doc-generator.ts +187 -0
  287. package/src/utils/ghq-integration.test.ts +195 -0
  288. package/src/utils/ghq-integration.ts +317 -0
  289. package/src/utils/git-operations.test.ts +265 -0
  290. package/src/utils/git-operations.ts +233 -0
  291. package/src/utils/git-status.ts +171 -0
  292. package/src/utils/github.ts +74 -0
  293. package/src/utils/health-checks.ts +359 -0
  294. package/src/utils/history.ts +140 -0
  295. package/src/utils/hooks.ts +92 -0
  296. package/src/utils/logger.ts +37 -0
  297. package/src/utils/permission-sync.test.ts +593 -0
  298. package/src/utils/permission-sync.ts +720 -0
  299. package/src/utils/pi-extensions.test.ts +182 -0
  300. package/src/utils/pi-extensions.ts +226 -0
  301. package/src/utils/progress.ts +73 -0
  302. package/src/utils/prompts.test.ts +169 -0
  303. package/src/utils/prompts.ts +296 -0
  304. package/src/utils/repo-resolver.test.ts +313 -0
  305. package/src/utils/repo-resolver.ts +294 -0
  306. package/src/utils/retry.test.ts +124 -0
  307. package/src/utils/retry.ts +85 -0
  308. package/src/utils/run-operations.ts +38 -0
  309. package/src/utils/suite.test.ts +256 -0
  310. package/src/utils/suite.ts +144 -0
  311. package/src/utils/sync-operations.ts +87 -0
  312. package/src/utils/tmux-dashboard.ts +193 -0
  313. package/src/utils/validation.test.ts +139 -0
  314. package/src/utils/validation.ts +128 -0
  315. package/src/utils/version-check.test.ts +108 -0
  316. package/src/utils/version-check.ts +96 -0
  317. package/src/utils/workspace-meta.ts +173 -0
  318. package/sync-permissions.sh +137 -0
  319. package/tsconfig.json +20 -0
  320. package/uninstall.sh +162 -0
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Pi Permission Sync Extension (auto-generated by workspace-manager)
3
+ *
4
+ * Equivalent of Claude Code's sync-permissions.sh Stop hook.
5
+ * Syncs project-level permissions to global settings on session shutdown.
6
+ */
7
+
8
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
9
+ import { spawn } from "node:child_process";
10
+
11
+ const SYNC_SCRIPT = "__SYNC_PERMISSIONS_SCRIPT__";
12
+
13
+ async function syncPermissions(): Promise<void> {
14
+ return new Promise((resolve) => {
15
+ const proc = spawn("bash", [SYNC_SCRIPT], {
16
+ detached: true,
17
+ stdio: "ignore",
18
+ env: { ...process.env, CLAUDE_PROJECT_DIR: process.cwd() },
19
+ });
20
+ proc.unref();
21
+ resolve();
22
+ });
23
+ }
24
+
25
+ export default function (pi: ExtensionAPI) {
26
+ pi.on("session_shutdown", async () => {
27
+ try { await syncPermissions(); } catch { /* ignore */ }
28
+ });
29
+
30
+ pi.registerCommand("sync-permissions", {
31
+ description: "Sync project permissions to global settings",
32
+ handler: async (_args, ctx) => {
33
+ try {
34
+ await syncPermissions();
35
+ ctx.ui.notify("Permissions synced to global settings", "success");
36
+ } catch (error) {
37
+ ctx.ui.notify(`Failed to sync permissions: ${error}`, "error");
38
+ }
39
+ },
40
+ });
41
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Pi Permissions Gate Extension (auto-generated by workspace-manager)
3
+ *
4
+ * Equivalent of Claude Code's permission system.
5
+ * Confirms before running dangerous bash commands.
6
+ */
7
+
8
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
9
+ import { isToolCallEventType } from "@earendil-works/pi-coding-agent";
10
+
11
+ const DANGEROUS_PATTERNS = [
12
+ /\brm\s+-rf\b/,
13
+ /\brm\s+-r\b/,
14
+ /\brm\s+.*\*\b/,
15
+ /\brm\s+.*\/\b/,
16
+ /\bsudo\s+rm\b/,
17
+ /\bdd\s+if=/,
18
+ /\bmkfs\b/,
19
+ /\b:\(\)\{\s*:\|:\s*&\s*\};\s*:/,
20
+ />\s*\/dev\/sd/,
21
+ /\bgit\s+push\s+.*--force\b/,
22
+ /\bgit\s+reset\s+--hard\b/,
23
+ /\bkillall\s+-9\b/,
24
+ /\bpkill\s+-9\b/,
25
+ ];
26
+
27
+ const PROTECTED_PATHS = [
28
+ ".env", ".env.local", ".env.production",
29
+ "node_modules", ".git", "~/.ssh", "~/.gnupg",
30
+ ];
31
+
32
+ export default function (pi: ExtensionAPI) {
33
+ pi.on("tool_call", async (event, ctx) => {
34
+ if (!isToolCallEventType("bash", event)) return;
35
+ const command = event.input.command || "";
36
+
37
+ for (const pattern of DANGEROUS_PATTERNS) {
38
+ if (pattern.test(command)) {
39
+ const ok = await ctx.ui.confirm(
40
+ "⚠️ Dangerous Command",
41
+ `This command looks destructive:\n\n${command.substring(0, 200)}${command.length > 200 ? "..." : ""}\n\nProceed?`
42
+ );
43
+ if (!ok) return { block: true, reason: "Blocked by permission gate (dangerous command)" };
44
+ break;
45
+ }
46
+ }
47
+ });
48
+
49
+ pi.on("tool_call", async (event, ctx) => {
50
+ if (isToolCallEventType("write", event)) {
51
+ const filePath = event.input.path || "";
52
+ const basename = filePath.split("/").pop() || "";
53
+ for (const pp of PROTECTED_PATHS) {
54
+ if (filePath.includes(pp) || basename === pp) {
55
+ const ok = await ctx.ui.confirm(
56
+ "🔒 Protected Path",
57
+ `Writing to ${filePath} may be unsafe.\n\nProceed?`
58
+ );
59
+ if (!ok) return { block: true, reason: "Blocked by permission gate (protected path)" };
60
+ break;
61
+ }
62
+ }
63
+ }
64
+ });
65
+
66
+ pi.on("session_start", async (_event, ctx) => {
67
+ ctx.ui.notify("Permission gate active - dangerous commands require confirmation", "info");
68
+ });
69
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Pi PR-Fix Trigger Extension (auto-generated by workspace-manager)
3
+ *
4
+ * Equivalent of Claude Code's check-pr-fix-trigger.sh PostToolUse hook.
5
+ * Detects `gh pr create` in bash tool results, extracts the PR URL,
6
+ * and injects a directive to monitor CI and address review comments.
7
+ *
8
+ * @managed workspace-manager
9
+ */
10
+
11
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
12
+ import { isBashToolResult } from "@earendil-works/pi-coding-agent";
13
+
14
+ const PR_URL_REGEX = /https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/;
15
+
16
+ export default function (pi: ExtensionAPI) {
17
+ pi.on("tool_result", async (event, ctx) => {
18
+ // Only handle bash tool results
19
+ if (!isBashToolResult(event)) return;
20
+
21
+ // Check if the command was a `gh pr create`
22
+ const command = String(event.input?.command ?? "");
23
+ if (!command.includes("gh pr create")) return;
24
+
25
+ // Extract PR URL and components from tool result content
26
+ const resultText = Array.isArray(event.content)
27
+ ? event.content
28
+ .filter((c: { type: string }) => c.type === "text")
29
+ .map((c: { text: string }) => c.text)
30
+ .join("\n")
31
+ : String(event.content ?? "");
32
+
33
+ const match = resultText.match(PR_URL_REGEX);
34
+ if (!match) return;
35
+
36
+ const [prUrl, owner, repo, prNumber] = match;
37
+
38
+ // Inject the PR-fix directive as a steering message
39
+ const directive = buildPrFixDirective(prUrl, owner, repo, prNumber);
40
+
41
+ pi.sendMessage(
42
+ {
43
+ customType: "pr-fix-trigger",
44
+ content: directive,
45
+ display: true,
46
+ },
47
+ { deliverAs: "steer", triggerTurn: true }
48
+ );
49
+ });
50
+ }
51
+
52
+ function buildPrFixDirective(
53
+ prUrl: string,
54
+ owner: string,
55
+ repo: string,
56
+ prNumber: string
57
+ ): string {
58
+ return `[PR-FIX-TRIGGER] Pull request created: ${prUrl}
59
+
60
+ You MUST now execute the following two-phase autonomous feedback loop. Do NOT skip any phase. Do NOT ask the user for permission to start — begin immediately.
61
+
62
+ ═══════════════════════════════════════════════════════════════
63
+ PHASE 1: CI MONITORING & FIXES
64
+ ═══════════════════════════════════════════════════════════════
65
+
66
+ Monitor CircleCI for the PR. Run:
67
+ gh pr checks ${prUrl} --watch
68
+
69
+ If checks fail:
70
+ 1. Read the failing check details
71
+ 2. Identify the root cause (test failure, lint error, build error, etc.)
72
+ 3. Fix the code
73
+ 4. Commit with message: "fix: address CI failure"
74
+ 5. Push (never force-push)
75
+ 6. Re-run: gh pr checks ${prUrl} --watch
76
+ 7. Repeat up to 3 times
77
+
78
+ If checks pass → proceed to Phase 2.
79
+ If checks still fail after 3 attempts → STOP. Inform the user what failed and why manual help is needed.
80
+
81
+ ═══════════════════════════════════════════════════════════════
82
+ PHASE 2: PR REVIEW COMMENT MONITORING
83
+ ═══════════════════════════════════════════════════════════════
84
+
85
+ Enter a comment monitoring loop (max 5 iterations):
86
+
87
+ For each iteration:
88
+ 1. Fetch review comments using these two commands:
89
+ gh api repos/${owner}/${repo}/pulls/${prNumber}/reviews
90
+ gh api repos/${owner}/${repo}/pulls/${prNumber}/comments
91
+
92
+ 2. Filter for actionable comments:
93
+ - Ignore reviews with state APPROVED or DISMISSED
94
+ - Focus on CHANGES_REQUESTED and COMMENTED reviews that have a non-empty body
95
+ - Focus on inline comments (from /comments endpoint) that have not been resolved
96
+ - Ignore comments authored by the PR author (yourself / bots)
97
+
98
+ 3. If NO actionable comments are found → STOP. Report success: "No unresolved review comments. PR feedback loop complete."
99
+
100
+ 4. If actionable comments ARE found:
101
+ a. For each comment, read the referenced file and understand the context
102
+ b. If the comment is clear and actionable (typo fix, style change, logic fix, add test, etc.) → make the change
103
+ c. If the comment is ambiguous, requests major architectural changes, or you are unsure → ask the user for guidance on that specific comment before proceeding
104
+ d. After addressing all clear comments, commit with message: "fix: address PR review comments"
105
+ e. Push the commit (never force-push)
106
+ f. Show the user a summary of what you changed and why
107
+
108
+ 5. Track which comment IDs you saw in this iteration. If the SAME set of comment IDs appeared in the previous iteration (meaning no new comments, and your fixes haven't been acknowledged yet) → STOP. Report: "Previously seen comments already addressed. Waiting for reviewer to re-review."
109
+
110
+ 6. Wait 120 seconds, then start the next iteration.
111
+
112
+ TERMINATION CONDITIONS (stop the loop if ANY of these are true):
113
+ - Phase 1 required manual intervention → stop after Phase 1
114
+ - No actionable comments found → stop (success)
115
+ - Same comment IDs as previous iteration → stop (already addressed)
116
+ - Max 5 iterations reached → stop and report summary of all changes made
117
+
118
+ SAFETY RULES:
119
+ - NEVER force-push
120
+ - NEVER rewrite git history
121
+ - After each commit, show the user what changed (files modified, brief description)
122
+ - For ambiguous or architectural comments, ASK the user before making changes
123
+ - If a comment asks to revert or undo your previous changes, do so carefully`;
124
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Pi Review Reminder Extension (auto-generated by workspace-manager)
3
+ *
4
+ * Equivalent of Claude Code's check-review-reminder.sh SessionStart hook.
5
+ * Reminds user to review global permissions periodically.
6
+ */
7
+
8
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
9
+ import * as fs from "node:fs";
10
+ import * as path from "node:path";
11
+ import * as os from "node:os";
12
+
13
+ const CACHE_DIR = path.join(os.homedir(), ".workspace-manager-cache");
14
+ const REVIEW_FILE = path.join(CACHE_DIR, "last-permission-review");
15
+ const REMINDER_FILE = path.join(CACHE_DIR, "last-permission-reminder");
16
+ const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000;
17
+
18
+ function getLastTimestamp(filePath: string): number {
19
+ try {
20
+ const content = fs.readFileSync(filePath, "utf-8").trim();
21
+ const epoch = new Date(content).getTime();
22
+ return isNaN(epoch) ? 0 : epoch;
23
+ } catch {
24
+ return 0;
25
+ }
26
+ }
27
+
28
+ export default function (pi: ExtensionAPI) {
29
+ pi.on("session_start", async (_event, ctx) => {
30
+ const reviewEpoch = getLastTimestamp(REVIEW_FILE);
31
+ const reminderEpoch = getLastTimestamp(REMINDER_FILE);
32
+ const latestEpoch = Math.max(reviewEpoch, reminderEpoch);
33
+ const now = Date.now();
34
+
35
+ if (latestEpoch === 0) {
36
+ ctx.ui.notify(
37
+ "[nemus] Your global permissions have never been reviewed. Run /review-permissions to audit them.",
38
+ "warning"
39
+ );
40
+ } else {
41
+ const daysSince = Math.floor((now - latestEpoch) / (24 * 60 * 60 * 1000));
42
+ if (daysSince >= 30) {
43
+ ctx.ui.notify(
44
+ `[nemus] Your global permissions haven't been reviewed in ${daysSince} days. Run /review-permissions to clean up stale entries.`,
45
+ "warning"
46
+ );
47
+ } else {
48
+ return; // Recent — stay silent
49
+ }
50
+ }
51
+
52
+ // Write reminder timestamp
53
+ try {
54
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
55
+ fs.writeFileSync(REMINDER_FILE, new Date().toISOString());
56
+ } catch { /* ignore */ }
57
+ });
58
+ }