diff --git a/tools/status-md-generator.mjs b/tools/status-md-generator.mjs index 2fae6a3..220592c 100644 --- a/tools/status-md-generator.mjs +++ b/tools/status-md-generator.mjs @@ -521,8 +521,12 @@ function runControllerNode(scriptArgs) { } } +// Config-seam (Task 7): расположение журнала наблюдателя. Дефолт docs/observer +// (backward-compat); CLI-блок переопределяет из brain.local.md (resolveStateDir). +let STATE_DIR = 'docs/observer'; + function countEpisodes() { - const dir = 'docs/observer'; + const dir = STATE_DIR; if (!existsSync(dir)) return 0; const month = new Date().toISOString().slice(0, 7); const file = join(dir, `episodes-${month}.jsonl`); @@ -531,7 +535,7 @@ function countEpisodes() { } function countPiiMatches() { - const file = join('docs', 'observer', '.pii-counters.json'); + const file = join(STATE_DIR,'.pii-counters.json'); if (!existsSync(file)) return 0; try { const data = JSON.parse(readFileSync(file, 'utf-8')); @@ -542,7 +546,7 @@ function countPiiMatches() { } function lastRetroDaysAgo() { - const file = join('docs', 'observer', '.read-counter.json'); + const file = join(STATE_DIR,'.read-counter.json'); if (!existsSync(file)) return null; try { const data = JSON.parse(readFileSync(file, 'utf-8')); @@ -552,7 +556,7 @@ function lastRetroDaysAgo() { } function countObserverErrors() { - const dir = 'docs/observer'; + const dir = STATE_DIR; if (!existsSync(dir)) return 0; const month = new Date().toISOString().slice(0, 7); const file = join(dir, `episodes-${month}.jsonl`); @@ -565,7 +569,7 @@ function countObserverErrors() { /** Legacy v1 episode count — lines without schema_version=2, not observer_error markers. */ function countV1Episodes() { - const dir = 'docs/observer'; + const dir = STATE_DIR; if (!existsSync(dir)) return 0; const month = new Date().toISOString().slice(0, 7); const file = join(dir, `episodes-${month}.jsonl`); @@ -578,7 +582,7 @@ function countV1Episodes() { function loadCurrentMonthEpisodes() { const month = new Date().toISOString().slice(0, 7); - const file = join('docs', 'observer', `episodes-${month}.jsonl`); + const file = join(STATE_DIR,`episodes-${month}.jsonl`); if (!existsSync(file)) return []; const out = []; for (const line of readFileSync(file, 'utf-8').split('\n')) { @@ -590,6 +594,10 @@ function loadCurrentMonthEpisodes() { } if (process.argv[1] && process.argv[1].replace(/\\/g, '/').endsWith('/status-md-generator.mjs')) { + try { + const { loadConfig, resolveStateDir } = await import('./brain-config.mjs'); + STATE_DIR = resolveStateDir(loadConfig().state_dir).stateDir; + } catch { /* brain-config недоступен → STATE_DIR остаётся docs/observer */ } const cov = runCoverageChecker(); const c5ok = cov.coverage.ok && cov.registration.ok && cov.missed.totalMissed === 0; const c5detail = [ @@ -612,8 +620,8 @@ if (process.argv[1] && process.argv[1].replace(/\\/g, '/').endsWith('/status-md- }, missed: cov.missed, lastRetroDaysAgo: lastRetroDaysAgo(), - activeProjects: existsSync('docs/observer/active-projects.md') - ? readFileSync('docs/observer/active-projects.md', 'utf-8') + activeProjects: existsSync(join(STATE_DIR, 'active-projects.md')) + ? readFileSync(join(STATE_DIR, 'active-projects.md'), 'utf-8') : '', discipline: (() => { try { @@ -638,7 +646,7 @@ if (process.argv[1] && process.argv[1].replace(/\\/g, '/').endsWith('/status-md- let costBlock = null, anomalyBlock = null, selfRetrospectBlock = null, reviewerBlock = null, reviewerFindingsBlock = null, sessionLengthBlock = null, overrideUsageBlock = null; try { costBlock = computeCostBlock(eps, PRICING); } catch (err) { console.warn('[status-md-generator] costBlock skipped:', err.message); costBlock = '(нет данных)'; } try { anomalyBlock = computeAnomalyBlock(eps); } catch (err) { console.warn('[status-md-generator] anomalyBlock skipped:', err.message); anomalyBlock = '(нет данных)'; } - try { selfRetrospectBlock = computeSelfRetrospectBlock(join('docs', 'observer', '.self-retrospect-counter.json')); } catch (err) { console.warn('[status-md-generator] selfRetrospectBlock skipped:', err.message); selfRetrospectBlock = '(нет данных)'; } + try { selfRetrospectBlock = computeSelfRetrospectBlock(join(STATE_DIR,'.self-retrospect-counter.json')); } catch (err) { console.warn('[status-md-generator] selfRetrospectBlock skipped:', err.message); selfRetrospectBlock = '(нет данных)'; } try { reviewerBlock = computeReviewerBlock(eps); } catch (err) { console.warn('[status-md-generator] reviewerBlock skipped:', err.message); reviewerBlock = '(нет данных)'; } try { reviewerFindingsBlock = computeReviewerFindingsBlock(eps); } catch (err) { console.warn('[status-md-generator] reviewerFindingsBlock skipped:', err.message); reviewerFindingsBlock = '(нет данных)'; } try { sessionLengthBlock = computeSessionLengthBlock(eps); } catch (err) { console.warn('[status-md-generator] sessionLengthBlock skipped:', err.message); sessionLengthBlock = '(нет данных)'; } @@ -711,6 +719,6 @@ if (process.argv[1] && process.argv[1].replace(/\\/g, '/').endsWith('/status-md- inputs.guardBoardBlock = guardBoardBlock; const md = renderStatus(inputs); - writeFileSync('docs/observer/STATUS.md', md); - console.log(`[status-md-generator] OK — wrote docs/observer/STATUS.md`); + writeFileSync(join(STATE_DIR, 'STATUS.md'), md); + console.log(`[status-md-generator] OK — wrote ${join(STATE_DIR, 'STATUS.md')}`); }