@dzhechkov/harness-core 0.3.61 → 0.3.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -23,6 +23,8 @@ export { pretrain } from './pretrain.js';
23
23
  export { loadPatterns, loadSessions, computePatternBoost, readLearningConfig, BOOST_CAP, recordPattern, loadStorePatternsSync, patternToRecord, recordToPattern, consolidateSessions, recallPatterns, pruneNoisePatterns } from './patterns.js';
24
24
  export type { PatternRecord, SessionRecord, LearningConfig, LoadOptions, ConsolidateResult, ConsolidateOptions, SqliteBackendMode, RecallHit, SessionsSource, PruneNoiseResult } from './patterns.js';
25
25
  export { runSetup, generateHooksConfig, generateAgentdbWriter, writerVersionOf, AGENTDB_WRITER_VERSION } from './setup.js';
26
+ export { statuslineData, readFeatureAdrState, writeFeatureAdrState, featureAdrStatePath } from './statusline.js';
27
+ export type { StatuslineData, FeatureAdrState, WriteFeatureAdrStateInput } from './statusline.js';
26
28
  export { indexPatternsToAgentdb, resolveAgentdbPath } from './agentdb-index.js';
27
29
  export { putBookKnowledge, queryBookKnowledge, bookKbPath } from './book-kb.js';
28
30
  export type { BookKU, BookKUHit } from './book-kb.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ export { recommend } from './recommend.js';
20
20
  export { pretrain } from './pretrain.js';
21
21
  export { loadPatterns, loadSessions, computePatternBoost, readLearningConfig, BOOST_CAP, recordPattern, loadStorePatternsSync, patternToRecord, recordToPattern, consolidateSessions, recallPatterns, pruneNoisePatterns } from './patterns.js';
22
22
  export { runSetup, generateHooksConfig, generateAgentdbWriter, writerVersionOf, AGENTDB_WRITER_VERSION } from './setup.js';
23
+ export { statuslineData, readFeatureAdrState, writeFeatureAdrState, featureAdrStatePath } from './statusline.js';
23
24
  export { indexPatternsToAgentdb, resolveAgentdbPath } from './agentdb-index.js';
24
25
  export { putBookKnowledge, queryBookKnowledge, bookKbPath } from './book-kb.js';
25
26
  export { brainHome, brainBooksPath, brainAgentdbPath, brainRegistryPath, readRegistry, writeRegistry, listBrain, promoteProjectToBrain, updateBrainSource, queryBrain, rerankHits, groundPrompt, buildPrimer, writePrimer, readBookKus, exportBrainSlice, importBrainSlice, registerKusToBrain, } from './brain.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,mFAAmF;AACnF,MAAM,CAAC,MAAM,oBAAoB,GAC9B,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAyB,CAAC,OAAO,CAAC;AAErF,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAElH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC1H,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,qBAAqB,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEhP,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAC3H,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEhF,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,qBAAqB,EACrB,iBAAiB,EACjB,UAAU,EACV,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAK7C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAE,eAAe,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC3J,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EACL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,SAAS,EACT,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAS3B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,EACnB,cAAc,EACd,QAAQ,GACT,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * `dz statusline` data source — the FAST, best-effort read behind the live
3
+ * self-learning panel Claude Code renders in its status bar (modeled on
4
+ * agentic-qe's "🎓 12 patterns" statusline, showing dz's OWN counts).
5
+ *
6
+ * Claude Code refreshes a `statusLine` command up to every ~300ms, so this MUST
7
+ * be fast (<~50ms) and MUST NEVER throw or hang — a broken statusline garbles the
8
+ * terminal bar. Every read is therefore:
9
+ * - **readonly + short busy_timeout** — a live MCP writer holding the store lock
10
+ * must never make the panel wait; we back off immediately, not block.
11
+ * - **best-effort** — any error (absent/corrupt `.dz`, missing native module,
12
+ * locked db) collapses to `0` / an omitted field, never an exception.
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ /**
17
+ * Live learning state for one in-flight `/feature-adr` run — the per-run visibility panel
18
+ * that surfaces the Pattern memory loop (POOL learned, RECALLED for this run, STORED this run).
19
+ * Written by the pipeline at Steps 0/8/9 via `writeFeatureAdrState`; read back on the render
20
+ * path (readonly, best-effort) by `readFeatureAdrState`.
21
+ */
22
+ export interface FeatureAdrState {
23
+ /** The feature slug the pipeline is working on (kebab-case). */
24
+ readonly slug: string;
25
+ /** Human-readable step label (e.g. "Step 0", "Step 8 QE"). */
26
+ readonly step: string;
27
+ /** Total learned-pattern POOL (all patterns available to recall from) at write time. */
28
+ readonly pool: number;
29
+ /** How many patterns this run RECALLED / used to inform its work. */
30
+ readonly recalled: number;
31
+ /** How many NEW patterns this run STORED back into the pool. */
32
+ readonly stored: number;
33
+ /** ISO timestamp of the write — drives the freshness window on the render path. */
34
+ readonly ts: string;
35
+ /** Optional run mode (e.g. "reference", "full-qe", "full-qe-extended"). */
36
+ readonly mode?: string;
37
+ }
38
+ /** A snapshot of dz's self-learning state for one project (all fields best-effort). */
39
+ export interface StatuslineData {
40
+ /** Count of learned patterns in the project's unified memory store. */
41
+ readonly patterns: number;
42
+ /** Number of sources registered in the durable cross-project knowledge brain. */
43
+ readonly brainSources: number;
44
+ /** Hours since the last `dz consolidate` run, if a watermark is present. */
45
+ readonly consolidatedAgeH?: number;
46
+ /** Live `/feature-adr` learning state — present ONLY when a fresh run is in flight. */
47
+ readonly featureAdr?: FeatureAdrState;
48
+ }
49
+ /** Path of the live `/feature-adr` learning-state file (per-run panel source). */
50
+ export declare function featureAdrStatePath(projectRoot: string): string;
51
+ /**
52
+ * Read the live `/feature-adr` learning state for one project — the source of the per-run panel.
53
+ *
54
+ * RENDER-PATH DISCIPLINE (statusline pattern #1): this runs inside the ~300ms status-bar refresh, so
55
+ * it is a plain **readonly** file read, **best-effort**, and NEVER throws — an absent, unreadable, or
56
+ * corrupt state file collapses to `undefined`, not an exception.
57
+ *
58
+ * FRESHNESS: a run whose `ts` is older than {@link FEATURE_ADR_FRESH_MS} is treated as finished and
59
+ * returns `undefined`, so a stale run can never keep a panel pinned in the status bar.
60
+ *
61
+ * @param projectRoot Absolute (or cwd-relative) project directory.
62
+ * @param now Injectable clock (epoch ms) for the freshness check — defaults to `Date.now()`.
63
+ */
64
+ export declare function readFeatureAdrState(projectRoot: string, now?: number): FeatureAdrState | undefined;
65
+ /** Fields the `/feature-adr` pipeline supplies when recording its live learning state. */
66
+ export interface WriteFeatureAdrStateInput {
67
+ readonly slug: string;
68
+ readonly step: string;
69
+ readonly recalled: number;
70
+ readonly stored: number;
71
+ readonly mode?: string;
72
+ }
73
+ /**
74
+ * Record the live `/feature-adr` learning state — called by the pipeline at Steps 0/8/9. Computes
75
+ * `pool` as the total learned-pattern count (via the same readonly {@link countLearnedPatterns} the
76
+ * panel uses) and writes the JSON with a fresh `ts`. Best-effort: returns the written state, or
77
+ * `undefined` on any I/O error (this must never break the pipeline).
78
+ *
79
+ * @param now Injectable clock (epoch ms) for the write timestamp — defaults to `Date.now()`.
80
+ */
81
+ export declare function writeFeatureAdrState(projectRoot: string, input: WriteFeatureAdrStateInput, now?: number): FeatureAdrState | undefined;
82
+ /**
83
+ * Gather dz's self-learning counts for one project. FAST + best-effort: every read
84
+ * is guarded so a missing/corrupt `.dz`, absent native module, or locked store
85
+ * yields `0` / an omitted field — this function NEVER throws.
86
+ *
87
+ * @param projectRoot Absolute (or cwd-relative) project directory.
88
+ * @param now Injectable clock (epoch ms) for the consolidation age — defaults to `Date.now()`.
89
+ */
90
+ export declare function statuslineData(projectRoot: string, now?: number): StatuslineData;
91
+ //# sourceMappingURL=statusline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusline.d.ts","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wFAAwF;IACxF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,4EAA4E;IAC5E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,uFAAuF;IACvF,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC;CACvC;AAYD,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE/D;AAkFD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe,GAAG,SAAS,CAyB9G;AAED,0FAA0F;AAC1F,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,yBAAyB,EAChC,GAAG,GAAE,MAAmB,GACvB,eAAe,GAAG,SAAS,CAyB7B;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,cAAc,CAiC5F"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * `dz statusline` data source — the FAST, best-effort read behind the live
3
+ * self-learning panel Claude Code renders in its status bar (modeled on
4
+ * agentic-qe's "🎓 12 patterns" statusline, showing dz's OWN counts).
5
+ *
6
+ * Claude Code refreshes a `statusLine` command up to every ~300ms, so this MUST
7
+ * be fast (<~50ms) and MUST NEVER throw or hang — a broken statusline garbles the
8
+ * terminal bar. Every read is therefore:
9
+ * - **readonly + short busy_timeout** — a live MCP writer holding the store lock
10
+ * must never make the panel wait; we back off immediately, not block.
11
+ * - **best-effort** — any error (absent/corrupt `.dz`, missing native module,
12
+ * locked db) collapses to `0` / an omitted field, never an exception.
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
17
+ import { dirname, join, resolve } from 'node:path';
18
+ import { createRequire } from 'node:module';
19
+ import { listBrain } from './brain.js';
20
+ /** Path of the SQLite pattern store (the Tier-3 backend). */
21
+ function sqlitePatternPath(projectRoot) {
22
+ return join(projectRoot, '.dz', 'memory', 'patterns.sqlite');
23
+ }
24
+ /** The `dz consolidate` watermark (max processed transcript timestamp). */
25
+ function consolidateWatermarkPath(projectRoot) {
26
+ return join(projectRoot, '.dz', 'memory', 'consolidate.json');
27
+ }
28
+ /** Path of the live `/feature-adr` learning-state file (per-run panel source). */
29
+ export function featureAdrStatePath(projectRoot) {
30
+ return join(projectRoot, '.dz', 'feature-adr', 'learning-state.json');
31
+ }
32
+ /**
33
+ * Freshness window for the `/feature-adr` panel: a run older than this is considered finished, so
34
+ * its state must NOT keep showing a stale panel in the status bar. 30 minutes (in ms).
35
+ */
36
+ const FEATURE_ADR_FRESH_MS = 30 * 60 * 1_000;
37
+ /**
38
+ * Count learned patterns via a direct **readonly** `COUNT(*)` with a short
39
+ * `busy_timeout` — no FTS rebuild, no schema write, no waiting on a live writer.
40
+ * Returns `undefined` (not `0`) when the fast path is unavailable so the caller
41
+ * can fall back to a readonly jsonl line-count; any error → `undefined`.
42
+ */
43
+ function countSqlitePatternsReadonly(sqlitePath) {
44
+ try {
45
+ const require = createRequire(import.meta.url);
46
+ const Database = require('better-sqlite3');
47
+ const db = new Database(sqlitePath, { readonly: true });
48
+ try {
49
+ db.pragma('busy_timeout = 100'); // back off fast — never block the 300ms refresh on a write lock
50
+ const row = db.prepare('SELECT COUNT(*) as cnt FROM memory_records').get();
51
+ return typeof row?.cnt === 'number' ? row.cnt : undefined;
52
+ }
53
+ finally {
54
+ db.close();
55
+ }
56
+ }
57
+ catch {
58
+ return undefined;
59
+ }
60
+ }
61
+ /**
62
+ * Count the legacy/default `.dz/patterns.jsonl` store by reading the FILE directly — READONLY, no
63
+ * backend open, no FTS rebuild, no schema write. Used only when the SQLite readonly COUNT is
64
+ * unavailable (no SQLite tier, or a transient lock). Best-effort → 0 on any error.
65
+ */
66
+ function countJsonlPatternsReadonly(projectRoot) {
67
+ const path = join(projectRoot, '.dz', 'patterns.jsonl');
68
+ if (!existsSync(path))
69
+ return 0;
70
+ try {
71
+ return readFileSync(path, 'utf-8').split('\n').filter((l) => l.trim() !== '').length;
72
+ }
73
+ catch {
74
+ return 0;
75
+ }
76
+ }
77
+ /**
78
+ * Learned-pattern count for the panel: the fast **readonly** SQLite `COUNT(*)`, else a **readonly**
79
+ * jsonl line-count, else `0`. NEVER opens the store read-write (the render path must not run the
80
+ * mutating FTS rebuild `loadStorePatternsSync` does). This counts the durable SQLite tier and so
81
+ * tracks `dz recall --all` in steady state (jsonl folds into SQLite on consolidate); it is a fast
82
+ * approximation, not a deduped union, by design — a status bar must stay readonly + sub-50ms.
83
+ */
84
+ function countLearnedPatterns(projectRoot) {
85
+ const sqlitePath = sqlitePatternPath(projectRoot);
86
+ if (existsSync(sqlitePath)) {
87
+ const fast = countSqlitePatternsReadonly(sqlitePath);
88
+ if (fast !== undefined)
89
+ return fast;
90
+ }
91
+ return countJsonlPatternsReadonly(projectRoot);
92
+ }
93
+ /** Hours since the last consolidation, or `undefined` when never consolidated / unreadable. */
94
+ function consolidatedAgeHours(projectRoot, now) {
95
+ const path = consolidateWatermarkPath(projectRoot);
96
+ if (!existsSync(path))
97
+ return undefined;
98
+ try {
99
+ const parsed = JSON.parse(readFileSync(path, 'utf-8'));
100
+ const ts = typeof parsed.lastConsolidatedTs === 'string' ? Date.parse(parsed.lastConsolidatedTs) : Number.NaN;
101
+ if (Number.isNaN(ts))
102
+ return undefined;
103
+ return Math.max(0, Math.round((now - ts) / 3_600_000));
104
+ }
105
+ catch {
106
+ return undefined;
107
+ }
108
+ }
109
+ /**
110
+ * Read the live `/feature-adr` learning state for one project — the source of the per-run panel.
111
+ *
112
+ * RENDER-PATH DISCIPLINE (statusline pattern #1): this runs inside the ~300ms status-bar refresh, so
113
+ * it is a plain **readonly** file read, **best-effort**, and NEVER throws — an absent, unreadable, or
114
+ * corrupt state file collapses to `undefined`, not an exception.
115
+ *
116
+ * FRESHNESS: a run whose `ts` is older than {@link FEATURE_ADR_FRESH_MS} is treated as finished and
117
+ * returns `undefined`, so a stale run can never keep a panel pinned in the status bar.
118
+ *
119
+ * @param projectRoot Absolute (or cwd-relative) project directory.
120
+ * @param now Injectable clock (epoch ms) for the freshness check — defaults to `Date.now()`.
121
+ */
122
+ export function readFeatureAdrState(projectRoot, now = Date.now()) {
123
+ const path = featureAdrStatePath(resolve(projectRoot));
124
+ if (!existsSync(path))
125
+ return undefined;
126
+ try {
127
+ const parsed = JSON.parse(readFileSync(path, 'utf-8'));
128
+ if (typeof parsed.slug !== 'string' || parsed.slug.length === 0)
129
+ return undefined;
130
+ if (typeof parsed.step !== 'string' || parsed.step.length === 0)
131
+ return undefined;
132
+ if (typeof parsed.ts !== 'string')
133
+ return undefined;
134
+ const tsMs = Date.parse(parsed.ts);
135
+ if (Number.isNaN(tsMs))
136
+ return undefined;
137
+ if (now - tsMs > FEATURE_ADR_FRESH_MS)
138
+ return undefined; // stale run — do not surface a panel
139
+ const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : 0);
140
+ const state = {
141
+ slug: parsed.slug,
142
+ step: parsed.step,
143
+ pool: num(parsed.pool),
144
+ recalled: num(parsed.recalled),
145
+ stored: num(parsed.stored),
146
+ ts: parsed.ts,
147
+ ...(typeof parsed.mode === 'string' && parsed.mode.length > 0 ? { mode: parsed.mode } : {}),
148
+ };
149
+ return state;
150
+ }
151
+ catch {
152
+ return undefined;
153
+ }
154
+ }
155
+ /**
156
+ * Record the live `/feature-adr` learning state — called by the pipeline at Steps 0/8/9. Computes
157
+ * `pool` as the total learned-pattern count (via the same readonly {@link countLearnedPatterns} the
158
+ * panel uses) and writes the JSON with a fresh `ts`. Best-effort: returns the written state, or
159
+ * `undefined` on any I/O error (this must never break the pipeline).
160
+ *
161
+ * @param now Injectable clock (epoch ms) for the write timestamp — defaults to `Date.now()`.
162
+ */
163
+ export function writeFeatureAdrState(projectRoot, input, now = Date.now()) {
164
+ const root = resolve(projectRoot);
165
+ let pool = 0;
166
+ try {
167
+ pool = countLearnedPatterns(root);
168
+ }
169
+ catch {
170
+ pool = 0;
171
+ }
172
+ const state = {
173
+ slug: input.slug,
174
+ step: input.step,
175
+ pool,
176
+ recalled: Number.isFinite(input.recalled) ? input.recalled : 0,
177
+ stored: Number.isFinite(input.stored) ? input.stored : 0,
178
+ ts: new Date(now).toISOString(),
179
+ ...(input.mode !== undefined && input.mode.length > 0 ? { mode: input.mode } : {}),
180
+ };
181
+ try {
182
+ const path = featureAdrStatePath(root);
183
+ mkdirSync(dirname(path), { recursive: true });
184
+ writeFileSync(path, `${JSON.stringify(state, null, 2)}\n`);
185
+ }
186
+ catch {
187
+ return undefined;
188
+ }
189
+ return state;
190
+ }
191
+ /**
192
+ * Gather dz's self-learning counts for one project. FAST + best-effort: every read
193
+ * is guarded so a missing/corrupt `.dz`, absent native module, or locked store
194
+ * yields `0` / an omitted field — this function NEVER throws.
195
+ *
196
+ * @param projectRoot Absolute (or cwd-relative) project directory.
197
+ * @param now Injectable clock (epoch ms) for the consolidation age — defaults to `Date.now()`.
198
+ */
199
+ export function statuslineData(projectRoot, now = Date.now()) {
200
+ const root = resolve(projectRoot);
201
+ let patterns = 0;
202
+ try {
203
+ patterns = countLearnedPatterns(root);
204
+ }
205
+ catch {
206
+ patterns = 0;
207
+ }
208
+ let brainSources = 0;
209
+ try {
210
+ brainSources = listBrain().length;
211
+ }
212
+ catch {
213
+ brainSources = 0;
214
+ }
215
+ const ageH = consolidatedAgeHours(root, now);
216
+ // Live /feature-adr panel — attached ONLY when a fresh run is in flight (readonly, never throws).
217
+ let featureAdr;
218
+ try {
219
+ featureAdr = readFeatureAdrState(root, now);
220
+ }
221
+ catch {
222
+ featureAdr = undefined;
223
+ }
224
+ return {
225
+ patterns,
226
+ brainSources,
227
+ ...(ageH !== undefined ? { consolidatedAgeH: ageH } : {}),
228
+ ...(featureAdr !== undefined ? { featureAdr } : {}),
229
+ };
230
+ }
231
+ //# sourceMappingURL=statusline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusline.js","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAqCvC,6DAA6D;AAC7D,SAAS,iBAAiB,CAAC,WAAmB;IAC5C,OAAO,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAC/D,CAAC;AAED,2EAA2E;AAC3E,SAAS,wBAAwB,CAAC,WAAmB;IACnD,OAAO,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC;AAChE,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,OAAO,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,qBAAqB,CAAC,CAAC;AACxE,CAAC;AAED;;;GAGG;AACH,MAAM,oBAAoB,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;AAQ7C;;;;;GAKG;AACH,SAAS,2BAA2B,CAAC,UAAkB;IACrD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAmD,CAAC;QAC7F,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,gEAAgE;YACjG,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,4CAA4C,CAAC,CAAC,GAAG,EAAuB,CAAC;YAChG,OAAO,OAAO,GAAG,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5D,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,KAAK,EAAE,CAAC;QACb,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,0BAA0B,CAAC,WAAmB;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACxD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;IACvF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,WAAmB;IAC/C,MAAM,UAAU,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAClD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,2BAA2B,CAAC,UAAU,CAAC,CAAC;QACrD,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;IACtC,CAAC;IACD,OAAO,0BAA0B,CAAC,WAAW,CAAC,CAAC;AACjD,CAAC;AAED,+FAA+F;AAC/F,SAAS,oBAAoB,CAAC,WAAmB,EAAE,GAAW;IAC5D,MAAM,IAAI,GAAG,wBAAwB,CAAC,WAAW,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAqC,CAAC;QAC3F,MAAM,EAAE,GAAG,OAAO,MAAM,CAAC,kBAAkB,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;QAC9G,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAAE,OAAO,SAAS,CAAC;QACvC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;IAC/E,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAA6B,CAAC;QACnF,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAClF,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAClF,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QACzC,IAAI,GAAG,GAAG,IAAI,GAAG,oBAAoB;YAAE,OAAO,SAAS,CAAC,CAAC,qCAAqC;QAC9F,MAAM,GAAG,GAAG,CAAC,CAAU,EAAU,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1F,MAAM,KAAK,GAAoB;YAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;YACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC;YAC9B,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;YAC1B,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,GAAG,CAAC,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5F,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAWD;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAClC,WAAmB,EACnB,KAAgC,EAChC,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAClC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,CAAC;QACH,IAAI,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,CAAC,CAAC;IACX,CAAC;IACD,MAAM,KAAK,GAAoB;QAC7B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI;QACJ,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC9D,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACxD,EAAE,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE;QAC/B,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnF,CAAC;IACF,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;QACvC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;IAC1E,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAElC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,CAAC;QACH,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,GAAG,CAAC,CAAC;IACf,CAAC;IAED,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,CAAC;QACH,YAAY,GAAG,SAAS,EAAE,CAAC,MAAM,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,YAAY,GAAG,CAAC,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,GAAG,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE7C,kGAAkG;IAClG,IAAI,UAAuC,CAAC;IAC5C,IAAI,CAAC;QACH,UAAU,GAAG,mBAAmB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,GAAG,SAAS,CAAC;IACzB,CAAC;IAED,OAAO;QACL,QAAQ;QACR,YAAY;QACZ,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpD,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzhechkov/harness-core",
3
- "version": "0.3.61",
3
+ "version": "0.3.65",
4
4
  "description": "Shared harness logic - skill loading, additive apply, and the init/sync/verify/doctor operations.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -31,9 +31,9 @@
31
31
  "@dzhechkov/adapter-opencode": "^0.2.0",
32
32
  "yaml": "^2.0.0",
33
33
  "@dzhechkov/adapter-agents-md": "0.1.1",
34
- "@dzhechkov/core": "0.2.6",
35
34
  "@dzhechkov/adapter-copilot": "0.1.1",
36
- "@dzhechkov/memory": "0.2.9"
35
+ "@dzhechkov/memory": "0.2.9",
36
+ "@dzhechkov/core": "0.2.6"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^25.6.0",
package/src/index.ts CHANGED
@@ -28,6 +28,8 @@ export { pretrain } from './pretrain.js';
28
28
  export { loadPatterns, loadSessions, computePatternBoost, readLearningConfig, BOOST_CAP, recordPattern, loadStorePatternsSync, patternToRecord, recordToPattern, consolidateSessions, recallPatterns, pruneNoisePatterns } from './patterns.js';
29
29
  export type { PatternRecord, SessionRecord, LearningConfig, LoadOptions, ConsolidateResult, ConsolidateOptions, SqliteBackendMode, RecallHit, SessionsSource, PruneNoiseResult } from './patterns.js';
30
30
  export { runSetup, generateHooksConfig, generateAgentdbWriter, writerVersionOf, AGENTDB_WRITER_VERSION } from './setup.js';
31
+ export { statuslineData, readFeatureAdrState, writeFeatureAdrState, featureAdrStatePath } from './statusline.js';
32
+ export type { StatuslineData, FeatureAdrState, WriteFeatureAdrStateInput } from './statusline.js';
31
33
  export { indexPatternsToAgentdb, resolveAgentdbPath } from './agentdb-index.js';
32
34
  export { putBookKnowledge, queryBookKnowledge, bookKbPath } from './book-kb.js';
33
35
  export type { BookKU, BookKUHit } from './book-kb.js';
@@ -0,0 +1,282 @@
1
+ /**
2
+ * `dz statusline` data source — the FAST, best-effort read behind the live
3
+ * self-learning panel Claude Code renders in its status bar (modeled on
4
+ * agentic-qe's "🎓 12 patterns" statusline, showing dz's OWN counts).
5
+ *
6
+ * Claude Code refreshes a `statusLine` command up to every ~300ms, so this MUST
7
+ * be fast (<~50ms) and MUST NEVER throw or hang — a broken statusline garbles the
8
+ * terminal bar. Every read is therefore:
9
+ * - **readonly + short busy_timeout** — a live MCP writer holding the store lock
10
+ * must never make the panel wait; we back off immediately, not block.
11
+ * - **best-effort** — any error (absent/corrupt `.dz`, missing native module,
12
+ * locked db) collapses to `0` / an omitted field, never an exception.
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+
17
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
18
+ import { dirname, join, resolve } from 'node:path';
19
+ import { createRequire } from 'node:module';
20
+
21
+ import { listBrain } from './brain.js';
22
+
23
+ /**
24
+ * Live learning state for one in-flight `/feature-adr` run — the per-run visibility panel
25
+ * that surfaces the Pattern memory loop (POOL learned, RECALLED for this run, STORED this run).
26
+ * Written by the pipeline at Steps 0/8/9 via `writeFeatureAdrState`; read back on the render
27
+ * path (readonly, best-effort) by `readFeatureAdrState`.
28
+ */
29
+ export interface FeatureAdrState {
30
+ /** The feature slug the pipeline is working on (kebab-case). */
31
+ readonly slug: string;
32
+ /** Human-readable step label (e.g. "Step 0", "Step 8 QE"). */
33
+ readonly step: string;
34
+ /** Total learned-pattern POOL (all patterns available to recall from) at write time. */
35
+ readonly pool: number;
36
+ /** How many patterns this run RECALLED / used to inform its work. */
37
+ readonly recalled: number;
38
+ /** How many NEW patterns this run STORED back into the pool. */
39
+ readonly stored: number;
40
+ /** ISO timestamp of the write — drives the freshness window on the render path. */
41
+ readonly ts: string;
42
+ /** Optional run mode (e.g. "reference", "full-qe", "full-qe-extended"). */
43
+ readonly mode?: string;
44
+ }
45
+
46
+ /** A snapshot of dz's self-learning state for one project (all fields best-effort). */
47
+ export interface StatuslineData {
48
+ /** Count of learned patterns in the project's unified memory store. */
49
+ readonly patterns: number;
50
+ /** Number of sources registered in the durable cross-project knowledge brain. */
51
+ readonly brainSources: number;
52
+ /** Hours since the last `dz consolidate` run, if a watermark is present. */
53
+ readonly consolidatedAgeH?: number;
54
+ /** Live `/feature-adr` learning state — present ONLY when a fresh run is in flight. */
55
+ readonly featureAdr?: FeatureAdrState;
56
+ }
57
+
58
+ /** Path of the SQLite pattern store (the Tier-3 backend). */
59
+ function sqlitePatternPath(projectRoot: string): string {
60
+ return join(projectRoot, '.dz', 'memory', 'patterns.sqlite');
61
+ }
62
+
63
+ /** The `dz consolidate` watermark (max processed transcript timestamp). */
64
+ function consolidateWatermarkPath(projectRoot: string): string {
65
+ return join(projectRoot, '.dz', 'memory', 'consolidate.json');
66
+ }
67
+
68
+ /** Path of the live `/feature-adr` learning-state file (per-run panel source). */
69
+ export function featureAdrStatePath(projectRoot: string): string {
70
+ return join(projectRoot, '.dz', 'feature-adr', 'learning-state.json');
71
+ }
72
+
73
+ /**
74
+ * Freshness window for the `/feature-adr` panel: a run older than this is considered finished, so
75
+ * its state must NOT keep showing a stale panel in the status bar. 30 minutes (in ms).
76
+ */
77
+ const FEATURE_ADR_FRESH_MS = 30 * 60 * 1_000;
78
+
79
+ interface ReadonlyCountDb {
80
+ pragma: (s: string) => void;
81
+ prepare: (q: string) => { get: (...a: unknown[]) => unknown };
82
+ close: () => void;
83
+ }
84
+
85
+ /**
86
+ * Count learned patterns via a direct **readonly** `COUNT(*)` with a short
87
+ * `busy_timeout` — no FTS rebuild, no schema write, no waiting on a live writer.
88
+ * Returns `undefined` (not `0`) when the fast path is unavailable so the caller
89
+ * can fall back to a readonly jsonl line-count; any error → `undefined`.
90
+ */
91
+ function countSqlitePatternsReadonly(sqlitePath: string): number | undefined {
92
+ try {
93
+ const require = createRequire(import.meta.url);
94
+ const Database = require('better-sqlite3') as new (p: string, o?: object) => ReadonlyCountDb;
95
+ const db = new Database(sqlitePath, { readonly: true });
96
+ try {
97
+ db.pragma('busy_timeout = 100'); // back off fast — never block the 300ms refresh on a write lock
98
+ const row = db.prepare('SELECT COUNT(*) as cnt FROM memory_records').get() as { cnt?: unknown };
99
+ return typeof row?.cnt === 'number' ? row.cnt : undefined;
100
+ } finally {
101
+ db.close();
102
+ }
103
+ } catch {
104
+ return undefined;
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Count the legacy/default `.dz/patterns.jsonl` store by reading the FILE directly — READONLY, no
110
+ * backend open, no FTS rebuild, no schema write. Used only when the SQLite readonly COUNT is
111
+ * unavailable (no SQLite tier, or a transient lock). Best-effort → 0 on any error.
112
+ */
113
+ function countJsonlPatternsReadonly(projectRoot: string): number {
114
+ const path = join(projectRoot, '.dz', 'patterns.jsonl');
115
+ if (!existsSync(path)) return 0;
116
+ try {
117
+ return readFileSync(path, 'utf-8').split('\n').filter((l) => l.trim() !== '').length;
118
+ } catch {
119
+ return 0;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Learned-pattern count for the panel: the fast **readonly** SQLite `COUNT(*)`, else a **readonly**
125
+ * jsonl line-count, else `0`. NEVER opens the store read-write (the render path must not run the
126
+ * mutating FTS rebuild `loadStorePatternsSync` does). This counts the durable SQLite tier and so
127
+ * tracks `dz recall --all` in steady state (jsonl folds into SQLite on consolidate); it is a fast
128
+ * approximation, not a deduped union, by design — a status bar must stay readonly + sub-50ms.
129
+ */
130
+ function countLearnedPatterns(projectRoot: string): number {
131
+ const sqlitePath = sqlitePatternPath(projectRoot);
132
+ if (existsSync(sqlitePath)) {
133
+ const fast = countSqlitePatternsReadonly(sqlitePath);
134
+ if (fast !== undefined) return fast;
135
+ }
136
+ return countJsonlPatternsReadonly(projectRoot);
137
+ }
138
+
139
+ /** Hours since the last consolidation, or `undefined` when never consolidated / unreadable. */
140
+ function consolidatedAgeHours(projectRoot: string, now: number): number | undefined {
141
+ const path = consolidateWatermarkPath(projectRoot);
142
+ if (!existsSync(path)) return undefined;
143
+ try {
144
+ const parsed = JSON.parse(readFileSync(path, 'utf-8')) as { lastConsolidatedTs?: unknown };
145
+ const ts = typeof parsed.lastConsolidatedTs === 'string' ? Date.parse(parsed.lastConsolidatedTs) : Number.NaN;
146
+ if (Number.isNaN(ts)) return undefined;
147
+ return Math.max(0, Math.round((now - ts) / 3_600_000));
148
+ } catch {
149
+ return undefined;
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Read the live `/feature-adr` learning state for one project — the source of the per-run panel.
155
+ *
156
+ * RENDER-PATH DISCIPLINE (statusline pattern #1): this runs inside the ~300ms status-bar refresh, so
157
+ * it is a plain **readonly** file read, **best-effort**, and NEVER throws — an absent, unreadable, or
158
+ * corrupt state file collapses to `undefined`, not an exception.
159
+ *
160
+ * FRESHNESS: a run whose `ts` is older than {@link FEATURE_ADR_FRESH_MS} is treated as finished and
161
+ * returns `undefined`, so a stale run can never keep a panel pinned in the status bar.
162
+ *
163
+ * @param projectRoot Absolute (or cwd-relative) project directory.
164
+ * @param now Injectable clock (epoch ms) for the freshness check — defaults to `Date.now()`.
165
+ */
166
+ export function readFeatureAdrState(projectRoot: string, now: number = Date.now()): FeatureAdrState | undefined {
167
+ const path = featureAdrStatePath(resolve(projectRoot));
168
+ if (!existsSync(path)) return undefined;
169
+ try {
170
+ const parsed = JSON.parse(readFileSync(path, 'utf-8')) as Partial<FeatureAdrState>;
171
+ if (typeof parsed.slug !== 'string' || parsed.slug.length === 0) return undefined;
172
+ if (typeof parsed.step !== 'string' || parsed.step.length === 0) return undefined;
173
+ if (typeof parsed.ts !== 'string') return undefined;
174
+ const tsMs = Date.parse(parsed.ts);
175
+ if (Number.isNaN(tsMs)) return undefined;
176
+ if (now - tsMs > FEATURE_ADR_FRESH_MS) return undefined; // stale run — do not surface a panel
177
+ const num = (v: unknown): number => (typeof v === 'number' && Number.isFinite(v) ? v : 0);
178
+ const state: FeatureAdrState = {
179
+ slug: parsed.slug,
180
+ step: parsed.step,
181
+ pool: num(parsed.pool),
182
+ recalled: num(parsed.recalled),
183
+ stored: num(parsed.stored),
184
+ ts: parsed.ts,
185
+ ...(typeof parsed.mode === 'string' && parsed.mode.length > 0 ? { mode: parsed.mode } : {}),
186
+ };
187
+ return state;
188
+ } catch {
189
+ return undefined;
190
+ }
191
+ }
192
+
193
+ /** Fields the `/feature-adr` pipeline supplies when recording its live learning state. */
194
+ export interface WriteFeatureAdrStateInput {
195
+ readonly slug: string;
196
+ readonly step: string;
197
+ readonly recalled: number;
198
+ readonly stored: number;
199
+ readonly mode?: string;
200
+ }
201
+
202
+ /**
203
+ * Record the live `/feature-adr` learning state — called by the pipeline at Steps 0/8/9. Computes
204
+ * `pool` as the total learned-pattern count (via the same readonly {@link countLearnedPatterns} the
205
+ * panel uses) and writes the JSON with a fresh `ts`. Best-effort: returns the written state, or
206
+ * `undefined` on any I/O error (this must never break the pipeline).
207
+ *
208
+ * @param now Injectable clock (epoch ms) for the write timestamp — defaults to `Date.now()`.
209
+ */
210
+ export function writeFeatureAdrState(
211
+ projectRoot: string,
212
+ input: WriteFeatureAdrStateInput,
213
+ now: number = Date.now(),
214
+ ): FeatureAdrState | undefined {
215
+ const root = resolve(projectRoot);
216
+ let pool = 0;
217
+ try {
218
+ pool = countLearnedPatterns(root);
219
+ } catch {
220
+ pool = 0;
221
+ }
222
+ const state: FeatureAdrState = {
223
+ slug: input.slug,
224
+ step: input.step,
225
+ pool,
226
+ recalled: Number.isFinite(input.recalled) ? input.recalled : 0,
227
+ stored: Number.isFinite(input.stored) ? input.stored : 0,
228
+ ts: new Date(now).toISOString(),
229
+ ...(input.mode !== undefined && input.mode.length > 0 ? { mode: input.mode } : {}),
230
+ };
231
+ try {
232
+ const path = featureAdrStatePath(root);
233
+ mkdirSync(dirname(path), { recursive: true });
234
+ writeFileSync(path, `${JSON.stringify(state, null, 2)}\n`);
235
+ } catch {
236
+ return undefined;
237
+ }
238
+ return state;
239
+ }
240
+
241
+ /**
242
+ * Gather dz's self-learning counts for one project. FAST + best-effort: every read
243
+ * is guarded so a missing/corrupt `.dz`, absent native module, or locked store
244
+ * yields `0` / an omitted field — this function NEVER throws.
245
+ *
246
+ * @param projectRoot Absolute (or cwd-relative) project directory.
247
+ * @param now Injectable clock (epoch ms) for the consolidation age — defaults to `Date.now()`.
248
+ */
249
+ export function statuslineData(projectRoot: string, now: number = Date.now()): StatuslineData {
250
+ const root = resolve(projectRoot);
251
+
252
+ let patterns = 0;
253
+ try {
254
+ patterns = countLearnedPatterns(root);
255
+ } catch {
256
+ patterns = 0;
257
+ }
258
+
259
+ let brainSources = 0;
260
+ try {
261
+ brainSources = listBrain().length;
262
+ } catch {
263
+ brainSources = 0;
264
+ }
265
+
266
+ const ageH = consolidatedAgeHours(root, now);
267
+
268
+ // Live /feature-adr panel — attached ONLY when a fresh run is in flight (readonly, never throws).
269
+ let featureAdr: FeatureAdrState | undefined;
270
+ try {
271
+ featureAdr = readFeatureAdrState(root, now);
272
+ } catch {
273
+ featureAdr = undefined;
274
+ }
275
+
276
+ return {
277
+ patterns,
278
+ brainSources,
279
+ ...(ageH !== undefined ? { consolidatedAgeH: ageH } : {}),
280
+ ...(featureAdr !== undefined ? { featureAdr } : {}),
281
+ };
282
+ }