@synapsor/runner 0.1.0-alpha.9 → 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.
- package/CHANGELOG.md +162 -0
- package/README.md +388 -41
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/runner.mjs +2982 -238
- package/docs/README.md +40 -0
- package/docs/app-owned-executors.md +38 -0
- package/docs/capability-authoring.md +265 -0
- package/docs/cloud-mode.md +24 -0
- package/docs/current-scope.md +29 -0
- package/docs/dependency-license-inventory.md +35 -0
- package/docs/doctor.md +98 -0
- package/docs/getting-started-own-database.md +131 -46
- package/docs/handler-helper.md +228 -0
- package/docs/http-mcp.md +85 -17
- package/docs/licensing.md +36 -0
- package/docs/local-mode.md +44 -25
- package/docs/mcp-audit.md +8 -8
- package/docs/mcp-client-setup.md +59 -21
- package/docs/openai-agents-sdk.md +57 -0
- package/docs/recipes.md +6 -6
- package/docs/release-notes.md +327 -0
- package/docs/release-policy.md +125 -0
- package/docs/result-envelope-v2.md +151 -0
- package/docs/rfcs/001-result-envelope-v2.md +143 -0
- package/docs/rfcs/002-app-owned-handler-helper.md +161 -0
- package/docs/rfcs/003-integrator-feedback-teardown.md +97 -0
- package/docs/store-lifecycle.md +83 -0
- package/docs/troubleshooting-first-run.md +6 -6
- package/docs/use-your-own-database.md +18 -0
- package/docs/writeback-executors.md +92 -1
- package/examples/app-owned-writeback/README.md +128 -0
- package/examples/app-owned-writeback/business-actions.md +221 -0
- package/examples/app-owned-writeback/command-handler.mjs +55 -0
- package/examples/app-owned-writeback/node-fastify-handler.mjs +64 -0
- package/examples/app-owned-writeback/python-fastapi-handler.py +66 -0
- package/examples/mcp-postgres-billing-app-handler/README.md +94 -0
- package/examples/mcp-postgres-billing-app-handler/app-handler.mjs +123 -0
- package/examples/mcp-postgres-billing-app-handler/docker-compose.yml +13 -0
- package/examples/mcp-postgres-billing-app-handler/schema.sql +59 -0
- package/examples/mcp-postgres-billing-app-handler/scripts/run-demo.sh +100 -0
- package/examples/mcp-postgres-billing-app-handler/seed.sql +39 -0
- package/examples/mcp-postgres-billing-app-handler/synapsor-handler.mjs +437 -0
- package/examples/mcp-postgres-billing-app-handler/synapsor.runner.json +158 -0
- package/examples/openai-agents-http/README.md +19 -12
- package/examples/openai-agents-http/agent.py +29 -65
- package/examples/openai-agents-stdio/README.md +10 -6
- package/examples/openai-agents-stdio/agent.py +4 -2
- package/examples/reference-support-billing-app/README.md +16 -16
- package/examples/reference-support-billing-app/mcp-client.generic.json +1 -1
- package/fixtures/benchmark/mcp-efficiency.json +53 -0
- package/fixtures/benchmark/mcp-efficiency.txt +25 -0
- package/fixtures/protocol/MANIFEST.json +54 -0
- package/fixtures/protocol/change-set.late-fee-waiver.v1.json +72 -0
- package/fixtures/protocol/execution-receipt.applied.v1.json +14 -0
- package/fixtures/protocol/execution-receipt.conflict.v1.json +15 -0
- package/fixtures/protocol/runner-registration.v1.json +22 -0
- package/fixtures/protocol/writeback-job.late-fee-waiver.v1.json +44 -0
- package/package.json +6 -1
- package/schemas/change-set.v1.schema.json +140 -0
- package/schemas/execution-receipt.v1.schema.json +34 -0
- package/schemas/onboarding-selection.v1.schema.json +132 -0
- package/schemas/runner-registration.v1.schema.json +48 -0
- package/schemas/synapsor.app-handler-receipt.v1.json +39 -0
- package/schemas/synapsor.app-handler-request.v1.json +119 -0
- package/schemas/synapsor.runner.schema.json +415 -0
- package/schemas/writeback-job.v1.schema.json +121 -0
|
@@ -1,63 +1,17 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import json
|
|
3
2
|
import os
|
|
4
3
|
import sys
|
|
5
|
-
import urllib.error
|
|
6
|
-
import urllib.request
|
|
7
4
|
|
|
8
5
|
try:
|
|
9
|
-
from agents import Agent, Runner
|
|
6
|
+
from agents import Agent, Runner
|
|
7
|
+
from agents.mcp import MCPServerStreamableHttp
|
|
10
8
|
except ImportError as exc:
|
|
11
9
|
raise SystemExit(
|
|
12
|
-
"This example requires the OpenAI Agents SDK. "
|
|
10
|
+
"This example requires the OpenAI Agents SDK with Streamable HTTP MCP support. "
|
|
13
11
|
"Install with: pip install -r requirements.txt"
|
|
14
12
|
) from exc
|
|
15
13
|
|
|
16
14
|
|
|
17
|
-
def call_synapsor_http_mcp(method: str, params: dict) -> dict:
|
|
18
|
-
url = os.environ.get("SYNAPSOR_RUNNER_HTTP_URL", "http://127.0.0.1:8765/mcp")
|
|
19
|
-
token = os.environ.get("SYNAPSOR_RUNNER_HTTP_TOKEN")
|
|
20
|
-
if not token:
|
|
21
|
-
raise RuntimeError("SYNAPSOR_RUNNER_HTTP_TOKEN is not set")
|
|
22
|
-
|
|
23
|
-
payload = json.dumps({
|
|
24
|
-
"jsonrpc": "2.0",
|
|
25
|
-
"id": 1,
|
|
26
|
-
"method": method,
|
|
27
|
-
"params": params,
|
|
28
|
-
}).encode("utf-8")
|
|
29
|
-
request = urllib.request.Request(
|
|
30
|
-
url,
|
|
31
|
-
data=payload,
|
|
32
|
-
method="POST",
|
|
33
|
-
headers={
|
|
34
|
-
"authorization": f"Bearer {token}",
|
|
35
|
-
"content-type": "application/json",
|
|
36
|
-
},
|
|
37
|
-
)
|
|
38
|
-
try:
|
|
39
|
-
with urllib.request.urlopen(request, timeout=15) as response:
|
|
40
|
-
body = response.read().decode("utf-8")
|
|
41
|
-
except urllib.error.HTTPError as exc:
|
|
42
|
-
body = exc.read().decode("utf-8")
|
|
43
|
-
raise RuntimeError(f"Synapsor HTTP MCP returned HTTP {exc.code}: {body}") from exc
|
|
44
|
-
|
|
45
|
-
parsed = json.loads(body)
|
|
46
|
-
if "error" in parsed:
|
|
47
|
-
raise RuntimeError(f"Synapsor HTTP MCP error: {parsed['error']}")
|
|
48
|
-
return parsed["result"]
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
@function_tool
|
|
52
|
-
def billing_inspect_invoice(invoice_id: str) -> str:
|
|
53
|
-
"""Inspect one scoped invoice through Synapsor Runner HTTP MCP."""
|
|
54
|
-
result = call_synapsor_http_mcp("tools/call", {
|
|
55
|
-
"name": "billing.inspect_invoice",
|
|
56
|
-
"arguments": {"invoice_id": invoice_id},
|
|
57
|
-
})
|
|
58
|
-
return json.dumps(result.get("structuredContent", result), indent=2)
|
|
59
|
-
|
|
60
|
-
|
|
61
15
|
async def main() -> None:
|
|
62
16
|
required = ["OPENAI_API_KEY", "SYNAPSOR_RUNNER_HTTP_URL", "SYNAPSOR_RUNNER_HTTP_TOKEN"]
|
|
63
17
|
missing = [name for name in required if not os.environ.get(name)]
|
|
@@ -65,22 +19,32 @@ async def main() -> None:
|
|
|
65
19
|
raise SystemExit(f"Missing required environment variables: {', '.join(missing)}")
|
|
66
20
|
|
|
67
21
|
invoice_id = os.environ.get("SYNAPSOR_INVOICE_ID", "INV-3001")
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
22
|
+
mcp_url = os.environ["SYNAPSOR_RUNNER_HTTP_URL"]
|
|
23
|
+
token = os.environ["SYNAPSOR_RUNNER_HTTP_TOKEN"]
|
|
24
|
+
|
|
25
|
+
async with MCPServerStreamableHttp(
|
|
26
|
+
params={
|
|
27
|
+
"url": mcp_url,
|
|
28
|
+
"headers": {"Authorization": f"Bearer {token}"},
|
|
29
|
+
"timeout": 15,
|
|
30
|
+
}
|
|
31
|
+
) as mcp_server:
|
|
32
|
+
agent = Agent(
|
|
33
|
+
name="Synapsor Streamable HTTP MCP demo agent",
|
|
34
|
+
instructions=(
|
|
35
|
+
"Use Synapsor MCP tools to inspect scoped database data. "
|
|
36
|
+
"Do not claim that you can run SQL, approve proposals, or commit writes."
|
|
37
|
+
),
|
|
38
|
+
mcp_servers=[mcp_server],
|
|
39
|
+
)
|
|
40
|
+
result = await Runner.run(
|
|
41
|
+
agent,
|
|
42
|
+
(
|
|
43
|
+
f"Inspect invoice {invoice_id} using Synapsor. "
|
|
44
|
+
"Explain what you saw and whether you have write authority."
|
|
45
|
+
),
|
|
46
|
+
)
|
|
47
|
+
print(result.final_output)
|
|
84
48
|
|
|
85
49
|
|
|
86
50
|
if __name__ == "__main__":
|
|
@@ -4,7 +4,10 @@ This example shows an OpenAI Agents SDK app launching Synapsor Runner as a
|
|
|
4
4
|
local stdio MCP server.
|
|
5
5
|
|
|
6
6
|
Use stdio when the agent process can start the MCP server on the same machine.
|
|
7
|
-
The model sees Synapsor semantic tools such as
|
|
7
|
+
The model sees Synapsor semantic tools through OpenAI-safe aliases such as
|
|
8
|
+
`billing__inspect_invoice`. Runner keeps the canonical Synapsor capability
|
|
9
|
+
name, such as `billing.inspect_invoice`, in MCP metadata and maps calls back to
|
|
10
|
+
it. The model
|
|
8
11
|
does not receive raw SQL, database URLs, write credentials, approval tools, or
|
|
9
12
|
commit tools.
|
|
10
13
|
|
|
@@ -13,13 +16,13 @@ commit tools.
|
|
|
13
16
|
Generate `synapsor.runner.json` first:
|
|
14
17
|
|
|
15
18
|
```bash
|
|
16
|
-
npx -y -p @synapsor/runner
|
|
19
|
+
npx -y -p @synapsor/runner synapsor-runner demo
|
|
17
20
|
```
|
|
18
21
|
|
|
19
22
|
or connect your own staging database:
|
|
20
23
|
|
|
21
24
|
```bash
|
|
22
|
-
npx -y -p @synapsor/runner
|
|
25
|
+
npx -y -p @synapsor/runner synapsor-runner onboard db --from-env DATABASE_URL
|
|
23
26
|
```
|
|
24
27
|
|
|
25
28
|
Then install the Python dependencies:
|
|
@@ -52,11 +55,12 @@ export SYNAPSOR_INVOICE_ID="INV-3001"
|
|
|
52
55
|
|
|
53
56
|
Expected behavior:
|
|
54
57
|
|
|
55
|
-
- the agent can inspect the scoped invoice through Synapsor
|
|
58
|
+
- the agent can inspect the scoped invoice through Synapsor using an
|
|
59
|
+
OpenAI-safe tool alias;
|
|
60
|
+
- Runner maps the alias back to the canonical Synapsor capability;
|
|
56
61
|
- the agent cannot run SQL;
|
|
57
62
|
- the agent cannot approve or commit writes;
|
|
58
63
|
- evidence/query audit are saved in the local Runner store.
|
|
59
64
|
|
|
60
65
|
If your installed OpenAI Agents SDK does not expose `MCPServerStdio`, update the
|
|
61
|
-
SDK or use the HTTP example
|
|
62
|
-
client.
|
|
66
|
+
SDK or use the Streamable HTTP example.
|
|
@@ -27,14 +27,16 @@ async def main() -> None:
|
|
|
27
27
|
"args": [
|
|
28
28
|
"-y",
|
|
29
29
|
"-p",
|
|
30
|
-
"@synapsor/runner
|
|
31
|
-
"synapsor",
|
|
30
|
+
"@synapsor/runner",
|
|
31
|
+
"synapsor-runner",
|
|
32
32
|
"mcp",
|
|
33
33
|
"serve",
|
|
34
34
|
"--config",
|
|
35
35
|
config_path,
|
|
36
36
|
"--store",
|
|
37
37
|
store_path,
|
|
38
|
+
"--alias-mode",
|
|
39
|
+
"openai",
|
|
38
40
|
],
|
|
39
41
|
"env": {
|
|
40
42
|
**os.environ,
|
|
@@ -36,14 +36,14 @@ examples/reference-support-billing-app/scripts/run-demo.sh
|
|
|
36
36
|
Validate the reviewed contract:
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
npx -y -p @synapsor/runner
|
|
40
|
-
npx -y -p @synapsor/runner
|
|
39
|
+
npx -y -p @synapsor/runner synapsor-runner config validate --config examples/reference-support-billing-app/synapsor.runner.json
|
|
40
|
+
npx -y -p @synapsor/runner synapsor-runner doctor --config examples/reference-support-billing-app/synapsor.runner.json
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Serve MCP:
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
npx -y -p @synapsor/runner
|
|
46
|
+
npx -y -p @synapsor/runner synapsor-runner mcp serve \
|
|
47
47
|
--config examples/reference-support-billing-app/synapsor.runner.json \
|
|
48
48
|
--store ./tmp/reference-support-billing/local.db
|
|
49
49
|
```
|
|
@@ -69,11 +69,11 @@ After `synapsor-runner demo` or after starting this fixture manually, try the sa
|
|
|
69
69
|
proposal-first loop without connecting an MCP client:
|
|
70
70
|
|
|
71
71
|
```bash
|
|
72
|
-
npx -y -p @synapsor/runner
|
|
73
|
-
npx -y -p @synapsor/runner
|
|
74
|
-
npx -y -p @synapsor/runner
|
|
75
|
-
npx -y -p @synapsor/runner
|
|
76
|
-
npx -y -p @synapsor/runner
|
|
72
|
+
npx -y -p @synapsor/runner synapsor-runner propose billing.propose_late_fee_waiver --sample
|
|
73
|
+
npx -y -p @synapsor/runner synapsor-runner proposals show latest
|
|
74
|
+
npx -y -p @synapsor/runner synapsor-runner proposals approve latest --yes
|
|
75
|
+
npx -y -p @synapsor/runner synapsor-runner apply latest
|
|
76
|
+
npx -y -p @synapsor/runner synapsor-runner replay latest
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
Expected safety output:
|
|
@@ -93,8 +93,8 @@ Guarded writeback applied.
|
|
|
93
93
|
Other proposal examples use the same review/apply/replay path:
|
|
94
94
|
|
|
95
95
|
```bash
|
|
96
|
-
npx -y -p @synapsor/runner
|
|
97
|
-
npx -y -p @synapsor/runner
|
|
96
|
+
npx -y -p @synapsor/runner synapsor-runner propose support.propose_plan_credit --sample
|
|
97
|
+
npx -y -p @synapsor/runner synapsor-runner propose orders.propose_status_change --sample
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
Safety guarantees:
|
|
@@ -115,17 +115,17 @@ or production-scale runner orchestration.
|
|
|
115
115
|
After a proposal exists:
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
|
-
npx -y -p @synapsor/runner
|
|
119
|
-
npx -y -p @synapsor/runner
|
|
120
|
-
npx -y -p @synapsor/runner
|
|
121
|
-
npx -y -p @synapsor/runner
|
|
122
|
-
npx -y -p @synapsor/runner
|
|
118
|
+
npx -y -p @synapsor/runner synapsor-runner proposals list --store ./tmp/reference-support-billing/local.db
|
|
119
|
+
npx -y -p @synapsor/runner synapsor-runner proposals approve <proposal_id> --store ./tmp/reference-support-billing/local.db --actor local_reviewer --yes
|
|
120
|
+
npx -y -p @synapsor/runner synapsor-runner proposals writeback-job <proposal_id> --store ./tmp/reference-support-billing/local.db --output ./tmp/reference-support-billing/job.json
|
|
121
|
+
npx -y -p @synapsor/runner synapsor-runner apply --job ./tmp/reference-support-billing/job.json --store ./tmp/reference-support-billing/local.db
|
|
122
|
+
npx -y -p @synapsor/runner synapsor-runner replay export <proposal_id> --store ./tmp/reference-support-billing/local.db --output ./tmp/reference-support-billing/replay.json
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
To inspect locally in a browser:
|
|
126
126
|
|
|
127
127
|
```bash
|
|
128
|
-
npx -y -p @synapsor/runner
|
|
128
|
+
npx -y -p @synapsor/runner synapsor-runner ui \
|
|
129
129
|
--config examples/reference-support-billing-app/synapsor.runner.json \
|
|
130
130
|
--store ./tmp/reference-support-billing/local.db
|
|
131
131
|
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"benchmark": "mcp-efficiency",
|
|
3
|
+
"fixture": "late-fee-waiver",
|
|
4
|
+
"tokenizer": {
|
|
5
|
+
"name": "synapsor-fixture-tokenizer-v1",
|
|
6
|
+
"version": 1,
|
|
7
|
+
"method": "deterministic regex tokenization for fixture comparison; not a model billing tokenizer"
|
|
8
|
+
},
|
|
9
|
+
"note": "This benchmark compares the included fixture/reference workflow only. It is not a universal token-savings claim.",
|
|
10
|
+
"paths": {
|
|
11
|
+
"generic_database_mcp_reference": {
|
|
12
|
+
"exposed_tools": 4,
|
|
13
|
+
"serialized_tools_list_bytes": 822,
|
|
14
|
+
"serialized_tools_list_tokens": 298,
|
|
15
|
+
"schema_context_bytes": 215,
|
|
16
|
+
"schema_context_tokens": 75,
|
|
17
|
+
"business_result_bytes": 199,
|
|
18
|
+
"business_result_tokens": 77,
|
|
19
|
+
"scripted_tool_calls": 5,
|
|
20
|
+
"exposes_raw_sql": true,
|
|
21
|
+
"exposes_write_credentials": false,
|
|
22
|
+
"approval_separated": false,
|
|
23
|
+
"stale_row_conflict_checked": false
|
|
24
|
+
},
|
|
25
|
+
"synapsor_runner_semantic_path": {
|
|
26
|
+
"exposed_tools": 2,
|
|
27
|
+
"serialized_tools_list_bytes": 728,
|
|
28
|
+
"serialized_tools_list_tokens": 236,
|
|
29
|
+
"schema_context_bytes": 331,
|
|
30
|
+
"schema_context_tokens": 87,
|
|
31
|
+
"business_result_bytes": 277,
|
|
32
|
+
"business_result_tokens": 91,
|
|
33
|
+
"scripted_tool_calls": 2,
|
|
34
|
+
"exposes_raw_sql": false,
|
|
35
|
+
"exposes_write_credentials": false,
|
|
36
|
+
"approval_separated": true,
|
|
37
|
+
"stale_row_conflict_checked": true
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"scripted_plans": {
|
|
41
|
+
"generic_database_mcp_reference": [
|
|
42
|
+
"list_tables",
|
|
43
|
+
"describe_table invoices",
|
|
44
|
+
"query_database SELECT invoice",
|
|
45
|
+
"formulate raw UPDATE",
|
|
46
|
+
"execute_sql UPDATE invoice"
|
|
47
|
+
],
|
|
48
|
+
"synapsor_runner_semantic_path": [
|
|
49
|
+
"billing.inspect_invoice",
|
|
50
|
+
"billing.propose_late_fee_waiver"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
MCP efficiency benchmark: late-fee-waiver fixture
|
|
2
|
+
Tokenizer: synapsor-fixture-tokenizer-v1 (deterministic fixture tokenizer; not a model billing tokenizer)
|
|
3
|
+
Scope: included fixture/reference workflow only; not a universal savings claim.
|
|
4
|
+
|
|
5
|
+
Generic database MCP reference:
|
|
6
|
+
exposed tools: 4
|
|
7
|
+
tools/list: 822 bytes, 298 tokens
|
|
8
|
+
scripted tool calls: 5
|
|
9
|
+
schema/context: 215 bytes, 75 tokens
|
|
10
|
+
business result: 199 bytes, 77 tokens
|
|
11
|
+
raw SQL exposed: yes
|
|
12
|
+
approval separated: no
|
|
13
|
+
stale-row conflict checked: no
|
|
14
|
+
|
|
15
|
+
Synapsor Runner semantic path:
|
|
16
|
+
exposed tools: 2
|
|
17
|
+
tools/list: 728 bytes, 236 tokens
|
|
18
|
+
scripted tool calls: 2
|
|
19
|
+
schema/context: 331 bytes, 87 tokens
|
|
20
|
+
business result: 277 bytes, 91 tokens
|
|
21
|
+
raw SQL exposed: no
|
|
22
|
+
approval separated: yes
|
|
23
|
+
stale-row conflict checked: yes
|
|
24
|
+
|
|
25
|
+
Run with --json to inspect machine-readable measurements and scripted plans.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "synapsor.protocol-manifest.v1",
|
|
3
|
+
"protocol_set": "database-mcp-writeback",
|
|
4
|
+
"version": "0.1.0-alpha",
|
|
5
|
+
"hash_algorithm": "sha256",
|
|
6
|
+
"note": "This manifest is copied in Synapsor main protocol/MANIFEST.json and synapsor-runner fixtures/protocol/MANIFEST.json. Hashes are over the checked-in JSON artifact bytes.",
|
|
7
|
+
"artifacts": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "fixture",
|
|
10
|
+
"name": "change-set.late-fee-waiver.v1.json",
|
|
11
|
+
"sha256": "7112d0f28832e61b4ac5846d169666c0476ba92eb68c6790c10ac614ee3f2b33"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"kind": "fixture",
|
|
15
|
+
"name": "execution-receipt.applied.v1.json",
|
|
16
|
+
"sha256": "5af8be1b72b03d5a4c7af22748d9ade9f0febbf5e9503931054361ef998b5870"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"kind": "fixture",
|
|
20
|
+
"name": "execution-receipt.conflict.v1.json",
|
|
21
|
+
"sha256": "64e8a5fd90cdeafa2dd92a2c67cad1307b9d09e585cc82b06b987bde382f7733"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"kind": "fixture",
|
|
25
|
+
"name": "runner-registration.v1.json",
|
|
26
|
+
"sha256": "3eaf844cdc94a4274601cedfed7252d65dd837a345c8c3b0f17ab6bbdf7f75da"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"kind": "fixture",
|
|
30
|
+
"name": "writeback-job.late-fee-waiver.v1.json",
|
|
31
|
+
"sha256": "577e7987427031b55134c3d7296e644b1c8b7adec495758d4cff3665e954dbc8"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"kind": "schema",
|
|
35
|
+
"name": "change-set.v1.schema.json",
|
|
36
|
+
"sha256": "4e52b369b0d3bea30b0ed7b61ec239fc67de3dc691ed4014d6d5eabc7d2be4de"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"kind": "schema",
|
|
40
|
+
"name": "execution-receipt.v1.schema.json",
|
|
41
|
+
"sha256": "69504ce51fa66440e42d57ef6cb36cc6d8543427d8d385c9ccff954ecae5ec83"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"kind": "schema",
|
|
45
|
+
"name": "runner-registration.v1.schema.json",
|
|
46
|
+
"sha256": "86242555545b44ae747965ddb8aa35e2982587c76c2538f0f646e8b63994286b"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"kind": "schema",
|
|
50
|
+
"name": "writeback-job.v1.schema.json",
|
|
51
|
+
"sha256": "eab35194dd6b6caa7694aa8f14afbf265338d6ee8ed3d3db5d08ec83c4e7092e"
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "synapsor.change-set.v1",
|
|
3
|
+
"proposal_id": "wrp_123",
|
|
4
|
+
"proposal_version": 1,
|
|
5
|
+
"action": "billing.waive_late_fee",
|
|
6
|
+
"mode": "review_required",
|
|
7
|
+
"principal": {
|
|
8
|
+
"id": "support_agent_17",
|
|
9
|
+
"source": "trusted_session"
|
|
10
|
+
},
|
|
11
|
+
"scope": {
|
|
12
|
+
"tenant_id": "acme",
|
|
13
|
+
"business_object": "invoice",
|
|
14
|
+
"object_id": "INV-3001"
|
|
15
|
+
},
|
|
16
|
+
"source": {
|
|
17
|
+
"kind": "external_postgres",
|
|
18
|
+
"source_id": "src_pg_acme",
|
|
19
|
+
"schema": "public",
|
|
20
|
+
"table": "invoices",
|
|
21
|
+
"primary_key": {
|
|
22
|
+
"column": "id",
|
|
23
|
+
"value": "INV-3001"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"before": {
|
|
27
|
+
"late_fee_cents": 5500,
|
|
28
|
+
"waiver_reason": null,
|
|
29
|
+
"updated_at": "2026-06-20T14:31:08Z"
|
|
30
|
+
},
|
|
31
|
+
"patch": {
|
|
32
|
+
"late_fee_cents": 0,
|
|
33
|
+
"waiver_reason": "customer requested review"
|
|
34
|
+
},
|
|
35
|
+
"after": {
|
|
36
|
+
"late_fee_cents": 0,
|
|
37
|
+
"waiver_reason": "customer requested review",
|
|
38
|
+
"updated_at": "2026-06-20T14:31:08Z"
|
|
39
|
+
},
|
|
40
|
+
"guards": {
|
|
41
|
+
"tenant": {
|
|
42
|
+
"column": "tenant_id",
|
|
43
|
+
"value": "acme"
|
|
44
|
+
},
|
|
45
|
+
"allowed_columns": [
|
|
46
|
+
"late_fee_cents",
|
|
47
|
+
"waiver_reason"
|
|
48
|
+
],
|
|
49
|
+
"expected_version": {
|
|
50
|
+
"column": "updated_at",
|
|
51
|
+
"value": "2026-06-20T14:31:08Z"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"evidence": {
|
|
55
|
+
"bundle_id": "ev_456",
|
|
56
|
+
"query_fingerprint": "sha256:1111111111111111111111111111111111111111111111111111111111111111",
|
|
57
|
+
"items": []
|
|
58
|
+
},
|
|
59
|
+
"approval": {
|
|
60
|
+
"status": "pending",
|
|
61
|
+
"required_role": "support_lead"
|
|
62
|
+
},
|
|
63
|
+
"writeback": {
|
|
64
|
+
"status": "not_applied",
|
|
65
|
+
"mode": "trusted_worker_required"
|
|
66
|
+
},
|
|
67
|
+
"source_database_mutated": false,
|
|
68
|
+
"integrity": {
|
|
69
|
+
"proposal_hash": "sha256:2222222222222222222222222222222222222222222222222222222222222222"
|
|
70
|
+
},
|
|
71
|
+
"created_at": "2026-06-20T14:31:09Z"
|
|
72
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "synapsor.execution-receipt.v1",
|
|
3
|
+
"writeback_job_id": "wbj_123",
|
|
4
|
+
"proposal_id": "wrp_123",
|
|
5
|
+
"runner_id": "runner_123",
|
|
6
|
+
"status": "applied",
|
|
7
|
+
"rows_affected": 1,
|
|
8
|
+
"idempotency_key": "wrp_123:INV-3001",
|
|
9
|
+
"previous_version": "2026-06-20T14:31:08Z",
|
|
10
|
+
"new_version": "2026-06-20T14:34:19Z",
|
|
11
|
+
"source_database_mutated": true,
|
|
12
|
+
"executed_at": "2026-06-20T14:34:19Z",
|
|
13
|
+
"receipt_hash": "sha256:3333333333333333333333333333333333333333333333333333333333333333"
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "synapsor.execution-receipt.v1",
|
|
3
|
+
"writeback_job_id": "wbj_124",
|
|
4
|
+
"proposal_id": "wrp_124",
|
|
5
|
+
"runner_id": "runner_123",
|
|
6
|
+
"status": "conflict",
|
|
7
|
+
"rows_affected": 0,
|
|
8
|
+
"idempotency_key": "wrp_124:INV-3001",
|
|
9
|
+
"previous_version": "2026-06-20T14:31:08Z",
|
|
10
|
+
"new_version": "2026-06-20T14:39:19Z",
|
|
11
|
+
"source_database_mutated": false,
|
|
12
|
+
"executed_at": "2026-06-20T14:40:19Z",
|
|
13
|
+
"safe_error_code": "VERSION_CONFLICT",
|
|
14
|
+
"receipt_hash": "sha256:4444444444444444444444444444444444444444444444444444444444444444"
|
|
15
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "synapsor.runner-registration.v1",
|
|
3
|
+
"runner_id": "runner_123",
|
|
4
|
+
"runner_version": "0.1.0-alpha.0",
|
|
5
|
+
"engines": [
|
|
6
|
+
"postgres",
|
|
7
|
+
"mysql"
|
|
8
|
+
],
|
|
9
|
+
"capabilities": [
|
|
10
|
+
"single_row_update",
|
|
11
|
+
"idempotency_receipts",
|
|
12
|
+
"version_conflict_guard"
|
|
13
|
+
],
|
|
14
|
+
"scope": {
|
|
15
|
+
"project_id": "acme-support",
|
|
16
|
+
"source_ids": [
|
|
17
|
+
"src_pg_acme",
|
|
18
|
+
"src_mysql_acme"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"registered_at": "2026-06-20T14:30:00Z"
|
|
22
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "synapsor.writeback-job.v1",
|
|
3
|
+
"writeback_job_id": "wbj_123",
|
|
4
|
+
"proposal_id": "wrp_123",
|
|
5
|
+
"proposal_version": 1,
|
|
6
|
+
"proposal_hash": "sha256:2222222222222222222222222222222222222222222222222222222222222222",
|
|
7
|
+
"runner_scope": {
|
|
8
|
+
"project_id": "acme-support",
|
|
9
|
+
"source_id": "src_pg_acme"
|
|
10
|
+
},
|
|
11
|
+
"engine": "postgres",
|
|
12
|
+
"operation": "single_row_update",
|
|
13
|
+
"target": {
|
|
14
|
+
"schema": "public",
|
|
15
|
+
"table": "invoices",
|
|
16
|
+
"primary_key": {
|
|
17
|
+
"column": "id",
|
|
18
|
+
"value": "INV-3001"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"tenant_guard": {
|
|
22
|
+
"column": "tenant_id",
|
|
23
|
+
"value": "acme"
|
|
24
|
+
},
|
|
25
|
+
"allowed_columns": [
|
|
26
|
+
"late_fee_cents",
|
|
27
|
+
"waiver_reason"
|
|
28
|
+
],
|
|
29
|
+
"patch": {
|
|
30
|
+
"late_fee_cents": 0,
|
|
31
|
+
"waiver_reason": "approved support waiver"
|
|
32
|
+
},
|
|
33
|
+
"conflict_guard": {
|
|
34
|
+
"kind": "column",
|
|
35
|
+
"column": "updated_at",
|
|
36
|
+
"expected_value": "2026-06-20T14:31:08Z"
|
|
37
|
+
},
|
|
38
|
+
"idempotency_key": "wrp_123:INV-3001",
|
|
39
|
+
"lease": {
|
|
40
|
+
"lease_id": "lease_123",
|
|
41
|
+
"attempt": 1,
|
|
42
|
+
"expires_at": "2026-06-20T14:36:00Z"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synapsor/runner",
|
|
3
|
-
"version": "0.1.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Commit-safe MCP runner for Postgres and MySQL agents",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -16,11 +16,16 @@
|
|
|
16
16
|
"dist/runner.mjs",
|
|
17
17
|
"docs/**/*.md",
|
|
18
18
|
"examples/dangerous-mcp-tools.json",
|
|
19
|
+
"examples/app-owned-writeback/**",
|
|
20
|
+
"examples/mcp-postgres-billing-app-handler/**",
|
|
19
21
|
"examples/openai-agents-http/**",
|
|
20
22
|
"examples/openai-agents-stdio/**",
|
|
21
23
|
"examples/reference-support-billing-app/**",
|
|
24
|
+
"fixtures/**",
|
|
25
|
+
"schemas/**",
|
|
22
26
|
"recipes/**/*.json",
|
|
23
27
|
"README.md",
|
|
28
|
+
"CHANGELOG.md",
|
|
24
29
|
"LICENSE",
|
|
25
30
|
"NOTICE",
|
|
26
31
|
"TRADEMARKS.md"
|