coursecode 0.1.24 → 0.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -662,6 +662,10 @@ Runs **in Node.js** during build (via `vite.framework-dev.config.js` `closeBundl
662
662
 
663
663
  **Errors fail the build; warnings print but don't block.**
664
664
 
665
+ ### MCP `coursecode_lint` — Unified Results
666
+
667
+ The MCP `coursecode_lint` tool always runs the build linter. When the preview server is running and the headless browser is connected, it also merges runtime errors from the preview server's error log into the same response. These are the same errors shown in the debug panel's Errors tab and returned by `coursecode_state` — LMS API misuse, console errors, uncaught exceptions, and data limit warnings. Runtime-sourced items are tagged with `source: 'runtime'` and `rule: 'runtime-error'`. The `runtimeLintIncluded` flag in the response indicates whether runtime errors were included. This gives AI agents a single tool for both static lint and runtime errors without needing a separate `coursecode_state` call.
668
+
665
669
  ### Shared Rules (`lib/validation-rules.js`)
666
670
 
667
671
  Pure validation functions used by **both** linters. No environment-specific code (no DOM, no `fs`). Includes assessment validation, engagement validation, and result formatting.
@@ -306,14 +306,17 @@ Use to discover available interactions before creating assessments.`,
306
306
 
307
307
  {
308
308
  name: 'coursecode_lint',
309
- description: `Run the build-time linter and get structured results.
309
+ description: `Run the course linter and get structured results.
310
+
311
+ Always runs build-time lint (config, CSS classes, structure). When the preview server is running and the headless browser is connected, also includes runtime errors from the preview server (same errors shown in coursecode_state and the debug panel Errors tab).
310
312
 
311
313
  Returns:
312
- - errors: [{slideId, rule, message, severity}]
313
- - warnings: [{slideId, rule, message, severity, class?, suggestion?}]
314
+ - errors: [{slideId?, rule, message, severity, source?, hint?}]
315
+ - warnings: [{slideId?, rule, message, severity, source?, class?, suggestion?, hint?}]
314
316
  - passed: boolean
317
+ - runtimeLintIncluded: boolean (true when runtime errors were included)
315
318
 
316
- Rules detected:
319
+ Build-time rules (always checked):
317
320
  - undefined-css-class: hallucinated or stale class names (with fix suggestions)
318
321
  - unknown-component: unregistered data-component types
319
322
  - requirement-missing-component: engagement requirement without matching component
@@ -322,9 +325,11 @@ Rules detected:
322
325
  - assessment-id-mismatch: config ID doesn't match assessment ID
323
326
  - invalid-gating: bad gating condition configuration
324
327
 
325
- The runtime linter (visible via coursecode_state errors/warnings) also checks:
326
- - Spacing: flex/grid containers without gap, adjacent elements with no margin, containers with no padding
327
- - Contrast, touch targets, text proximity to borders, element overlap, styled lists
328
+ Runtime errors (included when preview is running, source='runtime'):
329
+ - LMS API misuse (GetValue before Initialize, SetValue after Terminate, etc.)
330
+ - Console errors and warnings from the course
331
+ - Uncaught exceptions and unhandled promise rejections
332
+ - Suspend data size warnings
328
333
 
329
334
  Suppression: Add data-lint-ignore to any HTML element to suppress warnings for it and children.
330
335
  data-lint-ignore — suppress all warnings
package/lib/mcp-server.js CHANGED
@@ -247,6 +247,48 @@ export async function startMcpServer(options = {}) {
247
247
  break;
248
248
  case 'coursecode_lint':
249
249
  result = await lintCourse();
250
+ // Merge runtime errors if headless browser is already connected
251
+ if (headless.isRunning()) {
252
+ try {
253
+ const runtimeErrors = await headless.evaluateParent(() => {
254
+ return window._stubPlayerState?.errorLog || [];
255
+ });
256
+ result.runtimeLintIncluded = true;
257
+ if (runtimeErrors.length > 0) {
258
+ const runtimeWarnings = runtimeErrors.filter(e => e.isWarning);
259
+ const runtimeErrs = runtimeErrors.filter(e => !e.isWarning);
260
+ if (runtimeWarnings.length > 0) {
261
+ result.warnings = (result.warnings || []).concat(
262
+ runtimeWarnings.map(e => ({
263
+ severity: 'warning',
264
+ type: e.type,
265
+ message: e.message,
266
+ hint: e.hint,
267
+ rule: 'runtime-error',
268
+ source: 'runtime'
269
+ }))
270
+ );
271
+ result.warningCount = result.warnings.length;
272
+ }
273
+ if (runtimeErrs.length > 0) {
274
+ result.errors = (result.errors || []).concat(
275
+ runtimeErrs.map(e => ({
276
+ severity: 'error',
277
+ type: e.type,
278
+ message: e.message,
279
+ hint: e.hint,
280
+ rule: 'runtime-error',
281
+ source: 'runtime'
282
+ }))
283
+ );
284
+ result.errorCount = result.errors.length;
285
+ result.passed = result.errors.length === 0;
286
+ }
287
+ }
288
+ } catch {
289
+ // Headless browser may have disconnected — non-fatal, build lint still valid
290
+ }
291
+ }
250
292
  break;
251
293
 
252
294
  case 'coursecode_export_content':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coursecode",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "description": "Multi-format course authoring framework with CLI tools (SCORM 2004, SCORM 1.2, cmi5, LTI 1.3)",
5
5
  "type": "module",
6
6
  "bin": {