@fractary/codex 0.5.1 → 0.7.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.d.cts CHANGED
@@ -870,16 +870,24 @@ interface SyncRule {
870
870
  priority?: number;
871
871
  direction?: SyncDirection;
872
872
  }
873
+ interface DirectionalSyncConfig {
874
+ include: string[];
875
+ exclude?: string[];
876
+ }
877
+ interface RoutingConfig {
878
+ use_frontmatter?: boolean;
879
+ }
873
880
  interface SyncConfig {
874
881
  defaultDirection: SyncDirection;
875
882
  rules: SyncRule[];
876
883
  defaultExcludes: string[];
877
884
  deleteOrphans: boolean;
878
885
  conflictStrategy: 'newest' | 'local' | 'remote' | 'manual';
879
- to_codex?: string[];
880
- from_codex?: string[];
881
- default_to_codex?: string[];
886
+ from_codex?: DirectionalSyncConfig;
887
+ to_codex?: DirectionalSyncConfig;
888
+ routing?: RoutingConfig;
882
889
  default_from_codex?: string[];
890
+ default_to_codex?: string[];
883
891
  exclude?: string[];
884
892
  }
885
893
  declare const DEFAULT_SYNC_CONFIG: SyncConfig;
@@ -960,6 +968,8 @@ declare class SyncManager {
960
968
  private manifestPath;
961
969
  private manifest;
962
970
  constructor(options: SyncManagerConfig);
971
+ private resolveFromCodexPatterns;
972
+ private resolveToCodexPatterns;
963
973
  loadManifest(): Promise<SyncManifest | null>;
964
974
  saveManifest(manifest: SyncManifest): Promise<void>;
965
975
  getOrCreateManifest(org: string, project: string): Promise<SyncManifest>;
package/dist/index.d.ts CHANGED
@@ -870,16 +870,24 @@ interface SyncRule {
870
870
  priority?: number;
871
871
  direction?: SyncDirection;
872
872
  }
873
+ interface DirectionalSyncConfig {
874
+ include: string[];
875
+ exclude?: string[];
876
+ }
877
+ interface RoutingConfig {
878
+ use_frontmatter?: boolean;
879
+ }
873
880
  interface SyncConfig {
874
881
  defaultDirection: SyncDirection;
875
882
  rules: SyncRule[];
876
883
  defaultExcludes: string[];
877
884
  deleteOrphans: boolean;
878
885
  conflictStrategy: 'newest' | 'local' | 'remote' | 'manual';
879
- to_codex?: string[];
880
- from_codex?: string[];
881
- default_to_codex?: string[];
886
+ from_codex?: DirectionalSyncConfig;
887
+ to_codex?: DirectionalSyncConfig;
888
+ routing?: RoutingConfig;
882
889
  default_from_codex?: string[];
890
+ default_to_codex?: string[];
883
891
  exclude?: string[];
884
892
  }
885
893
  declare const DEFAULT_SYNC_CONFIG: SyncConfig;
@@ -960,6 +968,8 @@ declare class SyncManager {
960
968
  private manifestPath;
961
969
  private manifest;
962
970
  constructor(options: SyncManagerConfig);
971
+ private resolveFromCodexPatterns;
972
+ private resolveToCodexPatterns;
963
973
  loadManifest(): Promise<SyncManifest | null>;
964
974
  saveManifest(manifest: SyncManifest): Promise<void>;
965
975
  getOrCreateManifest(org: string, project: string): Promise<SyncManifest>;
package/dist/index.js CHANGED
@@ -2855,16 +2855,24 @@ async function scanCodexWithRouting(options) {
2855
2855
  continue;
2856
2856
  }
2857
2857
  const content = await storage.readText(fullPath);
2858
- const parseResult = parseMetadata(content, { strict: false });
2859
- if (!matchFromCodexPattern2 && skipNoFrontmatter && Object.keys(parseResult.metadata).length === 0) {
2860
- totalSkipped++;
2861
- continue;
2862
- }
2863
2858
  const sourceProject = extractProjectFromPath(filePath, org);
2864
2859
  let shouldSync = false;
2860
+ let parseResult = null;
2861
+ const useFrontmatter = options.routing?.use_frontmatter === true;
2865
2862
  if (matchFromCodexPattern2 && expandedFromCodexPatterns && expandedFromCodexPatterns.length > 0) {
2866
2863
  shouldSync = matchFromCodexPattern2(filePath, expandedFromCodexPatterns, targetProject);
2867
- } else {
2864
+ parseResult = parseMetadata(content, { strict: false });
2865
+ } else if (useFrontmatter) {
2866
+ parseResult = parseMetadata(content, { strict: false });
2867
+ if (parseResult.metadata.codex_sync_include) {
2868
+ console.warn(
2869
+ `[DEPRECATION] File ${filePath} uses codex_sync_include frontmatter. This feature will be removed in v1.0. Use config.yaml patterns instead.`
2870
+ );
2871
+ }
2872
+ if (skipNoFrontmatter && Object.keys(parseResult.metadata).length === 0) {
2873
+ totalSkipped++;
2874
+ continue;
2875
+ }
2868
2876
  shouldSync = shouldSyncToRepo({
2869
2877
  filePath,
2870
2878
  fileMetadata: parseResult.metadata,
@@ -2872,6 +2880,9 @@ async function scanCodexWithRouting(options) {
2872
2880
  sourceRepo: sourceProject,
2873
2881
  rules
2874
2882
  });
2883
+ } else {
2884
+ totalSkipped++;
2885
+ continue;
2875
2886
  }
2876
2887
  if (shouldSync) {
2877
2888
  const buffer = Buffer.from(content);
@@ -2881,7 +2892,7 @@ async function scanCodexWithRouting(options) {
2881
2892
  size: buffer.length,
2882
2893
  mtime: stats.mtimeMs,
2883
2894
  hash,
2884
- metadata: parseResult.metadata,
2895
+ metadata: parseResult?.metadata ?? {},
2885
2896
  sourceProject
2886
2897
  });
2887
2898
  sourceProjectsSet.add(sourceProject);
@@ -2964,6 +2975,30 @@ var SyncManager = class {
2964
2975
  };
2965
2976
  this.manifestPath = options.manifestPath ?? ".fractary/codex-sync-manifest.json";
2966
2977
  }
2978
+ /**
2979
+ * Resolve from_codex include patterns (v0.7.0+)
2980
+ *
2981
+ * Supports both new format (from_codex.include) and legacy format (default_from_codex).
2982
+ * New format takes precedence.
2983
+ */
2984
+ resolveFromCodexPatterns() {
2985
+ if (this.config.from_codex?.include) {
2986
+ return this.config.from_codex.include;
2987
+ }
2988
+ return this.config.default_from_codex || [];
2989
+ }
2990
+ /**
2991
+ * Resolve to_codex include patterns (v0.7.0+)
2992
+ *
2993
+ * Supports both new format (to_codex.include) and legacy format (default_to_codex).
2994
+ * New format takes precedence.
2995
+ */
2996
+ resolveToCodexPatterns() {
2997
+ if (this.config.to_codex?.include) {
2998
+ return this.config.to_codex.include;
2999
+ }
3000
+ return this.config.default_to_codex || [];
3001
+ }
2967
3002
  /**
2968
3003
  * Load the sync manifest
2969
3004
  */
@@ -3033,8 +3068,8 @@ var SyncManager = class {
3033
3068
  async createPlan(_org, _project, sourceDir, targetFiles, options) {
3034
3069
  let sourceFiles = await this.listLocalFiles(sourceDir);
3035
3070
  if (options?.direction === "to-codex") {
3036
- const toCodexPatterns = this.config.to_codex || this.config.default_to_codex;
3037
- if (toCodexPatterns) {
3071
+ const toCodexPatterns = this.resolveToCodexPatterns();
3072
+ if (toCodexPatterns.length > 0) {
3038
3073
  const { matchToCodexPattern: matchToCodexPattern2 } = await Promise.resolve().then(() => (init_directional_patterns(), directional_patterns_exports));
3039
3074
  sourceFiles = sourceFiles.filter(
3040
3075
  (file) => matchToCodexPattern2(file.path, toCodexPatterns)
@@ -3078,7 +3113,7 @@ var SyncManager = class {
3078
3113
  * ```
3079
3114
  */
3080
3115
  async createRoutingAwarePlan(org, project, codexDir, options) {
3081
- const fromCodexPatterns = this.config.from_codex || this.config.default_from_codex;
3116
+ const fromCodexPatterns = this.resolveFromCodexPatterns();
3082
3117
  const routingScan = await scanCodexWithRouting({
3083
3118
  codexDir,
3084
3119
  targetProject: project,
@@ -3086,8 +3121,9 @@ var SyncManager = class {
3086
3121
  rules: void 0,
3087
3122
  // Use default routing rules (preventSelfSync, preventCodexSync, etc.)
3088
3123
  storage: this.localStorage,
3089
- fromCodexPatterns
3090
- // Use directional patterns if configured
3124
+ fromCodexPatterns: fromCodexPatterns.length > 0 ? fromCodexPatterns : void 0,
3125
+ routing: this.config.routing
3126
+ // Pass routing config for frontmatter control
3091
3127
  });
3092
3128
  const sourceFiles = routingScan.files.map((rf) => ({
3093
3129
  path: rf.path,
@@ -3106,16 +3142,19 @@ var SyncManager = class {
3106
3142
  };
3107
3143
  const plan = createSyncPlan(sourceFiles, targetFiles, planOptions, this.config);
3108
3144
  plan.estimatedTime = estimateSyncTime(plan);
3145
+ plan.source = codexDir;
3146
+ plan.target = ".fractary/codex/cache";
3109
3147
  return {
3110
3148
  ...plan,
3111
3149
  routingScan
3112
3150
  };
3113
3151
  }
3114
3152
  /**
3115
- * Execute a sync plan (dry run)
3153
+ * Execute a sync plan
3116
3154
  *
3117
- * In a real implementation, this would actually copy files.
3118
- * For the SDK, we provide the plan and let consumers execute.
3155
+ * Copies files from source to target based on the plan.
3156
+ * For from-codex syncs, files are copied to .fractary/codex/cache/ preserving full paths.
3157
+ * For to-codex syncs, files are copied to the codex repository.
3119
3158
  */
3120
3159
  async executePlan(plan, options) {
3121
3160
  const startTime = Date.now();
@@ -3141,7 +3180,30 @@ var SyncManager = class {
3141
3180
  if (options?.onProgress) {
3142
3181
  options.onProgress(i + 1, plan.totalFiles, file.path);
3143
3182
  }
3144
- synced++;
3183
+ if (file.operation === "create" || file.operation === "update") {
3184
+ const sourcePath = `${plan.source}/${file.path}`;
3185
+ const targetPath = `${plan.target}/${file.path}`;
3186
+ const fs4 = await import('fs/promises');
3187
+ const path6 = await import('path');
3188
+ const targetDir = path6.dirname(targetPath);
3189
+ await fs4.mkdir(targetDir, { recursive: true });
3190
+ await fs4.copyFile(sourcePath, targetPath);
3191
+ synced++;
3192
+ } else if (file.operation === "delete") {
3193
+ const targetPath = `${plan.target}/${file.path}`;
3194
+ const fs4 = await import('fs/promises');
3195
+ try {
3196
+ await fs4.unlink(targetPath);
3197
+ synced++;
3198
+ } catch (error) {
3199
+ if (error.code !== "ENOENT") {
3200
+ throw error;
3201
+ }
3202
+ synced++;
3203
+ }
3204
+ } else {
3205
+ synced++;
3206
+ }
3145
3207
  } catch (error) {
3146
3208
  failed++;
3147
3209
  errors.push({