@ghl-ai/aw 0.1.83 → 0.1.84
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.
- package/commands/push.mjs +36 -24
- package/package.json +1 -1
package/commands/push.mjs
CHANGED
|
@@ -416,30 +416,28 @@ function resolveAwDocsPublishConfig(projectRoot) {
|
|
|
416
416
|
}
|
|
417
417
|
|
|
418
418
|
async function removeTrackedAwSymlink(cloneDir) {
|
|
419
|
+
const awPath = join(cloneDir, '.aw');
|
|
420
|
+
// Only ever touch a STRAY on-disk `.aw` symlink (e.g. one the IDE/worktree
|
|
421
|
+
// `aw link` hook drops into the cache clone). Remove it from the WORKTREE
|
|
422
|
+
// ONLY, with a filesystem unlink — never a git command.
|
|
423
|
+
//
|
|
424
|
+
// The docs repo may track a real `.aw/` tree (ghl-aw-docs tracks
|
|
425
|
+
// `.aw/.aw_rules/**`). A `git rm .aw` here would stage a deletion of that
|
|
426
|
+
// committed content and push it away (this is exactly what corrupted
|
|
427
|
+
// master-sync). A plain unlink cannot stage anything, so it can never delete
|
|
428
|
+
// the committed tree — and since `.aw` is kept out of the sparse cone, the
|
|
429
|
+
// tracked tree is SKIP_WORKTREE and unaffected by removing the disk symlink.
|
|
419
430
|
try {
|
|
420
|
-
if (!lstatSync(
|
|
431
|
+
if (!lstatSync(awPath).isSymbolicLink()) return false;
|
|
421
432
|
} catch {
|
|
422
433
|
return false;
|
|
423
434
|
}
|
|
424
|
-
|
|
425
435
|
try {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
encoding: 'utf8',
|
|
429
|
-
});
|
|
436
|
+
rmSync(awPath, { force: true });
|
|
437
|
+
return true;
|
|
430
438
|
} catch {
|
|
431
439
|
return false;
|
|
432
440
|
}
|
|
433
|
-
|
|
434
|
-
// `.aw` is always kept inside the sparse-checkout cone (see AW_DOCS_CACHE_PATH
|
|
435
|
-
// in ensureAwDocsRepoClone) so this remove works even on blobless/sparse
|
|
436
|
-
// clones. Without that, git rejects the rm with "outside sparse-checkout
|
|
437
|
-
// definition" against repos that track a real .aw/ tree (e.g. ghl-aw-docs).
|
|
438
|
-
await execFile('git', ['rm', '-f', '.aw'], {
|
|
439
|
-
cwd: cloneDir,
|
|
440
|
-
encoding: 'utf8',
|
|
441
|
-
});
|
|
442
|
-
return true;
|
|
443
441
|
}
|
|
444
442
|
|
|
445
443
|
function parseStatusPaths(status) {
|
|
@@ -484,9 +482,24 @@ async function selfHealManagedAwCacheDirtiness(cloneDir, status) {
|
|
|
484
482
|
});
|
|
485
483
|
|
|
486
484
|
if (await hasTrackedAwCachePaths(cloneDir)) {
|
|
485
|
+
// Restore a dirty tracked `.aw` from HEAD. In a full clone this cleans the
|
|
486
|
+
// worktree + index (the original behaviour). Best-effort (.catch): when `.aw`
|
|
487
|
+
// is sparse-excluded (out of cone) this pathspec can't match and the call is
|
|
488
|
+
// a no-op — but a sparse-excluded `.aw` is SKIP_WORKTREE and won't be dirty
|
|
489
|
+
// in the first place. This can only restore/un-stage, never delete tracked
|
|
490
|
+
// content.
|
|
487
491
|
await execFile('git', ['restore', '--staged', '--worktree', '--', '.aw'], {
|
|
488
492
|
cwd: cloneDir,
|
|
489
493
|
encoding: 'utf8',
|
|
494
|
+
}).catch((e) => {
|
|
495
|
+
const msg = (e?.stderr || e?.message || '').toString();
|
|
496
|
+
// Expected + ignorable: when `.aw` is sparse-excluded (out of cone) the
|
|
497
|
+
// pathspec cannot match, so the restore is simply a no-op.
|
|
498
|
+
if (/did not match any file|outside .*sparse-checkout/i.test(msg)) return;
|
|
499
|
+
// Anything else (permissions, index corruption, ...) is unexpected —
|
|
500
|
+
// surface it so a future `.aw` cache issue is diagnosable, but don't
|
|
501
|
+
// block the publish on a best-effort cleanup step.
|
|
502
|
+
fmt.logWarn(`AW docs cache: could not restore .aw (${msg.trim()})`);
|
|
490
503
|
});
|
|
491
504
|
}
|
|
492
505
|
|
|
@@ -583,12 +596,11 @@ async function getProjectSourceRepo(projectRoot) {
|
|
|
583
596
|
const AW_DOCS_GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: '0', GCM_INTERACTIVE: 'never' };
|
|
584
597
|
const AW_DOCS_CLONE_TIMEOUT_MS = Number(process.env.AW_DOCS_GIT_TIMEOUT_MS) || 180000;
|
|
585
598
|
const AW_DOCS_NET_TIMEOUT_MS = Number(process.env.AW_DOCS_GIT_TIMEOUT_MS) || 120000;
|
|
586
|
-
// `.aw` is
|
|
587
|
-
// real `.aw/` tree (
|
|
588
|
-
//
|
|
589
|
-
//
|
|
590
|
-
//
|
|
591
|
-
const AW_DOCS_CACHE_PATH = '.aw';
|
|
599
|
+
// NOTE: `.aw` is intentionally NOT added to the sparse cone. The docs repo may
|
|
600
|
+
// track a real `.aw/` tree (ghl-aw-docs tracks `.aw/.aw_rules/**`); keeping it
|
|
601
|
+
// out of the cone leaves that tree SKIP_WORKTREE so no publish can materialise
|
|
602
|
+
// or (crucially) stage a deletion of it. Any stray on-disk `.aw` symlink is
|
|
603
|
+
// removed worktree-only via a filesystem unlink (see removeTrackedAwSymlink).
|
|
592
604
|
|
|
593
605
|
async function awDocsSparseEnabled(cloneDir) {
|
|
594
606
|
try {
|
|
@@ -625,7 +637,7 @@ async function ensureAwDocsRepoClone(home, publishConfig, sparseIncludePaths = [
|
|
|
625
637
|
timeout: AW_DOCS_CLONE_TIMEOUT_MS,
|
|
626
638
|
});
|
|
627
639
|
if (wantSparse) {
|
|
628
|
-
await execFile('git', ['sparse-checkout', 'set', '--cone', ...sparseIncludePaths
|
|
640
|
+
await execFile('git', ['sparse-checkout', 'set', '--cone', ...sparseIncludePaths], {
|
|
629
641
|
cwd: cloneDir,
|
|
630
642
|
encoding: 'utf8',
|
|
631
643
|
}).catch(() => { /* sparse unsupported → full checkout below */ });
|
|
@@ -661,7 +673,7 @@ async function ensureAwDocsRepoClone(home, publishConfig, sparseIncludePaths = [
|
|
|
661
673
|
// clones that already use sparse-checkout (i.e. the blobless clones we
|
|
662
674
|
// created) — legacy full clones are left untouched so there is no regression.
|
|
663
675
|
if (wantSparse && await awDocsSparseEnabled(cloneDir)) {
|
|
664
|
-
await execFile('git', ['sparse-checkout', 'add', ...sparseIncludePaths
|
|
676
|
+
await execFile('git', ['sparse-checkout', 'add', ...sparseIncludePaths], {
|
|
665
677
|
cwd: cloneDir,
|
|
666
678
|
encoding: 'utf8',
|
|
667
679
|
}).catch(() => { /* best effort — checkout below still works */ });
|