akm-cli 0.9.17 → 0.9.19-alpha.1
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/CHANGELOG.md +157 -0
- package/STABILITY.md +2 -1
- package/dist/assets/hints/cli-hints-full.md +4 -2
- package/dist/assets/hints/cli-hints-short.md +5 -3
- package/dist/assets/prompts/reflect-feedback-framing.md +1 -1
- package/dist/commands/feedback-cli.js +1 -1
- package/dist/commands/health/checks.js +6 -6
- package/dist/commands/health.js +3 -3
- package/dist/commands/improve/consolidate/coverage.js +132 -0
- package/dist/commands/improve/consolidate/pair-pass.js +31 -21
- package/dist/commands/improve/consolidate.js +46 -13
- package/dist/commands/improve/distill.js +8 -4
- package/dist/commands/improve/eligibility.js +39 -9
- package/dist/commands/improve/improve-cli.js +9 -6
- package/dist/commands/improve/improve.js +13 -4
- package/dist/commands/improve/ledger.js +2 -2
- package/dist/commands/improve/loop-stages.js +2 -0
- package/dist/commands/improve/preparation.js +3 -1
- package/dist/commands/improve/reflect.js +2 -2
- package/dist/commands/improve/stage.js +43 -12
- package/dist/commands/proposal/diff-format.js +21 -0
- package/dist/commands/proposal/proposal-cli.js +48 -10
- package/dist/commands/proposal/proposal-types.js +11 -0
- package/dist/commands/proposal/proposal.js +60 -5
- package/dist/commands/proposal/repository.js +250 -18
- package/dist/commands/read/knowledge.js +13 -11
- package/dist/commands/read/remember-cli.js +7 -3
- package/dist/commands/sources/source-clone.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +1 -1
- package/dist/commands/tasks/tasks.js +10 -3
- package/dist/core/mutation-target.js +8 -3
- package/dist/core/write-source.js +3 -2
- package/dist/indexer/usage/usage-events.js +2 -1
- package/dist/output/shapes/helpers.js +7 -0
- package/dist/output/shapes/passthrough.js +1 -0
- package/dist/output/shapes/proposal/reopen.js +14 -0
- package/dist/output/shapes.js +2 -0
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/proposal/proposal.js +3 -1
- package/dist/output/text/proposal-format.js +87 -32
- package/dist/scripts/akm-migrate-node.js +102 -25
- package/dist/scripts/akm-migrate.js +102 -25
- package/dist/storage/repositories/improve-ledger-repository.js +65 -6
- package/dist/storage/repositories/index-vec-repository.js +13 -8
- package/dist/storage/repositories/proposals-repository.js +23 -0
- package/dist/storage/sqlite-read-snapshot.js +46 -2
- package/dist/storage/state-db-integrity.js +12 -9
- package/dist/tasks/run/load-task.js +5 -1
- package/docs/migration/README.md +1 -0
- package/docs/migration/release-notes/0.9.19.md +134 -0
- package/docs/migration/release-notes/README.md +5 -0
- package/docs/migration/v0.7-to-v0.8.md +2 -2
- package/docs/migration/v0.8-to-v0.9.md +5 -1
- package/docs/reference/cli.md +189 -28
- package/docs/reference/configuration.md +9 -8
- package/docs/reference/data-and-telemetry.md +24 -16
- package/package.json +1 -1
|
@@ -28540,6 +28540,7 @@ function shapeProposalEntry(entry, detail) {
|
|
|
28540
28540
|
"confidence",
|
|
28541
28541
|
"gateDecision",
|
|
28542
28542
|
"review",
|
|
28543
|
+
"reviewHistory",
|
|
28543
28544
|
"retirement"
|
|
28544
28545
|
]);
|
|
28545
28546
|
}
|
|
@@ -28555,6 +28556,7 @@ function shapeProposalEntry(entry, detail) {
|
|
|
28555
28556
|
"gateDecision",
|
|
28556
28557
|
"payload",
|
|
28557
28558
|
"review",
|
|
28559
|
+
"reviewHistory",
|
|
28558
28560
|
"retirement",
|
|
28559
28561
|
"retiredArchive",
|
|
28560
28562
|
"promotionSource",
|
|
@@ -28619,7 +28621,10 @@ function shapeProposalDiffOutput(result, detail) {
|
|
|
28619
28621
|
ref: result.ref,
|
|
28620
28622
|
isNew: result.isNew,
|
|
28621
28623
|
unified: result.unified,
|
|
28622
|
-
...result.targetPath !== undefined ? { targetPath: result.targetPath } : {}
|
|
28624
|
+
...result.targetPath !== undefined ? { targetPath: result.targetPath } : {},
|
|
28625
|
+
...result.op !== undefined ? { op: result.op } : {},
|
|
28626
|
+
...result.retirement !== undefined ? { retirement: result.retirement } : {},
|
|
28627
|
+
...result.note !== undefined ? { note: result.note } : {}
|
|
28623
28628
|
};
|
|
28624
28629
|
if (detail === "full") {
|
|
28625
28630
|
return { schemaVersion: result.schemaVersion, ...base };
|
|
@@ -29041,6 +29046,7 @@ var PASSTHROUGH_COMMANDS = [
|
|
|
29041
29046
|
"proposal-accept-batch",
|
|
29042
29047
|
"proposal-drain",
|
|
29043
29048
|
"proposal-reject-batch",
|
|
29049
|
+
"proposal-reopen-batch",
|
|
29044
29050
|
"proposal-revert",
|
|
29045
29051
|
"registry-add",
|
|
29046
29052
|
"registry-list",
|
|
@@ -29112,6 +29118,14 @@ var proposalRejectShapes = [
|
|
|
29112
29118
|
}
|
|
29113
29119
|
];
|
|
29114
29120
|
|
|
29121
|
+
// src/output/shapes/proposal/reopen.ts
|
|
29122
|
+
var proposalReopenShapes = [
|
|
29123
|
+
{
|
|
29124
|
+
command: "proposal-reopen",
|
|
29125
|
+
handler: (result, detail) => shapeProposalRejectOutput(result, detail)
|
|
29126
|
+
}
|
|
29127
|
+
];
|
|
29128
|
+
|
|
29115
29129
|
// src/output/shapes/proposal/show.ts
|
|
29116
29130
|
var proposalShowShapes = [
|
|
29117
29131
|
{
|
|
@@ -29202,6 +29216,7 @@ var BUILT_IN_OUTPUT_SHAPES = [
|
|
|
29202
29216
|
...proposalShowShapes,
|
|
29203
29217
|
...proposalAcceptShapes,
|
|
29204
29218
|
...proposalRejectShapes,
|
|
29219
|
+
...proposalReopenShapes,
|
|
29205
29220
|
...proposalDiffShapes,
|
|
29206
29221
|
...proposalProducerShapes,
|
|
29207
29222
|
...envListShapes,
|
|
@@ -30423,6 +30438,31 @@ Generate one with \`akm improve <ref>\` or \`akm proposal new <type> <name> --ta
|
|
|
30423
30438
|
return lines.join(`
|
|
30424
30439
|
`).trimEnd();
|
|
30425
30440
|
}
|
|
30441
|
+
function retireVerdictLines(retirement) {
|
|
30442
|
+
const lines = [
|
|
30443
|
+
`retire.label: ${String(retirement.judgeLabel)} (cosine=${String(retirement.cosine)})`,
|
|
30444
|
+
`retire.reason: ${String(retirement.judgeReason)}`
|
|
30445
|
+
];
|
|
30446
|
+
const continuityRisk = retirement.continuityRisk;
|
|
30447
|
+
if (continuityRisk) {
|
|
30448
|
+
const failingQueries = typeof continuityRisk.failingQueries === "number" ? continuityRisk.failingQueries : 0;
|
|
30449
|
+
const unverifiedQueries = typeof continuityRisk.unverifiedQueries === "number" ? continuityRisk.unverifiedQueries : 0;
|
|
30450
|
+
const summary = [];
|
|
30451
|
+
if (failingQueries > 0) {
|
|
30452
|
+
summary.push(`${failingQueries} of the retired asset's own quer${failingQueries === 1 ? "y" : "ies"} would not have found the successor top 10`);
|
|
30453
|
+
}
|
|
30454
|
+
if (unverifiedQueries > 0) {
|
|
30455
|
+
summary.push(`${unverifiedQueries} quer${unverifiedQueries === 1 ? "y" : "ies"} unverified (search failed or used the keyword-only fallback)`);
|
|
30456
|
+
}
|
|
30457
|
+
lines.push(`retire.continuityRisk: ${summary.join("; ")} — excluded from bulk accept`);
|
|
30458
|
+
const ranks = Array.isArray(continuityRisk.ranks) ? continuityRisk.ranks : [];
|
|
30459
|
+
for (const rank of ranks) {
|
|
30460
|
+
const successorRank = rank.successorRank === null || rank.successorRank === undefined ? "absent from top 10" : `#${String(rank.successorRank)}`;
|
|
30461
|
+
lines.push(` - "${String(rank.query)}": retired #${String(rank.retiredRank)}, successor ${successorRank}`);
|
|
30462
|
+
}
|
|
30463
|
+
}
|
|
30464
|
+
return lines;
|
|
30465
|
+
}
|
|
30426
30466
|
function formatProposalShowPlain(r) {
|
|
30427
30467
|
const p = r.proposal;
|
|
30428
30468
|
const lines = [];
|
|
@@ -30458,29 +30498,17 @@ function formatProposalShowPlain(r) {
|
|
|
30458
30498
|
if (review.decidedAt)
|
|
30459
30499
|
lines.push(`review.decidedAt: ${String(review.decidedAt)}`);
|
|
30460
30500
|
}
|
|
30501
|
+
const history = Array.isArray(p.reviewHistory) ? p.reviewHistory : [];
|
|
30502
|
+
for (const entry of history) {
|
|
30503
|
+
const undone = entry.review;
|
|
30504
|
+
const was = undone ? `${String(undone.outcome ?? "?")}${undone.reason ? `: ${String(undone.reason)}` : ""} (${String(undone.decidedAt ?? "?")})` : "an unrecorded review";
|
|
30505
|
+
const why = entry.reopenReason ? ` (${String(entry.reopenReason)})` : "";
|
|
30506
|
+
lines.push(`reopened: ${String(entry.reopenedAt)}${why}, undoing ${was}`);
|
|
30507
|
+
}
|
|
30461
30508
|
const retirement = p.retirement;
|
|
30462
30509
|
if (retirement) {
|
|
30463
30510
|
lines.push(`retire: ${String(retirement.retiredRef)} -> ${String(retirement.successorRef)}`);
|
|
30464
|
-
lines.push(
|
|
30465
|
-
lines.push(`retire.reason: ${String(retirement.judgeReason)}`);
|
|
30466
|
-
const continuityRisk = retirement.continuityRisk;
|
|
30467
|
-
if (continuityRisk) {
|
|
30468
|
-
const failingQueries = typeof continuityRisk.failingQueries === "number" ? continuityRisk.failingQueries : 0;
|
|
30469
|
-
const unverifiedQueries = typeof continuityRisk.unverifiedQueries === "number" ? continuityRisk.unverifiedQueries : 0;
|
|
30470
|
-
const summary = [];
|
|
30471
|
-
if (failingQueries > 0) {
|
|
30472
|
-
summary.push(`${failingQueries} of the retired asset's own quer${failingQueries === 1 ? "y" : "ies"} would not have found the successor top 10`);
|
|
30473
|
-
}
|
|
30474
|
-
if (unverifiedQueries > 0) {
|
|
30475
|
-
summary.push(`${unverifiedQueries} quer${unverifiedQueries === 1 ? "y" : "ies"} unverified (search failed or used the keyword-only fallback)`);
|
|
30476
|
-
}
|
|
30477
|
-
lines.push(`retire.continuityRisk: ${summary.join("; ")} — excluded from bulk accept`);
|
|
30478
|
-
const ranks = Array.isArray(continuityRisk.ranks) ? continuityRisk.ranks : [];
|
|
30479
|
-
for (const rank of ranks) {
|
|
30480
|
-
const successorRank = rank.successorRank === null || rank.successorRank === undefined ? "absent from top 10" : `#${String(rank.successorRank)}`;
|
|
30481
|
-
lines.push(` - "${String(rank.query)}": retired #${String(rank.retiredRank)}, successor ${successorRank}`);
|
|
30482
|
-
}
|
|
30483
|
-
}
|
|
30511
|
+
lines.push(...retireVerdictLines(retirement));
|
|
30484
30512
|
}
|
|
30485
30513
|
const validation = r.validation;
|
|
30486
30514
|
if (validation) {
|
|
@@ -30504,7 +30532,7 @@ function formatProposalShowPlain(r) {
|
|
|
30504
30532
|
}
|
|
30505
30533
|
}
|
|
30506
30534
|
const payload = p.payload;
|
|
30507
|
-
if (payload && typeof payload.content === "string") {
|
|
30535
|
+
if (!retirement && payload && typeof payload.content === "string") {
|
|
30508
30536
|
lines.push("");
|
|
30509
30537
|
lines.push("payload:");
|
|
30510
30538
|
lines.push(payload.content);
|
|
@@ -30519,6 +30547,19 @@ function formatProposalRejectPlain(r) {
|
|
|
30519
30547
|
const reason = r.reason ? ` (${String(r.reason)})` : "";
|
|
30520
30548
|
return `Rejected proposal ${String(r.id)} (${String(r.ref)})${reason}`;
|
|
30521
30549
|
}
|
|
30550
|
+
function formatProposalReopenPlain(r) {
|
|
30551
|
+
const reason = r.reason ? ` (${String(r.reason)})` : "";
|
|
30552
|
+
return `Reopened proposal ${String(r.id)} (${String(r.ref)}) [pending]${reason}`;
|
|
30553
|
+
}
|
|
30554
|
+
function formatProposalReopenBatchPlain(r) {
|
|
30555
|
+
const results = Array.isArray(r.results) ? r.results : [];
|
|
30556
|
+
const reason = results[0]?.reason ? ` (${String(results[0].reason)})` : "";
|
|
30557
|
+
return [
|
|
30558
|
+
`Reopened ${results.length} proposal(s) [pending]${reason}`,
|
|
30559
|
+
...results.map((result) => ` ${String(result.id)} ${String(result.ref)}`)
|
|
30560
|
+
].join(`
|
|
30561
|
+
`);
|
|
30562
|
+
}
|
|
30522
30563
|
function formatProposalDrainPlain(r) {
|
|
30523
30564
|
const applyMode = String(r.applyMode ?? "queue");
|
|
30524
30565
|
const promoted = Array.isArray(r.promoted) ? r.promoted : [];
|
|
@@ -30548,8 +30589,21 @@ function formatProposalDrainPlain(r) {
|
|
|
30548
30589
|
`).trimEnd();
|
|
30549
30590
|
}
|
|
30550
30591
|
function formatProposalDiffPlain(r) {
|
|
30551
|
-
const header = r.isNew ? `# proposal ${String(r.id)} (new asset: ${String(r.ref)})` : `# proposal ${String(r.id)} (update: ${String(r.ref)})`;
|
|
30552
30592
|
const unified = typeof r.unified === "string" ? r.unified : "";
|
|
30593
|
+
if (r.op === "delete") {
|
|
30594
|
+
const retirement = r.retirement;
|
|
30595
|
+
const subject = retirement ? `${String(retirement.retiredRef)} -> ${String(retirement.successorRef)}` : String(r.ref);
|
|
30596
|
+
const lines = [`# proposal ${String(r.id)} (retire: ${subject})`];
|
|
30597
|
+
if (retirement)
|
|
30598
|
+
lines.push(...retireVerdictLines(retirement));
|
|
30599
|
+
if (typeof r.note === "string")
|
|
30600
|
+
lines.push(`note: ${r.note}`);
|
|
30601
|
+
if (unified)
|
|
30602
|
+
lines.push(unified);
|
|
30603
|
+
return lines.join(`
|
|
30604
|
+
`);
|
|
30605
|
+
}
|
|
30606
|
+
const header = r.isNew ? `# proposal ${String(r.id)} (new asset: ${String(r.ref)})` : `# proposal ${String(r.id)} (update: ${String(r.ref)})`;
|
|
30553
30607
|
if (!unified)
|
|
30554
30608
|
return `${header}
|
|
30555
30609
|
(no changes)`;
|
|
@@ -52064,6 +52118,7 @@ import os6 from "node:os";
|
|
|
52064
52118
|
import path44 from "node:path";
|
|
52065
52119
|
|
|
52066
52120
|
// src/storage/sqlite-read-snapshot.ts
|
|
52121
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
52067
52122
|
import fs36 from "node:fs";
|
|
52068
52123
|
import os5 from "node:os";
|
|
52069
52124
|
import path43 from "node:path";
|
|
@@ -52108,6 +52163,26 @@ function fingerprintsEqual(left, right) {
|
|
|
52108
52163
|
const sameFile = (a, b) => a?.size === b?.size && a?.mtimeNs === b?.mtimeNs && a?.ctimeNs === b?.ctimeNs;
|
|
52109
52164
|
return sameFile(left.main, right.main) && sameFile(left.wal, right.wal);
|
|
52110
52165
|
}
|
|
52166
|
+
function copyFileOutsideThisProcess(source, destination) {
|
|
52167
|
+
if (process.platform === "win32") {
|
|
52168
|
+
fs36.copyFileSync(source, destination);
|
|
52169
|
+
return;
|
|
52170
|
+
}
|
|
52171
|
+
const result = spawnSync5("cp", ["--", source, destination], {
|
|
52172
|
+
encoding: "utf8",
|
|
52173
|
+
stdio: ["ignore", "ignore", "pipe"]
|
|
52174
|
+
});
|
|
52175
|
+
if (result.error) {
|
|
52176
|
+
throw new SqliteReadSnapshotUnavailableError(`cannot run cp to copy ${source}: ${result.error.message}`);
|
|
52177
|
+
}
|
|
52178
|
+
if (result.status === 0)
|
|
52179
|
+
return;
|
|
52180
|
+
if (fileFingerprint(source) === undefined) {
|
|
52181
|
+
throw Object.assign(new Error(`${source} disappeared while it was being copied`), { code: "ENOENT" });
|
|
52182
|
+
}
|
|
52183
|
+
const reason = result.stderr.trim() || (result.signal ? `killed by ${result.signal}` : `exit status ${result.status}`);
|
|
52184
|
+
throw new Error(`cp could not copy ${source}: ${reason}`);
|
|
52185
|
+
}
|
|
52111
52186
|
function openSqliteReadSnapshot(dbPath) {
|
|
52112
52187
|
if (!pathExists(dbPath))
|
|
52113
52188
|
return;
|
|
@@ -52123,9 +52198,9 @@ function openSqliteReadSnapshot(dbPath) {
|
|
|
52123
52198
|
if (pathExists(`${dbPath}-journal`))
|
|
52124
52199
|
continue;
|
|
52125
52200
|
const before = databaseFingerprint(dbPath);
|
|
52126
|
-
|
|
52201
|
+
copyFileOutsideThisProcess(dbPath, snapshotPath);
|
|
52127
52202
|
if (before.wal)
|
|
52128
|
-
|
|
52203
|
+
copyFileOutsideThisProcess(`${dbPath}-wal`, `${snapshotPath}-wal`);
|
|
52129
52204
|
else
|
|
52130
52205
|
fs36.rmSync(`${snapshotPath}-wal`, { force: true });
|
|
52131
52206
|
const after = databaseFingerprint(dbPath);
|
|
@@ -52894,6 +52969,8 @@ var proposalFormatters = [
|
|
|
52894
52969
|
{ command: "proposal-show", handler: (r) => formatProposalShowPlain(r) },
|
|
52895
52970
|
{ command: "proposal-accept", handler: (r) => formatProposalAcceptPlain(r) },
|
|
52896
52971
|
{ command: "proposal-reject", handler: (r) => formatProposalRejectPlain(r) },
|
|
52972
|
+
{ command: "proposal-reopen", handler: (r) => formatProposalReopenPlain(r) },
|
|
52973
|
+
{ command: "proposal-reopen-batch", handler: (r) => formatProposalReopenBatchPlain(r) },
|
|
52897
52974
|
{ command: "proposal-diff", handler: (r) => formatProposalDiffPlain(r) },
|
|
52898
52975
|
{ command: "proposal-drain", handler: (r) => formatProposalDrainPlain(r) }
|
|
52899
52976
|
];
|
|
@@ -27868,6 +27868,7 @@ function shapeProposalEntry(entry, detail) {
|
|
|
27868
27868
|
"confidence",
|
|
27869
27869
|
"gateDecision",
|
|
27870
27870
|
"review",
|
|
27871
|
+
"reviewHistory",
|
|
27871
27872
|
"retirement"
|
|
27872
27873
|
]);
|
|
27873
27874
|
}
|
|
@@ -27883,6 +27884,7 @@ function shapeProposalEntry(entry, detail) {
|
|
|
27883
27884
|
"gateDecision",
|
|
27884
27885
|
"payload",
|
|
27885
27886
|
"review",
|
|
27887
|
+
"reviewHistory",
|
|
27886
27888
|
"retirement",
|
|
27887
27889
|
"retiredArchive",
|
|
27888
27890
|
"promotionSource",
|
|
@@ -27947,7 +27949,10 @@ function shapeProposalDiffOutput(result, detail) {
|
|
|
27947
27949
|
ref: result.ref,
|
|
27948
27950
|
isNew: result.isNew,
|
|
27949
27951
|
unified: result.unified,
|
|
27950
|
-
...result.targetPath !== undefined ? { targetPath: result.targetPath } : {}
|
|
27952
|
+
...result.targetPath !== undefined ? { targetPath: result.targetPath } : {},
|
|
27953
|
+
...result.op !== undefined ? { op: result.op } : {},
|
|
27954
|
+
...result.retirement !== undefined ? { retirement: result.retirement } : {},
|
|
27955
|
+
...result.note !== undefined ? { note: result.note } : {}
|
|
27951
27956
|
};
|
|
27952
27957
|
if (detail === "full") {
|
|
27953
27958
|
return { schemaVersion: result.schemaVersion, ...base };
|
|
@@ -28369,6 +28374,7 @@ var PASSTHROUGH_COMMANDS = [
|
|
|
28369
28374
|
"proposal-accept-batch",
|
|
28370
28375
|
"proposal-drain",
|
|
28371
28376
|
"proposal-reject-batch",
|
|
28377
|
+
"proposal-reopen-batch",
|
|
28372
28378
|
"proposal-revert",
|
|
28373
28379
|
"registry-add",
|
|
28374
28380
|
"registry-list",
|
|
@@ -28440,6 +28446,14 @@ var proposalRejectShapes = [
|
|
|
28440
28446
|
}
|
|
28441
28447
|
];
|
|
28442
28448
|
|
|
28449
|
+
// src/output/shapes/proposal/reopen.ts
|
|
28450
|
+
var proposalReopenShapes = [
|
|
28451
|
+
{
|
|
28452
|
+
command: "proposal-reopen",
|
|
28453
|
+
handler: (result, detail) => shapeProposalRejectOutput(result, detail)
|
|
28454
|
+
}
|
|
28455
|
+
];
|
|
28456
|
+
|
|
28443
28457
|
// src/output/shapes/proposal/show.ts
|
|
28444
28458
|
var proposalShowShapes = [
|
|
28445
28459
|
{
|
|
@@ -28530,6 +28544,7 @@ var BUILT_IN_OUTPUT_SHAPES = [
|
|
|
28530
28544
|
...proposalShowShapes,
|
|
28531
28545
|
...proposalAcceptShapes,
|
|
28532
28546
|
...proposalRejectShapes,
|
|
28547
|
+
...proposalReopenShapes,
|
|
28533
28548
|
...proposalDiffShapes,
|
|
28534
28549
|
...proposalProducerShapes,
|
|
28535
28550
|
...envListShapes,
|
|
@@ -29751,6 +29766,31 @@ Generate one with \`akm improve <ref>\` or \`akm proposal new <type> <name> --ta
|
|
|
29751
29766
|
return lines.join(`
|
|
29752
29767
|
`).trimEnd();
|
|
29753
29768
|
}
|
|
29769
|
+
function retireVerdictLines(retirement) {
|
|
29770
|
+
const lines = [
|
|
29771
|
+
`retire.label: ${String(retirement.judgeLabel)} (cosine=${String(retirement.cosine)})`,
|
|
29772
|
+
`retire.reason: ${String(retirement.judgeReason)}`
|
|
29773
|
+
];
|
|
29774
|
+
const continuityRisk = retirement.continuityRisk;
|
|
29775
|
+
if (continuityRisk) {
|
|
29776
|
+
const failingQueries = typeof continuityRisk.failingQueries === "number" ? continuityRisk.failingQueries : 0;
|
|
29777
|
+
const unverifiedQueries = typeof continuityRisk.unverifiedQueries === "number" ? continuityRisk.unverifiedQueries : 0;
|
|
29778
|
+
const summary = [];
|
|
29779
|
+
if (failingQueries > 0) {
|
|
29780
|
+
summary.push(`${failingQueries} of the retired asset's own quer${failingQueries === 1 ? "y" : "ies"} would not have found the successor top 10`);
|
|
29781
|
+
}
|
|
29782
|
+
if (unverifiedQueries > 0) {
|
|
29783
|
+
summary.push(`${unverifiedQueries} quer${unverifiedQueries === 1 ? "y" : "ies"} unverified (search failed or used the keyword-only fallback)`);
|
|
29784
|
+
}
|
|
29785
|
+
lines.push(`retire.continuityRisk: ${summary.join("; ")} \u2014 excluded from bulk accept`);
|
|
29786
|
+
const ranks = Array.isArray(continuityRisk.ranks) ? continuityRisk.ranks : [];
|
|
29787
|
+
for (const rank of ranks) {
|
|
29788
|
+
const successorRank = rank.successorRank === null || rank.successorRank === undefined ? "absent from top 10" : `#${String(rank.successorRank)}`;
|
|
29789
|
+
lines.push(` - "${String(rank.query)}": retired #${String(rank.retiredRank)}, successor ${successorRank}`);
|
|
29790
|
+
}
|
|
29791
|
+
}
|
|
29792
|
+
return lines;
|
|
29793
|
+
}
|
|
29754
29794
|
function formatProposalShowPlain(r) {
|
|
29755
29795
|
const p = r.proposal;
|
|
29756
29796
|
const lines = [];
|
|
@@ -29786,29 +29826,17 @@ function formatProposalShowPlain(r) {
|
|
|
29786
29826
|
if (review.decidedAt)
|
|
29787
29827
|
lines.push(`review.decidedAt: ${String(review.decidedAt)}`);
|
|
29788
29828
|
}
|
|
29829
|
+
const history = Array.isArray(p.reviewHistory) ? p.reviewHistory : [];
|
|
29830
|
+
for (const entry of history) {
|
|
29831
|
+
const undone = entry.review;
|
|
29832
|
+
const was = undone ? `${String(undone.outcome ?? "?")}${undone.reason ? `: ${String(undone.reason)}` : ""} (${String(undone.decidedAt ?? "?")})` : "an unrecorded review";
|
|
29833
|
+
const why = entry.reopenReason ? ` (${String(entry.reopenReason)})` : "";
|
|
29834
|
+
lines.push(`reopened: ${String(entry.reopenedAt)}${why}, undoing ${was}`);
|
|
29835
|
+
}
|
|
29789
29836
|
const retirement = p.retirement;
|
|
29790
29837
|
if (retirement) {
|
|
29791
29838
|
lines.push(`retire: ${String(retirement.retiredRef)} -> ${String(retirement.successorRef)}`);
|
|
29792
|
-
lines.push(
|
|
29793
|
-
lines.push(`retire.reason: ${String(retirement.judgeReason)}`);
|
|
29794
|
-
const continuityRisk = retirement.continuityRisk;
|
|
29795
|
-
if (continuityRisk) {
|
|
29796
|
-
const failingQueries = typeof continuityRisk.failingQueries === "number" ? continuityRisk.failingQueries : 0;
|
|
29797
|
-
const unverifiedQueries = typeof continuityRisk.unverifiedQueries === "number" ? continuityRisk.unverifiedQueries : 0;
|
|
29798
|
-
const summary = [];
|
|
29799
|
-
if (failingQueries > 0) {
|
|
29800
|
-
summary.push(`${failingQueries} of the retired asset's own quer${failingQueries === 1 ? "y" : "ies"} would not have found the successor top 10`);
|
|
29801
|
-
}
|
|
29802
|
-
if (unverifiedQueries > 0) {
|
|
29803
|
-
summary.push(`${unverifiedQueries} quer${unverifiedQueries === 1 ? "y" : "ies"} unverified (search failed or used the keyword-only fallback)`);
|
|
29804
|
-
}
|
|
29805
|
-
lines.push(`retire.continuityRisk: ${summary.join("; ")} \u2014 excluded from bulk accept`);
|
|
29806
|
-
const ranks = Array.isArray(continuityRisk.ranks) ? continuityRisk.ranks : [];
|
|
29807
|
-
for (const rank of ranks) {
|
|
29808
|
-
const successorRank = rank.successorRank === null || rank.successorRank === undefined ? "absent from top 10" : `#${String(rank.successorRank)}`;
|
|
29809
|
-
lines.push(` - "${String(rank.query)}": retired #${String(rank.retiredRank)}, successor ${successorRank}`);
|
|
29810
|
-
}
|
|
29811
|
-
}
|
|
29839
|
+
lines.push(...retireVerdictLines(retirement));
|
|
29812
29840
|
}
|
|
29813
29841
|
const validation = r.validation;
|
|
29814
29842
|
if (validation) {
|
|
@@ -29832,7 +29860,7 @@ function formatProposalShowPlain(r) {
|
|
|
29832
29860
|
}
|
|
29833
29861
|
}
|
|
29834
29862
|
const payload = p.payload;
|
|
29835
|
-
if (payload && typeof payload.content === "string") {
|
|
29863
|
+
if (!retirement && payload && typeof payload.content === "string") {
|
|
29836
29864
|
lines.push("");
|
|
29837
29865
|
lines.push("payload:");
|
|
29838
29866
|
lines.push(payload.content);
|
|
@@ -29847,6 +29875,19 @@ function formatProposalRejectPlain(r) {
|
|
|
29847
29875
|
const reason = r.reason ? ` (${String(r.reason)})` : "";
|
|
29848
29876
|
return `Rejected proposal ${String(r.id)} (${String(r.ref)})${reason}`;
|
|
29849
29877
|
}
|
|
29878
|
+
function formatProposalReopenPlain(r) {
|
|
29879
|
+
const reason = r.reason ? ` (${String(r.reason)})` : "";
|
|
29880
|
+
return `Reopened proposal ${String(r.id)} (${String(r.ref)}) [pending]${reason}`;
|
|
29881
|
+
}
|
|
29882
|
+
function formatProposalReopenBatchPlain(r) {
|
|
29883
|
+
const results = Array.isArray(r.results) ? r.results : [];
|
|
29884
|
+
const reason = results[0]?.reason ? ` (${String(results[0].reason)})` : "";
|
|
29885
|
+
return [
|
|
29886
|
+
`Reopened ${results.length} proposal(s) [pending]${reason}`,
|
|
29887
|
+
...results.map((result) => ` ${String(result.id)} ${String(result.ref)}`)
|
|
29888
|
+
].join(`
|
|
29889
|
+
`);
|
|
29890
|
+
}
|
|
29850
29891
|
function formatProposalDrainPlain(r) {
|
|
29851
29892
|
const applyMode = String(r.applyMode ?? "queue");
|
|
29852
29893
|
const promoted = Array.isArray(r.promoted) ? r.promoted : [];
|
|
@@ -29876,8 +29917,21 @@ function formatProposalDrainPlain(r) {
|
|
|
29876
29917
|
`).trimEnd();
|
|
29877
29918
|
}
|
|
29878
29919
|
function formatProposalDiffPlain(r) {
|
|
29879
|
-
const header = r.isNew ? `# proposal ${String(r.id)} (new asset: ${String(r.ref)})` : `# proposal ${String(r.id)} (update: ${String(r.ref)})`;
|
|
29880
29920
|
const unified = typeof r.unified === "string" ? r.unified : "";
|
|
29921
|
+
if (r.op === "delete") {
|
|
29922
|
+
const retirement = r.retirement;
|
|
29923
|
+
const subject = retirement ? `${String(retirement.retiredRef)} -> ${String(retirement.successorRef)}` : String(r.ref);
|
|
29924
|
+
const lines = [`# proposal ${String(r.id)} (retire: ${subject})`];
|
|
29925
|
+
if (retirement)
|
|
29926
|
+
lines.push(...retireVerdictLines(retirement));
|
|
29927
|
+
if (typeof r.note === "string")
|
|
29928
|
+
lines.push(`note: ${r.note}`);
|
|
29929
|
+
if (unified)
|
|
29930
|
+
lines.push(unified);
|
|
29931
|
+
return lines.join(`
|
|
29932
|
+
`);
|
|
29933
|
+
}
|
|
29934
|
+
const header = r.isNew ? `# proposal ${String(r.id)} (new asset: ${String(r.ref)})` : `# proposal ${String(r.id)} (update: ${String(r.ref)})`;
|
|
29881
29935
|
if (!unified)
|
|
29882
29936
|
return `${header}
|
|
29883
29937
|
(no changes)`;
|
|
@@ -52059,6 +52113,7 @@ import os6 from "os";
|
|
|
52059
52113
|
import path44 from "path";
|
|
52060
52114
|
|
|
52061
52115
|
// src/storage/sqlite-read-snapshot.ts
|
|
52116
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
52062
52117
|
import fs36 from "fs";
|
|
52063
52118
|
import os5 from "os";
|
|
52064
52119
|
import path43 from "path";
|
|
@@ -52103,6 +52158,26 @@ function fingerprintsEqual(left, right) {
|
|
|
52103
52158
|
const sameFile = (a, b) => a?.size === b?.size && a?.mtimeNs === b?.mtimeNs && a?.ctimeNs === b?.ctimeNs;
|
|
52104
52159
|
return sameFile(left.main, right.main) && sameFile(left.wal, right.wal);
|
|
52105
52160
|
}
|
|
52161
|
+
function copyFileOutsideThisProcess(source, destination) {
|
|
52162
|
+
if (process.platform === "win32") {
|
|
52163
|
+
fs36.copyFileSync(source, destination);
|
|
52164
|
+
return;
|
|
52165
|
+
}
|
|
52166
|
+
const result = spawnSync5("cp", ["--", source, destination], {
|
|
52167
|
+
encoding: "utf8",
|
|
52168
|
+
stdio: ["ignore", "ignore", "pipe"]
|
|
52169
|
+
});
|
|
52170
|
+
if (result.error) {
|
|
52171
|
+
throw new SqliteReadSnapshotUnavailableError(`cannot run cp to copy ${source}: ${result.error.message}`);
|
|
52172
|
+
}
|
|
52173
|
+
if (result.status === 0)
|
|
52174
|
+
return;
|
|
52175
|
+
if (fileFingerprint(source) === undefined) {
|
|
52176
|
+
throw Object.assign(new Error(`${source} disappeared while it was being copied`), { code: "ENOENT" });
|
|
52177
|
+
}
|
|
52178
|
+
const reason = result.stderr.trim() || (result.signal ? `killed by ${result.signal}` : `exit status ${result.status}`);
|
|
52179
|
+
throw new Error(`cp could not copy ${source}: ${reason}`);
|
|
52180
|
+
}
|
|
52106
52181
|
function openSqliteReadSnapshot(dbPath) {
|
|
52107
52182
|
if (!pathExists(dbPath))
|
|
52108
52183
|
return;
|
|
@@ -52118,9 +52193,9 @@ function openSqliteReadSnapshot(dbPath) {
|
|
|
52118
52193
|
if (pathExists(`${dbPath}-journal`))
|
|
52119
52194
|
continue;
|
|
52120
52195
|
const before = databaseFingerprint(dbPath);
|
|
52121
|
-
|
|
52196
|
+
copyFileOutsideThisProcess(dbPath, snapshotPath);
|
|
52122
52197
|
if (before.wal)
|
|
52123
|
-
|
|
52198
|
+
copyFileOutsideThisProcess(`${dbPath}-wal`, `${snapshotPath}-wal`);
|
|
52124
52199
|
else
|
|
52125
52200
|
fs36.rmSync(`${snapshotPath}-wal`, { force: true });
|
|
52126
52201
|
const after = databaseFingerprint(dbPath);
|
|
@@ -52889,6 +52964,8 @@ var proposalFormatters = [
|
|
|
52889
52964
|
{ command: "proposal-show", handler: (r) => formatProposalShowPlain(r) },
|
|
52890
52965
|
{ command: "proposal-accept", handler: (r) => formatProposalAcceptPlain(r) },
|
|
52891
52966
|
{ command: "proposal-reject", handler: (r) => formatProposalRejectPlain(r) },
|
|
52967
|
+
{ command: "proposal-reopen", handler: (r) => formatProposalReopenPlain(r) },
|
|
52968
|
+
{ command: "proposal-reopen-batch", handler: (r) => formatProposalReopenBatchPlain(r) },
|
|
52892
52969
|
{ command: "proposal-diff", handler: (r) => formatProposalDiffPlain(r) },
|
|
52893
52970
|
{ command: "proposal-drain", handler: (r) => formatProposalDrainPlain(r) }
|
|
52894
52971
|
];
|
|
@@ -38,6 +38,33 @@ export const LEDGER_REVISIT_CADENCE_DAYS = 7;
|
|
|
38
38
|
* eligible again.
|
|
39
39
|
*/
|
|
40
40
|
export const PAIR_PASS_LEDGER_SOURCE = "consolidate-pair";
|
|
41
|
+
/**
|
|
42
|
+
* The consolidate promote pass's ledger source: one row per source memory,
|
|
43
|
+
* keyed by the memory (`memories/<name>`), not by the knowledge ref the
|
|
44
|
+
* promotion would create.
|
|
45
|
+
*/
|
|
46
|
+
export const CONSOLIDATE_LEDGER_SOURCE = "consolidate";
|
|
47
|
+
/**
|
|
48
|
+
* Whether a decision on `(source, outcome)` leaves the ref's next attempt to
|
|
49
|
+
* its content instead of a clock (#998). An accepted or rejected consolidate
|
|
50
|
+
* promotion is a verdict on that memory's text; asking the model about the
|
|
51
|
+
* same text again can only reproduce the proposal (accepted used to be
|
|
52
|
+
* eligible at once, rejected after 7 days), so the memory waits for an edit.
|
|
53
|
+
* The clock stays for a row with no recorded hash — one decided before the
|
|
54
|
+
* hash was recorded — see {@link nextEligibleAt} and {@link isContentDrivenRow}.
|
|
55
|
+
*/
|
|
56
|
+
export function isContentDrivenDecision(source, outcome) {
|
|
57
|
+
return source === CONSOLIDATE_LEDGER_SOURCE && (outcome === "accepted" || outcome === "rejected");
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Whether this row is held by its content hash: a decided consolidate
|
|
61
|
+
* promotion that recorded the body it was decided against. Such a row has no
|
|
62
|
+
* `next_eligible_at`; the caller compares `contentHash` with the asset's
|
|
63
|
+
* current body hash (the pair pass does the same in `selectInitiators`).
|
|
64
|
+
*/
|
|
65
|
+
export function isContentDrivenRow(row) {
|
|
66
|
+
return row.contentHash !== null && isContentDrivenDecision(row.source, row.outcome);
|
|
67
|
+
}
|
|
41
68
|
/**
|
|
42
69
|
* Outcomes whose window a fresh signal on the asset (new feedback, a content
|
|
43
70
|
* change) cannot lift. Every other window is a revisit cadence that a signal
|
|
@@ -73,12 +100,17 @@ function windowDays(source, outcome) {
|
|
|
73
100
|
}
|
|
74
101
|
/**
|
|
75
102
|
* The single cadence function: when a `(source, outcome)` recorded at
|
|
76
|
-
* `fromIso` becomes eligible again, or `null` for "immediately".
|
|
103
|
+
* `fromIso` becomes eligible again, or `null` for "immediately". A decision
|
|
104
|
+
* that {@link isContentDrivenDecision} holds by content, recorded together
|
|
105
|
+
* with the body hash it was decided against, starts no clock at all: `null`
|
|
106
|
+
* here means the hash is the whole test, not that the ref is free to retry.
|
|
77
107
|
*/
|
|
78
|
-
export function nextEligibleAt(source, outcome, fromIso) {
|
|
108
|
+
export function nextEligibleAt(source, outcome, fromIso, contentHash) {
|
|
79
109
|
const from = Date.parse(fromIso);
|
|
80
110
|
if (!Number.isFinite(from))
|
|
81
111
|
return null;
|
|
112
|
+
if (contentHash && isContentDrivenDecision(source, outcome))
|
|
113
|
+
return null;
|
|
82
114
|
const days = windowDays(source, outcome);
|
|
83
115
|
return days === null ? null : new Date(from + days * MS_PER_DAY).toISOString();
|
|
84
116
|
}
|
|
@@ -127,7 +159,7 @@ export function recordImproveLedger(db, input) {
|
|
|
127
159
|
source: input.source,
|
|
128
160
|
lastAttemptAt: input.at,
|
|
129
161
|
outcome: input.outcome,
|
|
130
|
-
nextEligibleAt: nextEligibleAt(input.source, input.outcome, input.at),
|
|
162
|
+
nextEligibleAt: nextEligibleAt(input.source, input.outcome, input.at, input.contentHash),
|
|
131
163
|
proposalId: input.proposalId ?? null,
|
|
132
164
|
detail: trimDetail(input.detail),
|
|
133
165
|
contentHash: input.contentHash ?? null,
|
|
@@ -150,14 +182,16 @@ export function recordImproveLedger(db, input) {
|
|
|
150
182
|
* differ from the ledger key (a distill proposal for `lessons/x` is keyed by
|
|
151
183
|
* its input `memories/x`) — and `last_attempt_at` is kept: the window starts
|
|
152
184
|
* at the decision, the attempt happened when it happened. A proposal no row
|
|
153
|
-
* knows (minted before the ledger existed
|
|
185
|
+
* knows (minted before the ledger existed, or whose row a later `judged_no_action`
|
|
186
|
+
* overwrote) gets a row keyed by `input.ref`.
|
|
154
187
|
*/
|
|
155
188
|
export function recordImproveLedgerDecision(db, input) {
|
|
189
|
+
const hash = isContentDrivenDecision(input.source, input.outcome) ? input.contentHash : undefined;
|
|
156
190
|
const changes = db
|
|
157
191
|
.prepare(`UPDATE improve_ledger
|
|
158
|
-
SET outcome = ?, next_eligible_at = ?, detail =
|
|
192
|
+
SET outcome = ?, next_eligible_at = ?, detail = ?, content_hash = COALESCE(?, content_hash)
|
|
159
193
|
WHERE stash_dir = ? AND proposal_id = ?`)
|
|
160
|
-
.run(input.outcome, nextEligibleAt(input.source, input.outcome, input.at), trimDetail(input.detail), input.stashDir, input.proposalId).changes;
|
|
194
|
+
.run(input.outcome, nextEligibleAt(input.source, input.outcome, input.at, hash), trimDetail(input.detail), hash ?? null, input.stashDir, input.proposalId).changes;
|
|
161
195
|
if (Number(changes) > 0)
|
|
162
196
|
return;
|
|
163
197
|
recordImproveLedger(db, {
|
|
@@ -168,8 +202,33 @@ export function recordImproveLedgerDecision(db, input) {
|
|
|
168
202
|
at: input.at,
|
|
169
203
|
proposalId: input.proposalId,
|
|
170
204
|
...(input.detail !== undefined ? { detail: input.detail } : {}),
|
|
205
|
+
...(hash !== undefined ? { contentHash: hash } : {}),
|
|
171
206
|
});
|
|
172
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* A rejected proposal was reopened (`akm proposal reopen`): put the rows
|
|
210
|
+
* {@link recordImproveLedgerDecision} found by `proposal_id` back to what the
|
|
211
|
+
* mint wrote — `proposed`, on the revisit cadence from the reopen, and no
|
|
212
|
+
* `content_hash` (a mint records none) — so the rejection's hard window stops
|
|
213
|
+
* reporting (and blocking) a proposal that is pending again.
|
|
214
|
+
* `last_attempt_at` is kept, as a decision keeps it. A proposal with no such
|
|
215
|
+
* row (its mint wrote none, or a later attempt took the key over) changes
|
|
216
|
+
* nothing.
|
|
217
|
+
*/
|
|
218
|
+
export function reopenImproveLedgerDecision(db, input) {
|
|
219
|
+
db.prepare(`UPDATE improve_ledger
|
|
220
|
+
SET outcome = 'proposed', next_eligible_at = ?, detail = ?, content_hash = NULL
|
|
221
|
+
WHERE stash_dir = ? AND proposal_id = ?`).run(nextEligibleAt(input.source, "proposed", input.at), trimDetail(input.detail), input.stashDir, input.proposalId);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* The same reopen for a proposal whose mint deliberately wrote no ledger row (a
|
|
225
|
+
* retire proposal — see `createRetireProposal`): the row its rejection created
|
|
226
|
+
* is dropped, returning the ledger to what the mint left. Found by
|
|
227
|
+
* `proposal_id`, like {@link recordImproveLedgerDecision}.
|
|
228
|
+
*/
|
|
229
|
+
export function forgetImproveLedgerDecision(db, stashDir, proposalId) {
|
|
230
|
+
db.prepare("DELETE FROM improve_ledger WHERE stash_dir = ? AND proposal_id = ?").run(stashDir, proposalId);
|
|
231
|
+
}
|
|
173
232
|
/**
|
|
174
233
|
* Should-fix 6 (second review round): a read-only or dry-run open never
|
|
175
234
|
* migrates, so it can land on a state.db from before migration 029 added
|
|
@@ -80,9 +80,11 @@ export function upsertEmbedding(db, entryId, embedding, model) {
|
|
|
80
80
|
* (ties by id): an exact scan of the current model's rows. `distance` is
|
|
81
81
|
* `sqrt(2 * (1 - cosine))`, the L2 distance between the unit-normalised
|
|
82
82
|
* vectors. Rows of another width, left by a model that is no longer current,
|
|
83
|
-
* never match.
|
|
83
|
+
* never match. With a `scope`, only that bundle's entries of that type are
|
|
84
|
+
* scanned: the `k` nearest of those, not the `k` nearest of everything filtered
|
|
85
|
+
* afterwards.
|
|
84
86
|
*/
|
|
85
|
-
export function searchVec(db, query, k) {
|
|
87
|
+
export function searchVec(db, query, k, scope) {
|
|
86
88
|
const dim = query.length;
|
|
87
89
|
const q = Float64Array.from(query);
|
|
88
90
|
let queryNorm = 0;
|
|
@@ -92,11 +94,13 @@ export function searchVec(db, query, k) {
|
|
|
92
94
|
return [];
|
|
93
95
|
queryNorm = Math.sqrt(queryNorm);
|
|
94
96
|
const current = modelPredicate(db, currentEmbeddingModel(db));
|
|
97
|
+
const scoped = scope ? " AND embeddings.id IN (SELECT id FROM entries WHERE type = ? AND bundle_id = ?)" : "";
|
|
98
|
+
const params = scope ? [...current.params, scope.type, scope.bundleId] : current.params;
|
|
95
99
|
const ids = [];
|
|
96
100
|
const similarities = [];
|
|
97
101
|
const rows = db
|
|
98
|
-
.prepare(`SELECT id, embedding FROM embeddings WHERE ${current.sql}`)
|
|
99
|
-
.iterate(...
|
|
102
|
+
.prepare(`SELECT id, embedding FROM embeddings WHERE ${current.sql}${scoped}`)
|
|
103
|
+
.iterate(...params);
|
|
100
104
|
for (const { id, embedding } of rows) {
|
|
101
105
|
if (embedding.byteLength !== dim * 4)
|
|
102
106
|
continue;
|
|
@@ -126,14 +130,15 @@ export function searchVec(db, query, k) {
|
|
|
126
130
|
/**
|
|
127
131
|
* The k nearest neighbours of an already-indexed entry, by its stored vector —
|
|
128
132
|
* no re-embedding, no network. Returns [] when the entry has no stored
|
|
129
|
-
* vector.
|
|
130
|
-
* filter it out by id.
|
|
133
|
+
* vector. Unscoped, the entry itself is typically returned with distance ~0;
|
|
134
|
+
* callers filter it out by id. A `scope` confines the neighbours to one
|
|
135
|
+
* bundle's entries of one type (see {@link searchVec}).
|
|
131
136
|
*/
|
|
132
|
-
export function getNeighborsByEntryId(db, id, k) {
|
|
137
|
+
export function getNeighborsByEntryId(db, id, k, scope) {
|
|
133
138
|
const row = db.prepare("SELECT embedding FROM embeddings WHERE id = ?").get(id);
|
|
134
139
|
if (!row || row.embedding.byteLength % 4 !== 0)
|
|
135
140
|
return [];
|
|
136
|
-
return searchVec(db, new Float32Array(row.embedding.slice().buffer), k);
|
|
141
|
+
return searchVec(db, new Float32Array(row.embedding.slice().buffer), k, scope);
|
|
137
142
|
}
|
|
138
143
|
/**
|
|
139
144
|
* Every entry that has no embedding row for `model` (any row when no model is
|