@ghl-ai/aw 0.1.36-beta.111 → 0.1.36-beta.112

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/git.mjs +10 -45
  2. package/package.json +1 -1
package/git.mjs CHANGED
@@ -293,51 +293,16 @@ export async function fetchAndMerge(awHome, { silent = true } = {}) {
293
293
  let updated = false;
294
294
  const conflicts = [];
295
295
 
296
- // ── 3. Fast-forward (no local commits ahead of remote) ───────────────────
297
- // Use `merge-base --is-ancestor` to detect the fast-forward case, then
298
- // advance with `git reset --hard` instead of `merge --ff-only`.
299
- // Reason: `merge --ff-only` (and `merge --no-edit`) on git 2.46+ with
300
- // blob:none + no-cone sparse-checkout silently drops bare-name patterns
301
- // (e.g. "content", "CODEOWNERS") from the sparse-checkout config when HEAD
302
- // advances. `reset --hard` is semantically identical for a fast-forward
303
- // but does NOT go through the merge machinery, so the sparse-checkout
304
- // config is left untouched. We only call reset when we've confirmed there
305
- // are no local commits (is-ancestor exits 0), so push-branch commits are
306
- // never lost.
307
- let canFF = false;
308
- try {
309
- await exec(`git -C "${awHome}" merge-base --is-ancestor HEAD origin/${REGISTRY_BASE_BRANCH}`);
310
- canFF = true;
311
- } catch { /* local commits exist — not a fast-forward */ }
312
-
313
- if (canFF) {
314
- // Stash staged/unstaged changes to tracked files before reset --hard so
315
- // they are not lost. Untracked files (e.g. newly created skills not yet
316
- // staged) are untouched by reset --hard and need no stashing.
317
- let stashed = false;
318
- try {
319
- const { stdout } = await exec(`git -C "${awHome}" stash push -m "aw: pre-sync stash"`);
320
- stashed = !stdout.includes('No local changes to save');
321
- } catch { /* nothing to stash */ }
322
-
323
- const { stdout: headBefore } = await exec(`git -C "${awHome}" rev-parse HEAD`);
324
- await exec(`git -C "${awHome}" reset --hard origin/${REGISTRY_BASE_BRANCH}`);
325
- const { stdout: headAfter } = await exec(`git -C "${awHome}" rev-parse HEAD`);
326
- updated = headBefore.trim() !== headAfter.trim();
327
-
328
- if (stashed) {
329
- try {
330
- await exec(`git -C "${awHome}" stash pop`);
331
- } catch { /* conflict between stash and remote — leave markers for user */ }
332
- }
333
-
334
- return { updated, conflicts };
335
- }
336
-
337
- // ── 4. Rebase current branch onto remote REGISTRY_BASE_BRANCH ────────────
338
- // For push branches: stacks our local commits on top of latest remote.
339
- // For base branch: only reached if local commits exist (unusual).
340
- // Never uses --no-edit merge — that disables sparse checkout on blob:none.
296
+ // ── 3 + 4. Rebase onto remote REGISTRY_BASE_BRANCH ──────────────────────
297
+ // Handles both cases in one path:
298
+ // No local commits (base branch, clean tree) fast-forward via rebase
299
+ // Local commits (push branch) rebases on top
300
+ // Uncommitted local changes → rebase refuses to run,
301
+ // sync is skipped this run, changes are preserved
302
+ //
303
+ // We avoid `merge --ff-only` and `merge --no-edit` entirely: both trigger a
304
+ // git 2.46+ bug on blob:none + no-cone sparse-checkout repos that silently
305
+ // drops bare-name patterns (e.g. "content", "CODEOWNERS") when HEAD advances.
341
306
  try {
342
307
  await exec(`git -C "${awHome}" rebase origin/${REGISTRY_BASE_BRANCH}`);
343
308
  updated = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghl-ai/aw",
3
- "version": "0.1.36-beta.111",
3
+ "version": "0.1.36-beta.112",
4
4
  "description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
5
5
  "type": "module",
6
6
  "bin": "bin.js",