Skip to content
Merged
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
87 changes: 79 additions & 8 deletions .github/workflows/verl-bridge.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,62 @@
name: pinned verl bridge

# The smoke installs the exact pinned verl source and takes a couple of
# minutes, so it only runs when bridge code actually changes. It used to do
# that with a `paths:` filter on the trigger, which meant the workflow did not
# run at all on an unrelated pull request -- and a required check that never
# reports blocks the pull request forever rather than passing. The filter now
# lives on the expensive job, and `pinned bridge gate` always reports a
# terminal status, so it is safe to require.

on:
workflow_dispatch:
pull_request:
paths:
- ".github/workflows/verl-bridge.yml"
- "pyproject.toml"
- "scripts/*verl_bridge*"
- "src/miniverl/bridge/**"
- "tests/**/*verl_bridge*"
branches: [main]
push:
tags:
- "v0.6.*"
branches: [main]
# Every release tag, not only the 0.6 series. `v0.6.*` would have silently
# skipped the bridge smoke on the v0.7.0 release tag.
tags: ["v*"]

permissions:
contents: read

jobs:
changes:
name: detect bridge changes
runs-on: ubuntu-latest
outputs:
bridge: ${{ steps.filter.outputs.bridge }}
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
with:
fetch-depth: 0
- id: filter
name: Decide whether the pinned smoke is relevant
env:
BASE_REF: ${{ github.base_ref }}
EVENT: ${{ github.event_name }}
run: |
set -euo pipefail
if [ "$EVENT" != "pull_request" ]; then
# A push to main or a release tag always runs the real smoke.
echo "bridge=true" >> "$GITHUB_OUTPUT"
exit 0
fi
git fetch --no-tags --depth=1 origin "$BASE_REF"
changed=$(git diff --name-only "origin/$BASE_REF"...HEAD)
echo "changed files:"
echo "$changed"
if echo "$changed" | grep -Eq '^(\.github/workflows/verl-bridge\.yml|pyproject\.toml|scripts/[^/]*verl_bridge[^/]*|src/miniverl/bridge/.*|tests/.*verl_bridge.*)$'; then
echo "bridge=true" >> "$GITHUB_OUTPUT"
else
echo "bridge=false" >> "$GITHUB_OUTPUT"
fi

pinned-profile-smoke:
name: pinned-profile-smoke
needs: changes
if: needs.changes.outputs.bridge == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
Expand Down Expand Up @@ -47,3 +86,35 @@ jobs:
name: verl-bridge-smoke-report
path: verl-bridge-smoke-report.json
if-no-files-found: error

bridge-gate:
# Always reports, so this context can be required without deadlocking a
# pull request that does not touch the bridge.
name: pinned bridge gate
needs: [changes, pinned-profile-smoke]
if: always()
runs-on: ubuntu-latest
steps:
- name: Aggregate
env:
RELEVANT: ${{ needs.changes.outputs.bridge }}
SMOKE: ${{ needs.pinned-profile-smoke.result }}
DETECT: ${{ needs.changes.result }}
run: |
set -euo pipefail
echo "bridge paths changed: $RELEVANT"
echo "detect result: $DETECT"
echo "smoke result: $SMOKE"
if [ "$DETECT" != "success" ]; then
echo "::error::could not determine whether bridge code changed"
exit 1
fi
if [ "$RELEVANT" != "true" ]; then
echo "not_applicable: no bridge path changed, pinned smoke not required"
exit 0
fi
if [ "$SMOKE" != "success" ]; then
echo "::error::pinned verl bridge smoke did not pass ($SMOKE)"
exit 1
fi
echo "pinned verl bridge smoke passed"
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ All notable changes to miniVERL are recorded here. The format follows
provenance, a versioned verifier-gated selector, deterministic tool-policy
evaluation and privacy-safe JSON/Markdown Alignment Cards.
- A preregistered three-seed Alignment Lab result, 864 task-level records, a
matched State Supervision diagnostic, four data-bound figures, technical
matched State × Supervision diagnostic, four data-bound figures, technical
report, article and reproducible short demo.

### Changed
Expand Down Expand Up @@ -303,7 +303,7 @@ All notable changes to miniVERL are recorded here. The format follows

### Results

- Batch-4 improved end-to-end throughput by 1.63脳 for dual ownership and 1.54脳
- Batch-4 improved end-to-end throughput by 1.63× for dual ownership and 1.54×
for shared ownership on the declared Qwen3-0.6B workload. Shared batch-4 used
2.227 GiB peak reserved memory versus 3.035 GiB for dual, but was 10.1% slower.
- Identical trajectory and teacher-target digests held across all eight cells;
Expand Down
45 changes: 43 additions & 2 deletions PROJECT_STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,53 @@ Living build log for **miniVERL** (`mini-verl` / `miniverl` / CLI `miniverl`).
A checkbox is not evidence: every completed item names the command that was run
and what it printed.

Last updated: 2026-08-05.
Last updated: 2026-08-06.

Canonical release state: stable `v0.6.3` (`005a4549da713716e64c3ae80ff55fb131519f79`), development `0.6.4.dev0`.
Canonical release state: stable `v0.6.3` (`005a4549da713716e64c3ae80ff55fb131519f79`), development `0.7.0.dev0`.
Every public version claim is generated from `release-state.yaml` and gated by
`python scripts/release_state.py --check`.

## v0.7.0 External alignment evidence — IN PROGRESS

Branch `v0.7.0-foundation`, based on `0bd194600aeb65b90eadd14bfa1ec313aa2a9c36`.
Not yet pushed. Commit author is
`Daoyuan Li <94409450+DaoyuanLi2816@users.noreply.github.com>` on every commit,
matching the 9:1 dominant identity since v0.6.0.

### Phase A progress

| item | state |
| --- | --- |
| 7.1 bundle-tree preflight | **done** (`71863b6`). Reproduced on Windows with a junction: `_check_hashes` walked into an outside directory and the metadata scan reported `semantic_secret_key` against a file the bundle did not contain. `preflight_bundle_tree` walks with `lstat` only and refuses symlinks, reparse points, non-regular files, escaping entries and trees over bounded file count / bytes / depth. Runs before any open; a refused bundle reports every check as `not_inspected`, never `failed`. 13 regressions; symlink cases skip locally for privileges and run on Linux CI |
| 7.2 privacy completeness | **done** (`b1e5ab7`). `heuristic_passed_full` / `heuristic_failed` / `heuristic_incomplete` / `not_inspected`; every gap records file and reason, bounded. `--require-complete-metadata-scan` fails on incomplete. 8 regressions |
| 7.6 text and CI cleanup | **done** (`b1e5ab7`). A mis-decoded multiplication sign is one character, not the three-byte CJK leaders the v0.6.3 gate looked for: `U+00D7` is two UTF-8 bytes, so reading them as GBK yields a single `U+8133`. Two CHANGELOG.md lines survived the release that way — the State-by-Supervision diagnostic name and the two batch-4 speedup figures. Leaders extended to the Latin-1 range (the misreadings of `U+00D7`, `U+00A7` and `U+00A6`), both lines repaired, 3 new gate cases. All four tensor-to-float warnings in `test_chunked_equivalence.py` detached. The gate then caught this very table describing the damage with the damaged characters, which is the behaviour we want |
| 7.3 sidecar v2 binding | not started |
| 7.4 source identity during conversion | not started |
| 7.5 residual O(N) metadata | not started |
| 7.7 quality provenance | not started |
| version bump to `0.7.0.dev0` | not started |

Local suite at `b1e5ab7`: 1853 passed, 6 skipped, 6 deselected. Ruff, format and
mypy clean.

### Frozen baseline recorded before any v0.7 work

All eleven artifacts match their v0.6.3 digests, including the calculator at
`53fc1d4d5b7adee09618d77ad62d4086ba56b78569832d6fc7c3bcd5c2695bbc`.

### Feasibility verified before starting

RTX 4080 16 GiB with torch 2.13+cu130; Qwen3-0.6B and Qwen3-1.7B already in the
local HF cache; `google/IFEval`, `natolambert/xstest-v2-copy` and
`allenai/reward-bench` reachable. No v0.7.0 tag exists, so the release number is
uncontested.

### Next action

Phase A 7.3: default new extension sidecars to schema version 2 binding
`dataset_sha256`, `dataset_rows` and generator identity, while continuing to
read valid public v1 sidecars.

## v0.6.3 Security, artifact integrity and release-state hardening

| item | current state |
Expand Down
54 changes: 36 additions & 18 deletions docs/generated/quality.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,41 @@
{
"schema_version": 1,
"schema_version": 2,
"release": "0.6.3",
"status": "released",
"measured_commit": "e8a36db60b2146b684204df8a8bea3e20c11d8e4",
"measured_at": "2026-08-05T18:20:00-07:00",
"platform": "Windows 11 Pro 10.0.22631, CPython 3.12, coverage branch mode",
"cpu_non_gpu_non_network": {
"passed": 1830,
"skipped": 2,
"deselected": 6,
"branch_coverage_percent": 86.10,
"skip_reason": "symlink creation requires privileges on Windows; hard-link and case aliases cover the same guard"
"quality_floor": "1,560+ tests and 85%+ branch coverage at v0.6.3",
"local_validation": {
"scope": "the maintainer's workstation, where the GPU and Windows-specific paths actually run",
"commit": "e8a36db60b2146b684204df8a8bea3e20c11d8e4",
"commit_relationship": "final pull-request head; the squash merge that became the release commit has a different hash and was not itself measured here",
"measured_at": "2026-08-05T18:20:00-07:00",
"platform": "Windows 11 Pro 10.0.22631",
"python": "CPython 3.12",
"coverage_mode": "branch",
"cpu_non_gpu_non_network": {
"passed": 1830,
"skipped": 2,
"deselected": 6,
"branch_coverage_percent": 86.1,
"skip_reason": "symlink creation requires privileges on Windows; hard-link and case aliases cover the same guard"
},
"gpu": {
"passed": 5,
"hardware": "NVIDIA GeForce RTX 4080"
},
"network": {
"passed": 3
}
},
"gpu": {
"passed": 5,
"hardware": "NVIDIA GeForce RTX 4080"
},
"network": {
"passed": 3
},
"quality_floor": "1,560+ tests and 85%+ branch coverage at v0.6.3"
"release_validation": {
"scope": "the exact published commit, validated by CI rather than locally",
"commit": "005a4549da713716e64c3ae80ff55fb131519f79",
"workflows": {
"ci": "https://github.com/DaoyuanLi2816/mini-verl/actions/runs/31080175904",
"build": "https://github.com/DaoyuanLi2816/mini-verl/actions/runs/31080175961",
"docs": "https://github.com/DaoyuanLi2816/mini-verl/actions/runs/31080175972",
"release": "https://github.com/DaoyuanLi2816/mini-verl/actions/runs/31084165317"
},
"conclusion": "success",
"gpu_coverage": "none; no GPU runner is configured for this repository, so the GPU counts above exist only from the local measurement"
}
}
4 changes: 2 additions & 2 deletions docs/overrides/main.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{% extends "base.html" %}

{% block announce %}
<div class="docs-channel" data-stable-version="0.6.3" data-dev-version="0.6.4.dev0">
<div class="docs-channel" data-stable-version="0.6.3" data-dev-version="0.7.0.dev0">
<strong id="docs-channel-label">Stable documentation</strong>
<label for="docs-version-selector">Version</label>
<select id="docs-version-selector" aria-label="Documentation version">
<option value="stable">Stable 0.6.3</option>
<option value="dev">Development 0.6.4.dev0</option>
<option value="dev">Development 0.7.0.dev0</option>
</select>
</div>
{% endblock %}
35 changes: 34 additions & 1 deletion docs/release-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,40 @@ This is the release gate and publication record for miniVERL. A checked item
names an invariant exercised on the stated source. Publication begins only
after the exact release commit and its remote checks are green.

## v0.6.4 (in development)
## v0.7.0 External alignment evidence (in development)

Phase A, foundation hardening, changes no scientific result.

- [x] `bridge doctor` validates the bundle tree before opening any file in it.
Reproduced on Windows with a junction: the hash check walked into a
directory outside the bundle and the metadata scan reported
`semantic_secret_key` against a file the bundle did not contain. Symlinks,
reparse points, non-regular files, escaping entries and oversized trees
are refused, and a refused bundle reports every check as `not_inspected`.
- [x] The portable metadata privacy scan distinguishes
`heuristic_passed_full` from `heuristic_incomplete`, records each gap
with its file and reason, and `--require-complete-metadata-scan` fails on
an incomplete inspection.
- [x] New extension sidecars are schema version 2 and bind the digest and row
count of the dataset they are published beside. Sidecars published by
0.6.0-0.6.3 still read.
- [x] Conversion captures source identity up front and re-checks it before
publishing, so a report can never describe bytes the conversion did not
read.
- [x] Output-to-source row provenance is encoded as contiguous runs rather than
one entry per row, and extension deduplication detail is bounded with an
exact total.
- [x] The text gate covers Latin-1 range mojibake; two CHANGELOG lines that
survived v0.6.3 are repaired. The tensor-to-float warnings in
`test_chunked_equivalence.py` are gone.
- [x] The quality record separates the locally measured commit and platform
from the exact release commit validated by CI, and states that no GPU
runner exists.
- [ ] Phases B-J: external benchmark governance, evaluation runtime,
non-saturated checkpoint selection, teacher qualification, the method
matrix, preregistration and the final study.

## v0.6.4 (superseded by v0.7.0)

- [x] A reward scaffold saved with a UTF-8 byte-order mark parses instead of
being reported as a syntax error. CPython strips the BOM when it reads a
Expand Down
5 changes: 4 additions & 1 deletion release-state.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ stable:
released_at: "2026-08-06"

development:
version: "0.6.4.dev0"
# v0.7.0 is the external alignment study. There is no v0.6.4 release: the
# foundation hardening in this cycle ships as part of it rather than as an
# intermediate maintenance version.
version: "0.7.0.dev0"
8 changes: 7 additions & 1 deletion scripts/check_text_integrity.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@
#: `鈥` is a mangled em dash, `鈫` a mangled arrow, `锛`/`銆` mangled CJK
#: punctuation. None of these is ever written on purpose here, including in the
#: Chinese README, so this needs no per-file allowlist.
MOJIBAKE_LEADERS = ("鈥", "鈫", "锛", "銆", "鎴", "鑰", "娴", "鏂")
#:
#: `脳` is the Latin-1 range case rather than the CJK one: `×` (U+00D7) is
#: `C3 97` in UTF-8, and those two bytes read as GBK are `脳`. The v0.6.3 gate
#: only looked for three-byte CJK punctuation leaders, so `State 脳 Supervision`
#: and `1.63脳` survived in CHANGELOG.md. `搂` (`§`) and `娄` (`¦`) damage the
#: same way.
MOJIBAKE_LEADERS = ("鈥", "鈫", "锛", "銆", "鎴", "鑰", "娴", "鏂", "脳", "搂", "娄")

#: The only files allowed to contain the damaged sequences: the detector itself
#: and its regression tests, which must spell them out to recognise them. Keep
Expand Down
2 changes: 1 addition & 1 deletion src/miniverl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@

from __future__ import annotations

__version__ = "0.6.4.dev0"
__version__ = "0.7.0.dev0"

__all__ = ["__version__"]
Loading