@synapsor/runner 1.6.2 → 1.6.4

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 (116) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +141 -2
  3. package/CONTRIBUTING.md +10 -3
  4. package/README.md +65 -83
  5. package/SECURITY.md +14 -2
  6. package/THREAT_MODEL.md +64 -4
  7. package/dist/authoring.mjs +151 -16
  8. package/dist/cli.d.ts +31 -3
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/local-ui.d.ts +145 -1
  11. package/dist/local-ui.d.ts.map +1 -1
  12. package/dist/runner.mjs +37488 -19009
  13. package/dist/runtime.mjs +4056 -235
  14. package/dist/shadow.mjs +2423 -65
  15. package/docs/README.md +36 -2
  16. package/docs/agent-guided-setup.md +239 -0
  17. package/docs/aggregate-reads.md +14 -5
  18. package/docs/app-owned-executors.md +5 -6
  19. package/docs/approval-roles-and-operator-identity.md +353 -0
  20. package/docs/auto-boundary-and-scoped-explore.md +89 -11
  21. package/docs/capability-authoring.md +21 -2
  22. package/docs/client-recipes.md +1 -1
  23. package/docs/cloud-mode.md +7 -7
  24. package/docs/conformance.md +6 -3
  25. package/docs/current-scope.md +32 -2
  26. package/docs/cursor-plugin.md +3 -3
  27. package/docs/database-enforced-scope.md +6 -0
  28. package/docs/dsl-json-parity.md +75 -0
  29. package/docs/dsl-reference.md +22 -1
  30. package/docs/fresh-developer-usability.md +155 -80
  31. package/docs/getting-started-own-database.md +45 -44
  32. package/docs/guarded-crud-writeback.md +19 -0
  33. package/docs/guided-onboarding.md +399 -0
  34. package/docs/human-attention-notifications.md +367 -0
  35. package/docs/limitations.md +49 -13
  36. package/docs/local-mode.md +36 -22
  37. package/docs/mcp-audit.md +14 -14
  38. package/docs/mcp-client-setup.md +11 -14
  39. package/docs/mcp-clients.md +1 -1
  40. package/docs/migrating-to-synapsor-spec.md +42 -0
  41. package/docs/openai-agents-sdk.md +2 -2
  42. package/docs/production.md +39 -0
  43. package/docs/proposal-evidence-freshness.md +7 -7
  44. package/docs/recipes.md +6 -6
  45. package/docs/release-notes.md +144 -4
  46. package/docs/release-policy.md +20 -7
  47. package/docs/reversible-change-sets.md +1 -1
  48. package/docs/reviewed-database-views.md +132 -0
  49. package/docs/reviewed-relationships.md +245 -0
  50. package/docs/rfcs/006-reviewed-reversible-change-sets.md +1 -1
  51. package/docs/runner-bundles.md +7 -7
  52. package/docs/runner-config-reference.md +132 -0
  53. package/docs/running-a-runner-fleet.md +16 -1
  54. package/docs/schema-api-candidates.md +1 -1
  55. package/docs/security-boundary.md +54 -0
  56. package/docs/store-lifecycle.md +20 -1
  57. package/docs/supervised-automatic-apply.md +267 -0
  58. package/docs/troubleshooting-first-run.md +85 -10
  59. package/docs/use-your-own-database.md +6 -4
  60. package/docs/workbench-ask.md +279 -0
  61. package/docs/writeback-executors.md +7 -7
  62. package/examples/auto-boundary-churn/README.md +1 -1
  63. package/examples/community-solar-clean-room/README.md +7 -0
  64. package/examples/community-solar-clean-room/docker-compose.yml +16 -0
  65. package/examples/community-solar-clean-room/package.json +15 -0
  66. package/examples/community-solar-clean-room/prisma/schema.prisma +171 -0
  67. package/examples/community-solar-clean-room/seed/postgres.sql +571 -0
  68. package/examples/fitflow-guided-onboarding/README.md +43 -0
  69. package/examples/fitflow-guided-onboarding/app/page.tsx +8 -0
  70. package/examples/fitflow-guided-onboarding/docker-compose.yml +16 -0
  71. package/examples/fitflow-guided-onboarding/package.json +18 -0
  72. package/examples/fitflow-guided-onboarding/prisma/schema.prisma +98 -0
  73. package/examples/fitflow-guided-onboarding/seed/postgres.sql +401 -0
  74. package/examples/openai-agents-http/Makefile +1 -1
  75. package/examples/openai-agents-http/README.md +1 -1
  76. package/examples/openai-agents-stdio/Makefile +1 -1
  77. package/examples/openai-agents-stdio/README.md +2 -2
  78. package/examples/openai-agents-stdio/agent.py +1 -4
  79. package/examples/operator-oidc/issuer.mjs +188 -0
  80. package/examples/reference-support-billing-app/README.md +16 -16
  81. package/examples/retail-clean-room/README.md +7 -0
  82. package/examples/retail-clean-room/docker-compose.yml +16 -0
  83. package/examples/retail-clean-room/package.json +9 -0
  84. package/examples/retail-clean-room/prisma/schema.prisma +239 -0
  85. package/examples/retail-clean-room/seed/postgres.sql +781 -0
  86. package/examples/retail-clean-room/view-recipe/average-retained-revenue.synapsor.sql +21 -0
  87. package/examples/retail-clean-room/view-recipe/synapsor.runner.json +25 -0
  88. package/examples/support-plan-credit/README.md +6 -2
  89. package/examples/support-plan-credit/mcp-client-examples/claude-code.sh +1 -4
  90. package/examples/support-plan-credit/mcp-client-examples/claude-desktop.json +1 -4
  91. package/examples/support-plan-credit/mcp-client-examples/codex.config.toml +1 -4
  92. package/examples/support-plan-credit/mcp-client-examples/cursor-global.mcp.json +1 -4
  93. package/examples/support-plan-credit/mcp-client-examples/cursor-project.mcp.json +1 -4
  94. package/examples/support-plan-credit/mcp-client-examples/generic-stdio.json +1 -4
  95. package/examples/support-plan-credit/mcp-client-examples/generic-stdio.mjs +1 -1
  96. package/examples/support-plan-credit/mcp-client-examples/google-adk.py +1 -1
  97. package/examples/support-plan-credit/mcp-client-examples/langchain.mjs +1 -1
  98. package/examples/support-plan-credit/mcp-client-examples/llamaindex.py +1 -1
  99. package/examples/support-plan-credit/mcp-client-examples/openai-agents-stdio.ts +1 -1
  100. package/examples/support-plan-credit/mcp-client-examples/vscode.mcp.json +1 -4
  101. package/fixtures/compatibility/published-1.6.3/manifest.json +76 -0
  102. package/fixtures/compatibility/published-1.6.3/sources/packages/dsl/examples/aggregate-read.synapsor.sql +21 -0
  103. package/fixtures/compatibility/published-1.6.3/sources/packages/dsl/examples/billing-late-fee.synapsor.sql +56 -0
  104. package/fixtures/compatibility/published-1.6.3/sources/packages/dsl/examples/bounded-set-multi-term.synapsor.sql +30 -0
  105. package/fixtures/compatibility/published-1.6.3/sources/packages/dsl/examples/principal-row-scope.synapsor.sql +23 -0
  106. package/fixtures/compatibility/published-1.6.3/sources/packages/spec/fixtures/conformance/aggregate-read/contract.json +119 -0
  107. package/fixtures/compatibility/published-1.6.3/sources/packages/spec/fixtures/conformance/approval-quorum/contract.json +44 -0
  108. package/fixtures/compatibility/published-1.6.3/sources/packages/spec/fixtures/conformance/bounded-set-threats/contract.json +115 -0
  109. package/fixtures/compatibility/published-1.6.3/sources/packages/spec/fixtures/conformance/principal-row-scope/contract.json +78 -0
  110. package/fixtures/compatibility/published-1.6.3/sources/packages/spec/fixtures/conformance/proposal-capability/contract.json +101 -0
  111. package/fixtures/compatibility/published-1.6.3/sources/packages/spec/fixtures/conformance/reversible-change-sets/contract.json +98 -0
  112. package/fixtures/compatibility/published-1.6.3/sources/packages/spec/fixtures/valid/basic-read.contract.json +60 -0
  113. package/llms.txt +10 -5
  114. package/package.json +11 -3
  115. package/schemas/schema-candidate-review.schema.json +42 -0
  116. package/schemas/synapsor.runner.schema.json +227 -4
@@ -0,0 +1,367 @@
1
+ # Human Attention And Notifications
2
+
3
+ Runner keeps the full lifecycle in its ledger and secured Workbench. External
4
+ notifications are a quiet interruption channel for meaningful human attention,
5
+ not a copy of every state transition.
6
+
7
+ Notifications are additive, local-first, and disabled by default. Runner needs
8
+ no webhook, network connection, Cloud account, or continuously running
9
+ dispatcher for its existing proposal, approval, apply, receipt, and replay
10
+ flows.
11
+
12
+ ## Architecture
13
+
14
+ ```text
15
+ authoritative ledger transition
16
+ -> immutable attention event in the same store transaction
17
+ -> coalesced Human Attention item
18
+ -> separately operated dispatcher
19
+ -> configured JSONL or signed webhook sink
20
+ -> authenticated human opens Workbench
21
+ -> existing approval/recovery control handles the item
22
+ ```
23
+
24
+ An event informs. It never authorizes. A webhook response, delivery receipt,
25
+ inbox acknowledgement, or notification replay cannot activate a capability,
26
+ approve a proposal, apply a write, cancel work, or resolve an unknown database
27
+ outcome.
28
+
29
+ SQLite and shared PostgreSQL runtime stores retain the same event identities,
30
+ attention projection, acknowledgement, and delivery state.
31
+
32
+ ## Quiet Default
33
+
34
+ Under the default route, successful activity remains visible in the ledger,
35
+ Workbench timeline, CLI, metrics, and optional digest, but does not interrupt a
36
+ human.
37
+
38
+ No immediate external notification is sent by default for:
39
+
40
+ - proposal creation, policy auto-approval, approval, or queueing;
41
+ - a worker lease or individual retry;
42
+ - successful manual or automatic apply;
43
+ - an isolated conflict that Runner handled safely;
44
+ - planned worker start, pause, resume, drain, or stop;
45
+ - capability activation by the same operator.
46
+
47
+ Immediate delivery defaults to states where timely attention matters:
48
+
49
+ - human approval required;
50
+ - UNKNOWN transaction outcome or reconciliation required;
51
+ - dead-letter work;
52
+ - sustained worker-health failure;
53
+ - queue depth/age crossing an operator threshold;
54
+ - schema drift or stale digest blocking authority;
55
+ - invalidated writer credential posture;
56
+ - critical policy/limit failure;
57
+ - an approved proposal approaching expiry while action is still possible.
58
+
59
+ Informational success events can be sent only through an explicit all-events
60
+ route or periodic digest.
61
+
62
+ ## Events And Attention Items
63
+
64
+ Events are immutable audit facts. Attention items are durable incident
65
+ projections over related events.
66
+
67
+ For example, ten proposals requiring the same role can produce ten immutable
68
+ events but one item saying that ten proposals need review. Repeated worker
69
+ failures, queue backlog, or the same schema-drift condition update one item and
70
+ its occurrence count. Retry attempts stay internal until the configured
71
+ attempt/duration threshold is crossed.
72
+
73
+ Attention states are:
74
+
75
+ - `open`;
76
+ - `acknowledged`;
77
+ - `resolved`;
78
+ - `expired`.
79
+
80
+ Acknowledgement means only that a verified operator saw the item. It is not
81
+ approval or resolution.
82
+
83
+ ## Configure Sinks
84
+
85
+ This operator-owned config enables one signed webhook and one optional
86
+ development JSONL stream:
87
+
88
+ ```json
89
+ {
90
+ "notifications": {
91
+ "enabled": true,
92
+ "workbench_url_env": "SYNAPSOR_WORKBENCH_URL",
93
+ "sinks": [
94
+ {
95
+ "id": "operations",
96
+ "type": "webhook",
97
+ "enabled": true,
98
+ "url_env": "SYNAPSOR_NOTIFY_WEBHOOK_URL",
99
+ "signing_secret_env": "SYNAPSOR_NOTIFY_SIGNING_SECRET",
100
+ "minimum_severity": "warning",
101
+ "events": [
102
+ "proposal.review_required",
103
+ "worker.dead_lettered",
104
+ "worker.unknown_outcome",
105
+ "worker.reconciliation_required",
106
+ "schema.drift_detected"
107
+ ],
108
+ "capabilities": ["billing.propose_small_credit"],
109
+ "environments": ["staging", "production"],
110
+ "delivery": "immediate",
111
+ "max_attempts": 5,
112
+ "timeout_ms": 3000,
113
+ "max_response_bytes": 1024,
114
+ "replay_window_seconds": 300,
115
+ "allow_private_destinations": false,
116
+ "recovery_notifications": false,
117
+ "budgets": {
118
+ "per_minute": 10,
119
+ "per_hour": 100,
120
+ "immediate_informational_per_hour": 0,
121
+ "aggregation_window_seconds": 300,
122
+ "cooldown_seconds": 600,
123
+ "max_unresolved_reminders": 3,
124
+ "digest_cadence_minutes": 1440,
125
+ "escalation_delay_seconds": 60,
126
+ "retry_attempt_threshold": 3,
127
+ "degraded_duration_seconds": 120,
128
+ "queue_depth_threshold": 100,
129
+ "queue_age_seconds": 300
130
+ },
131
+ "quiet_hours": {
132
+ "start_utc_hour": 22,
133
+ "end_utc_hour": 7
134
+ }
135
+ },
136
+ {
137
+ "id": "development",
138
+ "type": "jsonl",
139
+ "enabled": false,
140
+ "destination": "stdout",
141
+ "minimum_severity": "informational",
142
+ "delivery": "all"
143
+ }
144
+ ]
145
+ }
146
+ }
147
+ ```
148
+
149
+ Set values only in the operator environment:
150
+
151
+ ```bash
152
+ export SYNAPSOR_WORKBENCH_URL=https://runner-ops.example.internal
153
+ export SYNAPSOR_NOTIFY_WEBHOOK_URL=https://events.example.com/synapsor
154
+ export SYNAPSOR_NOTIFY_SIGNING_SECRET='at-least-32-random-bytes'
155
+ ```
156
+
157
+ The config stores environment-variable names, not URLs or secrets. Events never
158
+ contain credentials, database URLs, SQL, source rows, aggregate group results,
159
+ kept-out fields, trusted tenant/principal values, sensitive arguments, or
160
+ authority tokens.
161
+
162
+ ## Route By Destination
163
+
164
+ Every sink has its own event, severity, capability, environment, and delivery
165
+ route. A practical split is:
166
+
167
+ | Sink | Route |
168
+ | --- | --- |
169
+ | Workbench | Complete event and attention history |
170
+ | Team chat webhook | Review-required and operational warnings |
171
+ | Incident webhook | UNKNOWN, reconciliation, dead letter, sustained worker failure |
172
+ | Email-provider webhook | Daily digest |
173
+ | Audit webhook | Explicit all-events redacted stream |
174
+
175
+ The ledger and Workbench remain the source of truth.
176
+
177
+ ## Operate Without Copying IDs
178
+
179
+ Inspect the highest-priority item:
180
+
181
+ ```bash
182
+ synapsor-runner attention list --config ./synapsor.runner.json
183
+ synapsor-runner attention show --config ./synapsor.runner.json
184
+ ```
185
+
186
+ Use `attention show <attention_id>` only when selecting a specific item. JSON
187
+ automation is available with `--json`.
188
+
189
+ Acknowledgement is explicit:
190
+
191
+ ```bash
192
+ synapsor-runner attention acknowledge --actor alice \
193
+ --config ./synapsor.runner.json
194
+ ```
195
+
196
+ Production acknowledgement follows configured verified operator identity and is
197
+ cryptographically bound to the exact item digest and occurrence.
198
+
199
+ Inspect and test delivery:
200
+
201
+ ```bash
202
+ synapsor-runner notifications status --config ./synapsor.runner.json
203
+ synapsor-runner notifications test --sink operations \
204
+ --config ./synapsor.runner.json
205
+ synapsor-runner notifications dispatch --sink operations --limit 20 \
206
+ --config ./synapsor.runner.json
207
+ ```
208
+
209
+ `notifications test` sends an unmistakable synthetic event containing no
210
+ database or proposal data. Opening Workbench, installing Runner, and starting
211
+ MCP never start outbound delivery.
212
+
213
+ Requeue one dead-letter delivery:
214
+
215
+ ```bash
216
+ synapsor-runner notifications replay latest --yes \
217
+ --reason "Webhook repaired and synthetic test passed" \
218
+ --config ./synapsor.runner.json
219
+ ```
220
+
221
+ This replays only the immutable redacted notification. It does not replay an
222
+ approval or database mutation. Replay is an operator recovery action and
223
+ requires the configured `signed_key` or `jwt_oidc` identity. Runner binds the
224
+ verified decision to the exact delivery revision and records a redacted
225
+ immutable `notification.replayed` audit event.
226
+
227
+ ## Webhook Contract
228
+
229
+ Runner sends a CloudEvents 1.0 structured JSON body with content type
230
+ `application/cloudevents+json`. Important headers are:
231
+
232
+ ```text
233
+ X-Synapsor-Event-Id
234
+ X-Synapsor-Timestamp
235
+ X-Synapsor-Signature-Version: v1
236
+ X-Synapsor-Signature: sha256=<hex HMAC>
237
+ ```
238
+
239
+ The HMAC-SHA-256 input is the UTF-8 string
240
+ `v1.<timestamp>.<event-id>.<exact-body>`. Receivers must:
241
+
242
+ 1. Require signature version `v1`.
243
+ 2. Reject timestamps outside the configured replay window.
244
+ 3. Verify the HMAC with a timing-safe comparison.
245
+ 4. Deduplicate the stable event ID.
246
+ 5. Return only a bounded transport acknowledgement.
247
+
248
+ Runner ignores response content. A receiver cannot return a command.
249
+
250
+ A minimal Node receiver can verify the exact bytes before parsing JSON:
251
+
252
+ ```js
253
+ import { createHmac, timingSafeEqual } from "node:crypto";
254
+
255
+ export function verifySynapsorWebhook(rawBody, headers, secret, now = Date.now()) {
256
+ const eventId = headers["x-synapsor-event-id"];
257
+ const timestamp = headers["x-synapsor-timestamp"];
258
+ const version = headers["x-synapsor-signature-version"];
259
+ const suppliedHeader = headers["x-synapsor-signature"];
260
+ if (!eventId || !timestamp || version !== "v1" || !suppliedHeader?.startsWith("sha256=")) {
261
+ return false;
262
+ }
263
+
264
+ const timestampSeconds = Number(timestamp);
265
+ const ageMs = Math.abs(now - timestampSeconds * 1000);
266
+ if (!Number.isSafeInteger(timestampSeconds) || ageMs > 300_000) return false;
267
+
268
+ const expected = Buffer.from(
269
+ createHmac("sha256", secret)
270
+ .update(`v1.${timestamp}.${eventId}.${rawBody}`, "utf8")
271
+ .digest("hex"),
272
+ "hex",
273
+ );
274
+ const supplied = Buffer.from(suppliedHeader.slice("sha256=".length), "hex");
275
+ return expected.length === supplied.length && timingSafeEqual(expected, supplied);
276
+ }
277
+ ```
278
+
279
+ Read the request as raw UTF-8 bytes for verification; reserializing parsed JSON
280
+ changes the signed body. Store the event ID for at least the replay window and
281
+ reject a duplicate before processing it.
282
+
283
+ The structured body resembles:
284
+
285
+ ```json
286
+ {
287
+ "specversion": "1.0",
288
+ "id": "aev_...",
289
+ "type": "ai.synapsor.worker.reconciliation_required",
290
+ "source": "urn:synapsor:runner:production",
291
+ "time": "2026-07-25T00:00:00.000Z",
292
+ "datacontenttype": "application/json",
293
+ "subject": "billing.propose_small_credit",
294
+ "data": {
295
+ "schema_version": "synapsor.notification.v1",
296
+ "severity": "critical",
297
+ "environment": "production",
298
+ "capability": "billing.propose_small_credit",
299
+ "contract_digest": "sha256:...",
300
+ "summary": "A guarded apply needs operator reconciliation.",
301
+ "workbench_url": "https://runner-ops.example.internal/attention/att_..."
302
+ }
303
+ }
304
+ ```
305
+
306
+ The Workbench URL identifies an item but carries no approval or recovery
307
+ authority. The operator must authenticate normally.
308
+
309
+ HTTPS is required by default. Redirects and unsafe loopback, link-local,
310
+ metadata, multicast, unspecified, private, and rebinding destinations are
311
+ refused. Intentional private destinations require both
312
+ `allow_private_destinations: true` and an exact `private_host_allowlist`.
313
+
314
+ ## Delivery And Noise Guarantees
315
+
316
+ Delivery is at least once. Sink-specific records use atomic leases, fencing,
317
+ bounded retries, jittered backoff, timeout, maximum attempts, and dead-letter
318
+ state. Repeated delivery cannot repeat proposal authority or source mutation.
319
+
320
+ When a non-critical budget is exhausted, Runner preserves every event, updates
321
+ the Workbench item, and suppresses or batches external messages. Critical events
322
+ bypass ordinary quiet hours and budgets but still coalesce under a separate
323
+ bounded emergency ceiling.
324
+
325
+ Optional digests report redacted counts for proposals, auto-approval, apply,
326
+ review-required work, conflicts, retries, dead letters, limits, queue age, and
327
+ unresolved critical items. They link to authenticated Workbench detail.
328
+
329
+ Recovery messages are off by default. When an incident resolves, Workbench is
330
+ updated; an external recovery message is sent only when that sink explicitly
331
+ enables `recovery_notifications` or the critical-route policy requires it.
332
+
333
+ ## Retry And Dead-Letter Runbook
334
+
335
+ 1. Run `notifications status --json` and inspect sink health, pending delivery,
336
+ and dead-letter counts.
337
+ 2. Open the corresponding Workbench attention item. Confirm the authoritative
338
+ proposal/worker state before changing delivery.
339
+ 3. Repair the operator-owned destination, DNS policy, TLS, or secret rotation.
340
+ 4. Send `notifications test --sink <id>`; it contains no database data.
341
+ 5. Run `notifications dispatch --sink <id> --limit 20` to drain eligible work.
342
+ 6. Replay a dead-letter delivery only with
343
+ `notifications replay <delivery_id> --yes --reason "<why replay is safe>"`.
344
+
345
+ Replay preserves the original immutable event ID. It cannot re-run the database
346
+ operation. The exact recovery decision must be verified through the configured
347
+ operator identity. A still-failing sink remains observable and does not rewrite
348
+ the underlying proposal outcome.
349
+
350
+ ## Supervised Worker Health Gate
351
+
352
+ An exact supervised-worker capability may list:
353
+
354
+ ```json
355
+ {
356
+ "required_attention_sinks": ["operations"]
357
+ }
358
+ ```
359
+
360
+ If every required sink is unhealthy or untested, an otherwise eligible
361
+ policy-approved production write remains queued. Workbench explains that
362
+ operator visibility is unavailable. A healthy sink does not approve anything;
363
+ after recovery, the worker still repeats every ordinary digest, policy, scope,
364
+ freshness, limit, credential, lease, and guarded-write check.
365
+
366
+ See [Operator-Supervised Automatic
367
+ Apply](supervised-automatic-apply.md) for the execution boundary.
@@ -1,11 +1,14 @@
1
1
  # Limitations
2
2
 
3
- Synapsor Runner is intentionally narrow. Version 1.6 adds deterministic
4
- whole-application boundary drafting and a local authoring-only Explore ->
5
- Protect path on top of guarded writes. Version 1.6.1 also adds opt-in
6
- proposal/evidence freshness for exact same-source direct-SQL proposals. It does
7
- not turn Runner into a generic database query tool, claim Synapsor Cloud scale,
8
- or claim an enterprise SLA.
3
+ Synapsor Runner is intentionally narrow. It combines deterministic
4
+ whole-application boundary drafting, local authoring-only Explore -> Protect,
5
+ guarded writes, opt-in proposal/evidence freshness, verified operator identity,
6
+ default-off supervised execution, and quiet human-attention delivery. Reviewed
7
+ aggregate paths are limited to proven star/depth-two many-to-one relationships,
8
+ not a general join planner. Optional local Workbench Ask is a client of the
9
+ existing reviewed tools; the complete no-model path remains the default.
10
+ Runner does not become a generic database query tool, Synapsor Cloud, or an
11
+ enterprise SLA.
9
12
 
10
13
  ## Supported
11
14
 
@@ -15,8 +18,9 @@ or claim an enterprise SLA.
15
18
  - Optional shared Postgres proposal/evidence/replay runtime store for MCP serving.
16
19
  - Asymmetric claim-bound Streamable HTTP sessions and explicit readiness.
17
20
  - Native Postgres/MySQL source pools and operational/fleet-wide rate limits.
18
- - Verified operator approval through CLI, optional distinct-reviewer quorum,
19
- and shared local review UI reads.
21
+ - Verified operator approval through CLI or the secured local Workbench,
22
+ optional distinct-reviewer quorum, separate apply authority, and
23
+ proposal-centered lifecycle inspection.
20
24
  - Optional live target and explicitly declared supporting-row freshness checks
21
25
  before every approval, with immutable proof binding and final transactional
22
26
  revalidation for PostgreSQL/MySQL direct SQL writeback.
@@ -59,10 +63,20 @@ or claim an enterprise SLA.
59
63
  existing Synapsor definitions. Generated authority starts disabled.
60
64
  - Local development/staging Scoped Explore through exactly
61
65
  `app.describe_data` and `app.explore_data`, with no SQL-string argument.
66
+ - Optional development/staging loopback Workbench Ask through OpenAI,
67
+ Anthropic, or a configured OpenAI-compatible endpoint. Provider calls use the
68
+ exact active MCP/runtime surface, explicit direct-egress consent, in-memory
69
+ credential/history state, fixed tool/time/size/token bounds, and
70
+ proposal-only write behavior.
62
71
  - Reviewed PM-style aggregate Explore with `count`, `count_distinct`, `sum`,
63
72
  `avg`, categorical dimensions, fixed time buckets, typed filters, bounded
64
- top-N, optional one-hop proven many-to-one relationships, cohort suppression,
65
- and durable extraction/differencing budgets.
73
+ top-N, up to three reviewed relationship paths of at most two proven
74
+ many-to-one links each, cohort suppression, and durable
75
+ extraction/differencing budgets.
76
+ - Demand-driven operator review for an exact catalog-proven relationship,
77
+ including an explicit missing-row choice for nullable links. The model cannot
78
+ activate a relationship, and every participating relation receives trusted
79
+ tenant/principal scope.
66
80
  - Protect This Query to public DSL, canonical JSON, tests, and a disabled named
67
81
  capability that survives Explore shutdown after exact-digest activation.
68
82
  - Generation-lock drift detection for generated authority. Manually authored
@@ -75,6 +89,13 @@ or claim an enterprise SLA.
75
89
  and scoped tamper-evident JSON/Markdown/PDF ledger reports.
76
90
  - Off-by-default graduated-trust recommendations that require verified operator
77
91
  review and explicit artifact export without activation.
92
+ - Default-off operator-supervised apply for eligible exact-row direct
93
+ `INSERT`/`UPDATE`, requiring both public contract permission and an
94
+ independent deployment allowlist for the exact active digest. It reuses
95
+ guarded apply and preserves legacy `AUTO APPROVE` as manual-apply.
96
+ - Durable redacted human-attention events, a coalesced Workbench inbox,
97
+ no-ID CLI inspection, optional JSONL output, and signed generic HTTPS
98
+ webhooks with quiet routing, budgets, digests, and safe delivery replay.
78
99
 
79
100
  ## Runtime Contract
80
101
 
@@ -105,16 +126,25 @@ truth for the model-facing tools.
105
126
  - Inferred compensation for app-owned handlers or external effects.
106
127
  - General restoration of hard-deleted rows, cascades, or trigger side effects.
107
128
  - Model-callable approval or commit tools.
129
+ - Model-callable worker, notification-routing, acknowledgement, recovery, or
130
+ reconciliation controls.
108
131
  - Generic MCP firewall behavior.
109
132
  - Prompt-injection prevention.
110
133
  - Unbounded/high-throughput or multi-region ledger scale.
111
134
  - Managed fleet, SLA, compliance certification, or production support guarantee.
112
135
  - Production, shared HTTP, remote, or non-loopback Scoped Explore.
136
+ - Production, shared HTTP, remote, or non-loopback Workbench Ask; model-facing
137
+ provider configuration; Synapsor-relayed provider traffic; durable chat
138
+ history; automatic provider retries; exact monetary spend enforcement; or
139
+ universal compatibility with OpenAI-compatible servers.
140
+ - Automatic supervised execution for hard DELETE, reversible changes, bounded
141
+ sets, app-owned/external effects, or writes without deterministic conflict,
142
+ deduplication, freshness, and receipt authority.
113
143
  - Arbitrary aggregate expressions, dynamic identifiers, unrestricted joins,
114
144
  many-to-many joins, formulas, window functions, subqueries, `HAVING`,
115
- user-defined functions, or a statistical privacy guarantee. Version 1.6
116
- supports only the explicitly reviewed authoring cube described above and
117
- fixed protected named capabilities produced from it.
145
+ user-defined functions, or a statistical privacy guarantee. Runner supports
146
+ only the explicitly reviewed authoring cube described above and fixed
147
+ protected named capabilities produced from it.
118
148
  - Automatic policy widening or activation from graduated-trust metrics.
119
149
  - Immutable/WORM compliance storage from the local report exporter.
120
150
 
@@ -149,6 +179,12 @@ jobs. Mixed-minor v3/v4 rolling compensation is not claimed.
149
179
  See [Running A Small Runner
150
180
  Fleet](running-a-runner-fleet.md).
151
181
 
182
+ Workbench Ask token accounting uses provider-reported usage. A provider that
183
+ omits or misreports usage cannot provide exact token or monetary enforcement.
184
+ Runner still enforces request/response, tool-result, iteration, history, and
185
+ wall-clock bounds. A provider outage does not disable the no-model composer or
186
+ external MCP path. See [Workbench Ask With Your Model](workbench-ask.md).
187
+
152
188
  Use this wording:
153
189
 
154
190
  ```text
@@ -44,13 +44,13 @@ when you do not want to change your host Node version.
44
44
  Create a starter config without putting credentials in the file:
45
45
 
46
46
  ```bash
47
- npx -y -p @synapsor/runner synapsor-runner init --engine postgres --mode review
47
+ npx -y @synapsor/runner init --engine postgres --mode review
48
48
  ```
49
49
 
50
50
  For MySQL:
51
51
 
52
52
  ```bash
53
- npx -y -p @synapsor/runner synapsor-runner init --engine mysql --mode review --output synapsor.mysql.runner.json
53
+ npx -y @synapsor/runner init --engine mysql --mode review --output synapsor.mysql.runner.json
54
54
  ```
55
55
 
56
56
  The generated config uses environment-variable names for read/write URLs and trusted context. Edit the table, column, and capability names before serving tools.
@@ -63,8 +63,8 @@ persisted into proposals, evidence, query audit, runner state, or replay.
63
63
  For a reviewed own-database setup generated from explicit selections, use:
64
64
 
65
65
  ```bash
66
- npx -y -p @synapsor/runner synapsor-runner init --spec onboarding-selection.json --non-interactive
67
- npx -y -p @synapsor/runner synapsor-runner doctor --config synapsor.runner.json
66
+ npx -y @synapsor/runner init --spec onboarding-selection.json --non-interactive
67
+ npx -y @synapsor/runner doctor --config synapsor.runner.json
68
68
  ```
69
69
 
70
70
  `doctor --config` checks config validation, required environment variables,
@@ -76,7 +76,7 @@ and the semantic MCP tool boundary without printing credential values.
76
76
  Use stdio for local MCP clients that launch Synapsor Runner:
77
77
 
78
78
  ```bash
79
- npx -y -p @synapsor/runner synapsor-runner mcp serve \
79
+ npx -y @synapsor/runner mcp serve \
80
80
  --config ./synapsor.runner.json \
81
81
  --store ./.synapsor/local.db
82
82
  ```
@@ -87,7 +87,7 @@ MCP client:
87
87
  ```bash
88
88
  export SYNAPSOR_RUNNER_HTTP_TOKEN="$(node -e 'process.stdout.write(require("node:crypto").randomBytes(32).toString("base64url"))')"
89
89
 
90
- npx -y -p @synapsor/runner synapsor-runner mcp serve-streamable-http \
90
+ npx -y @synapsor/runner mcp serve-streamable-http \
91
91
  --config ./synapsor.runner.json \
92
92
  --store ./.synapsor/local.db \
93
93
  --auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN
@@ -131,19 +131,19 @@ If neither is set, the CLI uses:
131
131
  List proposals:
132
132
 
133
133
  ```bash
134
- npx -y -p @synapsor/runner synapsor-runner proposals list --store ./.synapsor/local.db
134
+ npx -y @synapsor/runner proposals list --store ./.synapsor/local.db
135
135
  ```
136
136
 
137
137
  Show a proposal:
138
138
 
139
139
  ```bash
140
- npx -y -p @synapsor/runner synapsor-runner proposals show wrp_123 --store ./.synapsor/local.db
140
+ npx -y @synapsor/runner proposals show wrp_123 --store ./.synapsor/local.db
141
141
  ```
142
142
 
143
143
  Check a freshness-enabled proposal without copying its id:
144
144
 
145
145
  ```bash
146
- npx -y -p @synapsor/runner synapsor-runner proposals check-freshness latest \
146
+ npx -y @synapsor/runner proposals check-freshness latest \
147
147
  --config ./synapsor.runner.json \
148
148
  --store ./.synapsor/local.db
149
149
  ```
@@ -151,13 +151,19 @@ npx -y -p @synapsor/runner synapsor-runner proposals check-freshness latest \
151
151
  Approve:
152
152
 
153
153
  ```bash
154
- npx -y -p @synapsor/runner synapsor-runner proposals approve wrp_123 \
154
+ npx -y @synapsor/runner proposals approve wrp_123 \
155
155
  --config ./synapsor.runner.json \
156
156
  --store ./.synapsor/local.db \
157
157
  --actor local_reviewer \
158
158
  --yes
159
159
  ```
160
160
 
161
+ The `--actor` example is the unverified local-development path. Shared and
162
+ production operation should require `signed_key` or `jwt_oidc`, resolve the
163
+ contract's exact role from verified identity, and authorize apply separately.
164
+ See [Approval Roles And Verified Operator
165
+ Identity](approval-roles-and-operator-identity.md).
166
+
161
167
  Before approval, the CLI prints the reviewer-critical proposal details: trusted principal, tenant, target row, primary key, required role, proposal hash/version, allowed columns, conflict guard, evidence bundle/query fingerprint, writeback boundary, source mutation state, and exact before/after diff. Interactive approval still requires typing `yes`; noninteractive scripts must pass `--yes`.
162
168
 
163
169
  When `proposal_freshness` is configured for that capability, approval also
@@ -171,7 +177,7 @@ revalidates again because source data can change after approval. See
171
177
  Create a guarded writeback job from an approved proposal:
172
178
 
173
179
  ```bash
174
- npx -y -p @synapsor/runner synapsor-runner proposals writeback-job wrp_123 \
180
+ npx -y @synapsor/runner proposals writeback-job wrp_123 \
175
181
  --store ./.synapsor/local.db \
176
182
  --project local \
177
183
  --runner local_runner \
@@ -183,7 +189,7 @@ The generated job uses the public `synapsor.writeback-job.v1` protocol and can b
183
189
  ```bash
184
190
  export SYNAPSOR_DATABASE_WRITE_URL="postgresql://writer:<password>@localhost:5432/app"
185
191
  SYNAPSOR_ENGINE=postgres \
186
- npx -y -p @synapsor/runner synapsor-runner apply --job job.json --config synapsor.runner.json --store ./.synapsor/local.db
192
+ npx -y @synapsor/runner apply --job job.json --config synapsor.runner.json --store ./.synapsor/local.db
187
193
  ```
188
194
 
189
195
  When `--config` is passed, direct SQL writeback reads the writer connection from
@@ -195,7 +201,7 @@ Passing `--store` records the terminal `synapsor.execution-receipt.v1` locally.
195
201
  Reject:
196
202
 
197
203
  ```bash
198
- npx -y -p @synapsor/runner synapsor-runner proposals reject wrp_123 \
204
+ npx -y @synapsor/runner proposals reject wrp_123 \
199
205
  --store ./.synapsor/local.db \
200
206
  --reason "policy evidence is incomplete" \
201
207
  --yes
@@ -216,7 +222,7 @@ pilot, use [Shadow Studies](shadow-studies.md).
216
222
  Start a localhost-only review UI:
217
223
 
218
224
  ```bash
219
- npx -y -p @synapsor/runner synapsor-runner ui --config synapsor.runner.json --store ./.synapsor/local.db
225
+ npx -y @synapsor/runner ui --config synapsor.runner.json --store ./.synapsor/local.db
220
226
  ```
221
227
 
222
228
  The UI shows setup summary, semantic tools, proposal states, exact diffs,
@@ -234,20 +240,20 @@ tools, MCP commit tools, or controls that widen configured tables/columns.
234
240
  Show replay:
235
241
 
236
242
  ```bash
237
- npx -y -p @synapsor/runner synapsor-runner replay show wrp_123 --store ./.synapsor/local.db
238
- npx -y -p @synapsor/runner synapsor-runner replay show --proposal wrp_123 --store ./.synapsor/local.db
239
- npx -y -p @synapsor/runner synapsor-runner replay show --replay replay_wrp_123 --store ./.synapsor/local.db
240
- npx -y -p @synapsor/runner synapsor-runner replay show --evidence ev_123 --store ./.synapsor/local.db
243
+ npx -y @synapsor/runner replay show wrp_123 --store ./.synapsor/local.db
244
+ npx -y @synapsor/runner replay show --proposal wrp_123 --store ./.synapsor/local.db
245
+ npx -y @synapsor/runner replay show --replay replay_wrp_123 --store ./.synapsor/local.db
246
+ npx -y @synapsor/runner replay show --evidence ev_123 --store ./.synapsor/local.db
241
247
  ```
242
248
 
243
249
  Export replay:
244
250
 
245
251
  ```bash
246
- npx -y -p @synapsor/runner synapsor-runner replay export wrp_123 \
252
+ npx -y @synapsor/runner replay export wrp_123 \
247
253
  --store ./.synapsor/local.db \
248
254
  --output replay.json
249
255
 
250
- npx -y -p @synapsor/runner synapsor-runner replay export --proposal wrp_123 \
256
+ npx -y @synapsor/runner replay export --proposal wrp_123 \
251
257
  --format markdown \
252
258
  --store ./.synapsor/local.db \
253
259
  --output replay.md
@@ -301,6 +307,8 @@ or prune it without touching your source Postgres/MySQL database:
301
307
  ```bash
302
308
  synapsor-runner store stats --store ./.synapsor/local.db
303
309
  synapsor-runner events tail --store ./.synapsor/local.db
310
+ synapsor-runner attention show --store ./.synapsor/local.db
311
+ synapsor-runner notifications status --store ./.synapsor/local.db
304
312
  synapsor-runner events webhook --url http://127.0.0.1:8788/synapsor/events --kind proposal_created --store ./.synapsor/local.db
305
313
  synapsor-runner store vacuum --store ./.synapsor/local.db
306
314
  synapsor-runner store prune --store ./.synapsor/local.db --older-than 30d --dry-run
@@ -316,8 +324,14 @@ running local store.
316
324
 
317
325
  `events webhook` pushes the same local lifecycle events to a local/dev/staging
318
326
  HTTP endpoint, one event envelope per POST. Use it for a review UI, Slack bridge,
319
- or app-local notification path when polling is awkward. It is not a hosted
320
- central ledger and does not expose database credentials.
327
+ or app-local compatibility path when polling is awkward. It is not the
328
+ production human-attention dispatcher.
329
+
330
+ For durable coalesced incidents, quiet defaults, budgets/digests, signed HTTPS
331
+ delivery, replay protection, sink health, and the no-ID Workbench inbox, use
332
+ `attention` and `notifications`. See [Human Attention And
333
+ Notifications](human-attention-notifications.md). Neither notification path
334
+ becomes approval or apply authority.
321
335
 
322
336
  `store prune` defaults to dry-run. `store reset` requires `--yes` and removes
323
337
  only the local SQLite ledger files. MCP server modes write a small active-store