- Add explanation that each agent runs in isolation, preventing accidental cascading triggers
- Clarify that Maestro runs each agent once and caches results for follow-up questions
- Update style agent description to note context-aware application of project rules
- Wrap leaderboard test page/browser context in try/finally to ensure cleanup on failure
Introduce `mark_orchestration_tools`, `set_tool_scope`, and `reset_tool_scope` in `agents/agent.py` to allow runtime filtering of tool payloads by scope and orchestration flag. Refactor `get_tool_payloads` to respect the active scope and exclude orchestration-only tools. Update `agents/core/__init__.py` with `worker_tool_names` helper that returns read/reasoning tools plus conditional write/verify tools per mode, replacing the old `payloads_for` exclusion logic. Modify `agents/maestro.py` to call `mark_orchestration_tools` and wire per-agent result recording via `on_result` callback in `run_fleet`. Extend `agents/orchestrator.py` `run_fleet` signature to accept an optional `on_result` callable and invoke it after each agent run. Revise `agents/style.py` em-dash rule to distinguish prose from data occurrences, and add repository layout guidance to `agents/base.py` MAINT_HEADER.
- Add `agents/reports/` to `.gitignore` to prevent generated agent report files from being tracked
- Implement `_TimestampStream` class and `install_timestamps()` function in `agents/agent.py` for prefixing stdout/stderr with timestamps and elapsed time
- Export `install_timestamps`, `set_write_budget`, `clear_write_budget`, and `set_shell_restricted` from `agents/base.py`; add `_RUN_LOCK`, `AGENT_ICONS` dictionary, and `WRITE_BUDGET = 20` constant
- Add `report_codename()` function and `CODENAME_ADJECTIVES`/`CODENAME_ANIMALS` tuples to `agents/core/__init__.py` for generating random agent report codenames
- Expand `WRITE_TOOLS` tuple in `agents/core/__init__.py` to include `replace_lines`, `insert_lines`, and `delete_lines`; remove `SWARM_TOOLS` from `payloads_for` exclusion list
- Update `CLAUDE.md` and `AGENTS.md` documentation with dataset column initialization rules and new agent infrastructure details
- Reorder route table in `README.md` to list `/uploads` before `/messages` and document Swagger/ReDoc/OpenAPI schema endpoints
The diff adds the mandatory `retoor <retoor@molodetz.nl>` header comment to every `.py` file under `devplacepy/` (including `__init__.py` and `routers/__init__.py`), and updates the `StyleAgent` in `agents/style.py` to instruct agents to only add the header on created or already-edited files rather than sweeping the entire repo. The `agents/base.py` operating protocol is also revised to reorder and clarify tool discipline rules.
- Bump DEFAULT_MAX_ITER from 40 to 60 in agents/base.py for longer agent runs
- Add seed_findings parameter to MaintenanceAgent.task_prompt() enabling targeted fix mode from prior check results
- Extend write_reports() with incomplete flag to track partial completion
- Introduce _LAST_CHECK cache in maestro.py to store check findings for subsequent fix runs
- Modify _dispatch() to pass seed findings to fix mode and include seeded_from_check in response
- Add incomplete field to orchestrator.py fleet results for consistency across agent outputs
Add the `agents/` directory containing a fleet of autonomous AI maintenance agents for codebase consistency, including a shared async engine (`agent.py`), a dependency-free validator (`validator.py`), and specialized agents for security, audit, docs, style, frontend, SEO, test coverage, and more. Wire the fleet into the Makefile with `--fix`/`--check` modes, document the architecture in `AGENTS.md`, `CLAUDE.md`, and `README.md`, and enforce a hard rule that the `agents/` directory itself is off-limits to any code modification to preserve detection data.
The label attribute on the dp-upload component previously defaulted to "Attach files" and always displayed. This change makes the label optional by defaulting to an empty string, hiding the label element when no label is provided, and updating the documentation to reflect the new behavior. The feed template also removes the now-redundant explicit label attribute.
- Replace `100vh` with `100dvh` in messages-layout height and min-height to properly account for mobile browser dynamic toolbar heights, adjusting offset from 2rem to 3.5rem for consistent spacing
- Remove `autofocus` attribute from message input field to prevent automatic keyboard popup on page load
- Remove `footer` block override that was incorrectly suppressing the site footer on messages page
- Change `input.focus()` to `input.focus({ preventScroll: true })` in the scroll-to-bottom script to avoid unwanted page jumps when focusing the input after sending a message
The comment depth multiplier was reduced from 0.25rem to 0.0625rem for main layout, and from 0.1rem to 0.025rem for mobile breakpoints, with corresponding padding-left reductions in .comment-replies from 0.25rem to 0.0625rem and 0.1rem to 0.025rem respectively. This tightens the visual nesting of threaded comments to prevent excessive horizontal drift in deeply nested reply chains.
Adjust margin-left and padding-left values in .comment and .comment-replies
selectors to use smaller multipliers (0.25rem, 0.1rem) instead of previous
larger values (1.5rem, 0.5rem, 0.25rem) for tighter nested comment display.
Add two new chat commands (`/stop` and `/reset`) to the Devii WebSocket handler, enabling users to stop or reset a session via text input. Introduce a new "Bots internals" documentation section with six prose pages covering architecture, personas, content generation, engagement, realism, and configuration for the autonomous bot fleet. Extend the bot service with article scoring, category picking, configurable pause/break timing, and a `gist_min_lines` parameter for LLM client initialization.
Refactor proxy target resolution to connect straight to the container's bridge IP and container port, bypassing the host port-publishing layer entirely. Introduce `container_ip`/`container_gateway` fields captured from Docker inspect on each running instance, stored alongside status updates. Update the fake backend to emit realistic `NetworkSettings` with per-container IPs. Remove the now-unused `CONTAINER_PROXY_HOST` config default and the old `ports_json`-based host port lookup in the proxy router.
Add JavaScript click handler for profile dropdown toggle in MobileNav, replace anchor with button in base template, add explicit profile link to dropdown menu, and apply z-index to nav-badge for proper stacking.
Replace five separate file-extension patterns for devplacepy/static/uploads/ with a single directory-level ignore, and add a clarifying comment that uploaded/downloaded files must never be tracked in git.
- Add new `/projects/{slug}/files` endpoint group for per-project filesystem operations including directory and file CRUD, upload, and inline editing with public read and owner write access
- Extend attachment system to support video formats (webm, ogv, mov, m4v) with proper file icons and MIME types
- Implement configurable allowed file types via `allowed_file_types` site setting, replacing hardcoded `ALLOWED_UPLOAD_TYPES` with dynamic `allowed_extensions()` and `is_extension_allowed()` functions
- Add `delete_all_project_files()` call in `delete_content_item()` to clean up project files when a project is deleted
- Create database indexes on `project_files` table for `(project_uid, path)` and `(project_uid, parent_path)` to optimize file lookups
- Introduce `docs_prose.py` module with `render_prose()` function that renders Markdown content inside `data-render` divs using mistune, enabling dynamic prose rendering in documentation pages
- Enhance docs search with Markdown-aware text stripping (`_demarkdown()`) and improved HTML/script/style sanitization for better search indexing
- Update documentation API samples to reflect new attachment response fields (`is_image`, `is_video`, `mime_type`) and note video format support
- Update README to document the new project files endpoint and clarify AI gateway attribution for guest Devii sessions
This commit introduces a comprehensive set of new features including API key authentication with CLI management commands (get, reset, backfill), a Devii agentic assistant with WebSocket terminal and session bootstrap, an OpenAI-compatible LLM gateway service, and an admin service management panel. It also adds Playwright browser automation for bot support, configures internal gateway URLs, refactors content editing/deletion to support JSON API responses, and updates documentation across AGENTS.md, README.md, and the developer docs site.
Add three new feature modules (reactions, bookmarks, polls) with corresponding database tables, indexes, and router registrations. Introduce `SESSION_MAX_AGE_REMEMBER` config for extended session duration, add `get_unread_messages` template global, and include operational defaults for rate limiting and session settings in `site_settings`.
Add coverage tooling to CI workflow, Makefile, and pyproject.toml dependencies.
Introduce new test suites for push notification helpers (base64 encoding, HKDF,
authorization JWT) and utility functions (safe_next, strip_html, mention extraction,
badge/xp awarding, milestone checks) with a session-scoped local_db fixture.
Implement canonical_redirect helper in content.py to enforce slug-based 301 redirects for gist, news, post, and project detail pages. Add first_image_url helper to extract primary image from item or attachments for Open Graph meta tags. Inject next_page_url into feed, gists, news, and projects list page SEO contexts for pagination link rel. Extend seo.py with SITEMAP_URL_LIMIT, SITEMAP_TTL constants and _sitemap cache variable for future sitemap generation optimization. Update profile page to raise 404 via not_found instead of 302 redirect, and include og_image from avatar_url.
- Fix test_bug_comment_reply and test_project_comment_reply to scope fill/click to .comment-reply-form instead of using generic textarea/button selectors
- Add test_login_next_redirects_to_target verifying ?next=/gists redirects after login
- Add test_login_next_rejects_external ensuring external ?next= URL falls back to /feed
- Add test_comment_reply_inline_form, test_comment_reply_toggle_and_cancel, test_comment_create_scrolls_to_anchor for post comment reply UX
- Add _seed_post_with_comments and _create_post_ui helpers in test_feed.py
- Fix test_news_comment URL assertion to use wildcard pattern for slug matching
- Add `next` field to LoginForm model for preserving post-login redirect target
- Implement `safe_next` utility to validate redirect URLs and prevent open redirect vulnerabilities
- Update login page handler to accept and pass `next` query parameter
- Add hidden `next` input to login form template for POST submission
- Modify `require_user` to redirect to `/auth/login` instead of root
- Add `Http.toLogin()` static method in JS for client-side redirect with current URL encoded
- Update CommentManager to redirect unauthenticated reply attempts to login
- Fix comment creation redirect to use `comment_url` instead of generic `redirect_url`
Extract comment item building into `_build_comment_items` helper in database.py, import `get_recent_comments_by_post_uids` in feed router to attach up to 3 recent comments per post, add `post-card-comments` CSS class and `.comment-reply-form` margin rule, refactor `CommentManager` to use event delegation and toggle reply forms via a hidden template, move comment rendering into a reusable `_comment.html` macro, and include recent comments in `_post_card.html` with inline reply capability.
Add `fuser -k` to kill stale processes on the locust port before starting the uvicorn server, and improve the server readiness loop to detect startup failures early. In the locustfile seed function, cap user creation attempts at 25 and log a clear error if fewer than 5 seed users are created, preventing silent hangs or partial test data.
Extract shared PAGE_SIZE constant and paginate() function into database.py, replacing inline cursor logic in feed, gists, news, and projects routers. Introduce `_load_more.html` partial template to unify "Load More" button rendering. Update all affected route handlers to accept `before` query parameter and return `next_cursor` for seamless infinite scroll. Adjust projects count display to use filtered length instead of total. Add test helper `_seed_posts` for pagination coverage.
Introduce a new `/leaderboard` endpoint ranking top 50 members by total stars, wire it into the app router and documentation. Implement `_backfill_gamification()` in `database.py` to compute XP/levels for existing accounts from prior posts, comments, votes, and follows. Extract `is_owner()`, `create_content_item()`, and `detail_context()` into `content.py` to centralize content creation, reward awarding, mention notifications, and attachment linking. Update comment creation/deletion in `comments.py` to use `award_rewards()` with `XP_COMMENT` and the new `is_owner()` helper. Add shared template partials documentation for vote bars, star buttons, post headers, and topic selectors to `AGENTS.md`.
- Remove `make demo` target from Makefile, AGENTS.md, and README.md
- Improve `_row_to_attachment` to glob for thumbnail files with any extension instead of hardcoding `.jpg`
- Rewrite `cmd_attachments_prune` to use time-based cutoff and `delete_attachment` helper instead of orphan detection
- Add cursor-based pagination to feed and notifications endpoints with `before` parameter
- Track `did_upvote` flag in vote handler to only notify on new upvotes, not vote changes
- Add `PAGE_SIZE` constant and `next_cursor` template variable to notifications page
- Implement Playwright tests for notification pagination with 30 seeded notifications
- Vendored DOMPurify at static/vendor/purify.min.js, loaded with defer in base.html
- ContentRenderer.js now sanitizes marked output via DOMPurify.sanitize before processMedia
- Fail-closed: render() throws if DOMPurify is undefined instead of emitting unsanitized HTML
- Added _json_ld_dumps helper in seo.py to escape <>&\u2028\u2029 in JSON-LD output
- Updated combine() to use the new safe dumper for all schema.org payloads
Replace static form-based vote buttons with a new VoteManager class that submits votes via fetch, returns JSON with net/up/down/current value, and updates vote count spans using data-vote-count attributes across all templates. Add JSONResponse endpoint in votes router for AJAX requests, switch VoteManager import from Http to Toast for error feedback, and refactor link_attachments to handle comma-separated UIDs.
Extract duplicate target-redirect logic from comments router into a new `resolve_object_url` database function, add `target_url` field to follow and message notifications, create `/notifications/open/{uid}` endpoint that marks notifications read and redirects to their target, implement client-side NotificationManager for card clicks and comment hash scrolling, and add comment-highlight CSS animation.
Implement two new database functions: get_top_authors aggregates star counts across posts, projects, and gists tables with 60-second TTL caching, and get_user_stars computes total stars for a given user_uid. Refactor feed page to use get_top_authors instead of raw users table query, and display aggregated star count on profile pages via get_user_stars. Add Playwright integration test verifying profile star count increments after a post vote.
The test was using a generic `.topnav-icon` locator that could match any topnav icon, but the notification bell specifically has an href pointing to `/notifications`. Updated the selector to `.topnav-icon[href='/notifications']` for precise element targeting.
Implement progressive web app capabilities including VAPID-based push notification infrastructure, service worker with offline caching, PWA install prompt handling, and manifest configuration. Add push.py module for VAPID key generation and notification delivery, PushManager and PwaInstaller JavaScript classes, service worker with precache and push event handling, offline fallback page, and app icons at multiple resolutions.
The test CI workflow in .gitea/workflows/test.yaml no longer includes the "Deploy to production" step that previously ran on successful pushes to the master branch. This change removes the conditional deployment logic and the associated `make deploy` command from the workflow configuration.
- Introduce push notification module with VAPID certificate generation, Web Push encryption, and subscription management
- Add push registration table index and database schema for storing user subscriptions
- Integrate push notification dispatch into existing notification creation flow via async background tasks
- Include PWA manifest, service worker, and install prompt UI elements in base template
- Register new push router and ensure certificate initialization on application startup
- Add configuration variables for VAPID private/public key file paths and subscription contact email
- Update JavaScript application entry point with PushManager and PwaInstaller modules
- Extend top navigation bar with hidden install and push enable buttons for authenticated users
Add a new `get_gist_languages()` function in database.py that queries distinct language codes from the gists table and caches results for 60 seconds. Create a database index on the `language` column of the gists table for efficient queries. Update the gists router to pass the set of active language codes to the template. Modify the gists.html sidebar to only display language filter links for codes that actually have gists in the database, hiding empty language categories and conditionally showing the plaintext link.
Introduce `update_target_stars`, `get_target_owner_uid`, and `VOTABLE_TARGETS`/`STAR_TARGETS` in database.py; replace inline badge insertion with `award_badge()` and inline notification creation with `create_notification()` across auth, comments, and follow routers; add `enrich_items()` in new content module to centralize post/gist list assembly and remove duplicated enrichment logic from feed and gists routers.
Introduce `get_int_setting()` in database.py to safely parse integer settings with a default fallback, replacing repeated `int(get_setting(...))` calls in uploads.py and templating.py. In admin.py, skip saving settings entries when the submitted value is an empty string, preventing accidental overwrites with blank values.
The import statement for `get_users_by_uids` was removed from the project_detail endpoint in `devplacepy/routers/projects.py` as it was no longer used after a prior refactor of user lookup logic. This eliminates a dead code path and potential linting warnings.
Add comprehensive test coverage for input validation scenarios including
rejecting bad vote values, oversized and undersized post content,
overlong profile bios, and short signup usernames with proper error
messages.
Migrate all route handlers from manual `request.form()` parsing to typed `Annotated[Model, Form()]` dependencies using new pydantic models (SignupForm, LoginForm, ForgotPasswordForm, AdminRoleForm, AdminPasswordForm, BugForm, CommentForm, GistForm). Remove inline validation logic from signup, login, password reset, admin role/password change, bug creation, comment creation, and gist creation endpoints, delegating validation to model validators and field constraints. Add `RequestValidationError` exception handler with friendly error messages for auth form pages. Update model definitions to use `field_validator` and `model_validator` for cross-field checks like password matching.
The change modifies the import statement from `multiavatar` to `multiavatar.multiavatar` and updates the function call to pass `None, None` as additional arguments, aligning with a newer version of the multiavatar library's API.
- Reduced input area padding from 1rem to 0.75rem 1rem and switched from flex-wrap to align-items center with smaller gap
- Changed send button from rectangular with padding to a 36px circular button with centered icon and hover transition
- Added flex-shrink and min-width:0 to text input to prevent overflow on narrow screens
- Added full-width attachment preview container with negative order to stack above input row
- Injected JavaScript to auto-scroll message thread to bottom and focus input on page load for mobile UX
Wrap post titles in anchor tags linking to post detail pages, make post content divs clickable to navigate on non-link clicks, and replace static star/comment indicators with inline upvote forms and dynamic vote count display in profile.html.
Implement responsive design adjustments across admin, auth, base, feed, gists, landing, messages, news, notifications, post, profile, projects, and services CSS files with collapsible sidebar, touch-friendly navigation, and reordered content sections for screen widths below 768px and 480px. Add hamburger menu toggle, mobile overlay panel, and back button for messages view in Application.js.