s9n-devops-agent 1.3.1 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "s9n-devops-agent",
3
- "version": "1.3.1",
3
+ "version": "1.3.4",
4
4
  "description": "CS_DevOpsAgent - Intelligent Git Automation System with multi-agent support and session management",
5
5
  "type": "module",
6
6
  "main": "src/cs-devops-agent-worker.js",
@@ -16,6 +16,7 @@ import path from 'path';
16
16
  import crypto from 'crypto';
17
17
  import { fileURLToPath } from 'url';
18
18
  import { dirname } from 'path';
19
+ import { execSync } from 'child_process';
19
20
 
20
21
  const __filename = fileURLToPath(import.meta.url);
21
22
  const __dirname = dirname(__filename);
@@ -112,15 +113,63 @@ To prevent conflicts with other agents editing the same files, you MUST follow t
112
113
 
113
114
  class HouseRulesManager {
114
115
  constructor(projectRoot) {
115
- this.projectRoot = projectRoot || process.cwd();
116
+ const cwd = projectRoot || process.cwd();
117
+
118
+ // If we're running from within a DevOpsAgent directory, we need to find the parent project
119
+ if (cwd.includes('/DevOpsAgent') || cwd.includes('/CS_DevOpsAgent')) {
120
+ // Parse the path to find where the DevOpsAgent directory is
121
+ const pathParts = cwd.split(path.sep);
122
+
123
+ // Find the index of DevOpsAgent or CS_DevOpsAgent
124
+ let targetIndex = -1;
125
+ for (let i = pathParts.length - 1; i >= 0; i--) {
126
+ if (pathParts[i] === 'CS_DevOpsAgent' || pathParts[i] === 'DevOpsAgent') {
127
+ targetIndex = i;
128
+ break;
129
+ }
130
+ }
131
+
132
+ // If found, use the parent directory as the project root
133
+ if (targetIndex > 0) {
134
+ // Check if the parent directory is 'Scripts_Dev' or similar subdirectory
135
+ // If so, go up one more level to reach the actual project root
136
+ let parentIndex = targetIndex;
137
+ if (targetIndex > 1 && (pathParts[targetIndex - 1] === 'Scripts_Dev' ||
138
+ pathParts[targetIndex - 1] === 'scripts' ||
139
+ pathParts[targetIndex - 1] === 'tools')) {
140
+ parentIndex = targetIndex - 1;
141
+ }
142
+ this.projectRoot = pathParts.slice(0, parentIndex).join(path.sep);
143
+ } else {
144
+ // Fallback: try to use git to find the parent repo
145
+ try {
146
+ const gitRoot = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf8' }).trim();
147
+ // Only use git root if it's not a DevOpsAgent directory
148
+ if (!gitRoot.includes('/DevOpsAgent') && !gitRoot.includes('/CS_DevOpsAgent')) {
149
+ this.projectRoot = gitRoot;
150
+ } else {
151
+ // Use parent of cwd
152
+ this.projectRoot = path.dirname(path.dirname(cwd));
153
+ }
154
+ } catch (err) {
155
+ // Default to parent of parent directory
156
+ this.projectRoot = path.dirname(path.dirname(cwd));
157
+ }
158
+ }
159
+ } else {
160
+ this.projectRoot = cwd;
161
+ }
162
+
116
163
  this.houseRulesPath = null;
117
164
  this.findHouseRulesFile();
118
165
  }
119
166
 
120
167
  /**
121
168
  * Find existing house rules file
169
+ * Searches across the repository, excluding the DevOps agent directories
122
170
  */
123
171
  findHouseRulesFile() {
172
+ // First try the standard locations
124
173
  const possiblePaths = [
125
174
  'houserules.md',
126
175
  'HOUSERULES.md',
@@ -132,11 +181,81 @@ class HouseRulesManager {
132
181
  for (const relativePath of possiblePaths) {
133
182
  const fullPath = path.join(this.projectRoot, relativePath);
134
183
  if (fs.existsSync(fullPath)) {
184
+ // NEVER use house rules from within DevOpsAgent directories
185
+ if (fullPath.includes('/DevOpsAgent/') || fullPath.includes('/CS_DevOpsAgent/')) {
186
+ continue;
187
+ }
188
+
135
189
  this.houseRulesPath = fullPath;
190
+ // Only log if not running as CLI
191
+ if (!process.argv[1]?.endsWith('house-rules-manager.js')) {
192
+ console.log(`Found house rules at: ${fullPath}`);
193
+ }
136
194
  return fullPath;
137
195
  }
138
196
  }
139
197
 
198
+ // If not found in standard locations, search the repository
199
+ // excluding DevOps agent directories
200
+ const foundPath = this.searchForHouseRules(this.projectRoot);
201
+ if (foundPath) {
202
+ this.houseRulesPath = foundPath;
203
+ // Only log if not running as CLI
204
+ if (!process.argv[1]?.endsWith('house-rules-manager.js')) {
205
+ console.log(`Found house rules at: ${foundPath}`);
206
+ }
207
+ return foundPath;
208
+ }
209
+
210
+ return null;
211
+ }
212
+
213
+ /**
214
+ * Recursively search for house rules files
215
+ * @param {string} dir Directory to search
216
+ * @param {number} depth Current depth (to prevent infinite recursion)
217
+ * @returns {string|null} Path to house rules file or null
218
+ */
219
+ searchForHouseRules(dir, depth = 0) {
220
+ // Limit search depth to prevent excessive recursion
221
+ if (depth > 5) return null;
222
+
223
+ try {
224
+ const files = fs.readdirSync(dir);
225
+
226
+ for (const file of files) {
227
+ const filePath = path.join(dir, file);
228
+ const stat = fs.statSync(filePath);
229
+
230
+ // Check if it's a house rules file
231
+ if (stat.isFile() && /^houserules\.md$/i.test(file)) {
232
+ // Skip if it's in a DevOps agent directory
233
+ if (!filePath.includes('DevOpsAgent') &&
234
+ !filePath.includes('CS_DevOpsAgent') &&
235
+ !filePath.includes('node_modules') &&
236
+ !filePath.includes('.git')) {
237
+ return filePath;
238
+ }
239
+ }
240
+
241
+ // Recursively search subdirectories
242
+ if (stat.isDirectory() &&
243
+ !file.startsWith('.') &&
244
+ file !== 'node_modules' &&
245
+ file !== 'DevOpsAgent' &&
246
+ file !== 'CS_DevOpsAgent' &&
247
+ file !== '.git') {
248
+ const found = this.searchForHouseRules(filePath, depth + 1);
249
+ if (found) return found;
250
+ }
251
+ }
252
+ } catch (err) {
253
+ // Ignore permission errors and continue searching
254
+ if (err.code !== 'EACCES' && err.code !== 'EPERM') {
255
+ console.error(`Error searching ${dir}:`, err.message);
256
+ }
257
+ }
258
+
140
259
  return null;
141
260
  }
142
261
 
@@ -306,8 +425,24 @@ ${endMarker}`;
306
425
 
307
426
  // Create backup if requested
308
427
  if (backupExisting) {
309
- const backupPath = `${this.houseRulesPath}.backup.${Date.now()}`;
428
+ // Create backup in DevopsAgent_Backups folder
429
+ const backupDir = path.join(this.projectRoot, 'DevopsAgent_Backups');
430
+ if (!fs.existsSync(backupDir)) {
431
+ fs.mkdirSync(backupDir, { recursive: true });
432
+ // Ensure backup folder is in gitignore
433
+ this.ensureBackupInGitignore();
434
+ }
435
+
436
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
437
+ const backupFileName = `houserules_backup_${timestamp}.md`;
438
+ const backupPath = path.join(backupDir, backupFileName);
439
+
310
440
  fs.copyFileSync(this.houseRulesPath, backupPath);
441
+
442
+ // Only log if not running as CLI
443
+ if (!process.argv[1]?.endsWith('house-rules-manager.js')) {
444
+ console.log(`Backup created: ${backupPath}`);
445
+ }
311
446
  }
312
447
 
313
448
  // Build new content
@@ -367,6 +502,33 @@ ${endMarker}`;
367
502
  };
368
503
  }
369
504
 
505
+ /**
506
+ * Ensure backup folder is in gitignore
507
+ */
508
+ ensureBackupInGitignore() {
509
+ const gitignorePath = path.join(this.projectRoot, '.gitignore');
510
+ const backupPattern = 'DevopsAgent_Backups/';
511
+
512
+ try {
513
+ if (fs.existsSync(gitignorePath)) {
514
+ const content = fs.readFileSync(gitignorePath, 'utf8');
515
+
516
+ // Check if pattern already exists
517
+ if (!content.includes(backupPattern)) {
518
+ // Add to gitignore
519
+ const updatedContent = content.trimEnd() + '\n\n# DevOps Agent backup files\n' + backupPattern + '\n';
520
+ fs.writeFileSync(gitignorePath, updatedContent);
521
+ }
522
+ } else {
523
+ // Create gitignore with the pattern
524
+ const content = '# DevOps Agent backup files\n' + backupPattern + '\n';
525
+ fs.writeFileSync(gitignorePath, content);
526
+ }
527
+ } catch (err) {
528
+ // Silently fail - not critical if gitignore can't be updated
529
+ }
530
+ }
531
+
370
532
  /**
371
533
  * Get status of house rules
372
534
  */
@@ -422,22 +584,27 @@ ${endMarker}`;
422
584
  export default HouseRulesManager;
423
585
 
424
586
  // CLI interface when run directly
425
- if (import.meta.url === `file://${process.argv[1]}`) {
587
+ // Check if this is the main module being run
588
+ const isMainModule = import.meta.url === `file://${process.argv[1]}` ||
589
+ process.argv[1]?.endsWith('house-rules-manager.js');
590
+
591
+ if (isMainModule) {
426
592
  const manager = new HouseRulesManager();
427
593
  const command = process.argv[2];
428
594
 
429
595
  switch (command) {
430
596
  case 'status':
431
- console.log('House Rules Status:', JSON.stringify(manager.getStatus(), null, 2));
597
+ // Output only the JSON for the bash script to parse
598
+ console.log(JSON.stringify(manager.getStatus()));
432
599
  break;
433
600
 
434
601
  case 'update':
435
602
  manager.updateHouseRules().then(result => {
436
- console.log('Update Result:', JSON.stringify(result, null, 2));
603
+ console.log(JSON.stringify(result));
437
604
  });
438
605
  break;
439
606
 
440
607
  default:
441
608
  console.log('Usage: node house-rules-manager.js [status|update]');
442
609
  }
443
- }
610
+ }
@@ -81,6 +81,14 @@ class SessionCoordinator {
81
81
 
82
82
  getRepoRoot() {
83
83
  try {
84
+ // Check if we're in a submodule
85
+ const superproject = execSync('git rev-parse --show-superproject-working-tree', { encoding: 'utf8' }).trim();
86
+ if (superproject) {
87
+ // We're in a submodule, use the parent repository root
88
+ console.log(`${CONFIG.colors.dim}Running from submodule, using parent repository: ${superproject}${CONFIG.colors.reset}`);
89
+ return superproject;
90
+ }
91
+ // Not in a submodule, use current repository root
84
92
  return execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
85
93
  } catch (error) {
86
94
  console.error('Error: Not in a git repository');
@@ -711,11 +719,47 @@ class SessionCoordinator {
711
719
  const branchName = `${agentType}/${devInitials}/${sessionId}/${task.replace(/\s+/g, '-')}`;
712
720
 
713
721
  try {
722
+ // Detect if we're in a submodule and get the parent repository
723
+ let repoRoot = process.cwd();
724
+ let isSubmodule = false;
725
+ let parentRemote = null;
726
+
727
+ try {
728
+ // Check if we're in a submodule
729
+ execSync('git rev-parse --show-superproject-working-tree', { stdio: 'pipe' });
730
+ const superproject = execSync('git rev-parse --show-superproject-working-tree', { encoding: 'utf8' }).trim();
731
+
732
+ if (superproject) {
733
+ isSubmodule = true;
734
+ // Get the parent repository's remote
735
+ parentRemote = execSync(`git -C "${superproject}" remote get-url origin`, { encoding: 'utf8' }).trim();
736
+ console.log(`\n${CONFIG.colors.yellow}Detected submodule - will configure worktree for parent repository${CONFIG.colors.reset}`);
737
+ console.log(`${CONFIG.colors.dim}Parent repository: ${superproject}${CONFIG.colors.reset}`);
738
+ console.log(`${CONFIG.colors.dim}Parent remote: ${parentRemote}${CONFIG.colors.reset}`);
739
+ }
740
+ } catch (e) {
741
+ // Not a submodule, continue normally
742
+ }
743
+
714
744
  // Create worktree
715
745
  console.log(`\n${CONFIG.colors.yellow}Creating worktree...${CONFIG.colors.reset}`);
716
746
  execSync(`git worktree add -b ${branchName} "${worktreePath}" HEAD`, { stdio: 'pipe' });
717
747
  console.log(`${CONFIG.colors.green}✓${CONFIG.colors.reset} Worktree created at: ${worktreePath}`);
718
748
 
749
+ // If we're in a submodule, set up the correct remote for the worktree
750
+ if (isSubmodule && parentRemote) {
751
+ console.log(`${CONFIG.colors.yellow}Configuring worktree to use parent repository remote...${CONFIG.colors.reset}`);
752
+ // Remove the default origin that points to the submodule
753
+ try {
754
+ execSync(`git -C "${worktreePath}" remote remove origin`, { stdio: 'pipe' });
755
+ } catch (e) {
756
+ // Origin might not exist, continue
757
+ }
758
+ // Add the parent repository as origin
759
+ execSync(`git -C "${worktreePath}" remote add origin ${parentRemote}`, { stdio: 'pipe' });
760
+ console.log(`${CONFIG.colors.green}✓${CONFIG.colors.reset} Worktree configured to push to parent repository`);
761
+ }
762
+
719
763
  // Create session lock
720
764
  const lockData = {
721
765
  sessionId,
@@ -753,7 +797,7 @@ class SessionCoordinator {
753
797
  branchName,
754
798
  lockFile,
755
799
  instructionsFile,
756
- instructions: instructions.plaintext
800
+ task
757
801
  };
758
802
 
759
803
  } catch (error) {
@@ -763,7 +807,7 @@ class SessionCoordinator {
763
807
  }
764
808
 
765
809
  /**
766
- * Generate instructions for Claude/Cline
810
+ * Generate instructions for the coding agent
767
811
  */
768
812
  generateClaudeInstructions(sessionData) {
769
813
  const { sessionId, worktreePath, branchName, task } = sessionData;
@@ -812,7 +856,7 @@ INSTRUCTIONS:
812
856
  3. **Only proceed if no conflicts** - wait or choose different files if blocked
813
857
  4. **Release files when done** - delete your declaration after edits
814
858
 
815
- ## Instructions for Claude/Cline
859
+ ## Instructions for Your Coding Agent
816
860
 
817
861
  ### Step 1: Navigate to Your Worktree
818
862
  \`\`\`bash
@@ -874,11 +918,15 @@ The DevOps agent will automatically:
874
918
  * Display instructions in a user-friendly format
875
919
  */
876
920
  displayInstructions(instructions, sessionId, task) {
877
- console.log(`\n${CONFIG.colors.bgGreen}${CONFIG.colors.bright} Instructions for Claude/Cline ${CONFIG.colors.reset}\n`);
921
+ // Get the parent repository root (where the session was started from)
922
+ const parentRepoRoot = process.cwd();
923
+ const houseRulesPath = path.join(parentRepoRoot, 'houserules.md');
924
+
925
+ console.log(`\n${CONFIG.colors.bgGreen}${CONFIG.colors.bright} Instructions for Your Coding Agent ${CONFIG.colors.reset}\n`);
878
926
 
879
927
  // Clean separator
880
928
  console.log(`${CONFIG.colors.yellow}══════════════════════════════════════════════════════════════${CONFIG.colors.reset}`);
881
- console.log(`${CONFIG.colors.bright}COPY AND PASTE THIS ENTIRE BLOCK INTO CLAUDE BEFORE YOUR PROMPT:${CONFIG.colors.reset}`);
929
+ console.log(`${CONFIG.colors.bright}COPY AND PASTE THIS ENTIRE BLOCK INTO YOUR CODING AGENT BEFORE YOUR PROMPT:${CONFIG.colors.reset}`);
882
930
  console.log(`${CONFIG.colors.yellow}──────────────────────────────────────────────────────────────${CONFIG.colors.reset}`);
883
931
  console.log();
884
932
 
@@ -888,11 +936,13 @@ The DevOps agent will automatically:
888
936
  console.log(`- Working Directory: ${instructions.worktreePath}`);
889
937
  console.log(`- Task: ${task || 'development'}`);
890
938
  console.log(``);
939
+ console.log(`⚠️ IMPORTANT: DO NOT start working yet! Wait for the user's specific instructions.`);
940
+ console.log(``);
891
941
  console.log(`CRITICAL FIRST STEP:`);
892
- console.log(`1. Read and follow the house rules: cat "${instructions.worktreePath}/houserules.md"`);
942
+ console.log(`1. Read and follow the house rules: cat "${houseRulesPath}"`);
893
943
  console.log(`2. Switch to the working directory: cd "${instructions.worktreePath}"`);
894
944
  console.log(``);
895
- console.log(`FILE COORDINATION PROTOCOL (from house rules at ${instructions.worktreePath}/houserules.md):`);
945
+ console.log(`FILE COORDINATION PROTOCOL (from house rules at ${houseRulesPath}):`);
896
946
  console.log(`Before editing ANY files, you MUST:`);
897
947
  console.log(`- Declare your intent in .file-coordination/active-edits/<agent>-${sessionId}.json`);
898
948
  console.log(`- Check for conflicts with other agents`);
@@ -902,13 +952,17 @@ The DevOps agent will automatically:
902
952
  console.log(`Write commit messages to: .devops-commit-${sessionId}.msg`);
903
953
  console.log(`The DevOps agent will automatically commit and push changes.`);
904
954
  console.log(``);
905
- console.log(`Remember: ALWAYS check house rules first for the latest protocols!`);
955
+ console.log(`Remember: ALWAYS check house rules first, then WAIT for user instructions!`);
906
956
  console.log();
907
957
 
908
958
  console.log(`${CONFIG.colors.yellow}══════════════════════════════════════════════════════════════${CONFIG.colors.reset}`);
959
+ console.log();
960
+
961
+ // Pause before continuing
962
+ console.log(`${CONFIG.colors.dim}Press Enter to start the DevOps agent monitoring...${CONFIG.colors.reset}`);
909
963
 
910
964
  // Status info
911
- console.log(`\n${CONFIG.colors.green}✓ DevOps agent is starting...${CONFIG.colors.reset}`);
965
+ console.log(`${CONFIG.colors.green}✓ DevOps agent is starting...${CONFIG.colors.reset}`);
912
966
  console.log(`${CONFIG.colors.dim}Full instructions saved to: ${CONFIG.instructionsDir}/${sessionId}.md${CONFIG.colors.reset}`);
913
967
  }
914
968
 
@@ -1070,11 +1124,11 @@ The DevOps agent is monitoring this worktree for changes.
1070
1124
  fs.writeFileSync(lockFile, JSON.stringify(session, null, 2));
1071
1125
 
1072
1126
  const instructions = this.generateClaudeInstructions(session);
1073
- this.displayInstructions(instructions, session.sessionId, session.task);
1127
+ // Don't display instructions here - they'll be shown after agent starts
1074
1128
 
1075
1129
  return {
1076
1130
  ...session,
1077
- instructions: instructions.plaintext
1131
+ instructions: instructions
1078
1132
  };
1079
1133
  }
1080
1134
 
@@ -1223,11 +1277,21 @@ The DevOps agent is monitoring this worktree for changes.
1223
1277
 
1224
1278
  console.log(`\n${CONFIG.colors.yellow}Starting agent for session ${session.sessionId}...${CONFIG.colors.reset}`);
1225
1279
 
1226
- // Wait a moment for user to see instructions
1227
- await new Promise(resolve => setTimeout(resolve, 2000));
1228
-
1280
+ // Start the agent first
1229
1281
  await this.startAgent(session.sessionId);
1230
1282
 
1283
+ // Wait for agent to initialize and show its interactive commands
1284
+ await new Promise(resolve => setTimeout(resolve, 3000));
1285
+
1286
+ // Now display the instructions AFTER the agent is running
1287
+ console.log('\n'.repeat(2)); // Add some spacing
1288
+ // Create instructions object with worktreePath for display
1289
+ const instructionsForDisplay = {
1290
+ worktreePath: session.worktreePath,
1291
+ sessionId: session.sessionId
1292
+ };
1293
+ this.displayInstructions(instructionsForDisplay, session.sessionId, options.task || 'development');
1294
+
1231
1295
  return session;
1232
1296
  }
1233
1297
 
@@ -12,21 +12,27 @@
12
12
  #
13
13
  # ============================================================================
14
14
 
15
- # Colors for output
16
- RED='\033[0;31m'
17
- GREEN='\033[0;32m'
18
- YELLOW='\033[1;33m'
19
- BLUE='\033[0;36m'
20
- MAGENTA='\033[0;35m'
21
- BOLD='\033[1m'
22
- DIM='\033[2m'
23
- NC='\033[0m' # No Color
24
- BG_BLUE='\033[44m'
25
- BG_GREEN='\033[42m'
26
- BG_YELLOW='\033[43m'
15
+ # Colors for output (using printf for better compatibility)
16
+ RED=$'\033[0;31m'
17
+ GREEN=$'\033[0;32m'
18
+ YELLOW=$'\033[1;33m'
19
+ BLUE=$'\033[0;36m'
20
+ MAGENTA=$'\033[0;35m'
21
+ BOLD=$'\033[1m'
22
+ DIM=$'\033[2m'
23
+ NC=$'\033[0m' # No Color
24
+ BG_BLUE=$'\033[44m'
25
+ BG_GREEN=$'\033[42m'
26
+ BG_YELLOW=$'\033[43m'
27
27
 
28
- # Get the directory where this script is located
29
- SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
28
+ # Get the directory where this script is located (compatible with both bash and zsh)
29
+ if [[ -n "${BASH_SOURCE[0]}" ]]; then
30
+ # Running in bash
31
+ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
32
+ else
33
+ # Running in zsh
34
+ SCRIPT_DIR="${0:A:h}"
35
+ fi
30
36
  SRC_DIR="$SCRIPT_DIR/src"
31
37
 
32
38
  # Function to display copyright
@@ -64,10 +70,10 @@ display_instructions() {
64
70
  local task="$4"
65
71
 
66
72
  echo
67
- echo -e "${BG_GREEN}${BOLD} Instructions for Claude/Cline ${NC}"
73
+ echo -e "${BG_GREEN}${BOLD} Instructions for Your Coding Agent ${NC}"
68
74
  echo
69
75
  echo -e "${YELLOW}══════════════════════════════════════════════════════════════${NC}"
70
- echo -e "${BOLD}COPY AND PASTE THIS ENTIRE BLOCK INTO CLAUDE BEFORE YOUR PROMPT:${NC}"
76
+ echo -e "${BOLD}COPY AND PASTE THIS ENTIRE BLOCK INTO YOUR CODING AGENT BEFORE YOUR PROMPT:${NC}"
71
77
  echo -e "${YELLOW}──────────────────────────────────────────────────────────────${NC}"
72
78
  echo
73
79
  echo "I'm working in a DevOps-managed session with the following setup:"
@@ -154,7 +160,7 @@ create_new_session() {
154
160
  echo -e "${YELLOW}Creating session for: ${task_name}${NC}"
155
161
 
156
162
  # Run the session coordinator to create AND START the session
157
- cd "$SCRIPT_DIR"
163
+ # Keep current directory to ensure session is created for the right repo
158
164
  node "$SRC_DIR/session-coordinator.js" create-and-start --task "$task_name" --agent "$agent_type"
159
165
  }
160
166
 
@@ -215,7 +221,7 @@ select_session() {
215
221
  echo
216
222
  echo -e "${GREEN}Using existing session: ${session_id}${NC}"
217
223
 
218
- # Display instructions for Claude/Cline IMMEDIATELY after selection
224
+ # Display instructions for coding agent IMMEDIATELY after selection
219
225
  display_instructions "$session_id" "$worktree_path" "$branch_name" "$task"
220
226
 
221
227
  # Add a pause and visual separator before starting the agent
@@ -228,7 +234,7 @@ select_session() {
228
234
  echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
229
235
 
230
236
  # Start the agent for this session
231
- cd "$SCRIPT_DIR"
237
+ # Keep current directory to ensure agent runs in the right repo
232
238
  node "$SRC_DIR/session-coordinator.js" start "$session_id"
233
239
  return 0
234
240
  else
@@ -299,22 +305,46 @@ setup_house_rules() {
299
305
  local HOUSERULES_PATH=""
300
306
  local HOUSERULES_FOUND=false
301
307
 
302
- if [[ -f "$ROOT/houserules.md" ]]; then
303
- HOUSERULES_PATH="$ROOT/houserules.md"
304
- HOUSERULES_FOUND=true
305
- echo -e "${GREEN}✓${NC} Found existing house rules at: houserules.md"
306
- elif [[ -f "$ROOT/HOUSERULES.md" ]]; then
307
- HOUSERULES_PATH="$ROOT/HOUSERULES.md"
308
- HOUSERULES_FOUND=true
309
- echo -e "${GREEN}✓${NC} Found existing house rules at: HOUSERULES.md"
310
- elif [[ -f "$ROOT/.github/HOUSERULES.md" ]]; then
311
- HOUSERULES_PATH="$ROOT/.github/HOUSERULES.md"
312
- HOUSERULES_FOUND=true
313
- echo -e "${GREEN}✓${NC} Found existing house rules at: .github/HOUSERULES.md"
314
- elif [[ -f "$ROOT/docs/houserules.md" ]]; then
315
- HOUSERULES_PATH="$ROOT/docs/houserules.md"
308
+ # Function to search for house rules file
309
+ find_house_rules() {
310
+ local search_dir="$1"
311
+ local depth="${2:-0}"
312
+
313
+ # Limit search depth
314
+ if [[ $depth -gt 5 ]]; then
315
+ return 1
316
+ fi
317
+
318
+ # First check standard locations
319
+ for possible_path in "houserules.md" "HOUSERULES.md" ".github/HOUSERULES.md" "docs/houserules.md" "docs/HOUSERULES.md"; do
320
+ if [[ -f "$search_dir/$possible_path" ]]; then
321
+ echo "$search_dir/$possible_path"
322
+ return 0
323
+ fi
324
+ done
325
+
326
+ # If not found, search recursively (excluding DevOps directories)
327
+ while IFS= read -r -d '' file; do
328
+ local rel_path="${file#$search_dir/}"
329
+ if [[ ! "$file" =~ "DevOpsAgent" ]] &&
330
+ [[ ! "$file" =~ "CS_DevOpsAgent" ]] &&
331
+ [[ ! "$file" =~ "node_modules" ]] &&
332
+ [[ ! "$file" =~ ".git" ]]; then
333
+ echo "$file"
334
+ return 0
335
+ fi
336
+ done < <(find "$search_dir" -maxdepth 3 -type f \( -iname "houserules.md" -o -iname "HOUSERULES.md" \) -print0 2>/dev/null)
337
+
338
+ return 1
339
+ }
340
+
341
+ # Search for house rules file
342
+ if FOUND_PATH=$(find_house_rules "$ROOT"); then
343
+ HOUSERULES_PATH="$FOUND_PATH"
316
344
  HOUSERULES_FOUND=true
317
- echo -e "${GREEN}✓${NC} Found existing house rules at: docs/houserules.md"
345
+ # Make path relative for display
346
+ local REL_PATH="${FOUND_PATH#$ROOT/}"
347
+ echo -e "${GREEN}✓${NC} Found existing house rules at: $REL_PATH"
318
348
  else
319
349
  echo "No existing house rules found."
320
350
  echo
@@ -358,7 +388,8 @@ setup_house_rules() {
358
388
 
359
389
  # Run the actual setup inline (simplified version)
360
390
  if [[ -f "$SCRIPT_DIR/scripts/setup-file-coordination.sh" ]]; then
361
- bash "$SCRIPT_DIR/scripts/setup-file-coordination.sh"
391
+ # Pass the house rules path we already found!
392
+ HOUSERULES_PATH="$HOUSERULES_PATH" bash "$SCRIPT_DIR/scripts/setup-file-coordination.sh"
362
393
  else
363
394
  # Inline setup if script doesn't exist
364
395
  mkdir -p "$COORD_DIR/active-edits" "$COORD_DIR/completed-edits"
@@ -399,7 +430,7 @@ main() {
399
430
  echo
400
431
  echo "This tool will:"
401
432
  echo " 1. Help you create or select a session"
402
- echo " 2. Generate instructions for Claude/Cline"
433
+ echo " 2. Generate instructions for your coding agent"
403
434
  echo " 3. Start the DevOps agent to monitor changes"
404
435
  echo
405
436