Test that the guideline and the design skill cannot drift, and attribute Google

BoostResourcesTest: the guideline stays under 120 lines and verbatim, the skill
carries its frontmatter and every guideline section as a chapter, names every
--md-sys-*/--md-ref-* token family declared in resources/css/tokens and every M3
breakpoint, and ends with an Attribution chapter. NOTICE records that the rules
and wording come from m3.material.io (CC BY 4.0) and the token values from
androidx Compose (Apache-2.0), since docs/ is export-ignored and the skill ships.
Plan steps 29 and 30.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-14 04:04:25 +02:00
co-authored by Claude Fable 5.1
parent b3960d5eca
commit 5fc75a32eb
2 changed files with 71 additions and 0 deletions
+9
View File
@@ -50,4 +50,13 @@ Spring motion constants (resources/css/tokens/motion.css)
From androidx Compose Material 3, tokens/ExpressiveMotionTokens.kt.
Copyright The Android Open Source Project. Apache License 2.0.
Material Design 3 documentation (resources/boost/guidelines/material-3.blade.php,
resources/boost/skills/material-3-design/SKILL.md, docs/reference/m3)
Rules, tables and wording condensed from https://m3.material.io (Foundations, Styles,
Components), which Google publishes under the Creative Commons Attribution 4.0 License
except as otherwise noted; the numeric token values from androidx Compose Material 3's
token files.
Copyright Google LLC (CC BY 4.0, https://creativecommons.org/licenses/by/4.0/);
Copyright The Android Open Source Project (Apache License 2.0).
A copy of the Apache License 2.0 is available at https://www.apache.org/licenses/LICENSE-2.0.
+62
View File
@@ -28,3 +28,65 @@ it('names every component in the skill', function () {
expect($undocumented)->toBeEmpty();
});
const GUIDELINE_PATH = __DIR__.'/../../resources/boost/guidelines/material-3.blade.php';
const DESIGN_SKILL_PATH = __DIR__.'/../../resources/boost/skills/material-3-design/SKILL.md';
it('keeps the Material 3 guideline short, verbatim and always on', function () {
$guideline = File::get(GUIDELINE_PATH);
expect($guideline)
->toStartWith("@verbatim\n")
->toContain("\n@endverbatim")
->toContain("\n## Material 3\n");
// Boost inlines every guideline into every session, so this one must stay a page.
expect(substr_count($guideline, "\n"))->toBeLessThan(120);
});
it('gives the design skill the frontmatter Boost requires', function () {
$skill = File::get(DESIGN_SKILL_PATH);
expect($skill)
->toStartWith("---\n")
->toContain("\nname: material-3-design\n")
->toMatch('/\ndescription: \S.+\n/');
});
it('carries every guideline section in the design skill', function () {
preg_match_all('/^### (.+)$/m', File::get(GUIDELINE_PATH), $sections);
preg_match_all('/^## (.+)$/m', File::get(DESIGN_SKILL_PATH), $chapters);
expect($sections[1])->not->toBeEmpty();
expect(array_values(array_diff($sections[1], $chapters[1])))->toBe([]);
});
it('names every token family and breakpoint in the design skill', function () {
$skill = File::get(DESIGN_SKILL_PATH);
$families = collect(File::files(__DIR__.'/../../resources/css/tokens'))
->flatMap(function (SplFileInfo $file): array {
preg_match_all('/--md-(?:sys|ref)-[a-z]+-/', $file->getContents(), $matches);
return $matches[0];
})
->unique()
->values();
expect($families)->not->toBeEmpty();
foreach ($families as $family) {
expect($skill)->toContain($family.'*');
}
foreach (['medium', 'expanded', 'large', 'extra-large'] as $breakpoint) {
expect($skill)->toContain("`{$breakpoint}:`");
}
});
it('attributes the design skill to Google', function () {
expect(File::get(DESIGN_SKILL_PATH))
->toContain("\n## Attribution\n")
->toContain('Creative Commons Attribution 4.0')
->toContain('Apache License 2.0');
});