@zktx.io/sui-mcp 0.5.0 → 0.6.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/README.md +21 -21
- package/dist/adapters/adapterPromptSurfaces.js +0 -20
- package/dist/adapters/deepbook/deepbookQuotePolicy.js +0 -4
- package/dist/adapters/deepbook/deepbookReviewEvidence.js +0 -9
- package/dist/adapters/deepbook/deepbookTransactionMaterialProducer.js +0 -9
- package/dist/adapters/intentPlanFactories.js +0 -6
- package/dist/core/action/contractNameRegistry.js +0 -53
- package/dist/core/action/forbiddenFields.js +0 -4
- package/dist/core/action/ptbVisualizationProducer.js +0 -3
- package/dist/core/action/receiptPtbGraph.js +0 -17
- package/dist/core/action/reviewTimeSimulationEvidence.js +0 -4
- package/dist/core/action/signableAdapterContract.js +0 -5
- package/dist/core/action/suiChainReceiptMapping.js +0 -18
- package/dist/core/action/suiChainReceiptReader.js +1 -21
- package/dist/core/action/suiChainReceiptVerifier.js +0 -10
- package/dist/core/action/transactionFunding.js +0 -7
- package/dist/core/action/types.js +0 -1
- package/dist/core/action/walletReviewContractAssembler.js +0 -2
- package/dist/core/activity/localDataService.js +65 -52
- package/dist/core/activity/localDataValidation.js +1 -3
- package/dist/core/activity/sqliteActivityStore.js +24 -24
- package/dist/core/activity/sqliteActivityStoreRows.js +0 -2
- package/dist/core/activity/sqliteActivityStoreSchema.js +81 -14
- package/dist/core/preferences/sqlitePreferencesRepository.js +5 -3
- package/dist/core/read/deepbookReadHelpers.js +0 -2
- package/dist/core/read/deepbookRegistry.js +0 -19
- package/dist/core/read/deepbookUsdcChartService.js +0 -2
- package/dist/core/read/readCardResult.js +0 -2
- package/dist/core/read/readService.js +0 -19
- package/dist/core/read/readServiceTypes.js +0 -2
- package/dist/core/session/cardSession.js +1 -5
- package/dist/core/session/cardSessionStore.js +54 -7
- package/dist/core/session/reviewValidity.js +0 -3
- package/dist/core/session/sessionRecordStore.js +0 -1
- package/dist/core/session/sessionStore.js +0 -32
- package/dist/core/session/settingsFileIdentity.js +9 -0
- package/dist/core/session/settingsFileProtocol.js +20 -0
- package/dist/core/session/settingsFileStore.js +337 -0
- package/dist/core/session/settingsInputError.js +32 -0
- package/dist/core/session/settingsOperation.js +220 -0
- package/dist/core/session/settingsPreparationSql.js +13 -0
- package/dist/core/session/settingsWorkflow.js +1183 -0
- package/dist/core/session/sqliteCardStore.js +0 -2
- package/dist/core/session/sqliteSessionStore.js +0 -51
- package/dist/core/session/sqliteSettingsWorkflowStore.js +453 -0
- package/dist/core/session/sqliteTransactionMaterialStore.js +0 -11
- package/dist/core/session/sqliteWalletWorkflowStore.js +160 -66
- package/dist/core/session/status.js +2 -4
- package/dist/core/session/transactionMaterialStore.js +0 -4
- package/dist/core/session/transactionRequest.js +0 -4
- package/dist/core/session/walletConnection.js +26 -10
- package/dist/core/session/walletWorkflow.js +70 -30
- package/dist/core/session/workflowState.js +14 -14
- package/dist/core/session/workflowView.js +18 -8
- package/dist/core/suiAddress.js +0 -5
- package/dist/core/suiEndpoint.js +0 -3
- package/dist/mcp/prompts.js +0 -12
- package/dist/mcp/responseGuidance.js +10 -5
- package/dist/mcp/schemas.js +0 -3
- package/dist/mcp/serverInfo.js +3 -4
- package/dist/mcp/toolNames.js +2 -2
- package/dist/mcp/tools/account/index.js +1 -19
- package/dist/mcp/tools/action/prepareSuiActionReview.js +0 -6
- package/dist/mcp/tools/read/readToolHelpers.js +5 -4
- package/dist/mcp/tools/read/serverStatusTools.js +0 -1
- package/dist/mcp/tools/session/executionResultTools.js +2 -2
- package/dist/mcp/tools/session/shared.js +1 -2
- package/dist/mcp/tools/session/statusTools.js +4 -5
- package/dist/mcp/tools/settings/index.js +8 -28
- package/dist/mcp-app/account.html +14 -14
- package/dist/mcp-app/account.notices.txt +1 -1
- package/dist/mcp-app/chart.html +9 -9
- package/dist/mcp-app/chart.notices.txt +1 -1
- package/dist/mcp-app/connect.html +14 -14
- package/dist/mcp-app/connect.notices.txt +1 -1
- package/dist/mcp-app/receipt.html +1298 -1463
- package/dist/mcp-app/receipt.notices.txt +226 -1204
- package/dist/mcp-app/review.html +1298 -1463
- package/dist/mcp-app/review.notices.txt +226 -1204
- package/dist/mcp-app/settings.html +3133 -0
- package/dist/mcp-app/settings.notices.txt +973 -0
- package/dist/mcp-ui/contracts.js +8 -2
- package/dist/mcp-ui/readCards.js +1 -1
- package/dist/mcp-ui/tools.js +34 -4
- package/dist/review-server/server.js +3 -51
- package/dist/runtime/application.js +41 -14
- package/dist/runtime/config.js +0 -2
- package/dist/runtime/localSettingsService.js +23 -2
- package/dist/runtime/logger.js +0 -2
- package/dist/runtime/reviewServerAcquire.js +1 -18
- package/dist/runtime/runtimeTermination.js +1 -4
- package/dist/runtime/shared/authenticatedFetch.js +2 -4
- package/dist/runtime/shared/control.js +4 -7
- package/dist/runtime/shared/dataAccess.js +0 -2
- package/dist/runtime/shared/http.js +14 -0
- package/dist/runtime/shared/mcpHttp.js +6 -6
- package/dist/runtime/shared/ownerLease.js +0 -4
- package/dist/runtime/shared/server.js +1 -2
- package/dist/runtime/shared/stdio.js +2 -5
- package/dist/runtime/smokeMainnetRead.js +0 -3
- package/dist/runtime/smokeReview.js +0 -4
- package/dist/runtime/start.js +0 -2
- package/dist/runtime/suiTransactionGraphqlMapping.js +0 -2
- package/dist/runtime/suiTransactionGraphqlQueries.js +0 -3
- package/dist/runtime/walletConnectConfig.js +0 -2
- package/dist/runtime/walletConnectStorage.js +2 -10
- package/dist/runtime/walletConnectTransport.js +0 -11
- package/dist/runtime/walletSdkChildRuntime.js +2 -6
- package/dist/runtime/walletSdkIpc.js +2 -1
- package/dist/runtime/walletSdkProcess.js +3 -8
- package/docs/AGENT_BEHAVIOR.md +45 -15
- package/docs/LOCAL_DB_ARCHITECTURE.md +145 -22
- package/docs/MCP_SETUP.md +99 -39
- package/docs/MCP_TOOLS.md +288 -24
- package/docs/SDK_API.md +63 -10
- package/docs/UTILITY_INDEX.md +9 -6
- package/docs/WALLET_CONNECTION.md +32 -10
- package/package.json +22 -8
- package/dist/core/activity/schemaVersion.js +0 -2
- package/dist/core/session/keyedRecordStore.js +0 -18
- package/dist/core/session/settingsSession.js +0 -1
- package/dist/core/session/settingsSessions.js +0 -45
- package/dist/review-app/brand-dark.svg +0 -1
- package/dist/review-app/brand-light.svg +0 -1
- package/dist/review-app/favicon.svg +0 -1
- package/dist/review-app/settings.css +0 -1
- package/dist/review-app/settings.js +0 -1
- package/dist/review-app/ui.css +0 -809
- package/dist/review-server/assets.js +0 -48
- package/dist/review-server/html.js +0 -45
- package/dist/review-server/http.js +0 -47
- package/dist/review-server/middleware/reviewToken.js +0 -7
- package/dist/review-server/settingsApi.js +0 -158
- package/docs/AGENT_DEVELOPMENT_POLICY.md +0 -815
- package/docs/FRONTEND_POLICY.md +0 -534
- package/docs/golden-scenarios/BEHAVIOR_MATRIX.md +0 -166
- package/docs/golden-scenarios/INTENT_EVIDENCE_GOLDEN_ANSWERS.md +0 -161
- package/docs/golden-scenarios/INTENT_EVIDENCE_MATRIX.md +0 -259
|
@@ -3,8 +3,6 @@ import { computeReviewStateWithPrivateArtifacts } from "../core/review/reviewCom
|
|
|
3
3
|
export class SmokeReviewConfigError extends Error {
|
|
4
4
|
}
|
|
5
5
|
const requiredSwapInputs = ["SMOKE_SWAP_PROTOCOL", "SMOKE_SWAP_FROM_SYMBOL", "SMOKE_SWAP_TO_SYMBOL", "SMOKE_SWAP_AMOUNT_DISPLAY"];
|
|
6
|
-
/** Optional read-only review computation. This never establishes a wallet
|
|
7
|
-
* connection; the caller owns the explicit temporary read-account fixture. */
|
|
8
6
|
export async function computeSmokeReview(options) {
|
|
9
7
|
const { env, sessions, computation, account } = options;
|
|
10
8
|
const rawSlippage = env.SMOKE_SWAP_MAX_SLIPPAGE_BPS;
|
|
@@ -16,8 +14,6 @@ export async function computeSmokeReview(options) {
|
|
|
16
14
|
return { status: "not_run", notRunReason: "missing_env", requiredEnv: [...requiredSwapInputs] };
|
|
17
15
|
if (missing.length)
|
|
18
16
|
throw new SmokeReviewConfigError(`Partial account-bound swap smoke configuration; missing: ${missing.join(", ")}`);
|
|
19
|
-
// Preserve the utility's existing 50 bps CLI default; it is not a product
|
|
20
|
-
// recommendation or a silently selected protocol/settlement asset.
|
|
21
17
|
const parsed = swapIntentInputSchema.safeParse({ type: "swap", protocol: env.SMOKE_SWAP_PROTOCOL,
|
|
22
18
|
from: { symbol: env.SMOKE_SWAP_FROM_SYMBOL, amount: env.SMOKE_SWAP_AMOUNT_DISPLAY },
|
|
23
19
|
to: { symbol: env.SMOKE_SWAP_TO_SYMBOL }, maxSlippageBps: Number(env.SMOKE_SWAP_MAX_SLIPPAGE_BPS ?? "50") });
|
package/dist/runtime/start.js
CHANGED
|
@@ -43,8 +43,6 @@ async function main() {
|
|
|
43
43
|
grpcOverride: process.env.SUI_GRPC_URL ?? null, graphqlOverride: process.env.SUI_GRAPHQL_URL ?? null
|
|
44
44
|
});
|
|
45
45
|
void controlReady.catch(() => { });
|
|
46
|
-
// The SDK owns stdin from the start, including fragmented initialization
|
|
47
|
-
// and EOF while backend startup is pending. No second reader buffers bytes.
|
|
48
46
|
stage = "stdio_start";
|
|
49
47
|
bridge = await startSharedStdio({ stdio, port: bootConfig.reviewPort, control: controlReady, ready: backendReady,
|
|
50
48
|
onError: (error) => logger.error("MCP transport failed", { error: error.message }) });
|
|
@@ -187,8 +187,6 @@ function executionStatusFromGraphql(value) {
|
|
|
187
187
|
return "success";
|
|
188
188
|
if (value === "FAILURE")
|
|
189
189
|
return "failure";
|
|
190
|
-
// Null status can occur before checkpointed effects are available; unmapped
|
|
191
|
-
// provider enum values stay unknown until explicitly mapped.
|
|
192
190
|
return "unknown";
|
|
193
191
|
}
|
|
194
192
|
function normalizeGraphqlTimestamp(value) {
|
|
@@ -211,9 +211,6 @@ async function queryGraphql(client, options) {
|
|
|
211
211
|
const result = await client.query({ query: options.query, variables: options.variables ?? {} });
|
|
212
212
|
if (result.errors && result.errors.length > 0) {
|
|
213
213
|
const message = result.errors.map((error) => error.message).join("; ");
|
|
214
|
-
// The pinned SDK exposes provider GraphQL errors as messages here. Cursor
|
|
215
|
-
// rejection is intentionally detected conservatively and otherwise falls
|
|
216
|
-
// back to provider_error.
|
|
217
214
|
throw new TransactionActivitySourceError(message.toLowerCase().includes("cursor") ? "cursor_invalid" : "provider_error", "Sui GraphQL query returned errors", { message });
|
|
218
215
|
}
|
|
219
216
|
if (!result.data) {
|
|
@@ -2,9 +2,6 @@ import { existsSync, lstatSync, mkdirSync } from "node:fs";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { serialize, deserialize } from "node:v8";
|
|
4
4
|
import Database from "better-sqlite3";
|
|
5
|
-
// Restoration namespaces of pinned SignClient/Core 2.23.10. Request history,
|
|
6
|
-
// pending requests, messages, unacknowledged envelopes and new namespaces are
|
|
7
|
-
// intentionally volatile; they may contain transaction or signature material.
|
|
8
5
|
const persistentKeys = new Set([
|
|
9
6
|
"wc@2:core:0.3//keychain", "wc@2:core:0.3//pairing",
|
|
10
7
|
"wc@2:core:0.3//subscription", "wc@2:core:0.3//expirer",
|
|
@@ -12,12 +9,11 @@ const persistentKeys = new Set([
|
|
|
12
9
|
]);
|
|
13
10
|
const storageSchema = "CREATE TABLE sdk_sessions (key TEXT PRIMARY KEY, value BLOB NOT NULL)";
|
|
14
11
|
function storageFormat(db) {
|
|
15
|
-
const version = db.pragma("user_version", { simple: true });
|
|
16
12
|
const schema = db.prepare("SELECT type,name,sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%' ORDER BY type,name")
|
|
17
13
|
.all();
|
|
18
|
-
if (
|
|
14
|
+
if (schema.length === 0)
|
|
19
15
|
return "empty";
|
|
20
|
-
if (
|
|
16
|
+
if (schema.length === 1 && schema[0]?.type === "table" &&
|
|
21
17
|
schema[0].name === "sdk_sessions" && schema[0].sql === storageSchema)
|
|
22
18
|
return "current";
|
|
23
19
|
throw new Error("WalletConnect storage format is unsupported.");
|
|
@@ -59,11 +55,8 @@ export function openWalletConnectStorage(dataDirectory) {
|
|
|
59
55
|
if (storageFormat(db) === "empty") {
|
|
60
56
|
db.transaction(() => {
|
|
61
57
|
db.exec(storageSchema);
|
|
62
|
-
db.pragma("user_version = 1");
|
|
63
58
|
})();
|
|
64
59
|
}
|
|
65
|
-
// There is exactly one SDK owner. FULL protects the session material that
|
|
66
|
-
// the SDK needs to resume an acknowledged connection after process exit.
|
|
67
60
|
db.pragma("journal_mode = DELETE");
|
|
68
61
|
db.pragma("synchronous = FULL");
|
|
69
62
|
}
|
|
@@ -94,6 +87,5 @@ export function openWalletConnectStorage(dataDirectory) {
|
|
|
94
87
|
volatile.delete(key);
|
|
95
88
|
}
|
|
96
89
|
};
|
|
97
|
-
// Once injected, SDK timers own the storage until the owner process exits.
|
|
98
90
|
return { storage, closeBeforeSdkUse: () => { volatile.clear(); db.close(); } };
|
|
99
91
|
}
|
|
@@ -27,8 +27,6 @@ export async function createWalletConnectTransport(options) {
|
|
|
27
27
|
if (!/^[0-9a-f]{32}$/i.test(options.projectId))
|
|
28
28
|
throw new Error("WalletConnect project ID format is invalid.");
|
|
29
29
|
const owner = openWalletConnectStorage(options.dataDirectory);
|
|
30
|
-
// SDK log bodies can contain pairing credentials and serialized requests.
|
|
31
|
-
// Product failure stages are recorded by the caller without these values.
|
|
32
30
|
options.onSdkStart?.();
|
|
33
31
|
const client = await (options.initialize ?? SignClient.init.bind(SignClient))({ projectId: options.projectId, metadata: { ...options.metadata, icons: [] },
|
|
34
32
|
storage: owner.storage, logger: "silent", telemetryEnabled: false });
|
|
@@ -37,8 +35,6 @@ export async function createWalletConnectTransport(options) {
|
|
|
37
35
|
const changed = (event) => { if (!stopped)
|
|
38
36
|
for (const listener of listeners)
|
|
39
37
|
listener(event.topic); };
|
|
40
|
-
// Pinned SignClient emits session_event without changing session.namespaces.
|
|
41
|
-
// Treat active account/chain changes as invalidation, not new authorization.
|
|
42
38
|
const selectionChanged = (event) => {
|
|
43
39
|
if (!stopped && ["accountsChanged", "chainChanged"].includes(event.params.event.name)) {
|
|
44
40
|
for (const listener of listeners)
|
|
@@ -60,7 +56,6 @@ export async function createWalletConnectTransport(options) {
|
|
|
60
56
|
const inspect = (topic) => {
|
|
61
57
|
if (stopped)
|
|
62
58
|
throw new Error("WalletConnect owner stopped.");
|
|
63
|
-
// A store failure is not evidence that the session disappeared.
|
|
64
59
|
const session = client.session.getAll().find((item) => item.topic === topic);
|
|
65
60
|
return session ? inspectValue(session) : { topic, status: "absent" };
|
|
66
61
|
};
|
|
@@ -75,8 +70,6 @@ export async function createWalletConnectTransport(options) {
|
|
|
75
70
|
return {
|
|
76
71
|
async restore() {
|
|
77
72
|
requireActive();
|
|
78
|
-
// A pending proposal is not an approved session and must not reappear as
|
|
79
|
-
// a new approval ceremony after owner replacement.
|
|
80
73
|
for (const pairing of client.core.pairing.getPairings()) {
|
|
81
74
|
if (!pairing.active)
|
|
82
75
|
await client.core.pairing.disconnect({ topic: pairing.topic });
|
|
@@ -89,8 +82,6 @@ export async function createWalletConnectTransport(options) {
|
|
|
89
82
|
chains: [SUI_MAINNET_WALLET_CHAIN], methods: [SUI_SIGN_TRANSACTION_METHOD], events: ["accountsChanged", "chainChanged"]
|
|
90
83
|
} } });
|
|
91
84
|
const approval = connecting.approval().then(sessionValue).catch((error) => { throw transportError(error); });
|
|
92
|
-
// Attach a rejection handler immediately; the backend records the same
|
|
93
|
-
// promise's outcome once the private QR has been associated with its row.
|
|
94
85
|
void approval.catch(() => undefined);
|
|
95
86
|
if (!connecting.uri)
|
|
96
87
|
throw new Error("The wallet pairing could not be prepared.");
|
|
@@ -121,8 +112,6 @@ export async function createWalletConnectTransport(options) {
|
|
|
121
112
|
client.off("session_delete", changed);
|
|
122
113
|
client.off("session_expire", changed);
|
|
123
114
|
client.off("session_event", selectionChanged);
|
|
124
|
-
// SignClient has no supported complete in-process disposal. The runtime
|
|
125
|
-
// ends the owner process; it must not close injected storage under timers.
|
|
126
115
|
}
|
|
127
116
|
};
|
|
128
117
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
import { SERVER_VERSION } from "../mcp/serverInfo.js";
|
|
1
2
|
import { join } from "node:path";
|
|
2
3
|
import { isDeepStrictEqual } from "node:util";
|
|
3
4
|
import { WalletUserRejectedError } from "../core/session/walletConnection.js";
|
|
4
5
|
import { acquireDataDirectoryOwner } from "./shared/ownerLease.js";
|
|
5
6
|
import { walletCommandSchema, walletEventSchema } from "./walletSdkIpc.js";
|
|
6
|
-
// Production and the real-SDK wire fixture run this same process lifecycle.
|
|
7
|
-
// The factory is a code dependency, never a serialized command or setting.
|
|
8
7
|
export function runWalletSdkChild(createTransport) {
|
|
9
8
|
let init, transport;
|
|
10
9
|
let sequence = 0, lastRequest = 0, ready = false, exiting = false;
|
|
@@ -19,7 +18,7 @@ export function runWalletSdkChild(createTransport) {
|
|
|
19
18
|
process.send(walletEventSchema.parse(message), (error) => { if (error)
|
|
20
19
|
exit(); });
|
|
21
20
|
};
|
|
22
|
-
const envelope = () => ({
|
|
21
|
+
const envelope = () => ({ packageVersion: SERVER_VERSION, runId: init.runId });
|
|
23
22
|
const exit = () => { if (!exiting) {
|
|
24
23
|
exiting = true;
|
|
25
24
|
void ownership;
|
|
@@ -29,7 +28,6 @@ export function runWalletSdkChild(createTransport) {
|
|
|
29
28
|
ready = false;
|
|
30
29
|
if (init && !exiting)
|
|
31
30
|
send({ ...envelope(), type: "failure", reason });
|
|
32
|
-
// Neither SDK cleanup nor a callback is a prerequisite for process exit.
|
|
33
31
|
if (!exiting) {
|
|
34
32
|
exiting = true;
|
|
35
33
|
process.exit(1);
|
|
@@ -74,7 +72,6 @@ export function runWalletSdkChild(createTransport) {
|
|
|
74
72
|
};
|
|
75
73
|
const start = async (input) => {
|
|
76
74
|
init = input;
|
|
77
|
-
// The child alone opens the SDK store; OS exit releases this separate lock.
|
|
78
75
|
ownership = acquireDataDirectoryOwner(join(input.dataDirectory, "walletconnect", "sessions.sqlite"));
|
|
79
76
|
send({ ...envelope(), type: "stage", stage: "sdk_start" });
|
|
80
77
|
transport = await createTransport(input);
|
|
@@ -153,7 +150,6 @@ export function runWalletSdkChild(createTransport) {
|
|
|
153
150
|
}
|
|
154
151
|
if (!init || input.runId !== init.runId || input.requestId <= lastRequest)
|
|
155
152
|
return;
|
|
156
|
-
// Reserve before awaiting anything, including a connect approval.
|
|
157
153
|
lastRequest = input.requestId;
|
|
158
154
|
void command(input).catch(() => fail("wallet_state_unavailable"));
|
|
159
155
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { SERVER_VERSION } from "../mcp/serverInfo.js";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
import { suiAddressStringSchema } from "../core/suiAddress.js";
|
|
3
4
|
import { walletRunIdSchema, walletStartStageSchema, walletSnapshotSchema, walletSessionObservationSchema, walletSessionSchema } from "../core/session/walletRuntime.js";
|
|
4
5
|
import { walletUnavailableReasonSchema } from "../core/session/walletConnection.js";
|
|
5
|
-
const envelope = z.object({
|
|
6
|
+
const envelope = z.object({ packageVersion: z.literal(SERVER_VERSION), runId: walletRunIdSchema });
|
|
6
7
|
const request = envelope.extend({ requestId: z.number().int().positive(), operationId: z.string().min(1) });
|
|
7
8
|
export const walletCommandSchema = z.union([
|
|
8
9
|
envelope.extend({ type: z.literal("init"), dataDirectory: z.string().min(1), projectId: z.string().regex(/^[0-9a-f]{32}$/i),
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
import { SERVER_VERSION } from "../mcp/serverInfo.js";
|
|
1
2
|
import { fork } from "node:child_process";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
4
|
import { isDeepStrictEqual } from "node:util";
|
|
4
5
|
import { walletUnavailable, WalletUnavailableError, WalletUserRejectedError } from "../core/session/walletConnection.js";
|
|
5
6
|
import { WalletRunInterruptedError, WalletReplacementFailedError } from "../core/session/walletRuntime.js";
|
|
6
7
|
import { walletCommandSchema, walletEventSchema } from "./walletSdkIpc.js";
|
|
7
|
-
/** Owns one SDK process. Business authority and all database transitions remain
|
|
8
|
-
* in the workflow; a process event is never transaction approval. */
|
|
9
8
|
export class WalletSdkProcess {
|
|
10
9
|
options;
|
|
11
10
|
run = this.newRun();
|
|
@@ -74,13 +73,12 @@ export class WalletSdkProcess {
|
|
|
74
73
|
child.once("exit", () => this.exited(run));
|
|
75
74
|
child.once("error", () => {
|
|
76
75
|
this.lose(run, this.failureReason());
|
|
77
|
-
// Failed spawn has no process and therefore cannot emit exit.
|
|
78
76
|
if (child.pid === undefined)
|
|
79
77
|
this.exited(run);
|
|
80
78
|
});
|
|
81
79
|
child.once("disconnect", () => { if (!run.fenced && !run.didExit)
|
|
82
80
|
this.lose(run, this.failureReason()); });
|
|
83
|
-
this.send(run, {
|
|
81
|
+
this.send(run, { packageVersion: SERVER_VERSION, runId: run.id, type: "init", dataDirectory: this.options.dataDirectory,
|
|
84
82
|
projectId: this.options.projectId, metadata: this.options.metadata });
|
|
85
83
|
}
|
|
86
84
|
catch {
|
|
@@ -92,7 +90,6 @@ export class WalletSdkProcess {
|
|
|
92
90
|
send(run, message) {
|
|
93
91
|
if (run !== this.run || run.fenced || this.closed || !run.child?.connected)
|
|
94
92
|
throw new WalletRunInterruptedError(run.id);
|
|
95
|
-
// A false return means backpressure, not permission to repeat the command.
|
|
96
93
|
run.child.send(walletCommandSchema.parse(message), (error) => { if (error)
|
|
97
94
|
this.lose(run, "wallet_state_unavailable"); });
|
|
98
95
|
}
|
|
@@ -270,8 +267,6 @@ export class WalletSdkProcess {
|
|
|
270
267
|
if (this.closed || this.run !== old || this.replacement !== replacement)
|
|
271
268
|
throw new WalletRunInterruptedError(runId);
|
|
272
269
|
const next = this.newRun();
|
|
273
|
-
// A failed reservation ends this attempt. Reads may save its failure,
|
|
274
|
-
// but only a new explicit admission may start another SDK process.
|
|
275
270
|
beforeStart(next.id);
|
|
276
271
|
this.run = next;
|
|
277
272
|
this.state = this.starting(next.id, "process_start");
|
|
@@ -318,7 +313,7 @@ export class WalletSdkProcess {
|
|
|
318
313
|
return new Promise((resolve, reject) => {
|
|
319
314
|
run.pending.set(requestId, { operationId, type: input.type, resolve, reject, ...approval });
|
|
320
315
|
try {
|
|
321
|
-
this.send(run, { ...input,
|
|
316
|
+
this.send(run, { ...input, packageVersion: SERVER_VERSION, runId: run.id, requestId, operationId });
|
|
322
317
|
}
|
|
323
318
|
catch (error) {
|
|
324
319
|
run.pending.delete(requestId);
|
package/docs/AGENT_BEHAVIOR.md
CHANGED
|
@@ -4,7 +4,7 @@ This document is the MCP-exposed answer playbook for AI clients. It owns user-qu
|
|
|
4
4
|
|
|
5
5
|
It does not define tool schemas or field contracts. Use `docs/MCP_TOOLS.md` for the MCP API reference, response fields, statuses, and follow-up fields.
|
|
6
6
|
|
|
7
|
-
It is not the contributor rulebook and it is not enforcement. Development rules live in `AGENTS.md` and `docs/AGENT_DEVELOPMENT_POLICY.md
|
|
7
|
+
It is not the contributor rulebook and it is not enforcement. Development rules live in `AGENTS.md` and `docs/AGENT_DEVELOPMENT_POLICY.md` in the [source repository](https://github.com/zktx-mcp/sui-mcp). They are not installed MCP resources. Hard product boundaries live in code, schemas, allowlists, mainnet guards, and the local review layer.
|
|
8
8
|
|
|
9
9
|
## Support Matrix
|
|
10
10
|
|
|
@@ -311,7 +311,7 @@ For a connected-account-only read, use `session.get_interaction_status` to disti
|
|
|
311
311
|
1. `account.get_active_account` reports the stored selection, with `source` and `setAt`. For current assets without a user-provided address, use `session.get_interaction_status.assetReadAccount` to check whether that selection is a usable default. If not, request an address only for tools that accept `account`; connected-account-only tools require the connection/account-selection flow. Do not infer current connection from the stored selection.
|
|
312
312
|
2. An explicit connect/reconnect/disconnect/account replacement request opens an internal
|
|
313
313
|
Connect card with `session.create_wallet_connection`: use `intent: connect` for requested pairing, `intent: disconnect` for requested disconnection, and `intent: manage` for inspection or account selection. The model must not call app-only actions on the user's behalf.
|
|
314
|
-
For "disconnect my wallet", when the wallet service is available and the target is connected, open `session.create_wallet_connection` with `intent: disconnect`. For one connected target the card shows Confirm disconnect or Back directly; Back only returns to the connection view; it does not submit Cancel review or disconnect. The card starts no pairing. Do not substitute
|
|
314
|
+
For "disconnect my wallet", when the wallet service is available and the target is connected, open `session.create_wallet_connection` with `intent: disconnect`. For one connected target the card shows Confirm disconnect or Back directly; Back only returns to the connection view; it does not submit Cancel review or disconnect. The card starts no pairing. Do not substitute the Settings action to clear the default read address, claim disconnection is unsupported merely because there is no direct model-facing disconnect tool, or equate disconnection with revoking onchain permissions. If disconnection is already pending, read or wait on that exact card instead of opening another operation.
|
|
315
315
|
|
|
316
316
|
3. `session.get_wallet_connection` and `session.wait_wallet_connection` use the
|
|
317
317
|
returned cardId. An unsubmitted card needs input; waiting does not create a
|
|
@@ -347,12 +347,28 @@ them. `allowedActions` describes permitted action types, not all buttons visible
|
|
|
347
347
|
in a particular frame. In particular, a card without a target does not show
|
|
348
348
|
Disconnect or Use account merely because a general action name was mentioned.
|
|
349
349
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
350
|
+
Connection-service recovery belongs to Settings. When the service is unavailable
|
|
351
|
+
or a connection operation remains unresponsive, open
|
|
352
|
+
`settings.create_local_settings_session` on the user's request and direct them
|
|
353
|
+
to Troubleshooting. The user inspects the affected run/requests and explicitly
|
|
354
|
+
confirms Restart connection service; do not call app-only actions for them.
|
|
355
|
+
A new Settings card can explicitly supersede a startup still pending. Read the
|
|
356
|
+
same operation's result; neither a new available run nor restart completion
|
|
357
|
+
confirms an interrupted disconnect or a transaction result. Do not repeatedly
|
|
358
|
+
request wallet approval or report recovery before its new run is observed.
|
|
359
|
+
`manageableConnectionIds` names exact disconnect targets, not usable wallet
|
|
360
|
+
choices. A terminal record may remain manageable when its SDK session is still
|
|
361
|
+
present; do not describe the old failed operation as successful. If
|
|
362
|
+
`connectionReconciliationRequired` is true, explain that the service contains an
|
|
363
|
+
unrecorded connection. Ask the user to remove that retained connection in the
|
|
364
|
+
wallet app, then check its status. Settings/Troubleshooting can restart the
|
|
365
|
+
service to inspect it again; restarting does not approve an unrecorded session.
|
|
366
|
+
Do not infer a free pairing slot from a failed or expired record.
|
|
367
|
+
|
|
368
|
+
If the parent or Settings itself cannot be reached, explain the full app exit
|
|
369
|
+
procedure in the setup guide. All participating apps must quit; closing a peer
|
|
370
|
+
or window can leave the owner alive. Full app restart is also required for
|
|
371
|
+
stored endpoint or installation changes. Do not kill another app's processes.
|
|
356
372
|
|
|
357
373
|
A failed `connectionAction: "disconnect"` means removal was not confirmed.
|
|
358
374
|
Direct the user to inspect/remove the retained connection in their wallet app.
|
|
@@ -468,9 +484,27 @@ For `read.list_review_activity`, `dataScope.recordCount` is the full matching lo
|
|
|
468
484
|
|
|
469
485
|
For `read.get_review_session_detail`, transition rows with `isNoOp: true` are repeated lifecycle observations where the stored status did not change. Mention them only as audit details; do not count them as extra funnel progress.
|
|
470
486
|
|
|
471
|
-
For local settings or
|
|
472
|
-
|
|
473
|
-
|
|
487
|
+
For local settings, local records or connection-service recovery, call `settings.create_local_settings_session` to open the internal Settings card. Its name is unchanged; no external URL is returned. Explain Address for viewing assets, Local records, Troubleshooting or Advanced settings as needed and leave selection/confirmation to the user.
|
|
488
|
+
|
|
489
|
+
For a backup, use the exact label Download backup in Local records. It prepares
|
|
490
|
+
and verifies the snapshot internally and asks the app to save it in one user
|
|
491
|
+
action. Do not instruct a separate Create backup step or confuse Download backup
|
|
492
|
+
with Restore local records. If the actual download function is unsupported,
|
|
493
|
+
the same file is saved once in the Sui MCP backup folder. Use the verified
|
|
494
|
+
Backup saved result's Folder and File name for that local artifact. Do not
|
|
495
|
+
describe that folder as the Host download destination. Suggested file name and Host acknowledgment do not establish where
|
|
496
|
+
or whether a file was saved. Retry download is explicit and may create another
|
|
497
|
+
copy after an unconfirmed earlier request. It uses the same snapshot only during
|
|
498
|
+
its fixed transfer period; a new request after expiry or server restart captures
|
|
499
|
+
current records. Cancel download does not delete a file already saved by the app.
|
|
500
|
+
Use the same function-based product instructions across desktop apps. Missing
|
|
501
|
+
advertisement is not proof of non-support, and timeout, cancellation or denial
|
|
502
|
+
does not trigger local saving. Save a local copy is the explicit decision after
|
|
503
|
+
an earlier possibly handled request. Retry save follows only a confirmed failure
|
|
504
|
+
with no published file; Check status settles uncertain saving or cleanup without
|
|
505
|
+
another file effect. Report saved-file and cleanup facts separately.
|
|
506
|
+
|
|
507
|
+
Ordinary MCP tools never apply a Settings change. Do not call `ui.act_card` or `ui.read_settings_file` as model work. Never request/paste raw backup bytes or card permissions in chat. Clear default address only changes read context, not wallet connections or admitted transactions. Endpoint changes require quitting/reopening all apps; a connection-service restart does not apply them. Report operation result, temporary-file cleanup and Host download acknowledgment as separate facts. A saved result is not proof that the Host saved a downloaded file. For restore validation refusal, let the user correct input or choose another file and prepare a new confirmation; reading or returning to a frame never applies it.
|
|
474
508
|
|
|
475
509
|
## User Vocabulary
|
|
476
510
|
|
|
@@ -518,7 +552,3 @@ Avoid unqualified words such as best, recommended, guaranteed, or safe. Prefer:
|
|
|
518
552
|
## Language
|
|
519
553
|
|
|
520
554
|
This reference document stays in English. Reply in the user's language. Translate response patterns as needed, but keep SDK names, tool names, object IDs, package IDs, and token symbols in their original form.
|
|
521
|
-
|
|
522
|
-
## Golden Scenarios
|
|
523
|
-
|
|
524
|
-
Detailed expected response classes live in `docs/golden-scenarios/BEHAVIOR_MATRIX.md`. They are documentation for release review, not automated cross-client results.
|
|
@@ -10,7 +10,7 @@ The process that binds the configured loopback port initializes these local comp
|
|
|
10
10
|
|
|
11
11
|
- a local SQLite store;
|
|
12
12
|
- a mainnet guard for the configured Sui gRPC endpoint;
|
|
13
|
-
- the
|
|
13
|
+
- the shared private HTTP transport on `127.0.0.1`;
|
|
14
14
|
- authenticated internal MCP sessions, reached by each client through a stdio forwarder.
|
|
15
15
|
|
|
16
16
|
The GraphQL endpoint is also mainnet-guarded when it is saved through settings, imported from a local-data backup, or first used by Sui activity tools.
|
|
@@ -33,7 +33,7 @@ User-requested bounded transaction scans can store normalized facts only when a
|
|
|
33
33
|
|
|
34
34
|
The default Sui mainnet gRPC and GraphQL endpoints are stored in the local SQLite settings table on first run.
|
|
35
35
|
|
|
36
|
-
To inspect settings or change local data, ask
|
|
36
|
+
To inspect settings or change local data, ask for the internal Settings card. Ordinary MCP creates an unsubmitted card or reads settings; scoped app-only preparation/confirmation owns changes. No external page or Settings HTTP API remains.
|
|
37
37
|
|
|
38
38
|
Endpoint changes apply after the MCP server restarts.
|
|
39
39
|
|
|
@@ -105,7 +105,10 @@ The following live session tables hold runtime session state in the shared datab
|
|
|
105
105
|
- `live_private_review_artifacts`: per-session private review evidence (the transaction-material handle, its digest commitment, and derived evidence), cascade-deleted with its review session.
|
|
106
106
|
- `live_transaction_materials`: locally built unsigned transaction bytes stored as a BLOB behind a redacted handle, with a TTL; retained for the admitted request. Terminal request cleanup removes only material still owned by that revision, preserving newer preparation. Owner replacement deletes old private material while retaining immutable review and chain-result evidence.
|
|
107
107
|
- `live_wallet_connections`: verified connection facts, private topic and callback state.
|
|
108
|
-
- `
|
|
108
|
+
- `live_read_cards`: public card state with private permission hash, scope, operation and CAS revision.
|
|
109
|
+
- `settings_operations`: one draft/upload/preparation/admission/result identity per Settings card, with owner/data epoch, user-data revision, fingerprint and SDK supersession/checkpoint facts. A download stores its typed snapshot lifetime and per-attempt delivery reports in private `preparation_json`, separately from the immutable result. Updating delivery never reserializes a terminal `result_json`.
|
|
110
|
+
- `settings_files`: private file identity, original operation, upload/export role, generated paths, lengths/hash, chunk reservation and seal/invalidation/cleanup state. `cleanup_operation_id` separately names the operation responsible for cleanup; replacement can transfer that responsibility without changing the file identity, public path or input eligibility.
|
|
111
|
+
- `settings_control`: current data epoch/user-data revision, one final-operation slot, one file-I/O reservation and the SDK input block owner. These are semantic state/authority facts, not release-version counters.
|
|
109
112
|
|
|
110
113
|
These live tables are distinct from the append-only review evidence tables above: the evidence tables remain the durable activity/audit record, while the live tables hold the in-flight session state that the review server serves.
|
|
111
114
|
|
|
@@ -132,13 +135,92 @@ update triggers reject revision-unaware writers: inserts must use
|
|
|
132
135
|
`revision = 0` and the current write-contract marker, and updates must increase
|
|
133
136
|
the revision by exactly one and keep the current write-contract marker.
|
|
134
137
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
Reset/import are explicitly confirmed Settings operations. They validate the
|
|
139
|
+
current backup shape and imported mainnet endpoints, check current prepared
|
|
140
|
+
impact and reject unsettled wallet/transaction work. One SQLite transaction
|
|
141
|
+
replaces user data, clears coin metadata and other live authorities, advances
|
|
142
|
+
data epoch and preserves the applying operation's read-only card/result. It
|
|
143
|
+
never recreates that result from a callback after deleting it. Rollback
|
|
144
|
+
preserves the prior data, permissions and admission state.
|
|
145
|
+
The private `live_wallet_connections` service journal remains because replacing
|
|
146
|
+
user data does not end SDK sessions. It cannot restore old card permissions or
|
|
147
|
+
transaction authority and is not imported from a backup. Reset clears the
|
|
148
|
+
default address; an imported default still needs its exact current connection
|
|
149
|
+
ID and approved address. Outstanding connection SDK callbacks also block replacement.
|
|
150
|
+
|
|
151
|
+
User-data and wallet/request writers invalidate affected preparations and
|
|
152
|
+
increment their card revision in the same transaction. The trigger and `settings_back`
|
|
153
|
+
reuse one SQL transition: a complete, sealed, non-invalidated upload belonging
|
|
154
|
+
to that operation returns to sealed; other preparations return to draft. Old
|
|
155
|
+
confirmations cannot apply. Backup checking and final I/O still verify physical content;
|
|
156
|
+
a manifest alone is not proof of a valid file.
|
|
157
|
+
|
|
158
|
+
A `download_backup` admission consumes one card input and captures one local-data
|
|
159
|
+
snapshot in the same SQLite transaction. The export role and exact generated
|
|
160
|
+
`.settings-staging/<fileId>.download` namespace identify its private file; an
|
|
161
|
+
export role or display name alone is insufficient. File bytes are not stored
|
|
162
|
+
in operation JSON or nested in exported local data. Physical write, fsync, length and SHA checks
|
|
163
|
+
finish before the snapshot becomes available. `result` is immutable preparation
|
|
164
|
+
evidence; delivery reports have separate typed state and atomic attempt identity.
|
|
165
|
+
|
|
166
|
+
An exact unsupported download report can atomically reserve final/file I/O and
|
|
167
|
+
admit local publication of that same snapshot. An earlier possibly handled
|
|
168
|
+
attempt instead records a pending local-copy decision. Explicit consent/retry
|
|
169
|
+
uses a distinct save-attempt identity and compare-and-set predecessor, without
|
|
170
|
+
creating another snapshot. Application names and absent capability advertisement
|
|
171
|
+
do not authorize this effect.
|
|
172
|
+
|
|
173
|
+
The private `download.localSave` journal in `preparation_json` records its source
|
|
174
|
+
manifest, fixed `backups/<operationId>.json` destination, attempt/consent and
|
|
175
|
+
physical source device/inode as decimal strings. The verified source identity
|
|
176
|
+
is committed before exclusive same-volume hard-link publication. The source and
|
|
177
|
+
target must name the recorded file and pass size/SHA checks before `saved` is
|
|
178
|
+
committed. Existing destinations are never overwritten or removed. Private
|
|
179
|
+
unlink follows that result and actual descriptor closure; the final file has
|
|
180
|
+
no automatic expiry. Historical export path validation remains distinct from
|
|
181
|
+
the private `.download` row identity.
|
|
182
|
+
|
|
183
|
+
Unknown file effects remain `saving`, retaining their source and reservations.
|
|
184
|
+
A failed DB result write retains the ended physical outcome for settlement.
|
|
185
|
+
A missing target is distinct from one that could not be read. Only a verified
|
|
186
|
+
absent target with a valid source permits an explicit retry within the original
|
|
187
|
+
period. Recovery after owner exit verifies an existing source-bound target only;
|
|
188
|
+
an absent or mismatching artifact is not regenerated. The new owner inherits
|
|
189
|
+
settlement responsibility without restoring the old card's action permission.
|
|
190
|
+
A committed saved result remains a past fact when its private file is gone.
|
|
191
|
+
|
|
192
|
+
The fixed thirty-minute transfer period begins at physical readiness, independently
|
|
193
|
+
of the original input expiry. The owner schedules its earliest live transfer
|
|
194
|
+
deadline; current DB time, owner and epoch decide expiry. An abandoned frame does
|
|
195
|
+
not own cleanup. A failed already-due journal cannot create a zero-delay loop or
|
|
196
|
+
cancel another snapshot's future deadline. Status reads and owner recovery can
|
|
197
|
+
retry cleanup. Current-generation access rejects stale callbacks after replacement.
|
|
198
|
+
|
|
199
|
+
Private staging files survive as cleanup journal entries when cards are
|
|
200
|
+
invalidated. Reset/import invalidate uploads and private downloads and transfer
|
|
201
|
+
cleanup ownership without changing file identity. Existing public backup files
|
|
202
|
+
remain unchanged. Acknowledgment, explicit cancellation, expiry, source failure
|
|
203
|
+
or owner restart ends private retention, except that an already-admitted local
|
|
204
|
+
publication retains the evidence needed to settle its result first. Its final
|
|
205
|
+
reservation blocks competing Settings application and data replacement until
|
|
206
|
+
physical I/O and result settlement end. Active descriptor reads/writes finish
|
|
207
|
+
before deletion; new ranges and retries are refused once authority ends.
|
|
208
|
+
`temporaryFileCleanup` includes physical cleanup and settlement of the operation's
|
|
209
|
+
ended I/O reservation. Stored results remain readable during pending cleanup,
|
|
210
|
+
including when expiry persistence fails; input remains closed and the failed
|
|
211
|
+
cleanup stays visible. Another operation's reservation is never released.
|
|
212
|
+
|
|
213
|
+
An explicit same-result read may finish its cleanup or verify an existing
|
|
214
|
+
published export, never regenerate a backup, repeat Host delivery, reapply data
|
|
215
|
+
or replace an SDK run. Files/permissions/SDK credentials/private transaction
|
|
216
|
+
material are excluded from public backups. Clearing the default address does
|
|
217
|
+
not invalidate account-independent coin metadata or disconnect the wallet.
|
|
218
|
+
|
|
219
|
+
Non-terminal review session expiry is recorded lazily when the session is read or mutated after its TTL. Review-session expiry has no background worker; private download retention uses the separate owner timer described above.
|
|
138
220
|
|
|
139
221
|
## Shared local server
|
|
140
222
|
|
|
141
|
-
Exactly one parent runtime owner per data directory binds the configured loopback port and creates the shared product services and SQLite stores. Other clients authenticate the listener before sending control credentials and forward MCP messages to it. The authentication covers database identity,
|
|
223
|
+
Exactly one parent runtime owner per data directory binds the configured loopback port and creates the shared product services and SQLite stores. Other clients authenticate the listener before sending control credentials and forward MCP messages to it. The authentication covers database identity, the package release version, configuration (including WalletConnect project configuration) and server instance. Proof and subsequent dispatch use the same TCP connection. Host/Origin validation is separate from authentication; neither protects against a malicious process running as the same OS user.
|
|
142
224
|
|
|
143
225
|
The private `runtime-control.key` file is separate from UI permissions and wallet credentials and is excluded from product backups. Stdio closure and process signals close the owned server. No client signals a peer backend. The parent may terminate only its own SDK child. A peer can acquire the port after it becomes free. Failed calls are not replayed automatically. MCP framing, cancellation and EOF handling start before backend acquisition; wallet SDK readiness does not block parent service startup.
|
|
144
226
|
|
|
@@ -204,10 +286,12 @@ child exit, while parent verification, submission and lookup flags remain until
|
|
|
204
286
|
their own work ends. SDK readiness does not clear those independent guards.
|
|
205
287
|
|
|
206
288
|
Initial SDK restoration considers the entire known connection set, including
|
|
207
|
-
prior-owner records, before publishing current eligibility.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
289
|
+
prior-owner records, before publishing current eligibility. Confirmed known
|
|
290
|
+
connected records transfer to the new owner. Known terminal records with a
|
|
291
|
+
present SDK session transfer management metadata without changing their outcome.
|
|
292
|
+
Multiple known occupied connections are management targets, not usable wallet
|
|
293
|
+
choices: `connectionConflict` is derived from the journal and current supervisor
|
|
294
|
+
snapshot, with no additional table. Targeted disconnection remains
|
|
211
295
|
available while new pairing, account use, review preparation and signing are
|
|
212
296
|
blocked. The final submission transaction applies the same single-connection
|
|
213
297
|
rule. Failed/stopped records and unknown SDK sessions do not restore authority.
|
|
@@ -221,6 +305,17 @@ database evaluation time and published to cards as `usableConnectionId` and
|
|
|
221
305
|
`assetReadAccount`; Views do not recount recorded connections. This adds no
|
|
222
306
|
table or expiry writer. Stored status, disconnection outcomes and historical
|
|
223
307
|
account records retain their separate meanings.
|
|
308
|
+
The store reads the current run's private supervisor snapshot inside evaluation
|
|
309
|
+
and immediate admission. Missing inspection does not mean an empty service.
|
|
310
|
+
`manageableConnectionIds` names exact nonpending recorded disconnect targets,
|
|
311
|
+
including known terminal records whose SDK sessions remain present. They are not
|
|
312
|
+
usable account choices. `connectionReconciliationRequired: true` means a present
|
|
313
|
+
SDK session has no journal target after ordinary registration/cleanup has ended;
|
|
314
|
+
it blocks pairing, account use and unsubmitted signing until the user removes the
|
|
315
|
+
retained connection in the wallet app and a complete current-run observation
|
|
316
|
+
confirms absence. Settings can explicitly restart the service to inspect it
|
|
317
|
+
again; restart alone does not resolve retained presence. Topics remain private. A pending registration
|
|
318
|
+
is not reported as a reconciliation failure.
|
|
224
319
|
|
|
225
320
|
An admission that changes connection eligibility or targets also publishes the
|
|
226
321
|
owner's ready Connect/Review card revisions in that same transaction, after
|
|
@@ -234,7 +329,8 @@ write; they do not start another SDK process. Repeated reads after a successful
|
|
|
234
329
|
repair do not repeat the transition. Unrelated stored transaction results and
|
|
235
330
|
already dispatched chain observation remain independent of that write.
|
|
236
331
|
The supervisor's explicit replacement primitive requires fencing and actual
|
|
237
|
-
child exit before a new run
|
|
332
|
+
child exit before a new run. Its user entry point is a scoped, explicitly
|
|
333
|
+
prepared and confirmed Settings card; ordinary model calls cannot replace it.
|
|
238
334
|
|
|
239
335
|
If a completed callback's flag write fails, the owner retains its exact operation
|
|
240
336
|
identity as completion evidence. A current state read can retry that database
|
|
@@ -257,6 +353,25 @@ The target session/card's own required expiry writes still propagate errors.
|
|
|
257
353
|
This is not availability during an unreadable database or a bypass of authority
|
|
258
354
|
revocation failures.
|
|
259
355
|
|
|
356
|
+
Connection facts and workflow maintenance have separate internal contracts.
|
|
357
|
+
`readConnectionFacts(at)` collects recorded connections, current-run SDK presence,
|
|
358
|
+
pending work and read-address provenance from one SQLite read snapshot. The
|
|
359
|
+
shared selector and qualification projection compute eligibility from those
|
|
360
|
+
facts; they do not update requests, expire connections or repair callbacks.
|
|
361
|
+
Settings general facts use this diagnostic path and stored counts, so another
|
|
362
|
+
request's refused deadline write does not prevent opening or reading Settings.
|
|
363
|
+
Creating a card and checking its own permission, input expiry or cleanup retain
|
|
364
|
+
their own writes. Stored counts are not a promise about a later deletion impact.
|
|
365
|
+
|
|
366
|
+
`reconcileAndEvaluate` requires a current-wallet or server-bound review purpose.
|
|
367
|
+
Current wallet consumers use `reconcileConnectionContext`; exact request reads
|
|
368
|
+
retain their narrower target. Reset/import preparation and final admission still
|
|
369
|
+
settle deadlines and compare the current impact in their transaction. Snapshot
|
|
370
|
+
memory may precede its DB publication: initializing/state_sync does not grant
|
|
371
|
+
account use or establish an unrecorded-connection removal diagnosis. Only a
|
|
372
|
+
published available run can qualify that guidance; missing guidance does not
|
|
373
|
+
prove that the SDK is empty.
|
|
374
|
+
|
|
260
375
|
Successful reset/import invalidates pending SDK startup or recovery in the old
|
|
261
376
|
data generation and ends that child without automatically starting another.
|
|
262
377
|
Rejected or rolled-back replacement does not change the run or generation.
|
|
@@ -335,13 +450,21 @@ unknown-outcome records may be removed after the explicit warning; removing
|
|
|
335
450
|
records cannot cancel a transaction. A generation change rejects late writes.
|
|
336
451
|
|
|
337
452
|
The wallet store advances expired signature and initial-observation deadlines
|
|
338
|
-
through the same request transition writer used by the workflow.
|
|
339
|
-
|
|
340
|
-
|
|
453
|
+
through the same request transition writer used by the workflow. Explicit
|
|
454
|
+
current-wallet reconciliation settles current wallet work. A server-bound review
|
|
455
|
+
read settles its own request target unless it depends on current wallet work;
|
|
456
|
+
it does not use an unrelated completed request as a reason for global maintenance.
|
|
457
|
+
Reset/import preparation settles deadlines before calculating its impact, and
|
|
458
|
+
final admission settles them again and compares the current impact in the same
|
|
459
|
+
transaction as replacement, even when no View is open.
|
|
460
|
+
|
|
461
|
+
General Settings facts and stored local-data counts use the diagnostic read
|
|
462
|
+
contract; they do not advance live requests. Creating or reading a card still
|
|
463
|
+
checks that card's own permission, input expiry and operation cleanup. Expiry
|
|
341
464
|
does not clear pending SDK/submission/lookup callbacks. Stored activity queries
|
|
342
|
-
and public backup export
|
|
343
|
-
requests or
|
|
344
|
-
claim an earlier counts snapshot is the number being deleted now.
|
|
465
|
+
and public backup export also read recorded facts without advancing live
|
|
466
|
+
requests or treating imported history as authority. Replacement warnings do not
|
|
467
|
+
claim an earlier stored-counts snapshot is the number being deleted now.
|
|
345
468
|
|
|
346
469
|
Disconnect progress is the existing running Connect card's accepted disconnect
|
|
347
470
|
action and connection reference. Connection updates preserve that operation
|
|
@@ -349,11 +472,11 @@ until its result is recorded; no additional persisted connection status is used.
|
|
|
349
472
|
|
|
350
473
|
### Current format and backups
|
|
351
474
|
|
|
352
|
-
The current
|
|
475
|
+
The runtime accepts one current SQLite structure, checked against its table, column, constraint, index and trigger definitions before writes. There is no separate database version counter, migration registry or older-format decoder. All clients sharing a data directory must use the same package release.
|
|
353
476
|
|
|
354
|
-
A current backup carries `format`, `
|
|
477
|
+
A current backup carries `format`, `network`, `exportedAt` and its product data. It has no numeric schema version. Import rejects a different format, unknown or missing fields, invalid references or invalid raw quantities. Missing settings or activity arrays are not filled from defaults. Supported `function_scan` provenance remains part of the current format. Validation failure leaves current data intact.
|
|
355
478
|
|
|
356
|
-
|
|
479
|
+
With a new empty data directory, users configure account context and endpoints; environment overrides retain their existing precedence. Empty local history does not imply an absence of on-chain transactions. Existing DB and backup files are not deleted by startup.
|
|
357
480
|
|
|
358
481
|
## Boundaries
|
|
359
482
|
|
|
@@ -373,7 +496,7 @@ Ownership and simulation private artifacts use their v2 evidence formats to
|
|
|
373
496
|
bind transaction funding to the stored material. They cover real coin objects,
|
|
374
497
|
address withdrawals, gas reservations, and their observed balance/epoch facts.
|
|
375
498
|
They are deeply copied and revalidated before admission, and are excluded from
|
|
376
|
-
public backup.
|
|
499
|
+
public backup.
|
|
377
500
|
|
|
378
501
|
Old private evidence is not upgraded into funding proof. Existing owner recovery
|
|
379
502
|
removes private material; a new review recomputes it. Historical public reviews,
|