agent-conf 2.1.1 → 2.2.0

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/dist/index.js CHANGED
@@ -67,9 +67,6 @@ var LockfileSchema = z.object({
67
67
  // src/core/lockfile.ts
68
68
  var CONFIG_DIR = ".agent-conf";
69
69
  var LOCKFILE_NAME = "lockfile.json";
70
- function getBuildCommit() {
71
- return true ? "641fa01067697521d17cc7883300f8e326a97724" : "unknown";
72
- }
73
70
  function getLockfilePath(targetDir) {
74
71
  return path.join(targetDir, CONFIG_DIR, LOCKFILE_NAME);
75
72
  }
@@ -114,28 +111,30 @@ function hashContent(content) {
114
111
  return `sha256:${hash.slice(0, 12)}`;
115
112
  }
116
113
  function getCliVersion() {
117
- return true ? "2.1.1" : "0.0.0";
114
+ return true ? "2.2.0" : "0.0.0";
118
115
  }
119
116
  async function checkCliVersionMismatch(targetDir) {
120
117
  const lockfile = await readLockfile(targetDir);
121
118
  if (!lockfile) {
122
119
  return null;
123
120
  }
124
- if (lockfile.source.type !== "github") {
125
- return null;
126
- }
127
- const cliCommit = getBuildCommit();
128
- const lockfileCommit = lockfile.source.commit_sha;
129
- if (cliCommit === "unknown") {
121
+ const currentVersion = getCliVersion();
122
+ const lockfileVersion = lockfile.cli_version;
123
+ if (!currentVersion || !lockfileVersion) {
130
124
  return null;
131
125
  }
132
- const cliShort = cliCommit.slice(0, 7);
133
- const lockfileShort = lockfileCommit.slice(0, 7);
134
- if (cliShort !== lockfileShort) {
135
- return {
136
- cliCommit: cliShort,
137
- lockfileCommit: lockfileShort
138
- };
126
+ const current = currentVersion.split(".").map(Number);
127
+ const lockfile_ = lockfileVersion.split(".").map(Number);
128
+ for (let i = 0; i < 3; i++) {
129
+ if ((lockfile_[i] || 0) > (current[i] || 0)) {
130
+ return {
131
+ currentVersion,
132
+ lockfileVersion
133
+ };
134
+ }
135
+ if ((current[i] || 0) > (lockfile_[i] || 0)) {
136
+ return null;
137
+ }
139
138
  }
140
139
  return null;
141
140
  }
@@ -896,6 +895,7 @@ async function deleteOrphanedSkills(targetDir, orphanedSkills, targets, previous
896
895
  }
897
896
 
898
897
  // src/commands/shared.ts
898
+ import * as fs12 from "fs/promises";
899
899
  import * as path12 from "path";
900
900
  import * as prompts3 from "@clack/prompts";
901
901
  import pc5 from "picocolors";
@@ -1660,8 +1660,7 @@ async function resolveVersion(options, status, _commandName, repo) {
1660
1660
  releaseInfo: release
1661
1661
  };
1662
1662
  } catch {
1663
- spinner.fail("Failed to fetch latest release, falling back to master");
1664
- logger.warn("Could not fetch latest release. Using master branch instead.");
1663
+ spinner.info("No releases found, using master branch");
1665
1664
  return {
1666
1665
  ref: "master",
1667
1666
  version: void 0,
@@ -1849,6 +1848,7 @@ async function performSync(options) {
1849
1848
  workflowSpinner.stop();
1850
1849
  }
1851
1850
  const hookResult = await installPreCommitHook(targetDir);
1851
+ const summaryLines = [];
1852
1852
  console.log();
1853
1853
  console.log(pc5.bold("Sync complete:"));
1854
1854
  console.log();
@@ -1856,38 +1856,71 @@ async function performSync(options) {
1856
1856
  if (result.agentsMd.merged) {
1857
1857
  const label = context.commandName === "sync" ? "(updated)" : "(merged)";
1858
1858
  console.log(` ${pc5.green("+")} ${agentsMdPath} ${pc5.dim(label)}`);
1859
+ summaryLines.push(`- \`AGENTS.md\` ${label}`);
1859
1860
  } else {
1860
1861
  console.log(` ${pc5.green("+")} ${agentsMdPath} ${pc5.dim("(created)")}`);
1862
+ summaryLines.push("- `AGENTS.md` (created)");
1861
1863
  }
1862
1864
  for (const targetResult of result.targets) {
1863
1865
  const config = getTargetConfig(targetResult.target);
1864
1866
  if (config.instructionsFile) {
1865
1867
  const instructionsPath = targetResult.instructionsMd.location === "root" ? formatPath(path12.join(targetDir, config.instructionsFile)) : formatPath(path12.join(targetDir, config.dir, config.instructionsFile));
1868
+ const instructionsRelPath = targetResult.instructionsMd.location === "root" ? config.instructionsFile : `${config.dir}/${config.instructionsFile}`;
1866
1869
  if (targetResult.instructionsMd.created) {
1867
1870
  console.log(` ${pc5.green("+")} ${instructionsPath} ${pc5.dim("(created)")}`);
1871
+ summaryLines.push(`- \`${instructionsRelPath}\` (created)`);
1868
1872
  } else if (targetResult.instructionsMd.updated) {
1869
1873
  const hint = targetResult.instructionsMd.contentMerged ? "(content merged into AGENTS.md, reference added)" : "(reference added)";
1870
1874
  console.log(` ${pc5.yellow("~")} ${instructionsPath} ${pc5.dim(hint)}`);
1875
+ summaryLines.push(`- \`${instructionsRelPath}\` ${hint}`);
1871
1876
  } else {
1872
1877
  console.log(` ${pc5.dim("-")} ${instructionsPath} ${pc5.dim("(unchanged)")}`);
1878
+ summaryLines.push(`- \`${instructionsRelPath}\` (unchanged)`);
1873
1879
  }
1874
1880
  }
1875
1881
  const skillsPath = formatPath(path12.join(targetDir, config.dir, "skills"));
1882
+ const skillsRelPath = `${config.dir}/skills/`;
1883
+ const newSkills = result.skills.synced.filter((s) => !previousSkills.includes(s)).sort();
1884
+ const updatedSkills = result.skills.synced.filter((s) => previousSkills.includes(s)).sort();
1885
+ const removedSkills = orphanResult.deleted.sort();
1876
1886
  console.log(
1877
1887
  ` ${pc5.green("+")} ${skillsPath}/ ${pc5.dim(`(${result.skills.synced.length} skills, ${targetResult.skills.copied} files)`)}`
1878
1888
  );
1879
- if (orphanResult.deleted.length > 0) {
1880
- for (const skill of orphanResult.deleted) {
1881
- const orphanPath = formatPath(path12.join(targetDir, config.dir, "skills", skill));
1882
- console.log(
1883
- ` ${pc5.red("-")} ${orphanPath}/ ${pc5.dim("(removed - no longer in source)")}`
1884
- );
1889
+ summaryLines.push(
1890
+ `- \`${skillsRelPath}\` (${result.skills.synced.length} skills, ${targetResult.skills.copied} files)`
1891
+ );
1892
+ const MAX_ITEMS_DEFAULT = 5;
1893
+ const shouldExpand = options.expandChanges === true;
1894
+ const formatSkillList = (skills, icon, colorFn, label, mdLabel) => {
1895
+ if (skills.length === 0) return;
1896
+ const maxDisplay = shouldExpand ? skills.length : MAX_ITEMS_DEFAULT;
1897
+ const displaySkills = skills.slice(0, maxDisplay);
1898
+ const hiddenCount = skills.length - displaySkills.length;
1899
+ for (const skill of displaySkills) {
1900
+ const skillPath = formatPath(path12.join(targetDir, config.dir, "skills", skill));
1901
+ const skillRelPath = `${config.dir}/skills/${skill}/`;
1902
+ console.log(` ${colorFn(icon)} ${skillPath}/ ${pc5.dim(`(${label})`)}`);
1903
+ summaryLines.push(` - \`${skillRelPath}\` (${mdLabel})`);
1885
1904
  }
1905
+ if (hiddenCount > 0) {
1906
+ console.log(` ${pc5.dim(` ... ${hiddenCount} more ${label}`)}`);
1907
+ summaryLines.push(` - ... ${hiddenCount} more ${mdLabel}`);
1908
+ }
1909
+ };
1910
+ formatSkillList(newSkills, "+", pc5.green, "new", "new");
1911
+ formatSkillList(updatedSkills, "~", pc5.yellow, "updated", "updated");
1912
+ for (const skill of removedSkills) {
1913
+ const orphanPath = formatPath(path12.join(targetDir, config.dir, "skills", skill));
1914
+ const orphanRelPath = `${config.dir}/skills/${skill}/`;
1915
+ console.log(` ${pc5.red("-")} ${orphanPath}/ ${pc5.dim("(removed)")}`);
1916
+ summaryLines.push(` - \`${orphanRelPath}\` (removed)`);
1886
1917
  }
1887
1918
  if (orphanResult.skipped.length > 0) {
1888
1919
  for (const skill of orphanResult.skipped) {
1889
1920
  const orphanPath = formatPath(path12.join(targetDir, config.dir, "skills", skill));
1890
- console.log(` ${pc5.yellow("!")} ${orphanPath}/ ${pc5.dim("(orphaned but skipped)")}`);
1921
+ const orphanRelPath = `${config.dir}/skills/${skill}/`;
1922
+ console.log(` ${pc5.yellow("!")} ${orphanPath}/ ${pc5.dim("(orphaned but skipped)")}`);
1923
+ summaryLines.push(` - \`${orphanRelPath}\` (orphaned but skipped)`);
1891
1924
  }
1892
1925
  }
1893
1926
  }
@@ -1895,29 +1928,37 @@ async function performSync(options) {
1895
1928
  for (const filename of workflowResult.created) {
1896
1929
  const workflowPath = formatPath(path12.join(targetDir, ".github/workflows", filename));
1897
1930
  console.log(` ${pc5.green("+")} ${workflowPath} ${pc5.dim("(created)")}`);
1931
+ summaryLines.push(`- \`.github/workflows/${filename}\` (created)`);
1898
1932
  }
1899
1933
  for (const filename of workflowResult.updated) {
1900
1934
  const workflowPath = formatPath(path12.join(targetDir, ".github/workflows", filename));
1901
1935
  console.log(` ${pc5.yellow("~")} ${workflowPath} ${pc5.dim("(updated)")}`);
1936
+ summaryLines.push(`- \`.github/workflows/${filename}\` (updated)`);
1902
1937
  }
1903
1938
  for (const filename of workflowResult.unchanged) {
1904
1939
  const workflowPath = formatPath(path12.join(targetDir, ".github/workflows", filename));
1905
1940
  console.log(` ${pc5.dim("-")} ${workflowPath} ${pc5.dim("(unchanged)")}`);
1941
+ summaryLines.push(`- \`.github/workflows/${filename}\` (unchanged)`);
1906
1942
  }
1907
1943
  }
1908
1944
  const lockfilePath = formatPath(path12.join(targetDir, ".agent-conf", "agent-conf.lock"));
1909
1945
  console.log(` ${pc5.green("+")} ${lockfilePath}`);
1946
+ summaryLines.push("- `.agent-conf/lockfile.json` (updated)");
1910
1947
  const hookPath = formatPath(path12.join(targetDir, ".git/hooks/pre-commit"));
1911
1948
  if (hookResult.installed) {
1912
1949
  if (hookResult.alreadyExisted && !hookResult.wasUpdated) {
1913
1950
  console.log(` ${pc5.dim("-")} ${hookPath} ${pc5.dim("(unchanged)")}`);
1951
+ summaryLines.push("- `.git/hooks/pre-commit` (unchanged)");
1914
1952
  } else if (hookResult.wasUpdated) {
1915
1953
  console.log(` ${pc5.yellow("~")} ${hookPath} ${pc5.dim("(updated)")}`);
1954
+ summaryLines.push("- `.git/hooks/pre-commit` (updated)");
1916
1955
  } else {
1917
1956
  console.log(` ${pc5.green("+")} ${hookPath} ${pc5.dim("(installed)")}`);
1957
+ summaryLines.push("- `.git/hooks/pre-commit` (installed)");
1918
1958
  }
1919
1959
  } else if (hookResult.alreadyExisted) {
1920
1960
  console.log(` ${pc5.yellow("!")} ${hookPath} ${pc5.dim("(skipped - custom hook exists)")}`);
1961
+ summaryLines.push("- `.git/hooks/pre-commit` (skipped - custom hook exists)");
1921
1962
  }
1922
1963
  console.log();
1923
1964
  console.log(pc5.dim(`Source: ${formatSourceString(resolvedSource.source)}`));
@@ -1927,6 +1968,19 @@ async function performSync(options) {
1927
1968
  if (targets.length > 1) {
1928
1969
  console.log(pc5.dim(`Targets: ${targets.join(", ")}`));
1929
1970
  }
1971
+ if (options.summaryFile) {
1972
+ const sourceStr = formatSourceString(resolvedSource.source);
1973
+ const versionStr = resolvedVersion.version ? `v${resolvedVersion.version}` : resolvedVersion.ref;
1974
+ const summary = `## Changes
1975
+
1976
+ ${summaryLines.join("\n")}
1977
+
1978
+ ---
1979
+ **Source:** ${sourceStr}
1980
+ **Version:** ${versionStr}
1981
+ `;
1982
+ await fs12.writeFile(options.summaryFile, summary, "utf-8");
1983
+ }
1930
1984
  prompts3.outro(pc5.green("Done!"));
1931
1985
  } catch (error) {
1932
1986
  syncSpinner.fail("Sync failed");
@@ -1977,7 +2031,7 @@ async function initCommand(options) {
1977
2031
  }
1978
2032
 
1979
2033
  // src/commands/init-canonical-repo.ts
1980
- import * as fs12 from "fs/promises";
2034
+ import * as fs13 from "fs/promises";
1981
2035
  import * as path13 from "path";
1982
2036
  import * as prompts5 from "@clack/prompts";
1983
2037
  import pc7 from "picocolors";
@@ -2160,7 +2214,7 @@ jobs:
2160
2214
  run: npm install -g agent-conf
2161
2215
 
2162
2216
  - name: Run sync
2163
- run: agent-conf sync --yes
2217
+ run: agent-conf sync --yes --summary-file /tmp/sync-summary.md --expand-changes
2164
2218
  env:
2165
2219
  GITHUB_TOKEN: \${{ secrets.token }}
2166
2220
 
@@ -2204,10 +2258,17 @@ jobs:
2204
2258
  env:
2205
2259
  GH_TOKEN: \${{ github.token }}
2206
2260
  run: |
2261
+ # Read sync summary if available
2262
+ if [ -f /tmp/sync-summary.md ]; then
2263
+ SYNC_SUMMARY=$(cat /tmp/sync-summary.md)
2264
+ else
2265
+ SYNC_SUMMARY="## Changes
2266
+ - Synced agent configuration from canonical repository"
2267
+ fi
2268
+
2207
2269
  PR_BODY="This PR was automatically created by the ${prefix} sync workflow.
2208
2270
 
2209
- ## Changes
2210
- - Synced agent configuration from canonical repository
2271
+ $SYNC_SUMMARY
2211
2272
 
2212
2273
  ---
2213
2274
  *This is an automated PR. Review the changes and merge when ready.*"
@@ -2397,27 +2458,27 @@ async function initCanonicalRepoCommand(options) {
2397
2458
  await ensureDir(skillsDir);
2398
2459
  await ensureDir(workflowsDir);
2399
2460
  const configPath = path13.join(resolvedOptions.targetDir, "agent-conf.yaml");
2400
- await fs12.writeFile(configPath, generateConfigYaml(resolvedOptions), "utf-8");
2461
+ await fs13.writeFile(configPath, generateConfigYaml(resolvedOptions), "utf-8");
2401
2462
  const agentsMdPath = path13.join(instructionsDir, "AGENTS.md");
2402
- await fs12.writeFile(agentsMdPath, generateAgentsMd(resolvedOptions), "utf-8");
2463
+ await fs13.writeFile(agentsMdPath, generateAgentsMd(resolvedOptions), "utf-8");
2403
2464
  if (resolvedOptions.includeExamples) {
2404
2465
  const exampleSkillDir = path13.join(skillsDir, "example-skill");
2405
2466
  const referencesDir = path13.join(exampleSkillDir, "references");
2406
2467
  await ensureDir(referencesDir);
2407
2468
  const skillMdPath = path13.join(exampleSkillDir, "SKILL.md");
2408
- await fs12.writeFile(skillMdPath, generateExampleSkillMd(), "utf-8");
2469
+ await fs13.writeFile(skillMdPath, generateExampleSkillMd(), "utf-8");
2409
2470
  const gitkeepPath = path13.join(referencesDir, ".gitkeep");
2410
- await fs12.writeFile(gitkeepPath, "", "utf-8");
2471
+ await fs13.writeFile(gitkeepPath, "", "utf-8");
2411
2472
  }
2412
2473
  const syncWorkflowPath = path13.join(workflowsDir, "sync-reusable.yml");
2413
2474
  const checkWorkflowPath = path13.join(workflowsDir, "check-reusable.yml");
2414
2475
  const repoFullName = resolvedOptions.organization ? `${resolvedOptions.organization}/${resolvedOptions.name}` : resolvedOptions.name;
2415
- await fs12.writeFile(
2476
+ await fs13.writeFile(
2416
2477
  syncWorkflowPath,
2417
2478
  generateSyncWorkflow2(repoFullName, resolvedOptions.markerPrefix),
2418
2479
  "utf-8"
2419
2480
  );
2420
- await fs12.writeFile(
2481
+ await fs13.writeFile(
2421
2482
  checkWorkflowPath,
2422
2483
  generateCheckWorkflow2(repoFullName, resolvedOptions.markerPrefix),
2423
2484
  "utf-8"
@@ -2602,7 +2663,9 @@ async function syncCommand(options) {
2602
2663
  },
2603
2664
  tempDir,
2604
2665
  yes: options.yes,
2605
- sourceRepo: repository
2666
+ sourceRepo: repository,
2667
+ summaryFile: options.summaryFile,
2668
+ expandChanges: options.expandChanges
2606
2669
  });
2607
2670
  }
2608
2671
 
@@ -2689,14 +2752,10 @@ async function warnIfCliOutdated() {
2689
2752
  console.log();
2690
2753
  console.log(
2691
2754
  pc11.yellow(
2692
- `\u26A0 CLI is outdated: built from ${mismatch.cliCommit}, but repo was synced from ${mismatch.lockfileCommit}`
2693
- )
2694
- );
2695
- console.log(
2696
- pc11.yellow(
2697
- " Rebuild the CLI: cd <agent-conf-repo>/cli && pnpm build && pnpm link --global"
2755
+ `\u26A0 CLI is outdated: v${mismatch.currentVersion} installed, but repo was synced with v${mismatch.lockfileVersion}`
2698
2756
  )
2699
2757
  );
2758
+ console.log(pc11.yellow(" Run: agent-conf upgrade-cli"));
2700
2759
  console.log();
2701
2760
  }
2702
2761
  } catch {
@@ -2718,7 +2777,7 @@ function createCli() {
2718
2777
  program.command("sync").description("Sync content from canonical repository (fetches latest by default)").option(
2719
2778
  "-s, --source <repo>",
2720
2779
  "Canonical repository in owner/repo format (e.g., acme/standards)"
2721
- ).option("--local [path]", "Use local canonical repository (auto-discover or specify path)").option("-y, --yes", "Non-interactive mode (merge by default)").option("--override", "Override existing AGENTS.md instead of merging").option("--ref <ref>", "GitHub ref/version to sync from").option("--pinned", "Use lockfile version without fetching latest").option("-t, --target <targets...>", "Target platforms (claude, codex)", ["claude"]).action(
2780
+ ).option("--local [path]", "Use local canonical repository (auto-discover or specify path)").option("-y, --yes", "Non-interactive mode (merge by default)").option("--override", "Override existing AGENTS.md instead of merging").option("--ref <ref>", "GitHub ref/version to sync from").option("--pinned", "Use lockfile version without fetching latest").option("-t, --target <targets...>", "Target platforms (claude, codex)", ["claude"]).option("--summary-file <path>", "Write sync summary to file (markdown, for CI)").option("--expand-changes", "Show all items in output (default: first 5)").action(
2722
2781
  async (options) => {
2723
2782
  await syncCommand(options);
2724
2783
  }