oh-my-claude-sisyphus 3.8.16 → 3.9.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 (178) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.mcp.json +1 -1
  4. package/agents/analyst.md +41 -0
  5. package/agents/architect.md +47 -2
  6. package/agents/critic.md +42 -0
  7. package/agents/deep-executor.md +193 -0
  8. package/agents/planner.md +82 -0
  9. package/bridge/mcp-server.cjs +181 -181
  10. package/commands/build-fix.md +3 -3
  11. package/commands/ralph.md +3 -3
  12. package/commands/ultraqa.md +4 -4
  13. package/commands/ultrawork.md +3 -3
  14. package/dist/__tests__/agent-registry.test.js +1 -1
  15. package/dist/__tests__/installer.test.js +8 -8
  16. package/dist/__tests__/installer.test.js.map +1 -1
  17. package/dist/__tests__/omc-tools-server.test.js +2 -2
  18. package/dist/__tests__/omc-tools-server.test.js.map +1 -1
  19. package/dist/__tests__/skills.test.js +5 -4
  20. package/dist/__tests__/skills.test.js.map +1 -1
  21. package/dist/agents/deep-executor.d.ts +15 -0
  22. package/dist/agents/deep-executor.d.ts.map +1 -0
  23. package/dist/agents/deep-executor.js +47 -0
  24. package/dist/agents/deep-executor.js.map +1 -0
  25. package/dist/agents/definitions.d.ts +16 -1
  26. package/dist/agents/definitions.d.ts.map +1 -1
  27. package/dist/agents/definitions.js +26 -1
  28. package/dist/agents/definitions.js.map +1 -1
  29. package/dist/agents/index.d.ts +1 -0
  30. package/dist/agents/index.d.ts.map +1 -1
  31. package/dist/agents/index.js +1 -0
  32. package/dist/agents/index.js.map +1 -1
  33. package/dist/cli/commands/doctor-conflicts.d.ts +55 -0
  34. package/dist/cli/commands/doctor-conflicts.d.ts.map +1 -0
  35. package/dist/cli/commands/doctor-conflicts.js +261 -0
  36. package/dist/cli/commands/doctor-conflicts.js.map +1 -0
  37. package/dist/cli/index.js +16 -1
  38. package/dist/cli/index.js.map +1 -1
  39. package/dist/features/auto-update.d.ts +12 -0
  40. package/dist/features/auto-update.d.ts.map +1 -1
  41. package/dist/features/auto-update.js +4 -1
  42. package/dist/features/auto-update.js.map +1 -1
  43. package/dist/features/background-tasks.js +4 -4
  44. package/dist/features/context-injector/types.d.ts +1 -1
  45. package/dist/features/context-injector/types.d.ts.map +1 -1
  46. package/dist/features/task-decomposer/index.js +3 -3
  47. package/dist/features/task-decomposer/index.js.map +1 -1
  48. package/dist/features/verification/index.d.ts +3 -3
  49. package/dist/features/verification/index.js +3 -3
  50. package/dist/features/verification/index.js.map +1 -1
  51. package/dist/hooks/__tests__/bridge.test.d.ts +2 -0
  52. package/dist/hooks/__tests__/bridge.test.d.ts.map +1 -0
  53. package/dist/hooks/__tests__/bridge.test.js +199 -0
  54. package/dist/hooks/__tests__/bridge.test.js.map +1 -0
  55. package/dist/hooks/autopilot/state.js +3 -3
  56. package/dist/hooks/beads-context/__tests__/index.test.d.ts +2 -0
  57. package/dist/hooks/beads-context/__tests__/index.test.d.ts.map +1 -0
  58. package/dist/hooks/beads-context/__tests__/index.test.js +150 -0
  59. package/dist/hooks/beads-context/__tests__/index.test.js.map +1 -0
  60. package/dist/hooks/beads-context/constants.d.ts +3 -0
  61. package/dist/hooks/beads-context/constants.d.ts.map +1 -0
  62. package/dist/hooks/beads-context/constants.js +35 -0
  63. package/dist/hooks/beads-context/constants.js.map +1 -0
  64. package/dist/hooks/beads-context/index.d.ts +21 -0
  65. package/dist/hooks/beads-context/index.d.ts.map +1 -0
  66. package/dist/hooks/beads-context/index.js +62 -0
  67. package/dist/hooks/beads-context/index.js.map +1 -0
  68. package/dist/hooks/beads-context/types.d.ts +7 -0
  69. package/dist/hooks/beads-context/types.d.ts.map +1 -0
  70. package/dist/hooks/beads-context/types.js +2 -0
  71. package/dist/hooks/beads-context/types.js.map +1 -0
  72. package/dist/hooks/bridge.d.ts +4 -0
  73. package/dist/hooks/bridge.d.ts.map +1 -1
  74. package/dist/hooks/bridge.js +76 -23
  75. package/dist/hooks/bridge.js.map +1 -1
  76. package/dist/hooks/clear-suggestions/constants.d.ts +54 -0
  77. package/dist/hooks/clear-suggestions/constants.d.ts.map +1 -0
  78. package/dist/hooks/clear-suggestions/constants.js +102 -0
  79. package/dist/hooks/clear-suggestions/constants.js.map +1 -0
  80. package/dist/hooks/clear-suggestions/index.d.ts +61 -0
  81. package/dist/hooks/clear-suggestions/index.d.ts.map +1 -0
  82. package/dist/hooks/clear-suggestions/index.js +282 -0
  83. package/dist/hooks/clear-suggestions/index.js.map +1 -0
  84. package/dist/hooks/clear-suggestions/triggers.d.ts +65 -0
  85. package/dist/hooks/clear-suggestions/triggers.d.ts.map +1 -0
  86. package/dist/hooks/clear-suggestions/triggers.js +222 -0
  87. package/dist/hooks/clear-suggestions/triggers.js.map +1 -0
  88. package/dist/hooks/clear-suggestions/types.d.ts +92 -0
  89. package/dist/hooks/clear-suggestions/types.d.ts.map +1 -0
  90. package/dist/hooks/clear-suggestions/types.js +9 -0
  91. package/dist/hooks/clear-suggestions/types.js.map +1 -0
  92. package/dist/hooks/index.d.ts +1 -0
  93. package/dist/hooks/index.d.ts.map +1 -1
  94. package/dist/hooks/index.js +3 -0
  95. package/dist/hooks/index.js.map +1 -1
  96. package/dist/hooks/permission-handler/index.d.ts.map +1 -1
  97. package/dist/hooks/permission-handler/index.js +3 -1
  98. package/dist/hooks/permission-handler/index.js.map +1 -1
  99. package/dist/hooks/setup/index.d.ts.map +1 -1
  100. package/dist/hooks/setup/index.js +12 -5
  101. package/dist/hooks/setup/index.js.map +1 -1
  102. package/dist/hooks/subagent-tracker/index.d.ts.map +1 -1
  103. package/dist/hooks/subagent-tracker/index.js +25 -9
  104. package/dist/hooks/subagent-tracker/index.js.map +1 -1
  105. package/dist/hooks/ultraqa/index.js +4 -4
  106. package/dist/hooks/ultraqa/index.js.map +1 -1
  107. package/dist/index.js +1 -1
  108. package/dist/index.js.map +1 -1
  109. package/dist/installer/__tests__/claude-md-merge.test.d.ts +6 -0
  110. package/dist/installer/__tests__/claude-md-merge.test.d.ts.map +1 -0
  111. package/dist/installer/__tests__/claude-md-merge.test.js +220 -0
  112. package/dist/installer/__tests__/claude-md-merge.test.js.map +1 -0
  113. package/dist/installer/__tests__/safe-installer.test.d.ts +6 -0
  114. package/dist/installer/__tests__/safe-installer.test.d.ts.map +1 -0
  115. package/dist/installer/__tests__/safe-installer.test.js +172 -0
  116. package/dist/installer/__tests__/safe-installer.test.js.map +1 -0
  117. package/dist/installer/hooks.d.ts.map +1 -1
  118. package/dist/installer/hooks.js +3 -1
  119. package/dist/installer/hooks.js.map +1 -1
  120. package/dist/installer/index.d.ts +27 -1
  121. package/dist/installer/index.d.ts.map +1 -1
  122. package/dist/installer/index.js +209 -85
  123. package/dist/installer/index.js.map +1 -1
  124. package/dist/mcp/omc-tools-server.d.ts +1 -1
  125. package/dist/mcp/omc-tools-server.d.ts.map +1 -1
  126. package/dist/mcp/omc-tools-server.js +3 -3
  127. package/dist/mcp/omc-tools-server.js.map +1 -1
  128. package/dist/mcp/standalone-server.js +1 -1
  129. package/dist/mcp/standalone-server.js.map +1 -1
  130. package/dist/verification/tier-selector.d.ts +40 -0
  131. package/dist/verification/tier-selector.d.ts.map +1 -0
  132. package/dist/verification/tier-selector.js +95 -0
  133. package/dist/verification/tier-selector.js.map +1 -0
  134. package/dist/verification/tier-selector.test.d.ts +2 -0
  135. package/dist/verification/tier-selector.test.d.ts.map +1 -0
  136. package/dist/verification/tier-selector.test.js +282 -0
  137. package/dist/verification/tier-selector.test.js.map +1 -0
  138. package/docs/AGENTS.md +1 -1
  139. package/docs/CLAUDE.md +90 -378
  140. package/docs/partials/agent-tiers.md +165 -0
  141. package/docs/partials/features.md +131 -0
  142. package/docs/partials/mode-hierarchy.md +120 -0
  143. package/docs/partials/mode-selection-guide.md +82 -0
  144. package/docs/partials/verification-tiers.md +107 -0
  145. package/docs/shared/agent-tiers.md +165 -0
  146. package/docs/shared/features.md +131 -0
  147. package/docs/shared/mode-hierarchy.md +120 -0
  148. package/docs/shared/mode-selection-guide.md +82 -0
  149. package/docs/shared/verification-tiers.md +107 -0
  150. package/package.json +4 -3
  151. package/scripts/compose-docs.mjs +44 -0
  152. package/scripts/keyword-detector.mjs +13 -3
  153. package/skills/build-fix/SKILL.md +8 -8
  154. package/skills/deep-executor/SKILL.md +50 -0
  155. package/skills/deepinit/SKILL.md +2 -2
  156. package/skills/ecomode/SKILL.md +58 -103
  157. package/skills/omc-setup/SKILL.md +197 -20
  158. package/skills/plan/SKILL.md +62 -0
  159. package/skills/project-session-manager/SKILL.md +87 -4
  160. package/skills/project-session-manager/lib/config.sh +54 -5
  161. package/skills/project-session-manager/lib/parse.sh +65 -11
  162. package/skills/project-session-manager/lib/providers/github.sh +52 -0
  163. package/skills/project-session-manager/lib/providers/interface.sh +76 -0
  164. package/skills/project-session-manager/lib/providers/jira.sh +79 -0
  165. package/skills/project-session-manager/lib/session.sh +49 -12
  166. package/skills/project-session-manager/lib/worktree.sh +37 -4
  167. package/skills/project-session-manager/psm.sh +116 -51
  168. package/skills/ralph/SKILL.md +44 -30
  169. package/skills/tdd/SKILL.md +2 -2
  170. package/skills/ultrapilot/SKILL.md +3 -3
  171. package/skills/ultraqa/SKILL.md +4 -4
  172. package/skills/ultrawork/SKILL.md +59 -69
  173. package/templates/hooks/keyword-detector.mjs +21 -13
  174. package/templates/hooks/lib/stdin.mjs +62 -0
  175. package/templates/hooks/persistent-mode.mjs +7 -8
  176. package/templates/hooks/post-tool-use.mjs +8 -10
  177. package/templates/hooks/pre-tool-use.mjs +9 -6
  178. package/templates/hooks/session-start.mjs +7 -8
@@ -1,105 +1,95 @@
1
1
  ---
2
2
  name: ultrawork
3
- description: Activate maximum performance mode with parallel agent orchestration for high-throughput task completion
3
+ description: Parallel execution engine for high-throughput task completion
4
4
  ---
5
5
 
6
6
  # Ultrawork Skill
7
7
 
8
- Activates maximum performance mode with parallel agent orchestration.
8
+ Parallel execution engine. This is a **COMPONENT**, not a standalone persistence mode.
9
9
 
10
- ## When Activated
11
-
12
- This skill enhances Claude's capabilities by:
10
+ ## What Ultrawork Provides
13
11
 
14
12
  1. **Parallel Execution**: Running multiple agents simultaneously for independent tasks
15
- 2. **Aggressive Delegation**: Routing tasks to specialist agents immediately
16
- 3. **Background Operations**: Using `run_in_background: true` for long operations
17
- 4. **Persistence Enforcement**: Never stopping until all tasks are verified complete
18
- 5. **Smart Model Routing**: Using tiered agents to save tokens
19
-
20
- ## Smart Model Routing (CRITICAL - SAVE TOKENS)
21
-
22
- **Choose tier based on task complexity: LOW (haiku) → MEDIUM (sonnet) → HIGH (opus)**
23
-
24
- ### Available Agents by Tier
13
+ 2. **Background Operations**: Using `run_in_background: true` for long operations
14
+ 3. **Smart Model Routing**: Using tiered agents to save tokens
25
15
 
26
- | Domain | LOW (Haiku) | MEDIUM (Sonnet) | HIGH (Opus) |
27
- |--------|-------------|-----------------|-------------|
28
- | **Analysis** | `architect-low` | `architect-medium` | `architect` |
29
- | **Execution** | `executor-low` | `executor` | `executor-high` |
30
- | **Search** | `explore` | `explore-medium` | - |
31
- | **Research** | `researcher-low` | `researcher` | - |
32
- | **Frontend** | `designer-low` | `designer` | `designer-high` |
33
- | **Docs** | `writer` | - | - |
34
- | **Visual** | - | `vision` | - |
35
- | **Planning** | - | - | `planner`, `critic`, `analyst` |
36
- | **Testing** | - | `qa-tester` | - |
37
- | **Security** | `security-reviewer-low` | - | `security-reviewer` |
38
- | **Build** | `build-fixer-low` | `build-fixer` | - |
39
- | **TDD** | `tdd-guide-low` | `tdd-guide` | - |
40
- | **Code Review** | `code-reviewer-low` | - | `code-reviewer` |
16
+ ## What Ultrawork Does NOT Provide
41
17
 
42
- ### Tier Selection Guide
18
+ - **Persistence**: Use `ralph` for "don't stop until done" behavior
19
+ - **Verification Loop**: Use `ralph` for mandatory architect verification
20
+ - **State Management**: Use `ralph` or `autopilot` for session persistence
43
21
 
44
- | Task Complexity | Tier | Examples |
45
- |-----------------|------|----------|
46
- | Simple lookups | LOW | "What does this function return?", "Find where X is defined" |
47
- | Standard work | MEDIUM | "Add error handling", "Implement this feature" |
48
- | Complex analysis | HIGH | "Debug this race condition", "Refactor auth module across 5 files" |
22
+ ## Usage
49
23
 
50
- ### Routing Examples
24
+ Ultrawork is automatically activated by:
25
+ - `ralph` (for persistent parallel work)
26
+ - `autopilot` (for autonomous parallel work)
27
+ - Direct invocation when you want parallel-only execution with manual oversight
51
28
 
52
- **CRITICAL: Always pass `model` parameter explicitly - Claude Code does NOT auto-apply models from agent definitions!**
29
+ ## Smart Model Routing
53
30
 
31
+ **FIRST ACTION:** Before delegating any work, read the agent reference file:
54
32
  ```
55
- // Simple question → LOW tier (saves tokens!)
56
- Task(subagent_type="oh-my-claudecode:architect-low", model="haiku", prompt="What does this function return?")
57
-
58
- // Standard implementation → MEDIUM tier
59
- Task(subagent_type="oh-my-claudecode:executor", model="sonnet", prompt="Add error handling to login")
60
-
61
- // Complex refactoring → HIGH tier
62
- Task(subagent_type="oh-my-claudecode:executor-high", model="opus", prompt="Refactor auth module using JWT across 5 files")
33
+ Read file: docs/shared/agent-tiers.md
34
+ ```
35
+ This provides the complete agent tier matrix, MCP tool assignments, and selection guidance.
63
36
 
64
- // Quick file lookup LOW tier
65
- Task(subagent_type="oh-my-claudecode:explore", model="haiku", prompt="Find where UserService is defined")
37
+ **CRITICAL: Always pass `model` parameter explicitly!**
66
38
 
67
- // Thorough search → MEDIUM tier
68
- Task(subagent_type="oh-my-claudecode:explore-medium", model="sonnet", prompt="Find all authentication patterns in the codebase")
39
+ ```
40
+ Task(subagent_type="oh-my-claudecode:architect-low", model="haiku", prompt="...")
41
+ Task(subagent_type="oh-my-claudecode:executor", model="sonnet", prompt="...")
42
+ Task(subagent_type="oh-my-claudecode:architect", model="opus", prompt="...")
69
43
  ```
70
44
 
71
45
  ## Background Execution Rules
72
46
 
73
47
  **Run in Background** (set `run_in_background: true`):
74
- - Package installation: npm install, pip install, cargo build
75
- - Build processes: npm run build, make, tsc
76
- - Test suites: npm test, pytest, cargo test
77
- - Docker operations: docker build, docker pull
48
+ - Package installation (npm install, pip install, cargo build, etc.)
49
+ - Build processes (project build command, make, etc.)
50
+ - Test suites (project test command, etc.)
78
51
 
79
52
  **Run Blocking** (foreground):
80
53
  - Quick status checks: git status, ls, pwd
81
54
  - File reads, edits
82
55
  - Simple commands
83
56
 
84
- ## Verification Checklist
57
+ ## Relationship to Other Modes
85
58
 
86
- Before stopping, verify:
87
- - [ ] TODO LIST: Zero pending/in_progress tasks
88
- - [ ] FUNCTIONALITY: All requested features work
89
- - [ ] TESTS: All tests pass (if applicable)
90
- - [ ] ERRORS: Zero unaddressed errors
59
+ ```
60
+ ralph (persistence wrapper)
61
+ └── includes: ultrawork (this skill)
62
+ └── provides: parallel execution only
63
+
64
+ autopilot (autonomous execution)
65
+ └── includes: ralph
66
+ └── includes: ultrawork (this skill)
91
67
 
92
- **If ANY checkbox is unchecked, CONTINUE WORKING.**
68
+ ecomode (token efficiency)
69
+ └── modifies: ultrawork's model selection
70
+ ```
93
71
 
94
- ## STATE CLEANUP ON COMPLETION
72
+ ## When to Use Ultrawork Directly
95
73
 
96
- **IMPORTANT: Delete state files on completion - do NOT just set `active: false`**
74
+ Use ultrawork directly when you want:
75
+ - Parallel execution without persistence guarantees
76
+ - Manual oversight over completion
77
+ - Quick parallel tasks where you'll verify yourself
97
78
 
98
- When all verification passes and work is complete:
79
+ Use `ralph` instead when you want:
80
+ - Verified completion (architect check)
81
+ - Automatic retry on failure
82
+ - Session persistence for resume
99
83
 
100
- ```bash
101
- # Delete ultrawork state files
102
- rm -f .omc/state/ultrawork-state.json
103
- ```
84
+ ## Completion Verification (Direct Invocations)
85
+
86
+ When ultrawork is invoked directly (not via ralph), apply lightweight verification before claiming completion:
87
+
88
+ ### Quick Verification Checklist
89
+ - [ ] **BUILD:** Project type check/build command passes
90
+ - [ ] **TESTS:** Run affected tests, all pass
91
+ - [ ] **ERRORS:** No new errors introduced
92
+
93
+ This is lighter than ralph's full verification but ensures basic quality for direct ultrawork usage.
104
94
 
105
- This ensures clean state for future sessions. Stale state files with `active: false` should not be left behind.
95
+ For full persistence and comprehensive verification, use `ralph` mode instead.
@@ -24,8 +24,15 @@
24
24
  */
25
25
 
26
26
  import { writeFileSync, mkdirSync, existsSync, unlinkSync } from 'fs';
27
- import { join } from 'path';
27
+ import { join, dirname } from 'path';
28
28
  import { homedir } from 'os';
29
+ import { fileURLToPath } from 'url';
30
+
31
+ const __filename = fileURLToPath(import.meta.url);
32
+ const __dirname = dirname(__filename);
33
+
34
+ // Dynamic import for the shared stdin module
35
+ const { readStdin } = await import(join(__dirname, 'lib', 'stdin.mjs'));
29
36
 
30
37
  const ULTRATHINK_MESSAGE = `<think-mode>
31
38
 
@@ -44,15 +51,6 @@ Use your extended thinking capabilities to provide the most thorough and well-re
44
51
  ---
45
52
  `;
46
53
 
47
- // Read all stdin
48
- async function readStdin() {
49
- const chunks = [];
50
- for await (const chunk of process.stdin) {
51
- chunks.push(chunk);
52
- }
53
- return Buffer.concat(chunks).toString('utf-8');
54
- }
55
-
56
54
  // Extract prompt from various JSON structures
57
55
  function extractPrompt(input) {
58
56
  try {
@@ -73,10 +71,20 @@ function extractPrompt(input) {
73
71
  }
74
72
  }
75
73
 
76
- // Remove code blocks to prevent false positives
77
- function removeCodeBlocks(text) {
74
+ // Sanitize text to prevent false positives from code blocks, XML tags, URLs, and file paths
75
+ function sanitizeForKeywordDetection(text) {
78
76
  return text
77
+ // 1. Strip XML-style tag blocks: <tag-name ...>...</tag-name> (multi-line, greedy on tag name)
78
+ .replace(/<(\w[\w-]*)[\s>][\s\S]*?<\/\1>/g, '')
79
+ // 2. Strip self-closing XML tags: <tag-name />, <tag-name attr="val" />
80
+ .replace(/<\w[\w-]*(?:\s[^>]*)?\s*\/>/g, '')
81
+ // 3. Strip URLs: http://... or https://... up to whitespace
82
+ .replace(/https?:\/\/[^\s)>\]]+/g, '')
83
+ // 4. Strip file paths: /foo/bar/baz or foo/bar/baz (using lookbehind to avoid consuming leading char)
84
+ .replace(/(?<=^|[\s"'`(])(?:\/)?(?:[\w.-]+\/)+[\w.-]+/gm, '')
85
+ // 5. Strip markdown code blocks (existing)
79
86
  .replace(/```[\s\S]*?```/g, '')
87
+ // 6. Strip inline code (existing)
80
88
  .replace(/`[^`]+`/g, '');
81
89
  }
82
90
 
@@ -225,7 +233,7 @@ async function main() {
225
233
  return;
226
234
  }
227
235
 
228
- const cleanPrompt = removeCodeBlocks(prompt).toLowerCase();
236
+ const cleanPrompt = sanitizeForKeywordDetection(prompt).toLowerCase();
229
237
 
230
238
  // Collect all matching keywords
231
239
  const matches = [];
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Shared stdin utilities for OMC hooks
3
+ * Provides timeout-protected stdin reading to prevent hangs on Linux
4
+ * See: https://github.com/Yeachan-Heo/oh-my-claudecode/issues/240
5
+ */
6
+
7
+ /**
8
+ * Read all stdin with timeout to prevent indefinite hang on Linux.
9
+ *
10
+ * The blocking `for await (const chunk of process.stdin)` pattern waits
11
+ * indefinitely for EOF. On Linux, if the parent process doesn't properly
12
+ * close stdin, this hangs forever. This function uses event-based reading
13
+ * with a timeout as a safety net.
14
+ *
15
+ * @param {number} timeoutMs - Maximum time to wait for stdin (default: 5000ms)
16
+ * @returns {Promise<string>} - The stdin content, or empty string on error/timeout
17
+ */
18
+ export async function readStdin(timeoutMs = 5000) {
19
+ return new Promise((resolve) => {
20
+ const chunks = [];
21
+ let settled = false;
22
+
23
+ const timeout = setTimeout(() => {
24
+ if (!settled) {
25
+ settled = true;
26
+ process.stdin.removeAllListeners();
27
+ process.stdin.destroy();
28
+ resolve(Buffer.concat(chunks).toString('utf-8'));
29
+ }
30
+ }, timeoutMs);
31
+
32
+ process.stdin.on('data', (chunk) => {
33
+ chunks.push(chunk);
34
+ });
35
+
36
+ process.stdin.on('end', () => {
37
+ if (!settled) {
38
+ settled = true;
39
+ clearTimeout(timeout);
40
+ resolve(Buffer.concat(chunks).toString('utf-8'));
41
+ }
42
+ });
43
+
44
+ process.stdin.on('error', () => {
45
+ if (!settled) {
46
+ settled = true;
47
+ clearTimeout(timeout);
48
+ resolve('');
49
+ }
50
+ });
51
+
52
+ // If stdin is already ended (e.g. empty pipe), 'end' fires immediately
53
+ // But if stdin is a TTY or never piped, we need the timeout as safety net
54
+ if (process.stdin.readableEnded) {
55
+ if (!settled) {
56
+ settled = true;
57
+ clearTimeout(timeout);
58
+ resolve(Buffer.concat(chunks).toString('utf-8'));
59
+ }
60
+ }
61
+ });
62
+ }
@@ -9,16 +9,15 @@
9
9
  */
10
10
 
11
11
  import { existsSync, readFileSync, writeFileSync, readdirSync, mkdirSync } from 'fs';
12
- import { join } from 'path';
12
+ import { join, dirname } from 'path';
13
13
  import { homedir } from 'os';
14
+ import { fileURLToPath } from 'url';
14
15
 
15
- async function readStdin() {
16
- const chunks = [];
17
- for await (const chunk of process.stdin) {
18
- chunks.push(chunk);
19
- }
20
- return Buffer.concat(chunks).toString('utf-8');
21
- }
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = dirname(__filename);
18
+
19
+ // Dynamic import for the shared stdin module
20
+ const { readStdin } = await import(join(__dirname, 'lib', 'stdin.mjs'));
22
21
 
23
22
  function readJsonFile(path) {
24
23
  try {
@@ -4,7 +4,14 @@
4
4
  // Saves to .omc/notepad.md for compaction-resilient memory
5
5
 
6
6
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
7
- import { join } from 'path';
7
+ import { join, dirname } from 'path';
8
+ import { fileURLToPath } from 'url';
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+
13
+ // Dynamic import for the shared stdin module
14
+ const { readStdin } = await import(join(__dirname, 'lib', 'stdin.mjs'));
8
15
 
9
16
  // Constants
10
17
  const NOTEPAD_TEMPLATE = '# Notepad\n' +
@@ -16,15 +23,6 @@ const NOTEPAD_TEMPLATE = '# Notepad\n' +
16
23
  '## MANUAL\n' +
17
24
  '<!-- User content. Never auto-pruned. -->\n';
18
25
 
19
- // Read all stdin
20
- async function readStdin() {
21
- const chunks = [];
22
- for await (const chunk of process.stdin) {
23
- chunks.push(chunk);
24
- }
25
- return Buffer.concat(chunks).toString('utf-8');
26
- }
27
-
28
26
  // Initialize notepad.md if needed
29
27
  function initNotepad(directory) {
30
28
  const sisyphusDir = join(directory, '.omc');
@@ -5,6 +5,14 @@
5
5
  */
6
6
 
7
7
  import * as path from 'path';
8
+ import { dirname } from 'path';
9
+ import { fileURLToPath } from 'url';
10
+
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+
14
+ // Dynamic import for the shared stdin module
15
+ const { readStdin } = await import(path.join(__dirname, 'lib', 'stdin.mjs'));
8
16
 
9
17
  // Allowed path patterns (no warning)
10
18
  const ALLOWED_PATH_PATTERNS = [
@@ -70,12 +78,7 @@ This is a soft warning. Operation will proceed.`;
70
78
  }
71
79
 
72
80
  async function main() {
73
- let input = '';
74
-
75
- // Read stdin
76
- for await (const chunk of process.stdin) {
77
- input += chunk;
78
- }
81
+ const input = await readStdin();
79
82
 
80
83
  let data;
81
84
  try {
@@ -4,16 +4,15 @@
4
4
  // Cross-platform: Windows, macOS, Linux
5
5
 
6
6
  import { existsSync, readFileSync, readdirSync, writeFileSync, mkdirSync } from 'fs';
7
- import { join } from 'path';
7
+ import { join, dirname } from 'path';
8
8
  import { homedir } from 'os';
9
+ import { fileURLToPath } from 'url';
9
10
 
10
- async function readStdin() {
11
- const chunks = [];
12
- for await (const chunk of process.stdin) {
13
- chunks.push(chunk);
14
- }
15
- return Buffer.concat(chunks).toString('utf-8');
16
- }
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+
14
+ // Dynamic import for the shared stdin module
15
+ const { readStdin } = await import(join(__dirname, 'lib', 'stdin.mjs'));
17
16
 
18
17
  function readJsonFile(path) {
19
18
  try {