@gmickel/gno 1.20.0 → 1.22.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.
- package/README.md +29 -5
- package/assets/skill/SKILL.md +46 -15
- package/package.json +2 -1
- package/spec/cli.md +144 -0
- package/spec/db/schema.sql +170 -0
- package/spec/evals-agentic.md +48 -0
- package/spec/mcp.md +22 -0
- package/spec/output-schemas/capsule-reverified-event.schema.json +47 -0
- package/spec/output-schemas/changes.schema.json +280 -0
- package/spec/output-schemas/document-diff.schema.json +185 -0
- package/spec/output-schemas/impact.schema.json +122 -0
- package/spec/output-schemas/publish-artifact.schema.json +284 -0
- package/spec/output-schemas/saved-capsule-list.schema.json +16 -0
- package/spec/output-schemas/saved-capsule-registration.schema.json +172 -0
- package/spec/output-schemas/saved-capsule-reverification.schema.json +59 -0
- package/spec/output-schemas/saved-capsule-unwatch.schema.json +16 -0
- package/spec/output-schemas/saved-capsule-watch.schema.json +17 -0
- package/src/cli/commands/changes.ts +160 -0
- package/src/cli/commands/context-saved.ts +189 -0
- package/src/cli/options.ts +8 -0
- package/src/cli/program.ts +195 -0
- package/src/core/capsule-registry.ts +279 -0
- package/src/core/capsule-reverification-scheduler.ts +218 -0
- package/src/core/capsule-reverification.ts +289 -0
- package/src/core/change-diff.ts +182 -0
- package/src/core/change-journal.ts +228 -0
- package/src/core/knowledge-delta.ts +395 -0
- package/src/core/knowledge-impact.ts +202 -0
- package/src/ingestion/sync.ts +214 -165
- package/src/mcp/tools/changes.ts +80 -0
- package/src/mcp/tools/index.ts +29 -0
- package/src/publish/artifact-validation.ts +259 -0
- package/src/publish/artifact.ts +234 -118
- package/src/publish/export-service.ts +5 -9
- package/src/publish/metadata.ts +195 -0
- package/src/sdk/client.ts +42 -0
- package/src/sdk/index.ts +7 -0
- package/src/sdk/types.ts +22 -0
- package/src/serve/doc-events.ts +12 -1
- package/src/serve/resident-runtime.ts +22 -0
- package/src/serve/routes/api.ts +13 -0
- package/src/serve/routes/changes.ts +102 -0
- package/src/serve/server.ts +34 -0
- package/src/serve/watch-service.ts +9 -0
- package/src/store/index.ts +21 -0
- package/src/store/migrations/015-document-change-journal.ts +85 -0
- package/src/store/migrations/016-saved-capsules.ts +131 -0
- package/src/store/migrations/017-document-change-retention-counters.ts +33 -0
- package/src/store/migrations/018-saved-capsule-registration-epoch.ts +24 -0
- package/src/store/migrations/019-saved-capsule-registration-generation.ts +53 -0
- package/src/store/migrations/index.ts +10 -0
- package/src/store/sqlite/adapter.ts +291 -7
- package/src/store/sqlite/capsule-registry-store.ts +534 -0
- package/src/store/sqlite/change-journal-store.ts +473 -0
- package/src/store/types.ts +262 -0
|
@@ -35,6 +35,12 @@ import type {
|
|
|
35
35
|
DocLinkInput,
|
|
36
36
|
DocLinkRow,
|
|
37
37
|
DocLinkSource,
|
|
38
|
+
DocumentChangeKind,
|
|
39
|
+
DocumentChangeListOptions,
|
|
40
|
+
DocumentChangePage,
|
|
41
|
+
DocumentChangePurgeResult,
|
|
42
|
+
DocumentChangeRetentionPolicy,
|
|
43
|
+
DocumentChangeRetentionResult,
|
|
38
44
|
DocumentInput,
|
|
39
45
|
DocumentRow,
|
|
40
46
|
EmbeddingCleanupStats,
|
|
@@ -70,6 +76,13 @@ import type {
|
|
|
70
76
|
RetrievalTraceRow,
|
|
71
77
|
RetrievalTraceRunInput,
|
|
72
78
|
RetrievalTraceTerminalStatus,
|
|
79
|
+
RenameDocumentOptions,
|
|
80
|
+
SavedCapsuleRegistrationInput,
|
|
81
|
+
SavedCapsuleRegistrationRecord,
|
|
82
|
+
SavedCapsuleRegistrationSnapshot,
|
|
83
|
+
SavedCapsuleReverificationState,
|
|
84
|
+
SavedCapsuleVerificationExpectation,
|
|
85
|
+
SavedCapsuleVerificationRecord,
|
|
73
86
|
StorePort,
|
|
74
87
|
StoreResult,
|
|
75
88
|
TagCount,
|
|
@@ -95,6 +108,25 @@ import { getSchemaVersion, migrations, runMigrations } from "../migrations";
|
|
|
95
108
|
import { err, ok } from "../types";
|
|
96
109
|
import { getStoredEmbeddingFingerprint } from "../vector/freshness";
|
|
97
110
|
import { modelTableName } from "../vector/sqlite-vec";
|
|
111
|
+
import {
|
|
112
|
+
deleteSavedCapsuleRegistration as deleteStoredSavedCapsuleRegistration,
|
|
113
|
+
getSavedCapsuleRegistration as getStoredSavedCapsuleRegistration,
|
|
114
|
+
getSavedCapsuleRegistrationSnapshot as getStoredSavedCapsuleRegistrationSnapshot,
|
|
115
|
+
getSavedCapsuleReverificationState as getStoredSavedCapsuleReverificationState,
|
|
116
|
+
getSavedCapsuleReverificationSequence as getStoredSavedCapsuleReverificationSequence,
|
|
117
|
+
listSavedCapsuleIdsAffectedByChanges as listStoredSavedCapsuleIdsAffectedByChanges,
|
|
118
|
+
listSavedCapsuleRegistrations as listStoredSavedCapsuleRegistrations,
|
|
119
|
+
setSavedCapsuleReverificationSequence as setStoredSavedCapsuleReverificationSequence,
|
|
120
|
+
upsertSavedCapsuleRegistration as upsertStoredSavedCapsuleRegistration,
|
|
121
|
+
upsertSavedCapsuleVerification as upsertStoredSavedCapsuleVerification,
|
|
122
|
+
} from "./capsule-registry-store";
|
|
123
|
+
import {
|
|
124
|
+
appendDocumentChange as appendStoredDocumentChange,
|
|
125
|
+
enforceDocumentChangeRetention as enforceStoredDocumentChangeRetention,
|
|
126
|
+
listDocumentChanges as listStoredDocumentChanges,
|
|
127
|
+
purgeDocumentChanges as purgeStoredDocumentChanges,
|
|
128
|
+
snapshotDocumentChange,
|
|
129
|
+
} from "./change-journal-store";
|
|
98
130
|
import { loadFts5Snowball } from "./fts5-snowball";
|
|
99
131
|
import {
|
|
100
132
|
appendExportManifest as appendStoredTraceExportManifest,
|
|
@@ -940,6 +972,12 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
940
972
|
const uri = buildUri(doc.collection, doc.relPath);
|
|
941
973
|
|
|
942
974
|
const transaction = db.transaction((): UpsertDocumentResult => {
|
|
975
|
+
const previousRow = db
|
|
976
|
+
.query<DbDocumentRow, [string, string]>(
|
|
977
|
+
"SELECT * FROM documents WHERE collection = ? AND rel_path = ?"
|
|
978
|
+
)
|
|
979
|
+
.get(doc.collection, doc.relPath);
|
|
980
|
+
|
|
943
981
|
db.run(
|
|
944
982
|
`
|
|
945
983
|
INSERT INTO documents (
|
|
@@ -1030,6 +1068,41 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
1030
1068
|
]);
|
|
1031
1069
|
}
|
|
1032
1070
|
|
|
1071
|
+
if (doc.changeJournal !== false) {
|
|
1072
|
+
const nextRow = db
|
|
1073
|
+
.query<DbDocumentRow, [number]>(
|
|
1074
|
+
"SELECT * FROM documents WHERE id = ?"
|
|
1075
|
+
)
|
|
1076
|
+
.get(idRow.id);
|
|
1077
|
+
if (!nextRow) {
|
|
1078
|
+
throw new Error("Failed to read document after upsert");
|
|
1079
|
+
}
|
|
1080
|
+
const previous = previousRow
|
|
1081
|
+
? snapshotDocumentChange(mapDocumentRow(previousRow))
|
|
1082
|
+
: null;
|
|
1083
|
+
const next = snapshotDocumentChange(mapDocumentRow(nextRow));
|
|
1084
|
+
const kind: DocumentChangeKind | null =
|
|
1085
|
+
previous === null
|
|
1086
|
+
? "create"
|
|
1087
|
+
: !previous.active
|
|
1088
|
+
? "reactivate"
|
|
1089
|
+
: previous.sourceHash !== next.sourceHash ||
|
|
1090
|
+
previous.mirrorHash !== next.mirrorHash
|
|
1091
|
+
? "update"
|
|
1092
|
+
: null;
|
|
1093
|
+
if (kind) {
|
|
1094
|
+
appendStoredDocumentChange(db, {
|
|
1095
|
+
documentId: idRow.id,
|
|
1096
|
+
collection: doc.collection,
|
|
1097
|
+
kind,
|
|
1098
|
+
oldSnapshot: previous,
|
|
1099
|
+
newSnapshot: next,
|
|
1100
|
+
structureDelta: doc.changeJournal?.structureDelta,
|
|
1101
|
+
observedAtMs: doc.changeJournal?.observedAtMs ?? Date.now(),
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1033
1106
|
return { id: idRow.id, docid };
|
|
1034
1107
|
});
|
|
1035
1108
|
|
|
@@ -1043,6 +1116,82 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
1043
1116
|
}
|
|
1044
1117
|
}
|
|
1045
1118
|
|
|
1119
|
+
async renameDocument(
|
|
1120
|
+
collection: string,
|
|
1121
|
+
oldRelPath: string,
|
|
1122
|
+
newRelPath: string,
|
|
1123
|
+
options: RenameDocumentOptions = {}
|
|
1124
|
+
): Promise<StoreResult<DocumentRow>> {
|
|
1125
|
+
try {
|
|
1126
|
+
if (!oldRelPath || !newRelPath) {
|
|
1127
|
+
return err("INVALID_INPUT", "Rename paths must be non-empty");
|
|
1128
|
+
}
|
|
1129
|
+
const db = this.ensureOpen();
|
|
1130
|
+
const transaction = db.transaction((): DocumentRow => {
|
|
1131
|
+
const oldRow = db
|
|
1132
|
+
.query<DbDocumentRow, [string, string]>(
|
|
1133
|
+
"SELECT * FROM documents WHERE collection = ? AND rel_path = ?"
|
|
1134
|
+
)
|
|
1135
|
+
.get(collection, oldRelPath);
|
|
1136
|
+
if (!oldRow) {
|
|
1137
|
+
throw new Error("DOCUMENT_RENAME_NOT_FOUND");
|
|
1138
|
+
}
|
|
1139
|
+
if (oldRelPath === newRelPath) {
|
|
1140
|
+
return mapDocumentRow(oldRow);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
const newUri = buildUri(collection, newRelPath);
|
|
1144
|
+
db.run(
|
|
1145
|
+
`UPDATE documents
|
|
1146
|
+
SET rel_path = ?, uri = ?, updated_at = datetime('now')
|
|
1147
|
+
WHERE id = ?`,
|
|
1148
|
+
[newRelPath, newUri, oldRow.id]
|
|
1149
|
+
);
|
|
1150
|
+
db.run("UPDATE documents_fts SET filepath = ? WHERE rowid = ?", [
|
|
1151
|
+
newRelPath,
|
|
1152
|
+
oldRow.id,
|
|
1153
|
+
]);
|
|
1154
|
+
const nextRow = db
|
|
1155
|
+
.query<DbDocumentRow, [number]>(
|
|
1156
|
+
"SELECT * FROM documents WHERE id = ?"
|
|
1157
|
+
)
|
|
1158
|
+
.get(oldRow.id);
|
|
1159
|
+
if (!nextRow) {
|
|
1160
|
+
throw new Error("Failed to read document after rename");
|
|
1161
|
+
}
|
|
1162
|
+
const oldSnapshot = snapshotDocumentChange(mapDocumentRow(oldRow));
|
|
1163
|
+
const nextDocument = mapDocumentRow(nextRow);
|
|
1164
|
+
appendStoredDocumentChange(db, {
|
|
1165
|
+
documentId: oldRow.id,
|
|
1166
|
+
collection,
|
|
1167
|
+
kind: "rename",
|
|
1168
|
+
oldSnapshot,
|
|
1169
|
+
newSnapshot: snapshotDocumentChange(nextDocument),
|
|
1170
|
+
structureDelta: options.structureDelta,
|
|
1171
|
+
observedAtMs: options.observedAtMs ?? Date.now(),
|
|
1172
|
+
});
|
|
1173
|
+
return nextDocument;
|
|
1174
|
+
});
|
|
1175
|
+
|
|
1176
|
+
return ok(transaction());
|
|
1177
|
+
} catch (cause) {
|
|
1178
|
+
if (
|
|
1179
|
+
cause instanceof Error &&
|
|
1180
|
+
cause.message === "DOCUMENT_RENAME_NOT_FOUND"
|
|
1181
|
+
) {
|
|
1182
|
+
return err(
|
|
1183
|
+
"NOT_FOUND",
|
|
1184
|
+
`Document not found for rename: ${collection}/${oldRelPath}`
|
|
1185
|
+
);
|
|
1186
|
+
}
|
|
1187
|
+
return err(
|
|
1188
|
+
"QUERY_FAILED",
|
|
1189
|
+
cause instanceof Error ? cause.message : "Failed to rename document",
|
|
1190
|
+
cause
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1046
1195
|
async getDocument(
|
|
1047
1196
|
collection: string,
|
|
1048
1197
|
relPath: string
|
|
@@ -1453,14 +1602,45 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
1453
1602
|
return ok(0);
|
|
1454
1603
|
}
|
|
1455
1604
|
|
|
1456
|
-
const
|
|
1457
|
-
const
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1605
|
+
const uniquePaths = [...new Set(relPaths)];
|
|
1606
|
+
const placeholders = uniquePaths.map(() => "?").join(",");
|
|
1607
|
+
const transaction = db.transaction((): number => {
|
|
1608
|
+
const activeRows = db
|
|
1609
|
+
.query<DbDocumentRow, (string | number)[]>(
|
|
1610
|
+
`SELECT *
|
|
1611
|
+
FROM documents
|
|
1612
|
+
WHERE collection = ?
|
|
1613
|
+
AND active = 1
|
|
1614
|
+
AND rel_path IN (${placeholders})
|
|
1615
|
+
ORDER BY rel_path ASC, id ASC`
|
|
1616
|
+
)
|
|
1617
|
+
.all(collection, ...uniquePaths);
|
|
1618
|
+
if (activeRows.length === 0) {
|
|
1619
|
+
return 0;
|
|
1620
|
+
}
|
|
1621
|
+
const result = db.run(
|
|
1622
|
+
`UPDATE documents SET active = 0, updated_at = datetime('now')
|
|
1623
|
+
WHERE collection = ?
|
|
1624
|
+
AND active = 1
|
|
1625
|
+
AND rel_path IN (${placeholders})`,
|
|
1626
|
+
[collection, ...uniquePaths]
|
|
1627
|
+
);
|
|
1628
|
+
const observedAtMs = Date.now();
|
|
1629
|
+
for (const activeRow of activeRows) {
|
|
1630
|
+
const previous = snapshotDocumentChange(mapDocumentRow(activeRow));
|
|
1631
|
+
appendStoredDocumentChange(db, {
|
|
1632
|
+
documentId: activeRow.id,
|
|
1633
|
+
collection,
|
|
1634
|
+
kind: "inactivate",
|
|
1635
|
+
oldSnapshot: previous,
|
|
1636
|
+
newSnapshot: { ...previous, active: false },
|
|
1637
|
+
observedAtMs,
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
return result.changes;
|
|
1641
|
+
});
|
|
1462
1642
|
|
|
1463
|
-
return ok(
|
|
1643
|
+
return ok(transaction());
|
|
1464
1644
|
} catch (cause) {
|
|
1465
1645
|
return err(
|
|
1466
1646
|
"QUERY_FAILED",
|
|
@@ -1472,6 +1652,110 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
1472
1652
|
}
|
|
1473
1653
|
}
|
|
1474
1654
|
|
|
1655
|
+
async listDocumentChanges(
|
|
1656
|
+
options: DocumentChangeListOptions = {}
|
|
1657
|
+
): Promise<StoreResult<DocumentChangePage>> {
|
|
1658
|
+
return listStoredDocumentChanges(this.ensureOpen(), options);
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
async enforceDocumentChangeRetention(
|
|
1662
|
+
policy: DocumentChangeRetentionPolicy,
|
|
1663
|
+
nowMs: number
|
|
1664
|
+
): Promise<StoreResult<DocumentChangeRetentionResult>> {
|
|
1665
|
+
return enforceStoredDocumentChangeRetention(
|
|
1666
|
+
this.ensureOpen(),
|
|
1667
|
+
policy,
|
|
1668
|
+
nowMs
|
|
1669
|
+
);
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
async purgeDocumentChanges(): Promise<
|
|
1673
|
+
StoreResult<DocumentChangePurgeResult>
|
|
1674
|
+
> {
|
|
1675
|
+
return purgeStoredDocumentChanges(this.ensureOpen());
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
async upsertSavedCapsuleRegistration(
|
|
1679
|
+
input: SavedCapsuleRegistrationInput
|
|
1680
|
+
): Promise<StoreResult<SavedCapsuleRegistrationRecord>> {
|
|
1681
|
+
return upsertStoredSavedCapsuleRegistration(this.ensureOpen(), input);
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
async listSavedCapsuleRegistrations(): Promise<
|
|
1685
|
+
StoreResult<SavedCapsuleRegistrationRecord[]>
|
|
1686
|
+
> {
|
|
1687
|
+
return listStoredSavedCapsuleRegistrations(this.ensureOpen());
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
async getSavedCapsuleRegistration(
|
|
1691
|
+
registrationId: string
|
|
1692
|
+
): Promise<StoreResult<SavedCapsuleRegistrationRecord | null>> {
|
|
1693
|
+
return getStoredSavedCapsuleRegistration(this.ensureOpen(), registrationId);
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
async getSavedCapsuleRegistrationSnapshot(
|
|
1697
|
+
registrationId: string
|
|
1698
|
+
): Promise<StoreResult<SavedCapsuleRegistrationSnapshot | null>> {
|
|
1699
|
+
return getStoredSavedCapsuleRegistrationSnapshot(
|
|
1700
|
+
this.ensureOpen(),
|
|
1701
|
+
registrationId
|
|
1702
|
+
);
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
async deleteSavedCapsuleRegistration(
|
|
1706
|
+
registrationId: string
|
|
1707
|
+
): Promise<StoreResult<boolean>> {
|
|
1708
|
+
return deleteStoredSavedCapsuleRegistration(
|
|
1709
|
+
this.ensureOpen(),
|
|
1710
|
+
registrationId
|
|
1711
|
+
);
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
async listSavedCapsuleIdsAffectedByChanges(
|
|
1715
|
+
afterSequence: number,
|
|
1716
|
+
throughSequence: number,
|
|
1717
|
+
limit: number
|
|
1718
|
+
): Promise<StoreResult<{ registrationIds: string[]; truncated: boolean }>> {
|
|
1719
|
+
return listStoredSavedCapsuleIdsAffectedByChanges(
|
|
1720
|
+
this.ensureOpen(),
|
|
1721
|
+
afterSequence,
|
|
1722
|
+
throughSequence,
|
|
1723
|
+
limit
|
|
1724
|
+
);
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
async upsertSavedCapsuleVerification(
|
|
1728
|
+
verification: SavedCapsuleVerificationRecord,
|
|
1729
|
+
expectedRegistration: SavedCapsuleVerificationExpectation
|
|
1730
|
+
): Promise<StoreResult<boolean>> {
|
|
1731
|
+
return upsertStoredSavedCapsuleVerification(
|
|
1732
|
+
this.ensureOpen(),
|
|
1733
|
+
verification,
|
|
1734
|
+
expectedRegistration
|
|
1735
|
+
);
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
async getSavedCapsuleReverificationSequence(): Promise<StoreResult<number>> {
|
|
1739
|
+
return getStoredSavedCapsuleReverificationSequence(this.ensureOpen());
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
async getSavedCapsuleReverificationState(): Promise<
|
|
1743
|
+
StoreResult<SavedCapsuleReverificationState>
|
|
1744
|
+
> {
|
|
1745
|
+
return getStoredSavedCapsuleReverificationState(this.ensureOpen());
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
async setSavedCapsuleReverificationSequence(
|
|
1749
|
+
sequence: number,
|
|
1750
|
+
expectedRegistrationEpoch: number
|
|
1751
|
+
): Promise<StoreResult<boolean>> {
|
|
1752
|
+
return setStoredSavedCapsuleReverificationSequence(
|
|
1753
|
+
this.ensureOpen(),
|
|
1754
|
+
sequence,
|
|
1755
|
+
expectedRegistrationEpoch
|
|
1756
|
+
);
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1475
1759
|
// ─────────────────────────────────────────────────────────────────────────
|
|
1476
1760
|
// Content
|
|
1477
1761
|
// ─────────────────────────────────────────────────────────────────────────
|