Skip to content

feat(tools): create_page_draft — the sixth writer creates a hidden page (ADR-180) - #832

Merged
CybotTM merged 2 commits into
mainfrom
feat/create-page-draft
Aug 20, 2026
Merged

feat(tools): create_page_draft — the sixth writer creates a hidden page (ADR-180)#832
CybotTM merged 2 commits into
mainfrom
feat/create-page-draft

Conversation

@CybotTM

@CybotTM CybotTM commented Aug 20, 2026

Copy link
Copy Markdown
Member

Closes #831.

What

create_page_draft — the sixth writing tool, and the first that creates a page. It creates ONE standard page under a parent page: always hidden, always in the default language, with title, nav_title and position (parent, optional after_page_uid that must be a subpage of the same parent) as the whole field set; the URL segment is left to the DataHandler's generator. Every other page field (hidden, doktype, slug, fe_group, perms_*, …) is refused by name. It follows the five existing writers to the letter: disabled by default, editing group, NON_IDEMPOTENT_WRITE, approval before every call (ADR-134), preview at suspend (ADR-136), DataHandler under the acting user's PAGE_NEW permission on the parent, read-after-write with discard of a page that came out visible, and a refusal vocabulary that never confirms a uid. Editor action declared on pages with parent as the uid-carrying argument (ADR-152).

Why this shape — ADR-180

ADR-146 named two revisit triggers: a sixth writer and more than one record per call. Both fired, because the obvious shape was "page plus first element in one call". ADR-180 keeps the one-record rule: the tool creates the page and nothing on it, and its success message hands the model the new uid and names create_content_element_draft for the text. Two approvals, each card showing one record. ADR-146 carries the :Amended: field; AdrLifecycleTest checks both ends.

Two things the functional tests taught

  • The DataHandler's permission check on a NEW page (recordEditAccessInternals(..., newRecord: true)) reads sys_language_uid from the incoming record — a non-admin is refused with "languageField … not found in testing record" when it is missing. The tool states it explicitly (it is the default language anyway).
  • Core's TCA default for a new page is hidden = 1, so the exclude-field drop the content-element test relies on changes nothing on stock core. The discard test therefore sets TCAdefaults.pages.hidden = 0 on the parent, the installation shape the read-back exists for — and the page that came out visible is deleted again.

Surfaces

Tool counts move from 46 / five to 47 / six everywhere ProductFactsConsistencyTest looks: README, Tools.rst (new section, group table, counts), the seven landing-page data files, and the pinned number in the test itself. New icon nrllm-editor-action-create-page, XLIFF labels (en/de), CHANGELOG under Unreleased.

Gates run locally (one matrix cell, PHP 8.5 / TYPO3 14)

cgl ✓ · phpstan (level 10) ✓ · unit (7263 tests) ✓ · fuzzy ✓ · changelog ✓ · functional -d sqlite, filtered to the tool, editor-action and effect-coverage classes (63 tests) ✓. Rector did not run locally — this worktree's .Build is resolved under PHP 8.4 and the pinned -p 8.2 dies on platform_check.php; CI is the place it runs. The full functional suite is left to CI as Tests/AGENTS.md advises.

Assisted by claude-code:claude-fable-5 — Session

The backend assistant could draft a content element and a translation
but had no way to create the page they would go on. create_page_draft
creates ONE standard page under a parent page: always hidden, always in
the default language, with title, navigation title and position as the
whole field set; the URL segment is left to the DataHandler. It follows
the five existing writers to the letter: disabled by default, editing
group, NON_IDEMPOTENT_WRITE, approval before every call, preview at
suspend, DataHandler under the acting user's PAGE_NEW permission,
read-after-write, and a refusal vocabulary that never confirms a uid.

ADR-146 named "a sixth writer" and "more than one record per call" as
its revisit triggers; both fired, because the obvious shape was "page
plus first element in one call". ADR-180 keeps the one-record rule:
the tool creates the page and nothing on it, and hands the model the
new uid for create_content_element_draft. ADR-146 carries the Amended
field.

Two things the functional tests taught: the DataHandler's permission
check on a NEW page reads sys_language_uid from the incoming record,
so the tool states it explicitly or a non-admin is refused; and core's
default for a new page is already hidden, so the read-back's discard
path is exercised against TCAdefaults.pages.hidden = 0, the case it
exists for.

Every surface that counts the tools moves from 46/five to 47/six:
README, Tools.rst, the landing-page data and ProductFactsConsistency.

Closes #831

Assisted-by: claude-code:claude-fable-5
Agent-Session: https://claude.ai/code/session_0124WZK5UoAM9oYQoSYF1Y8z
Agent-Host: 32116e
Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
@CybotTM
CybotTM requested a review from a team as a code owner August 20, 2026 11:01
Copilot AI lite review requested due to automatic review settings August 20, 2026 11:01
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests Test-related changes configuration Configuration changes labels Aug 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

github-actions[bot]
github-actions Bot previously approved these changes Aug 20, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for maintainer PR

All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.

@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 48.86878% with 113 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.74%. Comparing base (c650302) to head (4a55542).

Files with missing lines Patch % Lines
...asses/Service/Tool/Builtin/CreatePageDraftTool.php 49.46% 94 Missing ⚠️
...rvice/Tool/Builtin/PlansOneEditorialWriteTrait.php 41.17% 10 Missing ⚠️
...ice/Tool/Builtin/CreateContentElementDraftTool.php 25.00% 9 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##               main     #832      +/-   ##
============================================
- Coverage     87.01%   86.74%   -0.27%     
- Complexity     9809     9865      +56     
============================================
  Files           572      573       +1     
  Lines         31733    31920     +187     
============================================
+ Hits          27611    27689      +78     
- Misses         4122     4231     +109     
Flag Coverage Δ
unit 65.06% <48.86%> (-0.12%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ervice/Tool/Builtin/CreateTranslationDraftTool.php 85.24% <100.00%> (-0.24%) ⬇️
...es/Service/Tool/Builtin/MoveContentElementTool.php 84.18% <100.00%> (-0.35%) ⬇️
...ice/Tool/Builtin/CreateContentElementDraftTool.php 92.11% <25.00%> (-2.27%) ⬇️
...rvice/Tool/Builtin/PlansOneEditorialWriteTrait.php 74.41% <41.17%> (-21.74%) ⬇️
...asses/Service/Tool/Builtin/CreatePageDraftTool.php 49.46% <49.46%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The fourth plan() writer made two more blocks identical across all
four: the guard execute() opens with (acting user, backend environment,
live workspace) and the DataHandler creation of one record with the
read-back of its uid. SonarCloud counted the fourth copy as 4.5 % new
duplication against a 3 % gate — and a private copy per file would
have relocated it, not removed it.

Both move into PlansOneEditorialWriteTrait as writableActingUser() and
createRecord(); CreatePageDraftTool, CreateContentElementDraftTool,
MoveContentElementTool and CreateTranslationDraftTool use them. What
stays per tool is plan() and everything that reads its shape. The two
pre-ADR-146 writers are not retrofitted, as ADR-146 decided. ADR-180
records the review ADR-146 asked for at this writer.

Also names the repeated test title once (php:S1192).

Assisted-by: claude-code:claude-fable-5
Agent-Session: https://claude.ai/code/session_0124WZK5UoAM9oYQoSYF1Y8z
Agent-Host: 32116e
Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for maintainer PR

All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.

@sonarqubecloud

Copy link
Copy Markdown

@CybotTM

CybotTM commented Aug 20, 2026

Copy link
Copy Markdown
Member Author

Self-review: 4a55542

The review this pull request demands is unsatisfiable (Copilot quota wall or repeated bot failures on this head). Per the documented fallback, the diff on this head was reviewed by the PR author; this comment is the on-the-record attestation the merge gate reads back. It stops matching on the next push.

@CybotTM
CybotTM added this pull request to the merge queue Aug 20, 2026
Merged via the queue into main with commit cb7e823 Aug 20, 2026
92 checks passed
@CybotTM
CybotTM deleted the feat/create-page-draft branch August 20, 2026 11:33
CybotTM added a commit that referenced this pull request Aug 20, 2026
Both ADR-180 (#832) and ADR-181 appended to the ADR toctree; the
merge keeps both entries in order.

Assisted-by: claude-code:claude-fable-5
Agent-Session: https://claude.ai/code/session_0124WZK5UoAM9oYQoSYF1Y8z
Agent-Host: 32116e
Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

configuration Configuration changes documentation Improvements or additions to documentation tests Test-related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

create_page_draft — a purpose-built writer for new (hidden) pages

2 participants