Commit Graph
260 Commits
Author SHA1 Message Date
janniclas.loosenandClaude Opus 5.5 17402549c5 test: Task 7 review - broaden move/delete/duplicate coverage, fix outline for delete-only changes
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 15:47:01 +02:00
janniclas.loosenandClaude Opus 5.5 acd57c40c0 feat: lit/divi-move, lit/divi-delete, lit/divi-duplicate-node
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 15:38:38 +02:00
janniclas.loosenandClaude Opus 5.5 0fddece18d fix: Task 6 review round 2 - builder column classes, sum check only for exact rows, unknown path wins, column structure text (S43)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 15:31:05 +02:00
janniclas.loosenandClaude Opus 5.5 68ca4f45ec feat: Loosen-IT logo top right on the settings page
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 15:26:44 +02:00
janniclas.loosenandClaude Opus 5.5 909ac82594 fix: Task 6 review round 1 - admin label overlap, heading default level, structure deny-list, row widths (S41)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 15:26:12 +02:00
janniclas.loosenandClaude Opus 5.5 22bb1528db fix: S40 - short form and attrs on the same path refused for new nodes too
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 15:17:42 +02:00
janniclas.loosenandClaude Opus 5.5 110beb7698 feat: lit/divi-insert and lit/divi-update
All-or-nothing at ability level (S39), duplicate ids refused (S14),
set and attrs on the same path refused (S38), invalid_attr_path error.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 15:15:37 +02:00
janniclas.loosenandClaude Opus 5.5 b8cb01812e fix: Task 5 review round 1 - restore point inside the kses window, strict map field types (S37)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 15:08:48 +02:00
janniclas.loosenandClaude Opus 5.5 7762b76305 feat: Divi save pipeline – tree_rev lock, kses-safe save, revision, flags, cache, ToolResult
DiviSaver/DiviWriter/DiviComposition/DiviChange, WpValueSanitizer (S4),
WpMediaResolver, DiviFlags (S11), DynamicContentMap from Divi's live
registry (S22), S31 wiring, S35 control strip at apply() entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 14:56:47 +02:00
janniclas.loosenandClaude Opus 5.5 ea1fd607b2 feat: Divi tree editor and quality warnings
TreeEditor (position/insert/move/remove/duplicate on the BlockTree) and
Warnings (post-write quality checks), plus S18's outline breadth limit
on the 2a Outline/DiviOutlineAbility.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 14:42:26 +02:00
janniclas.loosenandClaude Opus 5.5 8688a02402 fix: Task 3 review round 1 - strip control chars before the sanitizer (S32a), S34 minors
Control characters now go on the raw value in AttrWriter::cleanNode and
VariableRef::setting; after the sanitizer only rejection remains ('<' + VT/FF
no longer turns into a tag). VALUE_KEY anchored with D, exact column-width
fractions, nested rows in columns, specialty columns refused, fullwidth by
catalog category, preset ambiguity in DesignSystem::modulePresetId().

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 14:26:18 +02:00
janniclas.loosenandClaude Opus 5.5 4b72c2bb42 feat: Divi composer – short/full form to blocks with structure rules, presets and labels
Labels, background_color and preset ids go through the choke point (S13);
ambiguous preset names fail with their ids (S13a); fullwidth + rows is an
error. Carry-ins: control characters stripped before the marker check (S32),
kind override may only tighten, reference alt texts dropped, color check via
VariableRef::typeOf (S33).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 14:15:33 +02:00
janniclas.loosenandClaude Opus 5.5 f86cd5b34a feat: Divi short-form writer
ShortformWriter routes every short-form string through AttrWriter::cleanValue()
with the curated field kind (new optional kind override), exposes the color
check for background_color and guards builder-only paths on removal too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 13:59:24 +02:00
janniclas.loosenandClaude Opus 5.5 4832ec1e10 fix: Task 1 review round 4 - meta keys checked after Divi's prefix derivation (S30)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:52:00 +02:00
janniclas.loosenandClaude Opus 5.5 665e603abe fix: Task 1 review round 3 - re-check $variable marker after sanitizing, meta-key rule
Critical-1/S28: sanitizers that strip <x>, NUL or %XX could rebuild the
$variable( marker after the raw check; every cleaned string (AttrWriter
at every depth, VariableRef settings) is checked again. S29: custom_meta_
map names and *meta_key setting values obey META_KEY. Minor-2: malformed
dynamic content maps fail with InvalidArgumentException.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:46:52 +02:00
janniclas.loosenandClaude Opus 5.5 eb99b360b4 fix: Task 1 review round 2 - custom CSS builder-only, no settings on gvid/font references
S26: every css.* path is gated like S7 for users without unfiltered_html.
S27: Divi ignores settings on global variable and theme font references,
so any settings there are rejected.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:39:36 +02:00
janniclas.loosenandClaude Opus 5.5 7180690611 fix: Task 1 review round 1 - escaped )$ in reference settings, allow map, routing rulings
I-1: reject )$ in every decoded string setting and in the re-serialized
JSON. S21: string settings cleaned and re-serialized. S22: injectable
dynamic-content allow map (name => setting => field type), loop_* only via
the map. S23: unknown content.innerContent is rich text. S24: keys below
scalar kinds are unknown, ...Url path segments are URLs. S25: isVariable
removed. M-1: real \u escapes in tests, malicious suite as editor, fixture
html() raw for unfiltered_html. M-2: S7 gate at any depth plus
css.advanced.customCss.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:37:56 +02:00
janniclas.loosenandClaude Opus 5.5 1ea2e16c49 feat: Divi placeholders, strict $variable references and full-form attribute writer
VariableRef parses, validates and re-serializes every $variable(...)$ value
(S1/S2/S12); AttrWriter routes strings by catalog kind incl. per-subName
composite kinds and key-name URL fallback (S3/S3a), rejects odd value keys
(S13) and Divi HTML/attribute fields without unfiltered_html (S7);
ambiguous design-system labels fail with their ids (S13a); R2 finding
recorded (S5).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:23:59 +02:00
janniclas.loosenandClaude Opus 5.5 c24b91d8a5 fix: anchor Divi name/id patterns at string end, number-advanced stays unknown, doc wording
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:16:20 +02:00
janniclas.loosenandClaude Opus 5.5 4356e69bb9 test: update divi-read-smoke.sh for node-get's short type name + rev
node-get's "type" is now the short module name ("heading"), matching
lit-divi-outline, instead of the namespaced "divi/heading"; the smoke test's
own hardcoded expectation is updated to match, and now also checks the new
post-level rev is present.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:12:50 +02:00
janniclas.loosenandClaude Opus 5.5 45dcd9176c fix: divi-node-get rev + short type, divi-outline id validation
- lit/divi-node-get now also returns the post-level rev (Rev::ofPost, same
  optimistic lock lit-content-update needs) next to tree_rev, and reports a
  node's type as the short name ("button"), matching lit-divi-outline instead
  of the namespaced "divi/button". description() notes that $variable(...)$
  values shown are re-validated when written, never taken over unchecked.
- lit/divi-outline validates its optional `id` input against the same
  path-ID pattern lit-divi-node-get uses (a malformed id is now a validation
  error, not a "not found"), and its outputSchema's per-node `required` list
  now includes info/presets/children, which are always present.
- NodeSummary::label() (the admin label shown in outlines and node-get)
  whitespace-normalizes and bounds its result via Text::shorten(), like every
  other summary string, instead of returning a raw, unbounded value.
- docs/superpowers/notes/.../etappe-2a-abnahme.md corrected: only a global
  module is "nur lesbar" - a specialty section is a normal, editable
  divi/section block; the outline just marks it "[specialty]".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:12:50 +02:00
janniclas.loosenandClaude Opus 5.5 73433ae862 feat: per-subName attribute-path kinds for composite Divi paths
lit/divi-catalog's path_kinds previously named one kind per whole attribute
path, built from Divi's metadata component name alone. For a composite path
(Divi groups several named sub-fields, "subName", under one path – e.g.
buttonOne.innerContent holds "text" and "linkUrl") that was wrong: the whole
path got one guessed kind (or none), even though the sub-fields can differ
(fullwidth-header's buttonOne/buttonTwo.innerContent -> "text", though it
also carries a "linkUrl"; image.innerContent -> "image", though the value
also carries alt/id/titleText the metadata never names on its own).

AttrPathIndex::kinds() now resolves a composite path to a map
subName => kind instead, preferring Divi's features.dynamicContent.type over
the (often shared/generic) field component for a named sub-field – this is
what tells a button's plain text sub-field apart from its linkUrl sub-field,
both of which use the same generic "divi/text" component. A plain (non-
composite) path is unaffected. Any subName the metadata never names (or that
disagrees between candidates) is therefore simply absent from the map, and
ModuleCatalog::pathKind() defaults it, like every unresolved path, to
"unknown" - the strictest routing for 2b's sanitizer, never a guess.

ModuleCatalog::pathKind() gains an optional $subName parameter to read a
composite path's map. docs/guides/divi-attrs.md documents the new shape and
that lit-divi-catalog without `module` lists all modules.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:12:49 +02:00
janniclas.loosenandClaude Opus 5.5 4137882008 fix: harden the Divi BlockTree against opaque/invalid writes
Final fix wave for stage 2a, load-bearing for 2b's writers:
- Block::setAttrs()/Container::insertChild()/removeChild() refuse on an opaque
  block (undecodable attrs or a global module) instead of silently corrupting it.
- Container::append() is now @internal (Parser only) and refuses on a void
  block, so a child can no longer be silently dropped from the serialized output.
- Block::create() validates the block name against namespace/block-name.
- Json::decodeObject() returns null (-> opaque) for a top-level object whose
  keys are a plain list ("0","1",...) rather than returning [] and letting the
  Serializer re-encode it as a corrupting JSON array.
- AttrMap::set() rejects empty path segments and keeps an existing stdClass
  value an object when rewrapping it (no silent object->list flip); AttrMap::get()
  is updated in step so it can still read back through such an object.
- Block::copy() deep-clones stdClass attribute values instead of sharing them.
- Json::encode()'s existing JsonException-on-invalid-UTF-8 behaviour is documented.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:12:49 +02:00
janniclas.loosenandClaude Opus 5.5 f433fef8f7 feat: Divi hints point to the read tools; guides divi-structure/attrs/design-system; test: Divi read end-to-end
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 12:41:42 +02:00
janniclas.loosenandClaude Opus 5.5 b3cd0eee62 fix: bound render-summary strings, restore postdata globals, drain buffers
Review fix round 1 for lit/page-render-summary: extract shared Text::shorten()
(reused by NodeSummary), replace data: URIs with a short marker, prefer
data-src/data-lazy-src over placeholder src, dedup nested p/li/blockquote
text and ignore script/style/noscript content, restore every setup_postdata
global (not just $post), drain output buffers robustly around the_content,
and disclose that rendering can trigger oEmbed/network requests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 12:31:20 +02:00
janniclas.loosenandClaude Opus 5.5 2e9acd686a feat: lit/page-render-summary – rendered content as structured excerpt
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 12:21:23 +02:00
janniclas.loosenandClaude Opus 5.5 d27504a750 feat: lit/divi-outline and lit/divi-node-get with tree_rev
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 12:14:38 +02:00
janniclas.loosenandClaude Opus 5.5 a54a337e0b feat: read the Divi design system live – lit/divi-design-system
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 12:06:15 +02:00
janniclas.loosenandClaude Opus 5.5 02ae76d4f3 fix: stop guessing a kind for composite Divi attribute paths
Review fix round 1 on the lit/divi-catalog task:
- AttrPathIndex::collectKinds() no longer records a kind from a
  component.type === "group" node (a composite of several sub-kinds,
  e.g. button.innerContent = text + link + target), and kinds() now
  drops any attrName with more than one distinct candidate kind
  instead of last-write-wins (e.g. imageIcon.innerContent had onoff +
  icon + image sub-fields sharing one attrName). Both previously
  produced a wrong-but-present kind, which is more dangerous for 2b's
  sanitization routing than "unknown". Verified against the committed
  blurb/button/fullwidth-header fixture entries and live against the
  full 100-module catalog.
- AttrPathIndex::fromDefaults() now builds on AttrMap::flatten()
  instead of a parallel walker.
- ModuleCatalog::shortName() replaces the duplicated
  substr($name, strlen('divi/')) in DiviCatalogAbility.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 12:00:35 +02:00
janniclas.loosenandClaude Opus 5.5 2f4dcf9ce4 feat: Divi module catalog, attribute paths, short form and lit/divi-catalog
Adds per-path attribute kind (text/richtext/code/url/image/color/enum/
onoff/number/list/icon), derived from Divi's field component metadata
where an attribute path names one unambiguously (module.paths() itself
is unchanged; kinds() is a new, separate lookup exposed as path_kinds
on lit/divi-catalog's module detail). This is not in the task-4 brief;
it is added because 2b's sanitization routing (ruling R3) needs a
metadata-derived field kind per attribute path. Verified live against
the full 100-module catalog (564/4358 paths resolve a kind; the rest
default to "unknown" and fall back to 2b's key-name routing).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 11:48:27 +02:00
janniclas.loosenandClaude Opus 5.5 08d70abfc7 feat: Divi path IDs, attribute paths and outline
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 11:35:03 +02:00
janniclas.loosenandClaude Opus 5.5 8222240ed6 feat: Divi BlockTree – byte-exact parser/serializer with round-trip fixtures
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 11:26:14 +02:00
janniclas.loosen ff0ab049e4 test: media smoke - direct-only download, file-name search 2026-09-26 05:10:25 +02:00
janniclas.loosen 50f0f98c8e chore: uuid string guard in revoke, docblock placement, stricter schedule warning test 2026-09-26 05:07:35 +02:00
janniclas.loosen 14b9508dfc fix: menu location assignment is destructive, neutral download hint in media preview 2026-09-26 05:06:53 +02:00
janniclas.loosen 66663daa99 fix: slash media title/alt on import, keep sideload errors out of client responses 2026-09-26 05:06:34 +02:00
janniclas.loosen 648d53cb96 fix: hide direct-only abilities from the adapter meta-tools 2026-09-26 05:05:48 +02:00
janniclas.loosen 8d0979cb73 fix: connections only manageable for users the admin may edit 2026-09-26 05:05:27 +02:00
janniclas.loosen 9634ca740d fix: media search also matches file names 2026-09-26 05:05:10 +02:00
janniclas.loosen 28bb033a8b fix: cap Base64 media transfers at 10 MB, upload limit at most 32 MB 2026-09-26 05:04:38 +02:00
janniclas.loosenandClaude Opus 5.5 7f58301a71 docs: readme with site-wide effects, media guide; test: media/admin end-to-end; version 0.2.0
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 04:51:11 +02:00
janniclas.loosenandClaude Opus 5.5 251934ce53 feat: deferred 1a items - menu_rev lock, lit_mcp_guides filter, warnings, schedule guard precision
Task 14 (rulings P17/P18, Q10):
- lit/menu-get returns menu_rev (Rev::ofMenu over id, parent, position,
  title, url, object, object_id); lit/menu-set-items requires it, refuses
  a stale one with rev_mismatch (hint: lit/menu-get) and returns the new
  menu_rev. Errors::revMismatch takes an optional message/hint.
- GuideRepository: filter lit_mcp_guides adds/overrides topics; invalid
  topic names and non-string content are ignored, files stay the default.
- lit/post-trash names front page, posts page and linking menus in the
  confirmation and as warnings; lit/menu-assign-location needs confirm
  to remove an assigned menu and names it; lit/post-schedule warns that
  a private entry becomes public; Divi hints no longer point to
  non-existing lit-divi-* tools.
- PostGuard::missedSchedule: 60 s publish window, zero GMT date falls
  back to get_gmt_from_date(post_date); post-schedule refuses dates
  within that window.
- write_failed after a clean rollback that keeps a revision/backup says
  "Die Aenderung wurde nicht gespeichert (... bleibt erhalten)" via the
  new state parameter (Errors::writeFailed / WriteFailed rolledBackState).
- wp-basis-smoke: menu_rev flow, unassign confirm, trash/menu and
  private-schedule warnings.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 04:33:15 +02:00
janniclas.loosenandClaude Opus 5.5 7035448f7d feat: clean up own data on deactivation and uninstall
Deactivation now clears the endpoint-check transient and the cached rewrite
rules (forcing WordPress to regenerate them without this plugin's routes on
the next request) and activation asks mcp-oauth to re-flush its own rules.
uninstall.php removes all own options/transient/cron/table across every site
of a network, delegating to the new self-contained LIT\MCP\Uninstaller class
so it works without the plugin's autoloader and is unit-testable on its own.
mcp-oauth's data (JWT secret, rewrite marker, refresh-token meta, application
passwords) is left untouched, as is every post/attachment/revision.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 04:21:23 +02:00
janniclas.loosenandClaude Opus 5.5 522f5bbd19 feat: change log tab with filters, revision links and clear button
ChangeLog gains query()/abilities()/clear() (filters: ability, user,
result, date range - all optional and additive). LogTab/LogListTable
render the "Protokoll" admin tab: WP_List_Table with pagination, links
to the post/attachment/nav_menu edit screen by object_type, a revision
link shown only when the user may edit the revision's parent post, and
a nonce+manage_options-gated "Protokoll leeren" with a JS confirmation
and highlighted 'partial' rows.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 04:12:13 +02:00
janniclas.loosenandClaude Opus 5.5 9104989c43 fix: neutral hint form for remaining client-facing tool mentions, Limits bounds accessor
Fix round 1 (task 10 review):
- FieldValidator's "unknown field" validation error (reaches the
  client via validation_failed's fields) and PostPresenter's
  DIVI_HINT (surfaced in the result's hints array) still named
  lit-content-types/lit-content-update as plain lit-<name>; converted
  both to the neutral "lit/<name> (direkt: lit-<name>)" form like the
  other hints from task 10. Re-grepped src/ for any other client-facing
  error/field/hints text naming a direct-by-default tool as lit-<name>
  (descriptions/schemas excluded per Q11c) - none left.
- Added Limits::bounds() (field => [min, max]) and made LimitsTab use
  it for the number inputs' min/max instead of a second, hardcoded
  copy of the same bounds.
- LimitsTab now shows a description note when the configured upload_mb
  exceeds wp_max_upload_size() (PHP's upload_max_filesize/post_max_size),
  since WordPress would refuse a larger upload before this limit ever
  applies.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 03:57:15 +02:00
janniclas.loosenandClaude Opus 5.5 bca35f6166 feat: tools and limits settings tabs
Adds Einstellungen → LIT MCP → Tools (direct/indirect/disabled per
ability, only ExposurePolicy-allowed modes offered) and → Limits
(upload size, log retention, snapshot count), wired into Plugin.php.

Ruling Q11b (carried from task 6): overview.md notes that direct
visibility is configurable; hints in src/ that name a tool which is
direct by default but can be switched to indirect (content-get,
content-query, content-types, post-publish, media-search) now use the
neutral "lit/<name> (direkt: lit-<name>)" form so they stay correct
after an admin override. lit/guide (always direct) and the
media-preview/-download DIRECT_ONLY tools are unaffected.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 03:47:40 +02:00
janniclas.loosenandClaude Opus 5.5 eee1840411 feat: access tab with allowed roles and connection revocation
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 03:33:54 +02:00
janniclas.loosenandClaude Opus 5.5 169d5772b5 fix: discovery admin notice fires on cached 'recommended' too, guarded against oauth/permalink early returns
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 03:30:11 +02:00
janniclas.loosenandClaude Opus 5.5 f084c47311 feat: settings page with connection tab, admin notices and site health test
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 03:21:56 +02:00
janniclas.loosenandClaude Opus 5.5 2674bf2ed1 feat: hide tool list and instructions from users without LIT MCP access
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 03:13:05 +02:00