Skip to content

Documentation: Publish a Docusaurus site, update the LICENCE and add the missing governance files - #178

Open
MarkusPaulsen wants to merge 65 commits into
mainfrom
docs/docusaurus-migration-and-repo-hygiene
Open

Documentation: Publish a Docusaurus site, update the LICENCE and add the missing governance files#178
MarkusPaulsen wants to merge 65 commits into
mainfrom
docs/docusaurus-migration-and-repo-hygiene

Conversation

@MarkusPaulsen

@MarkusPaulsen MarkusPaulsen commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Moves the Ares 2 documentation into a Docusaurus site published to GitHub Pages, updates the
LICENCE copyright holder, and adds the top-level governance files the repository was missing.

Linked issues

No linked issues

1. Problem

Three problems, all in documentation and metadata rather than in enforcement code. The original
wording, including the note on the LICENCE change, is in a comment below.

The repository front page was blank. README.md held only # Ares2, and GitHub renders it
in preference to README.adoc, so the 1407-line manual that was the entire documentation was
invisible to anyone landing on the repository.

The documentation site did not exist. README.adoc linked to a GitHub Pages address that
no workflow ever published to. The 13 manuals under docs/, some 11,600 lines, rendered as raw
Markdown with hand-written contents lists and no search.

Governance files were missing. Against Artemis, the repository had no CONTRIBUTING.md,
CODE_OF_CONDUCT.md, CITATION.cff or .editorconfig, so the community profile was
incomplete and contributors had no written build and test contract.

No production Java code is touched, so nothing about enforcement changes either way.

2. Improvement from the user's perspective

Instructors get a searchable documentation site organised around two audiences: an instructor
section covering what Ares 2 is, where the boundary ends, how to protect a Maven or Gradle
project and how to migrate an Ares 1 exercise; and a contributor section covering the
technologies, one page per policy domain, and the subsystems with the existing deep-dive
manuals as children. Cross-references resolve, and the build fails if one does not.

About 30 leaf pages in the contributor section are new and ship as stubs, each saying so, so the
tree is navigable and the gaps are visible rather than implied.

The front page now says what Ares 2 is, how to add it and where the documentation lives.

Three stale claims are corrected, the clearest being the reserved-package snippets, documented
at a path that does not exist; they ship inside the JAR.

3. Improvement from the maintainer's perspective

  • Documentation is built on every pull request that touches it, with onBrokenLinks and
    onBrokenAnchors set to throw, so a dangling cross-reference fails CI instead of shipping.
    PlantUML diagrams render to committed SVGs, and CI fails on a .puml edited without one.
  • The AET writing rules are a CI gate too. A check enforces what is decidable from the words
    alone and holds each advisory rule to a ceiling that may fall but not rise.
    contributor/writing-rules is the standard.
  • CONTRIBUTING.md and CLAUDE.md write down the build, the quality gates and the four
    enforcement mode combinations CI exercises, so that contract leaves maintainers' heads.
  • Four config files referenced paths this pull request moves and would have stopped matching:
    the examples workflow's path filter, the labeler globs, the template checklist, and links in
    examples/README.md and one pom.xml. All repointed.

The Artemis file comparison is in the comment below.

4. Testing manual

Prerequisites

  1. Node 24.18.0 or newer, and a JDK 17 with Maven, both on PATH.
  2. Check out this branch and cd documentation.
  3. corepack install — expected: Adding pnpm@11.18.0 to the cache.... Use this rather
    than corepack enable, which writes a shim into the Node install directory and fails with
    EACCES where that directory is not yours.
  4. GitHub Pages is already set to Source = GitHub Actions, serving
    https://ls1intum.github.io/Ares2/, which matches the configured baseUrl. None of the
    steps below need it.

Steps

  1. pnpm install --frozen-lockfile then pnpm run build — expected: [SUCCESS] Generated static files in "build". onBrokenLinks and onBrokenAnchors are throw, so a dangling
    cross-reference among the migrated pages fails here.
  2. pnpm run serve and open http://localhost:3000/Ares2/. Read the site, this is the
    change.
    Confirm each of these on screen:
    • the landing page offers Instructor and Contributor cards, and each reaches its guide;
    • in the Contributor guide the sidebar lists Technologies on which Ares 2 is built and
      Subsystems, and in the Instructor guide How to protect a Java project with Ares 2;
    • open any policy page: part of the YAML example is marked in red, and the words
      policy-focus-start and policy-focus-end appear nowhere on the page;
    • open a leaf under Contributor → Extending Ares 2: it says in a box that it is a scaffold;
    • the Simple Story box at the top of a page renders as a coloured admonition, not as the
      literal text :::tip;
    • search for reserved package, and results come back scoped to the guide you are in;
    • open http://localhost:3000/Ares2/nonsense and the 404 page renders.
      Stop the server with Ctrl-C.
  3. pnpm run test:install then pnpm run test — expected: 15 passed, in about 7 seconds.
    This is step 2 run for you, in a real browser, over every page rather than the few you
    opened. The build proves that links resolve; it does not prove that a page renders, which
    is how 53 admonitions shipped rendering as plain text. Read the test names: they are the
    list in step 2.
  4. cd .. && mvn -o test -Dtest='de.tum.cit.ase.ares.documentation.*Test' -DfailIfNoSpecifiedTests=false — expected: 644 tests in 9 classes, no failures. Read
    target/surefire-reports/. These hold the Markdown itself to one shape: every page
    declares its front matter, opens with a Simple Story box, carries no second top-level
    heading, and uses no admonition syntax that renders as plain text.
  5. cd documentation && pnpm run diagrams:check — expected: No .puml sources found ..., nothing to render. and exit 0. There are no .puml files on main.
  6. pnpm run test:prose then pnpm run lint:prose — expected: pass 77, then 0 enforced (0 accepted, 0 new), 1209 advisory and exit 0. The advisory count is held to
    scripts/prose/advisory-ceiling.json, and a rule fails whenever its count stops matching,
    in either direction, so an improvement is recorded rather than banked.
  7. pnpm run lint and pnpm run typecheck — expected: $ eslint ., the prose summary above,
    and $ tsc. Nothing else to look at.

pnpm start serves the same site with live reload, if you would rather browse it that way
than build first.

Expected result

Per step, above. The site has 122 routes, 43 under /instructor/ and 75 under
/contributor/; build/sitemap.xml lists them if you want the count.

Negative case (what must still be rejected)

  1. A dangling cross-reference must fail the build. Append
    See [nothing](./policy/reader-and-director.md#not-a-real-heading). to
    documentation/docs/contributor/subsystems/package-overview.md and run pnpm run build
    expected: the build fails with Docusaurus found broken anchors! and names
    /Ares2/contributor/subsystems/package-overview as the source page. Revert the edit.
  2. A box that renders as plain text must be caught, and the build cannot see it. In
    documentation/docs/instructor/policy-reference/file-system-access.md change
    :::tip[Simple Story] to :::tip Simple Story, then run all three: pnpm run build still
    reports [SUCCESS], pnpm run test reports 1 failed, 14 passed on "the Simple Story boxes
    render as admonitions", and mvn -o test reports 3 failures naming that file. Revert the edit.
  3. A word the rules forbid must fail. Add "Additionally, this is also true." to any page and
    run pnpm run lint:prose — expected: exit 1, naming no-always-filler twice. Revert.
  4. A .puml with invalid syntax must fail pnpm run diagrams with exit 1 rather than
    commit an error image. PlantUML exits 0 and writes an SVG reading "Syntax Error" in some
    failure modes, which the script now rejects explicitly.

Modes exercised

  • ArchUnit + AspectJ
  • ArchUnit + instrumentation
  • WALA + AspectJ
  • WALA + instrumentation

No mode-specific behaviour changed. No production Java code is modified.

5. Test case coverage regarding this PR

No production Java code changed.

Breaking changes and migration

None for consumers. The public API, the policy format, the generated security tests and the
minimum JDK are all untouched.

For anyone linking to the docs: README.adoc and the docs/ folder are removed. Deep links
into README.adoc anchors will break; the content is at https://ls1intum.github.io/Ares2/.

Documentation structure. The site is organised as Instructor / Contributor rather than the
user / developer split the migration first used. Routes are /instructor/... and
/contributor/....

For the in-flight chore/improve-policy-subsystem branch: it modifies README.adoc and 12
files under docs/, and holds the only five .puml files in the project. It will need a rebase
onto the new documentation/ layout. The PlantUML rendering pipeline in this PR is ready for
those diagrams: drop them under documentation/docs/contributor/** and run pnpm run diagrams.

Checklist

  • Documentation (documentation/, README.md, Javadoc) was updated where the change is user-facing.
  • CI is green, or every remaining failure is explained above.
  • No secrets, tokens or absolute local paths are contained in the diff.

Review progress

  • Code review
  • Manual test

Markus Paulsen added 10 commits August 7, 2026 05:02
Ares 2 is maintained by Markus Paulsen at the Applied Education Technologies
group. Update the MIT copyright line accordingly.

The pom.xml <developers> entry is authorship metadata rather than a
copyright notice and stays unchanged.
Ares 2 lacked several top-level files that Artemis has and that GitHub
surfaces in its community profile:

- CONTRIBUTING.md: identity expectations, build and test commands, the four
  enforcement mode combinations, the documentation workflow.
- CODE_OF_CONDUCT.md: Contributor Covenant 2.1. Unlike the Artemis copy, the
  enforcement contact placeholder is filled in.
- CITATION.cff: software citation metadata. No preferred-citation is claimed,
  since there is no accompanying paper to point at.
- .editorconfig: encodes the formatting Spotless already enforces (tabs, four
  spaces per tab for Java and XML) so editors agree with the build.
- CLAUDE.md: project guide for coding agents. AGENTS.md now points at it while
  keeping the network-testing rule in full, as that is the convention most
  often violated.
- .github/actionlint.yaml: configuration for the existing actionlint workflow.
Ares 2 had no rendered documentation. README.adoc linked to
https://ls1intum.github.io/Ares2/, but nothing ever published there.

The site mirrors the Artemis documentation setup, scaled to two audiences
(user and developer) rather than four, on the same pinned Docusaurus 3.10.2
stack.

Two choices are worth calling out:

- markdown.format is 'detect'. Docusaurus 3 parses .md as MDX by default,
  which rejects the bare '<' and '{' that fill the existing manuals (Java
  generics in prose, ${...} in Gradle snippets). 'detect' keeps .md as
  CommonMark and reserves MDX for .mdx.
- onBrokenLinks and onBrokenAnchors are 'throw'. This documentation is what
  an instructor follows while wiring a policy into an exercise, so a dangling
  cross-reference should fail the build rather than ship.

PlantUML diagrams are rendered at build time into committed SVGs, the same
way the .drawio sources here sit next to committed .drawio.png renders. The
renderer pins the Apache-licensed PlantUML 1.2026.6 by SHA-256 and uses the
built-in Smetana layout engine, so no Graphviz is needed and no diagram
source is sent to an external server at page-view time. It also verifies its
own output: PlantUML emits an error image and still exits 0, so the script
rejects renders containing error markers.

The pnpm overrides lift serialize-javascript and uuid past published
advisories (GHSA-5c6j-r48x-rmvq, GHSA-qj8w-gfj5-8c6v, GHSA-w5hq-g745-h8pq);
pnpm audit is clean.
Pure file moves, kept in their own commit so the content edits that follow
(front matter, table-of-contents removal, heading normalisation, link
rewrites) are reviewable on their own.

The 13 manuals are split by audience: the security policy manual and the two
project setup guides go to the user guide, the package overview, enforcement
model, reader/director, test-case factory, AOP and architecture manuals to
the developer guide. Filenames become kebab-case to match the URLs they now
produce. The .drawio sources and their rendered .png files travel with the
pages that reference them.
Per-file changes:

- The leading h1 becomes the front-matter title, so each page has exactly one
  h1 and the sidebar label comes from the same source.
- The hand-written 'Table of Contents' blocks are removed; Docusaurus renders
  its own from the headings.
- Six of the manuals used h1 as their section level and so had seven to nine
  h1s each. Every heading in those files is demoted one level. Demotion keeps
  the heading text, so the generated anchor slugs are unchanged and existing
  deep links still resolve.
- 42 internal links are repointed at the new paths. Within a guide these stay
  relative .md links, which Docusaurus resolves and validates. Across guides
  they become absolute route paths, because the user and developer doc plugin
  instances cannot resolve each other's relative paths.
- Links into examples/ and src/ now point at GitHub, since the documentation
  site has no copy of the repository.
- The policy manual, the reader/director manual and the enforcement model
  cross-reference each other, as they are tightly coupled but live in
  different guides.

Headings inside code fences were left alone throughout; the manuals contain
bash and YAML blocks whose '#' comments would otherwise have been rewritten.

The site builds clean with onBrokenLinks and onBrokenAnchors set to throw.
README.adoc was 1407 lines and served as the whole manual, but GitHub
prefers README.md and the repository only had a stub containing "# Ares2".
The project front page was therefore effectively blank, and the AsciiDoc
manual was reachable only by opening the raw file. README.adoc also linked
to https://ls1intum.github.io/Ares2/, which nothing published to.

Its 36 sections become nine pages under documentation/docs/user/, converted
from AsciiDoc to CommonMark: source blocks to fenced blocks, admonitions to
Docusaurus ":::" directives, callout lists to numbered lists, and internal
cross-references to resolved links. Long code blocks are copied verbatim
rather than retyped.

README.md now carries badges, the pitch, the install snippet and links to
the documentation, examples, contributing guide, security policy and
citation metadata.

Three stale claims in the source are corrected rather than carried over:

- The reserved-package snippets were said to live at
  "configuration/reservedPackages/", which does not exist. They ship inside
  the JAR and live at
  src/main/resources/de/tum/cit/ase/ares/api/configuration/reservedPackages/.
  The same wrong path appeared in two of the migrated manuals.
- The documented dependency version was 2.1.1; 2.1.2 is tagged and released
  to Maven Central.
- The examples were referenced by bare path; they now link to the Maven and
  Gradle exercises explicitly.
Ares 2 had no documentation workflow, and the README linked to
https://ls1intum.github.io/Ares2/ although nothing ever published there.

Three files, splitting reusable build logic from the two entry points:

- documentation.yml is workflow_call only. It installs with a frozen
  lockfile, type checks, verifies the committed PlantUML renders match their
  sources, and builds. Because onBrokenLinks and onBrokenAnchors are
  'throw', a dangling cross-reference fails here rather than shipping.
- documentation-ci.yml validates pull requests, uploading nothing.
- deploy-documentation.yml publishes to GitHub Pages on a push to main, and
  on workflow_dispatch so the site can be republished without a content
  change.

Both entry points share the same build, so the artefact that gets deployed
is produced by exactly the steps that validated it.

Actions are pinned by commit SHA with the version in a trailing comment, and
permissions follow the existing convention: empty at workflow level, minimal
per job, with pages/id-token confined to the deploy job.

Two path filters elsewhere referenced files this branch moved and would
otherwise have silently stopped matching:

- examples.yml watched docs/HowToMakeAProjectAnAresProject.md, which is now
  documentation/docs/user/make-a-project-an-ares-project.md. Left stale, the
  examples would no longer be rebuilt when the setup manual changes.
- labeler.yml globbed docs/** for the aop, architecture, policy,
  securitytest and docs labels.

Deploying still needs a one-time repository setting that no workflow can
make: Settings -> Pages -> Build and deployment -> Source = GitHub Actions.
The pull request template still asked contributors to update 'docs/' and
'README.adoc', and the examples linked to the setup manual and enforcement
model at their old paths. All three are now dead targets.

A commented-out assertion in SecurityTest.java also mentions README.adoc,
but it sits inside an already disabled block and is left alone.
Three defects found in review, each confirmed against PlantUML 1.2026.6
rather than reasoned about:

- The error-image marker list contained "An error has occured". PlantUML
  spells it "occurred", so the marker could never match. The markers are now
  the literal strings the tool emits, taken from the jar and from provoking
  each failure, and are compared case-insensitively. Verified: a syntax
  error, a Graphviz fallback and a missing include are all rejected, while a
  valid class diagram passes.

- --check staged every source into a flat scratch directory keyed by
  basename. Two diagrams with the same name in different directories
  overwrote each other, so drift in one of them was invisible; and a
  diagram using a relative !include of a sibling could not resolve it,
  because the sibling was never staged. The scratch tree now mirrors docs/
  exactly. Verified with a colliding pair (drift in one is caught and
  correctly attributed) and with a sibling include.

- --check launched one JVM per diagram. All staged sources now render in a
  single invocation, as the non-check path already did.

A failure also no longer prints a spawn() stack trace over PlantUML's own
message about the offending file and line.
.gitattributes checks this repository out with CRLF (* text=auto eol=crlf,
and *.svg text does not opt out of it), while PlantUML always writes LF.
Comparing the file contents directly therefore reported every committed
diagram as out of date on any fresh clone, so the CI check would have failed
permanently the moment the first .puml landed.

Both sides are now normalised to LF before comparison. Verified by rewriting
a committed render to CRLF (as a fresh checkout would have it), which now
passes, while an actual source change is still reported as out of date.
@MarkusPaulsen
MarkusPaulsen requested a review from a team August 7, 2026 11:01
@MarkusPaulsen
MarkusPaulsen requested review from a team and krusche as code owners August 7, 2026 11:01
@github-actions github-actions Bot added docs Automated area label: docs other Automated area label: other labels Aug 7, 2026
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e74f0add-3232-4d2f-8d85-741a87aea3ae

📝 Walkthrough

Summary by CodeRabbit

  • Documentation

    • Replaced the minimal README with comprehensive project information, including setup, features, contribution guidance, security, licensing and examples.
    • Added guides for Ares 2 protection capabilities, enforcement modes, Gradle and Maven setup, test annotations and migration from Ares 1.
    • Updated documentation references and repository guidance to reflect the new structure.
  • New Features

    • Added automated documentation validation and deployment to GitHub Pages.
  • Tests

    • Added checks for page structure, metadata, navigation, citations, examples and legacy formatting.
    • Expanded test-profile coverage to ensure all tests are executed.

Walkthrough

The change migrates repository references to documentation/, adds documentation content and validation tests, introduces reusable documentation CI, and automates GitHub Pages deployment.

Changes

Documentation delivery

Layer / File(s) Summary
Documentation paths and content
.github/PULL_REQUEST_TEMPLATE.md, .github/labeler.yml, .github/workflows/examples.yml, .coderabbit.yaml, AGENTS.md, README.md, documentation/docs/instructor/...
Repository guidance, path filters, README content, and Ares 2 setup documentation now use the current documentation structure.
Documentation parsing utilities
src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java, src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPagesTest.java
Adds shared utilities and tests for page discovery, front matter, admonitions, fenced blocks, sidebar positions, and headings.
Documentation structure and example validation
src/test/java/de/tum/cit/ase/ares/documentation/*DocumentationStructureTest.java, src/test/java/de/tum/cit/ase/ares/documentation/PolicyExampleValidityTest.java, src/test/java/de/tum/cit/ase/ares/documentation/DocumentationReferenceTest.java, pom.xml
Adds tests for documentation inventories, structure, citations, categories, policy examples, references, and Maven test selection.
Test profile coverage validation
src/test/java/de/tum/cit/ase/ares/testutilities/TestProfileCoverageTest.java
Checks that test sources are selected by Maven profiles or workflow-specific test arguments.
Reusable documentation build
.github/workflows/documentation.yml
Adds dependency installation, linting, type checking, PlantUML verification, Docusaurus build, browser tests, and optional Pages artefact upload.
Validation and Pages deployment
.github/workflows/documentation-ci.yml, .github/workflows/deploy-documentation.yml, .github/actionlint.yaml
Adds pull request and push validation, manual dispatch, workflow concurrency, actionlint rules, and GitHub Pages deployment.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: 🟡 Moderate · up to 150e0

The PR improves publishing and governance, but the current head still has correctness gaps in documentation validation and a contradictory Gradle negative-control procedure. These could allow documentation regressions to pass or mislead users, so merge readiness is moderate until the concrete issues are fixed or explicitly accepted.

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant DocumentationWorkflow
  participant Docusaurus
  participant GitHubPages
  GitHubActions->>DocumentationWorkflow: Run documentation checks
  DocumentationWorkflow->>Docusaurus: Build and test the site
  Docusaurus-->>DocumentationWorkflow: Produce documentation/build
  GitHubActions->>GitHubPages: Deploy the Pages artefact
Loading
🚥 Pre-merge checks | ✅ 7 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (7 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Sandbox Fail-Closed Behaviour ✅ Passed The diff changes no src/main or enforcement implementation files; Java changes are test-only, and other code changes only support documentation or examples. No fail-open path was introduced.
Trusted Boundary Preservation ✅ Passed The diff changes only PR-template tooling, workflow, and guidance; no Ares enforcement, fixtures, examples, or supervised code. PR_BODY is read as an environment value and not executed.
Github Workflow Least Privilege ✅ Passed Changed workflows default to no permissions, grant only contents: read or required Pages deploy rights, use pull_request for PR code, and add no secrets; the pull_request_target job does not checko...
Title check ✅ Passed The title concisely describes the main documentation site, governance, and automation changes.
Description check ✅ Passed The description clearly explains the Docusaurus migration, GitHub Pages automation, governance updates, testing, and documentation impact.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/docusaurus-migration-and-repo-hygiene

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/actionlint.yaml:
- Around line 10-14: Update the actionlint configuration to enable strict
validation by defining config-variables as an empty list instead of leaving it
commented out. Preserve the guidance to add intentionally introduced
configuration-variable names to that list, and remove the inaccurate explanation
that omission is appropriate.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 91231883-5e08-4bd8-8529-ee7e2b93a9ba

📥 Commits

Reviewing files that changed from the base of the PR and between c3e9426 and 63b5a11.

⛔ Files ignored due to path filters (62)
  • .editorconfig is excluded by none and included by none
  • CITATION.cff is excluded by none and included by none
  • CLAUDE.md is excluded by none and included by none
  • CODE_OF_CONDUCT.md is excluded by none and included by none
  • CONTRIBUTING.md is excluded by none and included by none
  • LICENSE is excluded by none and included by none
  • README.adoc is excluded by none and included by none
  • documentation/.gitignore is excluded by none and included by none
  • documentation/README.md is excluded by none and included by none
  • documentation/docs/developer/aop/BlockCommandSystemAccessAOP.drawio is excluded by none and included by none
  • documentation/docs/developer/aop/BlockCommandSystemAccessAOP.drawio.png is excluded by !**/*.png, !**/*.png and included by none
  • documentation/docs/developer/aop/BlockFileSystemAccessAOP.drawio is excluded by none and included by none
  • documentation/docs/developer/aop/BlockFileSystemAccessAOP.drawio.png is excluded by !**/*.png, !**/*.png and included by none
  • documentation/docs/developer/aop/BlockThreadSystemAccessAOP.drawio is excluded by none and included by none
  • documentation/docs/developer/aop/BlockThreadSystemAccessAOP.drawio.png is excluded by !**/*.png, !**/*.png and included by none
  • documentation/docs/developer/aop/_category_.json is excluded by none and included by none
  • documentation/docs/developer/aop/aspectj-vs-instrumentation-weaknesses.md is excluded by none and included by none
  • documentation/docs/developer/aop/block-command-system-access.md is excluded by none and included by none
  • documentation/docs/developer/aop/block-file-system-access.md is excluded by none and included by none
  • documentation/docs/developer/aop/block-thread-system-access.md is excluded by none and included by none
  • documentation/docs/developer/architecture/_category_.json is excluded by none and included by none
  • documentation/docs/developer/architecture/block-command-system-access.md is excluded by none and included by none
  • documentation/docs/developer/architecture/block-file-system-access.md is excluded by none and included by none
  • documentation/docs/developer/architecture/block-thread-system-access.md is excluded by none and included by none
  • documentation/docs/developer/overview.md is excluded by none and included by none
  • documentation/docs/developer/policy/SecurityPolicyReaderAndDirectorClassDiagram.drawio is excluded by none and included by none
  • documentation/docs/developer/policy/SecurityPolicyReaderAndDirectorSequenceDiagram.drawio is excluded by none and included by none
  • documentation/docs/developer/policy/_category_.json is excluded by none and included by none
  • documentation/docs/developer/policy/enforcement-model.md is excluded by none and included by none
  • documentation/docs/developer/policy/reader-and-director.md is excluded by none and included by none
  • documentation/docs/developer/securitytest/_category_.json is excluded by none and included by none
  • documentation/docs/developer/securitytest/test-case-factory-and-builder.md is excluded by none and included by none
  • documentation/docs/user/convert-ares1-to-ares2.md is excluded by none and included by none
  • documentation/docs/user/github-packages.md is excluded by none and included by none
  • documentation/docs/user/installation.md is excluded by none and included by none
  • documentation/docs/user/intro.md is excluded by none and included by none
  • documentation/docs/user/make-a-project-an-ares-project.md is excluded by none and included by none
  • documentation/docs/user/options.md is excluded by none and included by none
  • documentation/docs/user/security/_category_.json is excluded by none and included by none
  • documentation/docs/user/security/overview.md is excluded by none and included by none
  • documentation/docs/user/security/policy-configuration.md is excluded by none and included by none
  • documentation/docs/user/security/policy-manual.md is excluded by none and included by none
  • documentation/docs/user/security/postcompile.md is excluded by none and included by none
  • documentation/docs/user/security/precompile.md is excluded by none and included by none
  • documentation/docs/user/security/trust-boundary.md is excluded by none and included by none
  • documentation/docs/user/setup.md is excluded by none and included by none
  • documentation/docs/user/test-annotations.md is excluded by none and included by none
  • documentation/docusaurus.config.ts is excluded by none and included by none
  • documentation/package.json is excluded by none and included by none
  • documentation/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml and included by none
  • documentation/pnpm-workspace.yaml is excluded by none and included by none
  • documentation/scripts/render-plantuml.mjs is excluded by none and included by none
  • documentation/sidebar-developer.ts is excluded by none and included by none
  • documentation/sidebar-user.ts is excluded by none and included by none
  • documentation/src/css/custom.css is excluded by none and included by none
  • documentation/src/pages/index.module.css is excluded by none and included by none
  • documentation/src/pages/index.tsx is excluded by none and included by none
  • documentation/static/.nojekyll is excluded by none and included by none
  • documentation/static/img/tum-logo-blue.svg is excluded by !**/*.svg and included by none
  • documentation/tsconfig.json is excluded by none and included by none
  • examples/README.md is excluded by none and included by none
  • examples/ares-exercise-maven/pom.xml is excluded by none and included by none
📒 Files selected for processing (9)
  • .github/PULL_REQUEST_TEMPLATE.md
  • .github/actionlint.yaml
  • .github/labeler.yml
  • .github/workflows/deploy-documentation.yml
  • .github/workflows/documentation-ci.yml
  • .github/workflows/documentation.yml
  • .github/workflows/examples.yml
  • AGENTS.md
  • README.md
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: Run the gradle exercise
  • GitHub Check: Run the maven exercise
  • GitHub Check: Build
  • GitHub Check: Analyse Java
🧰 Additional context used
📓 Path-based instructions (3)
**/.github/workflows/*.{yml,yaml}

📄 CodeRabbit inference engine (Custom checks)

GitHub Actions workflows must use least-privilege permissions, avoid exposing secrets to untrusted pull-request code, and never use unsafe pull_request_target checkout patterns.

Files:

  • .github/workflows/documentation-ci.yml
  • .github/workflows/examples.yml
  • .github/workflows/deploy-documentation.yml
  • .github/workflows/documentation.yml
.github/workflows/**/*.yml

⚙️ CodeRabbit configuration file

Review GitHub Actions for least-privilege permissions, safe event choice, pinned third-party actions, safe pull_request_target usage, no secret exposure to untrusted code, and branch-protection compatibility.

Files:

  • .github/workflows/documentation-ci.yml
  • .github/workflows/examples.yml
  • .github/workflows/deploy-documentation.yml
  • .github/workflows/documentation.yml
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

Use LF line endings, UTF-8 encoding, and a final newline, as specified by .editorconfig.

Files:

  • AGENTS.md
  • README.md

⚙️ CodeRabbit configuration file

Dogmatically check all reviewed files for current British English in prose, comments, JavaDoc, documentation, workflow names, step names, issue/PR text, labels, user-facing messages, and review suggestions. Flag American spellings and grammar such as behavior, color, initialize, authorization, canceled, and program when they are natural-language text. Do not flag programming-language syntax, dependency coordinates, API names, class names, method names, package names, paths, URLs, quoted external identifiers, or other literals where American English is required by the technology.

Files:

  • AGENTS.md
  • README.md
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T11:01:50.757Z
Learning: `CLAUDE.md` is the single source of truth for repository structure, build and test commands, coding style, and pull-request processes; contributors and automated agents must read it first.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T11:01:58.458Z
Learning: Changes to the architecture or AOP layer must be verified across all affected combinations: ArchUnit + AspectJ, ArchUnit + instrumentation, WALA + AspectJ, and WALA + instrumentation.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T11:01:58.458Z
Learning: Update documentation in the same pull request as the user-facing change it describes.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T11:01:58.458Z
Learning: Use concise, imperative commit messages describing the change rather than its implementation.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T11:01:58.458Z
Learning: Fill in every section of `.github/PULL_REQUEST_TEMPLATE.md`, including the negative case and the mode combinations exercised.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T11:01:58.458Z
Learning: Target `main` and rebase rather than merge to keep history readable.
📚 Learning: 2026-07-14T16:44:59.365Z
Learnt from: MarkusPaulsen
Repo: ls1intum/Ares2 PR: 114
File: .github/workflows/pullrequest-labeler.yml:0-0
Timestamp: 2026-07-14T16:44:59.365Z
Learning: When reviewing GitHub Actions workflows, it can be acceptable to use `pull_request_target` (instead of `pull_request`) for jobs that need write access (e.g., auto-labeling) when fork PR tokens are read-only. Only consider it safe if the job does NOT check out or execute untrusted PR code, and it reads required configuration from the base ref (e.g., `.github/labeler.yml`) rather than from the PR. Enforce least-privilege permissions (e.g., `contents: read` and the minimum required `pull-requests: write`) and avoid any steps that would run code from the PR branch.

Applied to files:

  • .github/workflows/documentation-ci.yml
  • .github/workflows/examples.yml
  • .github/workflows/deploy-documentation.yml
  • .github/workflows/documentation.yml
🪛 LanguageTool
README.md

[locale-violation] ~7-~7: License must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ...type.com/artifact/de.tum.cit.ase/ares)
[![License: MIT](https://img.shields.io/github/lic...

(LICENCE_LICENSE_NOUN_SINGULAR)


[locale-violation] ~70-~70: LICENSE must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ...is licensed under the MIT Licence. See LICENSE for details.

(LICENCE_LICENSE_NOUN_SINGULAR)

🪛 YAMLlint (1.37.1)
.github/workflows/documentation-ci.yml

[warning] 7-7: truthy value should be one of [false, true]

(truthy)


[error] 9-9: too many spaces inside brackets

(brackets)


[error] 9-9: too many spaces inside brackets

(brackets)


[error] 15-15: too many spaces inside brackets

(brackets)


[error] 15-15: too many spaces inside brackets

(brackets)

.github/workflows/deploy-documentation.yml

[warning] 11-11: truthy value should be one of [false, true]

(truthy)


[error] 13-13: too many spaces inside brackets

(brackets)


[error] 13-13: too many spaces inside brackets

(brackets)

🪛 zizmor (1.29.0)
.github/workflows/deploy-documentation.yml

[warning] 42-42: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment

(undocumented-permissions)

🔇 Additional comments (10)
.github/PULL_REQUEST_TEMPLATE.md (1)

198-198: LGTM!

.github/labeler.yml (1)

7-15: LGTM!

Also applies to: 30-37, 50-50

.github/workflows/examples.yml (1)

16-16: LGTM!

AGENTS.md (1)

3-11: LGTM!

README.md (2)

1-6: LGTM!

Also applies to: 8-70


7-7: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use British English in the badge label.

The badge alt text is user-visible prose. Change License to Licence. Do not change the external URL or the LICENSE file identifier.

As per path instructions, use current British English in prose.

Proposed fix
-[![License: MIT](https://img.shields.io/github/license/ls1intum/Ares2)](LICENSE)
+[![Licence: MIT](https://img.shields.io/github/license/ls1intum/Ares2)](LICENSE)
			> Likely an incorrect or invalid review comment.

Sources: Path instructions, Linters/SAST tools

.github/workflows/documentation.yml (1)

1-80: LGTM!

.github/workflows/documentation-ci.yml (1)

1-34: LGTM!

.github/workflows/deploy-documentation.yml (1)

1-50: LGTM!

.github/actionlint.yaml (1)

1-9: LGTM!

Comment thread .github/actionlint.yaml Outdated
Markus Paulsen added 6 commits August 7, 2026 13:15
Replaces the user/developer split with the structure the two audiences
actually need: an instructor protecting an exercise, and a maintainer
working on Ares itself.

Instructor Documentation
  Ares 2: what it is, what it protects against, where the boundary ends
  How to protect a Java project: Maven and Gradle entry points, then the
    shared reference pages (installation, setup, annotations, policy
    configuration, both compile modes, further options, GitHub packages)
  How to transform an Ares 1 protected project into an Ares 2 one

Maintainer Documentation
  How can you contribute
  Technologies: JUnit Jupiter, jqwik, and four analysis techniques, each
    introduced by the vocabulary shared across its implementations
    (architecture: node, call graph, DFS path, rule; AOP: aspect, join
    point, pointcut, advice, binding, weaving; AST: node, call graph,
    visitor; Linux-based security: interception, allow list, wrapper)
  Policy: one page per domain, matching policySubComponents/ one to one
  Subsystems: the eight packages, with the existing deep-dive manuals as
    children of the subsystem they document

The Linux-based security vocabulary is derived from what Phobos actually
does. All three layers are wrappers that exec the next and so sit outside
the supervised process; each intercepts at a different level (kernel mount
namespace, dynamic linker ahead of libc, signal delivery); and each reads a
fail-closed allow list (bound paths, the host/CIDR/port table in
netblocker.c, the wall-clock budget).

Around 30 leaf pages are new and ship as stubs carrying front matter and a
note, so the tree is navigable and the gaps are explicit rather than
implied. The Phobos base-idea pages and "How can you contribute" are
written, since their content is derivable from the code and CONTRIBUTING.md.

69 internal links are repointed. Within a guide they stay relative .md
links so Docusaurus validates them; across guides they become absolute
routes, as the two plugin instances cannot resolve each other's relative
paths. The labeler globs and the examples workflow path filter are updated
again for the new layout.

The site builds clean with onBrokenLinks and onBrokenAnchors set to throw.
The Documentation CI workflow failed to start at all (startup_failure, 0s,
no logs), which is how GitHub reports a workflow it refuses to load.

Cause: this repository restricts Actions to an allowlist.

  allowed_actions:      selected
  github_owned_allowed: true
  verified_allowed:     false
  patterns_allowed:     ["MaximilianAnzinger/issue-labeler@*"]

pnpm/action-setup is third party and matches neither rule, so the whole
workflow was rejected before any job ran, and the caller failed with it.

Rather than widen the allowlist for a build tool, pnpm is now activated with
Corepack, which ships with Node and reads the exact version from the
packageManager field in documentation/package.json. CI and a local
`corepack enable` therefore resolve to the same pnpm, and the documentation
build gains no supply-chain dependency at all. For a project whose own
purpose is sandboxing untrusted code, that is the better trade.

The pnpm store is cached explicitly with actions/cache, because
actions/setup-node's built-in pnpm cache resolves the store path before
Corepack has run. Every action in this workflow is now GitHub-owned and
SHA-pinned.
Ares 2 is a substantial rewrite, but it still ships Christian Femers' work:
the public test API, the test context, the console IO testing utilities and
the reporting internals under de.tum.cit.ase.ares.api carry his authorship
in 41 source files. The MIT Licence requires its copyright notice to be
retained in all copies of the software, so replacing his notice outright
removed it for code that is still present.

Both notices are now listed in LICENSE, which is what the licence actually
requires and what the contribution deserves.

The lineage is explained in a separate NOTICE file rather than appended to
LICENSE, so that the licence text stays byte-for-byte standard MIT and
GitHub's licence detection keeps reporting MIT (the README badge reads that
detection). pom.xml already credits him under <contributors> as the creator
of Ares 1; NOTICE points at both.
"Contributor" matches CONTRIBUTING.md and the audience the section actually
addresses: anyone contributing to Ares 2, not only its maintainers.

Routes move from /maintainer/... to /contributor/... . Every internal link,
the plugin id, the sidebar file, the navbar and footer entries, the landing
page, the labeler globs and the three READMEs move with it.
The eight pages under documentation/docs/contributor/policy were stubs. Each
now documents one section of the policy file, derived from the records in
policy/policySubComponents and from PolicyValueValidator rather than from
prose.

Every page has the identical shape:

  ELI5 box      a plain-language explanation of what the domain is for
  Position      the example policy file, with this page's section in red
  Fields        Field | Datatype | Explanation | Example | Regex or Range
  Notes         the behaviour that the table cannot express

The example is one file shown identically on all eight pages, and the pages
are ordered so that the marked section moves down it: reading the section in
sidebar order walks the example from top to bottom. That reorders the pages
from the original listing, because YAML position rather than alphabetical
order is what makes the sequence readable.

The regexes and ranges are quoted from the implementation, not invented:
HOST_PATTERN, FILE_PATH_PATTERN, THREAD_CLASS_PATTERN, JAVA_PACKAGE_PATTERN
and the port 0-65535, non-negative thread count and positive timeout bounds
enforced in the record constructors.

One finding worth recording: ClassPermission has no field of its own in the
policy file. It is derived by JavaCreator.prepareAllowedClasses from the
essential classes and from theFollowingClassesAreTestClasses, so its page
marks that field and the Notes section explains the derivation.

The red marking uses a 'policy-focus' magic comment declared in
docusaurus.config.ts with its own CSS class, so it cannot be confused with
the default highlight colour used for ordinary emphasis.

PolicyDocumentationStructureTest pins all of this. It asserts the page count,
the front matter, the ELI5 box, the exact heading list, the table header, a
single contiguous non-blank marked region per page, that every page shows a
byte-identical example, and that the marked regions advance monotonically in
sidebar order. Verified to fail on each: a removed ELI5 box, an added
heading, a swapped sidebar position and a one-page edit to the example.
The 23 pages under documentation/docs/contributor/technologies were stubs.
Each now explains its concept, says how Ares 2 actually uses it, and links
out for further reading. Every page opens with an ELI5 box.

The pages are written to be read as a chain rather than in isolation: the
AOP vocabulary builds aspect -> join point -> pointcut -> advice -> binding
-> weaving, and the call/execution distinction introduced under "join point"
is what the AspectJ and instrumentation pages then draw their conclusions
from. Where a limit is real it is stated: AspectJ coverage is an enumerated
list of call sites, the AST layer is explicitly not a security boundary, and
LD_PRELOAD does not affect statically linked calls.

On citations. Every URL was checked before it was written down, and again
afterwards as it appears in the files: HTTP status, plus the page title read
back to confirm the link is on topic rather than merely alive. Nine
candidates were rejected during that pass, all of them plausible-looking
guesses that turned out to be 404s, and none of them appear here.

The three medium.com articles were each opened and confirmed to be readable
without a membership, as required. They return 403 to a scripted checker
because of bot protection, not because they are gated. Each is cited with
its author.

Sources are official documentation and repositories first (JUnit, jqwik,
ArchUnit, WALA, AspectJ, Byte Buddy, JavaParser, bubblewrap, the Linux man
pages), then Baeldung, Oracle, W3Schools and Medium. Where no good source
exists it is simply omitted: Baeldung has no jqwik article, so that page
cites the project's own guide instead of something approximate.
@github-actions github-actions Bot added policy Automated area label: policy tests Automated area label: tests labels Aug 7, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/test/java/de/tum/cit/ase/ares/api/policy/PolicyDocumentationStructureTest.java`:
- Around line 137-143: Update the assertions in
PolicyDocumentationStructureTest’s loop over inSidebarOrder so each
markedRangeOf(page) starts exactly at previousLast + 1, eliminating gaps while
preserving ordered non-overlapping coverage. After the loop, assert that the
final previousLast equals the last line of the example to require complete
coverage through the end.
- Around line 155-178: Replace the positional int[] returned by
markedRangeOf(Path) with a MarkedRange(int first, int last) record, preserving
the existing first/last calculations and sentinel values. Update all callers to
use the record’s named first() and last() accessors instead of range[0] and
range[1].
- Around line 83-84: Update the ELI5 validation in
PolicyDocumentationStructureTest so it verifies a closing ::: delimiter
specifically associated with the :::tip ELI5 block, rather than accepting any
directive marker elsewhere in the page. Preserve the existing requirement that
each page contains the ELI5 opening directive.
- Around line 78-81: Restrict front-matter field checks in
PolicyDocumentationStructureTest to group 1 captured by FRONT_MATTER instead of
searching the full page content; at
src/test/java/de/tum/cit/ase/ares/api/policy/PolicyDocumentationStructureTest.java
lines 78-81 update the title, sidebar_position, and description assertions
accordingly, and at lines 180-184 apply SIDEBAR_POSITION to the captured
front-matter content only.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 12220f09-4588-4536-867d-ef251fa65731

📥 Commits

Reviewing files that changed from the base of the PR and between 2ec3280 and a4f4d96.

⛔ Files ignored due to path filters (88)
  • CONTRIBUTING.md is excluded by none and included by none
  • documentation/README.md is excluded by none and included by none
  • documentation/docs/contributor/how-can-you-contribute.md is excluded by none and included by none
  • documentation/docs/contributor/policy/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/policy/class-permission.md is excluded by none and included by none
  • documentation/docs/contributor/policy/command-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/policy/file-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/policy/network-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/policy/package-permission.md is excluded by none and included by none
  • documentation/docs/contributor/policy/programming-language-configuration.md is excluded by none and included by none
  • documentation/docs/contributor/policy/resource-limits.md is excluded by none and included by none
  • documentation/docs/contributor/policy/thread-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/subsystems/aop/BlockCommandSystemAccessAOP.drawio is excluded by none and included by none
  • documentation/docs/contributor/subsystems/aop/BlockCommandSystemAccessAOP.drawio.png is excluded by !**/*.png, !**/*.png and included by none
  • documentation/docs/contributor/subsystems/aop/BlockFileSystemAccessAOP.drawio is excluded by none and included by none
  • documentation/docs/contributor/subsystems/aop/BlockFileSystemAccessAOP.drawio.png is excluded by !**/*.png, !**/*.png and included by none
  • documentation/docs/contributor/subsystems/aop/BlockThreadSystemAccessAOP.drawio is excluded by none and included by none
  • documentation/docs/contributor/subsystems/aop/BlockThreadSystemAccessAOP.drawio.png is excluded by !**/*.png, !**/*.png and included by none
  • documentation/docs/contributor/subsystems/aop/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/subsystems/aop/aspectj-vs-instrumentation-weaknesses.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/aop/block-command-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/aop/block-file-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/aop/block-thread-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/architecture/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/subsystems/architecture/block-command-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/architecture/block-file-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/architecture/block-thread-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/ast.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/jqwik.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/jupiter.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/package-overview.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/phobos.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/policy/SecurityPolicyReaderAndDirectorClassDiagram.drawio is excluded by none and included by none
  • documentation/docs/contributor/subsystems/policy/SecurityPolicyReaderAndDirectorSequenceDiagram.drawio is excluded by none and included by none
  • documentation/docs/contributor/subsystems/policy/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/subsystems/policy/enforcement-model.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/policy/reader-and-director.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/policy/security-policy-manual.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/securitytest/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/subsystems/securitytest/test-case-factory-and-builder.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/aspectj.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/advice.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/aspect.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/binding.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/join-point.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/pointcut.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/weaving.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/instrumentation-with-bytebuddy.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/archunit.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/base-idea/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/base-idea/call-graph.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/base-idea/dfs-path.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/base-idea/node.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/base-idea/rule.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/wala.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/ast-tests/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/technologies/ast-tests/base-idea/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/technologies/ast-tests/base-idea/call-graph.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/ast-tests/base-idea/node.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/ast-tests/base-idea/visitor.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/ast-tests/javaparser.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/jqwik.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/junit-jupiter.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/base-idea/_category_.json is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/base-idea/allow-list.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/base-idea/interception.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/base-idea/wrapper.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/bubblewrap.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/ld-preload-firewall.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/timeout.md is excluded by none and included by none
  • documentation/docs/instructor/ares-2/what-does-ares-2-not-protect-against.md is excluded by none and included by none
  • documentation/docs/instructor/ares-2/what-does-ares-2-protect-against.md is excluded by none and included by none
  • documentation/docs/instructor/ares-2/what-is-ares-2.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/complete-setup-manual.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/further-options.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/policy-configuration.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/postcompile.md is excluded by none and included by none
  • documentation/docs/instructor/transform-ares-1-into-ares-2.md is excluded by none and included by none
  • documentation/docusaurus.config.ts is excluded by none and included by none
  • documentation/sidebar-contributor.ts is excluded by none and included by none
  • documentation/src/css/custom.css is excluded by none and included by none
  • documentation/src/pages/index.tsx is excluded by none and included by none
📒 Files selected for processing (3)
  • .github/labeler.yml
  • README.md
  • src/test/java/de/tum/cit/ase/ares/api/policy/PolicyDocumentationStructureTest.java
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: Analyse Java
  • GitHub Check: Build
  • GitHub Check: Run the maven exercise
  • GitHub Check: Run the gradle exercise
🧰 Additional context used
📓 Path-based instructions (5)
**/*

⚙️ CodeRabbit configuration file

Dogmatically check all reviewed files for current British English in prose, comments, JavaDoc, documentation, workflow names, step names, issue/PR text, labels, user-facing messages, and review suggestions. Flag American spellings and grammar such as behavior, color, initialize, authorization, canceled, and program when they are natural-language text. Do not flag programming-language syntax, dependency coordinates, API names, class names, method names, package names, paths, URLs, quoted external identifiers, or other literals where American English is required by the technology.

Files:

  • README.md
  • src/test/java/de/tum/cit/ase/ares/api/policy/PolicyDocumentationStructureTest.java
**/src/test/**/*.java

📄 CodeRabbit inference engine (AGENTS.md)

**/src/test/**/*.java: Sandboxed Java tests must never start an in-process server, socket listener, or echo server to test incoming or outgoing network connections.
Outgoing-connection tests must connect to an external echo server at a configurable endpoint, currently using loopback port 25565, rather than a self-hosted listener.
If the external echo server is unreachable, abort or skip the test with JUnit Assumptions.abort instead of failing it.
An Ares SecurityException from an explicitly allowed connection must propagate as a real test failure and must never be skipped.
NetworkUser must not start an in-process echo server; connectLocallyAllowed must target the external echo server and skip only when that server is absent.

Files:

  • src/test/java/de/tum/cit/ase/ares/api/policy/PolicyDocumentationStructureTest.java
**/*.java

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.java: Use tabs for indentation, with each tab representing 4 spaces, in Java files.
Use PascalCase for classes and camelCase for fields and methods.
Never declare more than one attribute or method per line.
Prefer records and pattern matching where supported by the Java 17 target.

Files:

  • src/test/java/de/tum/cit/ase/ares/api/policy/PolicyDocumentationStructureTest.java
**/*.{java,xml}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{java,xml}: Do not use wildcard imports; follow the import order defined in .settings/eclipse-rules.importorder.
Use LF line endings, UTF-8 encoding, and a final newline.

Files:

  • src/test/java/de/tum/cit/ase/ares/api/policy/PolicyDocumentationStructureTest.java
src/test/java/**/*.java

📄 CodeRabbit inference engine (CLAUDE.md)

src/test/java/**/*.java: A sandboxed test JVM must never start its own server to test incoming or outgoing connections.
Outgoing-connection tests must target the external loopback echo server on port 25565 and abort with Assumptions.abort when it is unreachable.
An Ares SecurityException on an explicitly allowed operation must propagate; never swallow or skip it.
Every enforcement change must have both a positive test proving the allowed operation works and a negative test proving the forbidden operation remains rejected.

Files:

  • src/test/java/de/tum/cit/ase/ares/api/policy/PolicyDocumentationStructureTest.java

⚙️ CodeRabbit configuration file

Require tests to distinguish fixture failures from sandbox failures. Network tests must not start in-process listeners inside the sandbox; external fixtures may be skipped when absent, but explicit Ares SecurityException failures must propagate.

Files:

  • src/test/java/de/tum/cit/ase/ares/api/policy/PolicyDocumentationStructureTest.java
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T13:37:56.512Z
Learning: Architecture and AOP changes must be checked against all affected combinations: ArchUnit plus AspectJ, ArchUnit plus instrumentation, WALA plus AspectJ, and WALA plus instrumentation.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T13:37:56.512Z
Learning: Use concise, imperative commit messages describing the change rather than its implementation.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T13:37:56.512Z
Learning: Target `main` and rebase rather than merge to keep history readable.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T13:37:56.512Z
Learning: Update documentation in the same pull request as the user-facing change it describes.
🔇 Additional comments (4)
.github/labeler.yml (1)

7-17: LGTM!

Also applies to: 32-33, 52-52

README.md (1)

1-75: LGTM!

src/test/java/de/tum/cit/ase/ares/api/policy/PolicyDocumentationStructureTest.java (2)

1-75: LGTM!


85-136: LGTM!

Also applies to: 146-154, 179-179, 189-210

Closes the tooling gap against the Artemis documentation, and fixes a
defect the new tests immediately found.

The defect first. 53 admonitions across 47 pages, including every one of
the 31 ELI5 boxes, were rendering as literal paragraph text beginning with
three colons. Docusaurus 3 takes the title as a remark-directive label,
':::tip[ELI5]'; the Docusaurus 2 form ':::tip ELI5' is not a directive at
all. Nothing warns about it: the build succeeds, the page renders, the box
is simply absent. It was invisible to every check that reads the source and
only showed up once a browser looked at the built page.

Diagnosis is worth recording, because two plausible explanations were wrong.
It is not 'markdown.format: detect' (a .md file with the bracket syntax
renders fine, and dropping the setting breaks the migrated manuals with MDX
errors), and it is not a missing 'admonitions' plugin option (the option was
added, changed nothing, and has been removed again rather than left in as
cargo cult). A four-way probe isolated the title syntax as the only variable
that mattered.

Added:

- ESLint over the site sources, configured as in Artemis and extended to the
  Node-based diagram renderer. Verified to cover all 8 files and to fail on
  an unused variable.
- Playwright integration tests driving the built site through
  'docusaurus serve', at the /Ares2/ base path the site is deployed under.
  Ten tests: navigation between the guides, a cross-guide absolute route,
  each sidebar, the red marking on all eight policy pages, that the marking
  is actually coloured rather than merely classed, search indexes for both
  guides, the 404 page, and the ELI5 boxes.
- npm-check-updates as 'pnpm run update'.
- TechnologiesDocumentationStructureTest, which pins the shared page shape
  and enforces the citation policy: an allow list of hosts, at least two
  sources per page, and a recorded readability check on every Medium link.
- SubsystemsDocumentationStructureTest, which pins the contract that holds
  across a section that is deliberately not uniform: front matter, no
  competing h1, honest stub marking, ordered categories, and the ten long
  reference manuals pinned by name so one cannot be truncated unnoticed.
- AdmonitionSyntaxTest, which fails the Maven build on the syntax above so
  the defect cannot return.

Two bugs in the new tests themselves were found and fixed before this
landed: the h1 check matched '#' comments inside fenced code blocks, and the
manual count was asserted as a number rather than a set. Both now use a
fence-aware helper and a pinned list.

The three Phobos base-idea pages predated the technology template and had
neither an ELI5 box nor a further-reading section; they now match.

CI runs lint and the integration tests alongside the existing steps.
Verified locally: lint, typecheck, diagrams:check, build, 10 Playwright
tests, 153 documentation structure tests, spotless, checkstyle, pmd/cpd.
@github-actions github-actions Bot removed the policy Automated area label: policy label Aug 7, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

♻️ Duplicate comments (2)
src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java (2)

140-146: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Require complete contiguous coverage of the example.

Line 143 prevents overlap only. It permits a gap before, between, or after marked sections. Require each range to start at the previous range end plus one. After the loop, require the final range to end at the last example line.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java`
around lines 140 - 146, Update the range validation loop in
PolicyDocumentationStructureTest to require each markedRangeOf(page) range to
begin exactly at previousLast + 1, eliminating gaps while preserving ordered
traversal. After the loop, assert that the final previousLast equals the last
line of the example so coverage is complete through the end.

142-145: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the positional int[] with a record.

Use MarkedRange(int first, int last) instead of int[]. Named accessors make the ordering assertions and sentinel values unambiguous.

#!/bin/bash
set -euo pipefail

# Confirm that the repository compiler target supports Java records.
if [ -f pom.xml ]; then
  rg -n -C 2 '<maven\.compiler\.(release|source|target)>|<java\.version>|<release>' pom.xml
fi

Also applies to: 158-180

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java`
around lines 142 - 145, Replace the positional int[] returned by page range
handling with a MarkedRange(int first, int last) record, updating its
declaration and all usages in the relevant assertions. Use range.first() and
range.last() instead of numeric indexes, including sentinel and ordering checks,
while preserving the existing validation behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/test/java/de/tum/cit/ase/ares/documentation/AdmonitionSyntaxTest.java`:
- Around line 38-40: Update the scanning logic in AdmonitionSyntaxTest around
LEGACY_ADMONITION to process Markdown line by line with fenced-code state
tracking, including both opening and closing fences, and apply the matcher only
to text outside fenced blocks. Preserve the existing offender formatting while
ensuring legacy directives inside fenced examples are not reported.

In `@src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java`:
- Around line 98-106: Scope front-matter validation to the captured YAML block
rather than the complete page. In
src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java:98-106,
expose the captured front-matter content and make sidebarPosition operate only
on that content; update required-field validation in
src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java:78-81
and sidebar-position validation at :183-187 to use it. In
src/test/java/de/tum/cit/ase/ares/documentation/SubsystemsDocumentationStructureTest.java:84-88
and TechnologiesDocumentationStructureTest.java:76-80, replace page-wide checks
with the scoped shared helpers.

---

Duplicate comments:
In
`@src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java`:
- Around line 140-146: Update the range validation loop in
PolicyDocumentationStructureTest to require each markedRangeOf(page) range to
begin exactly at previousLast + 1, eliminating gaps while preserving ordered
traversal. After the loop, assert that the final previousLast equals the last
line of the example so coverage is complete through the end.
- Around line 142-145: Replace the positional int[] returned by page range
handling with a MarkedRange(int first, int last) record, updating its
declaration and all usages in the relevant assertions. Use range.first() and
range.last() instead of numeric indexes, including sentinel and ordering checks,
while preserving the existing validation behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f36dfb28-ccab-4127-bc78-1352e2693c3c

📥 Commits

Reviewing files that changed from the base of the PR and between a4f4d96 and c6d50fa.

⛔ Files ignored due to path filters (59)
  • CONTRIBUTING.md is excluded by none and included by none
  • documentation/.gitignore is excluded by none and included by none
  • documentation/README.md is excluded by none and included by none
  • documentation/docs/contributor/policy/class-permission.md is excluded by none and included by none
  • documentation/docs/contributor/policy/command-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/policy/file-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/policy/network-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/policy/package-permission.md is excluded by none and included by none
  • documentation/docs/contributor/policy/programming-language-configuration.md is excluded by none and included by none
  • documentation/docs/contributor/policy/resource-limits.md is excluded by none and included by none
  • documentation/docs/contributor/policy/thread-system-access.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/ast.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/jqwik.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/jupiter.md is excluded by none and included by none
  • documentation/docs/contributor/subsystems/phobos.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/aspectj.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/advice.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/aspect.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/binding.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/join-point.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/pointcut.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/base-idea/weaving.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/aop-tests/instrumentation-with-bytebuddy.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/archunit.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/base-idea/call-graph.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/base-idea/dfs-path.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/base-idea/node.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/base-idea/rule.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/architecture-tests/wala.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/ast-tests/base-idea/call-graph.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/ast-tests/base-idea/node.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/ast-tests/base-idea/visitor.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/ast-tests/javaparser.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/jqwik.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/junit-jupiter.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/base-idea/allow-list.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/base-idea/interception.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/base-idea/wrapper.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/bubblewrap.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/ld-preload-firewall.md is excluded by none and included by none
  • documentation/docs/contributor/technologies/linux-based-security/timeout.md is excluded by none and included by none
  • documentation/docs/instructor/ares-2/what-does-ares-2-not-protect-against.md is excluded by none and included by none
  • documentation/docs/instructor/ares-2/what-does-ares-2-protect-against.md is excluded by none and included by none
  • documentation/docs/instructor/ares-2/what-is-ares-2.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/further-options.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/github-packages.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/gradle.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/installation.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/maven.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/policy-configuration.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/postcompile.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/precompile.md is excluded by none and included by none
  • documentation/docs/instructor/protect-a-java-project/test-annotations.md is excluded by none and included by none
  • documentation/eslint.config.mjs is excluded by none and included by none
  • documentation/package.json is excluded by none and included by none
  • documentation/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml and included by none
  • documentation/tests/navigation.spec.ts is excluded by none and included by none
  • documentation/tests/playwright.config.ts is excluded by none and included by none
  • documentation/tests/tsconfig.json is excluded by none and included by none
📒 Files selected for processing (6)
  • .github/workflows/documentation.yml
  • src/test/java/de/tum/cit/ase/ares/documentation/AdmonitionSyntaxTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java
  • src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/SubsystemsDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/TechnologiesDocumentationStructureTest.java
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Integration Tests (WALA + instrumentation)
  • GitHub Check: Core Integration Tests
  • GitHub Check: Unit Tests
🧰 Additional context used
📓 Path-based instructions (8)
**/src/test/**/*.java

📄 CodeRabbit inference engine (AGENTS.md)

**/src/test/**/*.java: Sandboxed Java tests must never start an in-process server, socket listener, echo server, or other connection counterpart for testing incoming or outgoing network connections.
Outgoing-connection tests must connect to an external echo server at a configurable endpoint, currently port 25565, with the server running in a separate process or CI service.
If the external echo server is unreachable, tests must skip using JUnit Assumptions.abort rather than fail.
An Ares SecurityException from an explicitly allowed connection must propagate as a test failure and must never be treated as a reason to skip.
Do not hard-code a self-hosted listener as the connection counterpart; use the external echo service instead.
NetworkUser must not start an in-process echo server; connectLocallyAllowed must target the external echo server and skip when it is absent.

Files:

  • src/test/java/de/tum/cit/ase/ares/documentation/AdmonitionSyntaxTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java
  • src/test/java/de/tum/cit/ase/ares/documentation/TechnologiesDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/SubsystemsDocumentationStructureTest.java
**/*.{java,xml}

📄 CodeRabbit inference engine (CLAUDE.md)

Use tabs for indentation, with each tab representing 4 spaces, in Java and XML files.

Files:

  • src/test/java/de/tum/cit/ase/ares/documentation/AdmonitionSyntaxTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java
  • src/test/java/de/tum/cit/ase/ares/documentation/TechnologiesDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/SubsystemsDocumentationStructureTest.java
**/*.java

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.java: Do not use wildcard imports in Java files; follow the import order defined in .settings/eclipse-rules.importorder.
Use PascalCase for Java classes and camelCase for fields and methods.
Never declare more than one attribute or method per line in Java files.
Prefer records and pattern matching where supported by Java 17.

Files:

  • src/test/java/de/tum/cit/ase/ares/documentation/AdmonitionSyntaxTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java
  • src/test/java/de/tum/cit/ase/ares/documentation/TechnologiesDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/SubsystemsDocumentationStructureTest.java
**/*.{java,xml,md,mdx,json,yaml,yml}

📄 CodeRabbit inference engine (CLAUDE.md)

Use LF line endings, UTF-8 encoding, and a final newline, as specified by .editorconfig.

Files:

  • src/test/java/de/tum/cit/ase/ares/documentation/AdmonitionSyntaxTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java
  • src/test/java/de/tum/cit/ase/ares/documentation/TechnologiesDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/SubsystemsDocumentationStructureTest.java
src/test/java/**/*.java

📄 CodeRabbit inference engine (CLAUDE.md)

src/test/java/**/*.java: A sandboxed test JVM must never start its own server to test incoming or outgoing connections.
Outgoing-connection tests must target the external echo server on loopback port 25565 and abort with Assumptions.abort when it is unreachable.
An Ares SecurityException on an explicitly allowed operation must propagate and must never be swallowed or used to skip the test.
Every new enforcement feature must have both a positive test proving the allowed operation works and a negative test proving the forbidden operation remains rejected.

Files:

  • src/test/java/de/tum/cit/ase/ares/documentation/AdmonitionSyntaxTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java
  • src/test/java/de/tum/cit/ase/ares/documentation/TechnologiesDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/SubsystemsDocumentationStructureTest.java

⚙️ CodeRabbit configuration file

Require tests to distinguish fixture failures from sandbox failures. Network tests must not start in-process listeners inside the sandbox; external fixtures may be skipped when absent, but explicit Ares SecurityException failures must propagate.

Files:

  • src/test/java/de/tum/cit/ase/ares/documentation/AdmonitionSyntaxTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java
  • src/test/java/de/tum/cit/ase/ares/documentation/TechnologiesDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/SubsystemsDocumentationStructureTest.java
**/*

⚙️ CodeRabbit configuration file

Dogmatically check all reviewed files for current British English in prose, comments, JavaDoc, documentation, workflow names, step names, issue/PR text, labels, user-facing messages, and review suggestions. Flag American spellings and grammar such as behavior, color, initialize, authorization, canceled, and program when they are natural-language text. Do not flag programming-language syntax, dependency coordinates, API names, class names, method names, package names, paths, URLs, quoted external identifiers, or other literals where American English is required by the technology.

Files:

  • src/test/java/de/tum/cit/ase/ares/documentation/AdmonitionSyntaxTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/PolicyDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/DocumentationPages.java
  • src/test/java/de/tum/cit/ase/ares/documentation/TechnologiesDocumentationStructureTest.java
  • src/test/java/de/tum/cit/ase/ares/documentation/SubsystemsDocumentationStructureTest.java
**/.github/workflows/*.{yml,yaml}

📄 CodeRabbit inference engine (Custom checks)

GitHub Actions workflows must use least-privilege permissions, avoid exposing secrets to untrusted pull-request code, and never use unsafe pull_request_target checkout patterns.

Files:

  • .github/workflows/documentation.yml
.github/workflows/**/*.yml

⚙️ CodeRabbit configuration file

Review GitHub Actions for least-privilege permissions, safe event choice, pinned third-party actions, safe pull_request_target usage, no secret exposure to untrusted code, and branch-protection compatibility.

Files:

  • .github/workflows/documentation.yml
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T15:23:14.306Z
Learning: Read `CLAUDE.md` first; it is the repository's single source of truth for project structure, build and test commands, coding style, and pull-request processes.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T15:23:21.224Z
Learning: Architecture or AOP changes must be checked against all affected combinations of ArchUnit and WALA with both AspectJ and instrumentation.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T15:23:21.224Z
Learning: Update documentation in the same pull request as the user-facing change it describes.
Learnt from: CR
Repo: ls1intum/Ares2

Timestamp: 2026-08-07T15:23:21.224Z
Learning: Fill in every section of `.github/PULL_REQUEST_TEMPLATE.md`, including the negative case and the mode combinations exercised.
📚 Learning: 2026-07-14T16:44:59.365Z
Learnt from: MarkusPaulsen
Repo: ls1intum/Ares2 PR: 114
File: .github/workflows/pullrequest-labeler.yml:0-0
Timestamp: 2026-07-14T16:44:59.365Z
Learning: When reviewing GitHub Actions workflows, it can be acceptable to use `pull_request_target` (instead of `pull_request`) for jobs that need write access (e.g., auto-labeling) when fork PR tokens are read-only. Only consider it safe if the job does NOT check out or execute untrusted PR code, and it reads required configuration from the base ref (e.g., `.github/labeler.yml`) rather than from the PR. Enforce least-privilege permissions (e.g., `contents: read` and the minimum required `pull-requests: write`) and avoid any steps that would run code from the PR branch.

Applied to files:

  • .github/workflows/documentation.yml
🔇 Additional comments (2)
.github/workflows/documentation.yml (2)

72-74: LGTM!

Also applies to: 94-97, 102-105


98-100: 🩺 Stability & Availability

No change needed.

The test command runs the default Playwright browser project via playwright test --config tests/playwright.config.ts, and the workflow installs Chromium with playwright install --with-deps --only-shell chromium.

Comment thread src/test/java/de/tum/cit/ase/ares/documentation/AdmonitionSyntaxTest.java Outdated
The coverage matrix across the structure tests had blanks in it. Some were
deliberate, two were gaps I had not noticed, and one was a rule I had asked
for and then only half applied. Filling it in turned out to be worth more
than the tidiness suggested.

The half-applied rule first. Every chapter was supposed to open with an ELI5
box. 34 of 66 pages had one; the 15 instructor pages, the 16 subsystem pages
and the contributing page did not. All 32 now do, each written for its own
subject rather than templated, and all 66 render as boxes in the built site.

Two real gaps in the policy test, both one-liners, both now closed: it never
checked for a stray h1, and it only required sidebar_position to exist rather
than to be positive. It was the strictest test about what was unique to it
and the loosest about the basics.

AdmonitionSyntaxTest becomes SiteWideDocumentationStructureTest and grows
from one rule to five. It now owns the floor that applies to every page of
both guides: front matter and its three fields, a positive sidebar_position,
no competing h1, an ELI5 box, at least one section, and no admonition written
in the form that renders as plain text. A section added later inherits all of
that without anyone remembering to write a test for it.

Making "at least one section" hold everywhere exposed five pages with no
headings at all. Four were subsystem stubs, which are now written properly
from the package overview: the Jupiter and jqwik bindings, the AST package
and Phobos. The fifth was the trust-boundary page, which had real content in
one undivided block and is now split into three sections. The subsystem
section no longer contains a single stub.

Writing those four pages introduced four broken relative links, all of them
'../' where the files are siblings. onBrokenLinks caught every one before
the commit, which is the setting earning its keep for the second time.

419 documentation structure tests, 10 Playwright tests, lint, typecheck,
spotless, checkstyle and PMD all pass.

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@MarkusPaulsen The new commit fixes all three Claudia findings: the generator guide matches the two-argument API, the Gradle main-class name is valid, and both comparison parsers handle the migrated headings and reject empty parses. However, two functional findings from CodeRabbit’s non-dismissed review remain: the precompile negative-control instructions contradict themselves about the operation and expected build result, and the stale-path test still skips an entire line whenever it contains a URL. Those existing findings must be addressed before approval; no duplicate inline comments are added here.

@MarkusPaulsen

Copy link
Copy Markdown
Collaborator Author

Pushed 47b6e95, addressing the two outside-diff findings from CodeRabbit's review body that @Claudia-Anthropica flagged as still open. Both were real. The third finding in that block, the duplicated comma in .github/PULL_REQUEST_TEMPLATE.md, is already fixed on this head: it came in with the main merge, and the file now has no doubled comma.

The negative control contradicted itself. "The two controls that matter" defines the negative control as a forbidden read of secret.txt that the test asserts, and states that a correct run is green. Two hundred lines later, "Run the tests" described attempting to write secret.txt and said the test run fails. A reader could not tell whether to assert the exception or expect a red build, which is exactly the decision that section exists to settle.

It now describes the same read, asserted, with the run staying green, and says what each other outcome means: a red run is a test that has not asserted its negative control yet, while a green run with no exception at all is the one to worry about, because it says the read was permitted. The stack trace stays as it is, since security.advice.illegal.file.execution is the only file key in messages.properties and its "Stage: Execution" names the stage rather than the operation.

A URL took the whole line with it. nothingNamesTheRemovedDocumentationTree skipped any line containing ://, so a line naming a repository path beside a link, which is most of how documentation is written, was never checked. The URLs are now blanked out of the line instead of the line being dropped, through a withoutUrls(line) that replaces each URL with a space so a following path does not glue onto the word before it.

Worth noting: unskipping those lines found no hidden stale reference, so this closes a gap rather than fixing a live break. aUrlHidesItsOwnPathsAndNotTheRestOfTheLine pins both halves, that the path beside a URL is found and that the URL itself is gone, so this cannot quietly revert to line-skipping.

Verified at this head: 1341 tests pass under unit-core-tests, spotless:check, checkstyle:check and pmd:check are clean, and the Docusaurus build succeeds.

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@MarkusPaulsen The new head resolves both remaining functional findings: the Precompile guide consistently describes an asserted forbidden read with a green test run, and the stale-path scan removes URL spans while continuing to inspect the rest of each line, with focused regression coverage. The earlier generator CLI, Gradle main-class, and pointcut-parser corrections also remain present; the snapshot contains no relevant completed CI failure and lists no required check awaiting completion.

Markus Paulsen and others added 4 commits August 21, 2026 12:19
The documentation had no check on its prose. Adding one is only safe if it
separates the rules a machine can decide from the rules it cannot, so this
scanner does that separation and nothing else yet.

An enforced rule fails the build, and earns that only when its forbidden form
is decidable from the text alone: `doesn't` is a contraction in every sentence
there is. An advisory rule is reported and never fails, because `may` is
permission, possibility or uncertainty depending on the sentence around it.
"The static analysis may report false positives" is correct English, and a
rule that rewrote it to `must` would state a guarantee the code does not make.
In documentation for a security tool that is worse than the style problem it
fixes.

A line scanner cannot do this job. It has to be taught inline code, indented
code, reference links, link labels as against link targets, tables, block
quotations, HTML, directives, YAML quoting and escaped punctuation, and it
still reports a string rather than a file, a line and a column. The tree knows
all of that already.

Eligible prose is every surface a reader reads: paragraphs, headings and table
cells, the `title` and `description` of the front matter, the `alt` of an
image, and the `label` of a `_category_.json`. MDX is parsed rather than
forbidden, so a page using it later is not invisible.

The fixtures are the point of the commit rather than an accompaniment. Two
defects fell out of writing them: `just-in-time` matched the filler rule
through the hyphen, and image alt text was never reached at all because an
image is inline. Both are pinned now, along with quoted licence text, quoted
error output, `best-effort`, four-column indented code and a tilde fence
holding a backtick fence.
A rule enforced by a check nobody can find reads as an obstacle rather than a
standard, so the standard lands before the first rule starts failing builds.

The page states which rules are enforced and which are advisory, and why the
line falls there. It also records the four decisions the AET rules could not
answer for a two-audience reference site: who "you" is, that cross-references
are allowed here, which of the code-ownership terms are synonyms, and how
often an abbreviation is spelled out.

The terminology decision is the one worth reading twice. "Student code" and
"restricted code" are one concept, "test code" and "trusted code" are another,
and "supervised code" is a third thing that keeps its own name because it
names the package boundary Ares reserves for itself. Collapsing that third one
into the first would have erased a distinction Ares enforces.
Every enforced rule is now clean across all 97 pages: 232 findings fixed, and
the ratchet holds the line from here.

What changed, by rule:

- 145 abbreviations spelled out at their first use on a page.
- 28 contractions written out.
- 22 uses of `additionally` and one of `of course` deleted.
- 18 sentences reopened with their subject rather than with `As`, `To` or
  `Because`.
- 12 terms brought onto one name: `restricted code` to `student code`, and
  `trusted code` to `test code`.
- 7 American spellings corrected. `defence-in-depth` was already written that
  way on one of the three pages that used it, so this settles an inconsistency
  rather than imposing a preference.

The 425 advisory findings are untouched on purpose. Each is a judgement about
what a sentence means, and `pnpm run report:prose` lists them.

Three traps worth recording, all found by reading the output rather than by
reasoning about it. Expanding an abbreviation blindly produced
`in-Java Virtual Machine (JVM)` from `in-JVM`, so the rule now refuses to
expand a use glued to a hyphen. It also produced
`(continuous integration (CI)/CD pipelines)`, so it now prefers a use outside
brackets. And on 17 pages every single use sits inside brackets, a table cell
or a link label, where spelling the term out reads worse than leaving it;
those are recorded in the baseline with that reason rather than forced.

Nothing about the site's structure moved: the build still passes with
`onBrokenAnchors` set to `throw`, the 12 browser tests still pass, and the 644
Markdown structure tests still pass. No heading was reworded, so no anchor
changed.
Documentation: hold the prose to the writing rules a check can decide

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@MarkusPaulsen The new prose gate has two false-negative paths: it accepts abbreviations expanded only after their first use, and it drops reader-visible text inside MDX JSX elements. The captured documentation / Build Docusaurus site check is red, but its only annotation is a generic exit code 1 with no failed-step output, so I could not independently attribute that CI failure and am not treating it as a separate finding. The earlier documentation findings remain resolved.

Comment thread documentation/scripts/prose/prose.test.mjs
Comment thread documentation/scripts/prose/prose.test.mjs
Markus Paulsen added 6 commits August 21, 2026 15:15
Every documentation page opens with an intro admonition, and each one used to
invent its own metaphor: fences, doors, mazes, phone books, shops, maps of dots.
Individually good, collectively incoherent, so a reader moving between pages
re-learned the imagery each time.

The box is now called Simple Story, and all 96 sit inside one scenario. The
student's methods are pupils, JUnit and jqwik are the teachers, Ares is the
checklist the teacher works at every desk, and the checklist has three parts:
the room (Phobos), reach (the architecture layer) and use (the AOP layer). The
cast is written down in CLAUDE.md so later pages do not drift from it.

Each box is self-contained. Search drops readers on arbitrary pages, so none of
them depends on another having been read.

Also settles the "test case" ambiguity the documentation carried in both
directions: test method for what the instructor wrote, security test case for
what Ares generates.

Three pre-existing claims were wrong and are corrected rather than carried over:
an empty policy file is rejected on load rather than being the strictest policy;
the introductory security guarantee was absolute where the AspectJ weaknesses
page documents blind spots; and the both-directions testing rule applies to
enforcement changes, not to every change.

Verified: 640 documentation structure tests, strict Docusaurus build with
onBrokenLinks and onBrokenAnchors set to throw, 12 Playwright tests, spotless,
and a per-file line-ending manifest showing no renormalisation across the 96
pages.
The hero led with two buttons that repeated links already on the page. It now
says plainly what problem Ares 2 solves, so a visitor who has never heard of it
learns that from the first screen rather than from a button label.

The feature list gains jqwik, which was supported but unmentioned, and loses a
line that wrapped at every width.

Adds an imprint and a privacy statement, reachable from a new Legal column in
the footer. Both follow the TUM wording used on artemis.tum.de, adapted where
this site genuinely differs. The important difference is hosting: this site is
served by GitHub Pages rather than by TUM ITO, so visitor IP addresses reach
GitHub and are transferred to the USA. That is disclosed, along with the option
of building the documentation locally instead.

Claims about cookies, third-party content and search are deliberately narrow.
They describe what the documentation application does, not what the hosting
provider does, and a new Playwright test asserts the two that are checkable:
no request leaves the origin, and no cookie is set. A dependency bump that
broke either would fail the suite rather than quietly making the prose false.

The test for the removed button is replaced rather than deleted: the hero copy
and both legal pages are now covered.
The page on what Ares 2 protects against listed resources and then spent most
of its length on compile modes. It now leads with the question an instructor
actually has: what can I allow, and what will never be allowed whatever I write
in the policy.

That split is taken from the code rather than from prose. Five categories have
a policy field and can be granted narrowly: file system, network, command
execution, thread creation and package imports. Nine have no field at all:
reflection, native code, class loading, JVM termination, agent attach, module
system, serialisation, JNDI and environment access. For most of the nine an
ordinary exercise simply has no use for them; for reflection, class loading and
agent attach a narrow grant would not stay narrow, since each reaches every
other category.

Two things the page previously implied are now stated correctly, because both
change what an instructor should expect:

- Granting anything in a category drops its architecture check and makes the
  category runtime-only. Static analysis cannot tell a permitted path from a
  forbidden one, so it steps aside as soon as a list is non-empty.
- The nine have no runtime enforcement of their own. An individual call may
  still be caught where it overlaps a category that does, but that is a
  coincidence to know about rather than a guarantee to rely on.

The page on what Ares 2 does not protect against now separates what a sandbox
cannot attempt from where this implementation is thin. Plagiarism leads the
first group: Ares watches what a submission does and has no view of whether it
is the student's own work, so a copied solution inside the policy passes exactly
like an honest one. Solution quality, the exercise's own dependencies and the
host infrastructure follow. The thin spots are the nine static-only categories,
AspectJ being weaker than instrumentation, and a policy timeout that parses
without bounding anything.

Elsewhere: the sandboxing goal now names academic integrity, fairness and the
learning goal; "Artemis" leaves the public and hidden test bullet, since neither
depends on Artemis; the usability warning is less severe than it read; and
"Where to go next" follows the sidebar so reading down it matches working
through the guide.
The rebase onto the writing-rules work left fifteen enforced findings. Six were
the ones already on the pull request, where a page had moved under the baseline
and its identity no longer matched. Nine were new: the Simple Story rewrite
replaced the boxes that used to carry an expansion, and the rewritten prose
opened two sentences with "As" and "To".

Rather than accepting them, each page now spells the abbreviation out once. The
check is satisfied by the expansion appearing anywhere in body text, not by it
appearing at the first use, so a bracketed or tabular first use is fixed by
writing the long form at the place it reads best rather than by nesting one pair
of brackets inside another.

That also clears the seventeen findings the baseline had accepted, whose stated
reason was that expanding them in place read worse. It did; expanding them
elsewhere does not. `baseline.json` is now empty, so the ratchet starts from
zero and any enforced finding from here on is a new one.

Two sentences were reopened on their subject, and "CI/CD pipelines" is now "a
continuous integration (CI) pipeline" on the three pages that carried it.

Verified: pnpm run lint:prose reports 0 enforced, and pnpm run build succeeds.
The Outline writing rules give one list of filler words and call it absolute:
additional, furthermore, moreover, also, actually, clearly, obviously. Three of
them were enforced here. The other three were advisory, because the corpus used
them in 139 places and enforcing a word a hundred pages still carry means
shipping a baseline instead of a rule.

This is the clean-up. Every one of the 139 is gone from the pages, so the rule
can be enforced in the commit that follows.

Most were deletions: "before the command is actually executed" says exactly what
"before the command is executed" says. Where the word carried meaning it was
replaced by a word that carries it plainly, so nothing is lost and nothing needs
a suppression:

- "and" for another entry in a list, as in "(and the timed overload)";
- "further" for one more of something, as in "one further fail-closed rule";
- "as well" or "too" for an addition, as in "runs on the same attributes as well".

Three headings changed. "## See also" becomes "## Further reading" on the three
policy pages that had it, matching the technologies section, and no page linked
to the old anchor. "What the policy-free configuration actually restricts" loses
the word, and nothing linked to that anchor either.

The imprint loses an American spelling in a heading and a "Furthermore" that the
sentence beneath it does not need.

Verified: 644 documentation structure tests, 15 Playwright tests, a strict
Docusaurus build, and pnpm run lint:prose reporting 0 enforced.
The writing rules on this site implemented nine of the thirteen Outline rules
and said nothing about the other four, which reads as an oversight rather than a
decision. Advisory findings had no ratchet at all, so 1,000 of them could become
1,500 without anything noticing. And the check read only `docs/`, so the landing
page, the imprint, the privacy statement and every navbar and footer label were
held to no rule at all.

**The four rules that were missing.** Two are now checked and two are recorded as
unchecked, with the reason:

- `active-voice` reports a form of "to be" followed by a participle. Advisory,
  because "is interested" is an adjective wearing the same clothes; participles
  this corpus uses as plain states are named in the rule's allow list.
- `long-sentence` reports a sentence past 35 words, roughly two lines here. The
  Outline rule asks for short sentences with the verb early. Length is
  measurable, whether the length is earned is not.
- Using `can` only where something is optional, and defining a specialised term
  at first use, have no check and are not getting one. Both now have a row on the
  writing-rules page saying why.

**The filler rule is now the whole list.** `also`, `actually` and `additional`
join the enforced rule, which the previous commit made possible.

**The advisory ceiling.** `advisory-ceiling.json` records how many findings each
advisory rule is allowed. Over it fails; under it is reported so the number can
be lowered. A rule with no entry has a ceiling of zero, so adding a rule and
forgetting to record it fails rather than passing. The rule caught its own
author twice while this page was being written.

**Three surfaces added.** `src/pages/**` and the navbar, footer, tagline and
copyright strings in `docusaurus.config.ts` and the two sidebar files are read
now. The TypeScript is read lexically, not parsed: a parser would pull a
TypeScript toolchain into a check that runs before the build.

**The page and the code can no longer drift.** `test:prose` parses the three
tables on the writing-rules page and compares them with the levels in
`rules.mjs`. A rule promoted in the code and left in the advisory table fails, so
does one listed on the page that the code does not define. That page previously
said outright that nothing detected this.

The page also loses its stale ELI5 wording: the box has been Simple Story since
the rename, which is two ordinary words and needs no exemption.

Verified: 51 scanner fixtures, pnpm run lint:prose green, eslint, tsc, a strict
Docusaurus build, 644 documentation structure tests and 15 Playwright tests.

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@MarkusPaulsen [medium] abbreviationFindings still accepts an expansion anywhere after an abbreviation’s first use. [medium] flatten() still discards inline MDX JSX elements, while flow JSX elements are not traversed. [medium] The new TS/TSX scan only examines colon-keyed strings and literal >text<, so landing-page strings rendered through {features.map(...)} and prose split by JSX expressions bypass every rule; traverse reader-visible TS/TSX nodes and add focused fixtures. The completed documentation build succeeded, but these current-head false-negative paths keep the prose gate from enforcing its documented coverage.

Markus Paulsen added 2 commits August 21, 2026 16:07
A cross-model review of the previous commit found ten defects. All ten are
fixed here, and every one that could be reproduced has a fixture.

**The report was truncated at 64 KB.** `process.exit` does not wait for stdout
to drain, and writing to a pipe is asynchronous, so `pnpm run report:prose > f`
produced a file that did not parse the moment the report outgrew the pipe
buffer. The exit code is now set and the process left to end on its own. The
report is 500 KB and parses.

**The TypeScript scan read the raw source and got it wrong three ways.** A
regex cannot tell `// label: 'also'` from a property, `left > also < right`
from a tag, or a JSX snippet quoted inside a code sample from the page's own
words. All three reported enforced findings against text no reader sees, which
would have failed continuous integration on code. It also missed what it was
for: `<p>The color {value} is here.</p>` produced nothing, because the brace
split the text, and `alt="..."` was never read at all.

The scanner now parses with TypeScript, which is already a dependency. Node
kinds replace patterns, `node.text` gives the decoded value so an escaped
apostrophe reads as a contraction, and a finding inside a string is reported at
the string rather than at a column the decoded text cannot stand behind.

**The passive rule matched suffixes, not participles.** "The grass is green"
and "it is often wrong" were reported; a list of words that end in `ed` or `en`
without being participles now excludes them. The lower bound was also wrong:
`\w{3,}` needs five characters, so "is used" was missed. The exception check
matched anywhere within forty characters, so "access is allowed" excused "the
call is blocked" in the same sentence; an exception now has to cover the match.

**Both ratchets only bit upwards.** A count that fell below its ceiling was
mentioned and passed, so a ceiling of 100 against a true 90 left ten findings
of room for the next change to spend. Falling now fails too, as does a fixed
finding still in the baseline, a ceiling value that is not a whole number, and
a ceiling entry for a rule that no longer exists.

**Smaller ones.** `of course` used a literal space and so missed a Markdown
line wrap. `long-sentence` skipped front matter and every string in the source.
`No.` was treated as an abbreviation, which swallowed the sentence after it.
The fixture for the unchecked-rules table read first cells only, and that table
has none, so it checked nothing.

The page said advisory rules "never fail" four lines above the section saying
their counts do.

Verified: 61 scanner fixtures, lint:prose green at 0 enforced and 1,192
advisory, eslint, tsc, a strict build, 644 structure tests, 15 browser tests.
A second review pass over the previous commit. Six of the eight remaining
findings were real, and each has a fixture.

**A code component's children were read as prose.** `<CodeBlock>also</CodeBlock>`
produced an enforced finding, which is the Markdown scanner's fenced-block rule
broken in the one place it does not apply. Text inside a code component is
skipped now, and a template between JSX tags is skipped with it: every snippet
on the landing page is written that way, and a template there is a code sample
far more often than a sentence. A quoted string in braces stays prose.

**A quoted property name was not a name.** `{ 'label': '...' }` reads its name
through `getText`, which returns the quotes with it, so the property was skipped.
It reads `.text` now.

**A finding pointed at the key rather than at the text.** The comment claimed the
string's start; the code passed the whole property. Now it passes the value.

**Visible strings outside a key were unread.** The landing page holds its feature
list in a plain array, and a reader sees every entry. An array element in a page
counts as prose now. Configuration files keep to their named keys, where an array
holds document identifiers rather than sentences.

**Sentence length skipped two surfaces** it was said to cover: image alt text and
sidebar labels.

**A stale ceiling entry failed without saying so**, because the problems were
printed before that check appended to them.

`indeed` joins the words that end in `ed` without being participles.

Two findings are answered rather than fixed, and the reasons are in the code:
the passive rule cannot see "is not blocked" or "is read" without a verb list,
and the unchecked-rules fixture can catch a rule identifier written into that
table but not a rule described there in words and implemented under another
name. The page already says a change of level is a change to the page.

Verified: 67 scanner fixtures, lint:prose green at 0 enforced and 1,192
advisory against the recorded ceiling, eslint, tsc, a strict build, 644
structure tests, 15 browser tests.

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@MarkusPaulsen The current head improves TS/TSX extraction and all captured checks pass, but it does not resolve the two open scanner findings: abbreviation expansion is still accepted anywhere on the page, and MDX JSX children are still discarded. The source scanner also returns an empty body and accumulates only word, opener, and length findings, so abbreviation-first-use is never enforced for reader-visible TS/TSX strings. These current-head false negatives keep the prose gate from matching its documented coverage.

Three findings from Claudia's review of the previous head, all correct, all
false negatives in the gate itself.

**An expansion anywhere on the page counted.** `abbreviationFindings` tested the
expansion against the whole page, so "The JVM starts. Java Virtual Machine (JVM)
starts." passed, although a reader met `JVM` with nothing to read it with. The
rule now compares positions: the expansion has to arrive by the first plain use.
Both orders still count, because both are correct English, and the second leaves
the expansion a couple of characters after the abbreviation ends.

This finding lands on the commit that emptied the baseline. That commit spelled
seventeen abbreviations out *elsewhere* on their pages, which the rule accepted
and a reader would not have. Nineteen pages were reported once the rule was
fixed, and each now carries its expansion at the first use: in the table cell,
in the Simple Story box, or in the bullet where the abbreviation first appears,
whichever place the reader reaches first.

**MDX JSX children were discarded.** `flatten()` replaced an inline
`mdxJsxTextElement` with the code sentinel and `mdxJsxFlowElement` was not
walked into, so `<Callout>The color matters.</Callout>` escaped every rule on a
site that documents `.mdx` as supported. Children are prose now, inline and
block-level alike; attributes are not. An element with no children still becomes
the sentinel, so it cannot join the words on either side into one nobody wrote.

**The source scanner never ran the abbreviation rule.** `scanSource` returned an
empty `body`, which is the only input `abbreviationFindings` reads, so a landing
page could name an abbreviation the rest of the site is required to spell out.
It records its strings as blocks now and runs the rule over them.

Ten fixtures added, including the reverse-order regression and both JSX shapes
the review asked for.

Verified: 77 scanner fixtures, lint:prose at 0 enforced and 1,192 advisory
against the recorded ceiling, eslint, tsc, a strict build, 644 structure tests,
15 browser tests.

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@MarkusPaulsen The first-use abbreviation fix is present, and both trigger threads are resolved in the snapshot. However, non-empty inline JSX is still concatenated directly with surrounding text, so the newly added boundary fixture fails; the configuration guide also contains a malformed required-annotation link.

Comment thread documentation/scripts/prose/prose.test.mjs
Comment thread documentation/docs/instructor/protect-a-java-project/precompile-or-postcompile.md Outdated
Thirty-seven references, one for each place the version appears: the project
version in `pom.xml`, the two runnable examples, the README, the landing page,
the installation and setup pages, both postcompile walkthroughs, the migration
guide and the pages that name the version when explaining what Phobos does not
yet dispatch.

The migration guide sat at 2.1.1 under a "Version snapshot" banner and the rest
of the site at 2.1.2. Both now read 2.1.3, so the banner and the coordinates
below it agree again.

Replacement is per line and only on a line that names Ares, so an unrelated
2.1.x elsewhere on a page is untouched. Nothing below 2.1.3 refers to Ares any
more.

The examples workflow reads the version out of the pom, installs Ares from the
commit and pins the exercises to that artefact, so both example builds resolve
2.1.3 from the local repository rather than from Maven Central.

Note that 2.1.3 is not published yet: the newest release is 2.1.2. Until the tag
exists, an instructor who copies the installation snippet gets an unresolvable
dependency.

Verified: pnpm lint:prose, eslint, tsc, a strict build, 15 browser tests and 644
documentation structure tests.

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@MarkusPaulsen The 2.1.3 coordinate update is internally consistent, but both unresolved findings remain unchanged. [high] flatten() still joins col, the inline JSX child x, and or, so the new boundary regression necessarily receives no-american-spellings instead of the expected empty result. [low] The required Ares-test-annotation reference still uses malformed Markdown and renders without a working link.

The pull request had gone conflicting against main, and a conflicting pull
request has no merge ref, so GitHub could not schedule any `pull_request`
workflow. Only the labeler ran, on `pull_request_target`. The last two pushes
therefore had no continuous integration at all, which is why this merge is here
rather than later.

One conflict, in the test-case factory manual. Main rewrote the scanning section
when the scanner stopped matching regular expressions and started reading the
syntax tree with the imports resolved. This branch still carried the regex
description, `CLASS_PATTERN` and the rest. Main's text describes what the code
does, so it wins; git had already followed the rename from
`docs/securitytest/TestCaseFactoryAndBuilderManual.md`.

The version bump survives the merge: the pom reads 2.1.3 and nothing below it
refers to Ares. The two remaining mentions of 2.1.2 are in
`ReleasedCreatorContractTest` and `ReleasedConstructorCompatibilityTest`, which
say what the 2.1.2 release published and are kept callable. Those are statements
about a release that happened, not coordinates, and 2.1.3 has published nothing.

The prose gate found one enforced violation in the text main brought over, an
"actually" the sentence does not need, now gone. Three advisory counts rose with
that text: active-voice from 760 to 772, long-sentence from 111 to 115, and
prefer-must from 150 to 151. Those numbers are recorded rather than fixed. A
merge that carries in a page written before these rules existed is the one case
where a ceiling rises honestly, and both `cli.mjs` and the writing-rules page now
say so, along with the expectation that the next pass over that page lowers them.

Verified on the merge: 77 scanner fixtures, lint:prose at 0 enforced, eslint,
tsc, a strict build, 15 browser tests, and 644 documentation structure tests
compiled against main's production code.

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@MarkusPaulsen The current merge head leaves both unresolved findings unchanged. [high] flatten() still walks non-empty mdxJsxTextElement children without boundary sentinels, so col<Badge>x</Badge>or becomes color and contradicts the committed fixture’s expected empty result. [low] The required Ares-test-annotation reference still uses malformed Markdown and does not render as a working link.

Markus Paulsen added 3 commits August 22, 2026 07:22
The filler sweep moved "as well" to the end of a sentence and landed it between
a link label and its target: `[Ares test annotation] as well(./test-annotations.md)`
on the page that tells an instructor how to switch Ares on. Markdown renders
that as the label, the stray words and the path, all as plain text, so the one
reference a reader needs to activate enforcement was not a link at all.

Nothing could have caught it. `onBrokenLinks` is set to `throw`, but it only
sees links that parsed, and this one never became a link. That is the same
class of defect as the `:::tip Title` admonitions that shipped rendering as
literal text, so the guard goes next to that one:
`noPageSeversALinkLabelFromItsTarget` reports every page where words sit between
a label and its target, in one message rather than one file at a time, because
this slip arrives in batches.

The target has to look like a target, a relative path, an absolute one or a URL,
so a quoted stack trace reading `the frame] in (StudentCode.java:12)` is not
mistaken for a severed link. Verified both ways: the guard passes on the fixed
page and fails on the defect, naming the file and quoting the line.

Verified: 645 documentation structure tests, lint:prose at 0 enforced, a strict
build and 15 browser tests.
The Spotless Check job failed on the guard added in b70d8ae: one append chain
ran past the line length. Verified with spotless:check, which now passes, and
the 645 documentation tests still pass.

Running it offline reported a plugin resolution failure rather than a formatting
verdict, which is worth knowing: the version came in with the main merge and was
never in the local repository, so 'mvn -o spotless:check' fails for a reason
that has nothing to do with the code.
Main raised the project version to 2.1.3 in pull request #209. This branch had
already done so, and to the same value, so the merge resolves to no change at
all: no file differs from the commit before it.

Kept as a merge rather than dropped, so the branch has main's release commit in
its history and the pull request stays mergeable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Automated area label: docs other Automated area label: other tests Automated area label: tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants