fleet-memory/hindsight-docs/scripts/check-integration-seo.mjs
Nicolò Boschi 7990381f6a
fix(ci): resolve all CI failures (#847)
* fix(ci): resolve all CI failures — unversioned integrations, test retries

- Move integration docs to separate unversioned docs plugin (docs-integrations/)
  so new integrations don't need to be duplicated across versioned_docs
- Remove integration pages from versioned_docs (v0.3, v0.4) — sidebar
  entries now use links instead of doc refs
- Add missing title/description SEO frontmatter to autogen.md
- Add retry logic (2 attempts) to test-doc-examples.sh for transient
  LLM timeouts
- Add pytest-rerunfailures to test-api with --reruns 2 for flaky
  Gemini-dependent integration tests

* ci: retrigger

* fix: graph entity inheritance, SyncTaskBackend error propagation, fact_type test regressions

- Fix observation entity inheritance in get_graph_data: the unit_entities
  query only fetched entities for visible observation IDs, not their source
  memory IDs, so the inheritance loop always found an empty entity_map
- Remove error swallowing in SyncTaskBackend._execute_task so test failures
  surface instead of being silently logged
- Wrap remaining consolidation submission call sites with try/except since
  consolidation is non-critical for those operations
- Fix test_sync_backend test to expect errors to propagate
- Remove fact_type=["world"] filter from test_document_upsert_behavior and
  test_mentioned_at_from_context_string (same PR #848 regression)
- Remove flaky marker from consolidation test (now deterministic)
2026-04-02 17:17:42 +02:00

70 lines
2.6 KiB
JavaScript

#!/usr/bin/env node
/**
* Validates that every integration docs page has `title` and `description`
* in its frontmatter for SEO purposes.
*
* Only checks docs/sdks/integrations/ (the current/unreleased version).
* Versioned docs are frozen snapshots and checked separately on release.
*
* Run: node scripts/check-integration-seo.mjs
*/
import { readFileSync, readdirSync } from 'node:fs';
import { join, relative } from 'node:path';
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const integrationsDir = join(__dirname, '..', 'docs-integrations');
const IGNORED_FILES = ['_template.md', '_category_.json'];
function parseFrontmatter(content) {
if (!content.startsWith('---')) return {};
const end = content.indexOf('\n---', 3);
if (end === -1) return {};
const fm = content.slice(4, end);
const fields = {};
for (const line of fm.split('\n')) {
const match = line.match(/^(\w[\w-]*):\s*(.+)$/);
if (match) fields[match[1]] = match[2].trim();
}
return fields;
}
// ─── Main ────────────────────────────────────────────────────────────────────
const files = readdirSync(integrationsDir).filter(
f => (f.endsWith('.md') || f.endsWith('.mdx')) && !IGNORED_FILES.includes(f)
);
const violations = [];
for (const filename of files) {
const filepath = join(integrationsDir, filename);
const content = readFileSync(filepath, 'utf8');
const fm = parseFrontmatter(content);
const missing = [];
if (!fm.title) missing.push('title');
if (!fm.description) missing.push('description');
if (missing.length > 0) {
violations.push({ filename, missing });
}
}
if (violations.length > 0) {
console.error('[integration-seo] ❌ The following integration pages are missing required frontmatter:\n');
for (const { filename, missing } of violations) {
console.error(` docs-integrations/${filename} — missing: ${missing.join(', ')}`);
}
console.error('\nAll integration pages must have both `title` and `description` in their frontmatter.');
console.error('Example:\n');
console.error(' ---');
console.error(' sidebar_position: 1');
console.error(' title: "MyFramework Persistent Memory with Hindsight | Integration"');
console.error(' description: "Add long-term memory to MyFramework agents with Hindsight. ..."');
console.error(' ---');
process.exit(1);
} else {
console.log(`[integration-seo] ✅ All ${files.length} integration pages have title and description.`);
}