Stage 2 of the Ardur AI content pipeline. The deterministic topic-rating engine. Consumes the
AggregationArtifactand produces aRankingArtifactforardur-top10-engine.
Implements the finalized Ardur topic-rating model (design:
~/Documents/Ardur-AI-Website/news-rating-system.md, mirrored in
docs/spec.md). The full scoring engine is implemented —
all four signal extractors, recency decay, diversity, confidence gating,
tie-breaking, audit trail, and runRanking() orchestration. Deterministic, no
paid-API dependency, 141 tests green.
For each topic (a cluster of independent articles about one story), every 6h:
Score = Recency(t) × [ 0.30·C + 0.28·T + 0.22·S + 0.20·E ] × Diversity
| Symbol | Signal | Definition |
|---|---|---|
| C | Corroboration | min(1, ln(1+n)/ln(1+8)), n = independent source owners (not URLs), tier ≥ T3 |
| T | Technical significance | rules over CVE severity (KEV/CVSS/EPSS) / semver / release type; +0.1 AI / platform-eng lean |
| S | Source tier | 0.7·maxTier + 0.3·meanTier (T1 official 1.0 → T4 unknown 0.15) |
| E | Engagement | capped, baseline-normalized velocity (HN/GitHub/Reddit), counts only; necessary-not-sufficient |
| Recency(t) | multiplier ∈ (0,1] | 0.5^(t/H), H = 12 + 24·T h; t = age of the freshest corroboration (re-coverage resets decay) |
| Diversity | multiplier ∈ [0.8,1.15] | owner/type entropy; single-owner/single-type → echo penalty |
The four core weights sum to 1.0; with signals in [0,1] and the multipliers,
Score ∈ [0, 1.15].
Confidence is separate from score and drives the editorial gate:
Confidence = 0.35·C + 0.30·tierConf + 0.20·cohesion + 0.15·agreement
≥ 0.66 → auto-publish · 0.40–0.66 → flagged (review badge) · < 0.40 → editorial hold
- Deterministic core, no paid API. Every formula — corroboration curve, significance rules, tier blend, capped engagement, recency decay, diversity, confidence, the gate, and tie-breaks — is a pure function over metadata and public counts. Same inputs ⇒ same output.
- LLM is optional enrichment only. Sharper NER, near-dup merge, label/take polish. On budget exhaustion or failure the deterministic path still ships a complete, ranked Top-10.
- Copyright-safe. Operates on titles, source names, URLs, timestamps, extracted topic labels, and public counts — never article bodies.
- Anti-gaming. Owners-not-URLs dedup, per-platform velocity caps, a diversity echo-penalty, and "engagement alone can't reach the Top-10" (needs ≥2 independent owners or a Tier-1 primary).
flowchart LR
A[ardur-news-aggregator] -->|AggregationArtifact| R[ardur-ranking-engine]
R -->|RankingArtifact| T[ardur-top10-engine]
T --> S[ardur-article-synthesizer]
runRanking(aggregation) returns a RankingArtifact (see
src/contracts.ts):
rankedByTopic—RankedCluster[]per topic, sorted by score, each with aScoreBreakdown,sourceQuality,confidence,verification, andauditId.audit—AuditEntry[]: the lossless record of every topic's rating (all four signals incl. T, both multipliers, weights, confidence) — anyone can recompute the score.weightProfile— the profile id+version applied (balanced@v1).
Contract note. As of Rev 3,
ScoreBreakdownhas a typedtechnicalSignificancefield andtoScoreBreakdown()emits it — the mapping is fully lossless (C / T / S / E + recency / diversity multipliers + all four weights). The auditinputsstill carry the complete per-signal breakdown for independent recomputation.
| Path | Role |
|---|---|
src/contracts.ts |
Shared pipeline contract (identical across all 4 repos — do not edit here). |
src/weights.ts |
WeightProfile registry + balanced@v1 (all tunable model config, pure data). |
src/signals.ts |
The model's pure signal transforms + cluster→signal extraction. |
src/score.ts |
Score combination, confidence + gate, tie-breaks, contract mapping. |
src/audit.ts |
Lossless, reproducible audit-entry construction. |
src/index.ts |
runRanking() entrypoint + public surface. |
src/runners.ts |
CLI entrypoint: --in/--out/--now/--run-id/--describe; structured error envelope. |
src/model.test.ts |
Conformance tests against the spec's worked values. |
src/ranking.test.ts |
Integration + boundary tests for signal extractors and runRanking. |
npm install
npm run typecheck
npm test # model conformance + smoke
npm run buildMIT © 2026 ArdurAI