@mrciphersmith/keryx 0.3.53 → 0.3.54

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 (3) hide show
  1. package/dist/cli.js +31 -17
  2. package/dist/core.js +29 -15
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -20100,7 +20100,7 @@ var package_default;
20100
20100
  var init_package = __esm(() => {
20101
20101
  package_default = {
20102
20102
  name: "@mrciphersmith/keryx",
20103
- version: "0.3.53",
20103
+ version: "0.3.54",
20104
20104
  description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
20105
20105
  private: false,
20106
20106
  publishConfig: {
@@ -57349,14 +57349,15 @@ async function showPrefix(cwd) {
57349
57349
  }
57350
57350
  return result.stdout.trim();
57351
57351
  }
57352
+ function rankOfRef(ref, headTargets) {
57353
+ if (/^refs\/remotes\/[^/]+\/(main|master)$/.test(ref)) {
57354
+ return 0;
57355
+ }
57356
+ return headTargets.has(ref) ? 1 : 2;
57357
+ }
57352
57358
  function orderRemoteRefs(entries, max = MAX_REFS) {
57353
57359
  const headTargets = new Set(entries.map((entry) => entry.symref).filter((symref) => symref.length > 0));
57354
- const rank = (ref) => {
57355
- if (/^refs\/remotes\/[^/]+\/(main|master)$/.test(ref)) {
57356
- return 0;
57357
- }
57358
- return headTargets.has(ref) ? 1 : 2;
57359
- };
57360
+ const rank = (ref) => rankOfRef(ref, headTargets);
57360
57361
  const candidates = entries.filter((entry) => entry.ref.startsWith("refs/remotes/") && !entry.ref.endsWith("/HEAD") && entry.symref === "").sort((a, b) => rank(a.ref) - rank(b.ref) || (a.ref < b.ref ? -1 : a.ref > b.ref ? 1 : 0));
57361
57362
  const seenTips = new Set;
57362
57363
  const refs = [];
@@ -57385,7 +57386,8 @@ async function remoteRefs(cwd) {
57385
57386
  }
57386
57387
  entries.push({ tip, ref, symref: symref ?? "" });
57387
57388
  }
57388
- return orderRemoteRefs(entries);
57389
+ const headTargets = new Set(entries.map((entry) => entry.symref).filter((symref) => symref.length > 0));
57390
+ return orderRemoteRefs(entries).map((ref) => ({ ref, primary: rankOfRef(ref, headTargets) < 2 }));
57389
57391
  }
57390
57392
  async function flowDirsOnRef(cwd, ref, flowsPath) {
57391
57393
  const result = await runGit2(cwd, ["ls-tree", "-z", "-d", "--name-only", "--full-tree", ref, "--", `${flowsPath}/`]);
@@ -57411,12 +57413,16 @@ async function knownRemoteFlowDirs(cwd) {
57411
57413
  while (next < refs.length) {
57412
57414
  const index = next;
57413
57415
  next += 1;
57414
- const ref = refs[index];
57415
- if (ref === undefined) {
57416
+ const entry = refs[index];
57417
+ if (entry === undefined) {
57416
57418
  continue;
57417
57419
  }
57418
- const short = ref.slice("refs/remotes/".length);
57419
- found[index] = (await flowDirsOnRef(cwd, ref, flowsPath)).map((dir) => ({ ref: short, dir }));
57420
+ const short = entry.ref.slice("refs/remotes/".length);
57421
+ found[index] = (await flowDirsOnRef(cwd, entry.ref, flowsPath)).map((dir) => ({
57422
+ ref: short,
57423
+ dir,
57424
+ primary: entry.primary
57425
+ }));
57420
57426
  }
57421
57427
  };
57422
57428
  await Promise.all(Array.from({ length: Math.min(CONCURRENCY, refs.length) }, () => worker()));
@@ -57608,7 +57614,7 @@ tracker reporting.
57608
57614
  - \`keryx flow recover <id> --reason "<why>"\` (moves a flow stuck in
57609
57615
  \`completing\` back to \`in-progress\`)
57610
57616
  - \`keryx flow block|unblock <id>\` / \`flow check\` (duplicate ids, including a
57611
- number a known remote branch holds; warns about a flow folder that is not
57617
+ number the default branch holds, warns about a number another remote branch holds and about a flow folder that is not
57612
57618
  committed) / \`flow renumber <dir> --to <id> --reason "<why>"\` (refuses an id a
57613
57619
  known remote branch uses)
57614
57620
 
@@ -58771,20 +58777,28 @@ function createFlowService(deps) {
58771
58777
  });
58772
58778
  }
58773
58779
  }
58780
+ const warnings = [];
58774
58781
  const remoteDirs = await knownRemoteFlowDirs(cwd);
58775
58782
  if (remoteDirs.length > 0) {
58776
58783
  for (const dir of allDirs) {
58777
- const clash = remoteDirs.find((entry) => entry.dir !== dir && flowNumberOfDir(entry.dir) === Number(flowIdOf(dir)));
58778
- if (clash) {
58784
+ const clashes = remoteDirs.filter((entry) => entry.dir !== dir && flowNumberOfDir(entry.dir) === Number(flowIdOf(dir)));
58785
+ const primary = clashes.find((entry) => entry.primary);
58786
+ const other = clashes[0];
58787
+ if (primary) {
58779
58788
  issues.push({
58780
58789
  flow: dir,
58781
58790
  kind: "duplicate-id",
58782
- message: `flow id ${flowIdOf(dir)} is also used on ${clash.ref} by a different flow (${safeDirName(clash.dir)})` + ` \u2014 repair with: keryx flow renumber ${dir} --to <free id> --reason "<why>"`
58791
+ message: `flow id ${flowIdOf(dir)} is also used on ${primary.ref} by a different flow (${safeDirName(primary.dir)})` + ` \u2014 repair with: keryx flow renumber ${dir} --to <free id> --reason "<why>"`
58792
+ });
58793
+ } else if (other) {
58794
+ warnings.push({
58795
+ flow: dir,
58796
+ kind: "branch-duplicate-id",
58797
+ message: `flow id ${flowIdOf(dir)} is also used on ${other.ref} by a different flow (${safeDirName(other.dir)});` + ` ignore it if that branch is stale, otherwise renumber one of them before it merges`
58783
58798
  });
58784
58799
  }
58785
58800
  }
58786
58801
  }
58787
- const warnings = [];
58788
58802
  const inHead = await flowFoldersInHead(cwd, allDirs).catch(() => {
58789
58803
  return null;
58790
58804
  });
package/dist/core.js CHANGED
@@ -26318,14 +26318,15 @@ async function showPrefix(cwd) {
26318
26318
  }
26319
26319
  return result.stdout.trim();
26320
26320
  }
26321
+ function rankOfRef(ref, headTargets) {
26322
+ if (/^refs\/remotes\/[^/]+\/(main|master)$/.test(ref)) {
26323
+ return 0;
26324
+ }
26325
+ return headTargets.has(ref) ? 1 : 2;
26326
+ }
26321
26327
  function orderRemoteRefs(entries, max = MAX_REFS) {
26322
26328
  const headTargets = new Set(entries.map((entry) => entry.symref).filter((symref) => symref.length > 0));
26323
- const rank = (ref) => {
26324
- if (/^refs\/remotes\/[^/]+\/(main|master)$/.test(ref)) {
26325
- return 0;
26326
- }
26327
- return headTargets.has(ref) ? 1 : 2;
26328
- };
26329
+ const rank = (ref) => rankOfRef(ref, headTargets);
26329
26330
  const candidates = entries.filter((entry) => entry.ref.startsWith("refs/remotes/") && !entry.ref.endsWith("/HEAD") && entry.symref === "").sort((a, b) => rank(a.ref) - rank(b.ref) || (a.ref < b.ref ? -1 : a.ref > b.ref ? 1 : 0));
26330
26331
  const seenTips = new Set;
26331
26332
  const refs = [];
@@ -26354,7 +26355,8 @@ async function remoteRefs(cwd) {
26354
26355
  }
26355
26356
  entries.push({ tip, ref, symref: symref ?? "" });
26356
26357
  }
26357
- return orderRemoteRefs(entries);
26358
+ const headTargets = new Set(entries.map((entry) => entry.symref).filter((symref) => symref.length > 0));
26359
+ return orderRemoteRefs(entries).map((ref) => ({ ref, primary: rankOfRef(ref, headTargets) < 2 }));
26358
26360
  }
26359
26361
  async function flowDirsOnRef(cwd, ref, flowsPath) {
26360
26362
  const result = await runGit2(cwd, ["ls-tree", "-z", "-d", "--name-only", "--full-tree", ref, "--", `${flowsPath}/`]);
@@ -26380,12 +26382,16 @@ async function knownRemoteFlowDirs(cwd) {
26380
26382
  while (next < refs.length) {
26381
26383
  const index = next;
26382
26384
  next += 1;
26383
- const ref = refs[index];
26384
- if (ref === undefined) {
26385
+ const entry = refs[index];
26386
+ if (entry === undefined) {
26385
26387
  continue;
26386
26388
  }
26387
- const short = ref.slice("refs/remotes/".length);
26388
- found[index] = (await flowDirsOnRef(cwd, ref, flowsPath)).map((dir) => ({ ref: short, dir }));
26389
+ const short = entry.ref.slice("refs/remotes/".length);
26390
+ found[index] = (await flowDirsOnRef(cwd, entry.ref, flowsPath)).map((dir) => ({
26391
+ ref: short,
26392
+ dir,
26393
+ primary: entry.primary
26394
+ }));
26389
26395
  }
26390
26396
  };
26391
26397
  await Promise.all(Array.from({ length: Math.min(CONCURRENCY, refs.length) }, () => worker()));
@@ -27373,20 +27379,28 @@ function createFlowService(deps) {
27373
27379
  });
27374
27380
  }
27375
27381
  }
27382
+ const warnings = [];
27376
27383
  const remoteDirs = await knownRemoteFlowDirs(cwd);
27377
27384
  if (remoteDirs.length > 0) {
27378
27385
  for (const dir of allDirs) {
27379
- const clash = remoteDirs.find((entry) => entry.dir !== dir && flowNumberOfDir(entry.dir) === Number(flowIdOf(dir)));
27380
- if (clash) {
27386
+ const clashes = remoteDirs.filter((entry) => entry.dir !== dir && flowNumberOfDir(entry.dir) === Number(flowIdOf(dir)));
27387
+ const primary = clashes.find((entry) => entry.primary);
27388
+ const other = clashes[0];
27389
+ if (primary) {
27381
27390
  issues.push({
27382
27391
  flow: dir,
27383
27392
  kind: "duplicate-id",
27384
- message: `flow id ${flowIdOf(dir)} is also used on ${clash.ref} by a different flow (${safeDirName(clash.dir)})` + ` \u2014 repair with: keryx flow renumber ${dir} --to <free id> --reason "<why>"`
27393
+ message: `flow id ${flowIdOf(dir)} is also used on ${primary.ref} by a different flow (${safeDirName(primary.dir)})` + ` \u2014 repair with: keryx flow renumber ${dir} --to <free id> --reason "<why>"`
27394
+ });
27395
+ } else if (other) {
27396
+ warnings.push({
27397
+ flow: dir,
27398
+ kind: "branch-duplicate-id",
27399
+ message: `flow id ${flowIdOf(dir)} is also used on ${other.ref} by a different flow (${safeDirName(other.dir)});` + ` ignore it if that branch is stale, otherwise renumber one of them before it merges`
27385
27400
  });
27386
27401
  }
27387
27402
  }
27388
27403
  }
27389
- const warnings = [];
27390
27404
  const inHead = await flowFoldersInHead(cwd, allDirs).catch(() => {
27391
27405
  return null;
27392
27406
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrciphersmith/keryx",
3
- "version": "0.3.53",
3
+ "version": "0.3.54",
4
4
  "description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
5
5
  "private": false,
6
6
  "publishConfig": {