Documentation Plan
This wiki is organized as a disposable, self-contained technical reference under public/wiki/. It intentionally does not depend on the application router, layout, database, or session state.
- Inventory the current routes, controllers, services, jobs, and migrations.
- Document the user-facing feature set and the account/post model.
- Describe the score formulas in code-level terms, including OSINT-specific scoring.
- Record operations, testing, deployment, and known incomplete areas.
Architecture
TruthX is a PHP application running through public/index.php. Routes live in routes/web.php, controllers in app/Controllers, business rules in app/Services, database access helpers in app/Models, and templates in views.
Request Flow
Requests enter the front controller, match a route, run middleware such as auth or CSRF checks, call a controller, and render a view or JSON response.
Storage
Primary data is stored in MySQL. Migrations live in database/migrations and are applied through database/migrate.php.
Assets
Public CSS, JavaScript, images, uploads, and this wiki are served directly from public/.
Current Features
- Public and signed-in feeds ranked by quality score adjusted for post age and quality filters.
- Registration, login, logout, password reset, email verification, and profile editing.
- Case-sensitive alphanumeric usernames in the UI, with profile URLs that can resolve case-insensitively.
- Posts, replies, image uploads, likes, follows, pure reposts, deleted-post placeholders, and profile timelines.
- OSINT posting and verification for current or near-current claims.
- Scoring explainer pages:
/what-we-measureand/how-to-write-well. - Admin actions for manual rescoring and manual OSINT verification checks.
- Small
$metadata control on scored posts for API cost and token debugging.
Account Types And Privileges
| Account State | What It Allows | Where It Lives |
|---|---|---|
| Regular user | Posts, replies, likes, follows, profile, reposts, and normal scoring. | users, auth controllers, post services |
| Admin | Manual rescore, manual OSINT assessment, and OSINT publishing. | is_admin, admin routes |
| OSINT publisher | Can mark eligible top-level posts as OSINT claims. | is_breaking_news_publisher |
| Low writer quality | May receive warning emails and can be required to add payment before more AI-scored posting. | WriterPrivilegesService |
Writer quality is derived from scored posts. New users start at 280 characters. After the configured minimum scored-post count, score thresholds unlock higher tiers: Emerging at 50+, Established at 70+, and Elite at 85+.
Post Types
Post
A top-level public post. It can include text, images, source URLs for scoring, OSINT flagging when permitted, and paywall selection when eligible.
Reply
A post linked to a parent with reply_to_post_id. Replies are shown in thread views and count toward writer quality after scoring.
Repost
A pure repost creates an idempotent row in reposts and a posts-table shell with type = repost, so it appears in feeds and profiles as "Reposted by".
Essay
A long-form top-level post available to Established and Elite writers. Feed views show a summary and a read link.
Quote reposts are disabled. Legacy database columns can still exist for compatibility, but there is no visible quote action, no client-side quote prompt, no feed/thread quote rendering, and server-side quote creation is rejected.
Regular Scoring
Regular post quality is scored by CommentScoringService. It gathers the post, parent/root context, optional source URL summaries, optional image assessment, a heuristic fallback, and any configured OpenAI or Anthropic text scorers. Latest scores per model are averaged in Post::latestScoresFor().
Primary Rubric Formula
final = 100 * (
0.15 * claim_clarity +
0.25 * evidence_support +
0.20 * reasoning_quality +
0.15 * factual_responsibility +
0.15 * discussion_value +
0.10 * tone_and_conduct
)
Legacy Fallback Formula
final = 100 * (
0.20 * relevance +
0.25 * information_value +
0.25 * factuality +
0.10 * source_support +
0.10 * (1 - spam) +
0.10 * (1 - toxicity)
)
High spam, toxicity, or low confidence applies additional score reductions. Verdict thresholds are configured as high 80, medium 60, low 40, and spam 20 by default.
OSINT And Verification
OSINT is for current or near-current factual claims only. Older research-style items are blocked from the OSINT composer path and should be posted normally.
Verification Jobs
New OSINT posts enqueue an immediate self-attestation check, then automated corroboration checks at 1 hour, 6 hours, and 24 hours through BreakingTruthJob::enqueueSchedule().
Evidence Sources
BreakingTruthAssessmentService combines capped self-attestation, manual sources, and trusted news search results into one verification score.
Post Status
A post shows awaiting verification while under 24 hours with score 0, becomes verified when any pathway raises the score above 0, and becomes unverified if it remains at 0 after 24 hours.
Truth Factor Formula
corroboration_score = (
0.40 * key_claim_accuracy +
0.30 * source_reputation +
0.20 * corroboration_breadth +
0.10 * verification_speed
)
Self-attestation can add a capped baseline before corroboration lifts the score. Dispute signals such as "false", "hoax", "denied", "misleading", or "debunk" cap the truth factor at 35. Verification labels are likely_true at 78+ with at least two trusted sources, developing at 58+, and uncertain or disputed below that.
OSINT Post Quality Formula
quality = 100 * (
0.30 * discipline +
0.25 * source_tier +
0.20 * information_density +
0.15 * confidence_signaling +
0.10 * coherence
) * redundancy_modifier
Redundancy modifiers are 1.0 for significant new intelligence, 0.8 for partial new detail, 0.6 for essentially redundant information, and 0.4 for pure reposts.
Track Record
OSINT track records are calculated from resolved OSINT posts. The system stores all-time average, last-50 average, resolved count, verified count, false-positive/noise rate, and signal quality. A record is considered establishing until 50 resolved OSINT posts.
Feeds And Filters
Home and public feeds use FeedService. Feed rows include posts, repost shells, and essays. Repost shells inherit the original post score for ranking. Profile tabs separate posts from replies.
QualityFilterService supports floors of Show all, 25+, 50+, 70+, and 85+. The default is 50 unless changed by configuration or a signed-in user's saved preference.
Paywall And Payments
The current paywall policy is eligibility logic, not a complete paid-content platform. Elite writers can mark eligible top-level posts as paywalled when the post is at least 1000 characters. Posts under 1000 characters are always public, and replies cannot be paywalled.
Stripe configuration keys exist for future payment flows. Current writer-cost enforcement is separate: users below the minimum free writer-quality threshold after the configured post count can be required to add a payment method before more AI-scored posting.
Jobs And Background Work
| Job | Command | Purpose |
|---|---|---|
| Comment scoring | php cron/score_comments.php |
Backfills and processes pending AI quality score jobs. |
| OSINT verification | php cron/assess_breaking_news.php |
Queues stale checkpoint jobs and processes pending OSINT verification checks. |
| Anthropic backfill | php cron/backfill_anthropic_scores.php |
Adds missing Anthropic score rows where needed. |
The code supports persistent cron-style processing, but the server scheduler must be verified separately on the host. If cron is not installed, page-load or auto-run behavior may enqueue or run only opportunistically depending on environment flags.
Data And Migrations
Important tables include users, posts, likes, follows, reposts, media, comment_scores, comment_score_jobs, breaking_truth_jobs, breaking_truth_assessments, breaking_manual_sources, osint_track_record_snapshots, and user_settings.
Recent migration themes include the v1.2 workflow tables, username identity merge, OSINT quality and track record support, and feed-visible repost shells.
Testing And Deployment Notes
- Local syntax checks use
php -l. - Automated tests use
php vendor/bin/phpunit. - Remote database behavior is tested with temporary PHP files on the server, then those files are deleted after success.
- SFTP deployment uses the project SFTP configuration. Credentials should never be committed or copied into this wiki.
- Smoke tests should check public pages such as
/,/osint,/what-we-measure,/how-to-write-well, and/wiki/.
Known Open Items
- Confirm whether a persistent server cron is actually installed for OSINT and scoring jobs.
- Complete full Stripe checkout, subscription access, webhooks, and paid-content enforcement if paid content moves beyond eligibility rules.
- Finalize account-reset-evasion policy and any enforcement tooling.
- Decide whether subscription or paywall activity should appear in public user profiles.
- Complete any future Bubble U cleanup or game integration only if the project returns to that scope.
- Keep this wiki synchronized whenever scoring formulas, thresholds, migrations, or account rules change.