Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d68b06d
feat(claude): commands adapter, import-all, import --user
dldinternet Mar 10, 2026
ed2255b
fix(import-all): handle no-op force imports gracefully
dldinternet Mar 10, 2026
8f3f548
fix(claude-commands): change mode from file to hybrid
dldinternet Mar 10, 2026
c3d224c
fix(claude-agents,claude-rules): change mode from file to hybrid
dldinternet Mar 10, 2026
4d0e193
chore: release v0.7.0
dldinternet Mar 10, 2026
ae2a4c1
feat(claude): add output-styles, status-lines, agent-memory, settings…
Mar 12, 2026
48a47fc
chore: remove linkany version from output, bump to 0.8.0-beta.2
Mar 16, 2026
58508b5
Merge pull request #1 from softwarecatscomgm/feat/agt-9-new-claude-ad…
softwarecatscomgm Mar 17, 2026
c281175
fix: update vitest to ^4.1.0 to match @vitest/coverage-v8 peer depend…
dldinternet Mar 19, 2026
54e0167
0.8.0-beta.3
dldinternet Mar 19, 2026
26c777f
feat(claude): add status-lines, agent-memory, settings adapters; remo…
dldinternet Mar 20, 2026
fc3b068
feat: add claude adapters, list command, sync engine improvements
dldinternet Mar 23, 2026
ae49f79
chore: add agent-memory, kiro, and nwave config dirs
dldinternet Mar 23, 2026
3e9ec3f
fix: add minimal test suite to debug-mock.test.ts to prevent empty su…
dldinternet Mar 23, 2026
c46959c
feat: upstream-merge
dldinternet Mar 23, 2026
b0386f8
chore: Prepare for upstream-merge
dldinternet Mar 23, 2026
4d1f325
chore: .nwave
dldinternet Mar 23, 2026
d6a856b
chore: .nwave
dldinternet Mar 23, 2026
efef8b1
chore: merge down .kiro
dldinternet Mar 23, 2026
78ea2eb
chore: add upstream-merge spec files and merge notes from Tasks 1-2
dldinternet Mar 23, 2026
a5862e2
merge upstream aa53caac..6b562a3
dldinternet Mar 23, 2026
b39b2ee
fix: post-merge corrections and finalized merge documentation
dldinternet Mar 23, 2026
b9a8352
ci: add test workflow for PRs and main pushes
dldinternet Mar 23, 2026
b266fa1
fix(ci): let pnpm version come from package.json packageManager field
dldinternet Mar 23, 2026
cebf546
ci: add coverage script and use it in CI
dldinternet Mar 23, 2026
98bfcf9
Merge pull request #3 from softwarecatscomgm/feat/upstream-merge-2026…
softwarecatscomgm Mar 23, 2026
f818b33
chore: add coverage/ to gitignore
dldinternet Mar 23, 2026
f57847a
feat: improve test coverage to 91% stmts, 80% branches, 92% funcs
dldinternet Mar 23, 2026
7af1afc
chore: enter changesets beta pre-release mode
dldinternet Mar 23, 2026
2ecaffd
chore: replace stale changeset with upstream-merge and coverage entries
dldinternet Mar 23, 2026
77178d1
ci: strip npm publishing from release workflow, keep PR creation only
dldinternet Mar 24, 2026
51bc51f
chore: set fork version to 0.8.2-beta.1 to stay ahead of upstream 0.8.1
dldinternet Mar 24, 2026
8a46c1b
chore: change upstream-merge changeset to patch to stay in 0.8.2-beta…
dldinternet Mar 24, 2026
e2738f1
chore: release versions (beta)
github-actions[bot] Mar 24, 2026
285824d
Merge pull request #8 from softwarecatscomgm/changeset-release/main
softwarecatscomgm Mar 24, 2026
4c8f006
chore: trigger release workflow
dldinternet Mar 24, 2026
cd3b61d
Merge branch 'main' of sc.github.com:softwarecatscomgm/ai-rules-sync
dldinternet Mar 24, 2026
5d98907
chore: add changeset for CI improvements
dldinternet Mar 24, 2026
0dd808c
chore: release versions (beta)
github-actions[bot] Mar 24, 2026
24b1fd1
Merge pull request #9 from softwarecatscomgm/changeset-release/main
softwarecatscomgm Mar 24, 2026
9a1fc3f
feat(claude): add --local flag to list command for on-disk file disco…
dldinternet Mar 24, 2026
c95dfff
feat(claude): add --diff flag to list command for unified status table
dldinternet Mar 24, 2026
33f9ec1
fix(claude): use fixed-width columns in diff quiet mode instead of tabs
dldinternet Mar 24, 2026
6590199
feat(claude): split diff Repo column into Repo(P) and Repo(U) for pro…
dldinternet Mar 24, 2026
b80129f
fix: use userTargetDir and userDefaultSourceDir in import preview for…
dldinternet Mar 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/ci-improvements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ai-rules-sync": patch
---

Add CI workflow for PRs and coverage reporting
5 changes: 5 additions & 0 deletions .changeset/fix-user-import-preview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ai-rules-sync": patch
---

Fix --user import preview using wrong repo destination (defaultSourceDir instead of userDefaultSourceDir)
5 changes: 5 additions & 0 deletions .changeset/list-diff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ai-rules-sync": patch
---

Add --diff flag to ais claude list showing unified table with Local/Repo/User status columns
5 changes: 5 additions & 0 deletions .changeset/list-local.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ai-rules-sync": patch
---

Add --local flag to ais claude list for discovering on-disk Claude files not managed by ais
12 changes: 12 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"mode": "pre",
"tag": "beta",
"initialVersions": {
"ai-rules-sync": "0.8.2-beta.1"
},
"changesets": [
"ci-improvements",
"test-coverage",
"upstream-merge"
]
}
5 changes: 5 additions & 0 deletions .changeset/test-coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ai-rules-sync": patch
---

Improve test coverage from 67% to 91% statements, 80% branches, 92% functions. Add vitest coverage configuration with enforced thresholds. Add 18 new test files covering git, plugins, commands, adapters, dotany, and utilities (802 total tests).
5 changes: 5 additions & 0 deletions .changeset/upstream-merge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ai-rules-sync": patch
---

Merge upstream lbb00/ai-rules-sync (aa53caac..6b562a3) bringing sourceDir object format, init --only/--exclude, wildcard config fallback, and VitePress documentation site. All fork features preserved.
23 changes: 23 additions & 0 deletions .claude/agent-memory/kiro-spec-design-agent/MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Spec Design Agent Memory

## Project: ai-rules-sync

### Key patterns

- Design template at `.kiro/settings/templates/specs/design.md` does NOT exist in this project — use inline structure with note.
- Design rules at `.kiro/settings/rules/design-principles.md` do NOT exist in this project — proceed without them.
- Requirements approval check: auto-approve=false means check `spec.json` approvals.requirements.approved — if false, STOP unless instructed.
- `src/index.ts` is >25000 tokens and cannot be read in one call — use offset/limit to read relevant sections (the claude command block starts around line 1098).
- `adapterRegistry.getForTool('claude')` is the correct API to get all Claude adapters from the registry.
- `createBaseAdapter` in `src/adapters/base.ts` is the factory for all adapters; `AdapterConfig` and `SyncAdapter` in `types.ts` are the twin interfaces to update for new optional fields.
- `skipIgnore` in `SyncOptions`/`ImportOptions` is the user-mode signal throughout the codebase — always propagate it from `CommandContext` through to engine calls.
- Test files live in `src/__tests__/` with `.test.ts` suffix; mock `execa`, `project-config.js`, and `config.js` via `vi.mock`.

### Upstream merge context
- Upstream remote: `git@github.com:lbb00/ai-rules-sync.git`, remote name `upstream`
- Common ancestor: `aa53caac`, upstream HEAD: `6b562a3`
- Fork has 11 commits post-ancestor; upstream has unknown count but significant changes
- Both sides use same `sourceDir` object format: `{ [tool]: Record<string, string> }`
- WebFetch is blocked by context-mode plugin -- use WebSearch instead for external research
- Upstream npm latest is `0.4.0` but git HEAD is well beyond that
- Fork-only files (adapters, commands, tests) should survive merge cleanly unless upstream created same-path files independently
25 changes: 25 additions & 0 deletions .claude/agent-memory/kiro-spec-requirements-agent/MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Kiro Spec Requirements Agent Memory

## Project: ai-rules-sync

### Key File Paths
- Specs: `.kiro/specs/<feature>/requirements.md` and `spec.json`
- Steering: `.kiro/steering/product.md`, `tech.md`, `structure.md`
- EARS/template files do NOT exist in this project — use inline EARS knowledge

### EARS Format Rules (Inline Fallback)
- Ubiquitous: "The system SHALL..."
- Event-driven: "WHEN <trigger>, THEN the system SHALL..."
- State-driven: "WHILE <state>, the system SHALL..."
- Optional: "WHERE <feature>, the system SHALL..."
- Unwanted: "IF <condition>, THEN the system SHALL NOT..."
- Subject should be the product name or system, not "it"

### Adapter System Notes
- Claude adapters with `userTargetDir`: `claude-settings`, `claude-status-lines`
- `skipIgnore: true` in SyncOptions signals user mode throughout the pipeline
- `importEntry()` in `sync-engine.ts` uses `adapter.targetDir` for source resolution — does NOT check `skipIgnore` for user path (this is the known bug)
- `handleImport()` in `handlers.ts` does NOT pass `skipIgnore` into `importOpts` (second part of bug)

### Requirement Numbering
- Must use numeric IDs only in headings (e.g. "Requirement 1", "1."); never alphabetic (e.g. "Requirement A")
31 changes: 31 additions & 0 deletions .claude/agent-memory/kiro-spec-tasks-agent/MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Kiro Spec-Tasks Agent Memory

## Project: ai-rules-sync

### Settings directory
`.kiro/settings/` does not exist in this project. Rules and templates are absent.
Fallback: generate tasks from inline knowledge per the safety protocol.

### Approval handling
When auto-approve=false but the user explicitly invokes task generation, treat the
invocation as implicit approval intent. Update spec.json to set both requirements
and design approved=true. Note this in the output.

### Spec JSON phase values
- After design: `"phase": "design-generated"`
- After tasks: `"phase": "tasks-generated"`
- tasks approvals block: `{ "generated": true, "approved": false }`

### Language
All specs in this project use `"language": "en"`.

### Project conventions (from steering)
- TypeScript strict mode, ESM, `.js` extensions in imports
- vitest for tests, `src/__tests__/` directory
- `vi.mock` for execa and config reads; `os.tmpdir()` + fs-extra for real FS fixtures
- pnpm package manager
- 80% minimum test coverage
- Adapter files: `src/adapters/<tool>-<subtype>.ts`
- Commands barrel: `src/commands/index.ts`

See: patterns.md for task structure patterns
31 changes: 31 additions & 0 deletions .claude/agent-memory/kiro-spec-tdd-impl-agent/MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Agent Memory: kiro-spec-tdd-impl-agent

## Project: ai-rules-sync

### Key Facts
- Package manager: pnpm
- Test runner: `pnpm exec vitest run` (NOT `npx vitest`)
- TypeScript check: `pnpm tsc --noEmit`
- Coverage: `@vitest/coverage-v8` installed; `vitest.config.ts` created with v8 provider, text+json-summary reporters, 80% global thresholds
- Coverage exclusions in vitest.config.ts: `src/__tests__/**`, `src/index.ts`, `src/cli/register.ts`, `src/adapters/types.ts`, `src/dotany/types.ts`
- Pre-existing failing tests: resolved as of upstream-merge (agents-md tests updated for nested config)
- Vitest+Vitepress conflict: vitepress pulls vite 5.x, vitest needs vite >=6. Fix: add `"vite": "^7.0.0"` as explicit devDependency
- agents-md configPath is now `['agentsMd', 'file']` (nested), not flat `agentsMd`
- Import paths use `.js` extension even for `.ts` source files (ESM NodeNext)

### Patterns
- All test mocks use `vi.mock` with factory functions; `vi.resetAllMocks()` in `beforeEach`
- `vi.mock('fs-extra', async (importOriginal) => { ... })` pattern used for partial mocks
- Test fixtures use `os.tmpdir()` with `fs-extra.mkdtemp`; cleanup in `afterEach`
- Adapter tests use `runStandardAdapterContract` helper from `./helpers/adapter-contract.js`
- When mocking a class used with `new`, must use `class` syntax in vi.mock factory (arrow functions are not constructors in vitest v4)

### Already-implemented items (as of 2026-03-19)
The type-list feature implementation was already complete before the agent ran:
- `userDefaultSourceDir` field on `SyncAdapter` and `AdapterConfig` interfaces
- `importEntry` / `importEntryNoCommit` user-mode path branching in `sync-engine.ts`
- `handleImport` skipIgnore propagation in `handlers.ts`
- `src/commands/list.ts` with all 4 modes
- CLI registration in `src/index.ts`
- All test files: `claude-list.test.ts`, `sync-engine-user.test.ts`, `handlers-user-import.test.ts`
- Adapter tests extended for `userDefaultSourceDir`
13 changes: 13 additions & 0 deletions .claude/agent-memory/kiro-steering-agent/MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Kiro Steering Agent Memory

## Project: ai-rules-sync

Bootstrapped steering on 2026-03-19. Core files written to `.kiro/steering/`.

Key facts worth preserving:
- No templates exist at `.kiro/settings/templates/steering/`
- No principles file at `.kiro/settings/rules/steering-principles.md`
- The `src/dotany/` directory is named `dotany` in source but referred to as `dotfile` in KNOWLEDGE_BASE.md (it was previously `dotfile/`, then renamed). The import alias `from '../dotany/...'` is the live path.
- Adapters use factory functions not classes; `createBaseAdapter()` is the pattern for all adapters.
- All symlink ops go through `linkany` — never bare `fs.ensureSymlink`.
- ESM project: all imports need `.js` extensions even in `.ts` source files.
34 changes: 34 additions & 0 deletions .claude/agent-memory/kiro-validate-gap-agent/MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Kiro Validate-Gap Agent Memory

## Project: ai-rules-sync (SoftwareCats fork)

### Key Facts
- Fork of `git@github.com:lbb00/ai-rules-sync.git`
- Common ancestor: `aa53caac`
- Fork HEAD: `efef8b1` (main), Upstream HEAD: `6b562a3` (upstream/main)
- Fork version: `0.8.0-beta.3`, upstream npm: `0.4.0`
- Package manager: pnpm@9.15.3, ESM TypeScript

### Architecture Essentials
- Adapter-based plugin system: `SyncAdapter` interface in `src/adapters/types.ts`
- Factory: `createBaseAdapter()` in `src/adapters/base.ts`
- Registry: `DefaultAdapterRegistry` in `src/adapters/index.ts`
- CLI entry: `src/index.ts` (~2000+ lines, high-conflict file)
- Dotfile abstraction: `src/dotany/` (manager, composer, sources, manifest)
- Test baseline: 466 tests across 38 test files in `src/__tests__/`

### Tool Limitations
- No Bash tool available in this agent configuration
- WebFetch blocked by context-mode plugin; use WebSearch instead
- Git internals can be read via `.git/` directory (packed-refs, logs, config)
- Reflog at `.git/logs/refs/heads/main` provides full commit history
- Packed git objects (`.git/objects/pack/*.pack`) are binary and cannot be read with Read tool
- Cannot enumerate upstream commits without Bash (`git log`) -- reflog only covers local branches

### Gap Analysis Patterns
- When Bash is unavailable, read `.git/refs/remotes/*/main` for loose refs to confirm fetch status
- Use `.git/logs/refs/heads/main` to extract full local commit history with timestamps
- Import chain tracing via Grep is effective for identifying merge-critical dependencies
- Line-number grep on `src/index.ts` identifies exact fork-specific sections to preserve
- `docs/supported-tools.json` reveals adapter modes at fork point (useful for semantic conflict prediction)
- Gap analysis rules file at `.kiro/settings/rules/gap-analysis.md` does not exist in this project
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: CI

on:
pull_request:
branches: [main]
push:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20, 22]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm exec tsc --noEmit
- run: pnpm run build
- run: pnpm run coverage
50 changes: 1 addition & 49 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@ on:
- main
paths-ignore:
- Formula/ais.rb
workflow_dispatch:
inputs:
publish_test:
description: Publish a prerelease package to npm "test" tag
required: false
default: true
type: boolean

permissions:
contents: write
Expand All @@ -21,9 +14,6 @@ permissions:
jobs:
release:
runs-on: ubuntu-latest
outputs:
published: ${{ steps.changesets.outputs.published }}
published_version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -38,7 +28,6 @@ jobs:
with:
node-version: 20
cache: pnpm
registry-url: https://registry.npmjs.org

- name: Install dependencies
run: pnpm install --frozen-lockfile
Expand All @@ -49,48 +38,11 @@ jobs:
- name: Build
run: pnpm build

- name: Set unique prerelease version for test publish
id: test_version
if: github.event_name == 'workflow_dispatch' && inputs.publish_test
run: |
VERSION=$(node -e 'const fs=require("fs");const pkg=JSON.parse(fs.readFileSync("package.json","utf8"));const [major,minor,patch]=pkg.version.split("-")[0].split(".").map(Number);console.log([major,minor,patch+1].join(".")+"-test."+process.env.GITHUB_RUN_NUMBER+"."+process.env.GITHUB_RUN_ATTEMPT);')
npm version "$VERSION" --no-git-tag-version
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Publish npm test tag
if: github.event_name == 'workflow_dispatch' && inputs.publish_test
run: pnpm publish --tag test --no-git-checks
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Create release PR or publish
id: changesets
if: github.event_name != 'workflow_dispatch' || inputs.publish_test != true
- name: Create release PR
uses: changesets/action@v1.7.0
with:
version: pnpm changeset version
publish: pnpm changeset publish
title: "chore: release versions"
commit: "chore: release versions"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Resolve published version
id: version
if: steps.changesets.outputs.published == 'true'
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Summary for test publish
if: github.event_name == 'workflow_dispatch' && inputs.publish_test
run: echo "Published ai-rules-sync@${{ steps.test_version.outputs.version }} to npm tag 'test'."

update-homebrew:
needs: release
if: needs.release.outputs.published == 'true'
uses: ./.github/workflows/update-homebrew.yml
with:
version: ${{ needs.release.outputs.published_version }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ node_modules
# Local Cursor Rules Config
cursor-rules.local.json
dist
/coverage
.nwave

# VitePress
docs/.vitepress/dist
Expand Down
Loading