feat(okr): splitt inject-hook ved 91/92 - kjerne + resolvert index-peker (SC5) [skip-docs]
This commit is contained in:
parent
bf0e463b4a
commit
ea2bd444ea
2 changed files with 161 additions and 102 deletions
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
// inject-okr-context.mjs
|
||||
// Event: UserPromptSubmit
|
||||
// Purpose: Inject OKR organization context from .claude/okr.local.md and .claude/okr/ tree.
|
||||
// Zero npm dependencies. Target execution: <50ms.
|
||||
// Purpose: Inject the core OKR organization context from .claude/okr.local.md
|
||||
// (or the home org profile) plus ONE pointer to the second-brain index.md.
|
||||
// Cycle/history/context retrieval is on-demand via the okr-second-brain-search
|
||||
// skill — no longer pre-injected here. Zero npm dependencies. Target: <50ms.
|
||||
|
||||
import { readFileSync, existsSync, readdirSync } from 'node:fs';
|
||||
import { readFileSync, existsSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { homedir } from 'node:os';
|
||||
import { parseFrontmatter } from '../../lib/frontmatter.mjs';
|
||||
|
|
@ -45,8 +47,9 @@ if (rawPrompt) {
|
|||
// Hybrid org-profile resolution (most-specific-wins): project-local overrides
|
||||
// the machine-global home profile. The home path is the Fase 3 migration target;
|
||||
// this read is forward-compatible and stays inert until that file exists.
|
||||
// NOTE: only the org PROFILE resolves to home. The cycle/work tree scan
|
||||
// (okrDir, below) stays cwd-bound -- syklus data is always project-local.
|
||||
// NOTE: only the org PROFILE resolves to home. Cycle/work data stays cwd-bound
|
||||
// and is no longer pre-injected -- it is retrieved on-demand via the
|
||||
// okr-second-brain-search skill.
|
||||
const configPath = existsSync(projectConfigPath)
|
||||
? projectConfigPath
|
||||
: (existsSync(homeConfigPath) ? homeConfigPath : null);
|
||||
|
|
@ -84,105 +87,23 @@ try {
|
|||
if (trygghet) parts.push(`Psykologisk trygghet: ${trygghet}`);
|
||||
if (linear) parts.push('Linear: aktivert');
|
||||
|
||||
// Scan .claude/okr/ directory tree (cap at 50 files)
|
||||
const okrDir = join(cwd, '.claude', 'okr');
|
||||
const dirParts = [];
|
||||
let totalFiles = 0;
|
||||
|
||||
if (existsSync(okrDir)) {
|
||||
try {
|
||||
const topEntries = readdirSync(okrDir, { withFileTypes: true });
|
||||
for (const entry of topEntries) {
|
||||
if (!entry.isDirectory()) continue;
|
||||
if (totalFiles >= 50) break;
|
||||
try {
|
||||
const subEntries = readdirSync(join(okrDir, entry.name), { withFileTypes: true });
|
||||
const mdFiles = [];
|
||||
const subDirs = [];
|
||||
for (const sub of subEntries) {
|
||||
if (totalFiles >= 50) break;
|
||||
if (sub.isFile() && sub.name.endsWith('.md')) {
|
||||
mdFiles.push(sub.name);
|
||||
totalFiles++;
|
||||
} else if (sub.isDirectory()) {
|
||||
subDirs.push(sub.name);
|
||||
}
|
||||
}
|
||||
// Enumerate nested subdirectories (e.g. syklus/T1-2026/)
|
||||
for (const sd of subDirs) {
|
||||
if (totalFiles >= 50) break;
|
||||
try {
|
||||
const nested = readdirSync(join(okrDir, entry.name, sd), { withFileTypes: true });
|
||||
const nestedMd = [];
|
||||
for (const n of nested) {
|
||||
if (totalFiles >= 50) break;
|
||||
if (n.isFile() && n.name.endsWith('.md')) {
|
||||
nestedMd.push(n.name);
|
||||
totalFiles++;
|
||||
}
|
||||
}
|
||||
if (nestedMd.length > 0) {
|
||||
dirParts.push(`${entry.name}/${sd}/ (${nestedMd.length} fil${nestedMd.length > 1 ? 'er' : ''}: ${nestedMd.join(', ')})`);
|
||||
}
|
||||
} catch { /* skip unreadable nested dirs */ }
|
||||
}
|
||||
if (mdFiles.length > 0) {
|
||||
dirParts.push(`${entry.name}/ (${mdFiles.length} fil${mdFiles.length > 1 ? 'er' : ''}: ${mdFiles.join(', ')})`);
|
||||
}
|
||||
} catch { /* skip unreadable dirs */ }
|
||||
}
|
||||
} catch { /* .claude/okr/ scan failed — continue without */ }
|
||||
}
|
||||
|
||||
// Scan historikk/ for archived cycle count
|
||||
const histDir = join(okrDir, 'historikk');
|
||||
const archivedCycles = [];
|
||||
if (existsSync(histDir)) {
|
||||
try {
|
||||
const histEntries = readdirSync(histDir, { withFileTypes: true });
|
||||
for (const entry of histEntries) {
|
||||
if (entry.isDirectory()) {
|
||||
archivedCycles.push(entry.name);
|
||||
}
|
||||
}
|
||||
} catch { /* skip */ }
|
||||
}
|
||||
|
||||
// List active cycle files
|
||||
const cycleId = syklus;
|
||||
const cycleParts = [];
|
||||
if (cycleId) {
|
||||
const cyclePath = join(okrDir, 'syklus', cycleId);
|
||||
if (existsSync(cyclePath)) {
|
||||
try {
|
||||
const cycleEntries = readdirSync(cyclePath, { withFileTypes: true });
|
||||
for (const e of cycleEntries) {
|
||||
if (e.isFile() && e.name.endsWith('.md')) {
|
||||
cycleParts.push(e.name);
|
||||
}
|
||||
}
|
||||
} catch { /* skip */ }
|
||||
}
|
||||
}
|
||||
|
||||
// Build rich systemMessage
|
||||
// Base context line from the core profile fields only. The directory-tree
|
||||
// enumeration that used to live here (the :92-191 MOVE block) is removed:
|
||||
// retrieval is now on-demand via the okr-second-brain-search skill, not
|
||||
// pre-injected. The payload is therefore independent of file count. (SC5)
|
||||
let msg = `OKR-kontekst (fra .claude/okr.local.md): ${parts.join(', ')}.`;
|
||||
|
||||
if (dirParts.length > 0) {
|
||||
msg += `\nTilgjengelige kontekstfiler: ${dirParts.join('; ')}.`;
|
||||
}
|
||||
// Resolve ONE pointer to the second-brain index.md, reusing most-specific-wins
|
||||
// (project bundle preferred, else home bundle). Project root is cwd-bound
|
||||
// (.claude/okr/); the home bundle root is ~/.claude/okr/org/ (two-root model).
|
||||
const projectIndex = join(cwd, '.claude', 'okr', 'index.md');
|
||||
const homeIndex = join(homedir(), '.claude', 'okr', 'org', 'index.md');
|
||||
const indexPath = existsSync(projectIndex)
|
||||
? projectIndex
|
||||
: (existsSync(homeIndex) ? homeIndex : null);
|
||||
|
||||
if (cycleParts.length > 0) {
|
||||
msg += `\nAktive OKR-filer i syklus ${cycleId}: ${cycleParts.join(', ')}.`;
|
||||
}
|
||||
|
||||
if (archivedCycles.length > 0) {
|
||||
msg += `\nArkiverte sykluser (${archivedCycles.length}): ${archivedCycles.sort().join(', ')}.`;
|
||||
msg += ' Bruk /okr:analyse for trendanalyse.';
|
||||
}
|
||||
|
||||
if (dirParts.length > 0 || cycleParts.length > 0) {
|
||||
msg += '\nBruk disse filene automatisk nar relevant — ikke be brukeren om a lime inn innhold som allerede finnes.';
|
||||
if (indexPath) {
|
||||
msg += `\nPersonlig OKF-kontekst finnes - sok wikien (skill: okr-second-brain-search) eller se ${indexPath}.`;
|
||||
}
|
||||
|
||||
process.stdout.write(JSON.stringify({ systemMessage: msg }));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue