ProjectHub Scout is online free-tier constrained stack

Scout — Intelligence Engine for ProjectHub Recruiter Alpha

Scout is a portable intelligence engine that powers an AI recruiter assistant for Bradley Matera's portfolio. It uses Cloudflare Workers AI for generative inference, local BM25 retrieval for evidence gathering, server-owned session state for multi-turn coherence, and strict grounded validation — all within a 15-second response contract. The frontend widget runs on GitHub Pages with zero build step.

Bradley Matera · Recruiter assistant

Calm, concise, honest, and grounded in real project data — powered by Cloudflare Workers AI free-tier inference.

What Scout is

Scout is a portable intelligence engine — not a hard-coded FAQ bot. It retrieves from real project data, recruiter knowledge, and source material using local BM25 retrieval, then generates conversational replies through Cloudflare Workers AI. Every generated reply passes safety, entity, number, length, source-overlap, polarity, and overclaim validation before it reaches the visitor.

The frontend widget is vanilla JavaScript with no build step, embeddable via a single script tag on GitHub Pages. The backend runs on a free GCP e2-micro VM with Cloudflare Workers AI free-tier inference.

Live deployment status

Inference Cloudflare Workers AI

Model: @cf/meta/llama-3.1-8b-instruct-fast. RAG evidence is primary; one factual repair is allowed if the first generated answer fails validation.

Response contract 15-second deadline

Every request has a hard 15,000 ms budget. A factually invalid answer gets at most one generative repair; if that still fails, Scout fails closed instead of returning known-invalid prose.

Backend GCP e2-micro (free tier)

Node.js Express API with server-owned session state, BM25 retrieval, and Cloudflare inference routing.

Frontend GitHub Pages widget

Vanilla JavaScript, no build step. Embedded via a single script tag. Zero hosting cost.

Validation Strict grounded validation

Safety, entity grounding, number accuracy, source overlap, polarity, overclaim detection, and length checks on every reply.

Memory Server-owned session state

Per-tab session ID with topic tracking, referent resolution, and per-topic stance consistency (60-min TTL, cap 12).

Production is live at bradleymatera.dev/recruiter. The Scout Engineering Lab (experimental dev surface) is at bradleymatera.github.io/ProjectHub-dev.

What Scout answers

  • Project questions: Explain my projects, CodePens, GitHub repos, tech stack, and what each project proves.
  • Recruiter questions: Summarize my skills, background, certifications, AWS internship, education, and job fit.
  • Career-fit questions: Compare my real experience against roles like web developer, IT support, cloud support, DevOps, technical writing, QA, or data-focused work.
  • Grounded replies: All conversational responses are generated by the inference layer, then validated against retrieved evidence before delivery. No deterministic prose reaches the visitor.
  • Honest limits: If the evidence does not support an answer, Scout says so instead of inventing experience. Unknown tools fail closed; no public tool performs writes or arbitrary web access.

Scout pipeline

Visitor message
Conversation-aware query
BM25 + RRF top candidates
Ranked evidence packet
Cloudflare generation
Factual validation
Scout reply

How it works now

ProjectHub first resolves the current conversation into a retrieval query and always runs local BM25/RRF search. The highest-value evidence blocks become the model's primary context; structured tools may add evidence but do not replace RAG. Cloudflare Workers AI generates the conversational answer from that scoped packet. Factual validation then checks unsupported entities, relationships, project-to-technology attribution, employment, certifications, temporal claims, and overclaiming. If the first generation is factually invalid, Scout gets one evidence-guided generative repair. If the repair is still invalid, the request fails closed with a technical error instead of exposing known-invalid prose.

Inference efficiency

Scout saves hosted-model work by shrinking the context before generation rather than trying to replace the model with hard-coded answers.

  • Local retrieval first: BM25/RRF searches the verified knowledge without a model call.
  • Small evidence packet: only the highest-value evidence blocks are sent to Cloudflare instead of the entire knowledge base.
  • One normal generation: most successful requests use one provider call; a second call is reserved for factual repair.
  • Visible accounting: each reply exposes provider calls, input/output tokens, neurons, model latency, RAG selection, and repairs.
  • Fail closed: validation cannot silently return a known-invalid answer just to save a provider call.

Browser WebGPU direction

The inference adapter boundary is designed for future browser-side WebGPU generation. In this model, capable browsers would run inference locally on the visitor's GPU, eliminating cloud inference costs entirely. Incapable browsers would fall back to cloud generation transparently. The server remains authoritative for RAG, state, evidence, validation, and orchestration regardless of where generation occurs.

This is an active research direction, not a current production feature. The Scout Engineering Lab (ProjectHub-dev) includes a browser capability panel that probes WebGPU support, memory, and adapter info.

Free-tier stack

GitHub Pages

Hosts the widget, landing page, and knowledge JSON for free.

Cloudflare Workers AI

Generative inference with @cf/meta/llama-3.1-8b-instruct-fast. The included allocation is 10,000 neurons per day, resetting at 00:00 UTC; the page now exposes live estimated usage.

GCP e2-micro (free tier)

Runs the Node.js Express API, BM25 retrieval, session state, and validation.

Bundled knowledge

Verified recruiter facts and BM25 retrieval require no external database or API key.

How to embed ProjectHub

This is the script tag used to load the floating ProjectHub chat widget:

<script src="https://bradleymatera.github.io/ProjectHub/ProjectHub.js?v=14"></script>

If the script is cached aggressively, bump the version query like ?v=14.

Important links

Development state

Active branch: feat/rag-primary-restoration. The dev surface is validating the RAG-first pipeline, factual validator restoration, privacy controls, and live token/neuron/cost telemetry against the separate dev backend.

Latest commit

9b5728f — Scout alpha production state: Cloudflare Workers AI inference, session state fixes, lenient validation, GREETING mode relaxation, clarification fallback fix, cache-hit session state update. 667 unit tests passing, 29 retrieval tests passing.

Scout pipeline (detailed)

Visitor message
Session state lookup
Query understanding
Policy classification
BM25 retrieval (RRF)
Response contract
Inference generation
Grounding validation
Recovery (×3)
Session state update
Scout reply

Stage details

StageModuleWhat happens
Session statelib/session-state.jsLook up per-tab session ID. Track current topic, projects, recent turns, stances.
Query understandinglib/query-understanding.jsNormalize, typo-correct, classify intent, rewrite bare follow-ups with context.
Policy classificationlib/response-policy-classifier.jsDetermine response mode: GREETING, VERIFIED_FACT, PROFILE, OUT_OF_SCOPE, REFUSAL, FALSE_CLAIM_DENIAL.
BM25 retrievallib/bm25.js, lib/rrf.jsOkapi BM25 with TF saturation, IDF weighting, doc-length normalization. RRF fuses literal, alias-expanded, and context-rewritten rankings (k=60).
Response contractlib/response-contract.jsBuild requiredFacts, optionalFacts, contextEntities, mustMentionEntities, evidenceEntities, forbiddenEntities, responseShape.
Inferencelib/local-model-router.js, lib/cloudflare-provider.jsGenerate conversational reply from contract + evidence + conversation state. Cloudflare Workers AI in prod, Ollama in dev.
Validationlib/grounding-validator.jsEntity grounding, number accuracy, source overlap, polarity, overclaim, safety, length, fabricated entity detection.
Recoverylib/lite-agent.jsUp to 3 attempts with progressively lenient validation. Final attempt uses lenientValidate (safety-critical only).
Session updatelib/session-state.jsRecord turn, update topic, projects, stances. 60-min TTL, cap 12 stances.

Production vs. development

DimensionProductionDevelopment
Backend URLprojecthub-chat.bradleymatera.devdev.projecthub-chat.bradleymatera.dev
Widget assetbradleymatera.github.io/ProjectHub/ProjectHub.js./ProjectHub.js (local dev asset)
Inference providerCloudflare Workers AIOllama (qwen2.5:1.5b)
Model@cf/meta/llama-3.1-8b-instruct-fastqwen2.5:1.5b
Agent modeLite agent (production-safe)Full agent (experimental tools enabled)
ValidationStrict + lenient recoveryStrict + lenient recovery (same)
Session stateServer-owned, in-memoryServer-owned, in-memory (same)
Response cacheEnabled (5-min TTL)Enabled (5-min TTL)
Think ModeDisabledEnabled (20-min interval)
Deadline15,000 ms15,000 ms (same)

Inference routing

The inference adapter (lib/local-model-router.js) abstracts the provider behind a unified generate() interface. Provider selection is driven by environment variables:

Env varProduction valueDev value
SCOUT_INFERENCE_PROVIDERcloudflareollama
CLOUDFLARE_ACCOUNT_IDSetNot set
CLOUDFLARE_API_TOKENSetNot set
OLLAMA_BASE_URLNot sethttp://127.0.0.1:11434
SCOUT_AGENT_ENGINE_ENABLEDtruetrue
SCOUT_AGENT_MODElitefull

Future: browser WebGPU routing

The adapter is designed for a third provider: browser-webgpu. In this mode, the server would send the contract + evidence to the browser, which runs inference locally via WebGPU. The server remains authoritative for RAG, state, validation, and orchestration. This is not yet implemented.

WebGPU research

Browser-side WebGPU inference would eliminate cloud inference costs for capable browsers. The research direction involves:

  • Adapter detection: Probe navigator.gpu, request adapter, query device limits.
  • Model selection: Identify browser-runnable models (ONNX, GGUF via WebLLM) that fit GPU memory.
  • Fallback chain: WebGPU → Cloudflare Workers AI → constrained grounded recovery.
  • Validation parity: Server-side validation must still run on browser-generated text.
  • Contract transport: Server sends JSON contract; browser generates; server validates.

The browser capability panel below probes your current browser for WebGPU support.

Neuron economics

Cloudflare Workers AI uses neuron-based pricing. Each generation call consumes neurons proportional to input + output tokens. The free tier provides a generous monthly allocation. Scout's efficiency strategies:

StrategyImpact
Response cacheEliminates inference calls for repeated questions within 5-min window
Context budget (5 turns)Reduces input tokens vs. full history
Policy-aware contractsGREETING mode = smaller contract = fewer input tokens
Lenient recoveryAvoids 4th+ inference call when answer is "close enough"
Max 3 recovery attemptsHard cap on inference calls per request
15s deadlinePrevents runaway generation from consuming neurons

15-second budget

Every request has a hard 15,000 ms deadline enforced by server-gemini.js. The budget is allocated across pipeline stages:

StageBudgetNotes
Session + query understanding~50 msIn-memory lookup + sync processing
BM25 retrieval + RRF~100 msLocal index, no network
Response contract~20 msSync contract construction
Inference generation~5–12 sCloudflare Workers AI round-trip
Validation~50 msSync validation checks
Recovery (if needed)remaining budgetUp to 3 attempts, each with inference
Session update~10 msIn-memory state update

If the deadline fires during generation, Scout delivers a constrained grounded fallback — never an incomplete or unvalidated reply.

Retrieval

BM25 configuration

ParameterValue
k1 (TF saturation)1.2
b (doc-length normalization)0.75
RRF k60
Views fusedLiteral, alias-expanded, context-rewritten
Golden eval set40 queries
Recall@61.000

Query understanding pipeline

  • Normalization: Lowercase, strip punctuation, collapse whitespace.
  • Typo correction: Damerau-Levenshtein against vocabulary (edit distance ≤ 2).
  • Intent classification: Contact, role-fit, experience, smalltalk, frustration, factual-lookup.
  • Contextual rewriting: Bare follow-ups ("tell me more about that") rewritten using recent turns.

Response contracts

The response contract (lib/response-contract.js) defines what the generated reply must contain and what it must not contain:

FieldPurpose
requiredFactsFacts that must appear in the reply
optionalFactsFacts that may be included for context
contextEntitiesEntities from the question context
mustMentionEntitiesEntities that must appear in the reply
evidenceEntitiesEntities from retrieved evidence
forbiddenEntitiesEntities that must NOT appear (e.g., wrong person, wrong company)
responseShapeMin sentences, max sentences, expected structure
policyModeGREETING, VERIFIED_FACT, REFUSAL, etc. — drives validation strictness

Validation layers

CheckModuleWhat it catches
SafetyGrounding validatorPII leakage, harmful content, private data
Entity groundingGrounding validatorEntities in reply not supported by evidence
Fabricated entityGrounding validatorEntities not in knowledge base
Number accuracyGrounding validatorNumbers in reply not matching evidence
Source overlapGrounding validatorReply doesn't overlap with retrieved evidence
PolarityGrounding validatorAffirming a false claim or denying a true one
OverclaimGrounding validatorClaiming more than evidence supports
Cross-project provenanceGrounding validatorAttributing one project's facts to another
Technology claimslib/claim-extractor.jsUnsupported tech stack claims with alias matching
Relationship validitylib/relationship-validator.jsUnsupported entity relationships (e.g., "uses_tech" not in graph)
Completenesslib/completeness-check.jsReply too short or missing required content
Negation scopelib/negation-scope.jsNegated claims incorrectly flagged or affirmed

Policy-aware validation

GREETING mode skips entity grounding, fabricated entity, and relevance checks — greetings don't need topic overlap or knowledge-base entity support. All other modes run full validation.

Recovery

When the initial generation fails validation, Scout attempts generative recovery:

AttemptValidationPrompt strategy
1 (initial)Full strictStandard contract + evidence
2 (recovery 1)LenientRejection reason + "fix this issue" instruction
3 (recovery 2)LenientStricter constraint emphasis + evidence re-injection
4 (recovery 3)Lenient (safety-critical only)Minimal prompt — accept any safe answer
5 (fallback)N/AConstrained grounded recovery — no inference call

Lenient validation only rejects on safety-critical issues (PII leakage, harmful content). It accepts minor grounding imperfections to avoid wasting inference cycles on near-misses from the small model.

Conversation state

Server-owned session state (lib/session-state.js) enables multi-turn coherence:

  • currentTopic: Tracks what the conversation is about (e.g., "projects", "skills", "experience").
  • currentProjects: Which projects were recently mentioned — enables "tell me more about that one."
  • recentTurns: Last 5 turns for context window construction.
  • topicStances: Per-topic positions Scout has taken (e.g., "Bradley's main stack is JavaScript") — prevents contradictions. 60-min TTL, cap 12.
  • Cache-hit update: Even cached responses update session state so follow-ups work after a cache hit.

Referent resolution

When a visitor says "tell me more about that" or "what tech does it use", Scout resolves the referent ("that", "it") using lib/conversation-resolver.js:

  • Build conversation state: Construct context from recent turns + session state.
  • Resolve referent: Map pronouns to the most recent subject in session state.
  • Rewrite query: Replace "it" → "ProjectHub", "that" → "the weather dashboard", etc.
  • BM25 with rewritten query: Retrieval uses the rewritten query for better evidence matching.

Failure taxonomy

Failure typeCauseRecovery
entity_not_groundedReply mentions entity not in evidenceRecovery with entity constraint
fabricated_entityReply mentions entity not in knowledge baseRecovery with entity allowlist
not_relevant_to_questionReply doesn't address the question topicRecovery with topic emphasis
number_mismatchNumbers in reply don't match evidenceRecovery with number constraint
polarity_violationAffirming false claim or denying true oneRecovery with polarity correction
overclaimReply claims more than evidence supportsRecovery with scope limitation
cross_project_provenanceOne project's facts attributed to anotherRecovery with project disambiguation
unsupported_tech_claimTech mentioned not in evidenceRecovery with tech allowlist
relationship_violationUnsupported entity relationshipRecovery with relationship graph
incomplete_answerReply too short or missing required contentRecovery with completeness emphasis
safety_violationPII leakage or harmful contentImmediate fallback, no recovery
deadline_exceeded15s budget exhaustedConstrained grounded fallback
clarification_requiredQuestion too ambiguous to answerScout asks for clarification

Current experiments

Browser WebGPU inference

Probe WebGPU adapter, identify runnable models, design contract transport protocol.

Think Mode self-improvement

20-min loop: stash weak answers, generate improved wording, score, judge, retain validated improvements locally.

Relationship graph expansion

Graph-derived type words replace hardcoded lists. Entity-type validation uses is_type triples.

Negation-aware claim parsing

lib/negation-scope.js prevents negated tech claims from being flagged as unsupported.

Tenant portability

Engine works with non-Bradley knowledge sets. Two-tenant test suite validates cross-tenant isolation.

Docker production-parity

docker-compose.yml provides Ollama-parity testing. Cloudflare production uses GCP VM direct deploy.

Latest benchmarks

MetricValueSource
Unit tests667 pass, 0 failnpm test
Retrieval tests29 pass, 0 failnpm run test:retrieval
BM25 Recall@61.00040-query golden set
Test suites11Node test runner
Production smoke10/10 passscripts/prod-smoke-test.js
Conversation regression132 inputs126 production + 6-turn unknown-tech repair
Local API eval61 requestsscripts/eval-local-api.js

Known limitations

  • Hosted model constraints: @cf/meta/llama-3.1-8b-instruct-fast (prod) and qwen2.5:1.5b (dev) are general-purpose instruction-tuned models. They can hallucinate, miss nuances, or produce awkward phrasing. Validation and recovery compensate but cannot eliminate all errors.
  • No persistent storage: Session state is in-memory on the GCP VM. A VM restart loses all sessions. No external database.
  • Free-tier rate limits: Cloudflare Workers AI free tier has neuron allocation limits. High traffic could exhaust the monthly allocation.
  • Single VM: One GCP e2-micro instance. No horizontal scaling, no load balancer, no redundancy.
  • No streaming: Responses are delivered as complete JSON, not streamed. The 15s budget includes full round-trip.
  • WebGPU not implemented: Browser-side inference is a research direction, not a current feature.
  • Think Mode is dev-only: The self-improvement loop runs only on the dev backend. It never writes to GitHub or external systems.
  • No multi-language: Scout speaks English only. No internationalization layer.

Browser capability panel

Probing your browser…

WebGPU: checking…
GPU Adapter: checking…
GPU Memory: checking…
WebLLM support: checking…
WebAssembly: checking…
Hardware concurrency: checking…
Device memory: checking…