@baton-dx/cli 0.7.0 → 0.8.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.
@@ -19477,7 +19477,8 @@ async function detectInstallMethod() {
19477
19477
  args: [
19478
19478
  "update",
19479
19479
  "-g",
19480
- "@baton-dx/cli"
19480
+ "@baton-dx/cli",
19481
+ "--latest"
19481
19482
  ]
19482
19483
  };
19483
19484
  if (normalized.includes(".bun") || normalized.includes("/bun/")) return {
@@ -19486,16 +19487,17 @@ async function detectInstallMethod() {
19486
19487
  args: [
19487
19488
  "update",
19488
19489
  "-g",
19489
- "@baton-dx/cli"
19490
+ "@baton-dx/cli",
19491
+ "--latest"
19490
19492
  ]
19491
19493
  };
19492
19494
  if (normalized.includes("node_modules") || normalized.includes("npm")) return {
19493
19495
  type: "npm",
19494
19496
  bin: "npm",
19495
19497
  args: [
19496
- "update",
19498
+ "install",
19497
19499
  "-g",
19498
- "@baton-dx/cli"
19500
+ "@baton-dx/cli@latest"
19499
19501
  ]
19500
19502
  };
19501
19503
  return { type: "unknown" };
@@ -19553,5 +19555,292 @@ async function checkLatestVersion() {
19553
19555
  }
19554
19556
 
19555
19557
  //#endregion
19556
- export { cloneGitSource as $, mergeRulesWithWarnings as A, loadProfileManifest as At, detectLegacyPaths as B, CircularInheritanceError as Bt, setGlobalAiTools as C, ClineAdapter as Ct, mergeMemoryWithWarnings as D, BaseAIToolAdapter as Dt, mergeMemory as E, AmpAdapter as Et, isLockedProfile as F, sourceManifestSchema as Ft, placementStateSchema as G, VersionNotFoundError as Gt, discoverProfilesInSourceRepo as H, GitSourceError as Ht, sortProfilesByWeight as I, weightSchema as It, removePlacedFiles as J, getAllAIToolKeys as Jt, readState as K, getAIToolConfig as Kt, mergeContentParts as L, KEBAB_CASE_REGEX as Lt, mergeSkillsWithWarnings as M, lockfileSchema as Mt, WEIGHT_LOCK as N, projectManifestSchema as Nt, mergeAgentsWithWarnings as O, parseFrontmatter as Ot, getProfileWeight as P, profileManifestSchema as Pt, resolveVersion as Q, resolveProfileSupport as R, AIToolAdapterNotFoundError as Rt, saveGlobalConfig as S, CodexAdapter as St, require_lib as T, AntigravityAdapter as Tt, findSourceManifest as U, ManifestValidationError as Ut, placeFile as V, FileNotFoundError as Vt, getStatePath as W, SourceParseError as Wt, readLock as X, generateLock as Y, AIToolNotFoundError as Yt, writeLock as Z, getGlobalConfigPath as _, OpenCodeAdapter as _t, resolvePreferences as a, updateGitignore as at, loadGlobalConfig as b, GitHubCopilotAdapter as bt, writeProjectPreferences as c, idePlatformRegistry as ct, clearIdeCache as d, getAIToolAdaptersForKeys as dt, expandSparseCheckout as et, detectInstalledIdes as f, getAllAIToolAdapters as ft, getGlobalAiTools as g, RooAdapter as gt, getDefaultGlobalSource as h, TraeAdapter as ht, formatInstallCommand as i, removeGitignoreManagedSection as it, mergeSkills as j, loadProjectManifest as jt, mergeRules as k, parseSource as kt, projectPreferencesSchema as l, isKnownIdePlatform as lt, getBatonHome as m, WindsurfAdapter as mt, isUpdateAvailable as n, collectComprehensivePatterns as nt, getPreferencesPath as o, getIdePlatformTargetDir as ot, addGlobalSource as p, ZedAdapter as pt, writeState as q, getAIToolPath as qt, detectInstallMethod as r, ensureBatonDirGitignored as rt, readProjectPreferences as s, getRegisteredIdePlatforms as st, checkLatestVersion as t, esm_default as tt, computeIntersection as u, getAIToolAdapter as ut, getGlobalIdePlatforms as v, KiroAdapter as vt, setGlobalIdePlatforms as w, ClaudeCodeAdapter as wt, removeGlobalSource as x, CursorAdapter as xt, getGlobalSources as y, JunieAdapter as yt, resolveProfileChain as z, BatonError as zt };
19557
- //# sourceMappingURL=src-BI6xWv0H.mjs.map
19558
+ //#region ../core/src/validation/validate-source.ts
19559
+ /**
19560
+ * Check whether a path exists on disk.
19561
+ */
19562
+ async function pathExists(filePath) {
19563
+ try {
19564
+ await access(filePath);
19565
+ return true;
19566
+ } catch {
19567
+ return false;
19568
+ }
19569
+ }
19570
+ /**
19571
+ * Recursively collect all .md files under a directory.
19572
+ */
19573
+ async function collectMdFiles(dir) {
19574
+ const results = [];
19575
+ try {
19576
+ const entries = await readdir(dir, {
19577
+ withFileTypes: true,
19578
+ encoding: "utf-8"
19579
+ });
19580
+ for (const entry of entries) {
19581
+ const fullPath = join(dir, entry.name);
19582
+ if (entry.isDirectory()) {
19583
+ const nested = await collectMdFiles(fullPath);
19584
+ results.push(...nested);
19585
+ } else if (entry.name.endsWith(".md")) results.push(fullPath);
19586
+ }
19587
+ } catch {}
19588
+ return results;
19589
+ }
19590
+ /**
19591
+ * Extract all {{varName}} references from a string.
19592
+ */
19593
+ function extractVariableReferences(content) {
19594
+ const matches = content.matchAll(/\{\{(\w+)\}\}/g);
19595
+ return Array.from(matches, (m) => m[1]);
19596
+ }
19597
+ /**
19598
+ * Validates a Baton source repository, checking the source manifest,
19599
+ * profile manifests, referenced files, and consistency.
19600
+ *
19601
+ * Returns a ValidationReport with all discovered issues.
19602
+ *
19603
+ * @param sourceRoot - Absolute path to the source repository root
19604
+ */
19605
+ async function validateSource(sourceRoot) {
19606
+ const issues = [];
19607
+ let profilesChecked = 0;
19608
+ const sourceManifestPath = join(sourceRoot, "baton.source.yaml");
19609
+ let rawSourceManifest;
19610
+ try {
19611
+ rawSourceManifest = (0, import_dist$2.parse)(await readFile(sourceManifestPath, "utf-8"));
19612
+ } catch {
19613
+ issues.push({
19614
+ severity: "error",
19615
+ message: "Source manifest (baton.source.yaml) not found",
19616
+ path: "baton.source.yaml",
19617
+ context: "source-manifest"
19618
+ });
19619
+ return buildReport(issues, profilesChecked);
19620
+ }
19621
+ const sourceResult = sourceManifestSchema.safeParse(rawSourceManifest);
19622
+ if (!sourceResult.success) {
19623
+ for (const issue of sourceResult.error.issues) issues.push({
19624
+ severity: "error",
19625
+ message: `Source manifest schema error: ${issue.message} (at ${issue.path.join(".")})`,
19626
+ path: "baton.source.yaml",
19627
+ context: "source-manifest"
19628
+ });
19629
+ return buildReport(issues, profilesChecked);
19630
+ }
19631
+ const sourceManifest = sourceResult.data;
19632
+ const knownKeys = getAllAIToolKeys();
19633
+ if (sourceManifest.ai?.tools) {
19634
+ for (const tool of sourceManifest.ai.tools) if (!knownKeys.includes(tool)) issues.push({
19635
+ severity: "warning",
19636
+ message: `Unknown AI tool key "${tool}" in source manifest`,
19637
+ path: "baton.source.yaml",
19638
+ context: "source-manifest"
19639
+ });
19640
+ }
19641
+ let declaredProfiles;
19642
+ if (sourceManifest.profiles && sourceManifest.profiles.length > 0) declaredProfiles = sourceManifest.profiles;
19643
+ const profilesToCheck = declaredProfiles ?? await discoverProfiles(sourceRoot);
19644
+ for (const profile of profilesToCheck) {
19645
+ const profileDir = join(sourceRoot, profile.path);
19646
+ if (!await pathExists(profileDir)) {
19647
+ issues.push({
19648
+ severity: "error",
19649
+ message: `Declared profile directory does not exist: ${profile.path}`,
19650
+ path: profile.path,
19651
+ context: `profile:${profile.name}`
19652
+ });
19653
+ continue;
19654
+ }
19655
+ const profileManifestPath = join(profileDir, "baton.profile.yaml");
19656
+ let rawProfileManifest;
19657
+ try {
19658
+ rawProfileManifest = (0, import_dist$2.parse)(await readFile(profileManifestPath, "utf-8"));
19659
+ } catch {
19660
+ issues.push({
19661
+ severity: "error",
19662
+ message: `Profile manifest (baton.profile.yaml) not found in ${profile.path}`,
19663
+ path: join(profile.path, "baton.profile.yaml"),
19664
+ context: `profile:${profile.name}`
19665
+ });
19666
+ profilesChecked++;
19667
+ continue;
19668
+ }
19669
+ const profileResult = profileManifestSchema.safeParse(rawProfileManifest);
19670
+ if (!profileResult.success) {
19671
+ for (const issue of profileResult.error.issues) issues.push({
19672
+ severity: "error",
19673
+ message: `Profile manifest schema error: ${issue.message} (at ${issue.path.join(".")})`,
19674
+ path: join(profile.path, "baton.profile.yaml"),
19675
+ context: `profile:${profile.name}`
19676
+ });
19677
+ profilesChecked++;
19678
+ continue;
19679
+ }
19680
+ const profileManifest = profileResult.data;
19681
+ profilesChecked++;
19682
+ const ctx = `profile:${profile.name}`;
19683
+ if (profileManifest.ai?.tools) {
19684
+ for (const tool of profileManifest.ai.tools) if (!knownKeys.includes(tool)) issues.push({
19685
+ severity: "warning",
19686
+ message: `Unknown AI tool key "${tool}"`,
19687
+ path: join(profile.path, "baton.profile.yaml"),
19688
+ context: ctx
19689
+ });
19690
+ }
19691
+ if (profileManifest.ai?.skills) {
19692
+ for (const skill of profileManifest.ai.skills) if (!await pathExists(join(profileDir, "ai", "skills", skill.name, "SKILL.md"))) issues.push({
19693
+ severity: "warning",
19694
+ message: `Skill file missing: ai/skills/${skill.name}/SKILL.md`,
19695
+ path: join(profile.path, "ai", "skills", skill.name, "SKILL.md"),
19696
+ context: ctx
19697
+ });
19698
+ }
19699
+ if (profileManifest.ai?.rules) {
19700
+ const rules = profileManifest.ai.rules;
19701
+ if (Array.isArray(rules)) {
19702
+ for (const name of rules) if (!await pathExists(join(profileDir, "ai", "rules", "universal", `${name}.md`))) issues.push({
19703
+ severity: "warning",
19704
+ message: `Rule file missing: ai/rules/universal/${name}.md`,
19705
+ path: join(profile.path, "ai", "rules", "universal", `${name}.md`),
19706
+ context: ctx
19707
+ });
19708
+ } else for (const [scope, names] of Object.entries(rules)) {
19709
+ if (!names) continue;
19710
+ for (const name of names) if (!await pathExists(join(profileDir, "ai", "rules", scope, `${name}.md`))) issues.push({
19711
+ severity: "warning",
19712
+ message: `Rule file missing: ai/rules/${scope}/${name}.md`,
19713
+ path: join(profile.path, "ai", "rules", scope, `${name}.md`),
19714
+ context: ctx
19715
+ });
19716
+ }
19717
+ }
19718
+ if (profileManifest.ai?.agents) {
19719
+ const agents = profileManifest.ai.agents;
19720
+ if (Array.isArray(agents)) {
19721
+ for (const name of agents) if (!await pathExists(join(profileDir, "ai", "agents", `${name}.md`))) issues.push({
19722
+ severity: "warning",
19723
+ message: `Agent file missing: ai/agents/${name}.md`,
19724
+ path: join(profile.path, "ai", "agents", `${name}.md`),
19725
+ context: ctx
19726
+ });
19727
+ } else for (const [scope, names] of Object.entries(agents)) {
19728
+ if (!names) continue;
19729
+ for (const name of names) if (!await pathExists(join(profileDir, "ai", "agents", scope, `${name}.md`))) issues.push({
19730
+ severity: "warning",
19731
+ message: `Agent file missing: ai/agents/${scope}/${name}.md`,
19732
+ path: join(profile.path, "ai", "agents", scope, `${name}.md`),
19733
+ context: ctx
19734
+ });
19735
+ }
19736
+ }
19737
+ if (profileManifest.ai?.memory) {
19738
+ for (const mem of profileManifest.ai.memory) if (!await pathExists(join(profileDir, "ai", "memory", mem.source))) issues.push({
19739
+ severity: "warning",
19740
+ message: `Memory file missing: ai/memory/${mem.source}`,
19741
+ path: join(profile.path, "ai", "memory", mem.source),
19742
+ context: ctx
19743
+ });
19744
+ }
19745
+ if (profileManifest.ai?.commands) {
19746
+ for (const cmd of profileManifest.ai.commands) if (!await pathExists(join(profileDir, "ai", "commands", `${cmd}.md`))) issues.push({
19747
+ severity: "warning",
19748
+ message: `Command file missing: ai/commands/${cmd}.md`,
19749
+ path: join(profile.path, "ai", "commands", `${cmd}.md`),
19750
+ context: ctx
19751
+ });
19752
+ }
19753
+ if (profileManifest.files) {
19754
+ for (const file of profileManifest.files) if (!await pathExists(join(profileDir, "files", file.source))) issues.push({
19755
+ severity: "warning",
19756
+ message: `File missing: files/${file.source}`,
19757
+ path: join(profile.path, "files", file.source),
19758
+ context: ctx
19759
+ });
19760
+ }
19761
+ if (profileManifest.ide) {
19762
+ for (const [platform, files] of Object.entries(profileManifest.ide)) for (const file of files) if (!await pathExists(join(profileDir, "ide", platform, file))) issues.push({
19763
+ severity: "warning",
19764
+ message: `IDE file missing: ide/${platform}/${file}`,
19765
+ path: join(profile.path, "ide", platform, file),
19766
+ context: ctx
19767
+ });
19768
+ }
19769
+ if (profileManifest.extends) {
19770
+ for (const ext of profileManifest.extends) if (!await pathExists(join(join(profileDir, ext), "baton.profile.yaml"))) issues.push({
19771
+ severity: "error",
19772
+ message: `Extends reference unresolvable: "${ext}" — no baton.profile.yaml found`,
19773
+ path: join(profile.path, ext, "baton.profile.yaml"),
19774
+ context: ctx
19775
+ });
19776
+ }
19777
+ const declaredVars = new Set(Object.keys(profileManifest.variables ?? {}));
19778
+ const mdFiles = await collectMdFiles(profileDir);
19779
+ for (const mdFile of mdFiles) {
19780
+ const varNames = extractVariableReferences(await readFile(mdFile, "utf-8"));
19781
+ const undeclaredInFile = new Set(varNames.filter((v) => !declaredVars.has(v)));
19782
+ for (const varName of undeclaredInFile) {
19783
+ const relPath = relative(sourceRoot, mdFile);
19784
+ issues.push({
19785
+ severity: "warning",
19786
+ message: `Undefined variable "{{${varName}}}" in ${relPath}`,
19787
+ path: relPath,
19788
+ context: ctx
19789
+ });
19790
+ }
19791
+ }
19792
+ }
19793
+ if (declaredProfiles) {
19794
+ const declaredPaths = new Set(declaredProfiles.map((p) => p.path));
19795
+ const diskProfiles = await discoverProfiles(sourceRoot);
19796
+ for (const diskProfile of diskProfiles) if (!declaredPaths.has(diskProfile.path)) issues.push({
19797
+ severity: "warning",
19798
+ message: `Orphaned profile on disk not declared in source manifest: ${diskProfile.path}`,
19799
+ path: diskProfile.path,
19800
+ context: "source-manifest"
19801
+ });
19802
+ }
19803
+ return buildReport(issues, profilesChecked);
19804
+ }
19805
+ /**
19806
+ * Auto-discover profiles by scanning the profiles/ directory for
19807
+ * subdirectories that contain baton.profile.yaml.
19808
+ */
19809
+ async function discoverProfiles(sourceRoot) {
19810
+ const profilesDir = join(sourceRoot, "profiles");
19811
+ const results = [];
19812
+ try {
19813
+ const entries = await readdir(profilesDir, {
19814
+ withFileTypes: true,
19815
+ encoding: "utf-8"
19816
+ });
19817
+ for (const entry of entries) {
19818
+ if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
19819
+ if (await pathExists(join(profilesDir, entry.name, "baton.profile.yaml"))) results.push({
19820
+ name: entry.name,
19821
+ path: join("profiles", entry.name)
19822
+ });
19823
+ }
19824
+ } catch {}
19825
+ return results;
19826
+ }
19827
+ /**
19828
+ * Build the final ValidationReport from a list of issues.
19829
+ */
19830
+ function buildReport(issues, profilesChecked) {
19831
+ const errors = issues.filter((i) => i.severity === "error").length;
19832
+ const warnings = issues.filter((i) => i.severity === "warning").length;
19833
+ return {
19834
+ valid: errors === 0,
19835
+ issues,
19836
+ summary: {
19837
+ errors,
19838
+ warnings,
19839
+ profilesChecked
19840
+ }
19841
+ };
19842
+ }
19843
+
19844
+ //#endregion
19845
+ export { resolveVersion as $, mergeRules as A, parseSource as At, resolveProfileChain as B, BatonError as Bt, saveGlobalConfig as C, CodexAdapter as Ct, mergeMemory as D, AmpAdapter as Dt, require_lib as E, AntigravityAdapter as Et, getProfileWeight as F, profileManifestSchema as Ft, getStatePath as G, SourceParseError as Gt, placeFile as H, FileNotFoundError as Ht, isLockedProfile as I, sourceManifestSchema as It, writeState as J, getAIToolPath as Jt, placementStateSchema as K, VersionNotFoundError as Kt, sortProfilesByWeight as L, weightSchema as Lt, mergeSkills as M, loadProjectManifest as Mt, mergeSkillsWithWarnings as N, lockfileSchema as Nt, mergeMemoryWithWarnings as O, BaseAIToolAdapter as Ot, WEIGHT_LOCK as P, projectManifestSchema as Pt, writeLock as Q, mergeContentParts as R, KEBAB_CASE_REGEX as Rt, removeGlobalSource as S, CursorAdapter as St, setGlobalIdePlatforms as T, ClaudeCodeAdapter as Tt, discoverProfilesInSourceRepo as U, GitSourceError as Ut, detectLegacyPaths as V, CircularInheritanceError as Vt, findSourceManifest as W, ManifestValidationError as Wt, generateLock as X, AIToolNotFoundError as Xt, removePlacedFiles as Y, getAllAIToolKeys as Yt, readLock as Z, getGlobalAiTools as _, RooAdapter as _t, formatInstallCommand as a, removeGitignoreManagedSection as at, getGlobalSources as b, JunieAdapter as bt, readProjectPreferences as c, getRegisteredIdePlatforms as ct, computeIntersection as d, getAIToolAdapter as dt, cloneGitSource as et, clearIdeCache as f, getAIToolAdaptersForKeys as ft, getDefaultGlobalSource as g, TraeAdapter as gt, getBatonHome as h, WindsurfAdapter as ht, detectInstallMethod as i, ensureBatonDirGitignored as it, mergeRulesWithWarnings as j, loadProfileManifest as jt, mergeAgentsWithWarnings as k, parseFrontmatter as kt, writeProjectPreferences as l, idePlatformRegistry as lt, addGlobalSource as m, ZedAdapter as mt, checkLatestVersion as n, esm_default as nt, resolvePreferences as o, updateGitignore as ot, detectInstalledIdes as p, getAllAIToolAdapters as pt, readState as q, getAIToolConfig as qt, isUpdateAvailable as r, collectComprehensivePatterns as rt, getPreferencesPath as s, getIdePlatformTargetDir as st, validateSource as t, expandSparseCheckout as tt, projectPreferencesSchema as u, isKnownIdePlatform as ut, getGlobalConfigPath as v, OpenCodeAdapter as vt, setGlobalAiTools as w, ClineAdapter as wt, loadGlobalConfig as x, GitHubCopilotAdapter as xt, getGlobalIdePlatforms as y, KiroAdapter as yt, resolveProfileSupport as z, AIToolAdapterNotFoundError as zt };
19846
+ //# sourceMappingURL=src-qYK6F_wF.mjs.map