Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 75 additions & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:
scripts/workbench/pre423_contract_ledger.py \
scripts/workbench/workbench_contract.py \
scripts/workbench/live_workbench.py \
scripts/workbench/native_cli_workbench.py \
scripts/workbench/local_wal_recovery_gate.py \
scripts/workbench/object_namespace_recovery_gate.py \
scripts/workbench/restore_composition_gate.py \
Expand All @@ -59,6 +60,7 @@ jobs:
python3 scripts/workbench/pre423_contract_ledger_test.py
python3 scripts/workbench/workbench_contract_test.py
python3 scripts/workbench/live_workbench_test.py
python3 scripts/workbench/native_cli_workbench_test.py
python3 scripts/workbench/local_wal_recovery_gate_test.py
python3 scripts/workbench/object_namespace_recovery_gate_test.py
python3 scripts/workbench/restore_composition_gate_test.py
Expand Down Expand Up @@ -188,7 +190,7 @@ jobs:
--dependency "etcd=sha256:e8cd3fa8064c98137c5dbd78b76f969417ace84efb83c481041d7a52ffdd8fb9"
--dependency "object-store=oci:rustfs/rustfs@sha256:e620d37756fff072b10bf648c7bb9d370d7e91a928b7e6a5e1ac85bdfb4e4dab"
--evidence "qualification=$evidence_root/qualification.json"
--evidence "mcp-transcript=$evidence_root/mcp-transcript.jsonl"
--evidence "cli-transcript=$evidence_root/cli-transcript.jsonl"
)
producer_args+=(
--nokv-bin "$product_binary"
Expand Down Expand Up @@ -532,6 +534,78 @@ jobs:
if-no-files-found: error
retention-days: 7

- name: Qualify primary native CLI Workbench contracts
id: native_cli_workbench
shell: bash
env:
NATIVE_CLI_WORKBENCH_ROOT: ${{ runner.temp }}/native-cli-workbench
run: |
set -euo pipefail
endpoint=http://127.0.0.1:22381
peer=http://127.0.0.1:22382
mkdir -p "$NATIVE_CLI_WORKBENCH_ROOT"
etcd \
--name nokv-native-cli-workbench \
--data-dir "$NATIVE_CLI_WORKBENCH_ROOT/etcd-data" \
--listen-client-urls "$endpoint" \
--advertise-client-urls "$endpoint" \
--listen-peer-urls "$peer" \
--initial-advertise-peer-urls "$peer" \
--initial-cluster "nokv-native-cli-workbench=$peer" \
--initial-cluster-state new \
--log-level warn \
>"$NATIVE_CLI_WORKBENCH_ROOT/etcd.log" 2>&1 &
etcd_pid=$!
trap 'kill "$etcd_pid" >/dev/null 2>&1 || true; wait "$etcd_pid" >/dev/null 2>&1 || true' EXIT
ready=false
for _ in $(seq 1 60); do
if etcdctl --endpoints "$endpoint" endpoint health >/dev/null 2>&1; then
ready=true
break
fi
if ! kill -0 "$etcd_pid" >/dev/null 2>&1; then
break
fi
sleep 0.25
done
if [[ "$ready" != true ]]; then
cat "$NATIVE_CLI_WORKBENCH_ROOT/etcd.log"
exit 1
fi
python3 scripts/workbench/native_cli_workbench.py \
--nokv-bin target/debug/nokv \
--evidence-dir "$NATIVE_CLI_WORKBENCH_ROOT/evidence" \
--metadata-dir "$NATIVE_CLI_WORKBENCH_ROOT/metadata" \
--root-id 55555555555555555555555555555555 \
--agent-id 88888888888888888888888888888888 \
--agent-name ci-native-cli-agent \
--logical-shard-id 66666666666666666666666666666666 \
--etcd-endpoint "$endpoint" \
--etcd-key-prefix "/nokv/control/native-cli-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" \
--server-bind 127.0.0.1:17751 \
--advertise-endpoint 127.0.0.1:17751 \
--object-endpoint http://127.0.0.1:9000 \
--object-bucket nokv-local-wal-recovery-gate \
--object-root "native-cli-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" \
--object-access-key-id rustfsadmin \
--object-secret-access-key rustfsadmin \
--command-timeout-seconds 45
jq -e '.workbench_workflow.status == "PASS"' \
"$NATIVE_CLI_WORKBENCH_ROOT/evidence/qualification.json"
jq -e '.workbench_workflow.transport == "native-cli"' \
"$NATIVE_CLI_WORKBENCH_ROOT/evidence/qualification.json"
jq -e '.acceptance_gates["0"].status == "NOT QUALIFIED"' \
"$NATIVE_CLI_WORKBENCH_ROOT/evidence/qualification.json"

- name: Upload native CLI Workbench evidence
if: ${{ always() && steps.native_cli_workbench.outcome != 'skipped' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: native-cli-workbench-${{ github.sha }}
path: ${{ runner.temp }}/native-cli-workbench
if-no-files-found: error
retention-days: 7

- name: Qualify restored Workbench composition
id: restore_composition
shell: bash
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ workbench-test:
python3 scripts/workbench/pre423_contract_ledger_test.py
python3 scripts/workbench/workbench_contract_test.py
python3 scripts/workbench/live_workbench_test.py
python3 scripts/workbench/native_cli_workbench_test.py

governance-test:
python3 scripts/ci/pr_change_governance_test.py
Expand All @@ -58,6 +59,7 @@ verify:
python3 scripts/workbench/pre423_contract_ledger_test.py
python3 scripts/workbench/workbench_contract_test.py
python3 scripts/workbench/live_workbench_test.py
python3 scripts/workbench/native_cli_workbench_test.py
python3 scripts/ci/pr_change_governance_test.py
python3 scripts/release/test_homebrew_source_release.py
python3 scripts/release/test_python_sdk_release.py
Expand Down
26 changes: 15 additions & 11 deletions bench/workbench-live/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ SPDX-License-Identifier: Apache-2.0

# Live Workbench evidence

The executable product-boundary workload lives at
`scripts/workbench/live_workbench.py`. It exercises the flat `nokv`
CLI-backed optional MCP sidecar against real root routing, Holt metadata
ownership, and an S3-compatible object provider. It is sidecar qualification,
not evidence that MCP is NoKV's primary integration surface. Its deterministic
runtime evidence directory is under `target/workbench-live/evidence/` by
default; evidence is not checked into this source directory.
The primary executable product-boundary workload lives at
`scripts/workbench/native_cli_workbench.py`. It exercises the full
`nokv workbench <tool> <canonical-json>` CLI boundary against real root
routing, Holt metadata ownership, and an S3-compatible object provider. Its
deterministic runtime evidence directory is under
`target/native-cli-workbench/evidence/` by default; evidence is not checked
into this source directory.

This is a correctness and interoperability workload, not a performance result.
It records all 18 tool inputs and exact responses, one deliberate create-only
error, commit replay, frozen reads, restore projections, and the explicit
materialize/collect boundary. Missing external services are `NOT QUALIFIED`.
`scripts/workbench/live_workbench.py` separately qualifies the optional MCP
sidecar. It is not evidence that MCP is NoKV's primary integration surface.

These are correctness and interoperability workloads, not performance results.
The native runner records all 18 tool argv/input/result pairs, one deliberate
create-only error, commit replay, frozen reads, restore projections, and the
explicit materialize/collect boundary. Missing external services are
`NOT QUALIFIED`.

See `scripts/workbench/README.md` for commands and
`docs/development/workspace-acceptance.md` for the qualification boundary.
12 changes: 6 additions & 6 deletions docs/development/pre423-contract-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ typed producers pass.
| `pre423_contract_ledger.py`, `workbench_contract_test.py`, and every `*_gate_test.py` | Validate policy, checker, or harness shape only. They sign no product stable ID by themselves. |
| `cargo test -p nokv-agent` | Candidate `nokv-agent-unit` source for schema-surface `T01`-`T04`, `C01`, `C02`, `C07`, and `L01`. |
| `cargo test -p nokv-agent --test sdk_facade` | Candidate `nokv-agent-unit` source for the ledger's facade-contract and output-golden scenarios. Each claim still needs a direct assertion-to-scenario mapping; the broad command is not one receipt for all IDs. |
| `live_workbench.py` | Its explicit stable checks can back native scenarios for `T08`, `C04`, `C05`, and `C15`. Its `C06` probe proves same-name read/write isolation, reconnect, and wrong-agent admission, but does not yet cover every operation required by the `C06` root-authority scenario. It is raw MCP evidence, not LingTai evidence. |
| `native_cli_workbench.py` | Its explicit direct-CLI checks can back native scenarios for `T08`, `C04`, `C05`, and `C15`. Its `C06` probe proves same-name read/write isolation, reconnect, and wrong-agent admission, but does not yet cover every operation required by the `C06` root-authority scenario. It is raw native CLI evidence, not LingTai evidence. |
| `restore_composition_gate.py` | Can back restore-composition scenarios for `T14`, `T18`, `C20`, and `C21` where its exact A to snapshot A to B to snapshot B to C oracle asserts the scenario. It does not satisfy their independent provider, native, commit, output, or LingTai gates. |
| `object_namespace_recovery_gate.py` | Can back the provider restart binding scenario in `C06` and the explicit object-outage read scenario in `C12`. Its commit replay, wrong-prefix, and exact-byte observations are partial evidence only for the remaining provider scenarios. |
| `local_wal_recovery_gate.py` | Qualifies owner-epoch/local-WAL recovery, which is not one of the 47 pre-#423 stable IDs. It signs none of this ledger's scenarios. |
Expand All @@ -209,11 +209,11 @@ Workbench ledger qualification result.

The five source-bound static or exact-test producers are implemented and have
their own fail-closed policy tests. They still need to be executed as part of
the complete protected producer graph. Three existing live harnesses need
typed scenario/result/evidence integration without weakening their current
oracles: `live-workbench`, `object-namespace-recovery`, and
`restore-composition`. Three behavior boundaries still require dedicated
commands before the ledger can reach `PASS`:
the complete protected producer graph. The direct native CLI `live-workbench`
producer now retains `cli-transcript` evidence; the object-namespace and
restore-composition live harnesses still need typed scenario/result/evidence
integration without weakening their current oracles. Three behavior boundaries
still require dedicated commands before the ledger can reach `PASS`:

1. `snapshot-lifecycle` integration must deterministically cover committed-only
minting, frozen reads after live mutation, renew by id and alias, terminal
Expand Down
14 changes: 9 additions & 5 deletions docs/development/workspace-acceptance.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,17 @@ throughput, and p50/p95/p99/maximum latency.

The scientific reconstruction workflow must exercise the complete 18-tool
Workbench semantics through the primary native CLI boundary. The direct Python
SDK must independently exercise its supported programmatic path. The existing
black-box runner,
[`scripts/workbench/live_workbench.py`](../../scripts/workbench/live_workbench.py),
SDK must independently exercise its supported programmatic path. The black-box
native runner,
[`scripts/workbench/native_cli_workbench.py`](../../scripts/workbench/native_cli_workbench.py),
starts the same product owner and invokes every tool as
`nokv workbench <tool> <canonical-json>` in a fresh CLI process, retaining the
exact CLI transcript. The existing
[`scripts/workbench/live_workbench.py`](../../scripts/workbench/live_workbench.py)
qualifies the optional MCP sidecar only. Its dry-run proves only command
construction and tool coverage; a live run retains exact sidecar and process
evidence. It cannot substitute for native CLI or Python SDK evidence. Absent
etcd, S3-compatible storage, or the requested binary is `NOT QUALIFIED`, never
evidence. Neither runner substitutes for the Python SDK path. Absent etcd,
S3-compatible storage, or the requested binary is `NOT QUALIFIED`, never
`PASS`.

Required evidence:
Expand Down
70 changes: 57 additions & 13 deletions scripts/workbench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,19 @@ The checked-in integration assets are deliberately small:
exact Rust-owned schema at
`crates/nokv-agent/workbench_contract_schema.json`.
- `workbench_contract_test.py` tests normalization and exact surface matching.
- `live_workbench.py` provisions one root, starts one explicit metadata
owner and the flat `nokv mcp` command, then records a real
scientific reconstruction workflow through all 18 tools.
- `live_workbench_test.py` checks exact coverage/order, flat commands,
secret redaction, dry-run evidence, and fail-closed qualification.
- `native_cli_workbench.py` provisions one root, starts one explicit metadata
owner, and records the scientific reconstruction workflow by invoking every
tool through the primary `nokv workbench <tool> <canonical-json>` CLI
boundary in a fresh process.
- `native_cli_workbench_test.py` freezes direct-CLI argv construction, exact
tool coverage, transcript/error parsing, secret redaction, dry-run evidence,
and the required CI artifact.
- `live_workbench.py` provisions one root, starts one explicit metadata owner
and the flat optional `nokv mcp` command, then records the same workflow
through the sidecar transport.
- `live_workbench_test.py` checks the sidecar runner's exact coverage/order,
flat commands, secret redaction, dry-run evidence, and fail-closed
qualification.
- `local_wal_recovery_gate.py` starts an isolated real etcd process and proves
that a killed `Recovering(2)` owner is retried at epoch 2 both before and
after the local Holt fence advances. It separately sends `SIGTERM` to a
Expand Down Expand Up @@ -65,7 +73,7 @@ The checked-in integration assets are deliberately small:

The source-bound qualification manifest covers every producer declared by the
pre-#423 ledger. Live producers bind the exact product binary, pinned dependency
identities, and their required `qualification` and MCP-transcript evidence
identities, and their required `qualification` and transport-transcript evidence
roles. Missing LingTai and installed-Python live runners emit typed `NQ`
receipts with a concrete gap reason. The native Workbench and object-namespace
entrypoints also refuse to claim scenarios their bounded harnesses do not run.
Expand All @@ -83,6 +91,7 @@ python3 scripts/workbench/pre423_contract_ledger.py
python3 scripts/workbench/pre423_contract_ledger_test.py
python3 scripts/workbench/workbench_contract_test.py
python3 scripts/workbench/live_workbench_test.py
python3 scripts/workbench/native_cli_workbench_test.py
python3 scripts/workbench/local_wal_recovery_gate_test.py
python3 scripts/workbench/object_namespace_recovery_gate_test.py
python3 scripts/workbench/restore_composition_gate_test.py
Expand All @@ -109,16 +118,49 @@ metadata schemas are rejected; the sole marker is `nokv_workspace`.

## Live Workbench evidence

Dry-run validates the redacted command graph and exact 18-tool coverage without
claiming that any dependency ran:
### Primary native CLI

Dry-run validates the redacted direct-CLI command graph and exact 18-tool
coverage without claiming that any dependency ran:

```bash
python3 scripts/workbench/native_cli_workbench.py \
--dry-run \
--evidence-dir target/native-cli-workbench/evidence/dry-run
```

A live run consumes already-running etcd and S3-compatible services. Each
Workbench call is a separate invocation of `nokv workbench`; the evidence
records exact redacted argv, canonical JSON input, stdout, stderr, exit code,
and the decoded public result in `cli-transcript.jsonl`.

```bash
python3 scripts/workbench/native_cli_workbench.py \
--build \
--root-id 11111111111111111111111111111111 \
--agent-id 44444444444444444444444444444444 \
--agent-name research-agent \
--logical-shard-id 22222222222222222222222222222222 \
--etcd-endpoint http://127.0.0.1:2379 \
--object-endpoint http://127.0.0.1:9000 \
--object-bucket nokv-workbench-live \
--metadata-mode create \
--metadata-dir target/native-cli-workbench/metadata/live-01 \
--evidence-dir target/native-cli-workbench/evidence/live-01
```

### Optional MCP sidecar

The sidecar runner remains separate. Its dry-run validates the redacted command
graph and exact 18-tool coverage without claiming that any dependency ran:

```bash
python3 scripts/workbench/live_workbench.py \
--dry-run \
--evidence-dir target/workbench-live/evidence/dry-run
```

A live run consumes already-running etcd and S3-compatible services.
A live sidecar run consumes already-running etcd and S3-compatible services.
Credentials may be supplied with `NOKV_LIVE_S3_ACCESS_KEY_ID` and
`NOKV_LIVE_S3_SECRET_ACCESS_KEY`; evidence records only their presence and
redacts secret values without retaining a digest verifier.
Expand Down Expand Up @@ -163,10 +205,12 @@ record size, so a long-lived deployment such as a partner pre-pilot should run
recovery authority, nothing is published, and `--metadata-recover-log` is not
available for that shard.

The deterministic evidence directory contains `plan.json`, exact paired
requests/responses in `mcp-transcript.jsonl`, `processes.jsonl` and process
logs, build/config facts in `environment.json`, validated schema evidence in
`contract.json`, and explicit statuses in `qualification.json`.
The native deterministic evidence directory contains `plan.json`, exact direct
CLI invocations in `cli-transcript.jsonl`, `processes.jsonl` and process logs,
build/config facts in `environment.json`, the binary-exported 18-tool schema
check in `contract.json`, and explicit statuses in `qualification.json`. The
sidecar runner separately retains paired JSON-RPC requests/responses in
`mcp-transcript.jsonl` and its MCP schema evidence.

Exit status `3` means a required live dependency is absent and the workflow is
`NOT QUALIFIED`, never a pass. Exit status `2` means a configured live boundary
Expand Down
Loading