- Convert roadmap to YAML: - Add data structure: id, priority, title, goal, tags, milestone - Add `details` field (supports list or block string); populated initial content - Quote scalars and use explicit nulls to avoid YAML parse edge cases - Update `updated` date to 2025-08-22 - Flask blueprint + loader: - New /roadmap view with section switching (roadmap | backlog | open_questions) - Filters: q (search), tag (multi, AND), min_priority, milestone - Dataclasses: RoadmapData/RoadmapItem; include `details` - `_normalize_details()` to accept string or list, normalize to list[str] - Configurable path via `ROADMAP_FILE` (env or defaults) - Remove cache layer for simplicity - UI (Tailwind): - `templates/roadmap.html` with responsive cards, tag chips, and filter form - Details modal (larger max width, scrollable body) showing ID/goal/priority/tags/milestone - Safe JSON payload to modal via `|tojson|forceescape` - JS: - DOM-ready, event-delegated handler for `data-item` buttons - Populate modal fields and render multi-paragraph details - Fixes & polish: - Resolved YAML `ScannerError` by quoting strings with `:` and `#` - Ensured `details` is passed through route to template and included in button payload - Minor styling tweaks for consistency with Tailwind setup Usage: - Set `ROADMAP_FILE` if not using default path - Visit /roadmap and filter via q/tag/min_priority/milestone
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
import os
|
|
import logging
|
|
from pathlib import Path
|
|
from flask import Flask
|
|
|
|
# Local imports
|
|
from .utils.settings import get_settings
|
|
from .logging_setup import wire_logging_once, get_app_logger, get_engine_logger
|
|
|
|
from app.blueprints.ui import bp as main_bp # ui blueprint
|
|
from app.blueprints.api import api_bp as api_bp # api blueprint
|
|
from app.blueprints.roadmap import bp as roadmap_bp # roadmap
|
|
|
|
def create_app() -> Flask:
|
|
"""
|
|
Create and configure the Flask application instance.
|
|
|
|
Returns:
|
|
Flask: The configured Flask app.
|
|
"""
|
|
# Basic app object
|
|
app = Flask(__name__, template_folder="templates", static_folder="static")
|
|
|
|
# logging setup
|
|
wire_logging_once(app)
|
|
|
|
app_logger = get_app_logger()
|
|
|
|
# Load settings (safe fallback to defaults if file missing)
|
|
settings = get_settings()
|
|
|
|
# Secret key loaded from env (warn if missing)
|
|
app.secret_key = os.getenv("SECRET_KEY")
|
|
if not app.secret_key:
|
|
app_logger.warning("[init] SECRET_KEY is not set; sessions may be insecure in production.")
|
|
|
|
# Configure storage directory (bind-mount is still handled by sandbox.sh)
|
|
sandbox_storage_default = Path("/data")
|
|
app.config["SANDBOX_STORAGE"] = str(sandbox_storage_default)
|
|
|
|
# App metadata available to templates
|
|
app.config["APP_NAME"] = settings.app.name
|
|
app.config["APP_VERSION"] = f"v{settings.app.version_major}.{settings.app.version_minor}"
|
|
|
|
# roadmap file
|
|
app.config["ROADMAP_FILE"] = str(Path(app.root_path) / "docs" / "roadmap.yaml")
|
|
|
|
|
|
# Register blueprints
|
|
app.register_blueprint(main_bp)
|
|
app.register_blueprint(api_bp)
|
|
app.register_blueprint(roadmap_bp)
|
|
|
|
app_logger = get_app_logger()
|
|
|
|
# Example log lines so we know we booted cleanly
|
|
app_logger.info(f"SneakyScope started: {app.config['APP_NAME']} {app.config['APP_VERSION']}")
|
|
app_logger.info(f"SANDBOX_STORAGE: {app.config['SANDBOX_STORAGE']}")
|
|
|
|
return app
|