feat(ms-ai-architect): C2.1 lib/user-data resolver + ambient org-injeksjon + C1 config bakoverkompat (TDD) [skip-docs]
Bæreren i C2 onboarding-redesign (#26). TDD: test FØR kode. - lib/user-data.mjs (NY, ren, SKRIVER ALDRI; kun node:os/path): resolveUserDataDir/resolveOrgDir/resolveConfigPath peker ~/.claude/ms-ai-architect/ (uavhengig av pluginRoot -> overlever reinstall, K2). CONFIG_FILENAME delt med C1 (en sannhetskilde). buildOrgSummary: deterministisk, lengde-kappet H2-ekstraksjon. - detection-schedule.mjs: loadScheduleConfig(pluginRoot, home=homedir()) leser bruker-sti FORST, fallback plugin-rot. Lokal CONFIG_FILENAME -> importeres fra resolver. Alle 3 kallere bruker ett-arg-kall (uendret oppforsel). - session-start-context.mjs: injiserer buildOrgSummary ambient (K1) som egen Virksomhetskontekst-blokk; status-nudge beholdt nar org tom. Verifisert: user-data 16/16 · detection-schedule 23/23 · test-hooks 10/10 · kb-update 191 · kb-eval 100 · validate PASSED. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4ff60803ce
commit
dc0b627e98
6 changed files with 459 additions and 31 deletions
|
|
@ -25,6 +25,7 @@ import {
|
|||
summarizeSkillLifecycle,
|
||||
daysSinceLastPoll,
|
||||
} from '../../scripts/kb-update/lib/detection-schedule.mjs';
|
||||
import { resolveConfigPath, resolveUserDataDir } from '../../scripts/kb-update/lib/user-data.mjs';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const PLUGIN_ROOT = join(__dirname, '..', '..');
|
||||
|
|
@ -104,27 +105,66 @@ test('daysSinceLastPoll — computes whole days since last_poll', () => {
|
|||
assert.equal(daysSinceLastPoll({ last_poll: tenDaysAgo }, now), 10);
|
||||
});
|
||||
|
||||
test('loadScheduleConfig — missing config file => OFF default', () => {
|
||||
test('loadScheduleConfig — no config (neither user nor plugin-root) => OFF default', () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'sched-'));
|
||||
const home = mkdtempSync(join(tmpdir(), 'home-')); // empty home: no user-owned config
|
||||
try {
|
||||
assert.deepEqual(loadScheduleConfig(root), DEFAULT_SCHEDULE_CONFIG);
|
||||
assert.deepEqual(loadScheduleConfig(root, home), DEFAULT_SCHEDULE_CONFIG);
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
rmSync(home, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('loadScheduleConfig — reads ms-ai-architect.local.md when present', () => {
|
||||
test('loadScheduleConfig — reads plugin-root ms-ai-architect.local.md when no user config (fallback)', () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'sched-'));
|
||||
const home = mkdtempSync(join(tmpdir(), 'home-'));
|
||||
try {
|
||||
writeFileSync(
|
||||
join(root, 'ms-ai-architect.local.md'),
|
||||
'---\nscheduled_detection:\n enabled: true\n interval_days: 14\n---\n',
|
||||
);
|
||||
const cfg = loadScheduleConfig(root);
|
||||
const cfg = loadScheduleConfig(root, home);
|
||||
assert.equal(cfg.enabled, true);
|
||||
assert.equal(cfg.interval_days, 14);
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
rmSync(home, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
// --- C2.1: user-owned config wins; plugin-root is the backward-compat fallback ---
|
||||
|
||||
function writeUserConfig(home, text) {
|
||||
mkdirSync(resolveUserDataDir(home), { recursive: true });
|
||||
writeFileSync(resolveConfigPath(home), text);
|
||||
}
|
||||
|
||||
test('loadScheduleConfig — user-owned config is read even when pluginRoot has none (K2 survival)', () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'sched-')); // fresh reinstall: plugin root has no config
|
||||
const home = mkdtempSync(join(tmpdir(), 'home-'));
|
||||
try {
|
||||
writeUserConfig(home, '---\nscheduled_detection:\n enabled: true\n interval_days: 5\n---\n');
|
||||
const cfg = loadScheduleConfig(root, home);
|
||||
assert.equal(cfg.enabled, true, 'config survives in the user dir, independent of pluginRoot');
|
||||
assert.equal(cfg.interval_days, 5);
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
rmSync(home, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('loadScheduleConfig — user config wins over a plugin-root config', () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'sched-'));
|
||||
const home = mkdtempSync(join(tmpdir(), 'home-'));
|
||||
try {
|
||||
writeFileSync(join(root, 'ms-ai-architect.local.md'), 'scheduled_detection:\n enabled: true\n interval_days: 99\n');
|
||||
writeUserConfig(home, 'scheduled_detection:\n enabled: true\n interval_days: 3\n');
|
||||
const cfg = loadScheduleConfig(root, home);
|
||||
assert.equal(cfg.interval_days, 3, 'user path takes precedence over plugin-root');
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
rmSync(home, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue