Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
7d9fa3c
docs(adr): ADR-0012 persistence reset to SQLite + corrected project s…
RedEyeNinja-BKK Aug 6, 2026
84ff725
docs: finalize ADR-0012 persistence contracts
RedEyeNinja-BKK Aug 6, 2026
ce05625
chore: establish methodfactory package, test extras, CI matrix, and i…
RedEyeNinja-BKK Aug 6, 2026
fda563d
refactor: introduce storage protocol and canonical serialization prim…
RedEyeNinja-BKK Aug 6, 2026
e442929
feat: add SQLite schema creation, identity checks, and append-only gu…
RedEyeNinja-BKK Aug 6, 2026
b0dd2ca
fix(storage): Finding 1 - SQLite open and initialization contract exe…
RedEyeNinja-BKK Aug 7, 2026
11ba5a7
fix(storage+manifest+errors): Finding 2 - one canonical serialization…
RedEyeNinja-BKK Aug 7, 2026
6f3b94d
fix(artifacts+paths+limits): Finding 3 - durability, path validation,…
RedEyeNinja-BKK Aug 7, 2026
5c34953
docs+ci: Finding 4 - align documentation and CI evidence
RedEyeNinja-BKK Aug 7, 2026
798ce1c
fix(storage): Finding 2 item 4 completion - translate raw sqlite3 at …
RedEyeNinja-BKK Aug 7, 2026
91de1b8
ci: allowlist egg-info in explicit artifact scan (install byproduct)
RedEyeNinja-BKK Aug 7, 2026
daaa506
feat(boundary): Finding 1 - enforce the complete boundary model
RedEyeNinja-BKK Aug 7, 2026
f1fb72b
fix(artifacts): Finding 2 - genuinely immutable blob publication + re…
RedEyeNinja-BKK Aug 7, 2026
91f83af
fix(storage): Finding 3 - complete SQLite schema and open verification
RedEyeNinja-BKK Aug 7, 2026
94897ce
fix(errors): Finding 4 - complete the public error boundary
RedEyeNinja-BKK Aug 7, 2026
fd1bff5
fix(protocol): complete first-release boundary and unit model (review…
RedEyeNinja-BKK Aug 7, 2026
82fa8ca
fix(artifacts): complete durability and failure translation (review 4…
RedEyeNinja-BKK Aug 7, 2026
a810bef
fix(storage): make SQLite open and schema verification exact (review …
RedEyeNinja-BKK Aug 7, 2026
ea5b054
fix(boundary): freeze the actual public error surface (review 4879440…
RedEyeNinja-BKK Aug 7, 2026
9146872
feat(storage): transactional create/load/apply with idempotent replay…
RedEyeNinja-BKK Aug 7, 2026
b5adb3e
test(storage): transactional slice evidence - engine/store/chain suit…
RedEyeNinja-BKK Aug 7, 2026
e8b7879
fix(storage): closure A1-A3 - semantic create identity, canonical sto…
RedEyeNinja-BKK Aug 7, 2026
7213e3d
feat(storage): invariant closure - deterministic replay + timestamp c…
RedEyeNinja-BKK Aug 7, 2026
42ff7d9
docs: freeze v0.1.2 migration and export compatibility contract
RedEyeNinja-BKK Aug 7, 2026
b9e46c1
docs: close migration compatibility contract
RedEyeNinja-BKK Aug 7, 2026
c4ddcf0
feat(migration): frozen v0.1.2 reader, atomic SQLite migration, deter…
RedEyeNinja-BKK Aug 7, 2026
34ba9d1
test(migration): fb5641c-origin fixtures + 44 migration/export tests;…
RedEyeNinja-BKK Aug 7, 2026
54ac313
fix(migration): close code-review findings - fail-closed boundary, at…
RedEyeNinja-BKK Aug 7, 2026
3a8d158
fix(migration): close round-2 review - root-mode invariant, snapshot …
RedEyeNinja-BKK Aug 7, 2026
9b718d6
fix(migration): close round-3 review - typed snapshot container guard…
RedEyeNinja-BKK Aug 8, 2026
ec62f17
fix(migration): close round-4 review - surrogate encoding, dest-root …
RedEyeNinja-BKK Aug 8, 2026
a0450b1
fix(migration): close round-5 review - typed UTF-8 boundary for all j…
RedEyeNinja-BKK Aug 8, 2026
7abdf53
fix(migration): close round-6 review - fd-pinned dest root, unconditi…
RedEyeNinja-BKK Aug 8, 2026
6a365cd
chore(migration): post-review hygiene - docstring steps restored, fd-…
RedEyeNinja-BKK Aug 8, 2026
775630e
ci(release-gate): fetch full history for fb5641c fixture generation
RedEyeNinja-BKK Aug 8, 2026
c70a6f3
docs(architecture-reset): mark migration/export gate complete at 7756…
RedEyeNinja-BKK Aug 8, 2026
a9fafbf
chore(release): prepare 2.0.0rc1 candidate
RedEyeNinja-BKK Aug 8, 2026
a6aeb8c
ci(release-gate): fix isolated-venv import provenance (CWD shadowing)
RedEyeNinja-BKK Aug 8, 2026
a037ecb
docs(architecture-reset): record RC1 candidate head a6aeb8c and gate …
RedEyeNinja-BKK Aug 8, 2026
93ec1af
docs(architecture-reset): label a6aeb8c as CI-proven RC preparation head
RedEyeNinja-BKK Aug 8, 2026
ac090e8
chore(release): close RC1 evidence identity
RedEyeNinja-BKK Aug 8, 2026
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
218 changes: 192 additions & 26 deletions .github/workflows/release-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,208 @@ on:
branches: [main]
workflow_dispatch:

permissions:
contents: read

jobs:
gate:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4
# Explicitly check out the ACTUAL pull-request HEAD SHA, not GitHub's
# synthetic merge ref (actions/checkout defaults to the merge ref on
# pull_request). This makes the CI evidence literal-commit proof: the
# tested tree is exactly the branch head, not a candidate-tree-
# equivalent merge.
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 (pinned SHA)
with:
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
# Full history required: migration tests generate fixtures from the
# exact public v0.1.2 commit fb5641c (tag v0.1.2-integrity), which
# is not present in a depth-1 checkout of this branch.
fetch-depth: 0

- uses: actions/setup-python@v5
# Literal-commit identity assertion: the checked-out HEAD MUST equal the
# event's expected SHA. A mismatch fails CI. This is the proof that a
# successful run tested the exact commit, not a synthetic merge tree.
- name: Assert checkout identity
run: |
ACTUAL="$(git rev-parse HEAD)"
EXPECTED="${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}"
echo "actual HEAD: $ACTUAL"
echo "expected SHA: $EXPECTED"
if [ "$ACTUAL" != "$EXPECTED" ]; then
echo "::error::checkout identity mismatch (actual != expected)"; exit 1
fi
echo "checkout identity OK: tested tree is the exact expected commit"

- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 (pinned SHA)
with:
python-version: "3.11"
python-version: ${{ matrix.python-version }}

- name: Install deps
run: pip install pyyaml
- name: Install with test extras
run: pip install -e ".[test]"

- name: Unit tests (hard gate)
run: python -m unittest discover -s core/tests -t .
- name: Canonical unit tests
run: python -m unittest discover -s methodfactory/tests -t .

- name: Identity sweepno stale PE references in new content
- name: Packaging smokemf entry point
run: |
# Zero-tolerance: new Method Factory content (prompts/ + core/ +
# action envelope spec) must not carry any Process Engine identity.
# Legacy source material (skills/, templates/, references/, evals/,
# scripts/) is Phase 5 quarantine work — exempt (ADR-0009).
# ADRs and manifest-contract document the migration and are exempt.
STALE='Process Engine|process-engine|v1\.9\.1|lineage v7\.2'
SCOPE="prompts/ core/ docs/action-envelope.md"
mf --version
python -m methodfactory --version
test "$(mf --version)" = "methodfactory 2.0.0rc1"
test "$(python -m methodfactory --version)" = "methodfactory 2.0.0rc1"

FAIL=0
while IFS= read -r pattern; do
[ -z "$pattern" ] && continue
matches=$(grep -rIn "$pattern" $SCOPE --include='*.md' --include='*.py' 2>/dev/null || true)
if [ -n "$matches" ]; then
echo "::error::Stale PE reference in new content: $pattern"
echo "$matches"
FAIL=1
# RC1 packaging proof — build the distributable WHEEL from the EXACT
# candidate source into a disposable directory OUTSIDE the repo, so the
# tracked-worktree and artifact-scan steps below stay clean. No new
# build dependency: pip wheel uses the declared setuptools backend.
# (sdist is NOT claimed by CI; any sdist evidence is local-only
# supplemental unless independently CI-produced.)
- name: Build distributable wheel
run: |
set -euo pipefail
export MF_DIST="$RUNNER_TEMP/mf-dist"
mkdir -p "$MF_DIST" "$RUNNER_TEMP/mf-src"
git archive HEAD | tar -x -C "$RUNNER_TEMP/mf-src"
cd "$RUNNER_TEMP/mf-src"
python -m pip wheel . --no-deps -w "$MF_DIST"
ls -la "$MF_DIST"
python - <<'EOF'
import hashlib, os, pathlib
dist = pathlib.Path(os.environ["MF_DIST"])
wheels = sorted(dist.glob("methodfactory-2.0.0rc1-*.whl"))
assert len(wheels) == 1, f"expected exactly one rc1 wheel, got {[p.name for p in dist.iterdir()]}"
for p in wheels:
print(p.name, hashlib.sha256(p.read_bytes()).hexdigest())
EOF

- name: Isolated wheel install + version proof
run: |
set -euo pipefail
export MF_VENV="$RUNNER_TEMP/mf-venv"
export MF_DIST="$RUNNER_TEMP/mf-dist"
python -m venv "$MF_VENV"
"$MF_VENV/bin/python" -m pip install --no-deps "$MF_DIST"/*.whl
# Run OUTSIDE the repo: a heredoc through `python -` puts CWD on
# sys.path, which would shadow the installed package with the
# checkout copy and break the import-provenance proof.
cd "$RUNNER_TEMP"
# import provenance: must resolve from the venv site-packages, not
# the development checkout.
"$MF_VENV/bin/python" - <<'EOF'
import methodfactory, os, pathlib
print("import file:", methodfactory.__file__)
venv = pathlib.Path(os.environ["MF_VENV"]).resolve()
assert pathlib.Path(methodfactory.__file__).resolve().is_relative_to(venv), \
"methodfactory resolved outside the isolated venv"
assert methodfactory.__version__ == "2.0.0rc1", methodfactory.__version__
EOF
test "$("$MF_VENV/bin/mf" --version)" = "methodfactory 2.0.0rc1"
test "$("$MF_VENV/bin/python" -m methodfactory --version)" = "methodfactory 2.0.0rc1"
# CLI surface: only migrate-store + export may be present.
"$MF_VENV/bin/mf" --help
for banned in create apply status summary review trial ship triage; do
if "$MF_VENV/bin/mf" --help | grep -qE "^\s+$banned\b"; then
echo "::error::forbidden lifecycle command exposed: $banned"; exit 1
fi
done <<EOF
$(echo "$STALE" | tr '|' '\n')
done

# Packaged functional smoke: canonical exact-fb5641c fixture -> installed
# mf migrate-store -> authoritative validation -> installed mf export
# (both formats) -> legacy evidence revalidated by the frozen reader;
# source must remain unchanged.
- name: Packaged migration/export smoke (isolated env)
run: |
set -euo pipefail
export MF_SMOKE="$RUNNER_TEMP/mf-smoke"
export MF_STORE="$RUNNER_TEMP/mf-store"
export MF_LEGACY_REVAL="$RUNNER_TEMP/mf-legacy-revalidate"
export MF_VENV="$RUNNER_TEMP/mf-venv"
python - <<'EOF'
# Generate the canonical fixture through the sanctioned mechanism
# (exact public fb5641c code via the repo's disposable worktree).
# Runs from the checkout on purpose: the editable install provides
# methodfactory.tests._fixtures.
import os, pathlib, shutil
from methodfactory.tests._fixtures import generate_fixture, standard_workflow
root = pathlib.Path(os.environ["MF_SMOKE"])
shutil.rmtree(root, ignore_errors=True)
generate_fixture(str(root), workflow=standard_workflow)
EOF
mkdir -p "$MF_STORE"
chmod 700 "$MF_STORE"
# source immutability baseline
sha256sum "$MF_SMOKE"/events/*.events.jsonl > "$MF_STORE/source.before"
# Run the installed tooling OUTSIDE the repo (CWD on sys.path would
# shadow the installed package with the checkout copy).
cd "$RUNNER_TEMP"
# installed migrate-store
"$MF_VENV/bin/mf" migrate-store --source "$MF_SMOKE" --dest "$MF_STORE/methodfactory.sqlite3"
# authoritative validation via installed primitives
"$MF_VENV/bin/python" - <<'EOF'
import os
from methodfactory.storage.store import SqliteManifestStore
store = SqliteManifestStore(os.environ["MF_STORE"])
try:
for pkg in store.list_package_ids():
result = store.validate_chain(pkg, verify_artifacts=True)
assert result["valid"], result
print("validated", pkg, result)
finally:
store.close()
EOF
# installed exports (both formats)
"$MF_VENV/bin/mf" export --store "$MF_STORE" --output "$MF_STORE/events-v1.jsonl" --format method-factory-events-v1
"$MF_VENV/bin/mf" export --store "$MF_STORE" --output "$MF_STORE/legacy.jsonl" --format legacy-v012-jsonl
test -s "$MF_STORE/events-v1.jsonl"
test -s "$MF_STORE/legacy.jsonl"
# legacy evidence export revalidates under the frozen legacy reader
"$MF_VENV/bin/python" - <<'EOF'
import os, pathlib, shutil
from methodfactory.migrations.v012_jsonl import LegacySource
lr = pathlib.Path(os.environ["MF_LEGACY_REVAL"])
store = pathlib.Path(os.environ["MF_STORE"])
shutil.rmtree(lr, ignore_errors=True)
(lr / "events").mkdir(parents=True)
(lr / "packages").mkdir()
(lr / "artifacts" / "blobs").mkdir(parents=True)
shutil.copy(store / "legacy.jsonl", lr / "events" / "pkg_demo_001.events.jsonl")
for blob in (store / "blobs").iterdir():
shutil.copy(blob, lr / "artifacts" / "blobs" / blob.name)
LegacySource(lr).validate()
print("legacy evidence export revalidated OK")
EOF
# source unchanged after migration/export
sha256sum "$MF_SMOKE"/events/*.events.jsonl > "$MF_STORE/source.after"
diff "$MF_STORE/source.before" "$MF_STORE/source.after"
echo "source unchanged OK"

# Honest terminology (Finding 4 item 2): this proves a CLEAN TRACKED
# WORKTREE (no uncommitted/untracked tracked-tree changes). Generated
# runtime/build files are gitignored, so their absence is proven by the
# explicit artifact scan below, not by git status alone.
- name: Clean tracked worktree
run: |
test -z "$(git status --porcelain)" || { echo "::error::dirty tracked worktree"; git status --porcelain; exit 1; }

# Explicit runtime/build-artifact scan with a documented allowlist
# (Finding 4 item 2): runtime store artifacts and SQLite files must not
# exist in the filesystem. methodfactory.egg-info IS allowlisted here:
# it is a build byproduct of the `pip install -e ".[test]"` step above
# (generated + gitignored), not a runtime store artifact. build/, dist/,
# and .pytest_cache are checked when they would be produced by this job.
- name: Runtime/build-artifact scan (explicit)
run: |
FAIL=0
for p in .mf build dist .pytest_cache; do
if [ -e "$p" ]; then echo "::error::forbidden generated artifact present: $p"; FAIL=1; fi
done
# SQLite rollback-journal files are forbidden (Finding 4 item 3).
found=$(find . -name '*.sqlite3' -o -name '*.sqlite' -o -name '*.db' \
-o -name '*.wal' -o -name '*.shm' -o -name '*.journal' 2>/dev/null | grep -v '^\./\.git/' || true)
if [ -n "$found" ]; then echo "::error::forbidden SQLite/journal artifact:"; echo "$found"; FAIL=1; fi
exit $FAIL
19 changes: 19 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,22 @@ node_modules/
# Trial workspaces (generated at trial time)
workspace/
iteration-*/

# Python build artifacts
*.egg-info/
build/
dist/

# Method Factory runtime store (operator data)
.mf/

# SQLite store + sidecars + rollback journal (ADR-0012 §3, Finding 4 item 3)
*.sqlite3
*.sqlite
*.db
*.wal
*.shm
*.journal

# Test caches
.pytest_cache/
11 changes: 0 additions & 11 deletions core/__init__.py

This file was deleted.

70 changes: 0 additions & 70 deletions core/adapters/artifact_store.py

This file was deleted.

Loading
Loading