feat(ms-ai-architect): C3 (3) — --courses-flagg i write-schedule-config.mjs (TDD) + live-probe-doc

Eier-CLI kan nå sette include_course_detection uten å hand-edite den gitignored
local.md: `write-schedule-config.mjs --enabled true --cadence daily --courses true`.
Flagget er VALGFRITT (opt-in inni opt-in) — utelates det, bevares en verdi satt
andre steder gjennom onboarding-rewriten (samme merge-semantikk som
interval_days / include_skill_lifecycle).

Tester (+3): --courses true setter nøkkelen, string-coercion (CLI-args er
strenger), og non-clobbering når flagget utelates. kb-update 313→316.

docs/development.md: C3-workflow peker nå på CLI-flagget framfor manuell local.md.

Live-probe (2) kjørt mot ekte Learn Platform API: baseline-registry etablert
(1093 kurs: 843 modules + 250 learning-paths), 0 leads (korrekt baseline §8 b).
Registry/report er detektorens gitignored private state — ingen filer committet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-06-23 16:25:56 +02:00
commit cb0450ee2d
3 changed files with 65 additions and 7 deletions

View file

@ -201,6 +201,46 @@ test('writeScheduleConfig — merge preserves pre-existing keys (interval_days)
}
});
// --- C3 (3): --courses flag wires include_course_detection from the CLI ---
test('writeScheduleConfig — --courses true sets include_course_detection (opt-in inside opt-in)', () => {
const home = mkdtempSync(join(tmpdir(), 'home-'));
try {
writeScheduleConfig({ enabled: true, cadence: 'daily', courses: true, home });
const cfg = parseScheduleConfig(readFileSync(resolveConfigPath(home), 'utf8'));
assert.equal(cfg.include_course_detection, true);
} finally {
rmSync(home, { recursive: true, force: true });
}
});
test('writeScheduleConfig — coerces the --courses string flag (CLI args arrive as strings)', () => {
const home = mkdtempSync(join(tmpdir(), 'home-'));
try {
writeScheduleConfig({ enabled: true, cadence: 'daily', courses: 'true', home });
assert.equal(parseScheduleConfig(readFileSync(resolveConfigPath(home), 'utf8')).include_course_detection, true);
writeScheduleConfig({ enabled: true, cadence: 'daily', courses: 'false', home });
assert.equal(parseScheduleConfig(readFileSync(resolveConfigPath(home), 'utf8')).include_course_detection, false);
} finally {
rmSync(home, { recursive: true, force: true });
}
});
test('writeScheduleConfig — omitting --courses preserves a pre-existing include_course_detection', () => {
const home = mkdtempSync(join(tmpdir(), 'home-'));
try {
mkdirSync(resolveUserDataDir(home), { recursive: true });
writeFileSync(
resolveConfigPath(home),
'scheduled_detection:\n enabled: true\n include_course_detection: true\n',
);
writeScheduleConfig({ enabled: false, cadence: 'interval', home }); // no `courses` arg
const cfg = parseScheduleConfig(readFileSync(resolveConfigPath(home), 'utf8'));
assert.equal(cfg.include_course_detection, true, 'non-owned key preserved when --courses is omitted');
} finally {
rmSync(home, { recursive: true, force: true });
}
});
test('writeScheduleConfig — backs up an existing config before overwriting it', () => {
const home = mkdtempSync(join(tmpdir(), 'home-'));
try {