From 1f4a7030b5f1b41af000183fd837c77692128131 Mon Sep 17 00:00:00 2001 From: FilipBl4gojevic <84703395+FilipBl4gojevic@users.noreply.github.com> Date: Sat, 1 Aug 2026 10:31:18 +0200 Subject: [PATCH] fix: restore precision in tool descriptions and design-doc caveats after the voice pass --- docs/architecture/non-custodial-split.md | 4 ++-- packages/builder/src/vector/vector.ts | 6 +++--- packages/builder/test/build-contracts.test.ts | 2 +- packages/builder/test/smoke/tool-schemas.snapshot.json | 6 +++--- packages/signer/README.md | 5 +++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/architecture/non-custodial-split.md b/docs/architecture/non-custodial-split.md index e62e388..f5d7c74 100644 --- a/docs/architecture/non-custodial-split.md +++ b/docs/architecture/non-custodial-split.md @@ -119,7 +119,7 @@ interface Policy { `vector_signer_decode_transaction` is a read-only preview so an agent can show a human what it is about to sign. -**Accepted trade-off of the 4-call shape:** the signer records **intent to spend** at signing time, not confirmed submission. If a submit later fails, the audit log over-counts. Conservative, therefore acceptable, and it is the price of the signer having no network access. +**Accepted trade-off of the 4-call shape:** the signer records **intent to spend** at signing time, not confirmed submission. If a submit later fails, the audit log over-counts. Conservative, therefore acceptable, and it is the price of the signer having no network access. This trade-off is documented. ### Two-step self-improvement flow @@ -250,7 +250,7 @@ CI only runs `npm run build`, and `tsup`/esbuild strips types without checking t **Native-asset outflow is not limited in v1.** Spend limits apply to lovelace. A transaction moving ~2 AP3X plus a valuable NFT to a foreign address passes the lovelace check. Blanket-denying asset outflow is not viable because legitimate registry flows mint an NFT to the registry script address. -v1 mitigation: all asset movements are decoded, logged, and returned in the policy decision, and `assetOutflowPolicy` is configurable (`allow` default | `deny` | `allowlist`) for high-value wallets. Post-v1: per-policy asset rules. +v1 mitigation: all asset movements are decoded, logged, and returned in the policy decision, and `assetOutflowPolicy` is configurable (`allow` default | `deny` | `allowlist`) for high-value wallets. **This is a stated limitation.** Post-v1: per-policy asset rules. **Key at rest is plaintext in v1** (env var or `0600` file). The win is that the key is *local and never transits the LLM or a shared host*, not that it is in an HSM. `KeySource` exists so keychain/HSM/hardware land later without touching the sign path. diff --git a/packages/builder/src/vector/vector.ts b/packages/builder/src/vector/vector.ts index 19a1690..82876e5 100644 --- a/packages/builder/src/vector/vector.ts +++ b/packages/builder/src/vector/vector.ts @@ -230,7 +230,7 @@ Non-custodial flow: 1) sign locally with vector_signer_sign { txCbor } - your ke "vector_build_send_tokens", "Build an UNSIGNED transaction sending Vector native tokens. Takes no key material - sign the returned CBOR with your local signer (vector_signer_sign), then broadcast with vector_submit_transaction and confirm with vector_await_transaction.", { - changeAddress: z.string().describe("Your wallet address (holds the AP3X; receives change). Get it from your local signer's vector_signer_get_address."), + changeAddress: z.string().describe("Your wallet address (holds the AP3X and tokens; receives change). Get it from your local signer's vector_signer_get_address."), recipientAddress: z.string().describe("Recipient Vector address (addr1...)"), policyId: z.string().describe("Token policy ID (56 hex characters)"), assetName: z.string().describe("Asset name (text or hex; can be empty for policy-only tokens)"), @@ -287,7 +287,7 @@ Non-custodial flow: 1) sign locally with vector_signer_sign { txCbor }; 2) broad "vector_build_transaction", "Build an UNSIGNED multi-output transaction with optional metadata. Takes no key material and never submits - sign the returned CBOR with your local signer (vector_signer_sign), then broadcast with vector_submit_transaction and confirm with vector_await_transaction.", { - changeAddress: z.string().describe("Your wallet address (holds the AP3X; receives change). Get it from your local signer's vector_signer_get_address."), + changeAddress: z.string().describe("Your wallet address (supplies the inputs; receives change). Get it from your local signer's vector_signer_get_address."), outputs: z.array(z.object({ address: z.string().describe("Recipient Vector address"), lovelace: z.number().describe("Amount in lovelace (1 AP3X = 1,000,000 lovelace)"), @@ -659,7 +659,7 @@ Sign locally with vector_signer_sign, broadcast with vector_submit_transaction, "vector_build_interact_contract", "Build an UNSIGNED transaction interacting with a deployed Plutus/Aiken contract - lock AP3X at it or spend from it. Takes no key material - sign with your local signer, then broadcast with vector_submit_transaction and confirm with vector_await_transaction.", { - changeAddress: z.string().describe("Your wallet address (holds the AP3X, receives change, and is the required signer for spends). Get it from your local signer's vector_signer_get_address."), + changeAddress: z.string().describe("Your wallet address (supplies the inputs, receives change, and is the required signer for spends). Get it from your local signer's vector_signer_get_address."), scriptCbor: z.string().describe("Compiled Plutus/Aiken script in CBOR hex"), scriptType: z.enum(["PlutusV1", "PlutusV2", "PlutusV3"]).describe("Script version"), action: z.enum(["spend", "lock"]).describe("'spend' to collect UTxOs from the script, 'lock' to send AP3X to it"), diff --git a/packages/builder/test/build-contracts.test.ts b/packages/builder/test/build-contracts.test.ts index 2e7ce7e..ba4fca3 100644 --- a/packages/builder/test/build-contracts.test.ts +++ b/packages/builder/test/build-contracts.test.ts @@ -52,7 +52,7 @@ describe('buildMultiOutput', () => { }); describe('buildDeployContract', () => { - test('locks funds at the derived script address with an inline datum', async () => { + test('locks AP3X at the derived script address with an inline datum', async () => { const r = await buildDeployContract(lucid, { scriptCbor: ALWAYS_SUCCEEDS_V2, scriptType: 'PlutusV2', lovelaceAmount: 2_000_000, }); diff --git a/packages/builder/test/smoke/tool-schemas.snapshot.json b/packages/builder/test/smoke/tool-schemas.snapshot.json index 47ad857..04f0c97 100644 --- a/packages/builder/test/smoke/tool-schemas.snapshot.json +++ b/packages/builder/test/smoke/tool-schemas.snapshot.json @@ -87,7 +87,7 @@ "type": "object", "properties": { "changeAddress": { - "description": "Your wallet address (holds the AP3X, receives change, and is the required signer for spends). Get it from your local signer's vector_signer_get_address.", + "description": "Your wallet address (supplies the inputs, receives change, and is the required signer for spends). Get it from your local signer's vector_signer_get_address.", "type": "string" }, "scriptCbor": { @@ -494,7 +494,7 @@ "type": "object", "properties": { "changeAddress": { - "description": "Your wallet address (holds the AP3X; receives change). Get it from your local signer's vector_signer_get_address.", + "description": "Your wallet address (holds the AP3X and tokens; receives change). Get it from your local signer's vector_signer_get_address.", "type": "string" }, "recipientAddress": { @@ -534,7 +534,7 @@ "type": "object", "properties": { "changeAddress": { - "description": "Your wallet address (holds the AP3X; receives change). Get it from your local signer's vector_signer_get_address.", + "description": "Your wallet address (supplies the inputs; receives change). Get it from your local signer's vector_signer_get_address.", "type": "string" }, "outputs": { diff --git a/packages/signer/README.md b/packages/signer/README.md index 37bb689..01696e1 100644 --- a/packages/signer/README.md +++ b/packages/signer/README.md @@ -126,8 +126,9 @@ over-counts, which refuses too much rather than too little. today's spend, which quietly raises the effective daily limit. The practical effect: if the audit log's directory disappears, the disk fills, or the path loses write permission, every `vector_signer_sign` call starts returning `REFUSED`, including transactions well inside - policy, until it is writable again. That refusal names the audit failure explicitly, unlike - an ordinary policy refusal. Signing stops outright until the log is writable again. + policy, until it is writable again. That refusal names the audit failure explicitly rather + than reading like an ordinary policy refusal, but it is still a full stop on signing, not a + warning. - **The key is plaintext at rest** in v1 (env var or file). The win is that it is *local* and never transits your model provider or a shared host, not that it is in an HSM. `KeySource` exists so keychain and hardware backends can be added without touching the