web3skill 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/dist/archives/web3-audit-orchestrator.skill +0 -0
  4. package/dist/archives/web3-audit-reporting.skill +0 -0
  5. package/dist/archives/web3-fuzzing-and-invariants.skill +0 -0
  6. package/dist/archives/web3-native-operator.skill +0 -0
  7. package/dist/archives/web3-repo-heuristics.skill +0 -0
  8. package/dist/archives/web3-research-and-market-intel.skill +0 -0
  9. package/dist/archives/web3-risk-gate.skill +0 -0
  10. package/dist/archives/web3-service-orchestrator.skill +0 -0
  11. package/dist/archives/web3-static-analysis-runner.skill +0 -0
  12. package/dist/archives/web3-trace-and-state-analysis.skill +0 -0
  13. package/dist/archives/web3-transaction-simulator.skill +0 -0
  14. package/dist/archives/web3-wallet-operator.skill +0 -0
  15. package/dist/manifest.json +170 -0
  16. package/dist/skills/web3-audit-orchestrator/SKILL.md +79 -0
  17. package/dist/skills/web3-audit-orchestrator/references/ADAPTER_CONSUMPTION_MAP.md +15 -0
  18. package/dist/skills/web3-audit-orchestrator/references/OUTPUT_TEMPLATE.md +52 -0
  19. package/dist/skills/web3-audit-orchestrator/references/REVIEW_STATE_MACHINE.md +25 -0
  20. package/dist/skills/web3-audit-orchestrator/scripts/render_audit_review.py +95 -0
  21. package/dist/skills/web3-audit-reporting/SKILL.md +77 -0
  22. package/dist/skills/web3-audit-reporting/references/FINDING_TEMPLATE.md +54 -0
  23. package/dist/skills/web3-audit-reporting/references/REPORT_TEMPLATE.md +58 -0
  24. package/dist/skills/web3-audit-reporting/references/RETEST_TEMPLATE.md +35 -0
  25. package/dist/skills/web3-audit-reporting/references/SEVERITY_RUBRIC.md +75 -0
  26. package/dist/skills/web3-fuzzing-and-invariants/SKILL.md +68 -0
  27. package/dist/skills/web3-fuzzing-and-invariants/references/ADAPTER_CONSUMPTION_MAP.md +14 -0
  28. package/dist/skills/web3-fuzzing-and-invariants/references/OUTPUT_TEMPLATE.md +40 -0
  29. package/dist/skills/web3-fuzzing-and-invariants/references/READINESS_AND_FAILURES.md +25 -0
  30. package/dist/skills/web3-fuzzing-and-invariants/scripts/render_fuzz_summary.py +64 -0
  31. package/dist/skills/web3-native-operator/SKILL.md +218 -0
  32. package/dist/skills/web3-native-operator/references/EXECUTION_BUNDLE_TEMPLATE.md +47 -0
  33. package/dist/skills/web3-native-operator/references/OPERATOR_BUNDLE_TEMPLATE.md +39 -0
  34. package/dist/skills/web3-native-operator/references/POSTTRADE_FOLLOWUP_BUNDLE_TEMPLATE.md +35 -0
  35. package/dist/skills/web3-native-operator/references/POSTTRADE_WATCH_TEMPLATE.md +34 -0
  36. package/dist/skills/web3-native-operator/references/PRETRADE_PACKET_TEMPLATE.md +34 -0
  37. package/dist/skills/web3-native-operator/references/ROUTE_RECIPES.md +140 -0
  38. package/dist/skills/web3-native-operator/references/ROUTING_STATE_MACHINE.md +73 -0
  39. package/dist/skills/web3-native-operator/references/WATCH_CRON_REQUEST_TEMPLATE.md +26 -0
  40. package/dist/skills/web3-native-operator/references/WATCH_FOLLOWUP_BUNDLE_TEMPLATE.md +35 -0
  41. package/dist/skills/web3-native-operator/references/WATCH_HEARTBEAT_TEMPLATE.md +31 -0
  42. package/dist/skills/web3-native-operator/scripts/apply_followup_bundle_to_heartbeat.py +118 -0
  43. package/dist/skills/web3-native-operator/scripts/render_execution_bundle.py +259 -0
  44. package/dist/skills/web3-native-operator/scripts/render_operator_bundle.py +800 -0
  45. package/dist/skills/web3-native-operator/scripts/render_posttrade_followup_bundle.py +118 -0
  46. package/dist/skills/web3-native-operator/scripts/render_posttrade_watch_status.py +125 -0
  47. package/dist/skills/web3-native-operator/scripts/render_pretrade_packet.py +205 -0
  48. package/dist/skills/web3-native-operator/scripts/render_watch_cron_request.py +88 -0
  49. package/dist/skills/web3-native-operator/scripts/render_watch_followup_bundle.py +118 -0
  50. package/dist/skills/web3-native-operator/scripts/render_watch_heartbeat.py +52 -0
  51. package/dist/skills/web3-repo-heuristics/SKILL.md +37 -0
  52. package/dist/skills/web3-repo-heuristics/references/FOUNDRY.md +49 -0
  53. package/dist/skills/web3-repo-heuristics/references/HARDHAT.md +47 -0
  54. package/dist/skills/web3-repo-heuristics/references/VYPER.md +26 -0
  55. package/dist/skills/web3-research-and-market-intel/SKILL.md +138 -0
  56. package/dist/skills/web3-research-and-market-intel/references/ADAPTER_CONSUMPTION_MAP.md +66 -0
  57. package/dist/skills/web3-research-and-market-intel/references/EVIDENCE_QUALITY.md +27 -0
  58. package/dist/skills/web3-research-and-market-intel/references/OUTPUT_TEMPLATE.md +37 -0
  59. package/dist/skills/web3-research-and-market-intel/references/PORTFOLIO_STATUS_TEMPLATE.md +51 -0
  60. package/dist/skills/web3-research-and-market-intel/references/WATCH_STATUS_TEMPLATE.md +39 -0
  61. package/dist/skills/web3-research-and-market-intel/scripts/render_portfolio_status.py +85 -0
  62. package/dist/skills/web3-research-and-market-intel/scripts/render_research_brief.py +58 -0
  63. package/dist/skills/web3-research-and-market-intel/scripts/render_watch_status.py +70 -0
  64. package/dist/skills/web3-risk-gate/SKILL.md +100 -0
  65. package/dist/skills/web3-risk-gate/references/OUTPUT_TEMPLATE.md +72 -0
  66. package/dist/skills/web3-risk-gate/references/SIGNAL_TAXONOMY.md +34 -0
  67. package/dist/skills/web3-risk-gate/scripts/merge_risk_gate_blocks.py +189 -0
  68. package/dist/skills/web3-service-orchestrator/SKILL.md +34 -0
  69. package/dist/skills/web3-static-analysis-runner/SKILL.md +76 -0
  70. package/dist/skills/web3-static-analysis-runner/references/ADAPTER_CONSUMPTION_MAP.md +13 -0
  71. package/dist/skills/web3-static-analysis-runner/references/OUTPUT_TEMPLATE.md +45 -0
  72. package/dist/skills/web3-static-analysis-runner/references/TRIAGE_BUCKETS.md +16 -0
  73. package/dist/skills/web3-static-analysis-runner/scripts/render_static_analysis_summary.py +64 -0
  74. package/dist/skills/web3-trace-and-state-analysis/SKILL.md +74 -0
  75. package/dist/skills/web3-trace-and-state-analysis/references/ADAPTER_CONSUMPTION_MAP.md +27 -0
  76. package/dist/skills/web3-trace-and-state-analysis/references/OUTPUT_TEMPLATE.md +63 -0
  77. package/dist/skills/web3-trace-and-state-analysis/references/TRACE_BACKEND_PREFLIGHT.md +47 -0
  78. package/dist/skills/web3-trace-and-state-analysis/scripts/render_trace_summary.py +99 -0
  79. package/dist/skills/web3-transaction-simulator/SKILL.md +83 -0
  80. package/dist/skills/web3-transaction-simulator/references/OUTPUT_TEMPLATE.md +86 -0
  81. package/dist/skills/web3-transaction-simulator/references/STATUS_AND_FAILURES.md +49 -0
  82. package/dist/skills/web3-transaction-simulator/scripts/merge_simulation_blocks.py +198 -0
  83. package/dist/skills/web3-wallet-operator/SKILL.md +52 -0
  84. package/dist/skills/web3-wallet-operator/references/ACTION_RECIPES.md +56 -0
  85. package/dist/skills/web3-wallet-operator/references/OUTPUT_TEMPLATE.md +43 -0
  86. package/dist/skills/web3-wallet-operator/scripts/render_wallet_operation_plan.py +101 -0
  87. package/index.js +50 -0
  88. package/package.json +36 -0
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env python3
2
+ """Render a stable Web3 research brief block."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ import sys
9
+
10
+
11
+ def build_parser() -> argparse.ArgumentParser:
12
+ parser = argparse.ArgumentParser(description="Render a Web3 research brief block.")
13
+ parser.add_argument("--question", required=True)
14
+ parser.add_argument("--freshness", choices=("fresh", "mixed", "stale"), default="mixed")
15
+ parser.add_argument("--source", action="append", default=[])
16
+ parser.add_argument("--evidence", action="append", default=[])
17
+ parser.add_argument("--cross-check", action="append", default=[])
18
+ parser.add_argument(
19
+ "--conclusion",
20
+ choices=("watch", "investigate-more", "ready-for-risk-gate", "avoid-for-now"),
21
+ required=True,
22
+ )
23
+ parser.add_argument("--next-step", action="append", default=[])
24
+ return parser
25
+
26
+
27
+ def parse_evidence(entries: list[str]) -> list[dict[str, str]]:
28
+ parsed = []
29
+ for entry in entries:
30
+ adapter, sep, detail = entry.partition(":")
31
+ if sep:
32
+ parsed.append({"adapter": adapter.strip(), "detail": detail.strip()})
33
+ else:
34
+ parsed.append({"adapter": "unknown", "detail": entry})
35
+ return parsed
36
+
37
+
38
+ def main() -> int:
39
+ args = build_parser().parse_args()
40
+ payload = {
41
+ "research_brief": {
42
+ "version": 1,
43
+ "question": args.question,
44
+ "freshness": args.freshness,
45
+ "sources_used": args.source,
46
+ "evidence": parse_evidence(args.evidence),
47
+ "cross_checks": args.cross_check,
48
+ "conclusion": args.conclusion,
49
+ "next_steps": args.next_step,
50
+ }
51
+ }
52
+ json.dump(payload, sys.stdout, ensure_ascii=False, indent=2)
53
+ sys.stdout.write("\n")
54
+ return 0
55
+
56
+
57
+ if __name__ == "__main__":
58
+ raise SystemExit(main())
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env python3
2
+ """Render a stable Web3 watch status block."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ import sys
9
+
10
+
11
+ def build_parser() -> argparse.ArgumentParser:
12
+ parser = argparse.ArgumentParser(description="Render a Web3 watch status block.")
13
+ parser.add_argument(
14
+ "--status",
15
+ choices=("ACTIVE", "TRIGGERED", "CLEARED", "UNAVAILABLE"),
16
+ required=True,
17
+ )
18
+ parser.add_argument(
19
+ "--watch-kind",
20
+ choices=("research", "portfolio", "posttrade", "trace", "venue", "execution"),
21
+ required=True,
22
+ )
23
+ parser.add_argument("--subject", required=True)
24
+ parser.add_argument("--trigger-source", default="")
25
+ parser.add_argument(
26
+ "--severity",
27
+ choices=("low", "medium", "high", "critical"),
28
+ default="medium",
29
+ )
30
+ parser.add_argument("--next-check-hint", default="")
31
+ parser.add_argument("--schedule-hint", default="")
32
+ parser.add_argument("--recommended-adapter", default="")
33
+ parser.add_argument("--evidence", action="append", default=[])
34
+ return parser
35
+
36
+
37
+ def parse_evidence(entries: list[str]) -> list[dict[str, str]]:
38
+ parsed: list[dict[str, str]] = []
39
+ for entry in entries:
40
+ adapter, sep, detail = entry.partition(":")
41
+ if sep:
42
+ parsed.append({"adapter": adapter.strip(), "detail": detail.strip()})
43
+ else:
44
+ parsed.append({"adapter": "unknown", "detail": entry})
45
+ return parsed
46
+
47
+
48
+ def main() -> int:
49
+ args = build_parser().parse_args()
50
+ payload = {
51
+ "watch_status": {
52
+ "version": 1,
53
+ "status": args.status,
54
+ "watch_kind": args.watch_kind,
55
+ "subject": args.subject,
56
+ "trigger_source": args.trigger_source,
57
+ "severity": args.severity,
58
+ "next_check_hint": args.next_check_hint,
59
+ "schedule_hint": args.schedule_hint,
60
+ "recommended_adapter": args.recommended_adapter,
61
+ "evidence": parse_evidence(args.evidence),
62
+ }
63
+ }
64
+ json.dump(payload, sys.stdout, ensure_ascii=False, indent=2)
65
+ sys.stdout.write("\n")
66
+ return 0
67
+
68
+
69
+ if __name__ == "__main__":
70
+ raise SystemExit(main())
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: web3-risk-gate
3
+ description: Pre-execution Web3 risk gate for transfers, approvals, swaps, and protocol interactions. Use before any value-moving or approval-changing action. It normalizes adapter output into ALLOW, WARN, or BLOCK.
4
+ ---
5
+
6
+ # Web3 Risk Gate
7
+
8
+ Use this skill before any transfer, approval, swap, liquidity action, or contract interaction that can move funds or grant permissions.
9
+
10
+ ## Required Adapters
11
+
12
+ Load the matching Web3 profile adapters instead of improvising:
13
+
14
+ - `security-check`
15
+ - `binance-token-audit`
16
+ - `query-token-audit`
17
+ - `query-address-info`
18
+ - `token-integration-analyzer`
19
+ - `proxy-upgrade-safety`
20
+
21
+ When consuming adapter output, prefer each adapter's `references/RISK_GATE_NORMALIZATION.md`
22
+ to keep signal names and evidence fields stable.
23
+
24
+ ## Workflow
25
+
26
+ 1. Identify the action type: transfer, approve, swap, LP, or protocol interaction.
27
+ 2. Identify the subject: token, spender, receiver, router, proxy, or external protocol.
28
+ 3. Run the relevant adapter checks.
29
+ 4. Normalize the result into one gate decision.
30
+
31
+ ## Reusable Output Contract
32
+
33
+ Always emit both:
34
+
35
+ 1. A short human-readable gate summary
36
+ 2. A normalized block that other Web3 skills can reuse
37
+
38
+ Use [references/OUTPUT_TEMPLATE.md](references/OUTPUT_TEMPLATE.md) for the exact scaffold.
39
+ If you need to map adapter findings into stable blocker/warning labels, use
40
+ [references/SIGNAL_TAXONOMY.md](references/SIGNAL_TAXONOMY.md).
41
+ When deterministic merge behavior is needed, use
42
+ [scripts/merge_risk_gate_blocks.py](scripts/merge_risk_gate_blocks.py)
43
+ to combine multiple adapter-produced `risk_gate` blocks into one conservative result.
44
+
45
+ The minimum decision fields are:
46
+
47
+ ```text
48
+ Decision: ALLOW | WARN | BLOCK
49
+ Action:
50
+ - transfer | approve | swap | liquidity | protocol-interaction
51
+ Coverage:
52
+ - complete | partial | missing
53
+ Reasons:
54
+ - concrete signal
55
+ Warnings:
56
+ - optional risk signal
57
+ Must-Do Next:
58
+ - required follow-up
59
+ Evidence:
60
+ - adapter name + exact hit
61
+ ```
62
+
63
+ The normalized block must preserve:
64
+
65
+ - decision
66
+ - action type
67
+ - chain and subject
68
+ - coverage quality
69
+ - blockers and warnings as separate lists
70
+ - next steps
71
+ - exact evidence source per signal
72
+
73
+ ## Hard Block Conditions
74
+
75
+ Block by default if any checked source confirms one of:
76
+
77
+ - honeypot / unsellable token
78
+ - risk level `5` from Binance token audit
79
+ - selfdestruct risk on live token or target contract
80
+ - hidden owner combined with mint / reclaim ownership path
81
+ - storage collision or uninitialized implementation in an upgrade path
82
+ - clear proxy takeover or arbitrary upgrade control
83
+
84
+ ## Warning Conditions
85
+
86
+ Warn and require explicit confirmation if any checked source shows:
87
+
88
+ - buy or sell tax above 10%
89
+ - proxy / upgradeable token or contract
90
+ - mintable supply or concentrated owner control
91
+ - missing verification / opaque code
92
+ - abnormal holder concentration or thin distribution
93
+
94
+ ## Guardrails
95
+
96
+ - Do not average away critical signals just because another adapter returned a lower risk score.
97
+ - If the action is a swap, require `web3-transaction-simulator` after this gate.
98
+ - If adapter coverage is missing for the target chain or token, say `coverage incomplete` instead of implying safety.
99
+ - If evidence is weak or adapter coverage is partial, downgrade certainty, not the signal itself.
100
+ - If the output will be consumed by another skill, keep the normalized block stable and do not rename fields ad hoc.
@@ -0,0 +1,72 @@
1
+ # Web3 Risk Gate Output Template
2
+
3
+ Always emit two sections in this order.
4
+
5
+ ## 1. Human Summary
6
+
7
+ ```text
8
+ Decision: BLOCK
9
+ Action:
10
+ - swap
11
+ Coverage:
12
+ - partial
13
+ Reasons:
14
+ - Honeypot risk confirmed by query-token-audit
15
+ - Proxy upgrade path is externally controlled
16
+ Warnings:
17
+ - Holder concentration is elevated
18
+ Must-Do Next:
19
+ - Do not execute this swap
20
+ - If still investigating, fetch verified source and owner privileges
21
+ Evidence:
22
+ - query-token-audit: honeypot / unsellable token flag
23
+ - proxy-upgrade-safety: arbitrary upgrade control
24
+ ```
25
+
26
+ ## 2. Normalized Block
27
+
28
+ Use this exact field layout. Omit empty optional arrays, but do not rename fields.
29
+
30
+ ```yaml
31
+ risk_gate:
32
+ version: 1
33
+ decision: BLOCK
34
+ action: swap
35
+ chain: bsc
36
+ coverage: partial
37
+ subject:
38
+ token: "0x..."
39
+ router: "0x..."
40
+ spender: "0x..."
41
+ blockers:
42
+ - type: honeypot
43
+ severity: critical
44
+ source: query-token-audit
45
+ detail: unsellable token
46
+ - type: unsafe-upgrade-control
47
+ severity: critical
48
+ source: proxy-upgrade-safety
49
+ detail: privileged arbitrary implementation change
50
+ warnings:
51
+ - type: holder-concentration
52
+ severity: medium
53
+ source: binance-token-audit
54
+ detail: top holders dominate supply
55
+ next_steps:
56
+ - stop
57
+ - gather verified source and owner privilege evidence
58
+ evidence:
59
+ - adapter: query-token-audit
60
+ signal: honeypot
61
+ exact_hit: unsellable token flag
62
+ - adapter: proxy-upgrade-safety
63
+ signal: arbitrary upgrade control
64
+ exact_hit: implementation can be changed by privileged actor
65
+ ```
66
+
67
+ ## Notes
68
+
69
+ - `decision` is mandatory and must be one of `ALLOW`, `WARN`, `BLOCK`.
70
+ - `coverage` is mandatory and must be one of `complete`, `partial`, `missing`.
71
+ - `blockers` and `warnings` are separate. Do not merge them.
72
+ - `evidence` should retain adapter-level provenance so later skills can cite it.
@@ -0,0 +1,34 @@
1
+ # Web3 Risk Gate Signal Taxonomy
2
+
3
+ Use these stable labels when normalizing adapter output.
4
+
5
+ ## Blocker Types
6
+
7
+ - `honeypot`
8
+ - `unsellable-token`
9
+ - `malicious-upgrade-path`
10
+ - `unsafe-upgrade-control`
11
+ - `hidden-owner-with-mint`
12
+ - `storage-collision-risk`
13
+ - `uninitialized-implementation`
14
+ - `selfdestruct-risk`
15
+ - `known-blacklist-hit`
16
+ - `unsafe-token-callback`
17
+
18
+ ## Warning Types
19
+
20
+ - `high-tax`
21
+ - `mintable-supply`
22
+ - `upgradeable-contract`
23
+ - `opaque-code`
24
+ - `holder-concentration`
25
+ - `unverified-contract`
26
+ - `allowance-exposure`
27
+ - `admin-centralization`
28
+
29
+ ## Mapping Rules
30
+
31
+ - If any blocker type is confirmed, the decision is `BLOCK`.
32
+ - If only warning types are present, the decision is `WARN` unless the action is strictly read-only.
33
+ - If coverage is missing for the primary subject, keep the decision conservative and mark `coverage: missing` or `partial`.
34
+ - Do not invent new labels when an existing label is close enough. Stable labels are more useful than expressive prose.
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env python3
2
+ """Merge multiple normalized risk_gate blocks into one conservative decision."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ from pathlib import Path
9
+ import sys
10
+
11
+
12
+ COVERAGE_ORDER = {
13
+ "complete": 0,
14
+ "partial": 1,
15
+ "missing": 2,
16
+ }
17
+
18
+
19
+ def build_parser() -> argparse.ArgumentParser:
20
+ parser = argparse.ArgumentParser(description="Merge multiple risk_gate payloads into one block.")
21
+ parser.add_argument(
22
+ "--input-file",
23
+ action="append",
24
+ required=True,
25
+ help="Path to a JSON file containing a risk_gate payload or '-' for stdin",
26
+ )
27
+ return parser
28
+
29
+
30
+ def load_payload(path: str) -> dict[str, object]:
31
+ if path == "-":
32
+ return json.load(sys.stdin)
33
+ return json.loads(Path(path).read_text(encoding="utf-8"))
34
+
35
+
36
+ def extract_gate(payload: dict[str, object]) -> dict[str, object]:
37
+ gate = payload.get("risk_gate")
38
+ if isinstance(gate, dict):
39
+ return gate
40
+ if {"decision", "action", "chain", "coverage"}.issubset(payload):
41
+ return payload
42
+ raise ValueError("input payload does not contain risk_gate")
43
+
44
+
45
+ def merge_scalar(current: str, new_value: str, field_name: str) -> str:
46
+ if not new_value:
47
+ return current
48
+ if not current:
49
+ return new_value
50
+ if current != new_value:
51
+ raise ValueError(f"conflicting {field_name}: {current} vs {new_value}")
52
+ return current
53
+
54
+
55
+ def merge_subject(subject: dict[str, object], new_subject: dict[str, object]) -> dict[str, object]:
56
+ merged = dict(subject)
57
+ for key, value in new_subject.items():
58
+ if key in merged and merged[key] != value:
59
+ raise ValueError(f"conflicting subject field {key}: {merged[key]} vs {value}")
60
+ merged[key] = value
61
+ return merged
62
+
63
+
64
+ def dedupe_items(items: list[dict[str, object]]) -> list[dict[str, object]]:
65
+ seen: set[str] = set()
66
+ deduped: list[dict[str, object]] = []
67
+ for item in items:
68
+ key = json.dumps(item, sort_keys=True, ensure_ascii=False)
69
+ if key in seen:
70
+ continue
71
+ seen.add(key)
72
+ deduped.append(item)
73
+ return deduped
74
+
75
+
76
+ def dedupe_strings(items: list[str]) -> list[str]:
77
+ seen: set[str] = set()
78
+ deduped: list[str] = []
79
+ for item in items:
80
+ if item in seen:
81
+ continue
82
+ seen.add(item)
83
+ deduped.append(item)
84
+ return deduped
85
+
86
+
87
+ def default_next_steps(decision: str, action: str, coverage: str) -> list[str]:
88
+ if decision == "BLOCK":
89
+ return ["stop", "collect additional evidence before retrying"]
90
+
91
+ steps: list[str] = []
92
+ if coverage != "complete":
93
+ steps.append("gather missing adapter coverage")
94
+ if decision == "WARN":
95
+ steps.append("require explicit confirmation")
96
+ if action in {"transfer", "approve", "swap", "liquidity", "protocol-interaction"}:
97
+ steps.append("run web3-transaction-simulator")
98
+ if not steps:
99
+ steps.append("continue with standard confirmation")
100
+ return steps
101
+
102
+
103
+ def merge_payloads(payloads: list[dict[str, object]]) -> dict[str, object]:
104
+ action = ""
105
+ chain = ""
106
+ subject: dict[str, object] = {}
107
+ coverages: list[str] = []
108
+ blockers: list[dict[str, object]] = []
109
+ warnings: list[dict[str, object]] = []
110
+ evidence: list[dict[str, object]] = []
111
+ next_steps: list[str] = []
112
+ seen_warn = False
113
+ seen_block = False
114
+
115
+ for payload in payloads:
116
+ gate = extract_gate(payload)
117
+ gate_action = str(gate.get("action", ""))
118
+ gate_chain = str(gate.get("chain", ""))
119
+ gate_coverage = str(gate.get("coverage", "partial"))
120
+ if gate_coverage not in COVERAGE_ORDER:
121
+ raise ValueError(f"unsupported coverage value: {gate_coverage}")
122
+
123
+ action = merge_scalar(action, gate_action, "action")
124
+ chain = merge_scalar(chain, gate_chain, "chain")
125
+ coverages.append(gate_coverage)
126
+ seen_warn = seen_warn or str(gate.get("decision", "")) == "WARN"
127
+ seen_block = seen_block or str(gate.get("decision", "")) == "BLOCK"
128
+
129
+ gate_subject = gate.get("subject", {})
130
+ if isinstance(gate_subject, dict):
131
+ subject = merge_subject(subject, gate_subject)
132
+
133
+ gate_blockers = gate.get("blockers", [])
134
+ if isinstance(gate_blockers, list):
135
+ blockers.extend(item for item in gate_blockers if isinstance(item, dict))
136
+ gate_warnings = gate.get("warnings", [])
137
+ if isinstance(gate_warnings, list):
138
+ warnings.extend(item for item in gate_warnings if isinstance(item, dict))
139
+ gate_evidence = gate.get("evidence", [])
140
+ if isinstance(gate_evidence, list):
141
+ evidence.extend(item for item in gate_evidence if isinstance(item, dict))
142
+ gate_next_steps = gate.get("next_steps", [])
143
+ if isinstance(gate_next_steps, list):
144
+ next_steps.extend(str(item) for item in gate_next_steps if isinstance(item, str))
145
+
146
+ coverage = max(coverages, key=lambda item: COVERAGE_ORDER[item]) if coverages else "missing"
147
+ blockers = dedupe_items(blockers)
148
+ warnings = dedupe_items(warnings)
149
+ evidence = dedupe_items(evidence)
150
+
151
+ if blockers or seen_block:
152
+ decision = "BLOCK"
153
+ elif warnings or seen_warn or coverage != "complete":
154
+ decision = "WARN"
155
+ else:
156
+ decision = "ALLOW"
157
+
158
+ next_steps = dedupe_strings(next_steps) or default_next_steps(decision, action, coverage)
159
+
160
+ payload: dict[str, object] = {
161
+ "risk_gate": {
162
+ "version": 1,
163
+ "decision": decision,
164
+ "action": action,
165
+ "chain": chain,
166
+ "coverage": coverage,
167
+ "subject": subject,
168
+ "next_steps": next_steps,
169
+ "evidence": evidence,
170
+ }
171
+ }
172
+ if blockers:
173
+ payload["risk_gate"]["blockers"] = blockers
174
+ if warnings:
175
+ payload["risk_gate"]["warnings"] = warnings
176
+ return payload
177
+
178
+
179
+ def main() -> int:
180
+ args = build_parser().parse_args()
181
+ payloads = [load_payload(path) for path in args.input_file]
182
+ merged = merge_payloads(payloads)
183
+ json.dump(merged, sys.stdout, ensure_ascii=False, indent=2)
184
+ sys.stdout.write("\n")
185
+ return 0
186
+
187
+
188
+ if __name__ == "__main__":
189
+ raise SystemExit(main())
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: web3-service-orchestrator
3
+ description: Service-level orchestrator for complex Web3 tasks decomposed into a local DAG. Use when a service plan is already present in prompt context and the task should be completed by combining multiple base Web3 skills step by step instead of improvising a monolithic answer.
4
+ ---
5
+
6
+ # Web3 Service Orchestrator
7
+
8
+ Use this skill only when the runtime has injected an active Web3 service DAG.
9
+
10
+ ## Operating Contract
11
+
12
+ - Treat the injected `Active Web3 Service DAG` section as the local source of truth.
13
+ - Work only on the current frontier nodes.
14
+ - Do not skip ahead to downstream nodes whose dependencies are not yet satisfied.
15
+ - Prefer base Web3 skills and stable output blocks over free-form reasoning.
16
+
17
+ ## Node Execution Rules
18
+
19
+ 1. Read the current frontier node goals and candidate skills.
20
+ 2. Use the smallest set of skills needed for that node.
21
+ 3. Try to produce the node's declared output schema.
22
+ 4. If a node is blocked by `risk_gate = BLOCK` or `simulation.readiness = blocked`, stop and explain the blocker.
23
+ 5. If the DAG is awaiting confirmation, ask for confirmation instead of executing.
24
+
25
+ ## Output Discipline
26
+
27
+ - Prefer normalized artifacts like `wallet_operation_plan`, `research_brief`, `risk_gate`, `simulation`, `execution_receipt`, `portfolio_status`, and `watch_status`.
28
+ - If multiple artifacts are available, summarize progress in plain language but keep the normalized blocks available in the turn for runtime consumption.
29
+
30
+ ## Scope Boundaries
31
+
32
+ - This skill orchestrates.
33
+ - Downstream wallet, research, risk, simulation, and execution skills do the actual work.
34
+ - Do not treat MetaMask SDK documentation as an execution path unless the task explicitly becomes app-side development.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: web3-static-analysis-runner
3
+ description: Static analysis routing layer for smart contract and adjacent codebases. Use when running or coordinating Semgrep, CodeQL, SARIF parsing, or vulnerability pattern scans, especially during audits and pre-deployment reviews.
4
+ ---
5
+
6
+ # Web3 Static Analysis Runner
7
+
8
+ Use this skill to coordinate static analysis instead of improvising one-off scan commands.
9
+
10
+ ## Required Components
11
+
12
+ - `web3-repo-heuristics`
13
+ - `web3-audit-reporting`
14
+
15
+ ## Required Profile Adapters
16
+
17
+ - `codeql`
18
+ - `semgrep`
19
+ - `sarif-parsing`
20
+ - `scv-scan`
21
+
22
+ Use [references/ADAPTER_CONSUMPTION_MAP.md](references/ADAPTER_CONSUMPTION_MAP.md)
23
+ to normalize scanner output into stable triage buckets.
24
+ Use [references/TRIAGE_BUCKETS.md](references/TRIAGE_BUCKETS.md) and
25
+ [references/OUTPUT_TEMPLATE.md](references/OUTPUT_TEMPLATE.md) to keep scanner
26
+ triage and escalation semantics stable.
27
+ Use [scripts/render_static_analysis_summary.py](scripts/render_static_analysis_summary.py)
28
+ when downstream skills need a normalized static-analysis block.
29
+
30
+ ## Workflow
31
+
32
+ 1. Detect the repo shape with `web3-repo-heuristics`.
33
+ 2. Decide which scanners apply:
34
+ - `semgrep` for fast broad pattern coverage
35
+ - `codeql` for deeper interprocedural analysis when language/tooling fits
36
+ - `sarif-parsing` when results already exist or need normalization
37
+ - `scv-scan` for smart contract vulnerability pattern review and checklist support
38
+ 3. Run the chosen scanners through their own upstream workflows.
39
+ 4. Deduplicate by root cause before surfacing anything as a finding.
40
+ 5. Pass only evidence-backed issues to `web3-audit-reporting`.
41
+
42
+ ## Output Contract
43
+
44
+ ```text
45
+ Scanners Run:
46
+ - name + scope
47
+ Results:
48
+ - raw hits
49
+ Triage:
50
+ - deduped root causes
51
+ Escalate:
52
+ - confirmed finding | review needed | false positive
53
+ ```
54
+
55
+ ## Reusable Output Contract
56
+
57
+ Always emit both:
58
+
59
+ 1. A short scanner/triage summary
60
+ 2. A normalized `static_analysis_summary` block
61
+
62
+ The normalized block must preserve:
63
+
64
+ - scanners actually run
65
+ - raw hit count
66
+ - deduped root causes
67
+ - escalation counts
68
+ - blockers and next steps
69
+ - exact evidence source per normalized issue
70
+
71
+ ## Guardrails
72
+
73
+ - Zero findings is not proof of safety.
74
+ - Do not mix scanner hits with confirmed findings.
75
+ - If a tool cannot run because of environment or build constraints, say that explicitly.
76
+ - Prefer existing SARIF over rerunning scans if the user asked for interpretation rather than execution.
@@ -0,0 +1,13 @@
1
+ # Static Analysis Adapter Consumption Map
2
+
3
+ - `codeql` -> deep query results
4
+ - `semgrep` -> fast pattern hits
5
+ - `sarif-parsing` -> normalized imported results
6
+ - `scv-scan` -> checklist-aligned smart contract patterns
7
+
8
+ Normalize into:
9
+
10
+ - scanners run
11
+ - raw hits
12
+ - deduped root causes
13
+ - escalate: confirmed finding | review needed | false positive
@@ -0,0 +1,45 @@
1
+ # Web3 Static Analysis Output Template
2
+
3
+ Always emit:
4
+
5
+ 1. A short human-readable scanner triage summary
6
+ 2. A normalized block
7
+
8
+ ```yaml
9
+ static_analysis_summary:
10
+ version: 1
11
+ status: partial
12
+ scope: src/core
13
+ scanners_run:
14
+ - semgrep
15
+ - codeql
16
+ raw_hit_count: 17
17
+ deduped_root_causes:
18
+ - unchecked low-level call in withdraw path
19
+ - missing access control on emergency setter
20
+ escalation_counts:
21
+ confirmed_finding: 1
22
+ review_needed: 2
23
+ false_positive: 4
24
+ blockers:
25
+ - smart-contract-specific CodeQL pack unavailable
26
+ next_steps:
27
+ - manually validate emergency setter authorization
28
+ evidence:
29
+ - adapter: semgrep
30
+ detail: unsafe low-level call pattern in Vault.sol
31
+ - adapter: codeql
32
+ detail: path-sensitive result on setter authorization path
33
+ ```
34
+
35
+ ## Required Fields
36
+
37
+ - `status`: `complete | partial | blocked`
38
+ - `scope`
39
+ - `scanners_run`
40
+ - `raw_hit_count`
41
+ - `deduped_root_causes`
42
+ - `escalation_counts`
43
+ - `blockers`
44
+ - `next_steps`
45
+ - `evidence`