Document what Muninn does (content-operations hub for Sites, Social
Accounts, and Posts with a JSON API for AI agents) and how to set it
up locally.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Extends Sites with cms_type + WP Application Password credentials
and adds a posts:publish Artisan command to push a Post to a
WordPress site's REST API, mirroring the reddit-post sidecar's
role for a native, non-browser-automation CMS target.
Extends Sites with cms_type + WP Application Password credentials
and adds a posts:publish Artisan command to push a Post to a
WordPress site's REST API, mirroring the reddit-post sidecar's
role for a native, non-browser-automation CMS target.
Addresses whole-branch review's minor findings:
- Unknown CLI arguments now echo only the flag name, not its value, so a
mistyped flag (e.g. --pasword=secret) can't leak a credential into the
error output.
- README now notes that failed runs retain a screenshot/trace under
test-results/ (gitignored, may contain the username but not the masked
password), and points at the UNVERIFIED post-composer selectors as the
first thing to check during real home-network verification.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Implements run.sh with argument parsing (--username, --password, --subreddit,
--title, --body, optional --headed), environment variable mapping to Task 2's
env contract, Playwright invocation with proper exit-code capture via set +e,
and result file output to stdout.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addresses reviewer's minor findings on the prior fix commit: makes the
screenshot-verified/unverified boundary explicit in code comments so it
travels with the file rather than living only in commit messages, and
removes redundant .click() calls before .fill() (fill() already focuses).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Live verification against a real Reddit login page (from this dev
sandbox) showed:
- The actual submit button has no [type="submit"] attribute; its
accessible name is "Log In" — switched to getByRole with that name.
- Username/password fields are better targeted via their visible
labels (getByLabel) than brittle name= attribute selectors.
- A cookie-consent dialog can overlay the form and intercept clicks;
it's now dismissed via "Reject Optional Cookies" before filling in.
- This sandbox's network is flagged by Reddit's bot detection with a
"blocked by network security" interstitial before the login form
even loads — this is unrelated to credentials and unrelated to the
target account (confirmed reachable fine from a residential
network/browser). Added explicit detection for this state so it
reports a clear, distinguishable error instead of a generic
CAPTCHA/2FA guess. Full live end-to-end verification (successful
login + post creation) must be run from a network Reddit does not
block, e.g. the mini PC this app actually runs on.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The outer catch's overwrite guard checked `!outcome.error`, but outcome.error
is always truthy (even the default placeholder string), so an exception
occurring outside the two explicitly-guarded blocks (e.g. a .fill()/.click()
timeout) would leave the generic "Test did not complete" message instead of
the real error. Replaced with an explicit outcomeFinalized sentinel that is
set exactly where outcome is deliberately finalized (missing env var, login
timeout, post-submission timeout, success), so any other exception correctly
falls through to the catch-all branch with its real message.
Adds JSON API for Posts (index/show/store/update/destroy) so an AI
agent can draft posts, read what's due for publishing, and report
back publish/fail status. Unlike the existing read-only Sites/Accounts
APIs, this is full CRUD since the app itself never publishes anything.
- PostController with status/site_id/social_account_id/due filters
- StorePostRequest/UpdatePostRequest validate against Post::TYPES/STATUSES
- PostResource shapes the JSON response
- Route::apiResource('posts', ...) registered with ->names('api.posts')
to avoid colliding with the existing web posts.index route name
- store() calls ->fresh() after create() so the response reflects the
DB-level default status ('draft') instead of a stale in-memory null
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds the Posts index page (list/create/edit/delete) following the
existing Sites/SocialAccounts pattern, and extends the shared nav
layout with a Posts link.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds the Post model belonging to Site (required, cascade-deletes with
the site) and SocialAccount (nullable, nulled out on account delete).
Foundation for the Scheduled Posts feature; later tasks build the
Livewire CRUD UI and API on top of this model.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add GET /api/accounts (list with optional ?network= and ?type= filters) and
GET /api/accounts/{socialAccount} (show) endpoints. Include plain-text password
field for AI agent consumption.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add GET /api/sites endpoint for listing sites with optional name filter,
and GET /api/sites/{site} for showing individual sites. Includes API
resource, controller, routes registration, and comprehensive tests.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Generated during Task 5 (first task requiring npm install for the
Vite manifest); committing it so future installs resolve identical
dependency versions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Creates the <x-layouts.app> Blade component that provides the main
application shell, including Livewire styles/scripts, top navigation
linking to Sites and Social Accounts pages, and a slot for page content.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Implement SocialAccount model with enum fields for network and type,
along with migration and factory. Includes NETWORKS and TYPES constants
for dropdown usage in Livewire forms and validation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Implements Task 2: creates the Site model with fillable name, url, and
description fields; the corresponding database migration; and a factory
for generating test data. Includes TDD tests verifying model creation
with and without optional description.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>