@aramassa/ai-rules 0.4.3 → 0.5.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.
@@ -5,6 +5,7 @@ chatmode: planning
5
5
  tools:
6
6
  - "changes"
7
7
  - "searchResults"
8
+ - "createFile"
8
9
  - "editFiles"
9
10
  - "search"
10
11
  - "add_sub_issue"
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA+qBA;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,MAAY,GACpB,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BnB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAosBA;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,MAAY,GACpB,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BnB"}
package/dist/cli.js CHANGED
@@ -8,9 +8,11 @@ import require$$1 from 'node:child_process';
8
8
  import require$$2 from 'node:path';
9
9
  import require$$3$1 from 'node:fs';
10
10
  import require$$4 from 'node:process';
11
+ import readline from 'readline';
11
12
  import { fileURLToPath } from 'url';
12
13
  import { createHash } from 'crypto';
13
14
  import { homedir } from 'os';
15
+ import { execSync } from 'child_process';
14
16
 
15
17
  /******************************************************************************
16
18
  Copyright (c) Microsoft Corporation.
@@ -17810,6 +17812,15 @@ class RecipeValidator {
17810
17812
  return commonMistakeProps.includes(property);
17811
17813
  }
17812
17814
  checkCommonMistakes(recipeData, result) {
17815
+ // Validate pre-action if present
17816
+ if (recipeData['pre-action']) {
17817
+ if (!Array.isArray(recipeData['pre-action'])) {
17818
+ result.warnings.push('Warning: Pre-action should be an array');
17819
+ }
17820
+ else {
17821
+ this.validatePreActions(recipeData['pre-action'], result);
17822
+ }
17823
+ }
17813
17824
  // Check for properties that should be under filters or frontmatter
17814
17825
  if (Array.isArray(recipeData.recipe)) {
17815
17826
  recipeData.recipe.forEach((item, index) => {
@@ -17847,6 +17858,33 @@ class RecipeValidator {
17847
17858
  }
17848
17859
  });
17849
17860
  }
17861
+ validatePreActions(preActions, result) {
17862
+ for (let i = 0; i < preActions.length; i++) {
17863
+ const action = preActions[i];
17864
+ if (!action || typeof action !== 'object') {
17865
+ result.warnings.push(`Warning: Pre-action item ${i + 1} should be an object`);
17866
+ continue;
17867
+ }
17868
+ if (!action.type) {
17869
+ result.warnings.push(`Warning: Pre-action item ${i + 1} is missing required 'type' field`);
17870
+ continue;
17871
+ }
17872
+ if (action.type === 'git-pull') {
17873
+ if (!action.path) {
17874
+ result.warnings.push(`Warning: Git-pull action ${i + 1} is missing required 'path' field`);
17875
+ }
17876
+ if (action.depth !== undefined && typeof action.depth !== 'number') {
17877
+ result.warnings.push(`Warning: Git-pull action ${i + 1}: 'depth' should be a number`);
17878
+ }
17879
+ if (action.depth !== undefined && action.depth < 1) {
17880
+ result.warnings.push(`Warning: Git-pull action ${i + 1}: 'depth' should be at least 1`);
17881
+ }
17882
+ }
17883
+ else {
17884
+ result.warnings.push(`Warning: Pre-action item ${i + 1} has unknown type: ${action.type}`);
17885
+ }
17886
+ }
17887
+ }
17850
17888
  }
17851
17889
  // Singleton instance
17852
17890
  let validatorInstance = null;
@@ -17858,6 +17896,92 @@ async function getRecipeValidator() {
17858
17896
  return validatorInstance;
17859
17897
  }
17860
17898
 
17899
+ /**
17900
+ * Executes git pull in the specified repository
17901
+ * @param options - Configuration for the git pull operation
17902
+ * @param debugLogger - Optional debug logger
17903
+ * @returns Result of the git pull operation
17904
+ */
17905
+ async function executeGitPull(options, debugLogger) {
17906
+ try {
17907
+ // Verify it's a git repository
17908
+ const isRepo = await verifyGitRepository(options.path);
17909
+ if (!isRepo) {
17910
+ return {
17911
+ success: false,
17912
+ message: "Path is not a git repository",
17913
+ updated: false,
17914
+ };
17915
+ }
17916
+ // Switch to target branch if specified
17917
+ if (options.branch) {
17918
+ try {
17919
+ debugLogger?.log(`Switching to branch: ${options.branch}`);
17920
+ execSync(`git checkout ${options.branch}`, {
17921
+ cwd: options.path,
17922
+ encoding: "utf-8",
17923
+ stdio: "pipe",
17924
+ });
17925
+ }
17926
+ catch (error) {
17927
+ return {
17928
+ success: false,
17929
+ message: `Failed to checkout branch ${options.branch}: ${error.message}`,
17930
+ updated: false,
17931
+ };
17932
+ }
17933
+ }
17934
+ // Build git pull command
17935
+ let command = "git pull";
17936
+ if (options.depth) {
17937
+ command += ` --depth=${options.depth}`;
17938
+ }
17939
+ debugLogger?.log(`Executing: ${command} in ${options.path}`);
17940
+ // Execute git pull
17941
+ const output = execSync(command, {
17942
+ cwd: options.path,
17943
+ encoding: "utf-8",
17944
+ stdio: "pipe",
17945
+ });
17946
+ const updated = !output.includes("Already up to date");
17947
+ return {
17948
+ success: true,
17949
+ message: output.trim(),
17950
+ updated,
17951
+ };
17952
+ }
17953
+ catch (error) {
17954
+ return {
17955
+ success: false,
17956
+ message: error.message || "Unknown error",
17957
+ updated: false,
17958
+ };
17959
+ }
17960
+ }
17961
+ /**
17962
+ * Verifies that the given path is a git repository
17963
+ * @param repoPath - Path to verify
17964
+ * @returns True if the path is a git repository, false otherwise
17965
+ */
17966
+ async function verifyGitRepository(repoPath) {
17967
+ try {
17968
+ const gitDir = path.join(repoPath, ".git");
17969
+ if (!fsSync.existsSync(gitDir)) {
17970
+ return false;
17971
+ }
17972
+ // Verify with git command
17973
+ execSync("git rev-parse --git-dir", {
17974
+ cwd: repoPath,
17975
+ encoding: "utf-8",
17976
+ stdio: "pipe",
17977
+ });
17978
+ return true;
17979
+ }
17980
+ catch {
17981
+ return false;
17982
+ }
17983
+ }
17984
+
17861
17985
  const EXCLUDED_STATS_ATTRS = new Set(["human-instruction", "title"]);
17862
17986
  const MAX_IMPORT_DEPTH = 10;
17863
17987
  /**
@@ -18286,6 +18410,7 @@ function setupProgram() {
18286
18410
  .option("--debug", "Enable debug logging")
18287
18411
  .option("--verbose", "Enable verbose logging (alias for --debug)")
18288
18412
  .option("--dry-run", "Preview input/output files without writing")
18413
+ .option("-y, --yes", "Skip confirmation prompts (for pre-actions)")
18289
18414
  .action(async (options) => {
18290
18415
  await handleExtractCommand(options);
18291
18416
  });
@@ -18896,11 +19021,11 @@ async function handleExtractCommand(options) {
18896
19021
  await validateRecipeFilesExist(options.recipe);
18897
19022
  if (options.recipe.length === 1) {
18898
19023
  // Single recipe - maintain backward compatibility
18899
- await processRecipe(options.recipe[0], extractOptions, new ContentTracker(), debugLogger, options.baseDir, options.out, options.src);
19024
+ await processRecipe(options.recipe[0], extractOptions, new ContentTracker(), debugLogger, options.baseDir, options.out, options.src, options.yes);
18900
19025
  }
18901
19026
  else {
18902
19027
  // Multiple recipes - process in order with auto-append
18903
- await processMultipleRecipes(options.recipe, extractOptions, debugLogger, options.baseDir, options.out, options.src);
19028
+ await processMultipleRecipes(options.recipe, extractOptions, debugLogger, options.baseDir, options.out, options.src, options.yes);
18904
19029
  }
18905
19030
  }
18906
19031
  else {
@@ -18926,13 +19051,13 @@ async function handleStatsCommand(options) {
18926
19051
  /**
18927
19052
  * Processes multiple recipe files in the specified order
18928
19053
  */
18929
- async function processMultipleRecipes(recipePaths, baseOptions, debugLogger, cliBaseDir, cliOutFile, cliSrc) {
19054
+ async function processMultipleRecipes(recipePaths, baseOptions, debugLogger, cliBaseDir, cliOutFile, cliSrc, yesFlag) {
18930
19055
  const contentTracker = new ContentTracker();
18931
19056
  debugLogger.log(`Processing ${recipePaths.length} recipes in order`);
18932
19057
  for (const recipePath of recipePaths) {
18933
19058
  try {
18934
19059
  debugLogger.log(`Starting processing of recipe: ${recipePath}`);
18935
- await processRecipe(recipePath, baseOptions, contentTracker, debugLogger, cliBaseDir, cliOutFile, cliSrc);
19060
+ await processRecipe(recipePath, baseOptions, contentTracker, debugLogger, cliBaseDir, cliOutFile, cliSrc, yesFlag);
18936
19061
  debugLogger.log(`Completed processing of recipe: ${recipePath}`);
18937
19062
  }
18938
19063
  catch (error) {
@@ -19041,10 +19166,106 @@ async function processFrontmatterInheritance(frontmatter, srcDir, types, languag
19041
19166
  debugLogger?.log("Frontmatter after inheritance processing:", Object.keys(result));
19042
19167
  return result;
19043
19168
  }
19169
+ /**
19170
+ * Executes pre-actions defined in a recipe file
19171
+ */
19172
+ async function executePreActions(preActions, yesFlag, debugLogger) {
19173
+ const pulledRepos = new Set();
19174
+ console.log("[Pre-Action] Executing pre-actions...");
19175
+ for (let i = 0; i < preActions.length; i++) {
19176
+ const action = preActions[i];
19177
+ if (action.type === "git-pull") {
19178
+ await handleGitPullAction(action, pulledRepos, yesFlag, debugLogger);
19179
+ }
19180
+ else {
19181
+ throw new Error(`Unknown pre-action type: ${action.type}`);
19182
+ }
19183
+ }
19184
+ console.log("[Pre-Action] All pre-actions completed successfully");
19185
+ }
19186
+ /**
19187
+ * Handles a git-pull pre-action
19188
+ */
19189
+ async function handleGitPullAction(action, pulledRepos, yesFlag, debugLogger) {
19190
+ // Check if git-pull should be skipped via environment variable
19191
+ if (process.env.SKIP_GIT_PULL === "true" || process.env.SKIP_GIT_PULL === "1") {
19192
+ console.log(`[Pre-Action] Skipping git-pull (SKIP_GIT_PULL=${process.env.SKIP_GIT_PULL})`);
19193
+ debugLogger?.log(`Git-pull skipped due to SKIP_GIT_PULL environment variable`);
19194
+ return;
19195
+ }
19196
+ // Expand environment variables in path
19197
+ const expandedPath = resolvePath(action.path);
19198
+ const normalizedPath = path.normalize(path.resolve(expandedPath));
19199
+ console.log(`[Pre-Action] Executing git-pull for: ${normalizedPath}`);
19200
+ // Check for duplicate pull
19201
+ if (pulledRepos.has(normalizedPath)) {
19202
+ console.log(`[Pre-Action] Skipping git-pull for: ${normalizedPath} (already pulled)`);
19203
+ debugLogger?.log(`Skipping duplicate git-pull: ${normalizedPath}`);
19204
+ return;
19205
+ }
19206
+ // Confirmation prompt (unless -y flag is set)
19207
+ if (!yesFlag) {
19208
+ const confirmed = await promptConfirmation(normalizedPath, action.branch);
19209
+ if (!confirmed) {
19210
+ throw new Error("Pre-action cancelled by user");
19211
+ }
19212
+ }
19213
+ else {
19214
+ console.log(`[Pre-Action] Auto-confirmed (--yes flag)`);
19215
+ }
19216
+ // Execute git pull
19217
+ console.log("[Pre-Action] Pulling latest changes...");
19218
+ const result = await executeGitPull({
19219
+ path: normalizedPath,
19220
+ branch: action.branch,
19221
+ depth: action.depth,
19222
+ skipOnError: action["skip-on-error"] ?? false,
19223
+ }, debugLogger);
19224
+ if (result.success) {
19225
+ const statusMsg = result.updated
19226
+ ? "✓ Git pull successful (changes pulled)"
19227
+ : "✓ Git pull successful (no changes)";
19228
+ console.log(`[Pre-Action] ${statusMsg}`);
19229
+ debugLogger?.log(`Git pull result: ${result.message}`);
19230
+ }
19231
+ else {
19232
+ const errorMsg = `✗ Error: ${result.message}`;
19233
+ console.error(`[Pre-Action] ${errorMsg}`);
19234
+ if (!action["skip-on-error"]) {
19235
+ throw new Error(`Pre-action failed: ${result.message}`);
19236
+ }
19237
+ else {
19238
+ console.warn("[Pre-Action] Continuing despite error (skip-on-error: true)");
19239
+ }
19240
+ }
19241
+ // Mark this repo as pulled
19242
+ pulledRepos.add(normalizedPath);
19243
+ }
19244
+ /**
19245
+ * Prompts the user for confirmation before executing git pull
19246
+ */
19247
+ async function promptConfirmation(repoPath, branch) {
19248
+ console.log("[Pre-Action] Git pull confirmation required:");
19249
+ console.log(` Repository: ${repoPath}`);
19250
+ if (branch) {
19251
+ console.log(` Branch: ${branch}`);
19252
+ }
19253
+ console.log("");
19254
+ const rl = readline.createInterface({
19255
+ input: process.stdin,
19256
+ output: process.stdout,
19257
+ });
19258
+ return new Promise((resolve) => {
19259
+ rl.question("Continue? (y/N): ", (answer) => {
19260
+ rl.close();
19261
+ resolve(answer.toLowerCase() === "y");
19262
+ });
19263
+ });
19264
+ }
19044
19265
  /**
19045
19266
  * Processes a recipe file with multiple extract operations
19046
19267
  */
19047
- async function processRecipe(recipePath, baseOptions, contentTracker, debugLogger, cliBaseDir, cliOutFile, cliSrc) {
19268
+ async function processRecipe(recipePath, baseOptions, contentTracker, debugLogger, cliBaseDir, cliOutFile, cliSrc, yesFlag) {
19048
19269
  const resolvedPath = resolveRecipePath(recipePath);
19049
19270
  debugLogger?.log(`Processing recipe at path: ${resolvedPath}`);
19050
19271
  try {
@@ -19055,6 +19276,10 @@ async function processRecipe(recipePath, baseOptions, contentTracker, debugLogge
19055
19276
  if (!Array.isArray(data?.recipe)) {
19056
19277
  throw new Error("Invalid recipe file: 'recipe' array not found");
19057
19278
  }
19279
+ // Execute pre-actions if defined
19280
+ if (data["pre-action"] && Array.isArray(data["pre-action"])) {
19281
+ await executePreActions(data["pre-action"], yesFlag || false, debugLogger);
19282
+ }
19058
19283
  // Validate recipe structure and show warnings
19059
19284
  debugLogger?.time("Recipe validation");
19060
19285
  try {
@@ -17,6 +17,7 @@ export declare class RecipeValidator {
17
17
  private getHelpfulMessageForProperty;
18
18
  private isCommonMistake;
19
19
  private checkCommonMistakes;
20
+ private validatePreActions;
20
21
  }
21
22
  export declare function getRecipeValidator(): Promise<RecipeValidator>;
22
23
  //# sourceMappingURL=recipeValidator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"recipeValidator.d.ts","sourceRoot":"","sources":["../src/recipeValidator.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,MAAM,CAAM;;IAWd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBjC;;OAEG;IACH,OAAO,CAAC,eAAe;IAsBvB,cAAc,CAAC,UAAU,EAAE,GAAG,GAAG,gBAAgB;IA0CjD,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,4BAA4B;IAYpC,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,mBAAmB;CAyC5B;AAKD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC,CAMnE"}
1
+ {"version":3,"file":"recipeValidator.d.ts","sourceRoot":"","sources":["../src/recipeValidator.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,MAAM,CAAM;;IAWd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBjC;;OAEG;IACH,OAAO,CAAC,eAAe;IAsBvB,cAAc,CAAC,UAAU,EAAE,GAAG,GAAG,gBAAgB;IA0CjD,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,4BAA4B;IAYpC,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,mBAAmB;IAmD3B,OAAO,CAAC,kBAAkB;CA+B3B;AAKD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC,CAMnE"}
@@ -131,6 +131,15 @@ export class RecipeValidator {
131
131
  return commonMistakeProps.includes(property);
132
132
  }
133
133
  checkCommonMistakes(recipeData, result) {
134
+ // Validate pre-action if present
135
+ if (recipeData['pre-action']) {
136
+ if (!Array.isArray(recipeData['pre-action'])) {
137
+ result.warnings.push('Warning: Pre-action should be an array');
138
+ }
139
+ else {
140
+ this.validatePreActions(recipeData['pre-action'], result);
141
+ }
142
+ }
134
143
  // Check for properties that should be under filters or frontmatter
135
144
  if (Array.isArray(recipeData.recipe)) {
136
145
  recipeData.recipe.forEach((item, index) => {
@@ -168,6 +177,33 @@ export class RecipeValidator {
168
177
  }
169
178
  });
170
179
  }
180
+ validatePreActions(preActions, result) {
181
+ for (let i = 0; i < preActions.length; i++) {
182
+ const action = preActions[i];
183
+ if (!action || typeof action !== 'object') {
184
+ result.warnings.push(`Warning: Pre-action item ${i + 1} should be an object`);
185
+ continue;
186
+ }
187
+ if (!action.type) {
188
+ result.warnings.push(`Warning: Pre-action item ${i + 1} is missing required 'type' field`);
189
+ continue;
190
+ }
191
+ if (action.type === 'git-pull') {
192
+ if (!action.path) {
193
+ result.warnings.push(`Warning: Git-pull action ${i + 1} is missing required 'path' field`);
194
+ }
195
+ if (action.depth !== undefined && typeof action.depth !== 'number') {
196
+ result.warnings.push(`Warning: Git-pull action ${i + 1}: 'depth' should be a number`);
197
+ }
198
+ if (action.depth !== undefined && action.depth < 1) {
199
+ result.warnings.push(`Warning: Git-pull action ${i + 1}: 'depth' should be at least 1`);
200
+ }
201
+ }
202
+ else {
203
+ result.warnings.push(`Warning: Pre-action item ${i + 1} has unknown type: ${action.type}`);
204
+ }
205
+ }
206
+ }
171
207
  }
172
208
  // Singleton instance
173
209
  let validatorInstance = null;
@@ -0,0 +1,25 @@
1
+ export interface GitPullOptions {
2
+ path: string;
3
+ branch?: string;
4
+ depth?: number;
5
+ skipOnError?: boolean;
6
+ }
7
+ export interface GitPullResult {
8
+ success: boolean;
9
+ message: string;
10
+ updated: boolean;
11
+ }
12
+ /**
13
+ * Executes git pull in the specified repository
14
+ * @param options - Configuration for the git pull operation
15
+ * @param debugLogger - Optional debug logger
16
+ * @returns Result of the git pull operation
17
+ */
18
+ export declare function executeGitPull(options: GitPullOptions, debugLogger?: any): Promise<GitPullResult>;
19
+ /**
20
+ * Verifies that the given path is a git repository
21
+ * @param repoPath - Path to verify
22
+ * @returns True if the path is a git repository, false otherwise
23
+ */
24
+ export declare function verifyGitRepository(repoPath: string): Promise<boolean>;
25
+ //# sourceMappingURL=gitActions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitActions.d.ts","sourceRoot":"","sources":["../../src/utils/gitActions.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,WAAW,CAAC,EAAE,GAAG,GAChB,OAAO,CAAC,aAAa,CAAC,CA2DxB;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAkB5E"}
@@ -0,0 +1,88 @@
1
+ import { execSync } from "child_process";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ /**
5
+ * Executes git pull in the specified repository
6
+ * @param options - Configuration for the git pull operation
7
+ * @param debugLogger - Optional debug logger
8
+ * @returns Result of the git pull operation
9
+ */
10
+ export async function executeGitPull(options, debugLogger) {
11
+ try {
12
+ // Verify it's a git repository
13
+ const isRepo = await verifyGitRepository(options.path);
14
+ if (!isRepo) {
15
+ return {
16
+ success: false,
17
+ message: "Path is not a git repository",
18
+ updated: false,
19
+ };
20
+ }
21
+ // Switch to target branch if specified
22
+ if (options.branch) {
23
+ try {
24
+ debugLogger?.log(`Switching to branch: ${options.branch}`);
25
+ execSync(`git checkout ${options.branch}`, {
26
+ cwd: options.path,
27
+ encoding: "utf-8",
28
+ stdio: "pipe",
29
+ });
30
+ }
31
+ catch (error) {
32
+ return {
33
+ success: false,
34
+ message: `Failed to checkout branch ${options.branch}: ${error.message}`,
35
+ updated: false,
36
+ };
37
+ }
38
+ }
39
+ // Build git pull command
40
+ let command = "git pull";
41
+ if (options.depth) {
42
+ command += ` --depth=${options.depth}`;
43
+ }
44
+ debugLogger?.log(`Executing: ${command} in ${options.path}`);
45
+ // Execute git pull
46
+ const output = execSync(command, {
47
+ cwd: options.path,
48
+ encoding: "utf-8",
49
+ stdio: "pipe",
50
+ });
51
+ const updated = !output.includes("Already up to date");
52
+ return {
53
+ success: true,
54
+ message: output.trim(),
55
+ updated,
56
+ };
57
+ }
58
+ catch (error) {
59
+ return {
60
+ success: false,
61
+ message: error.message || "Unknown error",
62
+ updated: false,
63
+ };
64
+ }
65
+ }
66
+ /**
67
+ * Verifies that the given path is a git repository
68
+ * @param repoPath - Path to verify
69
+ * @returns True if the path is a git repository, false otherwise
70
+ */
71
+ export async function verifyGitRepository(repoPath) {
72
+ try {
73
+ const gitDir = path.join(repoPath, ".git");
74
+ if (!fs.existsSync(gitDir)) {
75
+ return false;
76
+ }
77
+ // Verify with git command
78
+ execSync("git rev-parse --git-dir", {
79
+ cwd: repoPath,
80
+ encoding: "utf-8",
81
+ stdio: "pipe",
82
+ });
83
+ return true;
84
+ }
85
+ catch {
86
+ return false;
87
+ }
88
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aramassa/ai-rules",
3
- "version": "0.4.3",
3
+ "version": "0.5.1",
4
4
  "description": "This repository collects guidelines and instructions for developing AI agents. It contains documents covering communication rules, coding standards, testing strategies, and general operational practices.",
5
5
  "workspaces": [
6
6
  "packages/extract",
@@ -14,6 +14,53 @@
14
14
  },
15
15
  "additionalProperties": false
16
16
  },
17
+ "pre-action": {
18
+ "type": "array",
19
+ "description": "Actions to execute before processing recipe items",
20
+ "items": {
21
+ "type": "object",
22
+ "properties": {
23
+ "type": {
24
+ "type": "string",
25
+ "enum": ["git-pull"],
26
+ "description": "Type of pre-action to execute"
27
+ },
28
+ "path": {
29
+ "type": "string",
30
+ "description": "Path to the git repository (for git-pull action)"
31
+ },
32
+ "branch": {
33
+ "type": "string",
34
+ "description": "Specific branch to pull (optional)"
35
+ },
36
+ "depth": {
37
+ "type": "number",
38
+ "minimum": 1,
39
+ "description": "Shallow clone depth (optional)"
40
+ },
41
+ "skip-on-error": {
42
+ "type": "boolean",
43
+ "description": "Whether to continue on error (default: false)"
44
+ }
45
+ },
46
+ "required": ["type"],
47
+ "allOf": [
48
+ {
49
+ "if": {
50
+ "properties": {
51
+ "type": {
52
+ "const": "git-pull"
53
+ }
54
+ }
55
+ },
56
+ "then": {
57
+ "required": ["path"]
58
+ }
59
+ }
60
+ ],
61
+ "additionalProperties": false
62
+ }
63
+ },
17
64
  "recipe": {
18
65
  "type": "array",
19
66
  "description": "Array of recipe items",