Answer · AI-written from the repository source
NiubiGEO is a GEO (Generative Engine Optimization) research tool — it runs structured "audits" that ask AI providers brand-related prompts, classifies the intent behind each question, checks whether the AI's answer satisfies that intent, and compiles the results into human-readable reports. Here's the flow based on what's in the retrieved code:
1. Planning an audit
A request comes in (e.g. POST /projects or POST /audit-jobs in src/server.ts:L649-662) carrying a "confirmed plan" — target domain, competitors, provider targets, language, prompt counts, keywords, etc. If no plan is given, the server builds one via AuditPlanner().plan(...), passing along things like target, competitors, providerTargets, promptCount, keywords, and autoDiscover src/server.ts:L927-941.
2. Running the audit
The plan is executed by AuditRunner().run(...), which actually queries the AI providers with the prompts and produces an output containing audit, metrics, gaps, and paths src/server.ts:L941-945. For recurring checks, a MonitoringService re-runs a baseline's existing prompts against providers on a schedule ("run-due" jobs) src/server.ts:L863-870.
3. Classifying each prompt's intent
Before/while interpreting answers, prompts are run through a brand-question classifier. INTENT_DEFINITIONS in src/prompts/brand-question-classifier.ts:L17-38 define categories like product_understanding, brand_evaluation, recommendation, comparison, alternative, pricing, product_fit, purchase_decision, risk_evaluation, adoption, and source_analysis, each with a definition and a "boundary" to disambiguate overlapping intents.
A separate intentAnalyzerInstructions() in src/intent/intent-analyzer.ts:L7-27 defines the schema an LLM must fill in per prompt: primaryIntent, secondaryIntents, requestedOutputs, targetBrandRole, booleans like requiresSources/requiresComparison/requiresRecommendation, and an uncertainty level. This is how the system decides what the user was really asking before judging whether the AI's answer satisfied it.
4. Tracking whether web search was used
searchSummary() in src/report/human-report.ts:L152-160 inspects run.search (or run.result?.search) to report whether the provider used live web search, requested-but-unconfirmed search, or no search at all — localized into Chinese, English, and Portuguese.
5. Persisting results as projects/baselines/runs
Results are saved through a ProjectService/ProjectStore abstraction: a project is derived from the confirmed plan, a baseline captures the initial prompt set, and subsequent audits become runs tied to that baseline via RunOrchestrator src/server.ts:L663-674, L915-L919. The server exposes REST-style read endpoints for baselines, tasks, runs, observations, and events per project, plus a combined workbench view built by WorkbenchReadModelBuilder src/server.ts:L684-713.
6. Building the human report
renderIntentAnswerDetails() in src/report/report-builder.ts:L153-192 turns the intent-analysis output into a narrative report section per answer: what the user asked for (requestedOutputs), what the AI answered, what it missed, what was uncertain, per-task completion status with evidence quotes, and mentioned entity relationships — all localized (zh / en / pt-BR).
In short: plan → run prompts against AI providers → classify each prompt's intent → judge whether the response satisfied that intent (including search usage) → persist as project/baseline/run data → render into a structured, localized visibility/competitor report.
Per RepoPilot's architecture signals, the most central files in the whole repo are actually the examples/lib/*.mjs helpers (io.mjs with 12 importers, study.mjs with 6), suggesting a lot of the day-to-day usage/examples logic funnels through those utility modules — worth reading first if you want the practical entry points, alongside `src
The saved answer stops here; it was cut off when it was generated.