Skip to content

fix: edge case handling for update, add, and compose - #13

Merged
zekariasasaminew merged 1 commit into
mainfrom
fix/edge-cases
Mar 3, 2026
Merged

zekariasasaminew merged 1 commit into
mainfrom
fix/edge-cases

Conversation

@zekariasasaminew

Copy link
Copy Markdown
Owner

Fixes 3 bugs found during manual testing. 18 tests passing.

Copilot AI review requested due to automatic review settings March 3, 2026 16:13
@zekariasasaminew
zekariasasaminew merged commit 32118b4 into main Mar 3, 2026
3 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses edge cases discovered during manual testing across the update, add, and compose commands in instruct-sync, improving behavior when files are missing and when users try to add already-installed packs.

Changes:

  • update: restores missing target files even when the remote SHA hasn’t changed, and logs “restored” vs “updated”.
  • compose: skips missing pack files with clearer warnings and reports composed vs skipped counts.
  • add: attempts to prevent reinstalling an already-installed pack; README updated with common scenarios; new Vitest coverage added for update.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/update.test.ts Adds coverage for the “restore missing file even when SHA unchanged” and “skip when unchanged + file exists” update behaviors.
src/commands/update.ts Adds existence check for targets to decide between “already up to date” vs “restored/updated”.
src/commands/compose.ts Tracks composed count and improves warnings/logging when some target files are missing.
src/commands/add.ts Adds an “already installed” early-return path before fetching/writing.
README.md Documents common scenarios and expected CLI outputs for restore/add/compose/upgrade flows.
Comments suppressed due to low confidence (1)

src/commands/update.ts:6

  • ../lockfile.js is imported twice (once for readLockfile and again for addEntry). Consolidating into a single import avoids duplication and keeps the module imports consistent.
import { readLockfile } from "../lockfile.js";
import { parseSource, fetchFile } from "../github.js";
import { writeInstructions } from "../writer.js";
import { addEntry } from "../lockfile.js";

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/commands/compose.ts
Comment on lines +29 to +33
if (composed < entries.length) {
console.log(`✓ Composed ${composed} of ${entries.length} pack(s) → ${OUTPUT} (${entries.length - composed} skipped — run: instruct-sync update)`);
} else {
console.log(`✓ Composed ${composed} pack(s) → ${OUTPUT}`);
}

Copilot AI Mar 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compose() now changes user-facing behavior by tracking how many packs were actually composed and adjusting the final log line when some are skipped. There are no tests for compose currently; adding a Vitest test for the “missing file(s) → skipped count in output” case would help lock this behavior in.

Copilot uses AI. Check for mistakes.
Comment thread src/commands/add.ts
Comment on lines +7 to +15
const name = nameOrSource.startsWith("github:")
? nameOrSource.split("/").pop()!.replace(/\.md$/, "").replace(/^github:/, "")
: nameOrSource;

const existing = readLockfile().packs[name];
if (existing) {
console.log(`"${name}" is already installed at ${existing.target}. Run: instruct-sync update`);
return;
}

Copilot AI Mar 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The derived name for github: sources is computed from the raw input string, so it can include the @ref suffix (e.g. file.md@main) and won’t strip .md. This will create incorrect targets (like .github/instructions/file.md@main.instructions.md) and also bypass the “already installed” check for the same GitHub source. Derive the name from parseSource(source).path (basename) after parsing, so refs don’t affect naming.

Copilot uses AI. Check for mistakes.
Comment thread README.md
Comment on lines +91 to +95
```bash
npm install -g instruct-sync@latest
```

`npm install -g instruct-sync` without `@latest` will keep the cached version.

Copilot AI Mar 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README claims npm install -g instruct-sync without @latest “will keep the cached version”, but earlier in the README the same command is presented as the normal install method. npm install -g <pkg> already installs the latest dist-tag by default; consider removing or rewording this to avoid giving incorrect upgrade guidance.

Copilot uses AI. Check for mistakes.
Comment thread tests/update.test.ts
@@ -0,0 +1,69 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { mkdtempSync, mkdirSync, writeFileSync, existsSync } from "node:fs";

Copilot AI Mar 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import: existsSync is imported from node:fs but never used in this test file. Removing it will keep the test code clean and avoid unused-import lint failures if linting is added/enabled.

Suggested change
import { mkdtempSync, mkdirSync, writeFileSync, existsSync } from "node:fs";
import { mkdtempSync, mkdirSync, writeFileSync } from "node:fs";

Copilot uses AI. Check for mistakes.
Comment thread src/commands/add.ts
Comment on lines +11 to +15
const existing = readLockfile().packs[name];
if (existing) {
console.log(`"${name}" is already installed at ${existing.target}. Run: instruct-sync update`);
return;
}

Copilot AI Mar 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New behavior added to short-circuit add when a pack is already installed, but there are no tests covering this branch (including the expected console output / lack of network fetch). Adding a Vitest test for this case would prevent regressions.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants