abapgit-agent 1.12.1 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -202,34 +202,82 @@ Examples:
202
202
  console.log(`\nšŸ”„ Updating abapGit Agent files`);
203
203
  console.log('');
204
204
 
205
- // Copy CLAUDE.md
206
- await copyFileIfExists(
207
- pathModule.join(__dirname, '..', '..', 'abap', 'CLAUDE.md'),
208
- pathModule.join(process.cwd(), 'CLAUDE.md'),
209
- 'CLAUDE.md'
210
- );
211
-
212
- // Copy copilot-instructions.md
213
- await copyFileIfExists(
214
- pathModule.join(__dirname, '..', '..', 'abap', '.github', 'copilot-instructions.md'),
215
- pathModule.join(process.cwd(), '.github', 'copilot-instructions.md'),
216
- '.github/copilot-instructions.md',
217
- true // create parent dir
218
- );
219
-
220
- // Copy guidelines folder to project root
221
- await copyGuidelinesFolder(
222
- pathModule.join(__dirname, '..', '..', 'abap', 'guidelines'),
223
- pathModule.join(process.cwd(), 'guidelines'),
224
- true // overwrite
225
- );
226
-
227
- // Detect and offer to remove old numbered guideline files
228
- await cleanupOldGuidelineFiles(pathModule.join(process.cwd(), 'guidelines'));
205
+ // copilot-instructions.md: never overwrite — user may have customised it
206
+ const localCopilotMdPath = pathModule.join(process.cwd(), '.github', 'copilot-instructions.md');
207
+ if (!fs.existsSync(localCopilotMdPath)) {
208
+ await copyFileIfExists(
209
+ pathModule.join(__dirname, '..', '..', 'abap', '.github', 'copilot-instructions.slim.md'),
210
+ localCopilotMdPath,
211
+ '.github/copilot-instructions.md',
212
+ true // create parent dir
213
+ );
214
+ } else {
215
+ console.log(`āš ļø .github/copilot-instructions.md already exists, skipped`);
216
+ }
217
+
218
+ // CLAUDE.md: never overwrite — user may have customised it
219
+ const localClaudeMdPath = pathModule.join(process.cwd(), 'CLAUDE.md');
220
+ if (!fs.existsSync(localClaudeMdPath)) {
221
+ await copyFileIfExists(
222
+ pathModule.join(__dirname, '..', '..', 'abap', 'CLAUDE.slim.md'),
223
+ localClaudeMdPath,
224
+ 'CLAUDE.md'
225
+ );
226
+ } else {
227
+ console.log(`āš ļø CLAUDE.md already exists, skipped (use 'abapgit-agent guide --migrate' to replace a full guide with the slim stub)`);
228
+ }
229
+
230
+ // guidelines/: never copy standard files — they're bundled in the package now.
231
+ // Only ensure objects.local.md stub exists if missing.
232
+ const guidelinesDestPath = pathModule.join(process.cwd(), 'guidelines');
233
+ if (!fs.existsSync(guidelinesDestPath)) {
234
+ fs.mkdirSync(guidelinesDestPath, { recursive: true });
235
+ console.log(`āœ… Created guidelines/`);
236
+ }
237
+ const localNamingPath = pathModule.join(guidelinesDestPath, 'objects.local.md');
238
+ if (!fs.existsSync(localNamingPath)) {
239
+ // reuse the same stub content as init
240
+ const localNamingStub = `---
241
+ nav_order: 8
242
+ ---
243
+
244
+ # Project Naming Conventions (Override)
245
+
246
+ This file overrides \`guidelines/objects.md\` for this project.
247
+ It is **never overwritten** by \`abapgit-agent init --update\` — safe to customise.
248
+
249
+ Searched by the \`ref\` command alongside all other guidelines.
250
+
251
+ ## Naming Conventions
252
+
253
+ Uncomment and edit the rows that differ from the defaults in \`guidelines/objects.md\`:
254
+
255
+ | Object Type | Prefix | Example |
256
+ |---|---|---|
257
+ | Class | ZCL_ | ZCL_MY_CLASS |
258
+ | Interface | ZIF_ | ZIF_MY_INTERFACE |
259
+ | Program | Z | ZMY_PROGRAM |
260
+ | Package | $ | $MY_PACKAGE |
261
+ | Table | Z | ZMY_TABLE |
262
+ | CDS View | ZC_ | ZC_MY_VIEW |
263
+ | CDS Entity | ZE_ | ZE_MY_ENTITY |
264
+ | Data Element | Z | ZMY_ELEMENT |
265
+ | Structure | Z | ZMY_STRUCTURE |
266
+ | Table Type | Z | ZMY_TABLE_TYPE |
267
+ `;
268
+ fs.writeFileSync(localNamingPath, localNamingStub);
269
+ console.log(`āœ… Created guidelines/objects.local.md`);
270
+ } else {
271
+ console.log(`āš ļø guidelines/objects.local.md already exists, skipped`);
272
+ }
273
+
274
+ // Detect and offer to remove old numbered guideline files (legacy cleanup)
275
+ await cleanupOldGuidelineFiles(guidelinesDestPath);
229
276
 
230
277
  console.log(`
231
278
  šŸ“‹ Update complete!
232
- Run 'abapgit-agent ref --list-topics' to see available topics.
279
+ Standard guidelines are read from the package automatically — no local copies needed.
280
+ Run 'abapgit-agent guide --migrate' if you still have copied guideline files to remove.
233
281
  `);
234
282
  return;
235
283
  }
@@ -386,66 +434,55 @@ Examples:
386
434
  console.log(`āœ… .gitignore already up to date`);
387
435
  }
388
436
 
389
- // Copy CLAUDE.md
390
- const claudeMdPath = pathModule.join(__dirname, '..', '..', 'abap', 'CLAUDE.md');
437
+ // Copy CLAUDE.md (slim stub — tells Claude to run 'abapgit-agent guide')
438
+ const claudeMdPath = pathModule.join(__dirname, '..', '..', 'abap', 'CLAUDE.slim.md');
391
439
  const localClaudeMdPath = pathModule.join(process.cwd(), 'CLAUDE.md');
392
440
  try {
393
- if (fs.existsSync(claudeMdPath)) {
441
+ if (fs.existsSync(localClaudeMdPath)) {
442
+ console.log(`āš ļø CLAUDE.md already exists, skipped`);
443
+ } else if (fs.existsSync(claudeMdPath)) {
394
444
  fs.copyFileSync(claudeMdPath, localClaudeMdPath);
395
445
  console.log(`āœ… Created CLAUDE.md`);
396
446
  } else {
397
- console.log(`āš ļø CLAUDE.md not found in abap/ directory`);
447
+ console.log(`āš ļø CLAUDE.slim.md not found in abap/ directory`);
398
448
  }
399
449
  } catch (error) {
400
450
  console.error(`Error copying CLAUDE.md: ${error.message}`);
401
451
  }
402
452
 
403
- // Copy copilot-instructions.md for GitHub Copilot
404
- const copilotMdPath = pathModule.join(__dirname, '..', '..', 'abap', '.github', 'copilot-instructions.md');
453
+ // Copy copilot-instructions.md for GitHub Copilot (slim stub)
454
+ const copilotMdPath = pathModule.join(__dirname, '..', '..', 'abap', '.github', 'copilot-instructions.slim.md');
405
455
  const githubDir = pathModule.join(process.cwd(), '.github');
406
456
  const localCopilotMdPath = pathModule.join(githubDir, 'copilot-instructions.md');
407
457
  try {
408
- if (fs.existsSync(copilotMdPath)) {
409
- // Ensure .github directory exists
458
+ if (fs.existsSync(localCopilotMdPath)) {
459
+ console.log(`āš ļø .github/copilot-instructions.md already exists, skipped`);
460
+ } else if (fs.existsSync(copilotMdPath)) {
410
461
  if (!fs.existsSync(githubDir)) {
411
462
  fs.mkdirSync(githubDir, { recursive: true });
412
463
  }
413
464
  fs.copyFileSync(copilotMdPath, localCopilotMdPath);
414
465
  console.log(`āœ… Created .github/copilot-instructions.md`);
415
466
  } else {
416
- console.log(`āš ļø copilot-instructions.md not found in abap/ directory`);
467
+ console.log(`āš ļø copilot-instructions.slim.md not found in abap/.github/ directory`);
417
468
  }
418
469
  } catch (error) {
419
470
  console.error(`Error copying copilot-instructions.md: ${error.message}`);
420
471
  }
421
472
 
422
- // Copy guidelines folder to project root
423
- const guidelinesSrcPath = pathModule.join(__dirname, '..', '..', 'abap', 'guidelines');
473
+ // Create guidelines/ directory and objects.local.md stub
474
+ // (Standard guidelines are bundled in the package — no need to copy them)
424
475
  const guidelinesDestPath = pathModule.join(process.cwd(), 'guidelines');
425
476
  try {
426
- if (fs.existsSync(guidelinesSrcPath)) {
427
- if (!fs.existsSync(guidelinesDestPath)) {
428
- // Create guidelines directory
429
- fs.mkdirSync(guidelinesDestPath, { recursive: true });
430
- // Copy all files from guidelines folder
431
- const files = fs.readdirSync(guidelinesSrcPath);
432
- for (const file of files) {
433
- if (file.endsWith('.md')) {
434
- fs.copyFileSync(
435
- pathModule.join(guidelinesSrcPath, file),
436
- pathModule.join(guidelinesDestPath, file)
437
- );
438
- }
439
- }
440
- console.log(`āœ… Created guidelines/ (${files.filter(f => f.endsWith('.md')).length} files)`);
441
- } else {
442
- console.log(`āš ļø guidelines/ already exists, skipped`);
443
- }
477
+ if (!fs.existsSync(guidelinesDestPath)) {
478
+ fs.mkdirSync(guidelinesDestPath, { recursive: true });
479
+ console.log(`āœ… Created guidelines/`);
480
+ }
444
481
 
445
- // Create objects.local.md stub if not already present
446
- const localNamingPath = pathModule.join(guidelinesDestPath, 'objects.local.md');
447
- if (!fs.existsSync(localNamingPath)) {
448
- const localNamingStub = `---
482
+ // Create objects.local.md stub if not already present
483
+ const localNamingPath = pathModule.join(guidelinesDestPath, 'objects.local.md');
484
+ if (!fs.existsSync(localNamingPath)) {
485
+ const localNamingStub = `---
449
486
  nav_order: 8
450
487
  ---
451
488
 
@@ -473,14 +510,11 @@ Uncomment and edit the rows that differ from the defaults in \`guidelines/object
473
510
  | Structure | Z | ZMY_STRUCTURE |
474
511
  | Table Type | Z | ZMY_TABLE_TYPE |
475
512
  `;
476
- fs.writeFileSync(localNamingPath, localNamingStub);
477
- console.log(`āœ… Created guidelines/objects.local.md (project naming conventions)`);
478
- }
479
- } else {
480
- console.log(`āš ļø guidelines folder not found in abap/ directory`);
513
+ fs.writeFileSync(localNamingPath, localNamingStub);
514
+ console.log(`āœ… Created guidelines/objects.local.md (project naming conventions)`);
481
515
  }
482
516
  } catch (error) {
483
- console.error(`Error copying guidelines: ${error.message}`);
517
+ console.error(`Error creating guidelines: ${error.message}`);
484
518
  }
485
519
 
486
520
  // Create folder
@@ -533,6 +567,11 @@ Uncomment and edit the rows that differ from the defaults in \`guidelines/object
533
567
  1. Edit .abapGitAgent with your ABAP credentials (host, user, password)
534
568
  2. Run 'abapgit-agent create --import' to create online repository
535
569
  3. Run 'abapgit-agent pull' to activate objects
570
+
571
+ šŸ’” Tips:
572
+ • Only guidelines/objects.local.md needs to live in your repo.
573
+ Standard guidelines are read from the package automatically via 'ref'.
574
+ • Run 'abapgit-agent guide' to read the full ABAP development guide.
536
575
  `);
537
576
  }
538
577
  };
@@ -323,6 +323,13 @@ module.exports = {
323
323
  if (success === 'X' || success === true) {
324
324
  console.log(`āœ… Pull completed successfully!`);
325
325
  console.log(` Message: ${message || 'N/A'}`);
326
+ } else if (failedCount === 0 && failedObjects.length === 0 &&
327
+ activatedCount === 0 && logMessages.length === 0 &&
328
+ (!message || /activation cancelled|nothing to activate|already active/i.test(message))) {
329
+ // abapGit returns SUCCESS='' with "Activation cancelled" when there are
330
+ // no inactive objects to activate — the object is already active and consistent.
331
+ console.log(`āœ… Pull completed — object already active, nothing to activate.`);
332
+ console.log(` Message: ${message || 'N/A'}`);
326
333
  } else {
327
334
  console.error(`āŒ Pull completed with errors!`);
328
335
  console.error(` Message: ${message || 'N/A'}`);
@@ -431,8 +438,12 @@ module.exports = {
431
438
  console.log(`\nāŒ Failed Objects Log (${failedCount})`);
432
439
  }
433
440
 
434
- // Throw if pull was not successful so callers (e.g. upgrade) can detect failure
435
- if (success !== 'X' && success !== true) {
441
+ // Throw if pull was not successful so callers (e.g. upgrade) can detect failure.
442
+ // Exception: SUCCESS='' with no failures and no log = object already active, not a real error.
443
+ const alreadyActive = failedCount === 0 && failedObjects.length === 0 &&
444
+ activatedCount === 0 && logMessages.length === 0 &&
445
+ (!message || /activation cancelled|nothing to activate|already active/i.test(message));
446
+ if (success !== 'X' && success !== true && !alreadyActive) {
436
447
  const err = new Error(message || 'Pull completed with errors');
437
448
  err._isPullError = true;
438
449
  throw err;