@mmnto/cli 1.105.0 → 1.107.0

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 (43) hide show
  1. package/dist/commands/doctor-qbd.d.ts +40 -0
  2. package/dist/commands/doctor-qbd.d.ts.map +1 -0
  3. package/dist/commands/doctor-qbd.js +156 -0
  4. package/dist/commands/doctor-qbd.js.map +1 -0
  5. package/dist/commands/doctor-qbd.test.d.ts +13 -0
  6. package/dist/commands/doctor-qbd.test.d.ts.map +1 -0
  7. package/dist/commands/doctor-qbd.test.js +548 -0
  8. package/dist/commands/doctor-qbd.test.js.map +1 -0
  9. package/dist/commands/mail-degraded-e4.test.d.ts +43 -0
  10. package/dist/commands/mail-degraded-e4.test.d.ts.map +1 -0
  11. package/dist/commands/mail-degraded-e4.test.js +317 -0
  12. package/dist/commands/mail-degraded-e4.test.js.map +1 -0
  13. package/dist/commands/orient.d.ts.map +1 -1
  14. package/dist/commands/orient.js +23 -0
  15. package/dist/commands/orient.js.map +1 -1
  16. package/dist/commands/qbd-seam.d.ts +77 -0
  17. package/dist/commands/qbd-seam.d.ts.map +1 -0
  18. package/dist/commands/qbd-seam.js +150 -0
  19. package/dist/commands/qbd-seam.js.map +1 -0
  20. package/dist/commands/qbd-seam.test.d.ts +16 -0
  21. package/dist/commands/qbd-seam.test.d.ts.map +1 -0
  22. package/dist/commands/qbd-seam.test.js +339 -0
  23. package/dist/commands/qbd-seam.test.js.map +1 -0
  24. package/dist/commands/review-fan.d.ts.map +1 -1
  25. package/dist/commands/review-fan.js +26 -0
  26. package/dist/commands/review-fan.js.map +1 -1
  27. package/dist/commands/run-compiled-rules.d.ts.map +1 -1
  28. package/dist/commands/run-compiled-rules.js +137 -5
  29. package/dist/commands/run-compiled-rules.js.map +1 -1
  30. package/dist/commands/run-compiled-rules.test.js +359 -1
  31. package/dist/commands/run-compiled-rules.test.js.map +1 -1
  32. package/dist/commands/search.d.ts.map +1 -1
  33. package/dist/commands/search.js +15 -0
  34. package/dist/commands/search.js.map +1 -1
  35. package/dist/commands/shield.d.ts.map +1 -1
  36. package/dist/commands/shield.js +34 -0
  37. package/dist/commands/shield.js.map +1 -1
  38. package/dist/commands/spec.d.ts.map +1 -1
  39. package/dist/commands/spec.js +16 -0
  40. package/dist/commands/spec.js.map +1 -1
  41. package/dist/index.js +8 -1
  42. package/dist/index.js.map +1 -1
  43. package/package.json +2 -2
@@ -0,0 +1,150 @@
1
+ /**
2
+ * The single place the query-before-derive seams resolve their ledger directory
3
+ * (mmnto-ai/totem#2510).
4
+ *
5
+ * ## Why this exists
6
+ *
7
+ * The seams originally each did `path.join(cwd, config.totemDir)`. That is
8
+ * wrong, and silently so. `resolveConfigPath` does NOT walk up the tree — it
9
+ * checks the cwd and then falls back to the global `~/.totem/` profile — so
10
+ * running a derive-class command from a subdirectory of a project resolves a
11
+ * config successfully (the command works) while the seam targets
12
+ * `<subdir>/.totem`, which does not exist. The core writer then skips, and the
13
+ * derive vanishes from the denominator: exactly the #2510 falsifier-1 failure,
14
+ * arrived at by accident instead of by gaming.
15
+ *
16
+ * The fix is to resolve the ledger directory the way this command family's
17
+ * EXISTING ledger writes already do — from the config root, e.g. `shield.ts`'s
18
+ * `path.join(configRoot, config.totemDir)` for `override` events — so QBD rows
19
+ * land in the same ledger as every other event the same command emits.
20
+ *
21
+ * Every seam and the doctor reader route through here, so the resolution can
22
+ * only be wrong in one place, and a fix lands everywhere at once. That
23
+ * writer/reader agreement is the load-bearing property: rows went missing
24
+ * precisely because the two resolved differently.
25
+ *
26
+ * ## Known residual, stated rather than hidden
27
+ *
28
+ * `resolveConfigPath` still does not walk up. Run from a subdirectory of a
29
+ * project that has no config of its own, it resolves the global `~/.totem/`
30
+ * profile, so the row lands in the global profile's ledger rather than the
31
+ * enclosing project's. That is consistent — telemetry follows the same config
32
+ * the command itself ran under, and the reader follows it too — but it is not
33
+ * the same as project-root discovery. Fixing it properly means changing
34
+ * `resolveConfigPath` semantics for EVERY command, which is a repo-wide change
35
+ * well outside this slice. Scoped out deliberately, not overlooked.
36
+ */
37
+ /**
38
+ * Resolve the ledger directory QBD rows belong in, for a given cwd.
39
+ *
40
+ * Returns `undefined` when no Totem config can be resolved at all — there is no
41
+ * project to instrument, which is a normal state for a general-purpose command
42
+ * like `orient` run outside a repo.
43
+ */
44
+ export async function resolveQbdLedgerDir(cwd, homeDir) {
45
+ return (await resolveQbdLedgerDirDetailed(cwd, homeDir)).dir;
46
+ }
47
+ /**
48
+ * As `resolveQbdLedgerDir`, but distinguishes the two reasons resolution can
49
+ * fail so the caller can say which happened.
50
+ *
51
+ * `CONFIG_MISSING` is the honest-absent case — no project here, nothing to
52
+ * instrument, an entirely normal state for a command like `orient`. Any other
53
+ * failure means a config exists but could not be read, which is a degradation
54
+ * worth naming rather than folding into "absent".
55
+ */
56
+ export async function resolveQbdLedgerDirDetailed(cwd, homeDir) {
57
+ try {
58
+ // Lazy, like every sibling command module: a top-level import here is on the
59
+ // CLI's cold-start path for every invocation, including ones that never
60
+ // touch this seam.
61
+ const path = await import('node:path');
62
+ const { isGlobalConfigPath, loadConfig, resolveConfigPath } = await import('../utils.js');
63
+ // `homeDir` is threaded through so tests can point the global-profile lookup
64
+ // at a temp home. Without it, a test running in a directory with no config
65
+ // resolves the DEVELOPER'S REAL `~/.totem/` profile and writes telemetry
66
+ // into their live ledger — which is exactly what happened: this suite wrote
67
+ // real derive rows into the maintainer's global ledger on every run.
68
+ const configPath = resolveConfigPath(cwd, homeDir);
69
+ const config = await loadConfig(configPath);
70
+ const global = isGlobalConfigPath(configPath, homeDir);
71
+ // configRoot, NOT cwd — see the header. Mirrors the sibling ledger writes.
72
+ return { dir: path.join(path.dirname(configPath), config.totemDir), global };
73
+ // totem-context: intentional cleanup — a sensor must not fail the command it instruments (Tenet 13); the reason is returned to the caller and surfaced, never discarded.
74
+ }
75
+ catch (err) {
76
+ // totem-context: intentional cleanup — a sensor must not fail the command it instruments (Tenet 13); the reason is returned to the caller and surfaced, never discarded.
77
+ const code = typeof err === 'object' && err !== null && 'code' in err
78
+ ? err.code
79
+ : undefined;
80
+ if (code === 'CONFIG_MISSING') {
81
+ return { reason: 'no Totem config found — not a project, nothing to instrument' };
82
+ }
83
+ const msg = err instanceof Error ? err.message : String(err);
84
+ return { reason: `Totem config could not be loaded (${msg})` };
85
+ }
86
+ }
87
+ /**
88
+ * Record a derive-class action from a CLI command.
89
+ *
90
+ * Never throws, never fails the instrumented command. Returns a note whenever
91
+ * nothing was recorded, so the caller can surface it — a sensor that quietly
92
+ * declines to measure is indistinguishable from one measuring zero, which is
93
+ * the ADR-115 § 2 defect class.
94
+ */
95
+ /**
96
+ * Landing in the global profile is legitimate but must never be silent: the
97
+ * row goes somewhere other than the project the user is looking at, and a
98
+ * reader comparing `doctor --compliance` in the project against these rows
99
+ * would otherwise see an unexplained gap.
100
+ */
101
+ function globalNote(totemDir) {
102
+ return `query-before-derive: recorded to the global profile ledger at ${totemDir} — no project config found from this cwd`;
103
+ }
104
+ /**
105
+ * The one resolve-then-record body both public seams share.
106
+ *
107
+ * The two used to carry six duplicated statements and three byte-identical note
108
+ * strings. Those strings are load-bearing — the doctor render and the tests
109
+ * match on them — so a reworded note had to be changed in two places or the
110
+ * surfaces silently drifted apart. Single-sourced here.
111
+ *
112
+ * `sense` is the only real difference: which core writer runs.
113
+ */
114
+ async function recordThrough(cwd, homeDir, sense) {
115
+ const { dir: totemDir, reason, global } = await resolveQbdLedgerDirDetailed(cwd, homeDir);
116
+ if (totemDir === undefined) {
117
+ return {
118
+ recorded: false,
119
+ note: `query-before-derive: ${reason ?? 'unresolved'} — not recording`,
120
+ };
121
+ }
122
+ const result = sense(totemDir);
123
+ if (result.skipped === true) {
124
+ return {
125
+ recorded: false,
126
+ note: `query-before-derive: no ledger at ${totemDir} — not recording`,
127
+ };
128
+ }
129
+ return { recorded: result.written, ...(global === true && { note: globalNote(totemDir) }) };
130
+ }
131
+ /**
132
+ * Record a derive-class action from a CLI command.
133
+ *
134
+ * Never throws, never fails the instrumented command. Returns a note whenever
135
+ * nothing was recorded, so the caller can surface it — a sensor that quietly
136
+ * declines to measure is indistinguishable from one measuring zero, which is
137
+ * the ADR-115 § 2 defect class.
138
+ */
139
+ export async function recordQbdDerive(cwd, surface, onWarn, homeDir) {
140
+ const { senseDeriveAction } = await import('@mmnto/totem');
141
+ return recordThrough(cwd, homeDir, (totemDir) => senseDeriveAction({ totemDir, source: 'lint', surface }, onWarn));
142
+ }
143
+ /**
144
+ * Record a corpus query from a CLI command. Same contract as `recordQbdDerive`.
145
+ */
146
+ export async function recordQbdQuery(cwd, onWarn, homeDir) {
147
+ const { senseCorpusQuery } = await import('@mmnto/totem');
148
+ return recordThrough(cwd, homeDir, (totemDir) => senseCorpusQuery({ totemDir, source: 'lint', surface: 'totem_search' }, onWarn));
149
+ }
150
+ //# sourceMappingURL=qbd-seam.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qbd-seam.js","sourceRoot":"","sources":["../../src/commands/qbd-seam.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Seam-resolution tests for the query-before-derive instrumentation
3
+ * (mmnto-ai/totem#2510).
4
+ *
5
+ * ## Test isolation is load-bearing here, not hygiene
6
+ *
7
+ * Every test passes an explicit temp `homeDir`. `resolveConfigPath` falls back
8
+ * to the global `~/.totem/` profile when the cwd has no config, so a test that
9
+ * omits it resolves the DEVELOPER'S REAL profile — and on a machine whose
10
+ * global config sets `totemDir: '.'`, the writer then appends real derive rows
11
+ * to their live `~/.totem/ledger/events.ndjson`. An earlier version of this
12
+ * file did exactly that on every suite run. No test here may be *able* to reach
13
+ * the real profile.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=qbd-seam.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qbd-seam.test.d.ts","sourceRoot":"","sources":["../../src/commands/qbd-seam.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Seam-resolution tests for the query-before-derive instrumentation
3
+ * (mmnto-ai/totem#2510).
4
+ *
5
+ * ## Test isolation is load-bearing here, not hygiene
6
+ *
7
+ * Every test passes an explicit temp `homeDir`. `resolveConfigPath` falls back
8
+ * to the global `~/.totem/` profile when the cwd has no config, so a test that
9
+ * omits it resolves the DEVELOPER'S REAL profile — and on a machine whose
10
+ * global config sets `totemDir: '.'`, the writer then appends real derive rows
11
+ * to their live `~/.totem/ledger/events.ndjson`. An earlier version of this
12
+ * file did exactly that on every suite run. No test here may be *able* to reach
13
+ * the real profile.
14
+ */
15
+ import * as fs from 'node:fs';
16
+ import * as os from 'node:os';
17
+ import * as path from 'node:path';
18
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
19
+ import { cleanTmpDir } from '../test-utils.js';
20
+ import { recordQbdDerive, recordQbdQuery, resolveQbdLedgerDirDetailed } from './qbd-seam.js';
21
+ /** A minimal VALID config — `targets` requires at least one entry. */
22
+ const TOTEM_YAML = [
23
+ 'targets:',
24
+ ' - glob: "src/**/*.ts"',
25
+ ' type: code',
26
+ ' strategy: file',
27
+ '',
28
+ ].join('\n');
29
+ let projectRoot;
30
+ /** A temp home with NO global profile — the "no config anywhere" case. */
31
+ let emptyHome;
32
+ beforeEach(() => {
33
+ projectRoot = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'totem-qbd-seam-')));
34
+ fs.writeFileSync(path.join(projectRoot, 'totem.yaml'), TOTEM_YAML, 'utf-8');
35
+ fs.mkdirSync(path.join(projectRoot, '.totem'), { recursive: true });
36
+ emptyHome = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'totem-qbd-home-')));
37
+ });
38
+ afterEach(() => {
39
+ cleanTmpDir(projectRoot);
40
+ cleanTmpDir(emptyHome);
41
+ });
42
+ /**
43
+ * Build a temp home that DOES carry a global profile.
44
+ *
45
+ * `totemDir: '.'` mirrors the real-world shape (it is what this machine's
46
+ * `~/.totem/totem.config.ts` sets), so the profile's ledger lives at
47
+ * `<home>/.totem/ledger/` — the layout the silent-landing finding was about.
48
+ */
49
+ function homeWithGlobalProfile() {
50
+ const home = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'totem-qbd-ghome-')));
51
+ const globalDir = path.join(home, '.totem');
52
+ fs.mkdirSync(globalDir, { recursive: true });
53
+ fs.writeFileSync(path.join(globalDir, 'totem.yaml'), `totemDir: "."\n${TOTEM_YAML}`, 'utf-8');
54
+ return home;
55
+ }
56
+ /** Where a `homeWithGlobalProfile` home keeps its ledger. */
57
+ function globalTotemDir(home) {
58
+ return path.join(home, '.totem');
59
+ }
60
+ function ledgerRows(totemDir) {
61
+ const file = path.join(totemDir, 'ledger', 'events.ndjson');
62
+ if (!fs.existsSync(file))
63
+ return [];
64
+ return fs
65
+ .readFileSync(file, 'utf-8')
66
+ .split('\n')
67
+ .filter((l) => l.trim().length > 0)
68
+ .map((l) => JSON.parse(l));
69
+ }
70
+ describe('resolveQbdLedgerDirDetailed', () => {
71
+ it('resolves from the config root', async () => {
72
+ const detailed = await resolveQbdLedgerDirDetailed(projectRoot, emptyHome);
73
+ expect(detailed.reason ?? 'resolved').toBe('resolved');
74
+ expect(detailed.dir).toBe(path.join(projectRoot, '.totem'));
75
+ expect(detailed.global).toBe(false);
76
+ });
77
+ it('resolves a cwd that is NOT the config root to the CONFIG ROOT ledger', async () => {
78
+ // The discriminating case. From a subdirectory with a global profile in
79
+ // play, the old `path.join(cwd, config.totemDir)` would answer
80
+ // `<subdir>/.totem`; the correct answer is the resolved config's own root.
81
+ // At the project root the two agree, which is why a root-only assertion
82
+ // proves nothing about the bug it is supposed to pin.
83
+ const home = homeWithGlobalProfile();
84
+ try {
85
+ const subdir = path.join(projectRoot, 'packages', 'thing');
86
+ fs.mkdirSync(subdir, { recursive: true });
87
+ const detailed = await resolveQbdLedgerDirDetailed(subdir, home);
88
+ // What the old cwd-joined logic would have answered, computed from the
89
+ // SAME `totemDir` this fixture's profile sets (`.`) — so it is `subdir`
90
+ // itself, not `subdir/.totem`. Hard-coding `.totem` here made the
91
+ // assertion pass under both implementations, i.e. pinned nothing.
92
+ const oldBuggyAnswer = path.join(subdir, '.');
93
+ expect(detailed.dir).toBeDefined();
94
+ expect(detailed.dir).not.toBe(oldBuggyAnswer);
95
+ expect(detailed.dir).toBe(globalTotemDir(home));
96
+ expect(detailed.global).toBe(true);
97
+ }
98
+ finally {
99
+ cleanTmpDir(home);
100
+ }
101
+ });
102
+ it('gives two different cwds under one config root the SAME ledger dir', async () => {
103
+ const home = homeWithGlobalProfile();
104
+ try {
105
+ const a = path.join(projectRoot, 'packages', 'alpha');
106
+ const b = path.join(projectRoot, 'docs', 'deep', 'nested');
107
+ fs.mkdirSync(a, { recursive: true });
108
+ fs.mkdirSync(b, { recursive: true });
109
+ const fromA = await resolveQbdLedgerDirDetailed(a, home);
110
+ const fromB = await resolveQbdLedgerDirDetailed(b, home);
111
+ // Resolution is a function of the resolved config root, so two cwds that
112
+ // resolve the same config cannot disagree about where rows land. Under
113
+ // the old cwd-joined logic these two answers differed.
114
+ expect(fromA.dir).toBe(fromB.dir);
115
+ expect(fromA.dir).not.toBe(path.join(a, '.totem'));
116
+ expect(fromB.dir).not.toBe(path.join(b, '.totem'));
117
+ }
118
+ finally {
119
+ cleanTmpDir(home);
120
+ }
121
+ });
122
+ it('reports CONFIG_MISSING when neither cwd nor home carries a config', async () => {
123
+ const orphan = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'totem-qbd-orphan-')));
124
+ try {
125
+ const detailed = await resolveQbdLedgerDirDetailed(orphan, emptyHome);
126
+ expect(detailed.dir).toBeUndefined();
127
+ expect(detailed.reason).toContain('no Totem config found');
128
+ }
129
+ finally {
130
+ cleanTmpDir(orphan);
131
+ }
132
+ });
133
+ });
134
+ describe('recordQbdDerive', () => {
135
+ it('records into the project ledger when run from the project root', async () => {
136
+ const report = await recordQbdDerive(projectRoot, 'review', () => { }, emptyHome);
137
+ expect(report.recorded).toBe(true);
138
+ expect(report.note).toBeUndefined();
139
+ const rows = ledgerRows(path.join(projectRoot, '.totem'));
140
+ expect(rows).toHaveLength(1);
141
+ expect(rows[0].type).toBe('derive_action');
142
+ expect(rows[0].activity_name).toBe('review');
143
+ });
144
+ it('never creates a stray ledger under a subdirectory', async () => {
145
+ const subdir = path.join(projectRoot, 'packages', 'thing');
146
+ fs.mkdirSync(subdir, { recursive: true });
147
+ const report = await recordQbdDerive(subdir, 'spec', () => { }, emptyHome);
148
+ expect(fs.existsSync(path.join(subdir, '.totem'))).toBe(false);
149
+ if (!report.recorded)
150
+ expect(report.note).toBeDefined();
151
+ });
152
+ it('ANNOUNCES a landing in the global profile instead of doing it silently', async () => {
153
+ // Legitimate, but the row goes somewhere other than the project the user is
154
+ // looking at — so it must say so. This was the silent half of the finding.
155
+ const home = homeWithGlobalProfile();
156
+ const orphan = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'totem-qbd-orphan-')));
157
+ try {
158
+ const report = await recordQbdDerive(orphan, 'orient', () => { }, home);
159
+ expect(report.recorded).toBe(true);
160
+ expect(report.note).toBeDefined();
161
+ expect(report.note).toContain('global profile ledger');
162
+ // And it landed in the global profile's ledger, not the orphan cwd.
163
+ expect(ledgerRows(globalTotemDir(home))).toHaveLength(1);
164
+ expect(fs.existsSync(path.join(orphan, '.totem'))).toBe(false);
165
+ }
166
+ finally {
167
+ cleanTmpDir(orphan);
168
+ cleanTmpDir(home);
169
+ }
170
+ });
171
+ it('never no-ops silently when there is no project at all', async () => {
172
+ const orphan = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'totem-qbd-orphan-')));
173
+ try {
174
+ const report = await recordQbdDerive(orphan, 'orient', () => { }, emptyHome);
175
+ expect(report.recorded).toBe(false);
176
+ expect(report.note).toContain('query-before-derive');
177
+ }
178
+ finally {
179
+ cleanTmpDir(orphan);
180
+ }
181
+ });
182
+ });
183
+ describe('recordQbdQuery', () => {
184
+ it('writes a corpus_query row carrying a correlation ID into the project ledger', async () => {
185
+ const report = await recordQbdQuery(projectRoot, () => { }, emptyHome);
186
+ expect(report.recorded).toBe(true);
187
+ const rows = ledgerRows(path.join(projectRoot, '.totem'));
188
+ expect(rows).toHaveLength(1);
189
+ expect(rows[0].type).toBe('corpus_query');
190
+ expect(rows[0].activity_name).toBe('totem_search');
191
+ expect(typeof rows[0].qbd_correlation_id).toBe('string');
192
+ });
193
+ it('shares the derive seam’s not-recording contract', async () => {
194
+ // Both seams route through one internal body, so the note strings cannot
195
+ // drift apart — this pins that they really are the same contract.
196
+ const orphan = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'totem-qbd-orphan-')));
197
+ try {
198
+ const queryReport = await recordQbdQuery(orphan, () => { }, emptyHome);
199
+ const deriveReport = await recordQbdDerive(orphan, 'orient', () => { }, emptyHome);
200
+ expect(queryReport.recorded).toBe(false);
201
+ expect(queryReport.note).toBe(deriveReport.note);
202
+ }
203
+ finally {
204
+ cleanTmpDir(orphan);
205
+ }
206
+ });
207
+ });
208
+ describe('review seam placement', () => {
209
+ /**
210
+ * Source pin, and an honest account of why it is one.
211
+ *
212
+ * `handleVerdictResult` is module-private and `shieldCommand` needs the
213
+ * orchestrator, the Lance index, git, and the exemption store before it
214
+ * reaches a verdict, so driving the structural branch executably is not
215
+ * feasible at unit scope. The previous version of this test was worse than
216
+ * useless: it indexed the IMPORT of `recordQbdDerive` rather than the call,
217
+ * never read the enclosing control flow, and would have passed after a
218
+ * comment edit.
219
+ *
220
+ * This one anchors to the CALL EXPRESSION inside the enclosing function body.
221
+ * Mutations it catches: moving the record call out of `handleVerdictResult`
222
+ * (structural and standard would both stop recording); deleting the fan's own
223
+ * call (the fan path would stop recording); the structural branch no longer
224
+ * routing through the shared handler before it returns.
225
+ *
226
+ * Mutations it does NOT catch, stated so the pin is not read as stronger than
227
+ * it is: reordering within the handler; a call that is present but
228
+ * unreachable; and — because these are substring matches, not parsed
229
+ * statements — a *comment* mentioning `recordQbdDerive(` would satisfy them
230
+ * just as well as the real call. Accepted, because the alternative at unit
231
+ * scope is no coverage at all, and building an AST harness for one call site
232
+ * is machinery this slice does not need.
233
+ */
234
+ const source = fs.readFileSync(path.join(__dirname, 'shield.ts'), 'utf-8');
235
+ /** Slice out one top-level function body by declaration name. */
236
+ function functionBody(name) {
237
+ const start = source.indexOf(`async function ${name}(`);
238
+ expect(start, `${name} should exist`).toBeGreaterThan(-1);
239
+ const rest = source.slice(start + 1);
240
+ const end = rest.search(/\n(?:export )?(?:async )?function /);
241
+ return end === -1 ? rest : rest.slice(0, end);
242
+ }
243
+ it('records the derive INSIDE the shared verdict handler', () => {
244
+ // Structural and standard both route through this function, so a call here
245
+ // fires exactly once per review and only after a verdict exists.
246
+ const body = functionBody('handleVerdictResult');
247
+ expect(body).toContain('recordQbdDerive(');
248
+ });
249
+ it('records only AFTER a verdict has parsed — never for --raw or unparsable', () => {
250
+ // The recording used to be the handler's first statement, which put it
251
+ // ahead of BOTH `if (options.raw) return` and the unparsable-verdict throw:
252
+ // a raw context dump recorded a derive (and could consume a query's
253
+ // grounding), and so did a run whose verdict never parsed.
254
+ //
255
+ // The invariant is positional, so pin it positionally: the record call must
256
+ // sit after the raw exit AND after the point where a verdict is parsed.
257
+ const body = functionBody('handleVerdictResult');
258
+ const rawExitIdx = body.indexOf('if (options.raw) return;');
259
+ const laneDeriveIdx = body.indexOf('deriveLaneOutcome(');
260
+ const structuralBranchIdx = body.indexOf('if (outcome.structuredVerdict)');
261
+ const v1BranchIdx = body.indexOf('const verdict = parseVerdict(content);');
262
+ const firstRecordIdx = body.indexOf('await recordReviewDerive()');
263
+ expect(rawExitIdx).toBeGreaterThan(-1);
264
+ expect(laneDeriveIdx).toBeGreaterThan(-1);
265
+ expect(firstRecordIdx).toBeGreaterThan(-1);
266
+ // After the raw exit: `--raw` returns before any record can fire.
267
+ expect(firstRecordIdx).toBeGreaterThan(rawExitIdx);
268
+ // After the verdict is derived: nothing records before parsing is attempted.
269
+ expect(firstRecordIdx).toBeGreaterThan(laneDeriveIdx);
270
+ // And the call sites are the two PARSED-verdict branches, not the body.
271
+ expect(firstRecordIdx).toBeGreaterThan(structuralBranchIdx);
272
+ expect(body.indexOf('await recordReviewDerive()', v1BranchIdx)).toBeGreaterThan(v1BranchIdx);
273
+ });
274
+ it('records on a FAIL verdict too — a failing review is a completed derive', () => {
275
+ // Excluding FAIL would shrink the denominator, which is the falsifier-1
276
+ // failure mode. The record sits at the TOP of the structured branch, ahead
277
+ // of the pass/fail split and ahead of the SHIELD_FAILED throw.
278
+ const body = functionBody('handleVerdictResult');
279
+ const recordIdx = body.indexOf('await recordReviewDerive()');
280
+ const failThrowIdx = body.indexOf("'SHIELD_FAILED'");
281
+ expect(failThrowIdx).toBeGreaterThan(-1);
282
+ expect(recordIdx).toBeLessThan(failThrowIdx);
283
+ });
284
+ it('routes the structural branch through that shared handler before returning', () => {
285
+ const body = functionBody('shieldCommand');
286
+ const structuralIdx = body.indexOf("options.mode === 'structural'");
287
+ expect(structuralIdx).toBeGreaterThan(-1);
288
+ const afterStructural = body.slice(structuralIdx);
289
+ const handlerIdx = afterStructural.indexOf('handleVerdictResult(');
290
+ const returnIdx = afterStructural.indexOf('\n return;');
291
+ expect(handlerIdx).toBeGreaterThan(-1);
292
+ expect(returnIdx).toBeGreaterThan(-1);
293
+ expect(handlerIdx).toBeLessThan(returnIdx);
294
+ });
295
+ it('does NOT record the fan derive at the runReviewFan call site', () => {
296
+ // The call site is unreachable for the two exit-policy paths: a
297
+ // zero-completed-lane round and a `--fail-on` failure both PERSIST an honest
298
+ // verdict and only then throw, so a record placed after the call skipped
299
+ // exactly those reviews — completed derives escaping the denominator, with
300
+ // the query correlation left consumable by a later derive.
301
+ const body = functionBody('shieldCommand');
302
+ const fanIdx = body.indexOf('runReviewFan(');
303
+ expect(fanIdx).toBeGreaterThan(-1);
304
+ // Between the fan call and the branch's `return`, nothing records.
305
+ const afterFan = body.slice(fanIdx);
306
+ const returnIdx = afterFan.indexOf('\n return;');
307
+ expect(returnIdx).toBeGreaterThan(-1);
308
+ expect(afterFan.slice(0, returnIdx)).not.toContain('await recordQbdDerive(');
309
+ });
310
+ it('writes the fan derive to the SAME totemDir the artifact was saved into', () => {
311
+ // Not re-resolved from cwd: a cwd with no local config falls back to the
312
+ // user's global `~/.totem/` profile, which appended real rows to the
313
+ // maintainer's live ledger during this package's tests. The artifact's own
314
+ // directory is both authoritative and incapable of wandering.
315
+ expect(fanSource).toContain('senseDeriveAction({ totemDir: ctx.totemDirAbs');
316
+ });
317
+ const fanSource = fs.readFileSync(path.join(__dirname, 'review-fan.ts'), 'utf-8');
318
+ it('records the fan derive the instant the verdict artifact is PERSISTED', () => {
319
+ // Persisted verdict ⇔ recorded derive. Ordering is the invariant, so it is
320
+ // pinned by ordering: the record must sit after the save and before both
321
+ // exit-policy throws.
322
+ const saveIdx = fanSource.indexOf('saveVerdictArtifact(ctx.totemDirAbs, verdict)');
323
+ const recordIdx = fanSource.indexOf('senseDeriveAction({ totemDir: ctx.totemDirAbs');
324
+ const zeroLaneThrowIdx = fanSource.indexOf('hasNoCompletedLane(verdict.lanes)');
325
+ const failOnIdx = fanSource.indexOf('const failOn = ctx.options.failOn;');
326
+ expect(saveIdx).toBeGreaterThan(-1);
327
+ expect(recordIdx).toBeGreaterThan(-1);
328
+ expect(zeroLaneThrowIdx).toBeGreaterThan(-1);
329
+ expect(failOnIdx).toBeGreaterThan(-1);
330
+ // After persistence: a fan that throws BEFORE writing an artifact records
331
+ // nothing, which keeps the other half of the invariant true.
332
+ expect(recordIdx).toBeGreaterThan(saveIdx);
333
+ // Before both exit-policy throws: a persisted-then-policy-throw round is a
334
+ // completed derive and still records.
335
+ expect(recordIdx).toBeLessThan(zeroLaneThrowIdx);
336
+ expect(recordIdx).toBeLessThan(failOnIdx);
337
+ });
338
+ });
339
+ //# sourceMappingURL=qbd-seam.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qbd-seam.test.js","sourceRoot":"","sources":["../../src/commands/qbd-seam.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAE7F,sEAAsE;AACtE,MAAM,UAAU,GAAG;IACjB,UAAU;IACV,yBAAyB;IACzB,gBAAgB;IAChB,oBAAoB;IACpB,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,IAAI,WAAmB,CAAC;AACxB,0EAA0E;AAC1E,IAAI,SAAiB,CAAC;AAEtB,UAAU,CAAC,GAAG,EAAE;IACd,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IACzF,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC5E,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpE,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;AACzF,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,WAAW,CAAC,WAAW,CAAC,CAAC;IACzB,WAAW,CAAC,SAAS,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,SAAS,qBAAqB;IAC5B,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;IACzF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,kBAAkB,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC;IAC9F,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6DAA6D;AAC7D,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC5D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,OAAO,EAAE;SACN,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC;SAC3B,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;SAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAA4B,CAAC,CAAC;AAC1D,CAAC;AAED,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,QAAQ,GAAG,MAAM,2BAA2B,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAC3E,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC5D,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACpF,wEAAwE;QACxE,+DAA+D;QAC/D,2EAA2E;QAC3E,wEAAwE;QACxE,sDAAsD;QACtD,MAAM,IAAI,GAAG,qBAAqB,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;YAC3D,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAE1C,MAAM,QAAQ,GAAG,MAAM,2BAA2B,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACjE,uEAAuE;YACvE,wEAAwE;YACxE,kEAAkE;YAClE,kEAAkE;YAClE,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9C,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YACnC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC9C,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;YAChD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,IAAI,GAAG,qBAAqB,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;YAC3D,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACrC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAErC,MAAM,KAAK,GAAG,MAAM,2BAA2B,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YACzD,MAAM,KAAK,GAAG,MAAM,2BAA2B,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YAEzD,yEAAyE;YACzE,uEAAuE;YACvE,uDAAuD;YACvD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;YACnD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QACrD,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC;QAC5F,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,2BAA2B,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YACtE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC;YACrC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC7D,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,WAAW,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QACjF,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;QAEpC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QAC3D,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAE1E,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,CAAC,QAAQ;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,4EAA4E;QAC5E,2EAA2E;QAC3E,MAAM,IAAI,GAAG,qBAAqB,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC;QAC5F,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,IAAI,CAAC,CAAC;YACvE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;YACvD,oEAAoE;YACpE,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACzD,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjE,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,MAAM,CAAC,CAAC;YACpB,WAAW,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC;QAC5F,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,SAAS,CAAC,CAAC;YAC5E,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QACvD,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,WAAW,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QACtE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEnC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,CAAE,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,yEAAyE;QACzE,kEAAkE;QAClE,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC;QAC5F,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,SAAS,CAAC,CAAC;YACtE,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,SAAS,CAAC,CAAC;YAClF,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;IAE3E,iEAAiE;IACjE,SAAS,YAAY,CAAC,IAAY;QAChC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,kBAAkB,IAAI,GAAG,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,eAAe,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,oCAAoC,CAAC,CAAC;QAC9D,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAChD,CAAC;IAED,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,2EAA2E;QAC3E,iEAAiE;QACjE,MAAM,IAAI,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;QACjD,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,uEAAuE;QACvE,4EAA4E;QAC5E,oEAAoE;QACpE,2DAA2D;QAC3D,EAAE;QACF,4EAA4E;QAC5E,wEAAwE;QACxE,MAAM,IAAI,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;QAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACzD,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;QAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;QAC3E,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAElE,MAAM,CAAC,UAAU,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,aAAa,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,cAAc,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAE3C,kEAAkE;QAClE,MAAM,CAAC,cAAc,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACnD,6EAA6E;QAC7E,MAAM,CAAC,cAAc,CAAC,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;QACtD,wEAAwE;QACxE,MAAM,CAAC,cAAc,CAAC,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC;QAC5D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,4BAA4B,EAAE,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;IAC/F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,wEAAwE;QACxE,2EAA2E;QAC3E,+DAA+D;QAC/D,MAAM,IAAI,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAC7D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACrD,MAAM,CAAC,YAAY,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,MAAM,IAAI,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;QAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC;QACpE,MAAM,CAAC,aAAa,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAE1C,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAClD,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;QACnE,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC3D,MAAM,CAAC,UAAU,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,gEAAgE;QAChE,6EAA6E;QAC7E,yEAAyE;QACzE,2EAA2E;QAC3E,2DAA2D;QAC3D,MAAM,IAAI,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,mEAAmE;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACpD,MAAM,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,yEAAyE;QACzE,qEAAqE;QACrE,2EAA2E;QAC3E,8DAA8D;QAC9D,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,+CAA+C,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,OAAO,CAAC,CAAC;IAElF,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,2EAA2E;QAC3E,yEAAyE;QACzE,sBAAsB;QACtB,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC;QACnF,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC;QACrF,MAAM,gBAAgB,GAAG,SAAS,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;QAChF,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC;QAE1E,MAAM,CAAC,OAAO,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,gBAAgB,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAEtC,0EAA0E;QAC1E,6DAA6D;QAC7D,MAAM,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAC3C,2EAA2E;QAC3E,sCAAsC;QACtC,MAAM,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QACjD,MAAM,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"review-fan.d.ts","sourceRoot":"","sources":["../../src/commands/review-fan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"review-fan.d.ts","sourceRoot":"","sources":["../../src/commands/review-fan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH,OAAO,KAAK,EACV,eAAe,EAEf,gBAAgB,EAEhB,yBAAyB,EAEzB,aAAa,EACb,WAAW,EACX,WAAW,EAEX,eAAe,EACf,gBAAgB,EAChB,WAAW,EAGX,YAAY,EACb,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAYzE,OAAO,EAA+B,KAAK,aAAa,EAAO,MAAM,uBAAuB,CAAC;AAE7F;;;GAGG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAIrC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACpC,YAAY,EAAE,MAAM,GAAG,SAAS,EAMhC,gBAAgB,EAAE,qBAAqB,GACtC,MAAM,EAAE,CA2CV;AAKD,yGAAyG;AACzG,KAAK,qBAAqB,GAAG,cAAc,cAAc,EAAE,gBAAgB,CAAC;AAE5E;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE;IACP,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,EAGD,gBAAgB,EAAE,qBAAqB,GACtC,IAAI,CAYN;AA4ED;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,EAAE,aAcxC,CAAC;AAiBF;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,kFAAkF;IAClF,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,yEAAyE;IACzE,WAAW,EAAE,WAAW,GAAG,SAAS,CAAC;CACtC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;AAElG,yFAAyF;AACzF,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,IAAI,EAAE,WAAW,CAAC;IAClB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,+FAA+F;IAC/F,gBAAgB,EAAE,aAAa,EAAE,CAAC;CACnC;AAcD;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAC3B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,eAAe,EACvB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,aAAa,CAAC,CAqExB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,aAAa,CAAC,CAmBxB;AA0FD,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,gBAAgB,GAAG,QAAQ,GAAG,aAAa,GAAG,gBAAgB,CAAC;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAgBtF;AAED,gFAAgF;AAChF,MAAM,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,CAAC;AAE1D,gDAAgD;AAChD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,iBAAiB,CAAC,CA0C5B;AA2DD,6CAA6C;AAC7C,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGlE;AAID,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,YAAY,CAAC;IACpB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,GAAG,SAAS,GAChC,OAAO,CAAC,eAAe,CAAC,CA+C1B;AAID,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,UAAU,EAAE,yBAAyB,EAAE,CAAC;IACxC,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iFAAiF;IACjF,SAAS,CAAC,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;CAC1C;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,SAAS,aAAa,EAAE,EACrC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC,CAsCzB;AAeD,yEAAyE;AACzE,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;IACtC,cAAc,EAAE,cAAc,CAAC;IAC/B,KAAK,EAAE,YAAY,CAAC;IACpB,oFAAoF;IACpF,aAAa,EAAE,SAAS,GAAG,SAAS,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,qBAAqB,EAI7B,aAAa,EAAE,CAAC,cAAc,cAAc,CAAC,CAAC,CAAC,eAAe,CAAC,EAC/D,+BAA+B,EAAE,CAAC,cAAc,cAAc,CAAC,CAAC,CAAC,iCAAiC,CAAC,GAClG,eAAe,CAmCjB;AAkCD,4EAA4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,YAAY,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,OAAO,EAAE;QACP,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;KAC9B,CAAC;IACF,sFAAsF;IACtF,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,eAAe,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,+EAA+E;IAC/E,MAAM,EAAE,eAAe,CAAC;IACxB,mFAAmF;IACnF,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,gFAAgF;IAChF,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC5C;AAwKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwUvE;AAID,0FAA0F;AAC1F,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B7E"}
@@ -984,6 +984,32 @@ export async function runReviewFan(ctx) {
984
984
  // The saved hash IS the content address (dedup-safe: an identical round returns
985
985
  // the existing address).
986
986
  const verdictHash = saveVerdictArtifact(ctx.totemDirAbs, verdict).hash;
987
+ // Query-before-derive instrumentation (mmnto-ai/totem#2510): the fan's derive
988
+ // is recorded HERE — the instant the verdict artifact is on disk — and not at
989
+ // the `runReviewFan` call site in `shield.ts`.
990
+ //
991
+ // The call site is unreachable for the two exit-policy paths below: a
992
+ // zero-completed-lane round and a `--fail-on` failure both PERSIST an honest
993
+ // verdict (including `settled=false` states, which `totem review --covariate`
994
+ // reads back) and only then throw. Recording after the call therefore skipped
995
+ // exactly those reviews — a completed derive escaping the denominator, and
996
+ // worse, leaving the query's correlation still consumable by a later derive.
997
+ //
998
+ // Placement keeps the other half true by construction: a fan that throws
999
+ // BEFORE reaching this line — a lane-assembly or invocation failure, with no
1000
+ // artifact written — records nothing. Persisted verdict ⇔ recorded derive.
1001
+ //
1002
+ // Writes to `ctx.totemDirAbs` — the very directory the artifact above was
1003
+ // saved into — rather than re-resolving from `ctx.cwd` through the seam
1004
+ // helper. Two reasons, one correctness and one safety: the derive row belongs
1005
+ // in the same ledger as the verdict it accompanies, and re-resolving from a
1006
+ // cwd with no local config would fall back to the user's global `~/.totem/`
1007
+ // profile. Routing through the helper here did exactly that, appending real
1008
+ // rows to the maintainer's live ledger during this package's tests.
1009
+ {
1010
+ const { senseDeriveAction } = await import('@mmnto/totem');
1011
+ senseDeriveAction({ totemDir: ctx.totemDirAbs, source: 'lint', surface: 'review' }, (msg) => log.warn(DISPLAY_TAG, msg));
1012
+ }
987
1013
  // ── ZERO completed verdict lanes (Gate G3, mmnto-ai/totem#2452): the honest verdict
988
1014
  // is now WRITTEN — hard-error ──
989
1015
  // Keyed on `hasNoCompletedLane` (⇔ `verdict.completedLaneCount === 0`, superRefine-bound):