arc-builder-kit 0.2.0__py3-none-any.whl
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.
- arc_builder_kit/__init__.py +4 -0
- arc_builder_kit/__main__.py +6 -0
- arc_builder_kit/_paths.py +47 -0
- arc_builder_kit/cli.py +277 -0
- arc_builder_kit/config/arc_testnet.facts.json +31 -0
- arc_builder_kit/doctor.py +936 -0
- arc_builder_kit/examples/agent-commerce-components/components.js +200 -0
- arc_builder_kit/examples/agent-commerce-components/index.html +120 -0
- arc_builder_kit/examples/agent-commerce-flows/flows.js +271 -0
- arc_builder_kit/examples/agent-commerce-flows/index.html +114 -0
- arc_builder_kit/examples/agent-commerce-live/commerce-live.js +190 -0
- arc_builder_kit/examples/agent-commerce-live/index.html +105 -0
- arc_builder_kit/examples/agent-commerce-review-packet/index.html +96 -0
- arc_builder_kit/examples/agent-commerce-review-packet/packet.js +125 -0
- arc_builder_kit/examples/agent-identity-profile-preview/identity.js +126 -0
- arc_builder_kit/examples/agent-identity-profile-preview/index.html +104 -0
- arc_builder_kit/examples/arc-agent-treasury-lab/index.html +152 -0
- arc_builder_kit/examples/arc-agent-treasury-lab/treasury.js +532 -0
- arc_builder_kit/examples/arc-testnet-operator-evidence/evidence.example.json +47 -0
- arc_builder_kit/examples/arc-testnet-wallet-send-gate/index.html +233 -0
- arc_builder_kit/examples/arc-testnet-wallet-send-gate/live-infrastructure-policy.example.json +59 -0
- arc_builder_kit/examples/arc-testnet-wallet-send-gate/wallet-send-gate.js +472 -0
- arc_builder_kit/examples/circle-wallet-integration/index.html +155 -0
- arc_builder_kit/examples/circle-wallet-integration/wallet-lab.js +91 -0
- arc_builder_kit/examples/job-escrow-simulator/index.html +121 -0
- arc_builder_kit/examples/job-escrow-simulator/simulator.js +162 -0
- arc_builder_kit/examples/payment-intent-demo/index.html +132 -0
- arc_builder_kit/examples/payment-intent-playground/index.html +301 -0
- arc_builder_kit/examples/payment-intent-playground/playground.js +835 -0
- arc_builder_kit/examples/payment-intent-receipt-matcher/index.html +157 -0
- arc_builder_kit/examples/payment-intent-receipt-matcher/matcher.js +877 -0
- arc_builder_kit/examples/receipt-verifier-playground/index.html +120 -0
- arc_builder_kit/examples/receipt-verifier-playground/verifier.js +226 -0
- arc_builder_kit/examples/receipt-viewer/index.html +138 -0
- arc_builder_kit/examples/receipt-viewer/receipt-viewer.js +472 -0
- arc_builder_kit/examples/transaction-status-playground/index.html +135 -0
- arc_builder_kit/examples/transaction-status-playground/status.js +518 -0
- arc_builder_kit/examples/x402-local-challenge-server/.env.example +25 -0
- arc_builder_kit/examples/x402-local-challenge-server/README.md +111 -0
- arc_builder_kit/examples/x402-local-challenge-server/server.py +711 -0
- arc_builder_kit/mcp_server.py +463 -0
- arc_builder_kit/release_packet.py +469 -0
- arc_builder_kit/templates/README.md +25 -0
- arc_builder_kit/templates/job-escrow-starter/README.md +25 -0
- arc_builder_kit/templates/job-escrow-starter/index.html +41 -0
- arc_builder_kit/templates/job-escrow-starter/index.js +14 -0
- arc_builder_kit/templates/payment-intent-starter/README.md +25 -0
- arc_builder_kit/templates/payment-intent-starter/index.html +42 -0
- arc_builder_kit/templates/payment-intent-starter/index.js +7 -0
- arc_builder_kit/templates/x402-agent-starter/README.md +29 -0
- arc_builder_kit/templates/x402-agent-starter/server.py +201 -0
- arc_builder_kit/validate_repo.py +2212 -0
- arc_builder_kit-0.2.0.dist-info/METADATA +543 -0
- arc_builder_kit-0.2.0.dist-info/RECORD +58 -0
- arc_builder_kit-0.2.0.dist-info/WHEEL +5 -0
- arc_builder_kit-0.2.0.dist-info/entry_points.txt +3 -0
- arc_builder_kit-0.2.0.dist-info/licenses/LICENSE +21 -0
- arc_builder_kit-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate a local, read-only Arc Builder release packet for PR/release review.
|
|
3
|
+
|
|
4
|
+
This script is dependency-free and makes zero network calls by default. It
|
|
5
|
+
re-uses the existing Arc Builder Doctor orchestrator and Arc Testnet facts file
|
|
6
|
+
to produce Markdown/JSON artifacts that a maintainer can inspect, archive, or
|
|
7
|
+
attach to a release. It never connects a wallet, signs, broadcasts, handles
|
|
8
|
+
secrets, or claims settlement/mainnet readiness.
|
|
9
|
+
|
|
10
|
+
Output directory default: .arc-release-packet/
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import json
|
|
17
|
+
import shutil
|
|
18
|
+
import subprocess
|
|
19
|
+
import sys
|
|
20
|
+
from datetime import datetime, timezone
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import Any, NoReturn
|
|
23
|
+
|
|
24
|
+
from arc_builder_kit._paths import CONFIG_DIR, DEFAULT_OUTPUT_ROOT, REPO_ROOT as ROOT
|
|
25
|
+
|
|
26
|
+
DEFAULT_OUT = DEFAULT_OUTPUT_ROOT / ".arc-release-packet"
|
|
27
|
+
|
|
28
|
+
KIND = "arc_builder_release_packet"
|
|
29
|
+
SCHEMA_VERSION = 1
|
|
30
|
+
|
|
31
|
+
# Reusable safety text used across generated artifacts.
|
|
32
|
+
DISCLAIMER = (
|
|
33
|
+
"This packet is a read-only local review artifact. It is not a settlement "
|
|
34
|
+
"proof, custody claim, mainnet readiness claim, or production release "
|
|
35
|
+
"certificate. No wallet was connected, no private key was handled, no "
|
|
36
|
+
"transaction was signed, and no transaction was broadcast while "
|
|
37
|
+
"generating this packet."
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
EXAMPLES = [
|
|
41
|
+
{
|
|
42
|
+
"id": "payment-intent-receipt-matcher",
|
|
43
|
+
"path": "examples/payment-intent-receipt-matcher",
|
|
44
|
+
"purpose": "Compare a local payment-intent JSON with an Arc Testnet receipt's pinned USDC Transfer logs and emit a match/mismatch/revert/not-found/unknown verdict.",
|
|
45
|
+
"boundary": "Read-only log inspection; no signing, no broadcast, no settlement claim; optional local evidence export via browser Blob only.",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "arc-testnet-wallet-send-gate",
|
|
49
|
+
"path": "examples/arc-testnet-wallet-send-gate",
|
|
50
|
+
"purpose": "Demonstrate a guarded, human-reviewed Arc Testnet browser-wallet send flow behind an explicit enable gate.",
|
|
51
|
+
"boundary": "Signing and submission are delegated to an external user-controlled wallet; one attempt per page load; 1.00 USDC cap; disabled by default.",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"id": "payment-intent-playground",
|
|
55
|
+
"path": "examples/payment-intent-playground",
|
|
56
|
+
"purpose": "Prepare reviewable payment-intent JSON with amount, recipient, memo, expiry, and local approval states.",
|
|
57
|
+
"boundary": "Local-only intent drafting; no wallet connection and no broadcast.",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "receipt-verifier-playground",
|
|
61
|
+
"path": "examples/receipt-verifier-playground",
|
|
62
|
+
"purpose": "Verify receipt fields and decode pinned Arc Testnet USDC Transfer logs locally.",
|
|
63
|
+
"boundary": "Read-only local verification; settlement claims are always false.",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"id": "transaction-status-playground",
|
|
67
|
+
"path": "examples/transaction-status-playground",
|
|
68
|
+
"purpose": "Look up the status of an Arc Testnet transaction hash with chain-first validation.",
|
|
69
|
+
"boundary": "Read-only; wrong-chain results stop before RPC; no signing or broadcast.",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"id": "x402-local-challenge-server",
|
|
73
|
+
"path": "examples/x402-local-challenge-server",
|
|
74
|
+
"purpose": "Run a local x402-style paid-agent challenge/response boundary over loopback HTTP.",
|
|
75
|
+
"boundary": "Loopback-only by default; no wallet required; no real settlement or mainnet mode.",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "arc-agent-treasury-lab",
|
|
79
|
+
"path": "examples/arc-agent-treasury-lab",
|
|
80
|
+
"purpose": "Simulate an agent treasury with x402 revenue, bounded compute spending, and deterministic verify/repair loops.",
|
|
81
|
+
"boundary": "Local simulation only; no real funds, no wallet, no broadcast.",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "agent-commerce-components",
|
|
85
|
+
"path": "examples/agent-commerce-components",
|
|
86
|
+
"purpose": "Static UI components for agent-commerce screens.",
|
|
87
|
+
"boundary": "Static HTML/JS demo; no network or wallet access.",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "agent-commerce-flows",
|
|
91
|
+
"path": "examples/agent-commerce-flows",
|
|
92
|
+
"purpose": "Interactive flow library for agent-commerce scenarios.",
|
|
93
|
+
"boundary": "Static local demo; no signing or broadcast.",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"id": "agent-commerce-review-packet",
|
|
97
|
+
"path": "examples/agent-commerce-review-packet",
|
|
98
|
+
"purpose": "Generate a human-readable review packet for agent-commerce terms.",
|
|
99
|
+
"boundary": "Read-only local preview; no external calls.",
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "agent-identity-profile-preview",
|
|
103
|
+
"path": "examples/agent-identity-profile-preview",
|
|
104
|
+
"purpose": "Preview ERC-8004-style agent identity metadata before registration.",
|
|
105
|
+
"boundary": "Static local preview; no onchain registration.",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"id": "job-escrow-simulator",
|
|
109
|
+
"path": "examples/job-escrow-simulator",
|
|
110
|
+
"purpose": "Simulate an ERC-8183-style job escrow lifecycle locally.",
|
|
111
|
+
"boundary": "Local simulation; no real funds or dispute resolution.",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"id": "receipt-viewer",
|
|
115
|
+
"path": "examples/receipt-viewer",
|
|
116
|
+
"purpose": "Read-only viewer for Arc Testnet payment receipts and USDC Transfer logs.",
|
|
117
|
+
"boundary": "Read-only; no signing, no broadcast, settlement claims false.",
|
|
118
|
+
},
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def fail(message: str) -> NoReturn:
|
|
123
|
+
print(f"error: {message}", file=sys.stderr)
|
|
124
|
+
raise SystemExit(1)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def git_info() -> tuple[str, str]:
|
|
128
|
+
"""Return (head_commit_sha, current_branch) without touching the network."""
|
|
129
|
+
head = "unknown"
|
|
130
|
+
branch = "unknown"
|
|
131
|
+
for argv, name in (
|
|
132
|
+
(["git", "rev-parse", "HEAD"], "head"),
|
|
133
|
+
(["git", "rev-parse", "--abbrev-ref", "HEAD"], "branch"),
|
|
134
|
+
):
|
|
135
|
+
try:
|
|
136
|
+
result = subprocess.run(
|
|
137
|
+
argv,
|
|
138
|
+
cwd=ROOT,
|
|
139
|
+
capture_output=True,
|
|
140
|
+
text=True,
|
|
141
|
+
check=False,
|
|
142
|
+
timeout=10,
|
|
143
|
+
)
|
|
144
|
+
if result.returncode == 0:
|
|
145
|
+
value = result.stdout.strip()
|
|
146
|
+
if name == "head":
|
|
147
|
+
head = value
|
|
148
|
+
else:
|
|
149
|
+
branch = value
|
|
150
|
+
except (OSError, subprocess.TimeoutExpired):
|
|
151
|
+
pass
|
|
152
|
+
return head, branch
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def render_arc_testnet_facts_md(facts: dict[str, Any]) -> str:
|
|
156
|
+
network = facts.get("network", {})
|
|
157
|
+
erc20 = facts.get("erc20Usdc", {})
|
|
158
|
+
native = facts.get("nativeGas", {})
|
|
159
|
+
policy = facts.get("policy", {})
|
|
160
|
+
lines = [
|
|
161
|
+
"# Arc Testnet Facts",
|
|
162
|
+
"",
|
|
163
|
+
"Reviewed offline source of truth for Arc Testnet implementation.",
|
|
164
|
+
"",
|
|
165
|
+
"## Network",
|
|
166
|
+
"",
|
|
167
|
+
f"- **Name:** {network.get('name')}",
|
|
168
|
+
f"- **Chain ID (decimal):** {network.get('chainId')}",
|
|
169
|
+
f"- **Chain ID (hex):** {network.get('chainIdHex')}",
|
|
170
|
+
f"- **RPC URL (label):** {network.get('rpcUrl')}",
|
|
171
|
+
f"- **Explorer URL (label):** {network.get('explorerUrl')}",
|
|
172
|
+
"",
|
|
173
|
+
"## Native gas token",
|
|
174
|
+
"",
|
|
175
|
+
f"- **Symbol:** {native.get('symbol')}",
|
|
176
|
+
f"- **Decimals:** {native.get('decimals')}",
|
|
177
|
+
"",
|
|
178
|
+
"## ERC-20 USDC",
|
|
179
|
+
"",
|
|
180
|
+
f"- **Symbol:** {erc20.get('symbol')}",
|
|
181
|
+
f"- **Address:** {erc20.get('address')}",
|
|
182
|
+
f"- **Decimals:** {erc20.get('decimals')}",
|
|
183
|
+
"",
|
|
184
|
+
"## Policy",
|
|
185
|
+
"",
|
|
186
|
+
f"- **Mainnet supported:** {policy.get('mainnetSupported')}",
|
|
187
|
+
f"- **Wallet required:** {policy.get('walletRequired')}",
|
|
188
|
+
f"- **Network checks opt-in:** {policy.get('networkChecksOptIn')}",
|
|
189
|
+
f"- **Recheck before publication:** {policy.get('recheckBeforePublication')}",
|
|
190
|
+
"",
|
|
191
|
+
"## Scope disclaimer",
|
|
192
|
+
"",
|
|
193
|
+
"These facts describe the Arc Testnet only. Mainnet, custody, production",
|
|
194
|
+
"deployment, and live settlement are out of scope for this builder kit.",
|
|
195
|
+
"",
|
|
196
|
+
DISCLAIMER,
|
|
197
|
+
"",
|
|
198
|
+
]
|
|
199
|
+
return "\n".join(lines)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def render_readiness_checklist_md() -> str:
|
|
203
|
+
lines = [
|
|
204
|
+
"# Release Readiness Checklist",
|
|
205
|
+
"",
|
|
206
|
+
"Run these checks before sharing a release packet or opening a release review.",
|
|
207
|
+
"",
|
|
208
|
+
"## Local verification commands",
|
|
209
|
+
"",
|
|
210
|
+
"- [ ] `python3 scripts/test_all.py` — full local regression suite passes.",
|
|
211
|
+
"- [ ] `python3 scripts/validate_repo.py` — repository validation passes.",
|
|
212
|
+
"- [ ] `python3 scripts/test_public_claims.py` — public claims are consistent.",
|
|
213
|
+
"- [ ] `python3 scripts/arc_builder_doctor.py` — local health report is pass/warn.",
|
|
214
|
+
"- [ ] `python3 scripts/validate_arc_testnet_facts.py` — Arc Testnet facts are consistent.",
|
|
215
|
+
"",
|
|
216
|
+
"## Docs and public-site checks",
|
|
217
|
+
"",
|
|
218
|
+
"- [ ] README describes the current MVP, quickstart, and safety boundaries.",
|
|
219
|
+
"- [ ] Docs viewer links resolve and no malicious Markdown HTML escapes.",
|
|
220
|
+
"- [ ] GitHub Pages site previewed locally or via published Pages URL.",
|
|
221
|
+
"",
|
|
222
|
+
"## Wallet and signing boundary",
|
|
223
|
+
"",
|
|
224
|
+
"- [ ] No private keys, seed phrases, or wallet credentials are committed.",
|
|
225
|
+
"- [ ] Wallet signing happens only in the guarded send lab and only through an injected user wallet.",
|
|
226
|
+
"- [ ] Local examples do not connect a wallet on page load.",
|
|
227
|
+
"",
|
|
228
|
+
"## x402 / local commerce boundary",
|
|
229
|
+
"",
|
|
230
|
+
"- [ ] x402 demo config keeps `X402_DEMO_MAINNET_ENABLED=false`.",
|
|
231
|
+
"- [ ] Local x402 HTTP mode rejects non-loopback hosts.",
|
|
232
|
+
"- [ ] No production verifier credentials are present.",
|
|
233
|
+
"",
|
|
234
|
+
"## Receipt matcher / evidence export boundary",
|
|
235
|
+
"",
|
|
236
|
+
"- [ ] Receipt matcher verdicts are local and read-only.",
|
|
237
|
+
"- [ ] Evidence export uses browser Blob/download only; no upload, no telemetry, no storage.",
|
|
238
|
+
"- [ ] Mismatch/revert/not-found verdicts do not claim settlement.",
|
|
239
|
+
"",
|
|
240
|
+
"## CI summary boundary",
|
|
241
|
+
"",
|
|
242
|
+
"- [ ] Validate workflow publishes the Arc Builder Doctor Markdown summary.",
|
|
243
|
+
"- [ ] Workflow permissions remain `contents: read` for the validate job.",
|
|
244
|
+
"",
|
|
245
|
+
"## Explicit non-perform declaration",
|
|
246
|
+
"",
|
|
247
|
+
"This packet and the repository it describes do **not**:",
|
|
248
|
+
"",
|
|
249
|
+
"- connect to or operate a wallet;",
|
|
250
|
+
"- sign or broadcast transactions;",
|
|
251
|
+
"- hold custody of user funds or private keys;",
|
|
252
|
+
"- target any mainnet;",
|
|
253
|
+
"- claim live settlement, payment finality, or production readiness.",
|
|
254
|
+
"",
|
|
255
|
+
DISCLAIMER,
|
|
256
|
+
"",
|
|
257
|
+
]
|
|
258
|
+
return "\n".join(lines)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def render_examples_index_md() -> str:
|
|
262
|
+
lines = [
|
|
263
|
+
"# Examples Index",
|
|
264
|
+
"",
|
|
265
|
+
"Local builder-kit examples and their safety boundaries.",
|
|
266
|
+
"",
|
|
267
|
+
"| Example | Path | Purpose | Safety Boundary |",
|
|
268
|
+
"| --- | --- | --- | --- |",
|
|
269
|
+
]
|
|
270
|
+
for example in EXAMPLES:
|
|
271
|
+
purpose = example["purpose"].replace("\n", " ").replace("|", "\\|")
|
|
272
|
+
boundary = example["boundary"].replace("\n", " ").replace("|", "\\|")
|
|
273
|
+
lines.append(
|
|
274
|
+
f"| {example['id']} | `{example['path']}` | {purpose} | {boundary} |"
|
|
275
|
+
)
|
|
276
|
+
lines.extend(
|
|
277
|
+
[
|
|
278
|
+
"",
|
|
279
|
+
"## Shared invariants",
|
|
280
|
+
"",
|
|
281
|
+
"- Examples are local-first and wallet-free unless explicitly labelled as a guarded wallet lab.",
|
|
282
|
+
"- No example signs or broadcasts on page load.",
|
|
283
|
+
"- No example claims mainnet readiness or live settlement.",
|
|
284
|
+
"",
|
|
285
|
+
DISCLAIMER,
|
|
286
|
+
"",
|
|
287
|
+
]
|
|
288
|
+
)
|
|
289
|
+
return "\n".join(lines)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def build_release_packet_json(
|
|
293
|
+
facts: dict[str, Any],
|
|
294
|
+
outputs: list[str],
|
|
295
|
+
repo_head: str,
|
|
296
|
+
branch: str,
|
|
297
|
+
doctor_report: dict[str, Any] | None,
|
|
298
|
+
) -> dict[str, Any]:
|
|
299
|
+
return {
|
|
300
|
+
"kind": KIND,
|
|
301
|
+
"schemaVersion": SCHEMA_VERSION,
|
|
302
|
+
"generatedAt": datetime.now(timezone.utc).replace(microsecond=0).isoformat(),
|
|
303
|
+
"generator": "scripts/generate_arc_release_packet.py",
|
|
304
|
+
"repoHead": repo_head,
|
|
305
|
+
"branch": branch,
|
|
306
|
+
"arcFacts": {
|
|
307
|
+
"network": facts.get("network", {}),
|
|
308
|
+
"nativeGas": facts.get("nativeGas", {}),
|
|
309
|
+
"erc20Usdc": facts.get("erc20Usdc", {}),
|
|
310
|
+
"policy": facts.get("policy", {}),
|
|
311
|
+
},
|
|
312
|
+
"outputs": outputs,
|
|
313
|
+
"doctorOverallStatus": doctor_report["overallStatus"] if doctor_report else "unknown",
|
|
314
|
+
"safetyBoundaries": {
|
|
315
|
+
"walletConnected": False,
|
|
316
|
+
"privateKeysAccepted": False,
|
|
317
|
+
"signingEnabled": False,
|
|
318
|
+
"transactionBroadcast": False,
|
|
319
|
+
"custodyEnabled": False,
|
|
320
|
+
"mainnetEnabled": False,
|
|
321
|
+
"autonomousSpending": False,
|
|
322
|
+
"networkChecksOptIn": True,
|
|
323
|
+
"localOnly": True,
|
|
324
|
+
"secretsRead": False,
|
|
325
|
+
},
|
|
326
|
+
"recommendedChecks": [
|
|
327
|
+
"python3 scripts/test_all.py",
|
|
328
|
+
"python3 scripts/validate_repo.py",
|
|
329
|
+
"python3 scripts/test_public_claims.py",
|
|
330
|
+
"python3 scripts/arc_builder_doctor.py",
|
|
331
|
+
"python3 scripts/validate_arc_testnet_facts.py",
|
|
332
|
+
],
|
|
333
|
+
"disclaimer": DISCLAIMER,
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def run_doctor_report() -> tuple[dict[str, Any], str]:
|
|
338
|
+
"""Build a local-only Arc Builder Doctor report and render Markdown.
|
|
339
|
+
|
|
340
|
+
Importing the doctor module re-uses its existing orchestration. Network
|
|
341
|
+
checks are never enabled here.
|
|
342
|
+
"""
|
|
343
|
+
from arc_builder_kit.doctor import Options, build_report, render_markdown
|
|
344
|
+
|
|
345
|
+
options = Options()
|
|
346
|
+
report = build_report(options)
|
|
347
|
+
markdown = render_markdown(report)
|
|
348
|
+
return report, markdown
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
352
|
+
parser = argparse.ArgumentParser(
|
|
353
|
+
prog="generate_arc_release_packet",
|
|
354
|
+
description=(
|
|
355
|
+
"Generate a local, read-only Arc Builder release packet for "
|
|
356
|
+
"PR/release review. No wallet, signing, broadcast, custody, "
|
|
357
|
+
"mainnet, secrets, or network calls are used by default."
|
|
358
|
+
),
|
|
359
|
+
)
|
|
360
|
+
parser.add_argument(
|
|
361
|
+
"--out",
|
|
362
|
+
type=Path,
|
|
363
|
+
default=DEFAULT_OUT,
|
|
364
|
+
help="output directory (default: .arc-release-packet)",
|
|
365
|
+
)
|
|
366
|
+
parser.add_argument(
|
|
367
|
+
"--force",
|
|
368
|
+
action="store_true",
|
|
369
|
+
help="overwrite an existing output directory",
|
|
370
|
+
)
|
|
371
|
+
parser.add_argument(
|
|
372
|
+
"--format",
|
|
373
|
+
choices=("markdown", "json", "all"),
|
|
374
|
+
default="all",
|
|
375
|
+
help="artifact formats to generate (default: all)",
|
|
376
|
+
)
|
|
377
|
+
return parser.parse_args(argv)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def validate_output_dir(out_dir: Path) -> Path:
|
|
381
|
+
"""Resolve and confirm output stays inside the reviewed output root."""
|
|
382
|
+
try:
|
|
383
|
+
resolved = out_dir.resolve(strict=False)
|
|
384
|
+
except (OSError, RuntimeError) as exc:
|
|
385
|
+
fail(f"cannot resolve output path: {exc}")
|
|
386
|
+
|
|
387
|
+
# resolve() follows symlinks, so symlink escapes fail.
|
|
388
|
+
try:
|
|
389
|
+
resolved.relative_to(DEFAULT_OUTPUT_ROOT.resolve())
|
|
390
|
+
except ValueError:
|
|
391
|
+
fail(f"output path must be inside output root: {resolved}")
|
|
392
|
+
|
|
393
|
+
if resolved == DEFAULT_OUTPUT_ROOT.resolve():
|
|
394
|
+
fail("refusing to use the output root as the output directory")
|
|
395
|
+
|
|
396
|
+
return resolved
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def main(argv: list[str] | None = None) -> int:
|
|
400
|
+
args = parse_args(argv)
|
|
401
|
+
out_dir = validate_output_dir(args.out)
|
|
402
|
+
|
|
403
|
+
if out_dir.exists():
|
|
404
|
+
if not args.force:
|
|
405
|
+
fail(
|
|
406
|
+
f"output directory already exists: {out_dir}; "
|
|
407
|
+
"use --force to overwrite"
|
|
408
|
+
)
|
|
409
|
+
shutil.rmtree(out_dir)
|
|
410
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
411
|
+
|
|
412
|
+
facts_path = CONFIG_DIR / "arc_testnet.facts.json"
|
|
413
|
+
try:
|
|
414
|
+
facts = json.loads(facts_path.read_text(encoding="utf-8"))
|
|
415
|
+
except (OSError, ValueError) as exc:
|
|
416
|
+
fail(f"failed to read Arc Testnet facts: {exc}")
|
|
417
|
+
|
|
418
|
+
doctor_report: dict[str, Any] | None = None
|
|
419
|
+
doctor_md = ""
|
|
420
|
+
try:
|
|
421
|
+
doctor_report, doctor_md = run_doctor_report()
|
|
422
|
+
except Exception as exc: # pragma: no cover - orchestrator failure surfaces clearly
|
|
423
|
+
fail(f"Arc Builder Doctor failed: {exc}")
|
|
424
|
+
|
|
425
|
+
outputs: list[str] = []
|
|
426
|
+
written: dict[str, Path] = {}
|
|
427
|
+
|
|
428
|
+
if args.format in ("markdown", "all"):
|
|
429
|
+
written["arc-builder-doctor.md"] = out_dir / "arc-builder-doctor.md"
|
|
430
|
+
written["arc-testnet-facts.md"] = out_dir / "arc-testnet-facts.md"
|
|
431
|
+
written["readiness-checklist.md"] = out_dir / "readiness-checklist.md"
|
|
432
|
+
written["examples-index.md"] = out_dir / "examples-index.md"
|
|
433
|
+
|
|
434
|
+
if args.format in ("json", "all"):
|
|
435
|
+
written["arc-testnet-facts.json"] = out_dir / "arc-testnet-facts.json"
|
|
436
|
+
|
|
437
|
+
content_map = {
|
|
438
|
+
"arc-builder-doctor.md": doctor_md,
|
|
439
|
+
"arc-testnet-facts.md": render_arc_testnet_facts_md(facts),
|
|
440
|
+
"arc-testnet-facts.json": json.dumps(facts, indent=2) + "\n",
|
|
441
|
+
"readiness-checklist.md": render_readiness_checklist_md(),
|
|
442
|
+
"examples-index.md": render_examples_index_md(),
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
for name, path in written.items():
|
|
446
|
+
path.write_text(content_map[name], encoding="utf-8")
|
|
447
|
+
outputs.append(name)
|
|
448
|
+
|
|
449
|
+
if args.format in ("json", "all"):
|
|
450
|
+
packet = build_release_packet_json(
|
|
451
|
+
facts=facts,
|
|
452
|
+
outputs=outputs + ["release-packet.json"],
|
|
453
|
+
repo_head=git_info()[0],
|
|
454
|
+
branch=git_info()[1],
|
|
455
|
+
doctor_report=doctor_report,
|
|
456
|
+
)
|
|
457
|
+
(out_dir / "release-packet.json").write_text(
|
|
458
|
+
json.dumps(packet, indent=2) + "\n", encoding="utf-8"
|
|
459
|
+
)
|
|
460
|
+
outputs.append("release-packet.json")
|
|
461
|
+
|
|
462
|
+
print(f"Generated Arc Builder release packet in {out_dir}")
|
|
463
|
+
for name in outputs:
|
|
464
|
+
print(f" - {name}")
|
|
465
|
+
return 0
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
if __name__ == "__main__":
|
|
469
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Arc Builder Starter Templates
|
|
2
|
+
|
|
3
|
+
Dependency-free project scaffolds for the Arc MCP Builder Assistant.
|
|
4
|
+
|
|
5
|
+
| Template | Files | Use |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| `payment-intent-starter` | `index.html`, `index.js` | Static payment-intent UI. |
|
|
8
|
+
| `x402-agent-starter` | `server.py` | Local x402 paid-agent boundary. |
|
|
9
|
+
| `job-escrow-starter` | `index.html`, `index.js` | Static ERC-8183-style escrow UI. |
|
|
10
|
+
|
|
11
|
+
## Scaffold a new project
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
python3 scripts/arc_builder_cli.py scaffold payment-intent-starter ./my-payment-demo
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or via the Arc Builder MCP server with the `scaffold_project` tool.
|
|
18
|
+
|
|
19
|
+
## Safety
|
|
20
|
+
|
|
21
|
+
All templates are:
|
|
22
|
+
- Arc Testnet only.
|
|
23
|
+
- Wallet-free and secret-free.
|
|
24
|
+
- Human-approved at every spending-related step.
|
|
25
|
+
- Not production-ready without a separate reviewed integration.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Arc Job Escrow Starter
|
|
2
|
+
|
|
3
|
+
Minimal static ERC-8183-style job escrow UI for Arc Testnet. User posts a job, agent accepts, user funds, agent submits work, user approves release.
|
|
4
|
+
|
|
5
|
+
This is a starter template from the Arc MCP Builder Assistant. It is wallet-free and does not sign or broadcast anything.
|
|
6
|
+
|
|
7
|
+
## Files
|
|
8
|
+
|
|
9
|
+
- `index.html` — job escrow simulator UI.
|
|
10
|
+
|
|
11
|
+
## Use
|
|
12
|
+
|
|
13
|
+
Open `index.html` in a browser or serve it locally:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
python3 -m http.server 8092
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Then open http://localhost:8092/.
|
|
20
|
+
|
|
21
|
+
## Safety notes
|
|
22
|
+
|
|
23
|
+
- No private keys or funds move in this starter.
|
|
24
|
+
- Status transitions are local and require explicit user clicks.
|
|
25
|
+
- Production handoff requires a reviewed smart-contract escrow on Arc Testnet.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'none'; form-action 'none'; upgrade-insecure-requests" />
|
|
7
|
+
<title>Arc Job Escrow Starter</title>
|
|
8
|
+
<meta name="description" content="Minimal Arc Testnet job escrow starter." />
|
|
9
|
+
<style>
|
|
10
|
+
:root { color-scheme: dark; font-family: Inter, ui-sans-serif, system-ui, sans-serif; }
|
|
11
|
+
body { margin: 0; min-height: 100vh; display: grid; place-items: center; background: radial-gradient(circle at top right, #2a1b7a 0, #080914 45%, #05060a 100%); color: #f7f7ff; }
|
|
12
|
+
main { width: min(560px, calc(100vw - 32px)); border: 1px solid rgba(255,255,255,.14); border-radius: 24px; padding: 28px; background: rgba(10,12,24,.82); box-shadow: 0 24px 80px rgba(0,0,0,.35); }
|
|
13
|
+
h1 { margin: 0 0 6px; font-size: 28px; }
|
|
14
|
+
p { color: #cbd2ff; margin: 0 0 18px; }
|
|
15
|
+
.timeline { list-style: none; padding: 0; margin: 0 0 20px; }
|
|
16
|
+
.timeline li { padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,.1); color: #8e95bc; }
|
|
17
|
+
.timeline li.active { color: #f7f7ff; font-weight: 700; }
|
|
18
|
+
.timeline li.done { color: #7cf7a8; }
|
|
19
|
+
button { border: 0; border-radius: 999px; padding: 14px 20px; font-weight: 800; cursor: pointer; background: #7cf7a8; color: #080914; }
|
|
20
|
+
button:disabled { opacity: .4; cursor: not-allowed; }
|
|
21
|
+
.muted { font-size: 12px; color: #8e95bc; margin-top: 14px; }
|
|
22
|
+
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } *, *::before, *::after { animation: none !important; transition: none !important; } }
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<main>
|
|
27
|
+
<h1>Job escrow</h1>
|
|
28
|
+
<p>ERC-8183-style flow on Arc Testnet. All actions require explicit clicks.</p>
|
|
29
|
+
<ul class="timeline" id="timeline">
|
|
30
|
+
<li id="s-post" class="active">Job posted</li>
|
|
31
|
+
<li id="s-accept">Agent accepted</li>
|
|
32
|
+
<li id="s-fund">Job funded (human-approved)</li>
|
|
33
|
+
<li id="s-submit">Work submitted</li>
|
|
34
|
+
<li id="s-release">Payout released (human-approved)</li>
|
|
35
|
+
</ul>
|
|
36
|
+
<button id="next">Next step</button>
|
|
37
|
+
<p class="muted">This starter does not sign or broadcast transactions.</p>
|
|
38
|
+
</main>
|
|
39
|
+
<script src="./index.js" defer></script>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Minimal Arc Job Escrow Starter - dependency-free local interactions only.
|
|
2
|
+
document.getElementById('next').addEventListener('click', advance);
|
|
3
|
+
const steps = ['s-post', 's-accept', 's-fund', 's-submit', 's-release'];
|
|
4
|
+
let index = 0;
|
|
5
|
+
function advance() {
|
|
6
|
+
if (index < steps.length - 1) {
|
|
7
|
+
document.getElementById(steps[index]).className = 'done';
|
|
8
|
+
index++;
|
|
9
|
+
document.getElementById(steps[index]).className = 'active';
|
|
10
|
+
}
|
|
11
|
+
if (index === steps.length - 1) {
|
|
12
|
+
document.getElementById('next').disabled = true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Arc Payment Intent Starter
|
|
2
|
+
|
|
3
|
+
Minimal static demo: an AI agent prepares a USDC payment intent on Arc Testnet and a human reviews/approves it.
|
|
4
|
+
|
|
5
|
+
This is a starter template from the Arc MCP Builder Assistant. It is wallet-free and does not sign or broadcast anything.
|
|
6
|
+
|
|
7
|
+
## Files
|
|
8
|
+
|
|
9
|
+
- `index.html` — reviewable payment-intent UI.
|
|
10
|
+
|
|
11
|
+
## Use
|
|
12
|
+
|
|
13
|
+
Open `index.html` in a browser or serve it locally:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
python3 -m http.server 8090
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Then open http://localhost:8090/.
|
|
20
|
+
|
|
21
|
+
## Safety notes
|
|
22
|
+
|
|
23
|
+
- No private keys, seed phrases, or API keys are stored or requested.
|
|
24
|
+
- Amounts are local mock values pinned to Arc Testnet/USDC semantics.
|
|
25
|
+
- Production handoff requires a separate reviewed integration with Circle Gateway or an injected wallet.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'none'; form-action 'none'; upgrade-insecure-requests" />
|
|
7
|
+
<title>Arc Payment Intent Starter</title>
|
|
8
|
+
<meta name="description" content="Minimal Arc Testnet USDC payment-intent starter." />
|
|
9
|
+
<style>
|
|
10
|
+
:root { color-scheme: dark; font-family: Inter, ui-sans-serif, system-ui, sans-serif; }
|
|
11
|
+
body { margin: 0; min-height: 100vh; display: grid; place-items: center; background: radial-gradient(circle at top, #1b2d7a 0, #080914 40%, #05060a 100%); color: #f7f7ff; }
|
|
12
|
+
main { width: min(520px, calc(100vw - 32px)); border: 1px solid rgba(255,255,255,.14); border-radius: 24px; padding: 28px; background: rgba(10,12,24,.82); box-shadow: 0 24px 80px rgba(0,0,0,.35); }
|
|
13
|
+
h1 { margin: 0 0 6px; font-size: 28px; }
|
|
14
|
+
p { color: #cbd2ff; margin: 0 0 18px; }
|
|
15
|
+
.row { display: flex; justify-content: space-between; padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,.1); }
|
|
16
|
+
.label { color: #8e95bc; }
|
|
17
|
+
.value { font-weight: 700; }
|
|
18
|
+
.actions { display: flex; gap: 12px; margin-top: 20px; }
|
|
19
|
+
button { border: 0; border-radius: 999px; padding: 14px 20px; font-weight: 800; cursor: pointer; background: #f7f7ff; color: #080914; }
|
|
20
|
+
.secondary { background: rgba(255,255,255,.12); color: #f7f7ff; }
|
|
21
|
+
.muted { font-size: 12px; color: #8e95bc; margin-top: 14px; }
|
|
22
|
+
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } *, *::before, *::after { animation: none !important; transition: none !important; } }
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<main>
|
|
27
|
+
<h1>Payment intent</h1>
|
|
28
|
+
<p>Agent-prepared USDC request on Arc Testnet. Review before any wallet action.</p>
|
|
29
|
+
<div class="row"><span class="label">Network</span><span class="value">Arc Testnet</span></div>
|
|
30
|
+
<div class="row"><span class="label">Asset</span><span class="value">USDC</span></div>
|
|
31
|
+
<div class="row"><span class="label">Amount</span><span class="value">0.10 USDC</span></div>
|
|
32
|
+
<div class="row"><span class="label">Recipient</span><span class="value">0xA11CE0...0000</span></div>
|
|
33
|
+
<div class="row"><span class="label">Memo</span><span class="value">Demo starter</span></div>
|
|
34
|
+
<div class="actions">
|
|
35
|
+
<button id="reject" class="secondary">Reject</button>
|
|
36
|
+
<button id="approve">Approve</button>
|
|
37
|
+
</div>
|
|
38
|
+
<p class="muted">This starter does not sign or broadcast transactions.</p>
|
|
39
|
+
</main>
|
|
40
|
+
<script src="./index.js" defer></script>
|
|
41
|
+
</body>
|
|
42
|
+
</html>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Minimal Arc Payment Intent Starter - dependency-free local interactions only.
|
|
2
|
+
document.getElementById('reject').addEventListener('click', function () {
|
|
3
|
+
alert('Rejected');
|
|
4
|
+
});
|
|
5
|
+
document.getElementById('approve').addEventListener('click', function () {
|
|
6
|
+
alert('Approved for external wallet handoff');
|
|
7
|
+
});
|