Spaces:
Running
Running
Commit 路
447d2ec
1
Parent(s): 16ff884
fix: normalize blocked facts and reuse subtitle helper
Browse files
.claude/skills/sync-nowai-leaderboard/lib/blocked-notify.mjs
CHANGED
|
@@ -5,6 +5,16 @@ const REASON_LABELS = {
|
|
| 5 |
'behind-or-diverged': 'Local main is behind or diverged from origin/main',
|
| 6 |
};
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
export function blockedSubtitle(now = new Date()) {
|
| 9 |
return 'NowAI-Bench Sync 路 ' + now.toISOString().replace('T', ' ').slice(0, 16) + ' UTC';
|
| 10 |
}
|
|
@@ -21,6 +31,12 @@ export function buildBlockedNotification({ reason, facts = [], now = new Date()
|
|
| 21 |
};
|
| 22 |
}
|
| 23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
export function parseBlockedCliArgs(argv) {
|
| 25 |
const facts = [];
|
| 26 |
let reason;
|
|
@@ -37,7 +53,7 @@ export function parseBlockedCliArgs(argv) {
|
|
| 37 |
const raw = argv[++i] ?? '';
|
| 38 |
const eq = raw.indexOf('=');
|
| 39 |
if (eq <= 0) throw new Error(`Invalid --fact, expected key=value: ${raw}`);
|
| 40 |
-
facts.push([raw.slice(0, eq), raw.slice(eq + 1)]);
|
| 41 |
continue;
|
| 42 |
}
|
| 43 |
|
|
|
|
| 5 |
'behind-or-diverged': 'Local main is behind or diverged from origin/main',
|
| 6 |
};
|
| 7 |
|
| 8 |
+
const FACT_LABELS = {
|
| 9 |
+
branch: 'Branch',
|
| 10 |
+
expected: 'Expected',
|
| 11 |
+
files: 'Files',
|
| 12 |
+
remote: 'Remote',
|
| 13 |
+
error: 'Error',
|
| 14 |
+
remoteahead: 'RemoteAhead',
|
| 15 |
+
localahead: 'LocalAhead',
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
export function blockedSubtitle(now = new Date()) {
|
| 19 |
return 'NowAI-Bench Sync 路 ' + now.toISOString().replace('T', ' ').slice(0, 16) + ' UTC';
|
| 20 |
}
|
|
|
|
| 31 |
};
|
| 32 |
}
|
| 33 |
|
| 34 |
+
function normalizeFactKey(rawKey) {
|
| 35 |
+
const key = rawKey.trim();
|
| 36 |
+
const canonical = key.replace(/[\s_-]+/g, '').toLowerCase();
|
| 37 |
+
return FACT_LABELS[canonical] ?? key;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
export function parseBlockedCliArgs(argv) {
|
| 41 |
const facts = [];
|
| 42 |
let reason;
|
|
|
|
| 53 |
const raw = argv[++i] ?? '';
|
| 54 |
const eq = raw.indexOf('=');
|
| 55 |
if (eq <= 0) throw new Error(`Invalid --fact, expected key=value: ${raw}`);
|
| 56 |
+
facts.push([normalizeFactKey(raw.slice(0, eq)), raw.slice(eq + 1)]);
|
| 57 |
continue;
|
| 58 |
}
|
| 59 |
|
.claude/skills/sync-nowai-leaderboard/sync.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { createHash } from 'node:crypto';
|
|
| 6 |
import { execFileSync } from 'node:child_process';
|
| 7 |
import { join, dirname } from 'node:path';
|
| 8 |
import { buildLeaderboard, hasChanges, diffBoards, validate } from './lib/transform.mjs';
|
|
|
|
| 9 |
import { postTeams } from './lib/teams.mjs';
|
| 10 |
|
| 11 |
const STAGING_URL = 'https://huggingface.co/spaces/ServiceNow-AI/NowAI-Bench-Staging';
|
|
@@ -39,11 +40,6 @@ async function fetchText(url, timeoutMs = FETCH_TIMEOUT_MS) {
|
|
| 39 |
}
|
| 40 |
}
|
| 41 |
|
| 42 |
-
// Shared subtitle line for every Teams card: "NowAI-Bench Sync 路 2026-06-12 14:00 UTC".
|
| 43 |
-
function subtitle() {
|
| 44 |
-
return 'NowAI-Bench Sync 路 ' + new Date().toISOString().replace('T', ' ').slice(0, 16) + ' UTC';
|
| 45 |
-
}
|
| 46 |
-
|
| 47 |
// Convenience: an error/abort card with a consistent title.
|
| 48 |
function notifyFailure(facts, kind = 'error') {
|
| 49 |
return postTeams({
|
|
|
|
| 6 |
import { execFileSync } from 'node:child_process';
|
| 7 |
import { join, dirname } from 'node:path';
|
| 8 |
import { buildLeaderboard, hasChanges, diffBoards, validate } from './lib/transform.mjs';
|
| 9 |
+
import { blockedSubtitle as subtitle } from './lib/blocked-notify.mjs';
|
| 10 |
import { postTeams } from './lib/teams.mjs';
|
| 11 |
|
| 12 |
const STAGING_URL = 'https://huggingface.co/spaces/ServiceNow-AI/NowAI-Bench-Staging';
|
|
|
|
| 40 |
}
|
| 41 |
}
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
// Convenience: an error/abort card with a consistent title.
|
| 44 |
function notifyFailure(facts, kind = 'error') {
|
| 45 |
return postTeams({
|
.claude/skills/sync-nowai-leaderboard/test/blocked-notify.test.mjs
CHANGED
|
@@ -38,6 +38,24 @@ test('parseBlockedCliArgs accepts repeated --fact pairs', () => {
|
|
| 38 |
]);
|
| 39 |
});
|
| 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
test('parseBlockedCliArgs rejects unknown blocked reasons', () => {
|
| 42 |
assert.throws(
|
| 43 |
() => parseBlockedCliArgs(['--reason', 'mystery-reason']),
|
|
|
|
| 38 |
]);
|
| 39 |
});
|
| 40 |
|
| 41 |
+
test('parseBlockedCliArgs normalizes lowercase fact keys for stable payload titles', () => {
|
| 42 |
+
const parsed = parseBlockedCliArgs([
|
| 43 |
+
'--reason', 'dirty-worktree',
|
| 44 |
+
'--fact', 'branch=main',
|
| 45 |
+
'--fact', 'files=3',
|
| 46 |
+
]);
|
| 47 |
+
const out = buildBlockedNotification({
|
| 48 |
+
...parsed,
|
| 49 |
+
now: new Date('2026-07-01T21:00:00Z'),
|
| 50 |
+
});
|
| 51 |
+
|
| 52 |
+
assert.deepEqual(out.facts, [
|
| 53 |
+
['Reason', 'Worktree has uncommitted files'],
|
| 54 |
+
['Branch', 'main'],
|
| 55 |
+
['Files', '3'],
|
| 56 |
+
]);
|
| 57 |
+
});
|
| 58 |
+
|
| 59 |
test('parseBlockedCliArgs rejects unknown blocked reasons', () => {
|
| 60 |
assert.throws(
|
| 61 |
() => parseBlockedCliArgs(['--reason', 'mystery-reason']),
|