@synapsor/runner 1.4.1 → 1.4.12
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 +19 -0
- package/README.md +4 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/runner.mjs +64 -21
- package/docs/getting-started-own-database.md +8 -1
- package/docs/production.md +10 -0
- package/docs/release-notes.md +18 -0
- package/docs/troubleshooting-first-run.md +20 -0
- package/examples/runner-fleet/seed/postgres.sql +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.4.12 (prepared, not published)
|
|
4
|
+
|
|
5
|
+
### Runtime-store smoke-call consistency
|
|
6
|
+
|
|
7
|
+
- Fixes BUG-017: `smoke call` now lets the MCP runtime resolve storage from the
|
|
8
|
+
complete config instead of injecting a local SQLite `ProposalStore`.
|
|
9
|
+
- In `runtime_store` mode, proposal, evidence, query-audit, event, and replay
|
|
10
|
+
records land in the authoritative shared Postgres ledger and are visible to
|
|
11
|
+
other Runner processes and normal approve/apply commands.
|
|
12
|
+
- Shared-ledger failures return a redacted, retryable availability result with
|
|
13
|
+
a nonzero CLI status and never create a local fallback proposal.
|
|
14
|
+
- Keeps local SQLite and mirror modes unchanged. The source database still
|
|
15
|
+
remains untouched until external approval and guarded apply.
|
|
16
|
+
- Adds focused no-fallback coverage and a disposable two-process fleet proof
|
|
17
|
+
covering ownership, approval/apply, one source receipt, replay, and safe
|
|
18
|
+
ledger unavailability.
|
|
19
|
+
- Stages only `@synapsor/runner@1.4.12`; `@synapsor/dsl` remains `1.4.1` and
|
|
20
|
+
`@synapsor/spec` remains `1.4.0`. Nothing is published by this change.
|
|
21
|
+
|
|
3
22
|
## 1.4.1 (prepared, not published)
|
|
4
23
|
|
|
5
24
|
### Canonical Bounded-Set Digest Verification
|
package/README.md
CHANGED
|
@@ -215,6 +215,10 @@ remains the default. See
|
|
|
215
215
|
[Production](docs/production.md) and the
|
|
216
216
|
[Runner Config Reference](docs/runner-config-reference.md).
|
|
217
217
|
|
|
218
|
+
`smoke call` honors `runtime_store`: artifacts go to shared Postgres; failures
|
|
219
|
+
never fall back to SQLite. `--store` is compatibility plumbing. Requires
|
|
220
|
+
`1.4.12`+.
|
|
221
|
+
|
|
218
222
|
For a small multi-tenant fleet, bind every capability context to verified HTTP
|
|
219
223
|
claims, use `jwt_asymmetric` session auth, and share a bounded Postgres
|
|
220
224
|
`runtime_store`. Never assume a global `http_claims` setting overrides an
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAYA,OAAO,EAAoP,KAAK,WAAW,EAA0H,MAAM,6BAA6B,CAAC;AAIza,OAAO,EAgBL,KAAK,qBAAqB,EAK3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAgI,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAuD,KAAK,YAAY,EAAwB,MAAM,2BAA2B,CAAC;AAElV,OAAO,EAQL,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAUL,KAAK,yBAAyB,EAE/B,MAAM,8BAA8B,CAAC;AAyUtC,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA6D1D;AA0FD,KAAK,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE9E,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACvC,GACL,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAYA,OAAO,EAAoP,KAAK,WAAW,EAA0H,MAAM,6BAA6B,CAAC;AAIza,OAAO,EAgBL,KAAK,qBAAqB,EAK3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAgI,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAuD,KAAK,YAAY,EAAwB,MAAM,2BAA2B,CAAC;AAElV,OAAO,EAQL,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAUL,KAAK,yBAAyB,EAE/B,MAAM,8BAA8B,CAAC;AAyUtC,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA6D1D;AA0FD,KAAK,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE9E,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACvC,GACL,OAAO,CAAC,MAAM,CAAC,CA2YjB;AAqmGD,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAS/H;AAs4CD,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,yBAAyB,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAKxH;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,qBAAqB,EAC7B,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,EAC1C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,kBAAkB,GAAG,kBAAkB,GAAG,kBAAkB,CAgH9D"}
|
package/dist/runner.mjs
CHANGED
|
@@ -16939,7 +16939,7 @@ function isRecord7(value) {
|
|
|
16939
16939
|
// apps/runner/package.json
|
|
16940
16940
|
var package_default = {
|
|
16941
16941
|
name: "@synapsor/runner",
|
|
16942
|
-
version: "1.4.
|
|
16942
|
+
version: "1.4.12",
|
|
16943
16943
|
description: "Stop giving AI agents execute_sql; expose reviewed Postgres/MySQL MCP actions with proposals, approval, writeback, and replay.",
|
|
16944
16944
|
license: "Apache-2.0",
|
|
16945
16945
|
type: "module",
|
|
@@ -17957,6 +17957,7 @@ async function runInitWizard(args, options = {}) {
|
|
|
17957
17957
|
`);
|
|
17958
17958
|
const smoke2 = await maybeRunGeneratedSmokeCall({
|
|
17959
17959
|
config: generated.config,
|
|
17960
|
+
configPath: outputPath,
|
|
17960
17961
|
env: options.env ?? process2.env,
|
|
17961
17962
|
input: { [lookupArg]: smokeObjectId },
|
|
17962
17963
|
readUrlEnv: configDatabaseUrlEnv,
|
|
@@ -18399,14 +18400,18 @@ async function maybeRunGeneratedSmokeCall(input) {
|
|
|
18399
18400
|
""
|
|
18400
18401
|
].join("\n");
|
|
18401
18402
|
}
|
|
18402
|
-
const
|
|
18403
|
-
const runtime = createMcpRuntime(input.config, { store, env: input.env, readRow: input.readRow });
|
|
18403
|
+
const runtime = createMcpRuntime(input.config, { storePath: input.storePath, env: input.env, readRow: input.readRow });
|
|
18404
18404
|
try {
|
|
18405
18405
|
const result = await runtime.callTool(input.toolName, input.input);
|
|
18406
18406
|
return [
|
|
18407
|
-
"Smoke call ran successfully.",
|
|
18407
|
+
result.ok === false ? "Smoke call attempted but did not pass." : "Smoke call ran successfully.",
|
|
18408
18408
|
"",
|
|
18409
|
-
formatSmokeCallResult(input.toolName, input.input, result,
|
|
18409
|
+
formatSmokeCallResult(input.toolName, input.input, result, {
|
|
18410
|
+
configPath: input.configPath,
|
|
18411
|
+
storePath: input.storePath,
|
|
18412
|
+
storeAuthority: "local_sqlite",
|
|
18413
|
+
sharedPostgresSchema: "synapsor_runner"
|
|
18414
|
+
})
|
|
18410
18415
|
].join("\n");
|
|
18411
18416
|
} catch (error) {
|
|
18412
18417
|
const message2 = error instanceof Error ? error.message : String(error);
|
|
@@ -23486,8 +23491,7 @@ async function smokeCall(args) {
|
|
|
23486
23491
|
const storePath = optionalArg(args, "--store") ?? process2.env.SYNAPSOR_LOCAL_STORE ?? defaultStorePath;
|
|
23487
23492
|
const config = await readRuntimeConfig(configPath);
|
|
23488
23493
|
const env = envWithDemoDefaults(config, configPath);
|
|
23489
|
-
const
|
|
23490
|
-
const runtime = createMcpRuntime(config, { store, env });
|
|
23494
|
+
const runtime = createMcpRuntime(config, { storePath, env });
|
|
23491
23495
|
try {
|
|
23492
23496
|
const tools2 = runtime.listTools();
|
|
23493
23497
|
const requestedTool = firstPositional(args);
|
|
@@ -23499,13 +23503,28 @@ async function smokeCall(args) {
|
|
|
23499
23503
|
if (!capability && config.mode !== "cloud") throw new Error(`capability not found in ${configPath}: ${toolName}`);
|
|
23500
23504
|
const input = capability ? await smokeToolInput(args, capability) : await smokeInputFromArgs(args);
|
|
23501
23505
|
const result = await runtime.callTool(toolName, input);
|
|
23506
|
+
const ok = result.ok !== false;
|
|
23507
|
+
const storeAuthority = config.storage?.shared_postgres?.mode === "runtime_store" ? "shared_postgres" : "local_sqlite";
|
|
23502
23508
|
if (args.includes("--json")) {
|
|
23503
|
-
process2.stdout.write(`${JSON.stringify({
|
|
23509
|
+
process2.stdout.write(`${JSON.stringify({
|
|
23510
|
+
ok,
|
|
23511
|
+
tool: toolName,
|
|
23512
|
+
input,
|
|
23513
|
+
result,
|
|
23514
|
+
store_path: storePath,
|
|
23515
|
+
store_authority: storeAuthority,
|
|
23516
|
+
...storeAuthority === "shared_postgres" ? { shared_postgres_schema: config.storage?.shared_postgres?.schema ?? "synapsor_runner" } : {}
|
|
23517
|
+
}, null, 2)}
|
|
23504
23518
|
`);
|
|
23505
23519
|
} else {
|
|
23506
|
-
process2.stdout.write(formatSmokeCallResult(toolName, input, result,
|
|
23520
|
+
process2.stdout.write(formatSmokeCallResult(toolName, input, result, {
|
|
23521
|
+
configPath,
|
|
23522
|
+
storePath,
|
|
23523
|
+
storeAuthority,
|
|
23524
|
+
sharedPostgresSchema: config.storage?.shared_postgres?.schema ?? "synapsor_runner"
|
|
23525
|
+
}));
|
|
23507
23526
|
}
|
|
23508
|
-
return 0;
|
|
23527
|
+
return ok ? 0 : 1;
|
|
23509
23528
|
} finally {
|
|
23510
23529
|
await runtime.close();
|
|
23511
23530
|
}
|
|
@@ -23722,13 +23741,25 @@ async function smokeInputFromArgs(args, capability) {
|
|
|
23722
23741
|
if (sample) return {};
|
|
23723
23742
|
return {};
|
|
23724
23743
|
}
|
|
23725
|
-
function formatSmokeCallResult(toolName, input, result,
|
|
23726
|
-
const
|
|
23727
|
-
const
|
|
23744
|
+
function formatSmokeCallResult(toolName, input, result, topology) {
|
|
23745
|
+
const proposal = isRecord8(result.proposal) ? result.proposal : void 0;
|
|
23746
|
+
const evidence2 = isRecord8(result.evidence) ? result.evidence : void 0;
|
|
23747
|
+
const error = isRecord8(result.error) ? result.error : void 0;
|
|
23748
|
+
const evidenceId = stringField(result, "evidence_bundle_id") ?? (evidence2 ? stringField(evidence2, "bundle_id") : void 0);
|
|
23749
|
+
const proposalId = stringField(result, "proposal_id") ?? (proposal ? stringField(proposal, "id") : void 0);
|
|
23728
23750
|
const replayResource = stringField(result, "replay_resource");
|
|
23729
23751
|
const sourceChanged = result.source_database_changed === true || result.source_database_mutated === true;
|
|
23752
|
+
const ok = result.ok !== false;
|
|
23753
|
+
const storeLines = topology.storeAuthority === "shared_postgres" ? [
|
|
23754
|
+
"Authoritative ledger:",
|
|
23755
|
+
`shared Postgres (${topology.sharedPostgresSchema})`,
|
|
23756
|
+
"",
|
|
23757
|
+
"Local --store path:",
|
|
23758
|
+
`${topology.storePath} (compatibility path only; no authoritative smoke records are written here)`,
|
|
23759
|
+
""
|
|
23760
|
+
] : ["Local ledger:", topology.storePath, ""];
|
|
23730
23761
|
const lines = [
|
|
23731
|
-
|
|
23762
|
+
`Synapsor smoke call: ${ok ? "ok" : "failed"}`,
|
|
23732
23763
|
"",
|
|
23733
23764
|
"Tool:",
|
|
23734
23765
|
toolName,
|
|
@@ -23741,20 +23772,32 @@ function formatSmokeCallResult(toolName, input, result, storePath) {
|
|
|
23741
23772
|
"",
|
|
23742
23773
|
"Evidence:",
|
|
23743
23774
|
evidenceId || "(not returned)",
|
|
23744
|
-
""
|
|
23775
|
+
"",
|
|
23776
|
+
...storeLines
|
|
23745
23777
|
];
|
|
23778
|
+
if (!ok) {
|
|
23779
|
+
lines.push("Error:", error ? stringField(error, "code") ?? "UNCLASSIFIED" : "UNCLASSIFIED");
|
|
23780
|
+
if (error?.retryable === true) {
|
|
23781
|
+
lines.push("Retryable:", "yes");
|
|
23782
|
+
const retryAfter = error.retry_after_ms;
|
|
23783
|
+
if (typeof retryAfter === "number") lines.push("Retry after:", `${retryAfter} ms`);
|
|
23784
|
+
}
|
|
23785
|
+
return `${lines.join("\n")}
|
|
23786
|
+
`;
|
|
23787
|
+
}
|
|
23746
23788
|
if (proposalId) {
|
|
23747
23789
|
lines.push("Proposal:", proposalId, "", "Replay:", replayResource || `synapsor://replay/replay_${proposalId}`, "");
|
|
23748
23790
|
}
|
|
23791
|
+
const storeSuffix = topology.storeAuthority === "shared_postgres" ? ` --config ${topology.configPath} --store ${topology.storePath}` : ` --store ${topology.storePath}`;
|
|
23749
23792
|
lines.push("Next:");
|
|
23750
|
-
if (evidenceId) lines.push(` ${cliCommandName()} evidence show ${evidenceId}
|
|
23793
|
+
if (evidenceId) lines.push(` ${cliCommandName()} evidence show ${evidenceId}${storeSuffix}`);
|
|
23751
23794
|
if (proposalId) {
|
|
23752
|
-
lines.push(` ${cliCommandName()} proposals show ${proposalId}
|
|
23753
|
-
lines.push(` ${cliCommandName()} proposals approve ${proposalId}
|
|
23754
|
-
lines.push(` ${cliCommandName()} apply ${proposalId}
|
|
23755
|
-
lines.push(` ${cliCommandName()} replay show --proposal ${proposalId}
|
|
23795
|
+
lines.push(` ${cliCommandName()} proposals show ${proposalId}${storeSuffix}`);
|
|
23796
|
+
lines.push(` ${cliCommandName()} proposals approve ${proposalId}${storeSuffix}`);
|
|
23797
|
+
lines.push(` ${cliCommandName()} apply ${proposalId}${storeSuffix}`);
|
|
23798
|
+
lines.push(` ${cliCommandName()} replay show --proposal ${proposalId}${storeSuffix}`);
|
|
23756
23799
|
} else if (evidenceId) {
|
|
23757
|
-
lines.push(` ${cliCommandName()} query-audit list --evidence ${evidenceId}
|
|
23800
|
+
lines.push(` ${cliCommandName()} query-audit list --evidence ${evidenceId}${storeSuffix}`);
|
|
23758
23801
|
}
|
|
23759
23802
|
return `${lines.join("\n")}
|
|
23760
23803
|
`;
|
|
@@ -368,7 +368,14 @@ npx -y -p @synapsor/runner synapsor-runner smoke call --config ./synapsor.runner
|
|
|
368
368
|
|
|
369
369
|
`smoke call` uses the same runtime as the MCP server. It records evidence and
|
|
370
370
|
query audit for read tools, or creates a proposal for proposal tools, then
|
|
371
|
-
prints the commands to inspect evidence/proposals/replay
|
|
371
|
+
prints the commands to inspect evidence/proposals/replay. With the default
|
|
372
|
+
storage topology those records are in local SQLite. With
|
|
373
|
+
`storage.shared_postgres.mode = "runtime_store"`, Runner `1.4.12` and later
|
|
374
|
+
write them to the authoritative shared Postgres ledger and include `--config`
|
|
375
|
+
in follow-up commands. The supplied `--store` path is compatibility plumbing
|
|
376
|
+
for those CLI commands; it does not receive an orphan proposal copy. If the
|
|
377
|
+
shared ledger is unavailable, `smoke call` fails safely and does not fall back
|
|
378
|
+
to SQLite.
|
|
372
379
|
|
|
373
380
|
The snippets contain the local command and args. They must not contain database
|
|
374
381
|
URLs, passwords, approval tools, commit tools, or write credentials.
|
package/docs/production.md
CHANGED
|
@@ -340,6 +340,16 @@ from `url_env`, auto-runs the shared-ledger migration, and serializes runtime
|
|
|
340
340
|
mutations with a transaction-scoped advisory lock. The MCP tools still expose no
|
|
341
341
|
database URLs or write credentials to the model.
|
|
342
342
|
|
|
343
|
+
`smoke call` uses the same runtime-store resolver as MCP serving. Its evidence,
|
|
344
|
+
query audit, proposal, events, and replay records therefore land directly in
|
|
345
|
+
the shared Postgres ledger and are immediately visible to another Runner using
|
|
346
|
+
the same config. `--store` remains accepted so the printed follow-up CLI
|
|
347
|
+
commands have a compatibility/bridge path, but that SQLite path is not an
|
|
348
|
+
authoritative copy and normally is not created by the smoke call. Shared-ledger
|
|
349
|
+
connection failure returns the safe availability error and a nonzero exit; it
|
|
350
|
+
never causes a local fallback. This consistency fix is present in Runner
|
|
351
|
+
`1.4.12` and later.
|
|
352
|
+
|
|
343
353
|
`runtime_store` covers MCP serving, CLI approval/apply, and supervised worker
|
|
344
354
|
runs. For CLI mutations, Runner restores the shared ledger into a temporary
|
|
345
355
|
local store while holding the Postgres advisory lock, runs the existing local
|
package/docs/release-notes.md
CHANGED
|
@@ -10,6 +10,24 @@ npx -y -p @synapsor/runner synapsor-runner demo --quick
|
|
|
10
10
|
The OSS runner command is `synapsor-runner`. The `synapsor` command is reserved
|
|
11
11
|
for the Synapsor Cloud CLI.
|
|
12
12
|
|
|
13
|
+
## 1.4.12 (prepared, not published)
|
|
14
|
+
|
|
15
|
+
### Runtime-store smoke-call consistency
|
|
16
|
+
|
|
17
|
+
- Fixes BUG-017, where `smoke call` could put proposal artifacts in the
|
|
18
|
+
requested local SQLite path even though the config selected authoritative
|
|
19
|
+
shared Postgres `runtime_store` mode.
|
|
20
|
+
- Smoke calls now use the same runtime storage resolver as MCP tool calls. A
|
|
21
|
+
second Runner can immediately inspect the proposal, evidence, query audit,
|
|
22
|
+
events, and replay from the shared ledger.
|
|
23
|
+
- Shared-ledger unavailability fails closed with a safe retryable error,
|
|
24
|
+
nonzero exit status, no credential leakage, and no local orphan proposal.
|
|
25
|
+
- Local SQLite and mirror modes retain their existing behavior; no source row
|
|
26
|
+
changes before the normal external approval/apply path.
|
|
27
|
+
|
|
28
|
+
Prepared package version: `@synapsor/runner@1.4.12`.
|
|
29
|
+
`@synapsor/dsl` remains `1.4.1`; `@synapsor/spec` remains `1.4.0`.
|
|
30
|
+
|
|
13
31
|
## 1.4.1 (prepared, not published)
|
|
14
32
|
|
|
15
33
|
### Bounded-set digest compatibility patch
|
|
@@ -12,6 +12,26 @@ Use JSON for automation:
|
|
|
12
12
|
npx -y -p @synapsor/runner synapsor-runner doctor --first-run --json
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
## Smoke Proposal Missing From Another Runner
|
|
16
|
+
|
|
17
|
+
What happened:
|
|
18
|
+
|
|
19
|
+
`smoke call` returned a proposal id, but `proposals list --config ...` on a
|
|
20
|
+
second Runner cannot find it.
|
|
21
|
+
|
|
22
|
+
Fix:
|
|
23
|
+
|
|
24
|
+
1. Verify `synapsor-runner --version` is `1.4.12` or later.
|
|
25
|
+
2. Confirm both commands use a config whose
|
|
26
|
+
`storage.shared_postgres.mode` is `runtime_store` and whose `url_env` and
|
|
27
|
+
`schema` identify the same ledger.
|
|
28
|
+
3. Run `store shared-postgres status --url-env <ENV> --schema <SCHEMA>`.
|
|
29
|
+
|
|
30
|
+
In `runtime_store` mode, `--store` is not the authoritative ledger. Runner does
|
|
31
|
+
not fall back to that SQLite path when shared Postgres is unavailable. Versions
|
|
32
|
+
before `1.4.12` could orphan smoke-call artifacts locally; recreate that test
|
|
33
|
+
proposal after upgrading.
|
|
34
|
+
|
|
15
35
|
## Docker Missing
|
|
16
36
|
|
|
17
37
|
What happened:
|
|
@@ -64,6 +64,7 @@ INSERT INTO public.invoices (id, tenant_id, status, late_fee_cents, waiver_reaso
|
|
|
64
64
|
('INV-ACME', 'acme', 'overdue', 2500, NULL, '2026-07-12T12:00:00Z'),
|
|
65
65
|
('INV-GLOBEX', 'globex', 'overdue', 3100, NULL, '2026-07-12T12:00:00Z'),
|
|
66
66
|
('INV-RATECO', 'rateco', 'overdue', 900, NULL, '2026-07-12T12:00:00Z'),
|
|
67
|
+
('INV-SMOKE-CALL', 'acme', 'overdue', 2100, NULL, '2026-07-12T12:00:00Z'),
|
|
67
68
|
('INV-BATCH-A', 'acme', 'overdue', 1100, NULL, '2026-07-12T12:00:00Z'),
|
|
68
69
|
('INV-BATCH-B', 'acme', 'overdue', 1300, NULL, '2026-07-12T12:00:00Z'),
|
|
69
70
|
('INV-QUORUM-RACE', 'acme', 'overdue', 1400, NULL, '2026-07-12T12:00:00Z'),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synapsor/runner",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.12",
|
|
4
4
|
"description": "Stop giving AI agents execute_sql; expose reviewed Postgres/MySQL MCP actions with proposals, approval, writeback, and replay.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|