@dzhechkov/harness-core 0.7.2 → 0.7.4

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.
Files changed (62) hide show
  1. package/.dz-manifest.json +121 -41
  2. package/README.md +1 -1
  3. package/dist/cli-flag-notice.d.ts +50 -0
  4. package/dist/cli-flag-notice.d.ts.map +1 -0
  5. package/dist/cli-flag-notice.js +106 -0
  6. package/dist/cli-flag-notice.js.map +1 -0
  7. package/dist/event-chain.d.ts +50 -0
  8. package/dist/event-chain.d.ts.map +1 -1
  9. package/dist/event-chain.js +31 -0
  10. package/dist/event-chain.js.map +1 -1
  11. package/dist/index.d.ts +9 -5
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +7 -3
  14. package/dist/index.js.map +1 -1
  15. package/dist/name-check.d.ts +98 -0
  16. package/dist/name-check.d.ts.map +1 -0
  17. package/dist/name-check.js +333 -0
  18. package/dist/name-check.js.map +1 -0
  19. package/dist/operations.d.ts.map +1 -1
  20. package/dist/operations.js +33 -5
  21. package/dist/operations.js.map +1 -1
  22. package/dist/provenance.d.ts +100 -92
  23. package/dist/provenance.d.ts.map +1 -1
  24. package/dist/provenance.js +122 -122
  25. package/dist/provenance.js.map +1 -1
  26. package/dist/recall-domain-boost.d.ts +10 -3
  27. package/dist/recall-domain-boost.d.ts.map +1 -1
  28. package/dist/recall-domain-boost.js +7 -0
  29. package/dist/recall-domain-boost.js.map +1 -1
  30. package/dist/recall-hook-policy.d.ts +15 -0
  31. package/dist/recall-hook-policy.d.ts.map +1 -1
  32. package/dist/recall-hook-policy.js +59 -0
  33. package/dist/recall-hook-policy.js.map +1 -1
  34. package/dist/recap.d.ts +146 -0
  35. package/dist/recap.d.ts.map +1 -0
  36. package/dist/recap.js +346 -0
  37. package/dist/recap.js.map +1 -0
  38. package/dist/retro.d.ts +131 -0
  39. package/dist/retro.d.ts.map +1 -0
  40. package/dist/retro.js +207 -0
  41. package/dist/retro.js.map +1 -0
  42. package/dist/score.d.ts +21 -0
  43. package/dist/score.d.ts.map +1 -1
  44. package/dist/score.js +44 -3
  45. package/dist/score.js.map +1 -1
  46. package/dist/vector-tier.d.ts +54 -0
  47. package/dist/vector-tier.d.ts.map +1 -1
  48. package/dist/vector-tier.js +69 -8
  49. package/dist/vector-tier.js.map +1 -1
  50. package/package.json +8 -8
  51. package/sbom.json +240 -40
  52. package/src/cli-flag-notice.ts +114 -0
  53. package/src/event-chain.ts +64 -0
  54. package/src/index.ts +13 -0
  55. package/src/name-check.ts +331 -0
  56. package/src/operations.ts +34 -6
  57. package/src/provenance.ts +217 -0
  58. package/src/recall-domain-boost.ts +10 -3
  59. package/src/recall-hook-policy.ts +60 -0
  60. package/src/recap.ts +462 -0
  61. package/src/score.ts +53 -3
  62. package/src/vector-tier.ts +109 -10
@@ -0,0 +1,131 @@
1
+ /**
2
+ * `dz retro` — what was done over a day, a week or a month.
3
+ *
4
+ * This module is PURE: no filesystem, no network, and — load-bearing — no clock. The window arrives
5
+ * as a parameter, because a window you cannot pin in a test is a window whose arithmetic errors you
6
+ * cannot catch. MEASURED in this project 2026-08-22: an agent's timestamp was off by a YEAR, the
7
+ * query returned 15 530 "hits" for a "week", and nothing about the output looked wrong.
8
+ *
9
+ * Its second job is refusing. Half of an honest report is declining to answer what the data cannot
10
+ * support, and those refusals live here as behaviour — types that cannot express a quarter, a
11
+ * decision function that names the real span in days, and a three-state section verdict where
12
+ * "the source said nothing" and "the source was not read" can never collapse into one zero.
13
+ *
14
+ * See features/dz-retro/03_adr/ for the decisions and the measurements behind them.
15
+ */
16
+ /** The only horizons this project has the data for. A quarter or a year is NOT SPELLABLE (ADR-001). */
17
+ export type RetroHorizon = 'day' | 'week' | 'month';
18
+ /** Horizons a user may ASK for — recognised so they are refused loudly, never swallowed. */
19
+ export type RefusedHorizon = 'quarter' | 'half-year' | 'year';
20
+ export declare const REFUSED_HORIZONS: readonly RefusedHorizon[];
21
+ export interface RetroWindow {
22
+ readonly horizon: RetroHorizon;
23
+ /** Inclusive ISO date (YYYY-MM-DD) of the first day in the window. */
24
+ readonly startIso: string;
25
+ /** Inclusive ISO date of the last day — the anchor. */
26
+ readonly endIso: string;
27
+ readonly days: number;
28
+ }
29
+ /**
30
+ * The window for a horizon, anchored on an EXPLICIT date. Never reads the clock.
31
+ * `atIso` may be a full timestamp; only its date part is used.
32
+ */
33
+ export declare function retroWindow(horizon: RetroHorizon, atIso: string): RetroWindow;
34
+ /** Is this instant inside the window? Compared in UTC, never as strings (ADR/AM-5). */
35
+ export declare function withinWindow(w: RetroWindow, isoInstant: string): boolean;
36
+ export interface HorizonDecision {
37
+ readonly action: 'report' | 'refuse';
38
+ readonly reason: string;
39
+ }
40
+ /**
41
+ * May we report over the requested horizon at all?
42
+ *
43
+ * `spanDays` is the age of the LONGEST record we actually hold. Asking for a year over 174 days of
44
+ * data is not a thin report — it is an invented one, so it is refused and the real span is named.
45
+ */
46
+ export declare function decideHorizon(input: {
47
+ requested: string;
48
+ spanDays: number;
49
+ }): HorizonDecision;
50
+ export type SectionStatus = 'full' | 'partial' | 'unavailable';
51
+ export interface SectionVerdict {
52
+ readonly status: SectionStatus;
53
+ /** The date this source's records begin — computed from the source itself, never hardcoded. */
54
+ readonly dataStart: string | null;
55
+ readonly note: string;
56
+ }
57
+ /**
58
+ * Does this source cover the whole window?
59
+ *
60
+ * `dataStart: null` means the source was NOT READ — a different fact from "read, and empty".
61
+ * Collapsing the two is how a report says "nothing happened" about a week it could not see.
62
+ */
63
+ export declare function sectionStatus(input: {
64
+ dataStart: string | null;
65
+ windowStart: string;
66
+ }): SectionVerdict;
67
+ export interface ForbiddenMetric {
68
+ readonly name: string;
69
+ /** The measurement that disqualifies it. A bare ban decays into a word list. */
70
+ readonly reason: string;
71
+ }
72
+ /**
73
+ * Measures of the INSTRUMENT, not of the work (ADR-003). Each will be proposed again precisely
74
+ * because each is a one-liner to compute, so each carries the measurement that refutes it.
75
+ */
76
+ export declare const FORBIDDEN_METRICS: readonly ForbiddenMetric[];
77
+ export interface Delivery {
78
+ readonly slug: string;
79
+ readonly createdIso: string;
80
+ /** 'unique' carries a grade; 'ambiguous' and 'none' are facts about the report, not gaps. */
81
+ readonly gradeStatus: 'unique' | 'ambiguous' | 'none' | 'no-report';
82
+ readonly grade: string | null;
83
+ }
84
+ export interface Publish {
85
+ readonly pkg: string;
86
+ readonly version: string;
87
+ readonly iso: string;
88
+ }
89
+ export interface GuardRun {
90
+ readonly iso: string;
91
+ readonly verdict: string;
92
+ readonly rules: readonly string[];
93
+ }
94
+ export interface ReuseFacts {
95
+ readonly dataStart: string | null;
96
+ readonly eventsInWindow: number;
97
+ readonly lessonsEverRecalled: number;
98
+ readonly lessonsTotal: number;
99
+ }
100
+ export interface SourceFacts<T> {
101
+ readonly dataStart: string | null;
102
+ readonly items: readonly T[];
103
+ }
104
+ export interface RetroFacts {
105
+ readonly window: RetroWindow;
106
+ /** The longest record we hold, in days — what `decideHorizon` judges against. */
107
+ readonly spanDays: number;
108
+ /** `null` means NOT READ. An empty `items` means read-and-empty. The type keeps them apart. */
109
+ readonly deliveries: SourceFacts<Delivery> | null;
110
+ readonly publishes: SourceFacts<Publish> | null;
111
+ readonly guard: SourceFacts<GuardRun> | null;
112
+ readonly reuse: ReuseFacts | null;
113
+ /** Feature dirs on disk that git has never seen — the report is blind to them, and says so. */
114
+ readonly uncommittedSlugs: readonly string[];
115
+ }
116
+ export interface RetroSection {
117
+ readonly id: 'deliveries' | 'publishes' | 'discipline' | 'reuse';
118
+ readonly title: string;
119
+ readonly verdict: SectionVerdict;
120
+ readonly lines: readonly string[];
121
+ }
122
+ export interface RetroReport {
123
+ readonly window: RetroWindow;
124
+ readonly spanDays: number;
125
+ readonly sections: readonly RetroSection[];
126
+ readonly caveats: readonly string[];
127
+ }
128
+ export declare function buildRetro(facts: RetroFacts): RetroReport;
129
+ /** The human rendering. `--json` prints the SAME `RetroReport` — one structure, two spellings (FR-6). */
130
+ export declare function renderRetro(report: RetroReport): string[];
131
+ //# sourceMappingURL=retro.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retro.d.ts","sourceRoot":"","sources":["../src/retro.ts"],"names":[],"mappings":"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"}
package/dist/retro.js ADDED
@@ -0,0 +1,207 @@
1
+ /**
2
+ * `dz retro` — what was done over a day, a week or a month.
3
+ *
4
+ * This module is PURE: no filesystem, no network, and — load-bearing — no clock. The window arrives
5
+ * as a parameter, because a window you cannot pin in a test is a window whose arithmetic errors you
6
+ * cannot catch. MEASURED in this project 2026-08-22: an agent's timestamp was off by a YEAR, the
7
+ * query returned 15 530 "hits" for a "week", and nothing about the output looked wrong.
8
+ *
9
+ * Its second job is refusing. Half of an honest report is declining to answer what the data cannot
10
+ * support, and those refusals live here as behaviour — types that cannot express a quarter, a
11
+ * decision function that names the real span in days, and a three-state section verdict where
12
+ * "the source said nothing" and "the source was not read" can never collapse into one zero.
13
+ *
14
+ * See features/dz-retro/03_adr/ for the decisions and the measurements behind them.
15
+ */
16
+ export const REFUSED_HORIZONS = ['quarter', 'half-year', 'year'];
17
+ const HORIZON_DAYS = { day: 1, week: 7, month: 30 };
18
+ const REFUSED_DAYS = { quarter: 90, 'half-year': 182, year: 365 };
19
+ const DAY_MS = 86_400_000;
20
+ function isoDay(value) {
21
+ return value.slice(0, 10);
22
+ }
23
+ /**
24
+ * The window for a horizon, anchored on an EXPLICIT date. Never reads the clock.
25
+ * `atIso` may be a full timestamp; only its date part is used.
26
+ */
27
+ export function retroWindow(horizon, atIso) {
28
+ const end = isoDay(atIso);
29
+ const endMs = Date.parse(`${end}T00:00:00.000Z`);
30
+ if (Number.isNaN(endMs))
31
+ throw new Error(`retroWindow: not an ISO date: ${JSON.stringify(atIso)}`);
32
+ const days = HORIZON_DAYS[horizon];
33
+ const startMs = endMs - (days - 1) * DAY_MS;
34
+ return { horizon, startIso: new Date(startMs).toISOString().slice(0, 10), endIso: end, days };
35
+ }
36
+ /** Is this instant inside the window? Compared in UTC, never as strings (ADR/AM-5). */
37
+ export function withinWindow(w, isoInstant) {
38
+ const t = Date.parse(isoInstant);
39
+ if (Number.isNaN(t))
40
+ return false;
41
+ const from = Date.parse(`${w.startIso}T00:00:00.000Z`);
42
+ const to = Date.parse(`${w.endIso}T00:00:00.000Z`) + DAY_MS;
43
+ return t >= from && t < to;
44
+ }
45
+ /**
46
+ * May we report over the requested horizon at all?
47
+ *
48
+ * `spanDays` is the age of the LONGEST record we actually hold. Asking for a year over 174 days of
49
+ * data is not a thin report — it is an invented one, so it is refused and the real span is named.
50
+ */
51
+ export function decideHorizon(input) {
52
+ const req = input.requested.trim().toLowerCase();
53
+ const span = Number.isFinite(input.spanDays) ? Math.max(0, Math.floor(input.spanDays)) : 0;
54
+ if (req in HORIZON_DAYS) {
55
+ const need = HORIZON_DAYS[req];
56
+ if (span < need) {
57
+ return {
58
+ action: 'refuse',
59
+ reason: `a ${req} needs ${need} day(s) of records and we hold ${span} — reporting it would invent the difference`,
60
+ };
61
+ }
62
+ return { action: 'report', reason: `${req}: ${need} day(s) against ${span} day(s) of records` };
63
+ }
64
+ if (REFUSED_HORIZONS.includes(req)) {
65
+ const need = REFUSED_DAYS[req];
66
+ return {
67
+ action: 'refuse',
68
+ reason: `a ${req} needs about ${need} days of records and the longest record here spans ${span} day(s) — there is exactly one complete quarter, so a quarter-over-quarter comparison is arithmetically impossible and a year would be fabrication`,
69
+ };
70
+ }
71
+ return { action: 'refuse', reason: `unknown horizon ${JSON.stringify(input.requested)} — use --day, --week or --month` };
72
+ }
73
+ /**
74
+ * Does this source cover the whole window?
75
+ *
76
+ * `dataStart: null` means the source was NOT READ — a different fact from "read, and empty".
77
+ * Collapsing the two is how a report says "nothing happened" about a week it could not see.
78
+ */
79
+ export function sectionStatus(input) {
80
+ if (input.dataStart === null) {
81
+ return { status: 'unavailable', dataStart: null, note: 'source not read — this section says nothing, which is not the same as zero' };
82
+ }
83
+ const start = isoDay(input.dataStart);
84
+ if (start <= isoDay(input.windowStart)) {
85
+ return { status: 'full', dataStart: start, note: `records cover the whole window (from ${start})` };
86
+ }
87
+ return { status: 'partial', dataStart: start, note: `records only begin ${start}, inside the window — everything before that is unknown, not absent` };
88
+ }
89
+ /**
90
+ * Measures of the INSTRUMENT, not of the work (ADR-003). Each will be proposed again precisely
91
+ * because each is a one-liner to compute, so each carries the measurement that refutes it.
92
+ */
93
+ export const FORBIDDEN_METRICS = [
94
+ { name: 'commit count', reason: 'this project mandates a commit per logical change; 1318 commits over 66 active days measures compliance with that rule, not output (MEASURED 2026-08-22)' },
95
+ { name: 'lines changed', reason: 'generated artifacts dominate — 352 of 1318 commits are docs, and one pipeline run writes 8-10 files before a line of product code exists' },
96
+ { name: 'token spend', reason: 'self-declared an estimate, once wrong sixfold, covers 17 days, and 20 of 86 ledger rows carry no number by construction' },
97
+ { name: 'learning event volume', reason: '640 in May against 10454 in August, but the sources are post-edit and post-command hooks: the curve measures when hooks were installed' },
98
+ { name: 'inventory counts', reason: 'skills, packages and tests only ever grow, so they can only ever flatter' },
99
+ { name: 'learned lesson count', reason: 'already refuted by this project’s own dz compounding: 54% of the pool has never been read by anyone' },
100
+ ];
101
+ function emptyOrUnavailable(v, emptyLine) {
102
+ return v.status === 'unavailable'
103
+ ? ['not read — this section cannot say anything about this window']
104
+ : [emptyLine];
105
+ }
106
+ export function buildRetro(facts) {
107
+ const ws = facts.window.startIso;
108
+ const sections = [];
109
+ // 1. Deliveries
110
+ {
111
+ const v = sectionStatus({ dataStart: facts.deliveries?.dataStart ?? null, windowStart: ws });
112
+ const items = (facts.deliveries?.items ?? []).filter((d) => withinWindow(facts.window, d.createdIso));
113
+ const graded = items.filter((d) => d.gradeStatus === 'unique');
114
+ const ambiguous = items.filter((d) => d.gradeStatus === 'ambiguous');
115
+ const ungraded = items.filter((d) => d.gradeStatus === 'none' || d.gradeStatus === 'no-report');
116
+ const lines = items.length === 0
117
+ ? emptyOrUnavailable(v, 'no feature directories were created in this window')
118
+ : [
119
+ `${items.length} feature director${items.length === 1 ? 'y' : 'ies'} created`,
120
+ `${graded.length} carry a grade an independent review stated unambiguously${graded.length > 0 ? `: ${tally(graded.map((d) => d.grade))}` : ''}`,
121
+ `${ambiguous.length} have a report that states MORE THAN ONE grade — reported as ambiguous, never guessed`,
122
+ `${ungraded.length} have no letter grade in their report, or no report at all`,
123
+ 'cadence is not value: this counts deliveries, not what they were worth',
124
+ ];
125
+ sections.push({ id: 'deliveries', title: 'Deliveries', verdict: v, lines });
126
+ }
127
+ // 2. Publishes
128
+ {
129
+ const v = sectionStatus({ dataStart: facts.publishes?.dataStart ?? null, windowStart: ws });
130
+ const items = (facts.publishes?.items ?? []).filter((p) => withinWindow(facts.window, p.iso));
131
+ const pkgs = new Set(items.map((p) => p.pkg));
132
+ const lines = items.length === 0
133
+ ? emptyOrUnavailable(v, 'no versions were accepted by the registry in this window')
134
+ : [
135
+ `${items.length} version(s) accepted by the registry across ${pkgs.size} package(s)`,
136
+ 'timestamps are the registry’s own — this is the one record here nobody local can backdate',
137
+ ];
138
+ sections.push({ id: 'publishes', title: 'Publishes', verdict: v, lines });
139
+ }
140
+ // 3. Discipline — DESCRIBES, never compares (ADR-004)
141
+ {
142
+ const v = sectionStatus({ dataStart: facts.guard?.dataStart ?? null, windowStart: ws });
143
+ const runs = (facts.guard?.items ?? []).filter((g) => withinWindow(facts.window, g.iso));
144
+ const byVerdict = new Map();
145
+ const byRule = new Map();
146
+ for (const r of runs) {
147
+ byVerdict.set(r.verdict, (byVerdict.get(r.verdict) ?? 0) + 1);
148
+ for (const rule of r.rules)
149
+ byRule.set(rule, (byRule.get(rule) ?? 0) + 1);
150
+ }
151
+ const lines = runs.length === 0
152
+ ? emptyOrUnavailable(v, 'no gate runs were recorded in this window')
153
+ : [
154
+ `${runs.length} gate run(s): ${[...byVerdict.entries()].map(([k, n]) => `${k} ${n}`).join(', ')}`,
155
+ byRule.size === 0
156
+ ? 'no rule was violated in this window'
157
+ : `violations by rule: ${[...byRule.entries()].sort((a, b) => b[1] - a[1]).map(([k, n]) => `${k} ${n}`).join(', ')}`,
158
+ ];
159
+ // The caveat is NOT optional and NOT conditional: it is the whole honesty of the section.
160
+ lines.push('a rule missing from this list was either never violated or did not yet exist — the log records a rule only when it fires, so it cannot tell those apart');
161
+ lines.push('this section describes the window; it deliberately computes no comparison between periods');
162
+ sections.push({ id: 'discipline', title: 'Discipline', verdict: v, lines });
163
+ }
164
+ // 4. Knowledge reuse
165
+ {
166
+ const v = sectionStatus({ dataStart: facts.reuse?.dataStart ?? null, windowStart: ws });
167
+ const r = facts.reuse;
168
+ const lines = r === null || r.lessonsTotal === 0
169
+ ? emptyOrUnavailable(v, 'no lessons are stored, so there is nothing to reuse')
170
+ : [
171
+ `${r.eventsInWindow} recall event(s) in this window`,
172
+ `${r.lessonsEverRecalled} of ${r.lessonsTotal} stored lessons have ever been read (${Math.round((r.lessonsEverRecalled / r.lessonsTotal) * 100)}%)`,
173
+ 'this is a ratio with a hostile denominator: storing more unread lessons makes it worse, not better',
174
+ ];
175
+ sections.push({ id: 'reuse', title: 'Knowledge reuse', verdict: v, lines });
176
+ }
177
+ const caveats = [];
178
+ if (facts.uncommittedSlugs.length > 0) {
179
+ caveats.push(`${facts.uncommittedSlugs.length} feature director${facts.uncommittedSlugs.length === 1 ? 'y is' : 'ies are'} not committed yet and therefore invisible to this report: ${facts.uncommittedSlugs.join(', ')}`);
180
+ }
181
+ caveats.push('none of the following is computed here, and each carries the measurement that disqualifies it: ' + FORBIDDEN_METRICS.map((m) => m.name).join(', '));
182
+ return { window: facts.window, spanDays: facts.spanDays, sections, caveats };
183
+ }
184
+ function tally(values) {
185
+ const m = new Map();
186
+ for (const v of values)
187
+ m.set(v, (m.get(v) ?? 0) + 1);
188
+ return [...m.entries()].sort((a, b) => (a[0] < b[0] ? -1 : 1)).map(([k, n]) => `${k}×${n}`).join(' ');
189
+ }
190
+ /** The human rendering. `--json` prints the SAME `RetroReport` — one structure, two spellings (FR-6). */
191
+ export function renderRetro(report) {
192
+ const out = [];
193
+ out.push(`dz retro — ${report.window.horizon}: ${report.window.startIso} … ${report.window.endIso} (${report.window.days} day(s))`);
194
+ out.push(`records held: ${report.spanDays} day(s)`);
195
+ for (const s of report.sections) {
196
+ out.push('');
197
+ out.push(`${s.title} [${s.verdict.status}]${s.verdict.dataStart !== null ? ` · records from ${s.verdict.dataStart}` : ''}`);
198
+ out.push(` ${s.verdict.note}`);
199
+ for (const l of s.lines)
200
+ out.push(` · ${l}`);
201
+ }
202
+ out.push('');
203
+ for (const c of report.caveats)
204
+ out.push(`! ${c}`);
205
+ return out;
206
+ }
207
+ //# sourceMappingURL=retro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retro.js","sourceRoot":"","sources":["../src/retro.ts"],"names":[],"mappings":"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"}
package/dist/score.d.ts CHANGED
@@ -38,6 +38,27 @@ export interface RunScorecard {
38
38
  }
39
39
  /** The artifact texts of one run, keyed by RELATIVE path under `features/<slug>/`. */
40
40
  export type RunArtifacts = Readonly<Record<string, string>>;
41
+ export type GradeReadStatus = 'unique' | 'ambiguous' | 'none';
42
+ export interface GradeReading {
43
+ readonly status: GradeReadStatus;
44
+ /** The grade, ONLY when the report names one unambiguously. */
45
+ readonly grade: string | null;
46
+ /** Every distinct grade found, normalised — what makes an `ambiguous` verdict inspectable. */
47
+ readonly found: readonly string[];
48
+ }
49
+ /**
50
+ * Read the review grade a report states — and refuse to guess when it states more than one.
51
+ *
52
+ * The obvious rules are both WRONG, and both were measured before this was written (ADR-002):
53
+ * FIRST match returns the round-1 grade of a report that was later fixed; LAST match returns a
54
+ * section heading naming the pre-fix grade, or a sentence quoting a grade in prose. Across 154
55
+ * real reports the two disagree in 14 files, and in `crossrt-2-codex-hooks` NEITHER is right —
56
+ * its true verdict is an all-caps `GRADE A` the old regex could not see at all.
57
+ *
58
+ * So: a grade is reported only when every occurrence agrees. Otherwise the caller is told the
59
+ * report is ambiguous, which is a fact about the report, not a missing number.
60
+ */
61
+ export declare function readQeGrade(qeText: string): GradeReading;
41
62
  export declare function extractQeGrade(qeText: string): string | null;
42
63
  export declare function scoreRun(slug: string, artifacts: RunArtifacts): RunScorecard;
43
64
  export declare function renderScorecard(card: RunScorecard): string;
@@ -1 +1 @@
1
- {"version":3,"file":"score.d.ts","sourceRoot":"","sources":["../src/score.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE9D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;IACjD,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,sFAAsF;AACtF,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAsD5D,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG5D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,YAAY,CA+I5E;AAID,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAW1D"}
1
+ {"version":3,"file":"score.d.ts","sourceRoot":"","sources":["../src/score.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE9D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;IACjD,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,sFAAsF;AACtF,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAwE5D,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CASxD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE5D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,YAAY,CA+I5E;AAID,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAW1D"}
package/dist/score.js CHANGED
@@ -67,10 +67,51 @@ function evidenceLinePositive(text, re, negationRe = NEGATION_RE) {
67
67
  }
68
68
  // Word-bounded on BOTH sides: "upgrade B-tree" fabricated a B- (Codex QE #1). The lookahead also
69
69
  // rejects "Grade B-tree" (letter after the dash) while keeping the real "Grade: A−" formats.
70
- const GRADE_RE = /(?<![A-Za-z])[Gg]rade[d]?:?\s*\*{0,2}\s*([A-F][+−-]?)(?![A-Za-z-])/;
70
+ //
71
+ // CASE: the whole word is case-insensitive, not just its first letter. The previous `[Gg]rade`
72
+ // could never match an all-caps `GRADE A` — MEASURED 2026-08-22: 15 reports spell it that way, and
73
+ // for several of them it is the ONLY grade in the file, so the parser returned `null` about a
74
+ // report that plainly states its verdict (ADR-002, features/dz-recap).
75
+ // The trailing `(?![A-Za-z])` is NOT decoration. Making the word case-insensitive let `GRADED by
76
+ // an independent reviewer` match: the engine took `GRADE`, skipped the optional `d`, and read the
77
+ // word's own final `D` as the grade. The old lowercase-only pattern could never reach that state,
78
+ // so widening the alphabet shifted the threshold — caught by the regression half of the test,
79
+ // which is exactly why that half is mandatory (recalled lesson, Step 0).
80
+ // NOT global. `evidenceLine` calls `re.test(line)` in a loop, and a /g regex carries `lastIndex`
81
+ // between calls — it would skip matches on every other line. `readQeGrade` makes its own global
82
+ // copy instead. (Caught by the existing evidence-locator test when /g was added here.)
83
+ const GRADE_RE = /(?<![A-Za-z])[Gg][Rr][Aa][Dd][Ee][Dd]?(?![A-Za-z]):?\s*\*{0,2}\s*([A-F][+\u2212-]?)(?![A-Za-z-])/;
84
+ /** U+2212 and the ASCII hyphen spell the same grade; a tally must not count them twice. */
85
+ function normaliseGradeSign(grade) {
86
+ return grade.replace('\u2212', '-');
87
+ }
88
+ /**
89
+ * Read the review grade a report states — and refuse to guess when it states more than one.
90
+ *
91
+ * The obvious rules are both WRONG, and both were measured before this was written (ADR-002):
92
+ * FIRST match returns the round-1 grade of a report that was later fixed; LAST match returns a
93
+ * section heading naming the pre-fix grade, or a sentence quoting a grade in prose. Across 154
94
+ * real reports the two disagree in 14 files, and in `crossrt-2-codex-hooks` NEITHER is right —
95
+ * its true verdict is an all-caps `GRADE A` the old regex could not see at all.
96
+ *
97
+ * So: a grade is reported only when every occurrence agrees. Otherwise the caller is told the
98
+ * report is ambiguous, which is a fact about the report, not a missing number.
99
+ */
100
+ export function readQeGrade(qeText) {
101
+ const found = [];
102
+ for (const m of qeText.matchAll(new RegExp(GRADE_RE.source, 'g'))) {
103
+ const g = normaliseGradeSign(m[1]);
104
+ if (!found.includes(g))
105
+ found.push(g);
106
+ }
107
+ if (found.length === 0)
108
+ return { status: 'none', grade: null, found: [] };
109
+ if (found.length === 1)
110
+ return { status: 'unique', grade: found[0], found };
111
+ return { status: 'ambiguous', grade: null, found };
112
+ }
71
113
  export function extractQeGrade(qeText) {
72
- const m = GRADE_RE.exec(qeText);
73
- return m?.[1] ?? null;
114
+ return readQeGrade(qeText).grade;
74
115
  }
75
116
  export function scoreRun(slug, artifacts) {
76
117
  const adrText = collect(artifacts, (p) => p.startsWith('03_adr/'));
package/dist/score.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"score.js","sourceRoot":"","sources":["../src/score.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"score.js","sourceRoot":"","sources":["../src/score.ts"],"names":[],"mappings":"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"}
@@ -80,8 +80,20 @@ export interface ImportVectorRow {
80
80
  readonly metadata?: Record<string, unknown> | undefined;
81
81
  }
82
82
  /** The engine PORT — both adapters implement exactly this surface (04 §4.1). */
83
+ /**
84
+ * Is this engine's `similarity` a real cosine, or only good enough to RANK by?
85
+ *
86
+ * `agentdb` computes a magnitude-normalised cosine over the stored vectors, so its number is
87
+ * comparable and lives in the space the recall floors were calibrated in. The `rvf` adapter returns
88
+ * `-distance` — unbounded, and the metric is not established — so its number may only order rows.
89
+ * Printing it beside a 0.38 cosine floor would hand the reader a figure that looks calibrated and is
90
+ * not; that is the one lie this feature must not tell (ADR, features/recall-true-closeness).
91
+ */
92
+ export type SimilarityKind = 'cosine' | 'rank-only';
83
93
  export interface VectorEngine {
84
94
  readonly kind: VectorEngineKind;
95
+ /** Absent means `rank-only`: an engine must SAY its number is a cosine to have it shown as one. */
96
+ readonly similarityKind?: SimilarityKind;
85
97
  upsert(entries: readonly VectorEntry[]): Promise<{
86
98
  indexed: number;
87
99
  error?: string | undefined;
@@ -134,6 +146,14 @@ export interface HybridHit {
134
146
  readonly score: number;
135
147
  /** lesson-quarantine: set only for a quarantined hit — display marks ⚠q, ranking was damped. */
136
148
  readonly quarantined?: boolean;
149
+ /**
150
+ * Raw closeness from the semantic leg, when the engine reports a genuine cosine. ABSENT for a
151
+ * lexical-only hit and for an engine whose score is not a cosine — the honest display there is a
152
+ * dash, never a substitute number. On a `both` hit this is the SEMANTIC leg's cosine, which
153
+ * explains less of the ordering than it may appear to: the list is ranked by RRF plus learning
154
+ * signals, not by this.
155
+ */
156
+ readonly similarity?: number;
137
157
  }
138
158
  /** Outcome of {@link recallHybrid}. With no engine this is content-identical to `recallPatterns`. */
139
159
  export interface HybridRecall {
@@ -198,6 +218,8 @@ export interface VectorTierStatus {
198
218
  * project print a fully-healthy status line over a dead writer (ADR-001).
199
219
  */
200
220
  readonly mirrorWriterEnabled: boolean;
221
+ /** WHY it is on or off — so the surface printing it cannot invent a cause (see mirrorWriterReason). */
222
+ readonly mirrorWriterState: MirrorWriterState;
201
223
  /**
202
224
  * Vectors of OTHER dz-owned task types (today: `dz-backlog`). Reported separately so a store of N
203
225
  * vectors can be fully accounted for, and never folded into `mirrored`, which must stay comparable
@@ -374,6 +396,31 @@ export declare function readHarmonizeThreshold(projectRoot: string): number;
374
396
  * `false`, so its `dz teach` output stays byte-identical to the pre-feature baseline (AC-1).
375
397
  */
376
398
  export declare function vectorMirrorEnabled(projectRoot: string): boolean;
399
+ /** Why the mirror writer is on or off — a CLOSED set, so a caller cannot invent a cause. */
400
+ export type MirrorWriterState = 'on'
401
+ /** No `.dz/config.json` at all — an unconfigured project, which is the normal quiet case. */
402
+ | 'no-config'
403
+ /** The config exists but could not be read or parsed. */
404
+ | 'config-unreadable'
405
+ /** The config is readable and simply does not enable a mirror. */
406
+ | 'not-enabled'
407
+ /** The config explicitly turns the vector tier off. */
408
+ | 'engine-off';
409
+ /**
410
+ * The mirror writer's state AND its real cause.
411
+ *
412
+ * Every failure used to collapse into `false`, and the one message printed above it named ONE
413
+ * specific cause: "no memory.backend=agentdb". MEASURED 2026-08-24 with a config that sets
414
+ * `memory.vector.engine: "off"` — the status line correctly said OFF and then blamed a setting the
415
+ * config did not mention. A diagnosis that names the wrong cause sends the reader to fix something
416
+ * that is not broken, which is worse than saying nothing.
417
+ */
418
+ export declare function mirrorWriterReason(projectRoot: string): {
419
+ enabled: boolean;
420
+ state: MirrorWriterState;
421
+ };
422
+ /** The sentence a reader can act on, for each state. */
423
+ export declare function mirrorWriterExplanation(state: MirrorWriterState): string;
377
424
  export declare function resolveVectorEngine(projectRoot: string): ResolvedVectorEngine;
378
425
  /** Options shared by the mirror/recall services. `engine: null` force-disables (tests). */
379
426
  export interface VectorServiceOptions {
@@ -410,6 +457,13 @@ export interface RankedPattern {
410
457
  readonly id: string;
411
458
  readonly pattern: PatternRecord;
412
459
  readonly backend: RecallHit['backend'];
460
+ /**
461
+ * The semantic leg's raw closeness, when the engine reports a real cosine. Rides ALONGSIDE the RRF
462
+ * score and never enters the ranking maths — four things depend on RRF magnitude (the reinforce
463
+ * cap, quarantine damping, the learning uplift, and an ADR-level note in backlog.ts), so this is a
464
+ * sibling field, never a repurposing.
465
+ */
466
+ readonly similarity?: number;
413
467
  }
414
468
  /**
415
469
  * Reciprocal Rank Fusion merge: `score(p) = Σ 1/(60 + rank)` over the lists containing `p`