faf-mcp 3.0.0 → 3.0.1

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 (50) hide show
  1. package/CHANGELOG.md +24 -2
  2. package/CLAUDE.md +6 -2
  3. package/README.md +28 -18
  4. package/dist/src/faf-core/commands/agents.d.ts +2 -2
  5. package/dist/src/faf-core/commands/agents.js +2 -2
  6. package/dist/src/faf-core/commands/claude.d.ts +31 -0
  7. package/dist/src/faf-core/commands/{bi-sync.js → claude.js} +18 -13
  8. package/dist/src/faf-core/commands/claude.js.map +1 -0
  9. package/dist/src/faf-core/commands/conductor.d.ts +1 -1
  10. package/dist/src/faf-core/commands/conductor.js +1 -1
  11. package/dist/src/faf-core/commands/cursor.d.ts +2 -2
  12. package/dist/src/faf-core/commands/cursor.js +2 -2
  13. package/dist/src/faf-core/commands/gemini.d.ts +2 -2
  14. package/dist/src/faf-core/commands/gemini.js +2 -2
  15. package/dist/src/faf-core/commands/git-context.d.ts +1 -1
  16. package/dist/src/faf-core/commands/git-context.js +2 -2
  17. package/dist/src/faf-core/commands/git-context.js.map +1 -1
  18. package/dist/src/faf-core/parsers/agents-parser.d.ts +4 -3
  19. package/dist/src/faf-core/parsers/agents-parser.js +4 -3
  20. package/dist/src/faf-core/parsers/agents-parser.js.map +1 -1
  21. package/dist/src/faf-core/parsers/conductor-parser.d.ts +1 -1
  22. package/dist/src/faf-core/parsers/conductor-parser.js +1 -1
  23. package/dist/src/faf-core/parsers/cursorrules-parser.d.ts +4 -3
  24. package/dist/src/faf-core/parsers/cursorrules-parser.js +4 -3
  25. package/dist/src/faf-core/parsers/cursorrules-parser.js.map +1 -1
  26. package/dist/src/faf-core/parsers/faf-git-generator.d.ts +1 -1
  27. package/dist/src/faf-core/parsers/faf-git-generator.js +6 -5
  28. package/dist/src/faf-core/parsers/faf-git-generator.js.map +1 -1
  29. package/dist/src/faf-core/parsers/gemini-parser.d.ts +4 -3
  30. package/dist/src/faf-core/parsers/gemini-parser.js +4 -3
  31. package/dist/src/faf-core/parsers/gemini-parser.js.map +1 -1
  32. package/dist/src/faf-core/parsers/github-extractor.d.ts +1 -1
  33. package/dist/src/faf-core/parsers/github-extractor.js +1 -1
  34. package/dist/src/faf-core/parsers/slot-counter.d.ts +1 -1
  35. package/dist/src/faf-core/parsers/slot-counter.js +1 -1
  36. package/dist/src/handlers/engine-adapter.js +5 -4
  37. package/dist/src/handlers/engine-adapter.js.map +1 -1
  38. package/dist/src/handlers/tools.d.ts +2 -2
  39. package/dist/src/handlers/tools.js +102 -132
  40. package/dist/src/handlers/tools.js.map +1 -1
  41. package/dist/src/server.js +1 -1
  42. package/dist/src/server.js.map +1 -1
  43. package/dist/src/utils/faf-cli-bridge.d.ts +12 -8
  44. package/dist/src/utils/faf-cli-bridge.js +12 -8
  45. package/dist/src/utils/faf-cli-bridge.js.map +1 -1
  46. package/package.json +3 -3
  47. package/project.faf +5 -5
  48. package/skills/faf-ide/SKILL.md +1 -1
  49. package/dist/src/faf-core/commands/bi-sync.d.ts +0 -29
  50. package/dist/src/faf-core/commands/bi-sync.js.map +0 -1
@@ -38,7 +38,6 @@ const fileHandler_1 = require("./fileHandler");
38
38
  const fs = __importStar(require("fs"));
39
39
  const os = __importStar(require("os"));
40
40
  const pathModule = __importStar(require("path"));
41
- const fuzzy_detector_1 = require("../utils/fuzzy-detector");
42
41
  const faf_file_finder_js_1 = require("../utils/faf-file-finder.js");
43
42
  const safe_path_1 = require("../utils/safe-path");
44
43
  const version_1 = require("../version");
@@ -49,12 +48,12 @@ const path_resolver_1 = require("../utils/path-resolver");
49
48
  // scoring or the tier ladder here — that's exactly the drift v2.1.0 set out
50
49
  // to kill across the surface; v2.1.1 closes the loop on the active handler.
51
50
  //
52
- // Imported via ../utils/faf-cli-bridge.js — a temporary one-file re-export
53
- // that pins the relative dist path (faf-cli 6.7.1's `bun` exports condition
54
- // resolves to a non-shipped src/, breaking the test runner). Both Node and
55
- // Bun load the same compiled module through the bridge. Bridge is removable
56
- // once faf-cli drops the bad `bun` condition. See the bridge header for full
57
- // rationale and the linked tracked issue.
51
+ // Imported via ../utils/faf-cli-bridge.js — a one-file re-export that pins
52
+ // the relative dist path. It began as a workaround for faf-cli 6.7.1's `bun`
53
+ // exports condition (pointed at a non-shipped src/); 6.8.0 dropped it and
54
+ // 7.12.0 exports only `types`/`default`. Node and Bun load the same compiled
55
+ // module through the bridge, which stays for the CJS-to-ESM load and
56
+ // bundledFafCliVersion()'s path-walk. See the bridge header for the rationale.
58
57
  const faf_cli_bridge_js_1 = require("../utils/faf-cli-bridge.js");
59
58
  const turbocat_bridge_js_1 = require("../faf-core/extract/turbocat-bridge.js");
60
59
  /**
@@ -66,8 +65,8 @@ const turbocat_bridge_js_1 = require("../faf-core/extract/turbocat-bridge.js");
66
65
  * the 40%-MIN rule means one weak tool on the surface caps the whole server.
67
66
  *
68
67
  * Spine mirrors claude-faf-mcp's proven-A Core; the interop quad
69
- * (faf_bi_sync + faf_agents/faf_cursor/faf_gemini) is this edition's identity —
70
- * the Cursor / IDE multi-format sync — where CFM carries memory tools instead.
68
+ * (faf_claude + faf_agents/faf_cursor/faf_gemini) is this edition's identity —
69
+ * the Cursor / IDE multi-format write — where CFM carries memory tools instead.
71
70
  * See PLANET-FAF/strategy/claude-faf-mcp-core-tier-glama-a-2026-06-17.md.
72
71
  */
73
72
  const CORE_TOOLS = new Set([
@@ -75,7 +74,7 @@ const CORE_TOOLS = new Set([
75
74
  'faf_init', 'faf_auto', 'faf_go', 'faf_score', 'faf_doctor',
76
75
  'faf_sync', 'faf_context', 'faf_trust', 'faf_about',
77
76
  // IDE-edition interop — the differentiator
78
- 'faf_bi_sync', 'faf_agents', 'faf_cursor', 'faf_gemini',
77
+ 'faf_claude', 'faf_agents', 'faf_cursor', 'faf_gemini',
79
78
  // Craft-grade utility
80
79
  'faf_check', 'faf_git',
81
80
  ]);
@@ -206,7 +205,7 @@ class FafToolHandler {
206
205
  },
207
206
  {
208
207
  name: 'faf_sync',
209
- description: 'Reconcile project.faf with what the repo manifests say now (package.json name, description, framework dependencies). Dry-run by default: reports the fields that would change. Pass apply:true to write them into project.faf. Does not touch CLAUDE.md — use faf_bi_sync for CLAUDE.md, AGENTS.md, .cursorrules and GEMINI.md.',
208
+ description: 'Reconcile project.faf with what the repo manifests say now (package.json name, description, framework dependencies). Dry-run by default: reports the fields that would change. Pass apply:true to write them into project.faf. Does not touch CLAUDE.md — use faf_claude for CLAUDE.md, AGENTS.md, .cursorrules and GEMINI.md.',
210
209
  annotations: {
211
210
  title: 'Reconcile .faf with repo manifests',
212
211
  readOnlyHint: false,
@@ -223,10 +222,10 @@ class FafToolHandler {
223
222
  }
224
223
  },
225
224
  {
226
- name: 'faf_bi_sync',
227
- description: 'Write CLAUDE.md from project.faf (one direction: .faf → CLAUDE.md) and, with the format flags or all, also AGENTS.md, .cursorrules and GEMINI.md. Content outside the faf-managed block is preserved. Returns the files written. Use this to keep every AI tool\'s context file current from one source.',
225
+ name: 'faf_claude',
226
+ description: 'Write CLAUDE.md from project.faf (one direction: .faf → CLAUDE.md) and, with the format flags or all, also AGENTS.md, .cursorrules and GEMINI.md. Content outside the faf-managed block is preserved. Returns the files written. Use this to keep every AI tool\'s context file current from one source. (Named faf_bi_sync before 3.0.1; that name still works.)',
228
227
  annotations: {
229
- title: 'Sync .faf to CLAUDE.md and IDE formats',
228
+ title: 'Write CLAUDE.md and IDE formats from .faf',
230
229
  readOnlyHint: false,
231
230
  destructiveHint: false,
232
231
  openWorldHint: false
@@ -234,10 +233,10 @@ class FafToolHandler {
234
233
  inputSchema: {
235
234
  type: 'object',
236
235
  properties: {
237
- agents: { type: 'boolean', description: 'Also sync to AGENTS.md (OpenAI/Codex format)' },
238
- cursor: { type: 'boolean', description: 'Also sync to .cursorrules (Cursor IDE format)' },
239
- gemini: { type: 'boolean', description: 'Also sync to GEMINI.md (Google Gemini format)' },
240
- all: { type: 'boolean', description: 'Sync to ALL formats: CLAUDE.md + AGENTS.md + .cursorrules + GEMINI.md' },
236
+ agents: { type: 'boolean', description: 'Also write AGENTS.md (OpenAI/Codex format)' },
237
+ cursor: { type: 'boolean', description: 'Also write .cursorrules (Cursor IDE format)' },
238
+ gemini: { type: 'boolean', description: 'Also write GEMINI.md (Google Gemini format)' },
239
+ all: { type: 'boolean', description: 'Write ALL formats: CLAUDE.md + AGENTS.md + .cursorrules + GEMINI.md' },
241
240
  path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
242
241
  },
243
242
  additionalProperties: false
@@ -472,7 +471,7 @@ class FafToolHandler {
472
471
  },
473
472
  {
474
473
  name: 'faf_auto',
475
- description: 'Run the full setup pipeline in one call — init, stack detection, sync, bi-sync, and score — taking a project from no context to a complete project.faf. Returns the final AI-readiness score and what was created. Use this as the fast path on a fresh project; use the individual tools when you need finer control.',
474
+ description: 'Run the full setup pipeline in one call — init, stack detection, sync, CLAUDE.md, and score — taking a project from no context to a complete project.faf. Returns the final AI-readiness score and what was created. Use this as the fast path on a fresh project; use the individual tools when you need finer control.',
476
475
  annotations: {
477
476
  title: 'Auto-detect Context',
478
477
  readOnlyHint: false,
@@ -492,7 +491,7 @@ class FafToolHandler {
492
491
  },
493
492
  {
494
493
  name: 'faf_dna',
495
- description: 'Show your FAF DNA journey - See your evolution from birth to championship (22% 85% 99%)',
494
+ description: 'Show your FAF DNA journey — the score evolution of this project.faf from birth to today (e.g. 22% → 85% → 100%)',
496
495
  annotations: {
497
496
  title: 'View Project DNA',
498
497
  readOnlyHint: true,
@@ -560,11 +559,11 @@ class FafToolHandler {
560
559
  }
561
560
  },
562
561
  // ============================================================================
563
- // v4.5.0 INTEROP TOOLS
562
+ // INTEROP TOOLS — landed in faf-mcp 2.0.0 (The Interop MCP for Context); ported from faf-cli 4.5.0 via claude-faf-mcp 4.5.0
564
563
  // ============================================================================
565
564
  {
566
565
  name: 'faf_agents',
567
- description: 'Import, export, or sync context between AGENTS.md (the OpenAI/Codex convention) and project.faf. Returns the merged or written result for the chosen action. Use this to keep a Codex/OpenAI-style AGENTS.md and your .faf in agreement from one source.',
566
+ description: 'Import AGENTS.md (the OpenAI/Codex convention) into project.faf, or write it from project.faf. Returns the merged or written result for the chosen action. Use this to keep a Codex/OpenAI-style AGENTS.md and your .faf in agreement from one source.',
568
567
  annotations: {
569
568
  title: 'Sync AGENTS.md',
570
569
  readOnlyHint: false,
@@ -574,7 +573,7 @@ class FafToolHandler {
574
573
  inputSchema: {
575
574
  type: 'object',
576
575
  properties: {
577
- action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (AGENTS.md -> .faf), export (.faf -> AGENTS.md), sync (bidirectional)' },
576
+ action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (AGENTS.md -> .faf; merge:true writes it into project.faf), export (.faf -> AGENTS.md), sync (re-writes AGENTS.md from .faf; export with force)' },
578
577
  force: { type: 'boolean', description: 'Force overwrite existing files' },
579
578
  merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
580
579
  path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
@@ -585,7 +584,7 @@ class FafToolHandler {
585
584
  },
586
585
  {
587
586
  name: 'faf_cursor',
588
- description: 'Import, export, or sync context between .cursorrules (the Cursor IDE convention) and project.faf. Returns the merged or written result for the chosen action. Use this to keep Cursor rules and your .faf in agreement from one source.',
587
+ description: 'Import .cursorrules (the Cursor IDE convention) into project.faf, or write it from project.faf. Returns the merged or written result for the chosen action. Use this to keep Cursor rules and your .faf in agreement from one source.',
589
588
  annotations: {
590
589
  title: 'Sync .cursorrules',
591
590
  readOnlyHint: false,
@@ -595,7 +594,7 @@ class FafToolHandler {
595
594
  inputSchema: {
596
595
  type: 'object',
597
596
  properties: {
598
- action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (.cursorrules -> .faf), export (.faf -> .cursorrules), sync (bidirectional)' },
597
+ action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (.cursorrules -> .faf; merge:true writes it into project.faf), export (.faf -> .cursorrules), sync (re-writes .cursorrules from .faf; export with force)' },
599
598
  force: { type: 'boolean', description: 'Force overwrite existing files' },
600
599
  merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
601
600
  path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
@@ -606,7 +605,7 @@ class FafToolHandler {
606
605
  },
607
606
  {
608
607
  name: 'faf_gemini',
609
- description: 'Import, export, or sync context between GEMINI.md (the Google Gemini CLI convention) and project.faf. Returns the merged or written result for the chosen action. Use this to keep a Gemini context file and your .faf in agreement from one source.',
608
+ description: 'Import GEMINI.md (the Google Gemini CLI convention) into project.faf, or write it from project.faf. Returns the merged or written result for the chosen action. Use this to keep a Gemini context file and your .faf in agreement from one source.',
610
609
  annotations: {
611
610
  title: 'Sync GEMINI.md',
612
611
  readOnlyHint: false,
@@ -616,7 +615,7 @@ class FafToolHandler {
616
615
  inputSchema: {
617
616
  type: 'object',
618
617
  properties: {
619
- action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (GEMINI.md -> .faf), export (.faf -> GEMINI.md), sync (bidirectional)' },
618
+ action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (GEMINI.md -> .faf; merge:true writes it into project.faf), export (.faf -> GEMINI.md), sync (re-writes GEMINI.md from .faf; export with force)' },
620
619
  force: { type: 'boolean', description: 'Force overwrite existing files' },
621
620
  merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
622
621
  path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
@@ -648,7 +647,7 @@ class FafToolHandler {
648
647
  },
649
648
  {
650
649
  name: 'faf_git',
651
- description: 'Generate a project.faf from any public GitHub repository URL — fetches the repo and extracts its stack and context. Returns the generated .faf. Use this to bootstrap context for a project you have the URL for but not cloned locally.',
650
+ description: 'Author a project.faf from any public GitHub repository URL — fetches the repo and extracts its stack and context. Returns the authored .faf. Use this to bootstrap context for a project you have the URL for but not cloned locally.',
652
651
  annotations: {
653
652
  title: 'Extract from GitHub',
654
653
  readOnlyHint: false,
@@ -659,7 +658,7 @@ class FafToolHandler {
659
658
  type: 'object',
660
659
  properties: {
661
660
  url: { type: 'string', description: 'GitHub repository URL (e.g., https://github.com/owner/repo or owner/repo)' },
662
- path: { type: 'string', description: 'Output directory for generated project.faf. If omitted, returns content without writing.' }
661
+ path: { type: 'string', description: 'Output directory for the authored project.faf. If omitted, returns content without writing.' }
663
662
  },
664
663
  required: ['url'],
665
664
  additionalProperties: false
@@ -689,8 +688,9 @@ class FafToolHandler {
689
688
  return await this.handleFafTrust(args);
690
689
  case 'faf_sync':
691
690
  return await this.handleFafSync(args);
692
- case 'faf_bi_sync':
693
- return await this.handleFafBiSync(args);
691
+ case 'faf_bi_sync': // pre-3.0.1 name: still callable, never listed
692
+ case 'faf_claude':
693
+ return await this.handleFafClaude(args);
694
694
  case 'faf_clear':
695
695
  return await this.handleFafClear(args);
696
696
  case 'faf_debug':
@@ -736,7 +736,7 @@ class FafToolHandler {
736
736
  return await this.handleFafQuick(args);
737
737
  case 'faf_doctor':
738
738
  return await this.handleFafDoctor(args);
739
- // v4.5.0 Interop tools
739
+ // Interop tools (faf-mcp 2.0.0; ported from faf-cli 4.5.0 via claude-faf-mcp 4.5.0)
740
740
  case 'faf_agents':
741
741
  return await this.handleFafAgents(args);
742
742
  case 'faf_cursor':
@@ -769,7 +769,7 @@ class FafToolHandler {
769
769
  return {
770
770
  content: [{
771
771
  type: 'text',
772
- text: `🤖 Claude FAF Project Status:\n\n❌ No FAF file found in ${cwd}\n💡 Run faf_init to create project.faf`
772
+ text: `🤖 FAF Project Status:\n\n❌ No FAF file found in ${cwd}\n💡 Run faf_init to create project.faf`
773
773
  }]
774
774
  };
775
775
  }
@@ -778,7 +778,7 @@ class FafToolHandler {
778
778
  return {
779
779
  content: [{
780
780
  type: 'text',
781
- text: `🤖 Claude FAF Project Status:\n\n✅ ${fafResult.filename} found in ${cwd}\n\nContent preview:\n${lines.join('\n')}`
781
+ text: `🤖 FAF Project Status:\n\n✅ ${fafResult.filename} found in ${cwd}\n\nContent preview:\n${lines.join('\n')}`
782
782
  }]
783
783
  };
784
784
  }
@@ -786,7 +786,7 @@ class FafToolHandler {
786
786
  return {
787
787
  content: [{
788
788
  type: 'text',
789
- text: `🤖 Claude FAF Project Status:\n\n❌ Error: ${error.message}`
789
+ text: `🤖 FAF Project Status:\n\n❌ Error: ${error.message}`
790
790
  }],
791
791
  isError: true
792
792
  };
@@ -849,7 +849,7 @@ class FafToolHandler {
849
849
  text: `FAF SCORE: 0/100 (0%) ○ INVALID\n\n` +
850
850
  `\`${fafPath}\` couldn't be parsed as a valid .faf YAML:\n` +
851
851
  ` ${error?.message ?? String(error)}\n\n` +
852
- `Re-run \`faf_init\` to regenerate a valid file.`,
852
+ `Re-run \`faf_init\` with force: true to write a fresh, valid file.`,
853
853
  },
854
854
  ],
855
855
  isError: true,
@@ -898,13 +898,19 @@ class FafToolHandler {
898
898
  };
899
899
  }
900
900
  async handleFafInit(args) {
901
- // Native implementation - creates project.faf with Pomelli-simple path resolution!
901
+ // faf_init is `faf init`: the same exported faf-cli steps the CLI command
902
+ // runs (assembleFreshFaf detects the folder → writeFaf → readFafRaw →
903
+ // scoreFafYaml), on the folder the path resolves to. Until 3.0.1 this
904
+ // wrote its own legacy template (no format version, `project:` as a
905
+ // plain string) that scored 0% whatever the folder held, failed faf_trust and
906
+ // crashed faf_go. Two steps of `faf init` are not exported by faf-cli
907
+ // 7.12 and are not repeated here: the home/root refusal and the
908
+ // .faf-dna birth record (faf_dna writes that on its first call).
902
909
  try {
903
- // Use smart path resolution (supports "my-app", "~/Projects/my-app", "/full/path")
910
+ // Path resolution unchanged (supports "my-app", "~/Projects/my-app", "/full/path")
904
911
  const userInput = args?.path;
905
912
  const resolution = (0, path_resolver_1.resolveProjectPath)(userInput);
906
913
  const targetDir = resolution.projectPath;
907
- const projectName = resolution.projectName;
908
914
  const fafPath = resolution.fafFilePath;
909
915
  // Ensure project directory exists
910
916
  if (!fs.existsSync(targetDir)) {
@@ -916,57 +922,16 @@ class FafToolHandler {
916
922
  return {
917
923
  content: [{
918
924
  type: 'text',
919
- text: `🚀 Claude FAF Initialization:\n\n⚠️ ${existingFaf.filename} already exists in ${targetDir}\n💡 Use force: true to overwrite`
925
+ text: `🚀 FAF Initialization:\n\n⚠️ ${existingFaf.filename} already exists in ${targetDir}\n💡 Use force: true to overwrite`
920
926
  }]
921
927
  };
922
928
  }
923
- // Check project type with fuzzy detection (Friday Feature!)
924
- const projectDescription = args?.description || '';
925
- // Detect Chrome Extension with fuzzy matching
926
- const chromeDetection = fuzzy_detector_1.FuzzyDetector.detectChromeExtension(projectDescription);
927
- const projectType = fuzzy_detector_1.FuzzyDetector.detectProjectType(projectDescription);
928
- // Build project data with Intel-Friday auto-fill!
929
- let projectData = {
930
- project: projectName,
931
- project_type: projectType,
932
- description: projectDescription,
933
- generated: new Date().toISOString(),
934
- version: version_1.VERSION
935
- };
936
- // Apply Intel-Friday: Auto-fill Chrome Extension slots for 90%+ score!
937
- if (chromeDetection.detected) {
938
- projectData = (0, fuzzy_detector_1.applyIntelFriday)(projectData);
939
- }
940
- // Create enhanced .faf content
941
- const fafContent = `# FAF - Foundational AI Context
942
- project: ${projectData.project}
943
- type: ${projectData.project_type}${chromeDetection.detected ? ' 🎯' : ''}
944
- context: I⚡🍊
945
- generated: ${projectData.generated}
946
- version: ${projectData.version}
947
- ${chromeDetection.corrected ? `# Auto-corrected: "${args?.description}" → "${chromeDetection.corrected}"` : ''}
948
-
949
- # The Formula
950
- human_input: Your project files
951
- multiplier: FAF Context
952
- output: Championship Performance
953
-
954
- # Quick Context
955
- working_directory: ${targetDir}
956
- initialized_by: faf-mcp${projectData._friday_feature ? `\nfriday_feature: ${projectData._friday_feature}` : ''}
957
- vitamin_context: true
958
- faffless: true
959
-
960
- ${chromeDetection.detected ? `# Chrome Extension Auto-Fill (90%+ Score!)
961
- runtime: ${projectData.runtime}
962
- hosting: ${projectData.hosting}
963
- api_type: ${projectData.api_type}
964
- backend: ${projectData.backend}
965
- database: ${projectData.database}
966
- build: ${projectData.build}
967
- package_manager: ${projectData.package_manager}` : ''}
968
- `;
969
- fs.writeFileSync(fafPath, fafContent);
929
+ const { assembleFreshFaf, writeFaf, readFafRaw, scoreFafYaml } = await faf_cli_bridge_js_1.fafCli;
930
+ writeFaf(fafPath, assembleFreshFaf(targetDir));
931
+ const score = scoreFafYaml(readFafRaw(fafPath));
932
+ // Like `cd` + `faf init`: the new project becomes the current one, so the
933
+ // next steps printed below (faf_score, faf_claude, faf_go) act on it.
934
+ this.engineAdapter.setWorkingDirectory(targetDir);
970
935
  // Pomelli-style success confirmation with path resolution info
971
936
  const pathConfirmation = (0, path_resolver_1.formatPathConfirmation)(resolution);
972
937
  const sourceExplanation = resolution.source === 'user-name'
@@ -975,7 +940,7 @@ package_manager: ${projectData.package_manager}` : ''}
975
940
  return {
976
941
  content: [{
977
942
  type: 'text',
978
- text: `🚀 Claude FAF Initialization:\n\n✅ Created project.faf\n\n${pathConfirmation}${sourceExplanation}\n\n🍊 Vitamin Context activated!\n⚡ FAFFLESS AI ready!${chromeDetection.detected ? '\n\n🎯 Friday Feature: Chrome Extension detected!\n📈 Auto-filled 7 slots for 90%+ score!' : ''}${chromeDetection.corrected ? `\n📝 Auto-corrected: "${args?.description}" → "${chromeDetection.corrected}"` : ''}\n\n🏁 Next steps:\n • Run faf_score for AI-readiness score\n • Run faf_bi_sync to create CLAUDE.md\n • Run faf_go to fill the gaps`
943
+ text: `🚀 FAF Initialization:\n\n✅ Created project.faf\n📊 ${score.score}/100 (${score.populated}/${score.active} slots populated) — ${score.tier.name}\n\n${pathConfirmation}${sourceExplanation}\n\n🍊 Vitamin Context activated!\n⚡ FAFFLESS AI ready!\n\n🏁 Next steps:\n • Run faf_score for AI-readiness score\n • Run faf_claude to write CLAUDE.md\n • Run faf_go to fill the gaps`
979
944
  }]
980
945
  };
981
946
  }
@@ -983,7 +948,7 @@ package_manager: ${projectData.package_manager}` : ''}
983
948
  return {
984
949
  content: [{
985
950
  type: 'text',
986
- text: `🚀 Claude FAF Initialization:\n\n❌ Error: ${error.message}`
951
+ text: `🚀 FAF Initialization:\n\n❌ Error: ${error.message}`
987
952
  }],
988
953
  isError: true
989
954
  };
@@ -1011,7 +976,7 @@ package_manager: ${projectData.package_manager}` : ''}
1011
976
  return {
1012
977
  content: [{
1013
978
  type: 'text',
1014
- text: `🔒 Claude FAF Trust Validation:\n\n❌ No .faf found in ${cwd}\n💡 Run faf_init to create one — then faf_trust reports real trust metrics.`
979
+ text: `🔒 FAF Trust Validation:\n\n❌ No .faf found in ${cwd}\n💡 Run faf_init to create one — then faf_trust reports real trust metrics.`
1015
980
  }]
1016
981
  };
1017
982
  }
@@ -1025,7 +990,7 @@ package_manager: ${projectData.package_manager}` : ''}
1025
990
  return {
1026
991
  content: [{
1027
992
  type: 'text',
1028
- text: `🔒 Claude FAF Trust Validation:\n\n❌ Could not read ${fafPath}: ${error?.message ?? String(error)}`
993
+ text: `🔒 FAF Trust Validation:\n\n❌ Could not read ${fafPath}: ${error?.message ?? String(error)}`
1029
994
  }],
1030
995
  isError: true
1031
996
  };
@@ -1045,7 +1010,7 @@ package_manager: ${projectData.package_manager}` : ''}
1045
1010
  return {
1046
1011
  content: [{
1047
1012
  type: 'text',
1048
- text: `🔒 Claude FAF Trust Validation:\n\n${output}`
1013
+ text: `🔒 FAF Trust Validation:\n\n${output}`
1049
1014
  }],
1050
1015
  isError: !validation.valid
1051
1016
  };
@@ -1062,7 +1027,7 @@ package_manager: ${projectData.package_manager}` : ''}
1062
1027
  return {
1063
1028
  content: [{
1064
1029
  type: 'text',
1065
- text: `🔄 Claude FAF Sync:\n\nFailed to sync: ${result.error}`
1030
+ text: `🔄 FAF Sync:\n\nFailed to sync: ${result.error}`
1066
1031
  }],
1067
1032
  isError: true
1068
1033
  };
@@ -1073,39 +1038,39 @@ package_manager: ${projectData.package_manager}` : ''}
1073
1038
  return {
1074
1039
  content: [{
1075
1040
  type: 'text',
1076
- text: `🔄 Claude FAF Sync:\n\n${output}`
1041
+ text: `🔄 FAF Sync:\n\n${output}`
1077
1042
  }]
1078
1043
  };
1079
1044
  }
1080
- async handleFafBiSync(args) {
1045
+ async handleFafClaude(args) {
1081
1046
  // Set project context if path provided
1082
1047
  if (args?.path) {
1083
1048
  this.getProjectPath(args.path);
1084
1049
  }
1085
1050
  // auto / watch / force used to be declared here too; none of them was
1086
- // ever read by syncBiDirectional, so the schema no longer promises them.
1087
- const biSyncArgs = [];
1051
+ // ever read by the command, so the schema no longer promises them.
1052
+ const claudeArgs = [];
1088
1053
  // v3.0 fix: the tool's own schema advertises agents/cursor/gemini/all,
1089
- // but they were never forwarded to engine-adapter's bi-sync dispatch —
1090
- // faf_bi_sync silently ignored them and only ever wrote CLAUDE.md.
1054
+ // but before 3.0 they were never forwarded to the engine adapter —
1055
+ // the tool silently ignored them and only ever wrote CLAUDE.md.
1091
1056
  if (args?.agents) {
1092
- biSyncArgs.push('--agents');
1057
+ claudeArgs.push('--agents');
1093
1058
  }
1094
1059
  if (args?.cursor) {
1095
- biSyncArgs.push('--cursor');
1060
+ claudeArgs.push('--cursor');
1096
1061
  }
1097
1062
  if (args?.gemini) {
1098
- biSyncArgs.push('--gemini');
1063
+ claudeArgs.push('--gemini');
1099
1064
  }
1100
1065
  if (args?.all) {
1101
- biSyncArgs.push('--all');
1066
+ claudeArgs.push('--all');
1102
1067
  }
1103
- const result = await this.engineAdapter.callEngine('bi-sync', biSyncArgs);
1068
+ const result = await this.engineAdapter.callEngine('claude', claudeArgs);
1104
1069
  if (!result.success) {
1105
1070
  return {
1106
1071
  content: [{
1107
1072
  type: 'text',
1108
- text: `🔗 Claude FAF Bi-Sync:\n\nFailed to bi-sync: ${result.error}`
1073
+ text: `🔗 FAF → CLAUDE.md:\n\nCould not write CLAUDE.md: ${result.error}`
1109
1074
  }],
1110
1075
  isError: true
1111
1076
  };
@@ -1116,7 +1081,7 @@ package_manager: ${projectData.package_manager}` : ''}
1116
1081
  return {
1117
1082
  content: [{
1118
1083
  type: 'text',
1119
- text: `🔗 Claude FAF Bi-Sync:\n\n${output}`
1084
+ text: `🔗 FAF → CLAUDE.md:\n\n${output}`
1120
1085
  }]
1121
1086
  };
1122
1087
  }
@@ -1159,7 +1124,7 @@ package_manager: ${projectData.package_manager}` : ''}
1159
1124
  return {
1160
1125
  content: [{
1161
1126
  type: 'text',
1162
- text: `🧹 Claude FAF Clear:\n\n${lines.join('\n')}`
1127
+ text: `🧹 FAF Clear:\n\n${lines.join('\n')}`
1163
1128
  }]
1164
1129
  };
1165
1130
  }
@@ -1188,7 +1153,7 @@ WHAT IS .FAF?
1188
1153
  • The dot (.) means it's a file format!
1189
1154
 
1190
1155
  🧡 Trust: Context verified
1191
- ⚡️ Speed: Generated in <29ms
1156
+ ⚡️ Speed: Authored in <29ms
1192
1157
  SPEEDY AI you can TRUST!
1193
1158
 
1194
1159
  Version ${packageInfo.version}
@@ -1199,10 +1164,10 @@ Just like JPEG makes images universal,
1199
1164
  HOW IT WORKS:
1200
1165
  1. Drop a file or paste the path
1201
1166
  2. Create .faf (Foundational AI-context Format)
1202
- 3. Talk to Claude to bi-sync it
1167
+ 3. Ask your AI to run faf_claude
1203
1168
  4. You're done⚡
1204
1169
 
1205
- 🩵 You just made Claude Happy
1170
+ 🩵 You just made your AI happy
1206
1171
  🧡⚡️ SPEEDY AI you can TRUST!`;
1207
1172
  return {
1208
1173
  content: [{
@@ -1221,7 +1186,7 @@ WHY: Just like JPEG makes images viewable everywhere,
1221
1186
  .faf makes projects understandable by AI.
1222
1187
 
1223
1188
  HOW: Run 'faf' on any project to create one.
1224
- Run 'faf_score' to check AI-readiness (target: 99%).
1189
+ Run 'faf_score' to check AI-readiness (target: 100%).
1225
1190
 
1226
1191
  REMEMBER: Always use ".faf" with the dot - it's a FORMAT!
1227
1192
 
@@ -1283,7 +1248,7 @@ ${debugInfo.permissions.writeError ? ` Error: ${debugInfo.permissions.writeErr
1283
1248
  return {
1284
1249
  content: [{
1285
1250
  type: 'text',
1286
- text: `🔍 Claude FAF Debug Failed: ${error instanceof Error ? error.message : String(error)}`
1251
+ text: `🔍 faf-mcp Debug Failed: ${error instanceof Error ? error.message : String(error)}`
1287
1252
  }],
1288
1253
  isError: true
1289
1254
  };
@@ -1335,7 +1300,6 @@ All work: \`faf init\`, \`faf init new\`, \`faf init --new\`, \`faf init -new\`
1335
1300
  **Extensions:**
1336
1301
  - \`new\` - force overwrite existing
1337
1302
  - \`full\` - detailed output
1338
- - \`bi\` - bi-directional sync
1339
1303
 
1340
1304
  ## UX Rules
1341
1305
  1. **Don't offer option menus** - just solve it
@@ -1495,7 +1459,7 @@ All work: \`faf init\`, \`faf init new\`, \`faf init --new\`, \`faf init -new\`
1495
1459
  }
1496
1460
  }
1497
1461
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1498
- // NEW: Human Context Tools (v3.2.0 parity)
1462
+ // Human Context Tools (parity with faf-cli v3.2.0)
1499
1463
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1500
1464
  async handleFafReadme(args) {
1501
1465
  try {
@@ -1722,7 +1686,7 @@ All work: \`faf init\`, \`faf init new\`, \`faf init --new\`, \`faf init -new\`
1722
1686
  }
1723
1687
  // Default: show quality report
1724
1688
  const icons = {
1725
- empty: '⬜', generic: '🟡', good: '🟢', excellent: '💎'
1689
+ empty: '⬜', generic: '◻️', good: '◼️', excellent: '💎'
1726
1690
  };
1727
1691
  let output = `🔍 FAF Human Context Quality\n\n`;
1728
1692
  for (const field of fields) {
@@ -1909,7 +1873,7 @@ All work: \`faf init\`, \`faf init new\`, \`faf init --new\`, \`faf init -new\`
1909
1873
  text: JSON.stringify({
1910
1874
  complete: true,
1911
1875
  score: 100,
1912
- message: '🏆 GOLD CODE ACHIEVED! Your project has 100% AI-Readiness.',
1876
+ message: '✪ GOLD CODE ACHIEVED! Your project has 100% AI-Readiness.',
1913
1877
  context: 'faf_go'
1914
1878
  }, null, 2)
1915
1879
  }]
@@ -2033,19 +1997,25 @@ All work: \`faf init\`, \`faf init new\`, \`faf init --new\`, \`faf init -new\`
2033
1997
  output += `⏱️ Completed in ${elapsed}s\n`;
2034
1998
  output += `📊 Before: ${beforeScore}% | After: ${newScore}% ${deltaDisplay}\n`;
2035
1999
  output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n`;
2036
- if (newScore >= 99) {
2037
- output += `🏆 CHAMPIONSHIP ACHIEVED! Your AI has complete context.\n`;
2000
+ if (newScore >= 100) {
2001
+ output += `✪ TROPHY — 100% AI-Readiness. Your AI has complete context.\n`;
2002
+ }
2003
+ else if (newScore >= 99) {
2004
+ output += `★ Gold — 1% to Trophy. Run faf_go to finish.\n`;
2005
+ }
2006
+ else if (newScore >= 95) {
2007
+ output += `◆ Silver — ${100 - newScore}% to Trophy.\n`;
2038
2008
  }
2039
2009
  else if (newScore >= 85) {
2040
- output += `🥇 Elite level! ${100 - newScore}% to perfection.\n`;
2010
+ output += `◇ Bronze — production ready. ${100 - newScore}% to Trophy.\n`;
2041
2011
  }
2042
2012
  else if (newScore >= 70) {
2043
- output += `🥈 Great progress! Run faf_go to reach championship.\n`;
2013
+ output += `● Green — solid foundation. Run faf_go to climb tiers.\n`;
2044
2014
  }
2045
2015
  else {
2046
2016
  output += `🚀 Good start! Run faf_go for guided improvement.\n`;
2047
2017
  }
2048
- output += `\n💡 Next: faf_score | faf_go | faf_bi_sync`;
2018
+ output += `\n💡 Next: faf_score | faf_go | faf_claude`;
2049
2019
  return { content: [{ type: 'text', text: output }] };
2050
2020
  }
2051
2021
  catch (error) {
@@ -2057,7 +2027,7 @@ All work: \`faf init\`, \`faf init new\`, \`faf init --new\`, \`faf init -new\`
2057
2027
  }
2058
2028
  /**
2059
2029
  * faf_dna - Show your FAF DNA journey
2060
- * Displays evolution from birth to current (22% → 85% → 99%)
2030
+ * Displays the score evolution from birth to today (e.g. 22% → 85% → 100%)
2061
2031
  */
2062
2032
  async handleFafDna(args) {
2063
2033
  const cwd = this.getProjectPath(args?.path);
@@ -2171,7 +2141,7 @@ All work: \`faf init\`, \`faf init new\`, \`faf init --new\`, \`faf init -new\`
2171
2141
  output += `\n🧬 MILESTONES\n`;
2172
2142
  const milestoneIcons = {
2173
2143
  birth: '🐣', first_save: '💾', doubled: '2️⃣', sync: '🔄',
2174
- championship: '🏆', elite: '⭐', peak: '🏔️', perfect: '💎'
2144
+ championship: '✪', elite: '⭐', peak: '🏔️', perfect: '💎'
2175
2145
  };
2176
2146
  for (const m of milestones) {
2177
2147
  const icon = milestoneIcons[m.type] || '📍';
@@ -2220,7 +2190,7 @@ All work: \`faf init\`, \`faf init new\`, \`faf init --new\`, \`faf init -new\`
2220
2190
  };
2221
2191
  }
2222
2192
  // Format human-readable output
2223
- let output = `😽 TURBO-CAT™ Format Discovery v2.0.0\n`;
2193
+ let output = `😽 TURBO-CAT™ Format Discovery\n`;
2224
2194
  output += `═══════════════════════════════════════════════════\n\n`;
2225
2195
  output += `✅ Found ${analysis.discoveredFormats.length} formats in ${elapsed}ms!\n\n`;
2226
2196
  output += `📋 Discovered Formats (A-Z):\n`;
@@ -2229,7 +2199,7 @@ All work: \`faf init\`, \`faf init new\`, \`faf init --new\`, \`faf init -new\`
2229
2199
  output += ` ✅ ${format.fileName}\n`;
2230
2200
  }
2231
2201
  output += `\n💡 Stack Signature: ${analysis.stackSignature}\n`;
2232
- output += `🏆 Intelligence Score: ${analysis.totalIntelligenceScore}\n\n`;
2202
+ output += `🧠 Intelligence Score: ${analysis.totalIntelligenceScore}\n\n`;
2233
2203
  if (Object.keys(analysis.slotFillRecommendations).length > 0) {
2234
2204
  output += `📊 Recommended Slot Fills:\n`;
2235
2205
  for (const [key, value] of Object.entries(analysis.slotFillRecommendations)) {
@@ -2438,7 +2408,7 @@ Use force: true to overwrite, or use faf_go / faf_human_add to modify.`
2438
2408
  results.push({
2439
2409
  status: 'error',
2440
2410
  message: '.faf file is empty',
2441
- fix: 'Run: faf_init with force option to regenerate'
2411
+ fix: 'Run: faf_init with force option to rewrite it'
2442
2412
  });
2443
2413
  }
2444
2414
  else {
@@ -2494,7 +2464,7 @@ Use force: true to overwrite, or use faf_go / faf_human_add to modify.`
2494
2464
  results.push({
2495
2465
  status: 'error',
2496
2466
  message: '.faf file is corrupted or invalid YAML',
2497
- fix: 'Run: faf_init with force option to regenerate'
2467
+ fix: 'Run: faf_init with force option to rewrite it'
2498
2468
  });
2499
2469
  }
2500
2470
  }
@@ -2504,13 +2474,13 @@ Use force: true to overwrite, or use faf_go / faf_human_add to modify.`
2504
2474
  results.push({
2505
2475
  status: 'warning',
2506
2476
  message: 'No CLAUDE.md file',
2507
- fix: 'Run: faf_auto or faf_bi_sync to create bi-directional sync'
2477
+ fix: 'Run: faf_auto or faf_claude to write CLAUDE.md'
2508
2478
  });
2509
2479
  }
2510
2480
  else {
2511
2481
  results.push({
2512
2482
  status: 'ok',
2513
- message: 'CLAUDE.md found (bi-sync ready)'
2483
+ message: 'CLAUDE.md found'
2514
2484
  });
2515
2485
  }
2516
2486
  // Check 6: Project detection
@@ -2568,7 +2538,7 @@ Use force: true to overwrite, or use faf_go / faf_human_add to modify.`
2568
2538
  }
2569
2539
  output += `\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n`;
2570
2540
  if (!hasErrors && !hasWarnings) {
2571
- output += `🏆 Perfect health! Your FAF setup is championship-ready!`;
2541
+ output += `✅ Perfect health! Your FAF setup is championship-ready!`;
2572
2542
  }
2573
2543
  else if (!hasErrors) {
2574
2544
  output += `🎯 Good health with minor improvements suggested.`;
@@ -2586,7 +2556,7 @@ Use force: true to overwrite, or use faf_go / faf_human_add to modify.`
2586
2556
  }
2587
2557
  }
2588
2558
  // ============================================================================
2589
- // v4.5.0 INTEROP HANDLERS
2559
+ // INTEROP HANDLERS (faf-mcp 2.0.0; ported from faf-cli 4.5.0 via claude-faf-mcp 4.5.0)
2590
2560
  // ============================================================================
2591
2561
  async handleFafAgents(args) {
2592
2562
  const cwd = this.getProjectPath(args?.path);
@@ -2724,7 +2694,7 @@ Use force: true to overwrite, or use faf_go / faf_human_add to modify.`
2724
2694
  let output = `GitHub Context:\n\n✅ ${data?.message || 'Done'}\n⏱️ ${result.duration}ms`;
2725
2695
  // Include generated .faf content if no output path (preview mode)
2726
2696
  if (!outputPath && data?.data?.fafContent) {
2727
- output += `\n\n--- Generated project.faf ---\n${data.data.fafContent}`;
2697
+ output += `\n\n--- Authored project.faf ---\n${data.data.fafContent}`;
2728
2698
  }
2729
2699
  return {
2730
2700
  content: [{ type: 'text', text: output }]