- commit
- f3c751c5ff2252e74022186018b6f5914a422a5c
- parent
- eebb18d8af98e494f4cc12c20ab0723ca597a3ba
- author
- Dami <dami.etoile@gmail.com>
| M | openspec/ | 10 | +++++----- |
| M | src/ | 11 | +++++++++++ |
| M | tests/ | 23 | +++++++++++++++++++++++ |
@@ -2,17 +2,17 @@
22 33 - [x] 1.1 Define the 32-character warning threshold and 24-character44 recommendation in the level-sharing delta.5-- [ ] 1.2 Confirm Gift and Workshop display the existing warning envelope5+- [x] 1.2 Confirm Gift and Workshop display the existing warning envelope66 without copying diagnostics into pack data.77 88 ## 2. Diagnostics99 10-- [ ] 2.1 Add bounded long-title warnings to `collectModWarnings` with proof10+- [x] 2.1 Add bounded long-title warnings to `collectModWarnings` with proof1111 ID, title, null sentence, and authored source detail.12-- [ ] 2.2 Cover short, boundary, long, and normalized local/shared preview12+- [x] 2.2 Cover short, boundary, long, and normalized local/shared preview1313 cases.1414 1515 ## 3. Verification1616 17-- [ ] 3.1 Run focused diagnostics and pack-service tests.18-- [ ] 3.2 Run the full Node suite and production build.17+- [x] 3.1 Run focused diagnostics and pack-service tests.18+- [x] 3.2 Run the full Node suite and production build.@@ -23,6 +23,17 @@ export function collectModWarnings(normalizedMod) {
2323 for (const [levelIndex, level] of levels.entries()) {2424 const levelId = typeof level?.id === 'string' ? level.id : undefined;2525 const levelTitle = typeof level?.title === 'string' && level.title ? level.title : `Proof ${levelIndex + 1}`;26+ if (typeof level?.title === 'string' && level.title.length > 32) {27+ warnings.push({28+ word: 'TITLE',29+ ...(levelId ? { levelId } : {}),30+ levelTitle,31+ sentence: null,32+ message: 'Proof titles should use 24 characters or fewer for easier reading.',33+ detail: `levels[${levelIndex}].title: proof title is ${level.title.length} characters; recommended maximum is 24.`,34+ });35+ if (warnings.length >= MAX_MOD_WARNINGS) return warnings;36+ }2637 const objects = (Array.isArray(level?.objects) ? level.objects : []).map((object, index) => ({ ...object, id: object.id || `o${index}` }));2738 const semantic = new Set(CORE_PROPERTIES);2839 for (const automaton of Array.isArray(level?.automata) ? level.automata : []) {@@ -83,6 +83,29 @@ test('reports parser budget exhaustion as a bounded diagnostics warning', () =>
8383 assert.match(warnings[0].detail, /spans budget exceeded/);8484 });8585 86+test('warns on long proof titles without changing authored data', () => {87+ const shortTitle = 's'.repeat(32);88+ const longTitle = 'A proof title that is deliberately too long';89+ const mod = loadMod(`module.exports = ${JSON.stringify({90+ manifest: { id: 'title-warning', name: 'Title Warning', version: '1.0.0' },91+ levels: [92+ { id: 'short', title: shortTitle, width: 1, height: 1, objects: [] },93+ { id: 'long', title: longTitle, width: 1, height: 1, objects: [] },94+ ],95+ })};`, { filename: 'title-warning.cjs' });96+ const warnings = collectModWarnings(mod);97+ assert.equal(mod.levels[1].title, longTitle);98+ assert.equal(warnings.length, 1);99+ assert.deepEqual(warnings[0], {100+ word: 'TITLE',101+ levelId: 'long',102+ levelTitle: longTitle,103+ sentence: null,104+ message: 'Proof titles should use 24 characters or fewer for easier reading.',105+ detail: `levels[1].title: proof title is ${longTitle.length} characters; recommended maximum is 24.`,106+ });107+});108+86109 test('loads the minimal playable fox automata proof', () => {87110 const mod = loadMod(automataExampleSource, { filename: 'automata-example.cjs' });88111 assert.equal(mod.manifest.id, 'automata-example');