Skip to content
Merged
49 changes: 49 additions & 0 deletions skills/create-pr/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
name: create-pr
description: Push the current branch and create a Pull Request for ByteSync. Use when the user wants the agent to push a branch and open a PR, and requires the PR title and description in English.
---

# Request PR

## Overview

Provide a short workflow to push the current branch and open a Pull Request with an English title and description using the `gh` CLI.

## Workflow

### 1) Confirm branch state

Confirm the current branch name and whether there are uncommitted changes. If changes remain, ask whether to commit before pushing.

### 2) Push branch

Push the current branch to the remote. If the user did not specify a tool, default to using the `gh` CLI context and run a normal git push for the current branch.

Example:
```bash
git push -u origin HEAD
```

### 3) Create PR

Create a Pull Request using `gh pr create` with:

- English title
- English description summarizing changes and approach

### 4) Provide PR text template

Provide a minimal PR template to pass to `gh pr create`:

Title: `[type] Short summary`

Description:
- Summary:
- Key changes:
- Notes/risks:

Ensure the template is in English and matches the repo's PR format when applicable.

### 5) Keep it brief

Keep the response focused on the push + PR actions, avoiding extra steps unless the user asks.
Binary file added skills/dist/create-pr.skill
Binary file not shown.
Binary file added skills/dist/perform-implement-plan.skill
Binary file not shown.
47 changes: 47 additions & 0 deletions skills/perform-implement-plan/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
name: perform-implement-plan
description: Execute an implementation plan end-to-end in the ByteSync repo. Use when the user asks to implement a previously established plan step by step, requires creating a branch before coding, expects regular commits during progress, and wants build/test validation.
---

# Plan Implementation

## Overview

Implement a previously agreed plan in ByteSync, one step at a time, while enforcing branch creation and frequent commits.

## Workflow

### 1) Confirm plan scope

Restate the implementation plan in brief. If the plan is not present in the conversation, ask for it before starting.

### 2) Create a branch before implementation

Create a new branch before making any code changes. The branch name must follow ByteSync guidelines:

- Use one prefix only: `feature/`, `fix/`, `refactor/`, `docs/`, or `test/`
- Avoid extra slashes beyond the prefix
- Include the issue number if an issue exists (e.g., `feature/1234-add-sync-filter`)
- Add a short English description

### 3) Implement step by step

Implement the plan in small, ordered steps. After each step:

- Verify the change fits the plan
- Commit the work with a concise English message
- Keep commits focused and incremental

### 4) Respect repo conventions and validation

Follow the repo guidance (AGENTS.md), including:

- Do not add unnecessary comments
- Use FluentAssertions for tests
- Build and test as separate commands
- During intermediate commits, run only tests related to the changes when reasonable
- At the end, run the full solution tests

### 5) Keep the user informed

Provide short progress updates after each step and call out any blockers or missing details before proceeding.
22 changes: 20 additions & 2 deletions src/ByteSync.Client/Business/Inventories/InventoryProcessData.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reactive.Linq;
using System.Collections.Concurrent;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading;
using ByteSync.Interfaces.Controls.Inventories;
Expand All @@ -11,6 +12,7 @@ namespace ByteSync.Business.Inventories;
public class InventoryProcessData : ReactiveObject
{
private readonly object _monitorDataLock = new object();
private readonly ConcurrentQueue<SkippedEntry> _skippedEntries = new();

public InventoryProcessData()
{
Expand Down Expand Up @@ -101,6 +103,8 @@ public List<Inventory>? Inventories

public IObservable<InventoryMonitorData> InventoryMonitorObservable => InventoryMonitorDataSubject.AsObservable();

public IReadOnlyCollection<SkippedEntry> SkippedEntries => _skippedEntries.ToArray();

[Reactive]
public DateTimeOffset InventoryStart { get; set; }

Expand Down Expand Up @@ -131,8 +135,14 @@ public void Reset()
LastException = null;

InventoryMonitorDataSubject.OnNext(new InventoryMonitorData());
ClearSkippedEntries();
}

public void RecordSkippedEntry(SkippedEntry entry)
{
_skippedEntries.Enqueue(entry);
}

public void SetError(Exception exception)
{
LastException = exception;
Expand All @@ -150,4 +160,12 @@ public void UpdateMonitorData(Action<InventoryMonitorData> action)
InventoryMonitorDataSubject.OnNext(newValue);
}
}
}

private void ClearSkippedEntries()
{
while (_skippedEntries.TryDequeue(out _))
{
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ namespace ByteSync.Interfaces.Controls.Inventories;
public interface IFileSystemInspector
{
bool IsHidden(FileSystemInfo fsi, OSPlatforms os);
bool IsSystem(FileInfo fileInfo);
bool IsSystemAttribute(FileInfo fileInfo);
bool IsNoiseFileName(FileInfo fileInfo, OSPlatforms os);
bool IsReparsePoint(FileSystemInfo fsi);
bool Exists(FileInfo fileInfo);
bool IsOffline(FileInfo fileInfo);
bool IsRecallOnDataAccess(FileInfo fileInfo);
}
}
15 changes: 15 additions & 0 deletions src/ByteSync.Client/Models/Inventories/SkipReason.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace ByteSync.Models.Inventories;

public enum SkipReason
{
Unknown = 0,
Hidden = 1,
SystemAttribute = 2,
NoiseFile = 3,
Symlink = 4,
SpecialPosixFile = 5,
Offline = 6,
Inaccessible = 7,
NotFound = 8,
IoError = 9
}
18 changes: 18 additions & 0 deletions src/ByteSync.Client/Models/Inventories/SkippedEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using ByteSync.Business.Inventories;

namespace ByteSync.Models.Inventories;

public class SkippedEntry
{
public string FullPath { get; init; } = string.Empty;

public string RelativePath { get; init; } = string.Empty;

public string Name { get; init; } = string.Empty;

public SkipReason Reason { get; init; }

public FileSystemEntryKind? DetectedKind { get; init; }

public DateTime SkippedAt { get; init; } = DateTime.UtcNow;
}
18 changes: 14 additions & 4 deletions src/ByteSync.Client/Services/Inventories/FileSystemInspector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,22 @@ public bool IsHidden(FileSystemInfo fsi, OSPlatforms os)
return isHidden || isDot;
}

public bool IsSystem(FileInfo fileInfo)
public bool IsSystemAttribute(FileInfo fileInfo)
{
var isCommon = fileInfo.Name.In("desktop.ini", "thumbs.db", ".desktop.ini", ".thumbs.db", ".DS_Store");
var isSystem = (fileInfo.Attributes & FileAttributes.System) == FileAttributes.System;

return isCommon || isSystem;
return isSystem;
}

public bool IsNoiseFileName(FileInfo fileInfo, OSPlatforms os)
{
var comparison = os == OSPlatforms.Linux ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;

return fileInfo.Name.Equals("desktop.ini", comparison)
|| fileInfo.Name.Equals("thumbs.db", comparison)
|| fileInfo.Name.Equals(".desktop.ini", comparison)
|| fileInfo.Name.Equals(".thumbs.db", comparison)
|| fileInfo.Name.Equals(".DS_Store", comparison);
}

public bool IsReparsePoint(FileSystemInfo fsi)
Expand All @@ -43,4 +53,4 @@ public bool IsRecallOnDataAccess(FileInfo fileInfo)
{
return (((int)fileInfo.Attributes) & FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS) == FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS;
}
}
}
Loading
Loading