aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-10-18 14:19:47 +0200
committerAgando <roduccomm@gmail.com>2026-10-18 14:19:47 +0200
commit1c1e5765e2d912f1b803ba11691b3ace19106361 (patch)
tree569c4992379595cccff46330d14c8e81f7e9ff0a
parent7150d6fa9538b808c647423a629f31a5a138eaca (diff)
newOS4 course: post-exec review fixes (telemetry detail sanitize, skill-sync retry, atlas check)
-rw-r--r--api/course/event.php6
-rw-r--r--modules/ext/course.js1
-rw-r--r--scripts/newos4-maintain.py19
3 files changed, 20 insertions, 6 deletions
diff --git a/api/course/event.php b/api/course/event.php
index 696d1c5..ce11041 100644
--- a/api/course/event.php
+++ b/api/course/event.php
@@ -30,7 +30,11 @@ if (random_int(1, 50) === 1) {
}
$detail = isset($p['detail']) && is_array($p['detail']) ? array_slice($p['detail'], 0, 8, true) : [];
-foreach ($detail as $k => $v) { if (is_string($v)) $detail[$k] = substr($v, 0, 300); }
+foreach ($detail as $k => $v) {
+ if (is_string($v)) $detail[$k] = substr($v, 0, 300);
+ elseif (is_scalar($v)) $detail[$k] = substr((string)$v, 0, 300);
+ else $detail[$k] = gettype($v);
+}
$row = ['ts' => gmdate('c'), 'type' => $type, 'sid' => $sid,
'version' => substr((string)($p['version'] ?? ''), 0, 40), 'detail' => $detail];
$out = $dir . '/events-' . date('Ym') . '.jsonl';
diff --git a/modules/ext/course.js b/modules/ext/course.js
index 3879cb5..3e00229 100644
--- a/modules/ext/course.js
+++ b/modules/ext/course.js
@@ -108,6 +108,7 @@ class CourseModule {
let m;
try { m = await this._load(); }
catch (e) { return this.terminal.print('Course content unreachable (' + e.message + '). Try `course list` again.', 'error'); }
+ if (localStorage.getItem('webx11_course_skills_ver') !== m.version) this._installSkills().catch(() => {});
const p = this._progress();
if (sub === 'list' || sub === 'chapters') {
this.terminal.print('📚 newOS4 Course — v' + m.version + ' (' + m.updated + ')', 'header');
diff --git a/scripts/newos4-maintain.py b/scripts/newos4-maintain.py
index 6321a3f..10ac62b 100644
--- a/scripts/newos4-maintain.py
+++ b/scripts/newos4-maintain.py
@@ -55,10 +55,11 @@ def check_index():
idxp = os.path.join(ROOT, 'modules-index.json')
atlas = json.load(open(os.path.join(ROOT, 'course/atlas.json')))
idx = json.load(open(idxp))
- cur = len(set(c for m in idx.get('modules', {}).values() for c in m.get('commands', [])))
- if cur == atlas['coverage']['commands']:
- add('PASS', f'modules-index {cur} commands'); return
- add('WARN', f'modules-index stale {cur} vs {atlas["coverage"]["commands"]}')
+ index_cmds = set(c for m in idx.get('modules', {}).values() for c in m.get('commands', []))
+ missing = sorted(c for c, e in atlas.get('commands', {}).items() if not e.get('builtin') and c not in index_cmds)
+ if not missing:
+ add('PASS', f'modules-index covers {len(index_cmds)} commands'); return
+ add('WARN', f'modules-index missing {len(missing)}: ' + ', '.join(missing[:5]))
if not FIX: return
for name, m in atlas['modules'].items():
e = idx['modules'].get(name, {'name': name, 'file': m['file'], 'type': 'core' if m['tier'] == 'core-bundle' else 'ext',
@@ -87,6 +88,14 @@ def check_live():
code = sh(f"curl -s -o /dev/null -w '%{{http_code}}' '{url}'")
add('PASS' if code == '200' else 'FAIL', f'HTTP {code} {url.replace(WEB, "")}')
+def check_atlas():
+ p = os.path.join(ROOT, 'course/atlas.json')
+ before = (json.load(open(p)).get('coverage', {}).get('commands') if os.path.exists(p) else None)
+ r = run([sys.executable, 'scripts/gen-course-atlas.py'], cwd=ROOT)
+ after = (json.load(open(p)).get('coverage', {}).get('commands') if os.path.exists(p) else None)
+ add('PASS' if r.returncode == 0 else 'FAIL',
+ f'atlas {after} commands' + (' (refreshed from ' + str(before) + ')' if before != after else ''))
+
def check_course():
r = run([sys.executable, 'scripts/course-validate.py'], cwd=ROOT)
add('PASS' if r.returncode == 0 else 'FAIL', 'course ' + ('valid' if r.returncode == 0 else 'INVALID: ' + r.stdout[-160:]))
@@ -106,7 +115,7 @@ def check_links():
def main():
os.chdir(ROOT)
- check_versions(); check_bundles(); check_syntax(); check_perms(); check_index(); check_data(); check_live(); check_course(); check_links()
+ check_versions(); check_bundles(); check_syntax(); check_perms(); check_index(); check_data(); check_live(); check_atlas(); check_course(); check_links()
fails = [m for l, m in issues if l == 'FAIL']
print('newOS4 maintenance — ' + datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%MZ') + (' [fix]' if FIX else '') + (' [deep]' if DEEP else ''))
for l, m in issues: print(f'{l}: {m}')