workflow-ai 1.0.27 → 1.0.28

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/runner.mjs +34 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workflow-ai",
3
- "version": "1.0.27",
3
+ "version": "1.0.28",
4
4
  "description": "AI Agent Workflow Coordinator — kanban-based pipeline for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/src/runner.mjs CHANGED
@@ -655,13 +655,16 @@ class FileGuard {
655
655
  }
656
656
 
657
657
  /**
658
- * Проверяет целостность защищённых файлов и откатывает несанкционированные изменения
658
+ * Проверяет целостность защищённых файлов и откатывает несанкционированные изменения.
659
+ * Обнаруживает как изменения/удаления существующих файлов, так и создание новых.
659
660
  * @returns {string[]} Список изменённых (и откаченных) файлов
660
661
  */
661
662
  checkAndRollback() {
662
- if (!this.enabled || this.snapshots.size === 0) return [];
663
+ if (!this.enabled) return [];
663
664
 
664
665
  const violations = [];
666
+
667
+ // 1. Проверяем файлы из снимка (изменённые или удалённые)
665
668
  for (const [filePath, originalHash] of this.snapshots) {
666
669
  const currentHash = this._hashFile(filePath);
667
670
  if (currentHash !== originalHash) {
@@ -671,6 +674,22 @@ class FileGuard {
671
674
  }
672
675
  }
673
676
 
677
+ // 2. Обнаруживаем новые файлы в защищённых директориях
678
+ for (const pattern of this.patterns) {
679
+ const baseDir = pattern.includes('*')
680
+ ? path.resolve(this.projectRoot, this._getBaseDir(pattern))
681
+ : path.resolve(this.projectRoot, pattern);
682
+
683
+ const currentFiles = this._getAllFiles(baseDir);
684
+ for (const filePath of currentFiles) {
685
+ if (this.matchesProtected(filePath) && !this.snapshots.has(filePath)) {
686
+ violations.push(filePath);
687
+ console.warn(`[FileGuard] WARNING: New file in protected area: ${filePath}`);
688
+ this._removeNewFile(filePath);
689
+ }
690
+ }
691
+ }
692
+
674
693
  if (violations.length > 0) {
675
694
  console.warn(`[FileGuard] WARNING: Rolled back ${violations.length} protected file(s): ${violations.join(', ')}`);
676
695
  } else {
@@ -680,6 +699,19 @@ class FileGuard {
680
699
  return violations;
681
700
  }
682
701
 
702
+ /**
703
+ * Удаляет файл, созданный агентом в защищённой директории
704
+ * @param {string} filePath - Путь к файлу
705
+ */
706
+ _removeNewFile(filePath) {
707
+ try {
708
+ fs.unlinkSync(filePath);
709
+ console.warn(`[FileGuard] WARNING: Removed unauthorized new file: ${filePath}`);
710
+ } catch (err) {
711
+ console.error(`[FileGuard] ERROR: Failed to remove ${filePath}: ${err.message}`);
712
+ }
713
+ }
714
+
683
715
  /**
684
716
  * Откатывает файл к последнему зафиксированному состоянию через git
685
717
  * @param {string} filePath - Путь к файлу