Skip to content

Commit c41be0b

Browse files
committed
test(aurora): add drift-detection test for aurora-page skill constructor signature
Adds AuroraSkillSignatureTest which uses reflection to assert the documented Aurora constructor signature in the aurora-page skill matches actual source. Fixes the documented signature to use correct parameter name ($cdn, not $cdnPath) and reflect nullable types with default values. This catches the §1.2 failure class — hand-written skill documentation drifting from source — at the /check gate on every run. Plan-by: glm-5.2 Acked-by: deepseek-v4-pro Signed-off-by: kyau <git@kyaulabs.com>
1 parent 0aa1d05 commit c41be0b

2 files changed

Lines changed: 97 additions & 2 deletions

File tree

.opencode/skills/aurora-page/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ echo $site->comment($rus, basename(__FILE__));
5757
## Aurora Constructor Parameters
5858

5959
```php
60-
new KYAULabs\Aurora(string $template, string $cdnPath, bool $status, bool $html, ?string $templateDir = null)
60+
new KYAULabs\Aurora(?string $template = null, ?string $cdn = '/cdn', bool $status = false, bool $html = false, ?string $templateDir = null)
6161
```
6262

6363
- `$template` — base HTML template name (e.g. `"index.html"`)
64-
- `$cdnPath`path prefix for CDN assets (e.g. `"/cdn"`)
64+
- `$cdn` — CDN directory path (e.g. `"/cdn"`)
6565
- `$status`**debug mode**: enables `display_errors`, `display_startup_errors`, `E_ALL` reporting, and `html_errors`. Must be `false` in production. Wire to `(bool)($_ENV['APP_DEBUG'] ?? false)`.
6666
- `$html`**HTML output mode**: sets `mb_http_output('UTF-8')` and sends `Content-Type: text/html; charset=UTF-8` header
6767
- `$templateDir` — optional custom template overlay directory (checked first; falls back to Aurora's default `html/` directory)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
# $KYAULabs: AuroraSkillSignatureTest.php kyau@nova 2026/07/05 -0700 Exp $
6+
7+
require_once __DIR__ . '/../../aurora/aurora.inc.php';
8+
9+
use KYAULabs\Aurora;
10+
11+
/**
12+
* Asserts that the Aurora constructor signature documented in the
13+
* aurora-page skill matches the actual source code. Catches the §1.2
14+
* failure class — hand-written skill documentation drifting from
15+
* source — at the /check gate on every run. Pairs with the
16+
* AuroraConstructorStatusTest for the $status sharp edge.
17+
*/
18+
19+
test('aurora-page skill constructor signature matches actual source', function () {
20+
// 1. Get the real signature via reflection
21+
$reflected = new ReflectionMethod(Aurora::class, '__construct');
22+
$params = $reflected->getParameters();
23+
24+
$realSignature = '';
25+
foreach ($params as $param) {
26+
$type = $param->getType();
27+
$typeStr = '';
28+
if ($type instanceof ReflectionNamedType) {
29+
if ($type->allowsNull() && !$param->isDefaultValueAvailable()) {
30+
$typeStr = '?' . $type->getName();
31+
} elseif ($type->allowsNull() && $param->isDefaultValueAvailable() && $param->getDefaultValue() === null) {
32+
$typeStr = '?' . $type->getName();
33+
} elseif ($type->allowsNull()) {
34+
$typeStr = '?' . $type->getName();
35+
} else {
36+
$typeStr = $type->getName();
37+
}
38+
}
39+
40+
$sig = '$' . $param->getName();
41+
if ($param->isDefaultValueAvailable()) {
42+
$default = $param->getDefaultValue();
43+
$sig .= ' = ';
44+
if ($default === null) {
45+
$sig .= 'null';
46+
} elseif ($default === false) {
47+
$sig .= 'false';
48+
} elseif ($default === true) {
49+
$sig .= 'true';
50+
} elseif (is_string($default)) {
51+
$sig .= var_export($default, true);
52+
} else {
53+
$sig .= var_export($default, true);
54+
}
55+
}
56+
57+
$realSignature .= ($realSignature === '' ? '' : ' ') . ltrim($typeStr . ' ' . $sig);
58+
}
59+
60+
// 2. Parse the documented signature from the skill file
61+
$skillPath = __DIR__ . '/../../.opencode/skills/aurora-page/SKILL.md';
62+
$skillContent = file_get_contents($skillPath);
63+
64+
// Extract the constructor signature from the fenced PHP block.
65+
// Must match the documented signature (with type-hinted params like
66+
// "?string $template = null"), NOT the named-argument usage call
67+
// ("template: ...") that appears earlier in the skill file.
68+
preg_match('/new\s+KYAULabs\\\\Aurora\(\s*(\??\w+\s+\$\w+(?:\s*=\s*(?:null|true|false|\'[^\']*\'|"[^"]*"|\d+))?\s*,?\s*)+\)/', $skillContent, $matches);
69+
$matchText = $matches[0] ?? '';
70+
preg_match('/new\s+KYAULabs\\\\Aurora\(([^)]+)\)/', $matchText, $matches);
71+
72+
expect($matches)->toHaveCount(2, 'Could not find Aurora constructor call in aurora-page SKILL.md');
73+
74+
$docArgs = $matches[1];
75+
// Remove whitespace
76+
$docArgs = preg_replace('/\s+/', ' ', trim($docArgs));
77+
78+
// 3. Build the expected signature from the doc
79+
$docParams = array_map('trim', explode(',', $docArgs));
80+
$docSignature = implode(' ', $docParams);
81+
82+
// 4. Compare
83+
$realSignature = str_replace(' ', ' ', trim(preg_replace('/\s+/', ' ', $realSignature)));
84+
$docSignature = trim($docSignature);
85+
86+
expect($docSignature)->toBe(
87+
$realSignature,
88+
"aurora-page SKILL.md constructor signature does not match actual Aurora source.\n" .
89+
" Documented: {$docSignature}\n" .
90+
" Actual: {$realSignature}\n" .
91+
'Fix: update the signature in .opencode/skills/aurora-page/SKILL.md',
92+
);
93+
});
94+
95+
// vim: ft=php sts=4 sw=4 ts=4 et :

0 commit comments

Comments
 (0)