- Phase 5A: Block Editor integration — Blocks feature service, per-CPT block registration, default templates @since 2026-07-08
- Phase 5D: Documentation — fill README placeholders, add model examples @since 2026-07-05
- MCP/REST gating refactor: McpPolicy + config-section model @since 2026-07-08
- Phase 5B: WP-CLI tools — 7 grouped command classes mapping every MCP tool
- Phase 5C: Frontend rendering — shortcodes, templates, meta field exposure
- Phase 5D: New doc files (BLOCKS.md, WPCLI.md, FRONTEND.md, FEATURES.md)
- None
-
Code review feedback: replaced wp_die with RuntimeException in single_export_query to avoid HTML death pages in REST/MCP contexts; added catch clause in export_post to return structured WP_Error; replaced unsafe property_exists with get_object_vars in ModelRestPolicy to avoid fatal errors on non-public properties; added explicit edit_posts permission checks for list_models/get_model/list_meta_fields/get_meta_fields in AbilityDefinitionFactory; changed AuditLogger created_at column from varchar(32) to datetime(3) — 2 commits @since 2026-07-04
-
Export query hardening: replaced fragile string-equality check in single_export_query with structural regex detection via is_fake_date_export_query; added wp_die fallback for unrecognized fake-date query shapes; added esc_html__ and wp_die test stubs — 1 commit @since 2026-07-04
-
Code review feedback: deferred RestServer instantiation inside rest_api_init to avoid overhead on non-REST requests; replaced wp_next_scheduled/wp_unschedule_event with wp_clear_scheduled_hook in MCP deactivation; gated ensure_table() behind DB version option to avoid unnecessary CREATE TABLE queries on every audit write; added wp_clear_scheduled_hook test stub — 3 commits @since 2026-07-04
-
PHP 7.4 test compatibility: removed
mixedtype hints from 6 test file anonymous classes implementing AuditDatabase to avoid fatal errors on PHP 7.4 (parse error) and PHP 8.x (interface signature mismatch) @since 2026-07-04 -
Audit/runtime hardening: MCP audit retention cleanup now runs through daily WP-Cron instead of after every audit write; settings updates safely sanitize object payloads; single-post REST export removes WordPress core download headers before returning through REST; health degradation now counts only server-side
errorandexceptionaudit statuses while still reporting validation and rate-limit status counts @since 2026-07-04 -
Service extraction: inline REST controller logic moved into shared service classes (SaltusSingleExport, MetaFieldProvider, ReorderPostsService, SettingsManager) and wired into both REST controllers and MCP tools; defensive guards added for null post, private property access, taxonomy object, and asset data types — 7 commits covering LegacyFeatureTest, FrameworkBootTest, RuntimeTest, RegistrarTest, and controller tests; 195 tests, 567 assertions @since 2026-07-03
-
Added MCP client integration guide at
docs/MCP-CLIENTS.md, covering recommended call flow, health-first checks, model and metadata discovery, safe reads/writes, permission and rate-limit handling, editor integration notes, prompt guidance, and anti-patterns @since 2026-07-03 -
Added
composer docs:mcpandbin/generate-mcp-docs.phpto generate MCP ability documentation fromsrc/MCP/Tools; generated output now refreshesdocs/MCP-ABILITIES.mdand the embedded ability table indocs/MCP.md@since 2026-07-03 -
Added long-form WordPress-native MCP/Abilities documentation at
docs/MCP.mdas the source page for future Saltus site docs, covering setup, discovery, permissions, all 17 abilities, metadata discovery, health monitoring, runtime filters, audit/cache/rate-limit behavior, compatibility, and troubleshooting @since 2026-07-03 -
MCP health ability added as
get_health, backed byGET /saltus-framework/v1/health, cacheable for 60 seconds, and registered assaltus/get-health; WordPress-native MCP/Abilities surface now exposes 17 tools @since 2026-07-03 -
Health monitoring REST endpoint added at
GET /saltus-framework/v1/health; reports framework version, native ability availability, audit sample/error rate/status counts, latency average/p95/max, and cache/rate-limit enabled flags. Route is registered independently of model-levelsaltus_restopt-in and is covered by HealthController and RestServer tests; verification is green withcomposer test,composer phpstan,composer phpcs, andgit diff --check@since 2026-07-03 -
Modeler ternary dispatch refactored into centralized
process_config()method; WP test stubs enhanced with add_filter, apply_filters callback execution, post_meta, nonce, enqueue, esc*, WP_Query, and WP_Term stubs; LegacyFeatureTest and ModelerLegacyTest added covering deprecated filter paths, file-order processing, and multi-model configs — 4 files, 812 insertions @since 2026-07-02 -
Code review hardening pass: single-post REST export now emits WXR only for the requested post;
Corecan register activation/deactivation hooks against the consuming plugin file; MCP mutating permission callbacks fail closed on missing target args; settings updates recursively preserve structured values;AbilityRuntimeJSON fallback works outside WordPress;AssetLoaderis covered by PHPStan viaAssetLoadingService@since 2026-07-02 -
Regression coverage added for export isolation, plugin-file lifecycle hook registration, fail-closed ability permissions, and nested settings payloads; verification is green with
composer test(166 tests, 416 assertions),composer phpstan,composer phpcs, andgit diff --check@since 2026-07-02 -
Permission granularity: REST controllers and MCP abilities now delegate to per-post-type and per-post WordPress capabilities instead of coarse edit_posts gate — 8 commits covering DuplicateController, MetaController, ModelsController, ReorderController, SettingsController, and AbilityDefinitionFactory; ToolFactory removed in favor of ToolContributor-driven provider injection @since 2026-07-02
-
MCP v1 refactoring: 14 commits — RestBackedToolInterface, RestCapabilityRequirement, RestTool, ToolContributor introduced; per-tool build_rest_request dispatch replaces monolithic AbilityRuntime switch; AbilityRegistrar gating via RestBackedToolInterface capability requirements; @phpstan-type AbilityDefinition added; all REST-backed tools migrated to RestBackedToolInterface; REST controllers updated for MCP v1 dispatch; ToolContributor wired into Modeler and all feature services @since 2026-07-02
-
Capability-gated REST routes: ModelRestPolicy, RestRouteDefinition, and RestRouteProvider infrastructure — per-model opt-in via
saltus_restconfig key; all 9 REST controllers enforce policy at request time; MCP abilities respect same policy gates @since 2026-07-01 -
Audit trail: insert validation and sanitization — null-byte stripping, column-length truncation, status whitelist, and WordPress sanitize_text_field applied to all string fields before persistence @since 2026-07-01
-
Fixed 2 pre-existing PHPStan errors in ResourceProvider — docblock param name mismatch (@param $context → $_context) @since 2026-07-01
-
Added unit tests for
BaseModel::get_name()andModeleradd/get_models (5 test methods, 248 total) -
Added
tests/Integration/.gitkeepto preserve the integration test directory -
composer phpcsis clean — all MCP module renamed to snake_case (14 commits) -
WordPress naming conventions enforced across MCP module: methods, properties, variables renamed from camelCase to snake_case
-
Added
Jsonhelper class for safe JSON encoding (wp_json_encode with json_encode fallback) -
Removed phpcs.xml exclusion rules for MCP and REST paths
-
Fixed ReflectionClass::getName() regression from rename
-
Full
composer phpstanis clean at PHPStan Level 7 across the configured analysis set -
Added
Model::get_name()andBaseModel::get_name()soModelerkeys models through the model contract instead of concrete public properties -
Tightened
Modeler::add()parameter and return types and removed redundant nullable fallback fromget_models() -
Updated REST controllers to register routes with non-empty namespace constants for PHPStan-safe WordPress route registration
-
Removed redundant taxonomy slug type narrowing in
ListPosts -
v2.0.0 released 2026-06-30 — merged feature/mcp-v0 to main, tagged v2.0.0
-
Added strict phpunit.xml config with random execution order, failOn* and beStrictAbout* flags
-
Added phpunit.xml.dist as distribution configuration
-
Created tests/TestCase.php base class for all framework tests
-
Added Unit test suite: Container, Asset, Model config tests (5 test files)
-
Added Integration test suite: FrameworkBootTest for service container verification
-
Added is_admin() stub in test functions for environment compatibility
-
Added PHPUnit test job to GitHub Actions CI workflow
-
Bumped version to 1.4.0
-
WordPress 7.0 MCP/Abilities connector:
MCPinjects feature-contributed tools intoAbilityRegistrarwhenwp_register_ability()exists -
Feature-owned
ToolContributorservices keep MCP tools aligned with their REST routes and capabilities -
Native ability callbacks dispatch through
rest_do_request()so existing REST permission callbacks remain authoritative -
Added compatibility tests covering native ability registration, capability gating, and REST-backed dispatch
-
README documents WordPress-native MCP/Abilities as the selected path
-
Removed standalone local stdio MCP server and related setup docs
-
WP7 clients use
list_meta_fieldsfor discovering model-defined meta fields across registered CPTs -
Added
list_meta_fieldsfor WordPress-native metadata discovery across registered CPTs -
Added aggregate
GET /saltus-framework/v1/metafor all post type meta definitions -
WP7 ability runtime resolves metadata discovery through the aggregate
/metaendpoint -
MCP clients currently see raw Saltus/Codestar meta config: metabox IDs, sections, field definitions, dynamic option callback names, and
register_rest_apihints -
Example for
itt_globe_point: clients discoverpoints_infoas serialized meta with nestedcoordinates,tooltipContent, andcontent;relationship_pointexposesglobe_idandglobe_id_select -
Metadata responses now preserve raw
metaconfig and addnormalized.fieldsplusnormalized.rest_meta_keys -
Normalized field discovery flattens nested Codestar fields into explicit paths such as
points_info.coordinates.latitude -
Normalized REST roots expose writable REST meta keys, serialized status, and JSON-schema-like types for MCP clients
-
Added MCP ability tests for meta field aggregation, empty fields, REST errors, and no-model cases
-
Phase 3 progress: 5 items completed, 5 items skipped
-
Removed local stdio MCP server: WordPress 7.0 Abilities is the adopted MCP integration path
-
Skipped SSE transport: Serve MCP over HTTP for remote connections
-
Skipped Multi-site management: Named site profiles, switchable at runtime
-
Skipped Role-based access: Map MCP tool access to WP user roles
-
Health monitoring: Endpoint with version, error rate, latency stats
-
Skipped Configuration profiles:
--profile=high-volume,--profile=strict -
WP7 ability errors now return
WP_Errordirectly from the WordPress-native runtime -
Caching layer: CacheInterface + TransientCache integrated into WP7 ability execution
-
Rate limiting: Sliding-window RateLimiter throttles WP7 ability calls (default 60/60s)
-
Audit trail: AuditLogger writes WP7 ability records to the Saltus MCP audit table
-
Config: WordPress filters control cache, rate limit, and audit behavior
-
38 new PHPUnit tests (243 total, 696 assertions) covering all 4 Phase 3 features
-
PHPStan Level 7 clean across all new MCP code
-
MCP stdio-only error wrapper removed with the standalone server path
-
Code review: Config constructor refactored to array bag pattern (#49 — medium)
-
Code review: stdio-only MCP error wrapper removed with old server path
-
Code review: RateLimitResult split into own file (#49 — low)
-
Code review: Unused getDefaultMessage() removed (#49 — low)
-
Defensive code review fix pass: 6 files updated — invalid item payload guard in ReorderPostsService, WP_Error handling after rest_do_request in AbilityRuntime, OBJECT output format support in WpdbAuditDatabase, explicit get_settings/reorder_posts permission checks in AbilityDefinitionFactory, repeater sub-field schema exposure in MetaFieldProvider, and cutoff timestamp millisecond fix in AuditLogger @since 2026-07-04
-
Code review follow-up: replaced unsafe property_exists with get_object_vars in MetaFieldProvider::get_model_args to align with ModelRestPolicy pattern; widened catch from \Exception to \Throwable in SaltusSingleExport::export_post for PHP 7+ Error type resilience — 2 commits @since 2026-07-05
-
Phase 5 planned and added to ROADMAP.md — 4 sub-tracks: 5A (Blocks), 5B (WP-CLI), 5C (Frontend), 5D (Docs). Implementation starting with 5A + 5D. @since 2026-07-05
-
Code review fixes: cache only cleared on non-GET requests in AbilityRuntime; added integer type support in Validator; moved null check before try block in AssetLoader — 3 commits @since 2026-07-05
-
Model interface hardening: added get_options(): array and get_args(): array to Model interface; removed fragile method_exists + get_object_vars fallbacks from ModelRestPolicy, ModelsController, and MetaFieldProvider; updated all anonymous Model implementations in test files — 5 commits, 13 files @since 2026-07-05
-
Replaced hardcoded tester.php with proper PHPUnit container integration tests in tests/Integration/ContainerIntegrationTest.php — 1 commit @since 2026-07-05
-
Code review feedback round 2: removed static clear guard from TransientCache to avoid stale cache in long-running processes; replaced fragile strict array comparison in SettingsManager with database re-read to prevent false-positive rest_update_failed errors; switched export SQL detection from regex to WP_Query var inspection via posts_request filter; set explicit UTC timezone in AuditEntry DateTimeImmutable to fix incorrect timestamps — 5 commits @since 2026-07-06
-
Code review gemini-code-assist round 1: replaced direct $model->name access with check_method() helper in ModelsController to avoid fatal errors on private/protected properties; added added_option and deleted_option hooks to MCP cache-clearing list to flush caches on option creation and deletion; replaced sanitize_key() with case-preserving preg_replace() in SettingsManager to avoid breaking camelCase settings keys; replaced ISO 8601 datetime format with MySQL-compatible format in AuditEntry and AuditLogger to prevent "Truncated incorrect datetime value" warnings — 4 commits, 8 files @since 2026-07-06
-
FilterAwareTrait extracted from 5 identical
filter()private methods in RateLimiter, HealthController, AbilityRuntime, AuditLogger, TransientCache — shared trait applied across MCP infrastructure @since 2026-07-06 -
REST route registration bug fix:
is_needed()gate bypassed for RestRouteProvider/ToolContributor registries via two-pass approach inCore::register_services()— REST routes now appear in WP-REST index even whenREST_REQUESTis undefined during plugin boot @since 2026-07-06 -
ServiceContainer::instantiate_unconditionally() added for bypassing Conditional gates @since 2026-07-06
-
MCP contributors() fallback preserves backward compatibility when MCP is instantiated outside Core @since 2026-07-06
-
AuditDatabase::prepare() added to interface and WpdbAuditDatabase for safe SQL parameterization @since 2026-07-06
-
Validator::is_list() helper added for type checks @since 2026-07-06
-
Test suite fixed and passing: 214 tests, 605 assertions — AuditLogger DAY_IN_SECONDS fallback, ExportController export_wp echo fix, wpdb prepare %s quoting, MCPFeatureTest contributor fallback, RestRegistrationTest modeler mock injection @since 2026-07-06
-
@covers annotations added to all test classes (26 test files) @since 2026-07-06
-
MCP error hints: actionable
hintkeys added to every WP_Error$dataarray across 7 REST controllers (HealthController, ExportController, DuplicateController, ModelsController, MetaController, ReorderController, SettingsController) and MetaFieldProvider — 5 commits @since 2026-07-07 -
Permission delegation: ToolInterface::has_permission() added; RestTool default + 13 per-tool overrides; AbilityDefinitionFactory::can_use_tool refactored to delegate to per-tool has_permission — 2 commits @since 2026-07-07
-
MetaController PUT route:
update_item+update_item_permissions_checkatPUT /saltus-framework/v1/meta/{post_type}/{post_id}with serialized meta merging; UpdateMetaFields MCP tool and MetaControllerTest + UpdateMetaFieldsTest added — 1 commit @since 2026-07-07 -
Test suite: 226 tests, 639 assertions (bumped from 214/605 by +12 tests, +34 assertions for new MCP tool, MetaController PUT, and count updates) @since 2026-07-07
-
ModelsController: use
check_methodfor description property access to prevent PHP 8.2+ dynamic property deprecation notices @since 2026-07-07 -
MCP namespace config filterability: added MCPConfig utility class with 3 WordPress filters (saltus/framework/mcp/namespace, saltus/framework/mcp/ability_category, saltus/framework/mcp/ability_prefix); added mcp_route() helper to RestTool base; refactored 21 source files from hardcoded strings to MCPConfig calls; added MCPConfigTest with 13 test cases — 6 commits, 236 tests, 655 assertions @since 2026-07-08
-
MCP/REST capability gating refactored: added get_config() to Model interface; added McpPolicy class with 14 test cases for MCP-specific mcp_tools/show_in_mcp gating; refactored ModelRestPolicy from saltus_rest array to per-feature config-section model; updated REST controller error hints; updated all existing tests for new config-section pattern — 7 commits, 250 tests, 669 assertions @since 2026-07-08
composer testpasses; Composer still prints a dependency deprecation notice fromjustinrainbow/json-schemaunder PHP 8.5.4.composer phpcspasses.- PHPStan: Level 7 clean across the configured analysis set (new service classes ReorderPostsService, MetaFieldProvider, SettingsManager added).
- WP7 Abilities is the MCP direction. Local stdio server was removed; SSE transport and standalone packaging are skipped.
- Standalone stdio MCP server removed; WP7 Abilities now owns MCP execution with WordPress-native audit, rate limiting, and transient caching.
- Metadata discovery is implemented through
saltus/list-meta-fieldsandsaltus/get-meta-fields. list_meta_fieldscallsGET /saltus-framework/v1/metaand returnspost_types.get_meta_fieldscallsGET /saltus-framework/v1/meta/{post_type}and returns one CPT's rawmetaplus normalized field paths and REST meta keys.- Service extraction completed 2026-07-03: SaltusSingleExport, MetaFieldProvider, ReorderPostsService, and SettingsManager are now shared between REST controllers and MCP tools via constructor injection. Feature classes (DragAndDrop, Meta, Settings, SingleExport) own the service instances and pass them to both paths, eliminating code duplication.
- Current verification: full
composer test(208 tests, 598 assertions),composer phpstan,composer phpcs, andgit diff --checkpass after the service extraction pass.