1052 Commits
Author SHA1 Message Date
John Smith 914088ff92 feat(abilities): enhance schema compat, user meta, e-commerce meta, and creator pipeline
- fix(schema-compat): prefer 'string' in non-null scalar unions to fix SanitizeSchemaUnionItemsTypeTest
- fix(content): define featured_image output properties and return resilient empty object structure for posts without thumbnails
- feat(content): add get_allowed_protected_meta() with WooCommerce and paywall whitelist
- feat(user): add sanitized meta support to create-user, update-user, and get-user with privilege escalation guard
- feat(database): support 'query' argument alias in emcp-tools/query
- feat(woo): expand create/update-product with author/vendor ownership, virtual/downloadable, prices, categories, tags, and meta; add list-vendors
- test: add 14 new automated unit tests across User, Content, Woo, and Database suites
2026-09-12 17:59:29 -04:00
John Smith 0f1f6ea2a2 fix(abilities): stop 'Ability not found' notice from get_active_ability_names
get_active_ability_names() probed wp_get_ability('emcp-tools/list-pages')
merely to trigger the lazy Abilities API init. wp_get_ability() routes
through WP_Abilities_Registry::get_registered(), which fires a
_doing_it_wrong() 'Ability not found' notice whenever the probed ability
is conditionally absent — list-pages is Elementor-gated, so on a site
without Elementor every admin-bar render logged it.

Trigger the init with the silent wp_has_ability() instead, and use the
same silent existence check for the core-ability guards in
register_mcp_server() and the dispatcher. resolve_ability() now fails
closed via wp_has_ability() before wp_get_ability().
2026-09-12 17:04:24 -04:00
John Smith 460afbadce fix(admin): stop the plugin deactivating itself, and 403ing on activation
Two fork-specific defects made "Activate" a dead end, ending at core's
"Sorry, you are not allowed to access this page." (403).

1. Self-deactivation. `.emcp-pro` is committed, so the build counts as
   premium, and the premium guard retired `$emcp_tools_free_basename` --
   which on the documented layout (wp-content/plugins/heretek-control-core)
   IS this plugin. The first admin_init after activation deactivated the
   site's only working copy. emcp_tools_retire_sibling() now refuses its own
   basename, and sibling candidates inside our own folder are filtered out
   (the same file loaded twice is deduplicated by require_once, so retiring
   it can only ever switch the plugin off). Legacy folders -- emcp-tools/,
   elementor-mcp/ -- are still retired whichever build runs.

2. Freemius owned the activation flow. Its post-activation redirect
   (class-freemius.php:24546) is the only code in the plugin that builds
   admin.php?page=emcp-tools, a URL that exists only if the bootstrap
   finished; its _prepare_admin_menu also replaced our dashboard with the
   opt-in/connect screen on a site that has never been connected. The fork
   hard-codes every licensing answer to "unlocked", so both are dropped:
   `redirect_on_activation` is filtered off and the _prepare_admin_menu hook
   is removed.

When neither the real menu nor anything else owned the `emcp-tools` slug,
WordPress core ended the request from wp-admin/includes/menu.php -- which
runs during admin_menu, BEFORE admin_init -- with that 403 and no
explanation.

New EMCP_Tools_Admin_Fallback (includes/admin/class-admin-fallback.php)
makes the slug always resolve. At the end of admin_menu it registers a
diagnostics page when nothing else claimed the slug (a no-op on a healthy
install), and admin_page_access_denied bounces emcp-tools-* sub-screens
there instead of letting core kill the request. The page reports boot
state, MCP adapter resolution, PHP/WordPress versions, other active copies
of the plugin, and a file-integrity check that flags 0-byte files -- the
issue #100 signature of a host malware scanner emptying a file in place so
require_once succeeds while nothing is declared.

Also: the release workflow still packaged the zip under `elementor-mcp/`,
the legacy folder name this plugin's own conflict guards look for. Release
assets are now built under `heretek-control-core/`.
2026-09-12 16:51:55 -04:00
John Smith 8ab6b50260 build(wporg): rebrand plugin to Heretek Control Core for WordPress.org compliance
- Establish heretek-control-core.php as canonical main plugin bootstrap
- Convert emcp-tools.php to non-conflicting backward-compatibility forwarder
- Update readme.txt header and tagline removing trademarked terms per Rule 17
- Update bin/build-wporg-zip.sh to package slug heretek-control-core
- Regenerate assets-wporg banners and icons with HCC / Heretek Control Core branding
- Rebrand admin interface, menu items, and headers to Heretek Core / Heretek Control Core
- Update composer.json, release tooling, and README.md
2026-09-05 15:38:15 -04:00
John Smith 23b12d73b9 fix(admin): neutralise core table stretching on History tab ledger 2026-09-05 15:28:55 -04:00
John Smith 8a0bea9893 fix(build): exclude shell scripts and developer configs from WordPress.org release zip 2026-09-05 15:16:33 -04:00
John Smith 24e92dc82c build(wporg): standardize manifest, generate assets, and add release packager for WordPress.org 2026-09-05 11:30:02 -04:00
John Smith 3d03f09124 refactor(admin): standardize interface labels and docs to official professional terms 2026-09-05 11:23:28 -04:00
John Smith 80ca8741d5 feat(ads): add ad monetization ability engine, exoclick api integration, skills, and tests 2026-09-05 11:23:24 -04:00
John Smith bf93cc08bf feat(comic): add featured_image and featured_image_url with attachment fallback to comic read ops 2026-09-04 19:11:49 -04:00
John Smith 5c4606fc77 emcp-tooling 2026-09-03 19:06:59 -04:00
John Smith 69267182df emcp-tooling 2026-09-03 18:06:15 -04:00
John Smith 17bacc7135 chore(release): 3.16.1 — AI Chat settings card layout hotfix v3.16.1 2026-09-03 13:26:21 -04:00
BillyOutlast 0228e4948a Merge pull request #5 from Heretek-AI/fix/ai-chat-formtable-reset
fix(admin): reset .form-table under any EMCP admin form
2026-09-03 13:24:01 -04:00
John SmithandClaude e11581e9ef fix(admin): reset .form-table under any EMCP admin form
Belt-and-braces reset for the WordPress core .form-table rules (forms.css /
common.css ship border-collapse: collapse; margin-top: .5em; width: 100%;
clear: both;) which, combined with an inherited flex stretch on the form,
can let the form table pull its parent's height instead of its cells'.

The form-level reset in #4 already nails the form itself; this kills the
table as a candidate for the same kind of stretch. Scoped to .elementor-mcp-admin
so nothing leaks outside admin pages.

Co-Authored-By: Claude <[email protected]>
2026-09-03 13:23:49 -04:00
BillyOutlast d579566090 Merge pull request #4 from Heretek-AI/fix/ai-chat-form-reset
fix(admin): belt-and-braces form reset so the AI Chat settings form isn't stretched
2026-09-03 13:20:44 -04:00
John SmithandClaude 024e736dd9 fix(admin): belt-and-braces reset for inline forms (anchors height/display)
A wholesale reset on every form inside any EMCP admin page so no ancestor
can stretch it past its content height: min-height: 0 !important,
height: auto !important, display: block. The AI Chat settings page
wrap-only rule from #3 was necessary but not sufficient — the stretch came
from an inherited rule (wp-admin/css/common.css in WP 7.1 uses
form { display:flex; flex-direction:column } combined with the shell's
min-height: calc(100vh - 32px), which resolved the inline form to
~1700 px on a tall page even with the wrap flush.

This scoped override does not affect non-admin pages (the selector is
gated by .elementor-mcp-admin) and is intentionally !important so it
defeats an inherited core style with the same specificity instead of
needing deeper !important chains for every ancestor.

Co-Authored-By: Claude <[email protected]>
2026-09-03 13:20:16 -04:00
BillyOutlast 8f5f03a9d2 Merge pull request #3 from Heretek-AI/fix/ai-chat-settings-layout
fix(admin): tighten AI Chat settings card so controls don't read as stranded
2026-09-03 13:11:57 -04:00
John SmithandClaude da48dbe4ff fix(admin): tighten AI Chat settings card so controls don't read as stranded
The AI Chat settings page is one short form; with the shared .tab-content
padding/margin it sat at the top of a tall card and the form rows landed
near the bottom of the visible viewport at 100% zoom — looking like the
controls were dropped below where they should be.

Make the .elementor-mcp-ai-chat wrap flush (transparent bg, no padding/
margin/border) on top of the existing .tab-content card, tighten the h2
and description spacing, and leave the form's existing 650px max-width
alone so the controls sit high in the viewport at any zoom.

Co-Authored-By: Claude <[email protected]>
2026-09-03 13:09:13 -04:00
BillyOutlast 8bd248e56b Merge pull request #2 from Heretek-AI/feature/migrate-targets-scoped-sync
feat(migrate): paired targets, scoped sync, push/sync admin, url-search-replace tool
2026-09-03 12:41:29 -04:00
John SmithandClaude d8b6c458c6 fix(migrate): confine archive paths to the backups dir (S2083 path-traversal taints)
push_packets()/finalize() now refuse any archive outside this site's backups
dir (Packager::archive_path()/create_archive() already enforce this; the guard
is defense-in-depth at the sink). The packager's directory walk keeps its
NOSONAR with the confinement rationale on the flagged line. Clears the three
phpsecurity:S2083 blockers that regressed the Sonar security rating to 5.

Co-Authored-By: Claude <[email protected]>
2026-09-03 12:37:59 -04:00
John SmithandClaude 431556842a fix(migrate): address CodeRabbit review — replay protection, prefix guard, poll deadline
Security:
- pair/issue + verify signatures now bind a per-request ts + single-use nonce
  (canonical 'pair|issue|<ts>|<nonce>' / 'verify|<ts>|<nonce>'); the connector
  rejects stale timestamps (+-300s) and replayed nonces (capped store), and the
  plugin's verify_endpoint() signs the same canonical, so a captured signature
  cannot be replayed to mint/verify pairing codes.
- Loopback decision for the secret-carrying exchange is now server-side
  (home_url() host + SERVER_ADDR), never the client Host header.
- The connector admin secret is stored verbatim (wp_unslash only) — no
  sanitize_text_field rewriting bytes used for HMAC.

Correctness:
- push_archive() defaults poll=true again (migrate-site/admin-push report the
  true destination job state) and poll_job() enforces a ~60s wall-clock
  deadline with per-request capped timeouts.
- Cross-prefix restores fail closed: manifests record db_prefix; source restore
  and the connector refuse with prefix_mismatch instead of importing
  foreign-prefixed tables.
- sync-to-live scope schema accepts 'all'/'none' or lists, and the description
  no longer claims empty arrays mean full sync; scope file-root manifest keys
  use the intended root_label for numeric keys.
- Targets store computes+validates the cipher before insert (no bare-IV rows);
  packager add_root_files() realpath-checks containment so a symlink cannot
  exfiltrate outside wp-content.

Admin UI:
- Push form wraps build/existing archive groups in the emcp-push-build /
  emcp-push-existing classes migrate.js toggles (the toggle was previously dead)
  and adds a "-- none --" destination option so raw URL+secret pushes work.

Co-Authored-By: Claude <[email protected]>
2026-09-03 12:32:13 -04:00
John SmithandClaude 130aa5a334 fix(migrate): cut duplication — shared archive + verify helpers
Dedupe the push/verify paths that existed in both the MCP abilities and the
admin module: EMCP_Tools_Migration_Engine::archive_for_push() now owns the
build-or-reuse-an-archive logic (used by migrate-site and the admin Push tab),
and EMCP_Tools_Migrate_Targets::verify_endpoint() (now public) backs the admin
Verify-target action instead of a hand-rolled request block.

Co-Authored-By: Claude <[email protected]>
2026-09-03 12:20:31 -04:00
John SmithandClaude f32d5a6668 fix(migrate): address SonarCloud findings on the migrate/connector work
Gate: clear the web a11y bugs on the new admin surfaces — labelled inputs +
ids in page-migrate.php (raw URL/secret fields, archive select) and the
connector settings page, which also drops its layout-table/th markup.
Duplication: fold the abilities + module destination resolvers into one
EMCP_Tools_Migration_Engine::destination_from_input() (the MCP tools and the
admin now share identical validation).

Code smells: sync_to_target/file_root_path/redeem_pairing_code/add_files/
execute_url_search_replace split into smaller helpers; unused params removed
from the connector pair/verify REST handlers and the scope-capability check;
"SELECT * FROM " literal const'd in the targets store; JS uses .dataset +
optional chaining; nested ternaries flattened.

Co-Authored-By: Claude <[email protected]>
2026-09-03 12:15:45 -04:00
John SmithandClaude 7d899d8a78 feat(migrate): paired targets, scoped sync, push/sync admin, url-search-replace tool
- EMCP_Tools_Migration_Engine: shared transfer engine — the four private
  helpers that lived in the migrate abilities moved here verbatim
  (push_packets/finalize/poll_job) plus push_archive orchestration.
- EMCP_Tools_Migrate_Targets: {prefix}emcp_migrate_targets store, encrypted
  secrets (never returned), single-use pairing-code redemption. Connector is
  now 1.2.0: adds /pair/issue, open /pair/exchange (HTTPS-gated), /verify, a
  settings page that issues codes, and advertises scope-restore.
- EMCP_Tools_Sync_Engine + Packager scope opts: full/selective .emcp sync
  archives (db all|none|tables[], file_roots all|none|roots[]) with additive
  scope+kind manifest keys (absent scope = full; format_version stays 2).
- Scope-aware restore on both sides: search-replace gated on a real DB import
  and restricted to archived tables; connector no longer errors on DB-less
  (files-only) archives.
- MCP surface: migrate-site gains optional target_id (raw remote_url+secret
  back-compat kept); sync-to-live is now the documented scoped push; new
  url-search-replace tool carries the old local search-replace body
  (disabled-by-default via DEFAULTS_VERSION 37, drift-guard + catalog wired).
- Admin: Backup & Migrate tab split into Archives | Push to Site | Sync with
  paired-target add/delete/verify + blocking push/sync handlers; adds
  assets/js/migrate.js and pro-manifest entry.
- Tests: migrate/packager assert suite extended (scope normalization, root
  traversal guards, scoped archive manifests, files-only has no DB dump).

Co-Authored-By: Claude <[email protected]>
2026-09-03 11:57:20 -04:00
BillyOutlast c09addb968 Merge pull request #1 from Heretek-AI/feature/pro-backup-migrate-rebuild
feat(migrate): real backup/restore/sync engine + HMAC connector, AI Chat hygiene
2026-09-03 10:50:06 -04:00
John SmithandClaude d6a93ceb5b fix(migrate): address CodeRabbit findings on the backup/migrate/restore flow
Code-review findings verified against the current code; only still-valid issues
fixed, minimal churn, no .emcp-format or push-protocol changes.

- migrate-site: schema now accepts direction "pull" so the explicit
  unsupported error is reachable (matches the docs); a restore is reported as
  success only when the destination job state is "done" — pending/unknown/
  queued return a WP_Error carrying the job details.
- search-replace engine: walk_table() with before_cap=0 no longer sets
  partial (no before-image capture is not truncation).
- connector: hashless archives (no database_sha256) now import instead of
  failing integrity; import statement errors stay under db stats (non-fatal)
  so a partial import still gets the URL rewrite, while stream/hash failures
  remain fatal and drive the job state; destination URL is captured before the
  import replaces wp_options; rewrite_rows/search_replace report partial when
  the per-table cap is hit so a run can never silently claim done.
- restore engine: destination URL captured before import; hash-mismatch abort
  no longer double-closes/cleans (the finally block owns cleanup); DB stream
  extraction requires a successful stream_copy_to_stream and closes handles on
  every failure path.
- packager: list_archives() no longer hashes every archive (full read per row
  on a plain listing); create_archive validates addFile/addFromString/close and
  removes a partial archive on failure; default filenames gain a random suffix
  and the backups dir gets .htaccess/index.html web-denial guards.
- search-replace wrapper guards on the engine class existing.
- migrate module: drains output buffers before streaming binary downloads.
- tests: extended harness with a walk_table before_cap=0 case (9 suites green).

Co-Authored-By: Claude <[email protected]>
2026-09-03 02:02:54 -04:00
John SmithandClaude 1bc1de23db fix(sonar): harden connector transfer path + reduce engine complexity
Addresses the first SonarCloud analysis on PR #1 (128 new-code findings).
Genuine issues are fixed in code; convention/style rules (camelCase naming
php:S100/S101/S116, too-many-returns php:S1142) and the standalone test
harnesses are handled via the SonarCloud profile + sonar-project.properties
because snake_case + WP_Error guards are the WordPress conventions here.

Security:
- connector: transfer ids are now whitelisted ([A-Za-z0-9_-]{8,64}) and
  rejected before any path use; the residual S2083 path-build findings (the
  resume-keyed store must use the id) carry NOSONAR + rationale after the HMAC
  gate + strict validation.

Complexity (php:S3776) - extracted helpers so no function sits far over the
raised threshold:
- connector: search_replace -> data_tables/text_columns/rewrite_rows;
  restore_archive -> restore_db; import -> run_dump_statement.
- migrate-abilities: execute_migrate -> push_archive_packets/packet_error/
  push_finalize/poll_job.
- db-importer: run_statement helper (per-statement execution shared with the
  trailing no-';' fragment).
- restore-engine: restore() -> restore_database(); append_log() dropped its
  unused $filename parameter.
- char-state-machine extractors (extract_statement x2) carry NOSONAR + rationale.

Other:
- packager: .emcp extension -> const EXT; add_files split into file_iterator/
  dir_is_skipped/zip_relative_name.
- db-exporter: removed unused $col_ph.
- migrate module: single-arg nonces (WP default _wpnonce, matching the view),
  page-URL helper, dropped unused $back params.
- page-migrate view: single-arg wp_nonce_field().
- restore-engine + serialized-search-replace: tabs -> spaces.
- sonar-project.properties: exclude tests/** + vendor/** (test harnesses mirror
  WP core function names by design).

Tests: tests/test-migrate-packager.php 8 suites still green; php -l clean.

Co-Authored-By: Claude <[email protected]>
2026-09-03 01:38:17 -04:00
John SmithandClaude 448e46ff18 feat(migrate): real backup/restore/sync engine + HMAC connector, AI Chat hygiene
The fork's Pro merge left Backup/Restore/Migrate/Sync as placeholders (4 naive
files): no restore path, migrate-site was a canned-success stub, sync-to-live
touched only wp_options, and the connector exposed only a /status route. This
makes the story real at a bounded scope and fixes the wiring/doc drift found in
a feature-parity review against upstream Pro.

- search-replace engine: byte-accurate serialized fixer (length-delta, never
  unserializes), JSON escaped+unescaped URL pair replace (_elementor_data), and
  a site-wide table walker; legacy EMCP_Tools_Search_Replace now delegates.
- backups: streamed DB export (bounded chunks, explicit-column INSERTs), richer
  .emcp manifest (format version, site_url, php/wp/db, DB sha256 + row stats),
  opt-in include_files bundling of uploads/plugins/themes.
- restore: hardened statement-aware importer (skips transaction-control
  directives, ';'-in-string safe); new Restore_Engine (hash-verified -> import
  -> URL rewrite -> traversal-guarded file placement); admin Restore/Download/
  Delete + restore-history panel (nonce + manage_options, admin-only).
- migrate-site: real push to a standalone HMAC connector (2 MB signed packets ->
  assemble -> verify -> self-contained restore -> pollable job). confirm:true
  required; direction "pull" returns unsupported.
- sync-to-live: real site-wide serialized-safe URL search-replace across
  options/posts/postmeta/comments/term+usermeta + prefixed tables, ledger-
  recorded for History rollback.
- remove 3 never-registered ghost tools (list-syncable-changes,
  sync-content-item, discard-sync-change) from catalog/slugs/seeding.
- AI Chat: canonical module id 'ai-chat' (admin toggle now works, legacy
  ai_chat read-back), /emcp/v1/chat route gated on module state, default on.
- docs: correct README/readme.txt over-claims (WooCommerce op list, addon slugs,
  atomic wording, SEO/forms counts), tidy pro-manifest.txt; bump 3.16.0.

Tests: extended tests/test-migrate-packager.php (8 suites, all passing) covering
byte-accurate SR, export/import round trip, directive-skip, quote-safe split,
and packager create/read/list/delete.

Co-Authored-By: Claude <[email protected]>
2026-09-03 01:09:03 -04:00
John Smith 1f64a65608 docs: overhaul README and update repo references to heretek-control-core
- Overhaul README.md with Adeptus Mechanicus / Heretek Control Core theme and updated badges
- Update REPO constant in class-github-updater.php to Heretek-AI/heretek-control-core
- Update Plugin URI in emcp-tools.php and help URLs across class-admin.php and page-dashboard.php
- Update clone and issue links in CONTRIBUTING.md
2026-09-03 00:25:52 -04:00
John Smith aa40a581f9 fix(freemius): disarm update hijacking and rebrand to Heretek Control Core
- Neutralize Freemius update hooks in class-freemius-abstract.php and class-fs-plugin-updater.php
- Add admin_init cache purge for stale Freemius update notices on update-core.php
- Rebrand plugin to Heretek Control Core: Unlocked Machine Rites
- Update admin menu to Heretek AI and transform submenus (Cogitator Deck, Machine Rites, Noosphere Uplink, Cyber-Theurgy, STC Archives, Engram Memory, Canticle Library, Adept Doctrines)
- Update app bar header to HERETEK CONTROL CORE with ARCH-HERETEK UNLOCKED badge
- Update help menu to Omnissiah Archives and drawer to Vox Transmissions
2026-09-03 00:07:33 -04:00
github-actions[bot] 64561e65a6 chore(release): bump version to 3.15.0 v3.15.0 2026-09-03 03:59:40 +00:00
John Smith 53e13043b8 feat(ci): add manual release workflow with decimal version rollover
- Add bin/release.mjs with getNextVersion rollover (+0.0.1 where 0.0.9 -> 0.1.0)
- Add bin/release.test.mjs unit test suite for versioning
- Add .gitattributes to exclude tests and development cruft from release archives
- Add .github/workflows/release.yml for manual workflow_dispatch releases with ZIP asset publishing
2026-09-02 23:57:46 -04:00
John Smith 95ca38e591 fix(theme): eliminate dark-on-dark headings, theme postboxes, widefat tables, and form controls
- Broaden CSS custom properties to :root and body shells
- Enforce pure white color (#ffffff) on all h1-h6 headings across all EMCP screens
- Theme WordPress postboxes to dark metal cards (#111116) with dark headers (#16161d) and white titles
- Theme widefat and wp-list-table with dark zebra striping and high-contrast links
- Style all form controls (input, select, textarea) and buttons to Blood & Steel palette
- Elevate description text to readable #a1a1aa and labels to #ffffff
- Remove nested .wrap classes in page-migrate.php and page-memory.php
- Bump EMCP_TOOLS_VERSION to 3.14.5
2026-09-02 23:40:45 -04:00
John Smith b2fb9f0074 fix(layout): eliminate horizontal overflow and admin sidebar drift
- Set display: none on closed emcp-notif-drawer to remove it from layout calculation
- Remove backdrop-filter containing-block trap on .emcp-appbar
- Eliminate legacy negative margins on .elementor-mcp-stats
- Enforce overflow-x: hidden / clip across html, body, #wpwrap, and #wpcontent
- Normalize #wpbody-content to float: none and width: auto
- Bump EMCP_TOOLS_VERSION to 3.14.4
2026-09-02 23:25:57 -04:00
John Smith 1e19fe26b7 fix(theme): improve contrast on low-mode card, AI chat, context preview, and redirects
- Bump EMCP_TOOLS_VERSION to 3.14.3 and use filemtime for instant asset cache-busting
- Add is_emcp_screen helper in class-admin.php to ensure assets enqueue on all submenus
- High-contrast pure white typography and dark metal surface on elementor-mcp-low-mode-card
- High-contrast styling for form-table on AI Chat tab (white labels, readable descriptions, dark inputs)
- Deep obsidian pre/code background with bright monospace text on elementor-mcp-context-preview
- Lock notification drawer with visibility:hidden, opacity:0, and pointer-events:none when closed
- Replace inline #fff styles in page-redirects.php, page-marketplace.php, and page-pro-upsell.php with dark theme cards and tables
2026-09-02 23:12:06 -04:00
John Smith 139b416a11 fix(admin): dock app bar flush to wpadminbar and apply dark canvas theme
- Eliminate 10px light gap between wpadminbar and emcp-appbar
- Reset .wrap.elementor-mcp-admin margins and padding to 0
- Add admin_body_class hook to inject emcp-admin-page emcp-theme-dark
- Paint wpcontent, wpbody-content, and wrap canvas with #09090b Obsidian Void
- Re-theme remaining white sub-cards, filters, disclosures, notices, and footer to dark steel
2026-09-02 22:36:10 -04:00
John Smith 4535bea933 feat(dashboard): remove video guides clutter and EMCP Cloud marketing banners
- Remove Featured video guides section and YouTube tutorial embeds from the dashboard
- Remove EMCP Cloud and Pro marketing sidebar cards from the dashboard
- Remove sticky rotating announcement marquee bar advertising Cloud and LTD
- Remove app-bar Cloud connection nag button
- Refactor Explore your toolkit and Help & resources into clean full-width responsive grids
- Unlock settings sync entitlement and remove paid cloud upgrade prompts
2026-09-02 22:16:55 -04:00
John Smith bb938bdd33 feat(branding): overhaul visual identity to Heretek Blood & Steel theme
- Import Heretek master logo (logo.png) from Heretek-AI/ProxmoxVE
- Generate scaled 96x96 (icon-sm.png) and 32x32 (icon-xs.png) RGBA icons
- Bundle self-hosted Cinzel-Bold.woff2 for offline gothic-tech typography
- Overhaul admin.css and ai-chat.css with dark steel void surfaces and crimson blood accents
- Port signature Heretek graphical effects (machine-icon glow, blood borders, corruption glow, circuit pulse, custom scrollbars)
- Update admin badge to HERETEK UNLOCKED and refresh documentation
2026-09-02 21:57:40 -04:00
John SmithandClaude 9610fc76ad fix(comic): expose per-operation argument schema on the comic dispatchers
LobeHub (and other) agents kept failing to call emcp-tools/comic-write
because its "scheme" was invisible: the static schema exposed only an
unconstrained operation string plus an opaque free-form arguments object,
and comic-write uniquely marked operation as REQUIRED, so the documented
"call with no operation to list the catalog" discovery call was blocked at
the schema level. The hand-maintained runtime catalog had also drifted from
the executors, omitting status (which defaults to publish), date, author,
taxonomies, content_warning, and comic_html_above/below — exactly the facts
agents were guessing at.

- comic-write no longer requires operation, so the empty-op discovery call
  is legal; both tools' operation property now carries an enum of the real
  operation names.
- Add op_schema() to the read and write operations classes as the single
  source of truth (typed JSON Schema + a realistic example per op). The
  discovery catalog is generated from it — each entry keeps the flat
  arguments hints and gains typed schema + example — so the docs can never
  drift from the executors again.
- Tool descriptions now state the discovery flow and the create-comic
  contract (status defaults to "publish", date backdating, image flow,
  author).
- Clarify in both emcp-comic-easel SKILL.md files that imported strips must
  always pass "status": "draft" explicitly, since the tool's own default is
  publish.
- Tests: new schema-exposure suite (no required operation, enum == spec
  keys, catalog schema+example, status default/fields exposed, and a parity
  guard pinning every executor field to the spec). All 8 suites pass.

Co-Authored-By: Claude <[email protected]>
2026-09-02 15:45:19 -04:00
John SmithandClaude 147365bafa fix(sandbox): complete EMCP_Tools_Block_Store API to stop the page=emcp-tools-widgets fatal
The Sandbox admin page fatals on shad-base.com with
"Call to undefined method EMCP_Tools_Block_Store::user_has_access()"
(views/sandbox/overview.php:41). The store loads eagerly so class_exists()
passes, but the class shipped by the unlocked port (9176dd7) was never given
the API its own views call — pagination commit b7cfe45 updated blocks.php and
the widget/snippet stores but not the block store.

Add the missing consumer-facing methods, mirroring the widget store and the
EMCP_Tools_Sandbox_Store base:
- user_has_access()   (overview.php:41, blocks.php:21, admin AJAX guards)
- summary()           admin-table row: block_id/block_name, publish->active
- list_blocks()       overview card counts
- list_blocks_page()  blocks.php table via EMCP_Tools_Sandbox_List_Query
- get_asset()         block.json/render.php code viewer (whitelisted)
- create_block()      fixes latent fatal in apply_bundle() (bundle import)
- uninstall_cleanup() uninstaller.php:77

Harden create()/update()/compile() with a class_exists guard on the deferred
EMCP_Tools_Block_Generator (matches class-widget-store.php:372).

New tests/test-sandbox-blocks.php: 7 suites — method presence, user_has_access
gate, summary mapping, overview.php render smoke (the previously-fatal file),
get_asset whitelist round-trip, apply_bundle->create_block draft import, and
list_blocks_page shape. All pass; migrate/comic/skills suites still green.

Co-Authored-By: Claude <[email protected]>
2026-09-02 14:34:34 -04:00
John Smith a2149de1fe feat(skills): add complete Agent Skills bundle including Comic Easel, performance, security, and 10 vertical packs 2026-09-02 14:05:02 -04:00
John Smith 51b3256ea7 fix(migrate): add ensure_packager fallback in class-migrate-abilities.php 2026-09-02 13:58:55 -04:00
John Smith fadea0060c fix(migrate): load EMCP_Tools_Packager and migrate engine classes to prevent fatal error 2026-09-02 13:58:33 -04:00
John Smith f73557df79 test(comic): add date preservation test for ISO 8601 twitter timestamps 2026-09-02 13:49:04 -04:00
John Smith ddf9318bf5 fix(comic): preserve original twitter publication date and GMT with edit_date=true 2026-09-02 13:48:28 -04:00
John Smith 74f87902bd fix(admin): use serverUrl in Antigravity direct HTTP connection config 2026-09-02 13:19:53 -04:00
John Smith bd56ed2cd2 fix(comic): decode HTML entities before parsing comic-html-below 2026-09-02 13:14:32 -04:00
John Smith 290ead0e64 feat(comic-easel): add Comic Easel MCP integration with multi-image strips and source tracking 2026-09-02 13:04:43 -04:00
John Smith 690eb55557 feat(ai-chat): add custom OpenAI-compatible endpoint and model support with test connection 2026-09-02 12:45:44 -04:00