bulk commit changes!
This commit is contained in:
36
openspec/specs/admin-maintenance-command-suite/spec.md
Normal file
36
openspec/specs/admin-maintenance-command-suite/spec.md
Normal file
@@ -0,0 +1,36 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for admin-maintenance-command-suite requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Unified admin command surface
|
||||
The system SHALL provide a single admin CLI command family exposing maintenance subcommands.
|
||||
|
||||
#### Scenario: Subcommand discovery
|
||||
- **WHEN** an operator runs the admin command help output
|
||||
- **THEN** available subcommands include refetch-images, clean-archive, clear-cache, clear-news, rebuild-site, regenerate-translations, and fetch
|
||||
|
||||
### Requirement: Fetch command supports configurable article count
|
||||
The admin fetch command SHALL support an operator-provided article count parameter.
|
||||
|
||||
#### Scenario: Fetch with explicit count
|
||||
- **WHEN** an operator invokes fetch with `n=25`
|
||||
- **THEN** the command executes ingestion targeting the requested count
|
||||
- **AND** prints completion summary including processed/stored counts
|
||||
|
||||
### Requirement: Translation regeneration command
|
||||
The system SHALL provide a command to regenerate translations for existing articles.
|
||||
|
||||
#### Scenario: Regenerate translations run
|
||||
- **WHEN** an operator runs regenerate-translations
|
||||
- **THEN** the system attempts translation regeneration for supported languages
|
||||
- **AND** outputs success/failure totals
|
||||
|
||||
### Requirement: Rebuild site command
|
||||
The system SHALL provide a rebuild-site command that executes the defined rebuild workflow.
|
||||
|
||||
#### Scenario: Rebuild execution
|
||||
- **WHEN** an operator runs rebuild-site
|
||||
- **THEN** the system executes the documented rebuild steps in deterministic order
|
||||
- **AND** prints a final success/failure summary
|
||||
26
openspec/specs/article-tldr-summary/spec.md
Normal file
26
openspec/specs/article-tldr-summary/spec.md
Normal file
@@ -0,0 +1,26 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for article-tldr-summary requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: System generates structured TL;DR summary for each fetched article
|
||||
The system SHALL generate a concise summary artifact for each newly fetched article using Perplexity during ingestion.
|
||||
|
||||
#### Scenario: Successful summary generation
|
||||
- **WHEN** a new article is accepted in ingestion
|
||||
- **THEN** the system generates TL;DR bullet points and a concise summary body
|
||||
- **AND** output is persisted in a structured, template-compatible format
|
||||
|
||||
#### Scenario: Summary generation fallback
|
||||
- **WHEN** summary generation fails for an article
|
||||
- **THEN** ingestion continues without failing the entire cycle
|
||||
- **AND** the article remains available with existing non-summary content
|
||||
|
||||
### Requirement: Summary storage includes citation and source context
|
||||
The system SHALL persist source/citation information needed to render summary provenance.
|
||||
|
||||
#### Scenario: Persist source and citation metadata
|
||||
- **WHEN** summary content is stored
|
||||
- **THEN** associated source/citation fields are stored with the article summary artifact
|
||||
- **AND** response payloads can render a "Source and Citation" section
|
||||
31
openspec/specs/article-translations-ml-tm/spec.md
Normal file
31
openspec/specs/article-translations-ml-tm/spec.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for article-translations-ml-tm requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: System generates Tamil and Malayalam translations at article creation time
|
||||
The system SHALL generate Tamil (`ta`) and Malayalam (`ml`) translations for each newly created article during ingestion.
|
||||
|
||||
#### Scenario: Translation generation for new article
|
||||
- **WHEN** a new source article is accepted for storage
|
||||
- **THEN** the system requests Tamil and Malayalam translations for headline and summary
|
||||
- **AND** translation generation occurs in the same ingestion flow for that article
|
||||
|
||||
#### Scenario: Translation failure fallback
|
||||
- **WHEN** translation generation fails for one or both target languages
|
||||
- **THEN** the system stores the base article in English
|
||||
- **AND** marks missing translations as unavailable without failing the whole ingestion cycle
|
||||
|
||||
### Requirement: System stores translation variants linked to the same article
|
||||
The system SHALL persist language-specific translated content as translation items associated with the base article.
|
||||
|
||||
#### Scenario: Persist linked translations
|
||||
- **WHEN** Tamil and Malayalam translations are generated successfully
|
||||
- **THEN** the system stores them as language-specific content variants linked to the base article identifier
|
||||
- **AND** translation records remain queryable by language code
|
||||
|
||||
#### Scenario: No duplicate translation variants per language
|
||||
- **WHEN** translation storage is attempted for an article-language pair that already exists
|
||||
- **THEN** the system avoids creating duplicate translation items for the same language
|
||||
- **AND** preserves one authoritative translation variant per article per language in this phase
|
||||
18
openspec/specs/attribution-disclaimer-page/spec.md
Normal file
18
openspec/specs/attribution-disclaimer-page/spec.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for attribution-disclaimer-page requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Attribution page discloses AI generation and non-ownership
|
||||
The system SHALL provide an Attribution page with explicit statements that content is AI-generated and not personally authored by the site owner.
|
||||
|
||||
#### Scenario: Attribution page title and disclosure content
|
||||
- **WHEN** a user opens the Attribution page
|
||||
- **THEN** the page title clearly indicates attribution/disclaimer purpose
|
||||
- **AND** the body states that content is AI-generated and not generated by the owner as an individual
|
||||
|
||||
#### Scenario: Attribution page includes non-involvement statement
|
||||
- **WHEN** a user reads the Attribution page
|
||||
- **THEN** the page explicitly states owner non-involvement in generated content claims
|
||||
- **AND** wording is presented in primary readable content area
|
||||
47
openspec/specs/containerized-deployment/spec.md
Normal file
47
openspec/specs/containerized-deployment/spec.md
Normal file
@@ -0,0 +1,47 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for containerized-deployment requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Containerized deployment
|
||||
The system SHALL run entirely within Docker containers with all dependencies included.
|
||||
|
||||
#### Scenario: Single container build
|
||||
- **WHEN** building the Docker image
|
||||
- **THEN** the Dockerfile SHALL include Python runtime, Node.js (for Tailwind if needed), and all application code
|
||||
- **AND** expose port 8000 for web traffic
|
||||
|
||||
#### Scenario: Environment configuration
|
||||
- **WHEN** running the container
|
||||
- **THEN** the system SHALL read PERPLEXITY_API_KEY from environment variables
|
||||
- **AND** fail to start if the key is missing or invalid
|
||||
- **AND** support optional configuration for retention days (default: 30)
|
||||
- **AND** support optional IMAGE_QUALITY for image compression (default: 85)
|
||||
- **AND** support optional OPENROUTER_API_KEY for fallback LLM provider
|
||||
- **AND** support optional UMAMI_SCRIPT_URL and UMAMI_WEBSITE_ID for analytics
|
||||
|
||||
#### Scenario: Data persistence
|
||||
- **WHEN** the container restarts
|
||||
- **THEN** the SQLite database SHALL persist via Docker volume mount
|
||||
- **AND** news data SHALL remain intact across restarts
|
||||
|
||||
### Requirement: Responsive single-page design
|
||||
The system SHALL provide a stunning, responsive one-page website with ClawFort branding.
|
||||
|
||||
#### Scenario: Brand consistency
|
||||
- **WHEN** viewing the website
|
||||
- **THEN** the design SHALL feature ClawFort branding (logo, colors, typography)
|
||||
- **AND** maintain visual consistency across all sections
|
||||
|
||||
#### Scenario: Responsive layout
|
||||
- **WHEN** viewing on mobile, tablet, or desktop
|
||||
- **THEN** the layout SHALL adapt appropriately
|
||||
- **AND** the hero block SHALL resize proportionally
|
||||
- **AND** the news feed SHALL use appropriate column layouts
|
||||
|
||||
#### Scenario: Performance
|
||||
- **WHEN** loading the page
|
||||
- **THEN** initial page load SHALL complete within 2 seconds
|
||||
- **AND** images SHALL lazy load outside viewport
|
||||
- **AND** JavaScript bundle SHALL be under 100KB gzipped
|
||||
@@ -0,0 +1,27 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for context-aware-image-selection-recovery requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Context-aware image query generation
|
||||
Image refetch SHALL construct provider queries from article context including keywords and mood/sentiment cues.
|
||||
|
||||
#### Scenario: Context-enriched query
|
||||
- **WHEN** a queued article is processed for image refetch
|
||||
- **THEN** the system derives query terms from article headline/summary content
|
||||
- **AND** includes mood/sentiment-informed cues to improve relevance
|
||||
|
||||
### Requirement: AI-domain fallback keywords
|
||||
When context extraction is insufficient, the system SHALL use AI-domain fallback keywords.
|
||||
|
||||
#### Scenario: Empty or weak context extraction
|
||||
- **WHEN** extracted context terms are empty or below quality threshold
|
||||
- **THEN** the system applies fallback terms such as `ai`, `machine learning`, `deep learning`
|
||||
|
||||
### Requirement: Generic AI fallback image on terminal failure
|
||||
If no usable provider image is returned, the system SHALL assign a generic AI fallback image.
|
||||
|
||||
#### Scenario: Provider chain exhaustion
|
||||
- **WHEN** all provider attempts fail or return unusable images
|
||||
- **THEN** the system stores a generic AI fallback image for the article
|
||||
18
openspec/specs/cookie-consent-tracking-gate/spec.md
Normal file
18
openspec/specs/cookie-consent-tracking-gate/spec.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for cookie-consent-tracking-gate requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Consent banner captures and persists tracking consent
|
||||
The system SHALL display a cookie consent banner and persist user consent decision in cookies before enabling analytics tracking.
|
||||
|
||||
#### Scenario: Consent capture and persistence
|
||||
- **WHEN** a user interacts with the consent banner and accepts
|
||||
- **THEN** consent state is stored in a cookie
|
||||
- **AND** stored consent is honored on subsequent visits
|
||||
|
||||
#### Scenario: Tracking gated by consent
|
||||
- **WHEN** consent has not been granted
|
||||
- **THEN** analytics/tracking scripts and events do not execute
|
||||
- **AND** tracking begins only after consent state indicates acceptance
|
||||
39
openspec/specs/delivery-and-rendering-performance/spec.md
Normal file
39
openspec/specs/delivery-and-rendering-performance/spec.md
Normal file
@@ -0,0 +1,39 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for delivery-and-rendering-performance requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: HTTP delivery applies compression and cache policy
|
||||
The system SHALL apply transport-level compression and explicit cache directives for static assets, API responses, and public HTML routes.
|
||||
|
||||
#### Scenario: Compressed responses are available for eligible payloads
|
||||
- **WHEN** a client requests compressible content that exceeds the compression threshold
|
||||
- **THEN** the response is served with gzip compression
|
||||
- **AND** response headers advertise the selected content encoding
|
||||
|
||||
#### Scenario: Route classes receive deterministic cache-control directives
|
||||
- **WHEN** clients request static assets, API responses, or HTML page routes
|
||||
- **THEN** each route class returns a cache policy aligned to its freshness requirements
|
||||
- **AND** cache directives are explicit and testable from response headers
|
||||
|
||||
### Requirement: Media rendering optimizes perceived loading performance
|
||||
The system SHALL lazy-load non-critical images and render shimmer placeholders until image load completion or fallback resolution.
|
||||
|
||||
#### Scenario: Feed and modal images lazy-load with placeholders
|
||||
- **WHEN** feed or modal images have not completed loading
|
||||
- **THEN** a shimmer placeholder is visible for the pending image region
|
||||
- **AND** the placeholder is removed after load or fallback error handling completes
|
||||
|
||||
#### Scenario: Image rendering reduces layout shift risk
|
||||
- **WHEN** article images are rendered in hero, feed, or modal contexts
|
||||
- **THEN** image elements include explicit dimensions and async decoding hints
|
||||
- **AND** layout remains stable while content loads
|
||||
|
||||
### Requirement: Smooth scrolling behavior is consistently enabled
|
||||
The system SHALL provide smooth scrolling behavior for in-page navigation and user-initiated scroll interactions.
|
||||
|
||||
#### Scenario: In-page navigation uses smooth scrolling
|
||||
- **WHEN** users navigate to in-page anchors or equivalent interactions
|
||||
- **THEN** scrolling transitions occur smoothly rather than jumping abruptly
|
||||
- **AND** behavior is consistent across supported breakpoints
|
||||
31
openspec/specs/fetch-run-reporting/spec.md
Normal file
31
openspec/specs/fetch-run-reporting/spec.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for fetch-run-reporting requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Command reports run outcome to operator
|
||||
The system SHALL present operator-facing output that describes whether the forced run succeeded or failed.
|
||||
|
||||
#### Scenario: Successful run reporting
|
||||
- **WHEN** a forced fetch command completes without fatal errors
|
||||
- **THEN** the command output includes a success indication
|
||||
- **AND** includes the number of items stored in that run
|
||||
|
||||
#### Scenario: Failed run reporting
|
||||
- **WHEN** a forced fetch command encounters a fatal execution error
|
||||
- **THEN** the command output includes a failure indication
|
||||
- **AND** includes actionable error details for operator diagnosis
|
||||
|
||||
### Requirement: Command exposes automation-friendly exit semantics
|
||||
The system SHALL return deterministic process exit codes for command success and failure.
|
||||
|
||||
#### Scenario: Exit code on success
|
||||
- **WHEN** the force-fetch command execution completes successfully
|
||||
- **THEN** the process exits with code 0
|
||||
- **AND** automation tooling can treat the run as successful
|
||||
|
||||
#### Scenario: Exit code on fatal failure
|
||||
- **WHEN** the force-fetch command execution fails fatally
|
||||
- **THEN** the process exits with a non-zero code
|
||||
- **AND** automation tooling can detect the failure state
|
||||
18
openspec/specs/footer-policy-links/spec.md
Normal file
18
openspec/specs/footer-policy-links/spec.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for footer-policy-links requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Footer exposes policy navigation links
|
||||
The system SHALL display footer links for Terms of Use and Attribution on the landing page.
|
||||
|
||||
#### Scenario: Footer links visible on landing page
|
||||
- **WHEN** a user loads the main page
|
||||
- **THEN** the footer includes links labeled "Terms of Use" and "Attribution"
|
||||
- **AND** links are visually distinguishable and keyboard focusable
|
||||
|
||||
#### Scenario: Footer links navigate correctly
|
||||
- **WHEN** a user activates either policy link
|
||||
- **THEN** the browser navigates to the corresponding policy page
|
||||
- **AND** navigation succeeds without API dependency
|
||||
31
openspec/specs/force-fetch-command/spec.md
Normal file
31
openspec/specs/force-fetch-command/spec.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for force-fetch-command requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Operator can trigger immediate news fetch via Python command
|
||||
The system SHALL provide a Python command that triggers one immediate news aggregation run outside of the hourly scheduler.
|
||||
|
||||
#### Scenario: Successful forced fetch invocation
|
||||
- **WHEN** an operator runs the documented force-fetch command with valid runtime configuration
|
||||
- **THEN** the system executes one full fetch cycle using the existing aggregation pipeline
|
||||
- **AND** the command terminates after the run completes
|
||||
|
||||
#### Scenario: Command does not reconfigure scheduler
|
||||
- **WHEN** an operator runs the force-fetch command while the service scheduler exists
|
||||
- **THEN** the command performs a one-off run only
|
||||
- **AND** scheduler job definitions and cadence remain unchanged
|
||||
|
||||
### Requirement: Forced fetch reuses existing aggregation behavior
|
||||
The system SHALL use the same retry, fallback, deduplication, image processing, and persistence logic as scheduled fetch runs.
|
||||
|
||||
#### Scenario: Retry and fallback parity
|
||||
- **WHEN** the primary news provider request fails during a forced run
|
||||
- **THEN** the system applies the configured retry behavior
|
||||
- **AND** uses the configured fallback provider path if available
|
||||
|
||||
#### Scenario: Deduplication parity
|
||||
- **WHEN** fetched headlines match existing duplicate rules
|
||||
- **THEN** duplicate items are skipped according to existing deduplication policy
|
||||
- **AND** only eligible items are persisted
|
||||
57
openspec/specs/hero-display/spec.md
Normal file
57
openspec/specs/hero-display/spec.md
Normal file
@@ -0,0 +1,57 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for hero-display requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Hero block display
|
||||
The system SHALL display the most recent news item as a featured hero block with full attribution.
|
||||
|
||||
#### Scenario: Hero rendering
|
||||
- **WHEN** the page loads
|
||||
- **THEN** the hero block SHALL display the latest news headline, summary, and featured image
|
||||
- **AND** show source attribution (e.g., "Via: TechCrunch")
|
||||
- **AND** show image credit (e.g., "Image: DALL-E")
|
||||
|
||||
#### Scenario: Hero update
|
||||
- **WHEN** new news is fetched hourly
|
||||
- **THEN** the hero block SHALL automatically update to show the newest item
|
||||
- **AND** the previous hero item SHALL move to the news feed
|
||||
|
||||
### Requirement: Infinite scroll news feed
|
||||
The system SHALL display news items in reverse chronological order with infinite scroll pagination.
|
||||
|
||||
#### Scenario: Initial load
|
||||
- **WHEN** the page first loads
|
||||
- **THEN** the system SHALL display the 10 most recent non-archived news items
|
||||
- **AND** exclude the hero item from the feed
|
||||
|
||||
#### Scenario: Infinite scroll
|
||||
- **WHEN** the user scrolls to the bottom of the feed
|
||||
- **THEN** the system SHALL fetch the next 10 news items via API
|
||||
- **AND** append them to the feed without page reload
|
||||
- **AND** show a loading indicator during fetch
|
||||
|
||||
#### Scenario: End of feed
|
||||
- **WHEN** all non-archived news items have been loaded
|
||||
- **THEN** the system SHALL display "No more news" message
|
||||
- **AND** disable further scroll triggers
|
||||
|
||||
### Requirement: News attribution display
|
||||
The system SHALL clearly attribute all news content and images to their sources.
|
||||
|
||||
#### Scenario: Source attribution
|
||||
- **WHEN** displaying any news item
|
||||
- **THEN** the system SHALL show the original source name and link
|
||||
- **AND** display image credit if available
|
||||
|
||||
#### Scenario: Perplexity attribution
|
||||
- **WHEN** displaying aggregated content
|
||||
- **THEN** the system SHALL include "Powered by Perplexity" in the footer
|
||||
|
||||
#### Scenario: Analytics tracking
|
||||
- **WHEN** Umami analytics is configured via `UMAMI_SCRIPT_URL` and `UMAMI_WEBSITE_ID`
|
||||
- **THEN** the system SHALL inject Umami tracking script into page head
|
||||
- **AND** track page view events on initial load
|
||||
- **AND** track scroll depth events (25%, 50%, 75%, 100%)
|
||||
- **AND** track CTA click events (news item clicks, source link clicks)
|
||||
31
openspec/specs/hero-summary-entry-and-readability/spec.md
Normal file
31
openspec/specs/hero-summary-entry-and-readability/spec.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for hero-summary-entry-and-readability requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Hero primary action opens in-site TL;DR summary
|
||||
The homepage hero primary CTA SHALL open the in-site summary modal for the hero article instead of navigating off-site.
|
||||
|
||||
#### Scenario: Hero CTA opens summary modal
|
||||
- **WHEN** a user clicks the hero primary CTA
|
||||
- **THEN** the system opens the summary modal for the current hero article
|
||||
- **AND** no external navigation is triggered by that CTA
|
||||
|
||||
### Requirement: Hero source link remains available as secondary action
|
||||
The hero section SHALL keep an explicit secondary source-link action for external navigation.
|
||||
|
||||
#### Scenario: Source link navigates externally
|
||||
- **WHEN** a user clicks the hero source link
|
||||
- **THEN** the system opens the article source URL in a new tab
|
||||
|
||||
### Requirement: Hero metadata readability over images
|
||||
Hero metadata (`LATEST`, relative time, headline, and summary) SHALL remain visually legible across bright and dark images on desktop and mobile.
|
||||
|
||||
#### Scenario: Bright image background
|
||||
- **WHEN** the hero image contains bright regions under metadata text
|
||||
- **THEN** overlay and text styles preserve readable contrast for metadata and headline blocks
|
||||
|
||||
#### Scenario: Mobile viewport readability
|
||||
- **WHEN** the hero renders on a mobile viewport
|
||||
- **THEN** metadata and title remain readable without overlapping controls or clipping
|
||||
63
openspec/specs/image-provider-fallback-chain/spec.md
Normal file
63
openspec/specs/image-provider-fallback-chain/spec.md
Normal file
@@ -0,0 +1,63 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for image-provider-fallback-chain requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Configurable provider priority
|
||||
The system SHALL support configuring image provider order via `ROYALTY_IMAGE_PROVIDERS` environment variable.
|
||||
|
||||
#### Scenario: Custom provider order
|
||||
- **WHEN** `ROYALTY_IMAGE_PROVIDERS=unsplash,pexels,pixabay,wikimedia,picsum`
|
||||
- **THEN** system tries providers in order: Unsplash → Pexels → Pixabay → Wikimedia → Picsum
|
||||
|
||||
#### Scenario: Default provider order
|
||||
- **WHEN** `ROYALTY_IMAGE_PROVIDERS` is not set or empty
|
||||
- **THEN** system uses default order: `pixabay,unsplash,pexels,wikimedia,picsum`
|
||||
|
||||
#### Scenario: Single provider configured
|
||||
- **WHEN** `ROYALTY_IMAGE_PROVIDERS=pexels`
|
||||
- **THEN** system only tries Pexels provider
|
||||
- **AND** returns `(None, None)` if Pexels fails or is not configured
|
||||
|
||||
### Requirement: Sequential fallback execution
|
||||
The system SHALL try providers sequentially until one returns a valid image.
|
||||
|
||||
#### Scenario: First provider succeeds
|
||||
- **WHEN** provider chain is `pixabay,unsplash,pexels` AND Pixabay returns valid image
|
||||
- **THEN** system returns Pixabay image immediately
|
||||
- **AND** does NOT call Unsplash or Pexels APIs
|
||||
|
||||
#### Scenario: First provider fails, second succeeds
|
||||
- **WHEN** provider chain is `pixabay,unsplash,pexels` AND Pixabay returns no results AND Unsplash returns valid image
|
||||
- **THEN** system returns Unsplash image
|
||||
- **AND** does NOT call Pexels API
|
||||
|
||||
#### Scenario: All providers fail
|
||||
- **WHEN** all configured providers return `(None, None)`
|
||||
- **THEN** system returns `(None, None)` as final result
|
||||
- **AND** caller handles fallback to article image or placeholder
|
||||
|
||||
### Requirement: MCP endpoint override
|
||||
The existing `ROYALTY_IMAGE_MCP_ENDPOINT` SHALL take priority over the provider chain when configured.
|
||||
|
||||
#### Scenario: MCP endpoint configured
|
||||
- **WHEN** `ROYALTY_IMAGE_MCP_ENDPOINT` is set to valid URL
|
||||
- **THEN** system tries MCP endpoint first before provider chain
|
||||
- **AND** falls back to provider chain only if MCP endpoint fails
|
||||
|
||||
#### Scenario: MCP endpoint not configured
|
||||
- **WHEN** `ROYALTY_IMAGE_MCP_ENDPOINT` is empty or unset
|
||||
- **THEN** system skips MCP endpoint and proceeds directly to provider chain
|
||||
|
||||
### Requirement: Provider skip on missing credentials
|
||||
Providers without required API keys SHALL be skipped silently.
|
||||
|
||||
#### Scenario: Skip unconfigured provider
|
||||
- **WHEN** provider chain includes `pixabay` AND `PIXABAY_API_KEY` is not set
|
||||
- **THEN** Pixabay is skipped without error
|
||||
- **AND** chain continues to next provider
|
||||
|
||||
#### Scenario: All providers skipped
|
||||
- **WHEN** no providers in chain have valid API keys configured
|
||||
- **THEN** system falls back to Wikimedia (no key required) or Picsum (always available)
|
||||
75
openspec/specs/image-query-refinement/spec.md
Normal file
75
openspec/specs/image-query-refinement/spec.md
Normal file
@@ -0,0 +1,75 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for image-query-refinement requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Keyword extraction from headline
|
||||
The system SHALL extract relevant keywords from article headlines for image search.
|
||||
|
||||
#### Scenario: Extract keywords from standard headline
|
||||
- **WHEN** headline is "OpenAI Announces GPT-5 with Revolutionary Reasoning Capabilities"
|
||||
- **THEN** extracted query is "OpenAI GPT-5 Revolutionary Reasoning"
|
||||
- **AND** stop words like "Announces", "with", "Capabilities" are removed
|
||||
|
||||
#### Scenario: Handle short headline
|
||||
- **WHEN** headline is "AI Breakthrough"
|
||||
- **THEN** extracted query is "AI Breakthrough"
|
||||
- **AND** no keywords are removed (headline too short)
|
||||
|
||||
#### Scenario: Handle headline with special characters
|
||||
- **WHEN** headline is "Tesla's Self-Driving AI: 99.9% Accuracy Achieved!"
|
||||
- **THEN** extracted query is "Tesla Self-Driving AI Accuracy"
|
||||
- **AND** special characters like apostrophes, colons, and punctuation are normalized
|
||||
|
||||
### Requirement: Stop word removal
|
||||
The system SHALL remove common English stop words from search queries.
|
||||
|
||||
#### Scenario: Remove articles and prepositions
|
||||
- **WHEN** headline is "The Future of AI in the Healthcare Industry"
|
||||
- **THEN** extracted query is "Future AI Healthcare Industry"
|
||||
- **AND** "The", "of", "in", "the" are removed
|
||||
|
||||
#### Scenario: Preserve technical terms
|
||||
- **WHEN** headline is "How Machine Learning Models Learn from Data"
|
||||
- **THEN** extracted query is "Machine Learning Models Learn Data"
|
||||
- **AND** technical terms "Machine", "Learning", "Models" are preserved
|
||||
|
||||
### Requirement: Query length limit
|
||||
The system SHALL limit search query length to optimize API results.
|
||||
|
||||
#### Scenario: Truncate long query
|
||||
- **WHEN** extracted keywords exceed 10 words
|
||||
- **THEN** query is limited to first 5 most significant keywords
|
||||
- **AND** remaining keywords are dropped
|
||||
|
||||
#### Scenario: Preserve short query
|
||||
- **WHEN** extracted keywords are 5 words or fewer
|
||||
- **THEN** all keywords are included in query
|
||||
- **AND** no truncation occurs
|
||||
|
||||
### Requirement: URL-safe query encoding
|
||||
The system SHALL URL-encode queries before sending to provider APIs.
|
||||
|
||||
#### Scenario: Encode spaces and special characters
|
||||
- **WHEN** query is "AI Machine Learning"
|
||||
- **THEN** encoded query is "AI+Machine+Learning" or "AI%20Machine%20Learning"
|
||||
- **AND** query is safe for HTTP GET parameters
|
||||
|
||||
#### Scenario: Handle Unicode characters
|
||||
- **WHEN** query contains Unicode like "AI für Deutschland"
|
||||
- **THEN** Unicode characters are properly percent-encoded
|
||||
- **AND** API request succeeds without encoding errors
|
||||
|
||||
### Requirement: Empty query handling
|
||||
The system SHALL handle edge cases where no keywords can be extracted.
|
||||
|
||||
#### Scenario: Headline with only stop words
|
||||
- **WHEN** headline is "The and a or but"
|
||||
- **THEN** system uses fallback query "news technology"
|
||||
- **AND** image search proceeds with generic query
|
||||
|
||||
#### Scenario: Empty headline
|
||||
- **WHEN** headline is empty string or whitespace only
|
||||
- **THEN** system uses fallback query "news technology"
|
||||
- **AND** image search proceeds with generic query
|
||||
31
openspec/specs/language-aware-content-delivery/spec.md
Normal file
31
openspec/specs/language-aware-content-delivery/spec.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for language-aware-content-delivery requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: API supports language-aware content retrieval
|
||||
The system SHALL support language-aware content delivery for hero and feed reads using selected language input.
|
||||
|
||||
#### Scenario: Language-specific latest article response
|
||||
- **WHEN** a client requests latest article data with a supported language selection
|
||||
- **THEN** the system returns headline and summary in the selected language when available
|
||||
- **AND** includes the corresponding base article metadata and media attribution
|
||||
|
||||
#### Scenario: Language-specific paginated feed response
|
||||
- **WHEN** a client requests paginated feed data with a supported language selection
|
||||
- **THEN** the system returns each feed item's headline and summary in the selected language when available
|
||||
- **AND** preserves existing pagination behavior and ordering semantics
|
||||
|
||||
### Requirement: Language fallback to English is deterministic
|
||||
The system SHALL return English source content when the requested translation is unavailable.
|
||||
|
||||
#### Scenario: Missing translation fallback
|
||||
- **WHEN** a client requests Tamil or Malayalam content for an article lacking that translation
|
||||
- **THEN** the system returns the English headline and summary for that article
|
||||
- **AND** response shape remains consistent with language-aware responses
|
||||
|
||||
#### Scenario: Unsupported language handling
|
||||
- **WHEN** a client requests a language outside supported values (`en`, `ta`, `ml`)
|
||||
- **THEN** the system applies the defined default language behavior for this phase
|
||||
- **AND** avoids breaking existing consumers of news endpoints
|
||||
31
openspec/specs/language-preference-persistence/spec.md
Normal file
31
openspec/specs/language-preference-persistence/spec.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for language-preference-persistence requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Landing page provides language selector
|
||||
The system SHALL display a language selector on the landing page that allows switching between English, Tamil, and Malayalam content views.
|
||||
|
||||
#### Scenario: User selects language from landing page
|
||||
- **WHEN** a user chooses Tamil or Malayalam from the language selector
|
||||
- **THEN** hero and feed content update to requested language-aware rendering
|
||||
- **AND** subsequent API requests use the selected language context
|
||||
|
||||
#### Scenario: User switches back to English
|
||||
- **WHEN** a user selects English in the language selector
|
||||
- **THEN** content renders in English
|
||||
- **AND** language state updates immediately in the frontend view
|
||||
|
||||
### Requirement: User language preference is persisted and restored
|
||||
The system SHALL persist selected language preference in client-side storage and restore it for returning users.
|
||||
|
||||
#### Scenario: Persist language selection
|
||||
- **WHEN** a user selects a supported language on the landing page
|
||||
- **THEN** the selected language code is stored in local storage or a client cookie
|
||||
- **AND** the persisted value is used as preferred language for future visits on the same browser
|
||||
|
||||
#### Scenario: Restore preference on return visit
|
||||
- **WHEN** a returning user opens the landing page
|
||||
- **THEN** the system reads persisted language preference from client storage
|
||||
- **AND** initializes the UI and content requests with that language by default
|
||||
26
openspec/specs/manual-fetch-recovery/spec.md
Normal file
26
openspec/specs/manual-fetch-recovery/spec.md
Normal file
@@ -0,0 +1,26 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for manual-fetch-recovery requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Manual command supports bootstrap and recovery workflows
|
||||
The system SHALL allow operators to run the forced fetch command during first-time setup and after failed scheduled cycles.
|
||||
|
||||
#### Scenario: Bootstrap content population
|
||||
- **WHEN** the system is newly deployed and contains no current news items
|
||||
- **THEN** an operator can run the force-fetch command immediately
|
||||
- **AND** the command attempts to populate the dataset without waiting for the next hourly schedule
|
||||
|
||||
#### Scenario: Recovery after failed scheduled fetch
|
||||
- **WHEN** a prior scheduled fetch cycle failed or produced incomplete results
|
||||
- **THEN** an operator can run the force-fetch command on demand
|
||||
- **AND** the system performs a fresh one-off fetch attempt
|
||||
|
||||
### Requirement: Repeated manual runs remain operationally safe
|
||||
The system SHALL support repeated operator-triggered runs without corrupting data integrity.
|
||||
|
||||
#### Scenario: Repeated invocation in same day
|
||||
- **WHEN** an operator runs the force-fetch command multiple times within the same day
|
||||
- **THEN** existing deduplication behavior prevents duplicate persistence for matching items
|
||||
- **AND** each command run completes with explicit run status output
|
||||
83
openspec/specs/mcp-image-provider-integration/spec.md
Normal file
83
openspec/specs/mcp-image-provider-integration/spec.md
Normal file
@@ -0,0 +1,83 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for mcp-image-provider-integration requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Pixabay image retrieval
|
||||
The system SHALL support retrieving images from Pixabay API when `PIXABAY_API_KEY` is configured.
|
||||
|
||||
#### Scenario: Successful Pixabay image search
|
||||
- **WHEN** Pixabay is enabled in provider chain AND query is "artificial intelligence breakthrough"
|
||||
- **THEN** system sends GET request to `https://pixabay.com/api/?key={key}&q=artificial+intelligence+breakthrough&image_type=photo&per_page=3&safesearch=true`
|
||||
- **AND** returns first hit's `webformatURL` as image URL
|
||||
- **AND** returns credit as `"Photo by {user} on Pixabay"`
|
||||
|
||||
#### Scenario: Pixabay returns no results
|
||||
- **WHEN** Pixabay search returns empty `hits` array
|
||||
- **THEN** system returns `(None, None)` for this provider
|
||||
- **AND** fallback chain continues to next provider
|
||||
|
||||
#### Scenario: Pixabay API key not configured
|
||||
- **WHEN** `PIXABAY_API_KEY` environment variable is empty or unset
|
||||
- **THEN** Pixabay provider is skipped in the fallback chain
|
||||
|
||||
### Requirement: Unsplash image retrieval
|
||||
The system SHALL support retrieving images from Unsplash API when `UNSPLASH_ACCESS_KEY` is configured.
|
||||
|
||||
#### Scenario: Successful Unsplash image search
|
||||
- **WHEN** Unsplash is enabled in provider chain AND query is "machine learning robot"
|
||||
- **THEN** system sends GET request to `https://api.unsplash.com/search/photos?query=machine+learning+robot&per_page=3` with header `Authorization: Client-ID {key}`
|
||||
- **AND** returns first result's `urls.regular` as image URL
|
||||
- **AND** returns credit as `"Photo by {user.name} on Unsplash"`
|
||||
|
||||
#### Scenario: Unsplash returns no results
|
||||
- **WHEN** Unsplash search returns empty `results` array
|
||||
- **THEN** system returns `(None, None)` for this provider
|
||||
- **AND** fallback chain continues to next provider
|
||||
|
||||
#### Scenario: Unsplash API key not configured
|
||||
- **WHEN** `UNSPLASH_ACCESS_KEY` environment variable is empty or unset
|
||||
- **THEN** Unsplash provider is skipped in the fallback chain
|
||||
|
||||
### Requirement: Pexels image retrieval
|
||||
The system SHALL support retrieving images from Pexels API when `PEXELS_API_KEY` is configured.
|
||||
|
||||
#### Scenario: Successful Pexels image search
|
||||
- **WHEN** Pexels is enabled in provider chain AND query is "tech startup office"
|
||||
- **THEN** system sends GET request to `https://api.pexels.com/v1/search?query=tech+startup+office&per_page=3` with header `Authorization: {key}`
|
||||
- **AND** returns first photo's `src.large` as image URL
|
||||
- **AND** returns credit as `"Photo by {photographer} on Pexels"`
|
||||
|
||||
#### Scenario: Pexels returns no results
|
||||
- **WHEN** Pexels search returns empty `photos` array
|
||||
- **THEN** system returns `(None, None)` for this provider
|
||||
- **AND** fallback chain continues to next provider
|
||||
|
||||
#### Scenario: Pexels API key not configured
|
||||
- **WHEN** `PEXELS_API_KEY` environment variable is empty or unset
|
||||
- **THEN** Pexels provider is skipped in the fallback chain
|
||||
|
||||
### Requirement: Provider timeout handling
|
||||
Each provider API call SHALL timeout after 15 seconds.
|
||||
|
||||
#### Scenario: Provider request timeout
|
||||
- **WHEN** provider API does not respond within 15 seconds
|
||||
- **THEN** system logs timeout warning
|
||||
- **AND** returns `(None, None)` for this provider
|
||||
- **AND** fallback chain continues to next provider
|
||||
|
||||
### Requirement: Provider error handling
|
||||
The system SHALL gracefully handle provider API errors without crashing.
|
||||
|
||||
#### Scenario: Provider returns HTTP error
|
||||
- **WHEN** provider API returns 4xx or 5xx status code
|
||||
- **THEN** system logs error with status code
|
||||
- **AND** returns `(None, None)` for this provider
|
||||
- **AND** fallback chain continues to next provider
|
||||
|
||||
#### Scenario: Provider returns malformed response
|
||||
- **WHEN** provider API returns invalid JSON or unexpected schema
|
||||
- **THEN** system logs parsing error
|
||||
- **AND** returns `(None, None)` for this provider
|
||||
- **AND** fallback chain continues to next provider
|
||||
37
openspec/specs/modal-layout-and-loading-feedback/spec.md
Normal file
37
openspec/specs/modal-layout-and-loading-feedback/spec.md
Normal file
@@ -0,0 +1,37 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for modal-layout-and-loading-feedback requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Modal width supports comfortable desktop reading
|
||||
The summary modal SHALL render with a desktop width that is approximately half of viewport width or larger when space allows, while remaining responsive on small screens.
|
||||
|
||||
#### Scenario: Desktop width expansion
|
||||
- **WHEN** the modal opens on desktop viewport widths
|
||||
- **THEN** the modal content area renders wider than the previous narrow baseline
|
||||
- **AND** text blocks are readable without excessive line wrapping
|
||||
|
||||
#### Scenario: Mobile responsiveness
|
||||
- **WHEN** the modal opens on small mobile viewport widths
|
||||
- **THEN** modal width remains fully usable without horizontal overflow
|
||||
|
||||
### Requirement: Modal height supports near-full viewport scrolling
|
||||
The summary modal SHALL use near full-height viewport behavior when content overflows.
|
||||
|
||||
#### Scenario: Overflowing summary content
|
||||
- **WHEN** summary content exceeds modal viewport height
|
||||
- **THEN** modal body remains scrollable with close controls accessible
|
||||
- **AND** modal container uses near full viewport height constraints
|
||||
|
||||
### Requirement: TL;DR loading placeholder is explicit
|
||||
The modal SHALL show a horizontal shimmer placeholder for TL;DR content while TL;DR bullets are not yet available.
|
||||
|
||||
#### Scenario: TL;DR pending state
|
||||
- **WHEN** the summary modal is open and TL;DR bullet data is pending
|
||||
- **THEN** the system displays a low-height horizontal shimmer placeholder
|
||||
|
||||
#### Scenario: TL;DR loaded state
|
||||
- **WHEN** TL;DR bullet data becomes available
|
||||
- **THEN** shimmer placeholder is removed
|
||||
- **AND** TL;DR bullet list is rendered
|
||||
58
openspec/specs/news-aggregator/spec.md
Normal file
58
openspec/specs/news-aggregator/spec.md
Normal file
@@ -0,0 +1,58 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for news-aggregator requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: News aggregation via Perplexity API
|
||||
The system SHALL fetch AI news hourly from Perplexity API and store it with full attribution.
|
||||
|
||||
#### Scenario: Hourly news fetch
|
||||
- **WHEN** the scheduled job runs every hour
|
||||
- **THEN** the system calls Perplexity API with query "latest AI news"
|
||||
- **AND** stores the response with headline, summary, source URL, and timestamp
|
||||
|
||||
#### Scenario: API error handling
|
||||
- **WHEN** Perplexity API returns an error or timeout
|
||||
- **THEN** the system logs the error with cost tracking
|
||||
- **AND** retries with exponential backoff up to 3 times
|
||||
- **AND** falls back to OpenRouter API if `OPENROUTER_API_KEY` is configured
|
||||
- **AND** continues using cached content if all retries and fallback fail
|
||||
|
||||
### Requirement: Featured image generation
|
||||
The system SHALL generate or fetch a relevant featured image for each news item.
|
||||
|
||||
#### Scenario: Image acquisition
|
||||
- **WHEN** a new news item is fetched
|
||||
- **THEN** the system SHALL request a relevant image URL from Perplexity
|
||||
- **AND** download and optimize the image locally using Pillow
|
||||
- **AND** apply quality compression based on `IMAGE_QUALITY` env var (1-100, default 85)
|
||||
- **AND** store the optimized image path and original image credit/source information
|
||||
|
||||
#### Scenario: Image optimization configuration
|
||||
- **WHEN** the system processes an image
|
||||
- **THEN** it SHALL read `IMAGE_QUALITY` from environment (default: 85)
|
||||
- **AND** apply JPEG compression at specified quality level
|
||||
- **AND** resize images exceeding 1200px width while maintaining aspect ratio
|
||||
- **AND** store optimized images in `/app/static/images/` directory
|
||||
|
||||
#### Scenario: Image fallback
|
||||
- **WHEN** image generation fails or returns no result
|
||||
- **THEN** the system SHALL use a default ClawFort branded placeholder image
|
||||
|
||||
### Requirement: News data persistence with retention
|
||||
The system SHALL store news items for exactly 30 days with automatic archiving.
|
||||
|
||||
#### Scenario: News storage
|
||||
- **WHEN** a news item is fetched from Perplexity
|
||||
- **THEN** the system SHALL store it in SQLite with fields: id, headline, summary, source_url, image_url, image_credit, published_at, created_at
|
||||
- **AND** set archived=false by default
|
||||
|
||||
#### Scenario: Automatic archiving
|
||||
- **WHEN** a nightly cleanup job runs
|
||||
- **THEN** the system SHALL mark all news items older than 30 days as archived=true
|
||||
- **AND** delete archived items older than 60 days permanently
|
||||
|
||||
#### Scenario: Duplicate prevention
|
||||
- **WHEN** fetching news that matches an existing headline (within 24 hours)
|
||||
- **THEN** the system SHALL skip insertion to prevent duplicates
|
||||
27
openspec/specs/news-image-relevance-and-fallbacks/spec.md
Normal file
27
openspec/specs/news-image-relevance-and-fallbacks/spec.md
Normal file
@@ -0,0 +1,27 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for news-image-relevance-and-fallbacks requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Image query fallback uses AI-focused defaults
|
||||
When extracted image keywords are insufficient, the system SHALL use AI-focused default fallback terms.
|
||||
|
||||
#### Scenario: Empty keyword extraction
|
||||
- **WHEN** keyword extraction yields no usable topic keywords
|
||||
- **THEN** the system uses default fallback terms including AI-domain keywords (for example `ai`, `machine learning`, `deep learning`)
|
||||
|
||||
### Requirement: Generic AI image fallback is guaranteed
|
||||
If provider lookups fail to return a usable summary image, the system SHALL use a generic AI-themed fallback image.
|
||||
|
||||
#### Scenario: Provider chain failure
|
||||
- **WHEN** all configured image providers return no usable image
|
||||
- **THEN** the system assigns a generic AI fallback image URL/path for summary image
|
||||
|
||||
### Requirement: Fallback behavior remains context-aware first
|
||||
The system SHALL attempt context-aware keyword retrieval before any generic fallback image is selected.
|
||||
|
||||
#### Scenario: Context-aware attempt precedes fallback
|
||||
- **WHEN** summary image selection runs for a news item
|
||||
- **THEN** the system first attempts provider queries from extracted context-aware keywords
|
||||
- **AND** only falls back to generic AI image if these attempts fail
|
||||
31
openspec/specs/news-structured-data/spec.md
Normal file
31
openspec/specs/news-structured-data/spec.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for news-structured-data requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Homepage publishes Newspaper structured data
|
||||
The system SHALL expose a valid JSON-LD entity of type `Newspaper` on the homepage.
|
||||
|
||||
#### Scenario: Newspaper entity is emitted on homepage
|
||||
- **WHEN** the homepage HTML is rendered
|
||||
- **THEN** a JSON-LD script block includes an entity with `@type` set to `Newspaper`
|
||||
- **AND** the entity includes stable publisher and site identity fields
|
||||
|
||||
#### Scenario: Newspaper entity remains language-aware
|
||||
- **WHEN** homepage content is rendered in a selected language
|
||||
- **THEN** the structured data includes language context for the active locale
|
||||
- **AND** language output stays consistent with visible content language
|
||||
|
||||
### Requirement: Each rendered news item publishes NewsArticle structured data
|
||||
The system SHALL expose a valid JSON-LD entity of type `NewsArticle` for each rendered news item in hero and feed contexts.
|
||||
|
||||
#### Scenario: NewsArticle entities include required semantic fields
|
||||
- **WHEN** news items are present on the homepage
|
||||
- **THEN** each `NewsArticle` entity includes headline, description, image, publication dates, and URL fields
|
||||
- **AND** publisher and author context are present for each item
|
||||
|
||||
#### Scenario: Structured data avoids duplicate article entities
|
||||
- **WHEN** article data appears across hero and feed sections
|
||||
- **THEN** structured-data output deduplicates entities for the same article URL
|
||||
- **AND** only one canonical semantic entry remains for each unique article
|
||||
37
openspec/specs/queued-image-refetch-with-backoff/spec.md
Normal file
37
openspec/specs/queued-image-refetch-with-backoff/spec.md
Normal file
@@ -0,0 +1,37 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for queued-image-refetch-with-backoff requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Latest-30 queue construction
|
||||
The refetch-images command SHALL enqueue up to the latest 30 news items for processing.
|
||||
|
||||
#### Scenario: Queue population
|
||||
- **WHEN** refetch-images is started
|
||||
- **THEN** the command loads recent news items
|
||||
- **AND** enqueues at most 30 items ordered from newest to oldest
|
||||
|
||||
### Requirement: Sequential processing
|
||||
The image refetch queue SHALL be processed one item at a time.
|
||||
|
||||
#### Scenario: Single-item worker behavior
|
||||
- **WHEN** queue processing runs
|
||||
- **THEN** only one queued item is processed concurrently
|
||||
- **AND** next item starts only after current item completes/fails
|
||||
|
||||
### Requirement: Exponential backoff on transient failures
|
||||
The queue processor SHALL retry transient image-provider failures using exponential backoff.
|
||||
|
||||
#### Scenario: Rate-limited provider response
|
||||
- **WHEN** provider call returns rate-limit or transient error
|
||||
- **THEN** command retries with exponential delay between attempts
|
||||
- **AND** stops retrying after configured max attempts
|
||||
|
||||
### Requirement: Progress and completion reporting
|
||||
The command SHALL emit operator-readable progress and final summary output.
|
||||
|
||||
#### Scenario: Queue progress output
|
||||
- **WHEN** queue processing is in progress
|
||||
- **THEN** the command prints per-item progress (processed/succeeded/failed)
|
||||
- **AND** prints final totals on completion
|
||||
18
openspec/specs/responsive-device-agnostic-layout/spec.md
Normal file
18
openspec/specs/responsive-device-agnostic-layout/spec.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for responsive-device-agnostic-layout requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Core layout is device-agnostic and responsive
|
||||
The system SHALL render key surfaces (header, hero, feed, modal, footer) responsively across mobile, tablet, and desktop viewports.
|
||||
|
||||
#### Scenario: Mobile layout behavior
|
||||
- **WHEN** a user opens the site on a mobile viewport
|
||||
- **THEN** content remains readable without horizontal overflow
|
||||
- **AND** interactive controls remain reachable and usable
|
||||
|
||||
#### Scenario: Desktop and tablet adaptation
|
||||
- **WHEN** a user opens the site on tablet or desktop viewports
|
||||
- **THEN** layout reflows according to breakpoint design rules
|
||||
- **AND** no key content or controls are clipped
|
||||
26
openspec/specs/royalty-free-image-enrichment/spec.md
Normal file
26
openspec/specs/royalty-free-image-enrichment/spec.md
Normal file
@@ -0,0 +1,26 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for royalty-free-image-enrichment requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: System enriches summaries with appropriate royalty-free images
|
||||
The system SHALL attach an appropriate royalty-free image to each summarized article.
|
||||
|
||||
#### Scenario: Successful royalty-free image retrieval
|
||||
- **WHEN** summary generation succeeds for an article
|
||||
- **THEN** the system retrieves an appropriate royalty-free image for that article context
|
||||
- **AND** stores image URL and attribution metadata for rendering
|
||||
|
||||
#### Scenario: MCP-preferred retrieval path
|
||||
- **WHEN** MCP image integration is available in runtime
|
||||
- **THEN** the system uses MCP-based retrieval as the preferred image sourcing path
|
||||
- **AND** falls back to configured non-MCP royalty-free source path when MCP retrieval fails or is unavailable
|
||||
|
||||
### Requirement: Image retrieval failures do not block article availability
|
||||
The system SHALL remain resilient when image sourcing fails.
|
||||
|
||||
#### Scenario: Image fallback behavior
|
||||
- **WHEN** no suitable royalty-free image can be retrieved
|
||||
- **THEN** the article summary remains available for modal display
|
||||
- **AND** UI uses configured placeholder/fallback image behavior
|
||||
31
openspec/specs/seo-meta-and-social-tags/spec.md
Normal file
31
openspec/specs/seo-meta-and-social-tags/spec.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for seo-meta-and-social-tags requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Core SEO metadata is present on public pages
|
||||
The system SHALL expose standards-compliant SEO metadata on the homepage and policy pages, including description, robots, canonical URL, and social preview metadata.
|
||||
|
||||
#### Scenario: Homepage metadata baseline exists
|
||||
- **WHEN** a crawler or browser loads the homepage
|
||||
- **THEN** the document includes `description`, `robots`, and canonical metadata
|
||||
- **AND** Open Graph and Twitter card metadata fields are present with non-empty values
|
||||
|
||||
#### Scenario: Policy pages include indexable metadata
|
||||
- **WHEN** a crawler loads `/terms` or `/attribution`
|
||||
- **THEN** the page includes page-specific `title` and `description` metadata
|
||||
- **AND** Open Graph and Twitter card metadata are present for link previews
|
||||
|
||||
### Requirement: Canonical and preview metadata remain deterministic
|
||||
The system SHALL keep canonical and preview metadata deterministic for each route to avoid conflicting crawler signals.
|
||||
|
||||
#### Scenario: Canonical URL reflects active route
|
||||
- **WHEN** metadata is rendered for a public route
|
||||
- **THEN** exactly one canonical link is emitted for that route
|
||||
- **AND** canonical metadata does not point to unrelated routes
|
||||
|
||||
#### Scenario: Social preview tags map to current page context
|
||||
- **WHEN** the page metadata is generated or updated
|
||||
- **THEN** `og:title`, `og:description`, and corresponding Twitter fields reflect the current page context
|
||||
- **AND** preview image fields resolve to a valid absolute URL
|
||||
29
openspec/specs/site-admin-safety-and-ergonomics/spec.md
Normal file
29
openspec/specs/site-admin-safety-and-ergonomics/spec.md
Normal file
@@ -0,0 +1,29 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for site-admin-safety-and-ergonomics requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Confirmation guard for destructive commands
|
||||
Destructive admin commands SHALL require explicit confirmation before execution.
|
||||
|
||||
#### Scenario: Missing confirmation flag
|
||||
- **WHEN** an operator runs clear-news or clean-archive without required confirmation
|
||||
- **THEN** the command exits without applying destructive changes
|
||||
- **AND** prints guidance for explicit confirmation usage
|
||||
|
||||
### Requirement: Dry-run support where applicable
|
||||
Maintenance commands SHALL provide dry-run mode for previewing effects where feasible.
|
||||
|
||||
#### Scenario: Dry-run preview
|
||||
- **WHEN** an operator invokes a command with dry-run mode
|
||||
- **THEN** the command reports intended actions and affected counts
|
||||
- **AND** persists no data changes
|
||||
|
||||
### Requirement: Actionable failure summaries
|
||||
Admin commands SHALL output actionable errors and final status summaries.
|
||||
|
||||
#### Scenario: Partial failure reporting
|
||||
- **WHEN** a maintenance command partially fails
|
||||
- **THEN** output includes succeeded/failed counts
|
||||
- **AND** includes actionable next-step guidance
|
||||
26
openspec/specs/summary-analytics-tagging/spec.md
Normal file
26
openspec/specs/summary-analytics-tagging/spec.md
Normal file
@@ -0,0 +1,26 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for summary-analytics-tagging requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Modal interactions are tagged for analytics
|
||||
The system SHALL emit Umami analytics events for summary modal open and close actions.
|
||||
|
||||
#### Scenario: Modal open event tagging
|
||||
- **WHEN** a user opens the summary modal
|
||||
- **THEN** the system emits a modal-open Umami event
|
||||
- **AND** event payload includes article context identifier
|
||||
|
||||
#### Scenario: Modal close event tagging
|
||||
- **WHEN** a user closes the summary modal
|
||||
- **THEN** the system emits a modal-close Umami event
|
||||
- **AND** event payload includes article context identifier when available
|
||||
|
||||
### Requirement: Source link-out interactions are tagged for analytics
|
||||
The system SHALL emit Umami analytics events for source/citation link-outs from summary modal.
|
||||
|
||||
#### Scenario: Source link-out event tagging
|
||||
- **WHEN** a user clicks source/citation link in summary modal
|
||||
- **THEN** the system emits a link-out Umami event before or at navigation trigger
|
||||
- **AND** event includes source URL or source identifier metadata
|
||||
26
openspec/specs/summary-modal-experience/spec.md
Normal file
26
openspec/specs/summary-modal-experience/spec.md
Normal file
@@ -0,0 +1,26 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for summary-modal-experience requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Summary is rendered in a modal dialog using standard template
|
||||
The system SHALL render article summary content in a modal dialog using the required structure.
|
||||
|
||||
#### Scenario: Open summary modal
|
||||
- **WHEN** a user triggers summary view for an article
|
||||
- **THEN** a modal dialog opens and displays content in this order: relevant image, TL;DR bullets, summary body, source and citation, and "Powered by Perplexity"
|
||||
- **AND** modal content corresponds to the selected article
|
||||
|
||||
#### Scenario: Close summary modal
|
||||
- **WHEN** a user closes the modal via close control or backdrop interaction
|
||||
- **THEN** the modal is dismissed cleanly
|
||||
- **AND** user returns to previous feed context without page navigation
|
||||
|
||||
### Requirement: Modal content preserves source link-out behavior
|
||||
The system SHALL provide source link-outs from the summary modal.
|
||||
|
||||
#### Scenario: Source link-out from modal
|
||||
- **WHEN** a user clicks source/citation link in the modal
|
||||
- **THEN** the original source opens in a new tab/window
|
||||
- **AND** modal behavior remains stable for continued browsing
|
||||
18
openspec/specs/terms-of-use-risk-disclosure/spec.md
Normal file
18
openspec/specs/terms-of-use-risk-disclosure/spec.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for terms-of-use-risk-disclosure requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Terms page states unverified-content risk
|
||||
The system SHALL provide a Terms of Use page that states information is unverified and use is at the user’s own risk.
|
||||
|
||||
#### Scenario: Terms page risk statement visible
|
||||
- **WHEN** a user opens the Terms of Use page
|
||||
- **THEN** the page includes clear at-own-risk usage language
|
||||
- **AND** the page states information is not independently verified
|
||||
|
||||
#### Scenario: Terms page references source uncertainty
|
||||
- **WHEN** a user reads terms details
|
||||
- **THEN** the page explains content is surfaced from external/AI-generated sources
|
||||
- **AND** users are informed responsibility remains with their own decisions
|
||||
18
openspec/specs/theme-default-system/spec.md
Normal file
18
openspec/specs/theme-default-system/spec.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for theme-default-system requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: System theme is default when no preference exists
|
||||
The system SHALL default to system theme behavior if no persisted theme preference is found.
|
||||
|
||||
#### Scenario: No saved preference on first visit
|
||||
- **WHEN** a user visits the site with no stored theme value
|
||||
- **THEN** the UI resolves theme from system color-scheme preference
|
||||
- **AND** switcher indicates system mode as active
|
||||
|
||||
#### Scenario: Persisted preference overrides system default
|
||||
- **WHEN** a user has an existing stored theme preference
|
||||
- **THEN** stored preference is applied instead of system mode
|
||||
- **AND** user-selected theme remains stable across reloads
|
||||
18
openspec/specs/theme-preference-persistence/spec.md
Normal file
18
openspec/specs/theme-preference-persistence/spec.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for theme-preference-persistence requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Theme choice persists across sessions
|
||||
The system SHALL persist user-selected theme with localStorage as primary storage and cookie fallback when localStorage is unavailable.
|
||||
|
||||
#### Scenario: Persist theme in localStorage
|
||||
- **WHEN** localStorage is available and user selects a theme
|
||||
- **THEN** selected theme is saved in localStorage
|
||||
- **AND** stored value is used on next visit in same browser
|
||||
|
||||
#### Scenario: Cookie fallback persistence
|
||||
- **WHEN** localStorage is unavailable or blocked
|
||||
- **THEN** selected theme is saved in cookie storage
|
||||
- **AND** cookie value is used to restore theme on return visit
|
||||
18
openspec/specs/theme-switcher-control/spec.md
Normal file
18
openspec/specs/theme-switcher-control/spec.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for theme-switcher-control requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Header provides icon-based theme switcher
|
||||
The system SHALL display a theme switcher in the top-right header area with icon controls for system, light, dark, and high-contrast modes.
|
||||
|
||||
#### Scenario: Theme options visible as icons
|
||||
- **WHEN** a user views the header
|
||||
- **THEN** all four theme options are represented by distinct icons
|
||||
- **AND** each option is keyboard-accessible and screen-reader labeled
|
||||
|
||||
#### Scenario: Theme selection applies immediately
|
||||
- **WHEN** a user selects a theme option
|
||||
- **THEN** the page updates visual theme without full page reload
|
||||
- **AND** selected option has a visible active state
|
||||
18
openspec/specs/wcag-2-2-aa-accessibility/spec.md
Normal file
18
openspec/specs/wcag-2-2-aa-accessibility/spec.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Purpose
|
||||
|
||||
Canonical specification for wcag-2-2-aa-accessibility requirements synced from OpenSpec change deltas.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Core user flows comply with WCAG 2.2 AA baseline
|
||||
The system SHALL meet WCAG 2.2 AA accessibility requirements for primary interactions and content presentation.
|
||||
|
||||
#### Scenario: Keyboard-only interaction flow
|
||||
- **WHEN** a keyboard-only user navigates the page
|
||||
- **THEN** all primary interactive elements are reachable and operable
|
||||
- **AND** visible focus indication is present at each step
|
||||
|
||||
#### Scenario: Contrast and non-text alternatives
|
||||
- **WHEN** users consume text and non-text UI content
|
||||
- **THEN** color contrast meets AA thresholds for relevant text and controls
|
||||
- **AND** meaningful images and controls include accessible labels/alternatives
|
||||
Reference in New Issue
Block a user