File size: 3,519 Bytes
5448d8b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env node
// Validates that count-based assertions in docs match the actual code state.
// Examples checked:
//   - executors count in open-sse/executors/
//   - routing strategies in src/shared/constants/routingStrategies.ts
//   - OAuth providers in src/lib/oauth/providers/
//   - A2A skills in src/lib/a2a/skills/
//   - Cloud agents in src/lib/cloudAgent/agents/
//
// Exits 0 on success, 1 on detected drift.
// Run: node scripts/check/check-docs-counts-sync.mjs

import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, "..", "..");

const COMMON_NON_IMPL_BASENAMES = new Set([
  "index.ts",
  "index.mts",
  "types.ts",
  "base.ts",
  "constants.ts",
]);

function countFiles(dir, suffix = ".ts") {
  const abs = path.join(ROOT, dir);
  if (!fs.existsSync(abs)) return 0;
  return fs
    .readdirSync(abs)
    .filter(
      (f) =>
        f.endsWith(suffix) &&
        !f.endsWith(".test.ts") &&
        !f.startsWith("__") &&
        !COMMON_NON_IMPL_BASENAMES.has(f)
    ).length;
}

function countRoutingStrategies() {
  const file = path.join(ROOT, "src", "shared", "constants", "routingStrategies.ts");
  if (!fs.existsSync(file)) return 0;
  const txt = fs.readFileSync(file, "utf8");
  const m = txt.match(/ROUTING_STRATEGY_VALUES\s*=\s*\[([^\]]*)\]/);
  if (!m) return 0;
  return (m[1].match(/"[^"]+"/g) || []).length;
}

function docContains(docPath, needle) {
  const abs = path.join(ROOT, "docs", docPath);
  if (!fs.existsSync(abs)) return false;
  return fs.readFileSync(abs, "utf8").includes(needle);
}

const checks = [
  {
    label: "Executors count",
    actual: countFiles("open-sse/executors"),
    docKey: "executors",
    docs: ["architecture/ARCHITECTURE.md", "architecture/CODEBASE_DOCUMENTATION.md"],
  },
  {
    label: "Routing strategies count",
    actual: countRoutingStrategies(),
    docKey: "strategies",
    docs: ["routing/AUTO-COMBO.md", "architecture/RESILIENCE_GUIDE.md"],
  },
  {
    label: "OAuth providers count",
    actual: countFiles("src/lib/oauth/providers"),
    docKey: "OAuth providers",
    docs: ["architecture/ARCHITECTURE.md"],
  },
  {
    label: "A2A skills count",
    actual: countFiles("src/lib/a2a/skills"),
    docKey: "A2A skills",
    docs: ["frameworks/A2A-SERVER.md"],
  },
  {
    label: "Cloud agents count",
    actual: countFiles("src/lib/cloudAgent/agents"),
    docKey: "cloud agents",
    docs: ["frameworks/CLOUD_AGENT.md", "frameworks/AGENT_PROTOCOLS_GUIDE.md"],
  },
];

let drift = 0;
console.log("Docs counts sync report");
console.log("=======================");

for (const c of checks) {
  console.log(`\n• ${c.label}: ${c.actual} (real)`);
  for (const doc of c.docs) {
    const found = docContains(doc, String(c.actual));
    if (found) {
      console.log(`  ✓ docs/${doc} mentions "${c.actual}"`);
    } else {
      console.log(`  ⚠ docs/${doc} does NOT mention "${c.actual}" for ${c.docKey}`);
      drift++;
    }
  }
}

console.log();
if (drift > 0) {
  console.warn(`⚠ ${drift} potential drift(s) detected. Review the docs above.`);
  // Soft-fail by default (count-based heuristic can false-positive).
  // To enforce, pass --strict.
  if (process.argv.includes("--strict")) process.exit(1);
} else {
  console.log("✓ All checks pass.");
}