patchr 0.1.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.
- apps/__init__.py +2 -0
- apps/api/__init__.py +2 -0
- apps/api/main.py +652 -0
- apps/benchmarks/__init__.py +1 -0
- apps/benchmarks/main.py +20 -0
- apps/sandbox/__init__.py +1 -0
- apps/sandbox/main.py +20 -0
- apps/worker/__init__.py +2 -0
- apps/worker/main.py +15 -0
- apps/worker/verify.py +14 -0
- patchr/__init__.py +12 -0
- patchr/sdk/__init__.py +20 -0
- patchr/sdk/client.py +12 -0
- patchr-0.1.0.dist-info/METADATA +137 -0
- patchr-0.1.0.dist-info/RECORD +116 -0
- patchr-0.1.0.dist-info/WHEEL +5 -0
- patchr-0.1.0.dist-info/entry_points.txt +5 -0
- patchr-0.1.0.dist-info/licenses/LICENSE +17 -0
- patchr-0.1.0.dist-info/top_level.txt +3 -0
- picux/__init__.py +6 -0
- picux/agents/__init__.py +5 -0
- picux/agents/registry.py +204 -0
- picux/api/__init__.py +5 -0
- picux/api/service.py +5075 -0
- picux/audit/__init__.py +31 -0
- picux/audit/activity.py +97 -0
- picux/audit/observability.py +55 -0
- picux/audit/verification/__init__.py +21 -0
- picux/audit/verification/ledger.py +633 -0
- picux/benchmarks/__init__.py +5 -0
- picux/benchmarks/local.py +286 -0
- picux/config.py +140 -0
- picux/contracts/__init__.py +22 -0
- picux/contracts/handshake.py +122 -0
- picux/contracts/integration.py +385 -0
- picux/contracts/openapi.py +187 -0
- picux/contracts/protocol_map.py +152 -0
- picux/contracts/routes.py +980 -0
- picux/contracts/schema_catalog.py +125 -0
- picux/core/__init__.py +17 -0
- picux/core/models.py +148 -0
- picux/core/router.py +131 -0
- picux/core/runtime.py +42 -0
- picux/core/state_machine.py +38 -0
- picux/domains/__init__.py +2 -0
- picux/domains/bridge/HostRun.py +1104 -0
- picux/domains/bridge/__init__.py +6 -0
- picux/domains/bridge/engine.py +345 -0
- picux/domains/hunt/__init__.py +6 -0
- picux/domains/hunt/engine.py +307 -0
- picux/domains/hunt/models.py +88 -0
- picux/domains/pay/__init__.py +16 -0
- picux/domains/pay/adapters.py +607 -0
- picux/domains/pay/engine.py +950 -0
- picux/domains/pay/models.py +95 -0
- picux/domains/proxy/__init__.py +5 -0
- picux/domains/proxy/engine.py +466 -0
- picux/domains/resolve/__init__.py +5 -0
- picux/domains/resolve/engine.py +546 -0
- picux/orchestrator/__init__.py +3 -0
- picux/orchestrator/engine.py +2840 -0
- picux/portals/__init__.py +17 -0
- picux/portals/templates.py +272 -0
- picux/protocols/__init__.py +1 -0
- picux/protocols/a2a/__init__.py +6 -0
- picux/protocols/a2a/client.py +51 -0
- picux/protocols/a2a/envelope.py +132 -0
- picux/protocols/mcp/__init__.py +7 -0
- picux/protocols/mcp/client.py +69 -0
- picux/protocols/mcp/contract.py +67 -0
- picux/protocols/mcp/server.py +76 -0
- picux/sandbox/__init__.py +6 -0
- picux/sandbox/midnight_arbitrage.py +215 -0
- picux/sandbox/models.py +90 -0
- picux/sdk/__init__.py +13 -0
- picux/sdk/client.py +768 -0
- picux/sdk/external.py +245 -0
- picux/security/__init__.py +18 -0
- picux/security/auth.py +86 -0
- picux/security/config_validator.py +58 -0
- picux/security/policy.py +158 -0
- picux/security/secrets.py +144 -0
- picux/signals/__init__.py +1 -0
- picux/signals/community/__init__.py +24 -0
- picux/signals/community/adapters/__init__.py +7 -0
- picux/signals/community/adapters/reddit.py +37 -0
- picux/signals/community/adapters/shopify.py +23 -0
- picux/signals/community/adapters/web.py +23 -0
- picux/signals/community/disambiguation.py +51 -0
- picux/signals/community/intake.py +227 -0
- picux/signals/community/models.py +102 -0
- picux/signals/community/rules.py +91 -0
- picux/signals/community/scoring.py +64 -0
- picux/storage/__init__.py +41 -0
- picux/storage/agents.py +50 -0
- picux/storage/cases.py +440 -0
- picux/storage/channels.py +476 -0
- picux/storage/connectors.py +411 -0
- picux/storage/envelopes.py +137 -0
- picux/storage/escrows.py +168 -0
- picux/storage/events.py +989 -0
- picux/storage/keyspace.py +60 -0
- picux/storage/mandates.py +107 -0
- picux/storage/portals.py +222 -0
- picux/storage/postgres.py +2049 -0
- picux/storage/providers.py +148 -0
- picux/storage/proxy.py +231 -0
- picux/storage/receipts.py +131 -0
- picux/storage/signals.py +147 -0
- picux/storage/tasks.py +179 -0
- picux/tools/__init__.py +11 -0
- picux/tools/shared.py +2048 -0
- picux/verification/__init__.py +5 -0
- picux/verification/rollout.py +183 -0
- picux/workflows/__init__.py +5 -0
- picux/workflows/templates.py +74 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from picux.api import PicuxApiService
|
|
8
|
+
from picux.config import PicuxSettings
|
|
9
|
+
from picux.core import Domain, ProtocolTask, ProtocolTaskStatus
|
|
10
|
+
from picux.domains.pay import PayDomain
|
|
11
|
+
from picux.security import validateProductionReady
|
|
12
|
+
from picux.storage import Keyspace, PicuxPostgresStore
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class RolloutGate:
|
|
17
|
+
name: str
|
|
18
|
+
ok: bool
|
|
19
|
+
detail: dict[str, Any]
|
|
20
|
+
|
|
21
|
+
def toMap(self) -> dict[str, Any]:
|
|
22
|
+
return {"name": self.name, "ok": self.ok, "detail": self.detail}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class RolloutReport:
|
|
27
|
+
ok: bool
|
|
28
|
+
gates: tuple[RolloutGate, ...]
|
|
29
|
+
|
|
30
|
+
def toMap(self) -> dict[str, Any]:
|
|
31
|
+
return {"ok": self.ok, "gates": [gate.toMap() for gate in self.gates]}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class RolloutVerifier:
|
|
35
|
+
"""Runs deterministic rollout gates that do not require live providers."""
|
|
36
|
+
|
|
37
|
+
def __init__(self, *, service: PicuxApiService | None = None, store: PicuxPostgresStore | None = None) -> None:
|
|
38
|
+
self.service = service or PicuxApiService(pay=PayDomain(verifier=self._verifier, clock=self._clock))
|
|
39
|
+
self.store = store or PicuxPostgresStore("", ensure=False)
|
|
40
|
+
|
|
41
|
+
def verify(self, *, settings: PicuxSettings | None = None) -> RolloutReport:
|
|
42
|
+
settings = settings or PicuxSettings.fromEnv({"PICUX_ENV": "local"})
|
|
43
|
+
gates = (
|
|
44
|
+
self.apiContractGate(),
|
|
45
|
+
self.externalIntegrationGate(),
|
|
46
|
+
self.postgresDurableGate(),
|
|
47
|
+
self.redisNamespaceGate(),
|
|
48
|
+
self.productionFailClosedGate(settings),
|
|
49
|
+
self.endToEndContractGate(),
|
|
50
|
+
)
|
|
51
|
+
return RolloutReport(ok=all(gate.ok for gate in gates), gates=gates)
|
|
52
|
+
|
|
53
|
+
def apiContractGate(self) -> RolloutGate:
|
|
54
|
+
checks = [
|
|
55
|
+
self.service.handle("GET", "/healthz")[0] == 200,
|
|
56
|
+
self.service.handle("GET", "/runtime")[0] == 200,
|
|
57
|
+
self.service.handle("POST", "/v1/tasks", {"goal": "find vendor arbitrage"})[1].get("ok") is True,
|
|
58
|
+
self.service.handle("GET", "/v1/signals/community/entities")[1].get("ok") is True,
|
|
59
|
+
]
|
|
60
|
+
return RolloutGate("apiContract", all(checks), {"checks": checks})
|
|
61
|
+
|
|
62
|
+
def externalIntegrationGate(self) -> RolloutGate:
|
|
63
|
+
status, result = self.service.handle(
|
|
64
|
+
"POST",
|
|
65
|
+
"/v1/tasks",
|
|
66
|
+
{"userId": "external_1", "channel": "external", "goal": "settle mandate after proof"},
|
|
67
|
+
)
|
|
68
|
+
ok = status == 200 and result.get("ok") is True and result["task"]["channel"] == "external"
|
|
69
|
+
return RolloutGate("externalIntegration", ok, {"status": status, "task": result.get("task", {})})
|
|
70
|
+
|
|
71
|
+
def postgresDurableGate(self) -> RolloutGate:
|
|
72
|
+
task = ProtocolTask(
|
|
73
|
+
taskId="task_rollout_probe",
|
|
74
|
+
userId="user_rollout",
|
|
75
|
+
domain=Domain.HUNT,
|
|
76
|
+
status=ProtocolTaskStatus.PENDING,
|
|
77
|
+
channel="verification",
|
|
78
|
+
)
|
|
79
|
+
result = self.store.durableWriteReadCheck(task)
|
|
80
|
+
ok = bool(result.get("ok") or result.get("skipped"))
|
|
81
|
+
return RolloutGate("postgresDurable", ok, result)
|
|
82
|
+
|
|
83
|
+
def redisNamespaceGate(self) -> RolloutGate:
|
|
84
|
+
plan = Keyspace().migrationReadPlan("task", "task_rollout_probe")
|
|
85
|
+
readKeys = plan["readKeys"]
|
|
86
|
+
ok = plan["writeKey"] == "picux:v1:task:task_rollout_probe" and readKeys[0] == plan["writeKey"]
|
|
87
|
+
return RolloutGate("redisNamespaceMigration", ok, plan)
|
|
88
|
+
|
|
89
|
+
def productionFailClosedGate(self, settings: PicuxSettings) -> RolloutGate:
|
|
90
|
+
readiness = validateProductionReady(settings)
|
|
91
|
+
if settings.prod:
|
|
92
|
+
ok = not readiness.ok and bool(readiness.issues)
|
|
93
|
+
else:
|
|
94
|
+
prodSettings = PicuxSettings.fromEnv({"PICUX_ENV": "production"})
|
|
95
|
+
prodReadiness = validateProductionReady(prodSettings)
|
|
96
|
+
ok = not prodReadiness.ok and bool(prodReadiness.issues)
|
|
97
|
+
readiness = prodReadiness
|
|
98
|
+
return RolloutGate("productionFailClosed", ok, readiness.toMap())
|
|
99
|
+
|
|
100
|
+
def endToEndContractGate(self) -> RolloutGate:
|
|
101
|
+
signalStatus, signal = self.service.handle(
|
|
102
|
+
"POST",
|
|
103
|
+
"/v1/signals/community/launch-task",
|
|
104
|
+
{
|
|
105
|
+
"userId": "external_1",
|
|
106
|
+
"targetDomain": "resolve",
|
|
107
|
+
"approved": True,
|
|
108
|
+
"signal": {
|
|
109
|
+
"source": {"platform": "reddit", "community": "agents"},
|
|
110
|
+
"text": "Picux Protocol request needs resolve proof before settlement",
|
|
111
|
+
"query": "Picux Protocol",
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
)
|
|
115
|
+
task = signal.get("task", {})
|
|
116
|
+
resolveStatus, resolved = self.service.handle(
|
|
117
|
+
"POST",
|
|
118
|
+
f"/v1/tasks/{task.get('taskId', '')}/resolve",
|
|
119
|
+
{"text": "Duplicate charge and overcharge $20 were found", "provider": "vendorA"},
|
|
120
|
+
)
|
|
121
|
+
mandate = self._mandate()
|
|
122
|
+
verifyStatus, verified = self.service.handle("POST", "/v1/mandates/mandate_rollout/verify", mandate)
|
|
123
|
+
settleStatus, settled = self.service.handle(
|
|
124
|
+
"POST",
|
|
125
|
+
"/v1/pay/settle",
|
|
126
|
+
{
|
|
127
|
+
"mandate": mandate,
|
|
128
|
+
"request": {
|
|
129
|
+
"taskId": task.get("taskId", ""),
|
|
130
|
+
"vendorId": "vendorA",
|
|
131
|
+
"amount": {"amount": 80, "currency": "USD"},
|
|
132
|
+
"pov": {"povId": "pov_rollout", "rules": ["inventoryVerified", "priceArbitrage20"]},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
)
|
|
136
|
+
receiptId = str(settled.get("receipt", {}).get("receiptId", "") or "")
|
|
137
|
+
receiptStatus, receipt = self.service.handle("GET", f"/v1/receipts/{receiptId}")
|
|
138
|
+
ok = all(
|
|
139
|
+
(
|
|
140
|
+
signalStatus == 200,
|
|
141
|
+
resolveStatus == 200,
|
|
142
|
+
verifyStatus == 200,
|
|
143
|
+
settleStatus == 200,
|
|
144
|
+
receiptStatus == 200,
|
|
145
|
+
signal.get("ok") is True,
|
|
146
|
+
resolved.get("ok") is True,
|
|
147
|
+
verified.get("ok") is True,
|
|
148
|
+
settled.get("ok") is True,
|
|
149
|
+
settled.get("receipt", {}).get("status") == "settled",
|
|
150
|
+
receipt.get("receipt", {}).get("receiptId") == receiptId,
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
return RolloutGate(
|
|
154
|
+
"endToEndContract",
|
|
155
|
+
ok,
|
|
156
|
+
{
|
|
157
|
+
"taskId": task.get("taskId", ""),
|
|
158
|
+
"receiptId": receiptId,
|
|
159
|
+
"statuses": [signalStatus, resolveStatus, verifyStatus, settleStatus, receiptStatus],
|
|
160
|
+
},
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
@staticmethod
|
|
164
|
+
def _clock() -> datetime:
|
|
165
|
+
return datetime(2026, 5, 9, 12, 0, tzinfo=timezone.utc)
|
|
166
|
+
|
|
167
|
+
@staticmethod
|
|
168
|
+
def _verifier(payload: dict[str, Any], signature: str, publicKey: str) -> bool:
|
|
169
|
+
return payload.get("mandateId") == "mandate_rollout" and signature == "rolloutSig" and publicKey == "rolloutPub"
|
|
170
|
+
|
|
171
|
+
@staticmethod
|
|
172
|
+
def _mandate() -> dict[str, Any]:
|
|
173
|
+
return {
|
|
174
|
+
"mandateId": "mandate_rollout",
|
|
175
|
+
"issuer": {"entityId": "tenant_rollout", "publicKey": "rolloutPub"},
|
|
176
|
+
"validUntil": "2099-01-01T00:00:00Z",
|
|
177
|
+
"constraints": {
|
|
178
|
+
"maxSpend": {"amount": 100.0, "currency": "USD"},
|
|
179
|
+
"allowedVendors": ["vendorA"],
|
|
180
|
+
"resolveRules": ["inventoryVerified", "priceArbitrage20"],
|
|
181
|
+
},
|
|
182
|
+
"signature": "rolloutSig",
|
|
183
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass(frozen=True)
|
|
8
|
+
class WorkflowTemplate:
|
|
9
|
+
templateId: str
|
|
10
|
+
name: str
|
|
11
|
+
domain: str
|
|
12
|
+
entryPoint: str
|
|
13
|
+
tagline: str
|
|
14
|
+
inputHints: tuple[str, ...]
|
|
15
|
+
outputs: tuple[str, ...]
|
|
16
|
+
proof: str
|
|
17
|
+
|
|
18
|
+
def toMap(self) -> dict[str, Any]:
|
|
19
|
+
return {
|
|
20
|
+
"templateId": self.templateId,
|
|
21
|
+
"name": self.name,
|
|
22
|
+
"domain": self.domain,
|
|
23
|
+
"entryPoint": self.entryPoint,
|
|
24
|
+
"tagline": self.tagline,
|
|
25
|
+
"inputHints": list(self.inputHints),
|
|
26
|
+
"outputs": list(self.outputs),
|
|
27
|
+
"proof": self.proof,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
TEMPLATES: tuple[WorkflowTemplate, ...] = (
|
|
32
|
+
WorkflowTemplate(
|
|
33
|
+
"findBestFit",
|
|
34
|
+
"Find my best-fit options",
|
|
35
|
+
"hunt",
|
|
36
|
+
"/v1/hunt/discover",
|
|
37
|
+
"Unify fragmented discovery, rank options, and suggest the next best action.",
|
|
38
|
+
("criteria", "offers", "sources"),
|
|
39
|
+
("rankedOptions", "selectedOption", "nextBestAction", "proofCard"),
|
|
40
|
+
"Source-bound HUNT proof card backed by a proof pack.",
|
|
41
|
+
),
|
|
42
|
+
WorkflowTemplate(
|
|
43
|
+
"auditDisputedClaim",
|
|
44
|
+
"Audit this disputed claim",
|
|
45
|
+
"resolve",
|
|
46
|
+
"/v1/workflows/templates/auditDisputedClaim/run",
|
|
47
|
+
"Turn a messy claim, dispute, audit trail, or migration-trust case into a reviewable evidence map.",
|
|
48
|
+
("claim", "documents", "agentClaims", "counterparty", "profile"),
|
|
49
|
+
("evidenceMap", "typedEvidence", "sourceClasses", "fraudIndicators", "caseOpsTimeline", "nextAction", "proofCard"),
|
|
50
|
+
"Resolve proof card with evidence status, confidence, open questions, and escalation guidance.",
|
|
51
|
+
),
|
|
52
|
+
WorkflowTemplate(
|
|
53
|
+
"coordinateHumanProcess",
|
|
54
|
+
"Coordinate this human process end-to-end",
|
|
55
|
+
"proxy",
|
|
56
|
+
"/v1/proxy/missions",
|
|
57
|
+
"Coordinate people, messages, documents, status, and verified follow-through.",
|
|
58
|
+
("task", "actors", "documents", "channels", "proofReq"),
|
|
59
|
+
("mission", "route", "status", "humanProof", "proofCard"),
|
|
60
|
+
"Proxy proof card backed by mission state and human completion proof.",
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def workflowTemplates() -> dict[str, Any]:
|
|
66
|
+
return {"ok": True, "templates": [item.toMap() for item in TEMPLATES], "count": len(TEMPLATES)}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def getWorkflowTemplate(templateId: str) -> dict[str, Any]:
|
|
70
|
+
requested = str(templateId or "")
|
|
71
|
+
match = next((item for item in TEMPLATES if item.templateId == requested), None)
|
|
72
|
+
if not match:
|
|
73
|
+
return {"ok": False, "error": "workflowTemplateNotFound", "templateId": requested}
|
|
74
|
+
return {"ok": True, "template": match.toMap()}
|