feat(brain-config): state_dir wiring status-md-generator Фаза 1 Task 7 CLI

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-15 19:39:59 +03:00
parent 165ff3a859
commit dcc14f83ec
+19 -11
View File
@@ -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')}`);
}