@aiwg/cli 2026.8.26 → 2026.8.28
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/bin/aiwg.mjs +6 -0
- package/dist/src/a2a/client.js +4 -1
- package/dist/src/a2a/codecs.js +5 -2
- package/dist/src/a2a/protocol.js +12 -1
- package/dist/src/activity-log/cli.js +4 -1
- package/dist/src/api/index.d.ts +1 -0
- package/dist/src/api/index.js +1 -0
- package/dist/src/artifacts/backends/graphology-backend.js +11 -2
- package/dist/src/artifacts/backends/json-backend.js +12 -2
- package/dist/src/artifacts/backends/sqlite-backend.js +20 -7
- package/dist/src/artifacts/fortemi-core-sync.js +37 -0
- package/dist/src/artifacts/graph-backend.js +16 -0
- package/dist/src/audit/operator-decision.js +9 -25
- package/dist/src/features/catalog.js +3 -2
- package/dist/src/governance/boundary.js +354 -0
- package/dist/src/governance/classification.js +191 -0
- package/dist/src/governance/index.js +5 -0
- package/dist/src/governance/redaction.js +324 -0
- package/dist/src/governance/retention.js +274 -0
- package/dist/src/jobs/executor.js +2 -3
- package/dist/src/ops/cli.js +95 -0
- package/dist/src/serve/dispatch-router.js +1 -1
- package/dist/src/sessions/repository.js +8 -6
- package/dist/src/storage/backends/postgres.js +6 -1
- package/dist/src/storage/index.js +1 -1
- package/dist/src/storage/migration-protocol.js +228 -50
- package/dist/src/storage/qualification.js +39 -5
- package/package.json +1 -1
|
@@ -9,6 +9,10 @@ export async function qualifyStorageBackend(endpoint, options) {
|
|
|
9
9
|
if (options.records.length !== options.scope.declaredRecords) {
|
|
10
10
|
throw new Error('declared record scope does not match the qualification corpus');
|
|
11
11
|
}
|
|
12
|
+
const readerCount = bounded(options.scope.readers, 1, 1, 32, 'readers');
|
|
13
|
+
if (options.scope.operations !== options.records.length + readerCount) {
|
|
14
|
+
throw new Error('declared operation scope must equal record writes plus concurrent readers');
|
|
15
|
+
}
|
|
12
16
|
const now = options.now ?? (() => new Date());
|
|
13
17
|
const startedAt = now().toISOString();
|
|
14
18
|
const cpuBefore = process.cpuUsage();
|
|
@@ -21,7 +25,7 @@ export async function qualifyStorageBackend(endpoint, options) {
|
|
|
21
25
|
const maxRetries = bounded(options.maxRetries, 5, 0, 20, 'maxRetries');
|
|
22
26
|
const baseBackoffMs = bounded(options.baseBackoffMs, 2, 0, 60_000, 'baseBackoffMs');
|
|
23
27
|
const batches = distribute(options.records, options.scope.writers);
|
|
24
|
-
|
|
28
|
+
const writes = Promise.all(batches.map(async (records, writer) => {
|
|
25
29
|
for (const record of records) {
|
|
26
30
|
const mutation = mutationFor(record, `qualification:${writer}:${record.identity.path}:${record.sourceRevision}`);
|
|
27
31
|
const operationStart = performance.now();
|
|
@@ -48,19 +52,33 @@ export async function qualifyStorageBackend(endpoint, options) {
|
|
|
48
52
|
sideEffects.push({ operation: `write:${record.identity.path}`, outcome: replayed ? 'replayed' : 'committed', batchId: receipt.batchId });
|
|
49
53
|
}
|
|
50
54
|
}));
|
|
55
|
+
const reads = Promise.all(Array.from({ length: readerCount }, async (_, reader) => {
|
|
56
|
+
const operationStart = performance.now();
|
|
57
|
+
try {
|
|
58
|
+
await endpoint.readAll();
|
|
59
|
+
latencies.push(performance.now() - operationStart);
|
|
60
|
+
sideEffects.push({ operation: `read:${reader}`, outcome: 'committed' });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
errors += 1;
|
|
64
|
+
sideEffects.push({ operation: `read:${reader}`, outcome: 'failed' });
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}));
|
|
68
|
+
await Promise.all([writes, reads]);
|
|
51
69
|
const expectedDigest = digestRecords(options.records);
|
|
52
70
|
const observed = [...await endpoint.readAll()];
|
|
53
71
|
const verification = verifyExactRecords(options.records, observed);
|
|
54
72
|
const durationMs = Math.max(performance.now() - start, 0.001);
|
|
55
73
|
const cpu = process.cpuUsage(cpuBefore);
|
|
56
|
-
const supplied = options.resourceObservation?.() ?? {};
|
|
57
|
-
const operations = options.records.length +
|
|
74
|
+
const supplied = await options.resourceObservation?.() ?? {};
|
|
75
|
+
const operations = options.records.length + readerCount;
|
|
58
76
|
const report = {
|
|
59
77
|
schemaVersion: STORAGE_QUALIFICATION_REPORT,
|
|
60
78
|
runId: createHash('sha256').update(`${options.scope.commit}\0${options.scope.backend}\0${startedAt}`).digest('hex'),
|
|
61
79
|
startedAt,
|
|
62
80
|
completedAt: now().toISOString(),
|
|
63
|
-
scope: { ...options.scope, observedRecords: observed.length },
|
|
81
|
+
scope: { ...options.scope, observedRecords: observed.length, observedOperations: sideEffects.length },
|
|
64
82
|
verification: { ...verification, expectedDigest, observedDigest: digestRecords(observed) },
|
|
65
83
|
latencyMs: percentiles(latencies),
|
|
66
84
|
throughputPerSecond: operations / (durationMs / 1000),
|
|
@@ -71,7 +89,14 @@ export async function qualifyStorageBackend(endpoint, options) {
|
|
|
71
89
|
resources: {
|
|
72
90
|
cpuUserMicros: cpu.user, cpuSystemMicros: cpu.system,
|
|
73
91
|
rssBytes: Math.max(process.memoryUsage().rss, rssBefore),
|
|
74
|
-
|
|
92
|
+
databaseBytes: resourceMetric(supplied.databaseBytes, 'databaseBytes'),
|
|
93
|
+
writeAmplification: resourceMetric(supplied.writeAmplification, 'writeAmplification'),
|
|
94
|
+
walBytes: resourceMetric(supplied.walBytes, 'walBytes'),
|
|
95
|
+
lockWaits: resourceMetric(supplied.lockWaits, 'lockWaits'),
|
|
96
|
+
poolSaturation: resourceMetric(supplied.poolSaturation, 'poolSaturation'),
|
|
97
|
+
migrationMs: resourceMetric(supplied.migrationMs, 'migrationMs'),
|
|
98
|
+
recoveryMs: resourceMetric(supplied.recoveryMs, 'recoveryMs'),
|
|
99
|
+
transportOverheadMs: resourceMetric(supplied.transportOverheadMs, 'transportOverheadMs'),
|
|
75
100
|
},
|
|
76
101
|
sideEffects: sideEffects.sort((a, b) => a.operation.localeCompare(b.operation)),
|
|
77
102
|
};
|
|
@@ -109,6 +134,8 @@ export function assertCurrentStorageEvidence(report, commit) {
|
|
|
109
134
|
throw new Error('storage qualification record is stale for the requested commit');
|
|
110
135
|
if (report.scope.declaredRecords !== report.scope.observedRecords)
|
|
111
136
|
throw new Error('storage qualification scope is incomplete');
|
|
137
|
+
if (report.scope.operations !== report.scope.observedOperations)
|
|
138
|
+
throw new Error('storage qualification operation scope is incomplete');
|
|
112
139
|
}
|
|
113
140
|
function mutationFor(record, idempotencyKey) {
|
|
114
141
|
return { operation: record.tombstone ? 'delete' : 'upsert', record, idempotencyKey };
|
|
@@ -134,4 +161,11 @@ function bounded(value, fallback, min, max, label) {
|
|
|
134
161
|
throw new Error(`${label} must be an integer from ${min} through ${max}`);
|
|
135
162
|
return resolved;
|
|
136
163
|
}
|
|
164
|
+
function resourceMetric(value, label) {
|
|
165
|
+
if (value === undefined || value === null)
|
|
166
|
+
return null;
|
|
167
|
+
if (!Number.isFinite(value) || value < 0)
|
|
168
|
+
throw new Error(`${label} must be a finite non-negative number`);
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
137
171
|
//# sourceMappingURL=qualification.js.map
|