Compare commits

..

17 Commits

Author SHA1 Message Date
marcus 37f0e950d0 docs: align scheduler wording 2026-05-21 00:50:11 +01:00
marcus ee38f4c4bc docs: generalize scheduler wording (#41) 2026-05-19 22:07:30 +01:00
marcus 80b9b581fb docs: record dashboard recovery runbook (#39) 2026-05-19 08:33:36 +01:00
marcus 79f2fa4399 docs: generalize health dashboard runbook paths (#37) 2026-05-11 14:38:51 +01:00
marcus 796d4ae381 docs: clarify health dashboard remediation (#35) 2026-05-10 08:57:31 +01:00
marcus 5d3ec80907 Resolve supervisor dashboard freshness alert (#32) (#33)
* wip: preserve worker changes on abnormal exit

* docs: document health dashboard remediation

* chore: drop restored metadata marker
2026-05-10 01:43:21 +01:00
marcus 4ecccbc107 fix: give Composer autoloader precedence and optimise PSR-4 loader (#30)
- Swap load_dependencies() before register_autoloader() in the
  constructor so Composer (when a vendor/ install is present) is
  registered on the spl_autoload stack first and therefore acts as
  the primary class resolver, with the custom loader as fallback.
- Add early-exit guard in the autoloader closure: skip the namespace
  map loop entirely for classes that don't share the plugin base
  prefix, avoiding unnecessary iteration on every WordPress class
  lookup.
- Store the namespace map in a static variable so it is allocated
  only once across all invocations rather than on each call.
- Switch from require_once to require inside the autoloader: the
  autoloader is only invoked for classes not yet defined, making the
  redundancy check in require_once unnecessary overhead.

Resolves #29
2026-04-26 11:01:53 +01:00
marcus 85d55e80fc feat: implement PSR-4 autoloader, remove manual require_once calls (#27)
- Add spl_autoload_register in Plugin::register_autoloader() mapping
  WPALLSTARS\FixPluginDoesNotExistNotices\Admin\ to admin/lib/ and
  WPALLSTARS\FixPluginDoesNotExistNotices\ to includes/
- Remove manual require_once calls for Core, Admin, and Modal classes
- Rename admin/lib/admin.php -> Admin.php and modal.php -> Modal.php
  for PSR-4 filename convention (class name must match file name)
- Fix composer.json: correct namespace case (WPAllStars -> WPALLSTARS)
  and add admin/lib/ directory mapping for Admin sub-namespace
- Fix wp-fix-plugin-does-not-exist-notices.php require_once to use
  correct case (plugin.php -> Plugin.php)

Resolves #25
2026-04-24 08:34:47 +01:00
marcus 5a80351d1f fix: correct class name and version locations in AGENTS.md
Resolves #24

- Use fully qualified class name WPALLSTARS\FixPluginDoesNotExistNotices\Plugin in version management snippet
- Replace misleading includes/Plugin.php entry (no version constant) with AGENTS.md as the fourth version location
- Add note clarifying Plugin.php passes version via constructor
- Add step 4 to bump-version checklist to update AGENTS.md version string
2026-04-24 08:28:14 +01:00
marcus 34b0b6f0d6 fix: replace ambiguous X.Y.Z placeholder with actual version in AGENTS.md (#23)
Gemini review (PR #14) flagged that 'X.Y.Z' in the Version Management
section is problematic for AI agents — they may interpret it literally
or fail to match it during automated edits.

Replace with the actual current version '2.4.0' plus a parenthetical
instruction '(replace 2.4.0 with the new version)' so the context is
unambiguous: agents can grep for the exact string and know what to
substitute.

Resolves #19
2026-04-23 05:29:11 +01:00
marcus 1d1380275e fix: add missing Updater.php require in load_dependencies and fix Core.php case (#22)
Resolves #20

- Adds require_once for includes/Updater.php which was instantiated in
  init_components() but never loaded in load_dependencies()
- Fixes includes/core.php → includes/Core.php case mismatch (would fail
  on case-sensitive Linux filesystems)
2026-04-23 05:26:36 +01:00
marcus b0bb363f99 fix: correct AI workflow doc file references to prevent read:file_not_found errors
fix: correct AI workflow doc file references to prevent read:file_not_found errors
2026-04-22 21:14:11 +01:00
marcus 17de1949ae fix: correct AI workflow doc file references to prevent read:file_not_found errors
- folder-structure.md: fix includes/core.php → Core.php, plugin.php → Plugin.php,
  updater.php → Updater.php (PascalCase matches actual filenames on disk)
- bug-fixing.md: fix fix-plugin-does-not-exist-notices.php →
  wp-fix-plugin-does-not-exist-notices.php (correct wp- prefix) and
  languages/fix-plugin... → languages/wp-fix-plugin... (same prefix fix)
- feature-development.md: remove reference to non-existent reference-plugins/
  directory to stop read:file_not_found errors when AI follows the docs

Addresses contributor insight issue #16: incorrect file paths in AI workflow
docs were the root cause of 23x read:file_not_found, 71x edit:not_read_first,
32x edit:edit_stale_read, and 66x bash:other errors in AI assistant sessions.
2026-04-22 21:09:42 +01:00
marcus 18cf60c2a4 fix: correct case-sensitive require_once paths and add AGENTS.md (#14)
* fix: correct case-sensitive require_once paths and add AGENTS.md for AI guidance

- Fix includes/plugin.php -> includes/Plugin.php in main plugin file
- Fix includes/core.php -> includes/Core.php in includes/Plugin.php
  (Linux case-sensitive filesystems fail silently on macOS; runtime bug on production)
- Fix .ai-workflows/folder-structure.md: update class files to PascalCase,
  remove references to non-existent admin/ subdirectories (images/, partials/,
  settings/, tools/) that caused read:file_not_found errors in AI sessions
- Add AGENTS.md with authoritative file map to reduce AI agent errors:
  edit:not_read_first, bash:other, edit:edit_stale_read, read:file_not_found

Resolves #13

* fix: markdown formatting in AGENTS.md (Codacy MD022/MD032)
2026-04-22 09:57:41 +01:00
marcus 3eaf8ec7a5 chore: add ai-training=false to .gitattributes 2026-03-26 01:32:25 +00:00
marcus ff838ec5f2 chore: fix malformed .gitignore entry and add loop-state ignore 2026-03-16 16:18:40 +00:00
marcus 7ae29b793f Merge v2.4.0 into main
Sync Wiki / sync-wiki (push) Has been cancelled
ci/woodpecker/push/woodpecker Pipeline failed
2025-04-17 04:29:58 +01:00
14 changed files with 260 additions and 24 deletions
+2 -2
View File
@@ -144,12 +144,12 @@ Apply the minimal fix necessary to address the critical issue.
Increment the PATCH version and update all version numbers:
- Main plugin file (fix-plugin-does-not-exist-notices.php)
- Main plugin file (wp-fix-plugin-does-not-exist-notices.php)
- FPDEN_VERSION constant
- CHANGELOG.md
- readme.txt
- README.md
- languages/fix-plugin-does-not-exist-notices.pot (Project-Id-Version)
- languages/wp-fix-plugin-does-not-exist-notices.pot (Project-Id-Version)
### 4. Commit and Push
-1
View File
@@ -27,7 +27,6 @@ When implementing a new feature:
- Add appropriate comments
- Consider performance implications
- Maintain backward compatibility
- Review reference plugins in the `reference-plugins/` directory for inspiration and best practices
### 3. Update Documentation
+8 -11
View File
@@ -16,10 +16,6 @@ This document outlines the folder structure of the plugin and explains the purpo
- **admin/css/** - Admin-specific CSS files
- **admin/js/** - Admin-specific JavaScript files
- **admin/images/** - Admin-specific images
- **admin/partials/** - Admin-specific template partials
- **admin/settings/** - Admin settings functionality
- **admin/tools/** - Admin tools functionality
- **admin/lib/** - Admin-specific library files and helper functions
- **admin/lib/admin.php** - Admin class for handling admin-specific functionality
- **admin/lib/modal.php** - Modal class for handling the update source selector modal
@@ -28,13 +24,14 @@ This document outlines the folder structure of the plugin and explains the purpo
The `includes/` directory contains the core plugin functionality:
- **includes/core.php** - Core class for handling the main plugin functionality
- **includes/plugin.php** - Main plugin class that initializes all components
- **includes/updater.php** - Updater class for handling plugin updates
- **includes/Core.php** - Core class for handling the main plugin functionality
- **includes/Plugin.php** - Main plugin class that initializes all components
- **includes/Updater.php** - Updater class for handling plugin updates
## File Naming Conventions
- All PHP files in the `includes/` directory use lowercase filenames
- PHP class files in the `includes/` directory use PascalCase filenames matching the class name (e.g., `Core.php`, `Plugin.php`, `Updater.php`)
- PHP files in `admin/lib/` use lowercase filenames (e.g., `admin.php`, `modal.php`)
- All directories use lowercase names
- JavaScript and CSS files use kebab-case (e.g., `update-source-selector.js`)
@@ -50,10 +47,10 @@ The `includes/` directory contains the core plugin functionality:
When referring to files or directories in AI conversations, use the following format:
- **@includes/plugin.php** - Main plugin class
- **@includes/core.php** - Core functionality
- **@includes/Plugin.php** - Main plugin class
- **@includes/Core.php** - Core functionality
- **@admin/lib/admin.php** - Admin functionality
- **@admin/lib/modal.php** - Modal functionality
- **@includes/updater.php** - Updater functionality
- **@includes/Updater.php** - Updater functionality
- **@admin/js/update-source-selector.js** - Update source selector JavaScript
- **@admin/css/update-source-selector.css** - Update source selector CSS
@@ -0,0 +1,48 @@
# Supervisor health dashboard remediation
Use this runbook when the repository supervisor health dashboard becomes stale.
## Signals
- The pinned supervisor issue has an old `last_refresh:` marker.
- The stats scheduler exists and is loaded, but wrapper runs overlap or remain
active beyond the expected timeout.
- Recent stats logs stop before the affected repository is updated.
## Remediation
1. Confirm the scheduler and stats log are present:
```bash
launchctl list | grep -i aidevops-stats-wrapper
ls -la ~/Library/LaunchAgents/com.aidevops.aidevops-stats-wrapper.plist
tail -40 ~/.aidevops/logs/stats.log
```
2. Check for an active `stats-wrapper.sh` process that has exceeded `STATS_TIMEOUT`.
The default timeout is `600` seconds and is defined near the top of
`~/.aidevops/agents/scripts/stats-wrapper.sh`; an operator can confirm the
runtime value with a dry run:
```bash
STATS_DRY_RUN=1 bash ~/.aidevops/agents/scripts/stats-wrapper.sh --dry-run
```
3. Terminate the stale wrapper process and remove the stale stats pidfile at
`~/.aidevops/logs/stats.pid`.
4. Run one targeted health issue refresh for this repository:
```bash
REPO_SLUG="<owner/repo>" \
REPO_PATH="<your/local/path>" \
bash -lc '
source "$HOME/.aidevops/agents/scripts/shared-constants.sh"
source "$HOME/.aidevops/agents/scripts/worker-lifecycle-common.sh"
source "$HOME/.aidevops/agents/scripts/stats-functions.sh"
_update_health_issue_for_repo "$REPO_SLUG" "$REPO_PATH" "" "" ""
'
```
5. Verify the pinned dashboard issue now has a fresh `last_refresh:` marker and
recent `updated_at` timestamp.
+27
View File
@@ -0,0 +1,27 @@
# Supervisor dashboard recovery
The repository's aidevops supervisor dashboard is maintained outside the
WordPress plugin runtime by the local stats scheduler. If a dashboard freshness
alert reports that the pinned dashboard issue is stale while `stats.log` still
shows hourly `Health issues: updated ... repo(s)` messages, verify the local
health-issue cache before changing plugin code.
## Triage
1. Confirm the local stats scheduler job exists and is running.
2. Inspect `~/.aidevops/logs/stats.log` for the affected repository.
3. Check the pinned dashboard issue body for the `last_refresh:` marker.
4. Confirm the cache file naming expected by the current aidevops version.
## Cache migration failure mode
Older aidevops releases wrote role-qualified cache files such as
`health-issue-<user>-supervisor-<owner>-<repo>`. Current dashboard refresh code
expects `health-issue-<canonical-user>-<owner>-<repo>`. If only the older cache
file exists and the repository has no active PRs, assigned issues, or workers,
the activity guard can skip resolving the already-open dashboard issue, leaving
the existing dashboard stale.
Restore the expected cache entry to the pinned dashboard issue number, then run
the dashboard update path again. Verify that the pinned issue's `updated_at` and
`last_refresh:` marker are current before closing the freshness alert.
+2
View File
@@ -10,9 +10,11 @@ This directory contains workflow documentation for AI assistants working with th
- **feature-development.md**: Process for developing new features
- **folder-structure.md**: Documentation of the plugin's folder structure and naming conventions
- **git-workflow.md**: Detailed git workflow and branch management guidelines
- **health-dashboard-remediation.md**: Supervisor health dashboard staleness triage and remediation
- **incremental-development.md**: Time-efficient approach for incremental development and testing
- **local-env-vars.md**: Local development environment paths and URLs
- **multi-repo-workspace.md**: Guidelines for working in workspaces with multiple repositories
- **ops-dashboard.md**: Triage notes for aidevops supervisor dashboard freshness alerts
- **release-process.md**: Steps for preparing and publishing new releases
- **wiki-documentation.md**: Guidelines for maintaining wiki documentation
+4 -1
View File
@@ -98,4 +98,7 @@ reference-plugins export-ignore
# Merge driver for changelog files to prevent conflicts
CHANGELOG.md merge=union
readme.txt merge=union
readme.txt merge=union
# Opt out of AI model training
* ai-training=false
+2 -1
View File
@@ -169,4 +169,5 @@ codecov.yml
webpack.config.js
gulpfile.js
Gruntfile.js
*.zip
*.zip
.agents/loop-state/
+104
View File
@@ -0,0 +1,104 @@
# AGENTS.md — AI Agent Guide for wp-fix-plugin-does-not-exist-notices
This file provides precise, verified guidance for AI agents working in this repository. Read it before editing any file to avoid `read:file_not_found` and `edit:not_read_first` errors.
## Repository Purpose
**Fix 'Plugin file does not exist' Notices** — a WordPress plugin that detects active plugins whose files are missing, adds them to the Plugins list with a "Remove Notice" action link, and safely removes their database references.
- GitHub: `wpallstars/wp-fix-plugin-does-not-exist-notices`
- Namespace: `WPALLSTARS\FixPluginDoesNotExistNotices`
- Text domain: `wp-fix-plugin-does-not-exist-notices`
- Current version: see `wp-fix-plugin-does-not-exist-notices.php` header
## Exact File Map (authoritative — verified against git ls-files)
**CRITICAL**: PHP class files in `includes/` use PascalCase. The docs and `require_once` paths must match exactly. On Linux (case-sensitive), wrong case = fatal error.
```
wp-fix-plugin-does-not-exist-notices.php # Plugin entry point — sets Version, requires includes/Plugin.php
includes/Plugin.php # Main Plugin class — loads dependencies, inits components
includes/Core.php # Core class — all WordPress hooks and plugin logic
includes/Updater.php # Updater class — handles Git Updater / WP.org update sources
admin/lib/admin.php # Admin\Admin class — admin page rendering, enqueues
admin/lib/modal.php # Admin\Modal class — update source selector modal
admin/css/admin-styles.css # General admin styles
admin/css/update-source-selector.css # Styles for the update source modal
admin/js/admin-scripts.js # General admin JS
admin/js/update-source-selector.js # JS for the update source modal
languages/wp-fix-plugin-does-not-exist-notices.pot # Translation template
build.sh # Build/release script
scripts/deploy-local.sh # Local deployment helper
composer.json # Composer config (no vendor/ committed)
README.md # Developer readme
readme.txt # WordPress.org readme (keep in sync with README.md)
CHANGELOG.md # Changelog (keep in sync with README.md and readme.txt)
```
**Directories that DO NOT exist** (do not attempt to read or create files here):
- `admin/images/` — does not exist
- `admin/partials/` — does not exist
- `admin/settings/` — does not exist
- `admin/tools/` — does not exist
- `vendor/` — not committed; loaded at runtime if present
## Before Editing Any File
1. Read the file first: `Read includes/Core.php` — not `includes/core.php` (wrong case fails).
2. Re-read the file if another tool call may have modified it since your last read.
3. Verify the file path with `git ls-files '<pattern>'` when uncertain.
## Version Management
Version appears in **four places** — all must be updated together:
1. `wp-fix-plugin-does-not-exist-notices.php``Version:` header and `new WPALLSTARS\FixPluginDoesNotExistNotices\Plugin(__FILE__, '2.4.0')` (replace `2.4.0` with the new version)
2. `readme.txt``Stable tag:` and changelog section
3. `CHANGELOG.md` — top entry
4. `AGENTS.md` — this file, item 1 above (replace the hardcoded version string)
Note: `includes/Plugin.php` has no direct version constant; the version is passed in via the constructor call in the entry point file.
`README.md` changelog section must also stay in sync with `CHANGELOG.md`.
## Common Tasks
### Fix a bug in core plugin logic
Edit `includes/Core.php`. All WordPress hooks are registered in the constructor.
### Change admin UI or settings
Edit `admin/lib/admin.php` (Admin class) and/or `admin/lib/modal.php` (Modal class).
CSS: `admin/css/admin-styles.css` or `admin/css/update-source-selector.css`.
JS: `admin/js/admin-scripts.js` or `admin/js/update-source-selector.js`.
### Bump version for a release
1. Update version in `wp-fix-plugin-does-not-exist-notices.php` (both header and constructor call).
2. Update `Stable tag:` in `readme.txt`.
3. Add changelog entry to `readme.txt`, `CHANGELOG.md`, and `README.md`.
4. Update the version string in `AGENTS.md` (item 1 of the Version Management list above).
### Add or fix update source logic
Edit `includes/Updater.php`.
## Git Workflow
- Branch naming: `feature/`, `fix/`, `patch/`, `refactor/` prefixes
- One branch per issue; one PR per issue
- Push to both `github` and `gitea` remotes
- Do not include version numbers in branch names during development
## AI Workflow Documentation
Extended guidance is in `.ai-workflows/`:
- `folder-structure.md` — directory layout with correct filenames
- `git-workflow.md` — branching, commit messages, remote management
- `feature-development.md` — feature development process
- `bug-fixing.md` — bug investigation and fix process
- `release-process.md` — full release checklist including Git Updater notes
- `dev-prefs-memory.md` — persistent developer preferences
+2 -1
View File
@@ -15,7 +15,8 @@
},
"autoload": {
"psr-4": {
"WPAllStars\\FixPluginDoesNotExistNotices\\": "includes/"
"WPALLSTARS\\FixPluginDoesNotExistNotices\\Admin\\": "admin/lib/",
"WPALLSTARS\\FixPluginDoesNotExistNotices\\": "includes/"
}
}
}
+60 -6
View File
@@ -77,6 +77,7 @@ class Plugin {
$this->define_constants();
$this->load_dependencies();
$this->register_autoloader();
$this->init_components();
}
@@ -97,22 +98,75 @@ class Plugin {
}
}
/**
* Register the PSR-4 autoloader
*
* Maps plugin namespaces to their corresponding directories so that
* new class files are loaded automatically without manual require_once calls.
*
* Optimisations applied:
* - Early exit when the class does not belong to this plugin's namespace,
* avoiding the loop entirely for every foreign class lookup.
* - The namespace map is stored in a static variable so it is allocated
* only once across all invocations rather than on every class lookup.
* - `require` is used instead of `require_once` because the autoloader is
* only called for classes that are not yet defined, making the redundancy
* check in `require_once` unnecessary.
*
* @return void
*/
private function register_autoloader() {
$plugin_dir = $this->plugin_dir;
spl_autoload_register(function ($class) use ($plugin_dir) {
// Skip immediately if the class is not in this plugin's namespace.
$base_prefix = 'WPALLSTARS\\FixPluginDoesNotExistNotices\\';
if (strncmp($base_prefix, $class, strlen($base_prefix)) !== 0) {
return;
}
// Static map allocated once; ordered most-specific first so Admin\
// resolves before the root namespace.
static $namespace_map = null;
if ($namespace_map === null) {
$namespace_map = array(
'WPALLSTARS\\FixPluginDoesNotExistNotices\\Admin\\' => 'admin/lib/',
'WPALLSTARS\\FixPluginDoesNotExistNotices\\' => 'includes/',
);
}
foreach ($namespace_map as $prefix => $relative_path) {
if (strncmp($prefix, $class, strlen($prefix)) !== 0) {
continue;
}
$relative_class = substr($class, strlen($prefix));
$file = $plugin_dir . $relative_path . str_replace('\\', DIRECTORY_SEPARATOR, $relative_class) . '.php';
if (file_exists($file)) {
require $file;
return;
}
}
});
}
/**
* Load dependencies
*
* Loads the Composer autoloader when available (vendor installs), registering
* it on the spl_autoload stack before the custom PSR-4 loader so that Composer
* acts as the primary resolver. Project classes without a vendor install are
* resolved by the autoloader registered in register_autoloader().
*
* @return void
*/
private function load_dependencies() {
// Load composer autoloader if it exists
// Load composer autoloader if it exists (vendor/ directory present).
$autoloader = $this->plugin_dir . 'vendor/autoload.php';
if (file_exists($autoloader)) {
require_once $autoloader;
}
// Load required files
require_once $this->plugin_dir . 'includes/core.php';
require_once $this->plugin_dir . 'admin/lib/admin.php';
require_once $this->plugin_dir . 'admin/lib/modal.php';
}
/**
+1 -1
View File
@@ -32,7 +32,7 @@ if (!defined('WPINC')) {
}
// Load the main plugin class
require_once plugin_dir_path(__FILE__) . 'includes/plugin.php';
require_once plugin_dir_path(__FILE__) . 'includes/Plugin.php';
// Initialize the plugin
// This is a test change for our new workflow