dotnet run --project src/RuleForge.Cli -- <verb> [options] verbs: run Execute a rule against a request, in-process or via HTTP publish Push a local rule snapshot into DocumentForge mirror Copy collections between DocumentForge instances bench Throughput + latency probe
run
Execute a rule against a request payload. Default is in-process; pass --http to talk to a deployed engine instead.
dotnet run --project src/RuleForge.Cli -- run \ --endpoint /v1/ancillary/bag-policy \ --request '@fixtures/scenarios/s-bag-3pc-markup15.json' \ --debug
| Flag | Description |
|---|---|
--endpoint <slug> | Endpoint path, e.g. /v1/ancillary/bag-policy (required) |
--request <json|@file> | Inline JSON body, or @path/to/file.json (required) |
--debug | Include the full per-node trace + envelope durationMs |
--http <baseUrl> | POST to a running engine instead of in-process |
--df | Use a DocumentForge source (otherwise local files) |
--env <name> | DF environment to read bindings from (default: staging) |
--df-base <url> | DF base URL (default https://documentforge.onrender.com) |
--df-api-key <k> | DF bearer token (or env RULEFORGE_DF_API_KEY) |
--fixtures <dir> | Override local fixture directory (in-process mode) |
publish
Push a local rule snapshot to DocumentForge. The verb is idempotent: if a ruleversions doc with the same {ruleId, version} already exists, it's replaced; otherwise inserted. The rules header's currentVersion is bumped, and environments[envName].ruleBindings[ruleId] is set to the version.
dotnet run --project src/RuleForge.Cli -- publish \ --rule fixtures/rules/rule-bag-policy.v7.json \ --env staging
| Flag | Description |
|---|---|
--rule <path> | Path to a local rule JSON (required) |
--env <name> | Environment to bind to (default: staging) |
--api-key <k> | DF bearer token (or env RULEFORGE_DF_API_KEY) |
--df-base <url> | DF base URL |
Effects on DocumentForge
ruleversions: insert (or replace){id: "rv-{ruleId}-{version}", ruleId, version, snapshot, publishedAt, publishedBy}rules[ruleId]: bumpcurrentVersionand setstatus: publishedenvironments[envName].ruleBindings[ruleId] = version
mirror
Copy collections from one DocumentForge instance to another. Idempotent: each source doc is matched to the target by logical id field — existing rows are replaced, new rows are inserted. Used to spin up a co-located dfdb that mirrors a hosted DF.
dotnet run --project src/RuleForge.Cli -- mirror \ --from https://documentforge.onrender.com \ --to http://localhost:5000
| Flag | Description |
|---|---|
--from <url> | Source DF base URL (required) |
--to <url> | Target DF base URL (required) |
--from-key <k> | Source bearer (or env RULEFORGE_DF_API_KEY) |
--to-key <k> | Target bearer |
--collections <list> | Comma-separated. Default: rules,ruleversions,environments,referencesets,referencesetversions,nodetemplates,scenarios,connections |
bench
Run N evaluations with a fixed request and report p50 / p95 / p99 / mean / max latency plus throughput. Two modes:
- Warm (default) — sources are built once. Steady-state CPU cost only.
- Cold (
--cold) — sources are rebuilt per request. Surfaces the DF round-trip cost.
dotnet run --project src/RuleForge.Cli -- bench \ --endpoint /v1/ancillary/bag-policy \ --request '@fixtures/scenarios/s-bag-3pc-markup15.json' \ --df --df-base http://localhost:5000 \ --warmup 100 --iterations 10000 --concurrency 16
| Flag | Description |
|---|---|
--endpoint <slug> | Endpoint to bench (required) |
--request <json|@file> | Request payload (required) |
--iterations N | Hot-loop iterations after warmup (default 1000) |
--warmup N | Pre-bench iterations (default 100) |
--concurrency N | Parallel workers (default 1) |
--cold | Build a fresh source per request (defeats the cache, surfaces DF round-trip) |
--df · --env · --df-base · --df-api-key | Same as run |
Sample output
━━ bench ━━
rule : Bag policy · slice 3d (calc markup + lookup fee) (v7)
source : DocumentForge
endpoint : POST /v1/ancillary/bag-policy
iterations : 10000
warmup : 100
concurrency : 16
cold : False (fresh source per request)
sample run : decision=Apply
total wall : 136 ms (73529 req/s effective)
per request :
p50 : 0.13 ms
p95 : 0.23 ms
p99 : 1.45 ms
max : 9.58 ms
mean : 0.18 ms