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:
Kjell Tore Guttormsen 2026-06-22 13:34:05 +02:00
commit dc0b627e98
6 changed files with 459 additions and 31 deletions

View file

@ -11,6 +11,11 @@ import {
shouldRunDetection,
summarizeSkillLifecycle,
} from '../../scripts/kb-update/lib/detection-schedule.mjs';
import {
resolveOrgDir,
ORG_FILES,
buildOrgSummary,
} from '../../scripts/kb-update/lib/user-data.mjs';
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || join(process.cwd());
const cwd = process.cwd();
@ -105,22 +110,33 @@ for (const dl of AI_ACT_DEADLINES) {
}
}
// --- 4. Check onboarding status ---
const orgDir = join(pluginRoot, 'org');
const ORG_FILES = [
'organization-profile.md',
'technology-stack.md',
'security-compliance.md',
'architecture-decisions.md',
'business-references.md',
];
let orgComplete = 0;
const orgExists = existsSync(orgDir);
if (orgExists) {
for (const f of ORG_FILES) {
if (existsSync(join(orgDir, f))) orgComplete++;
// --- 4. Onboarding status + ambient org context (C2.1) ---
// The user-owned org dir (~/.claude/ms-ai-architect/org) wins; the legacy
// plugin org/ dir is the backward-compat fallback. Read the files once: their
// count drives the status line, their content drives the ambient summary that
// makes org context present in EVERY session (not just a "run onboarding" nudge).
function readOrgFiles(dir) {
const files = {};
let count = 0;
if (existsSync(dir)) {
for (const f of ORG_FILES) {
const p = join(dir, f);
if (existsSync(p)) {
try {
files[f] = readFileSync(p, 'utf8');
count++;
} catch {
// Unreadable file — skip; advisory only
}
}
}
}
return { files, count };
}
const userOrg = readOrgFiles(resolveOrgDir());
const orgData = userOrg.count > 0 ? userOrg : readOrgFiles(join(pluginRoot, 'org'));
const orgComplete = orgData.count;
const orgSummary = buildOrgSummary(orgData.files);
// --- 4. Build output ---
const parts = [];
@ -132,7 +148,7 @@ if (utredningFiles > 0) {
parts.push(`${utredningFiles} utredningsdokument(er) i docs/`);
}
if (!orgExists || orgComplete === 0) {
if (orgComplete === 0) {
parts.push('Ingen virksomhetstilpasning. Kjør /architect:onboard (~5 min)');
} else if (orgComplete < ORG_FILES.length) {
parts.push(`Onboarding ${orgComplete}/${ORG_FILES.length}. Kjør /architect:onboard for å fullføre`);
@ -171,6 +187,14 @@ if (parts.length > 0) {
lines.push('Architect: Ingen aktive sesjoner. KB oppdatert. /architect:help');
}
// Ambient org context (C2.1): inject the compact summary so org facts are
// PRESENT in the session, not merely discoverable. Length-capped by
// buildOrgSummary. Only emitted when onboarding has produced content.
if (orgSummary) {
lines.push('Virksomhetskontekst (auto-injisert fra ~/.claude/ms-ai-architect/org):');
for (const l of orgSummary.split('\n')) lines.push(`- ${l}`);
}
if (lines.length > 0) {
process.stdout.write(lines.join('\n') + '\n');
}