Skip to content

refactor(replan): qualify semantic progress in TypeScript - #6613

Open
hhyykk wants to merge 3 commits into
loopx-project:mainfrom
hhyykk:codex/ts-replan-progress-20261016
Open

hhyykk wants to merge 3 commits into
loopx-project:mainfrom
hhyykk:codex/ts-replan-progress-20261016

Conversation

@hhyykk

@hhyykk hhyykk commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Goal And Delivered Outcome

Move the complete semantic-progress novelty rules into the existing TypeScript replan qualifier. Python's semantic_progress_delta and _has_new_terminal_coverage decision functions are deleted. The native delta and obligation-outcome owners now compose inside one existing request. Public refresh/ACK fields and persisted identities stay compatible.

Main sync: rebased onto b543d076995423544b0eeb1990d59d7480f48339; current head ed1bd14336e4c34038cfafdf0bc6b71a11d67b61. Main also merged #6615 during validation. The Python qualifier now reuses its shared project_replan_semantics transport. Our manual size check and two allowlist edits have been removed. The native novelty rules remain unchanged; no progress-rule owner is duplicated. The PR diff contains only these three DCO-signed commits.

Review holds remain: the previous head's File full-CLI p95 increased versus baseline by +33.757 ms for blocker refusal and +54.407 ms for first successful writeback; both increases exceed the unexplained 25 ms target. Matched performance has not been repeated on the synchronized head. Prior DSH maintainability and old-head CI failures are not waived or declared fixed by this rebase. This proposal is not merge-ready.

Author Declaration

Criterion Disposition Owner / evidence
One typed rule owner; remove replaced Python authority implemented progress_delta.ts feeds existing replan_semantics.ts; wire entrypoint rejects caller-precomputed observation_delta
Semantic parity, malformed input and replay implemented Native boundary tests, real File/SQLite CLI, complete state comparison; validation below
Ordinary packaged execution implemented Fresh normal wheel/sdist and imported-package prefix checks
Relevant performance not_met Prior full-CLI holds above; synchronized-head performance unqualified
Whole control-plane/Python retirement deferred Shared codecs and remaining caller exit below
Provider/default/promotion or deployment out_of_scope Existing authority and persistence contracts remain

Scope And Continuation

The target remains TypeScript for the whole control plane. This slice removes the Python novelty/terminal-coverage policy. It preserves error precedence: context/history checks first; missing/non-object current skips baseline/window normalization; otherwise current → prior → tolerant window, then Vision normalization. Full window order and multiplicity survive the wire. The existing shared project_replan_semantics adapter selects main's private same-UID request/response snapshot policy, with its existing 64 MiB cap; history is not truncated.

Python still owns shared observation/fingerprint, history and Vision codecs plus context/checkpoint orchestration. Native decoding validates normalized carrier shape; it does not attest fingerprint authenticity. Retire those codecs with their remaining refresh writers, replan context/history readers, external-progress-review and Explore-evidence consumers. Do not create a second normalization or fingerprint owner in this step.

PR overlap: #6591 owns delegation inventory; #6602 owns Goal task-map composition; #6596 merged quota admission. The main sync includes #6601 quota capture/checkpoint diagnostics, #6603 delivery-check presentation and #6615 complete replan snapshot transport. None duplicates this rule. The shared allowlist edits are now upstream and absent from this PR. The single Python adapter conflict was resolved by keeping main's shared transport and this PR's normalized progress_source; native rules and normalization/error order stay unchanged.

Migration economics against synchronized main

Field Receipt
Canonical owner Before: Python progress novelty/terminal coverage plus the native outcome owner. After: native progress_delta.ts feeds existing replan_semantics.ts in-process. The wire entrypoint rejects precomputed observation_delta.
Legacy code deleted Both Python decision functions removed: 107 exact function-definition lines (16 + 91, including signatures/docstrings). Python gross diff deletion is 117. Earlier historical text counted one separator as a definition line; 107 is the corrected span, not a new code change. Shared codecs remain live.
Bridge added 18 classified lines: 8 Python normalized-fact adapter lines, 9 native entrypoint/import lines, 1 dispatcher replacement. Main's shared project_replan_semantics owns transport. The former manual size check and both allowlist additions are removed from this PR. No new effect, daemon, leaf RPC, fallback or dual-run.
Cross-runtime calls Selected delta+outcome qualifier remains 1→1; first CLI qualification/replay uses 1/0 qualifier calls. The nonempty-context/checkpoint facade remains 3→3 by its unchanged orchestration; historical instrumented profile measured that count. Current console parity instruments actual qualifier calls.
Product net change 5 files, +140/−122 = +18. Validation/config: 7 files, +452/−221 = +231. Docs: 3 files, +32/−12 = +20. No dependency or generated-file change. Strict native decoding remains in the product count; no net deletion claim.
Scaffolding Python pure-policy assertions move to native tests; integration/codec tests stay. Temporary parity/mutation tools are not committed. Durable CLI/regression tests express public or persisted behavior.
Facade exit Retire shared observation/fingerprint/history/Vision codecs and source/context/checkpoint adaptation with the remaining refresh writers, replan context/history readers, external-progress-review and Explore-evidence consumers. Keep one normalization/fingerprint owner until that cutover.
Correctness/performance New-base real File/SQLite source and installed-artifact parity, large history, malformed input and replay are versioned separately below. The original mutation and matched performance remain historical. New matched performance is unqualified; both old File p95 holds remain.

Validation

Current validation base/head: b543d076995423544b0eeb1990d59d7480f48339 / ed1bd14336e4c34038cfafdf0bc6b71a11d67b61. Synthetic/public inputs on Linux x86_64, CPython 3.13.12, official Node.js 22.22.3 / SQLite 3.51.3.

Check Result Revision and limit
Rebase integrity passed Three DCO commits, 15 candidate files; the shared transport conflict is resolved, main is an ancestor
Python integration passed 151 tests on this head, including real module CLI File/SQLite, 12,000-row history, quota capture and main's new replan transport/lifecycle regressions
Native/static passed 78 native tests including current-main checkpoint artifacts; full control-plane typecheck, Ruff and diff check
Semantic vocabulary passed Final head passed in 89.8 s under the unchanged default 120 s budget. An intermediate-head run timed out at 120 s, then passed an isolated retry in 65.055 s; those intermediate observations remain versioned separately.
Frontend/packages passed Fresh Chat build and normal wheel/sdist installs; all 17 changed product files from the PR or upstream main match source/archive/install bytes
Full console/backend/distribution parity passed 12 backend/scenario rows × four variants: pinned main, source, installed wheel and installed sdist; complete JSON/state and accepted replay match
Historical rule/mutation evidence passed on old head Old 02fbace native known-blocker mutation incorrectly accepted and was caught by the real console assertion. Original 116-test/63-native run and broader 589-test run are historical, not current-head executions
Maintainability unresolved historical failure Oversized _run_dsh_operation_host failed on old base/head; its bytes remain unchanged on current main/head. No ratchet waiver or unrelated DSH edit
GitHub CI pending new head Old 02fbace had passing TS/static, Windows, real PostgreSQL and DCO checks, plus failed browser/Stage2C/release checks. They are not relabeled as current-head results
Broader scope not_run No local whole-repository suite, Windows/macOS, PostgreSQL, real-model journey, ten-day adoption or new matched performance run

The installed matrix compares pinned main, source, wheel and sdist on File/SQLite across six scenarios. It retains the complete JSON value, diagnostics, receipt/identity bindings, registry/Markdown/material artifacts, all durable JSONL and actual canonical snapshot. Successful replay is read back again and duplicates no persisted effect. Rejections retain the existing paused-delivery audit; they are not called zero effects. Fixed observation/rollout clock codecs and hash seed replace no domain rule; no output field is removed or rewritten.

refresh-state uses the published loopx.entrypoint.main route and currently falls back to the full parser. Its qualifier runs outside a whole-command runtime scope. First qualification uses one qualifier RPC; successful replay uses zero. The complete nonempty-context facade still uses three requests. Historical scoped microbenchmarks are not console-performance qualification.

Previous measured File tails and their full performance tables remain in the version-bound historical validation. The synchronization comment supplies current base/head commands and parity hashes. Old CI: Python Tests, Release Artifacts. The Stage2C collection imports removed capture_present; that static defect is also present in main. Browser failure attribution is unproven. No unrelated UI/CI repair is bundled here.

Frontend / Visual Evidence

UI impact from this PR: none. The refreshed Chat bundle includes already-merged main changes. The PR changes no screen, setting, command or caller-visible field. Existing refresh callers retain their contract.

Shared-authority Fixture Impact

Same persisted schema and semantic dimensions. Real File/SQLite read, refresh, ACK and replay are exercised. No provider routing/default, promotion or compatibility-projection format changes; no three-arm promotion or real PostgreSQL qualification is claimed for this synchronized head.

Boundary Checklist

  • Three commits DCO signed; exact patch scope preserved through rebase.
  • Public code/text exclude private state, machine paths, credentials and raw logs.
  • Clean Code Guard integration review applied; Test Guard and Docs Guard refreshed for the new validation packet.
  • Existing performance, maintainability and CI limits remain explicit; no merge/deploy authorization inferred.

Type: refactor, durable tests, docs. Area: control plane. Whole migration and shared-codec exits remain open.

@hhyykk

hhyykk commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor Author

Historical validation for 02fbace / a448. Superseded by the current main-sync validation. Exact deleted function-definition span corrected to 107 lines; the earlier 108 included one separator. Historical tests and performance values are unchanged.

Exact-head author validation

Run state: finished. Performance disposition: not_met; the two File tail holds and the pre-existing maintainability failure remain for owner review.

Base: a4483aaece5bc74ec3f969fd067229487022401b. Head: 02fbace7658b96489cf8be20dce6463c3d8c388d.

This is a proposed rule-owner cutover. It does not authorize merge, provider promotion, deployment, or whole-program completion. Inputs were synthetic/public fixtures on Linux x86_64, CPython 3.13.12, official Node.js 22.22.3 and embedded SQLite 3.51.3.

Checks and limits

  • Passed on this head: 116 related Python tests, 63 native tests, complete control-plane typecheck, Ruff, diff check, full semantic-vocabulary smoke and changed-diff inventory advisory. The Python run includes real python -m loopx.cli File/SQLite journeys and a 12,000-row complete-history regression.
  • Supporting earlier revision: 589 related Python tests passed at 1cda3637d before the final malformed-carrier hardening. They are not relabeled as a final-head run.
  • Ordinary installed artifacts: normal wheel and sdist built from this head, each installed in a fresh environment. All seven changed product files have identical bytes in source, archives and installed packages. The receiver checks the imported package prefix before invoking the real console target.
  • Semantic mutation: all seven product files copied from the exact head; only native blocker_repeated membership disabled. The same console receiver passed the base/head refusal and then failed because the mutant incorrectly accepted the old blocker. No scope/setup failure counts as mutation evidence.
  • Existing repository failure: test_current_repository_debt_is_reviewed_without_line_count_pins reports oversized _run_dsh_operation_host in loopx/control_plane/turn_driver/dsh_operation_host.py. It fails on both immutable base and final head, whose source bytes are identical. Other architecture/ratchet checks passed (40). No ratchet exception, budget or unrelated DSH code was changed. This hold still needs maintainer review.
  • Not run: whole repository suite, Windows/macOS, PostgreSQL, real-model journeys, ten-day adoption/soak. GitHub CI is separate and starts on publication. Newer unrelated main commits were inspected for overlap, not executed as a combined local build.

Re-run the focused committed checks from this head with the qualified Node version on PATH:

export LOOPX_USAGE_PING=0
uv run --extra test python -m pytest -q \
  tests/control_plane/test_progress_observation.py \
  tests/control_plane/test_external_progress_review.py \
  tests/control_plane/test_replan_writeback_projection.py \
  tests/control_plane/test_replan_context_evidence.py \
  tests/control_plane/test_replan_progress_native_cli.py
node --no-warnings --experimental-sqlite --experimental-strip-types --test \
  tests/control_plane_ts/progress_delta.test.ts \
  tests/control_plane_ts/replan_semantics.test.ts \
  tests/control_plane_ts/replan_history.test.ts \
  tests/control_plane_ts/effect_runtime_snapshot.test.ts
npm run typecheck:control-plane
uv run --extra test python scripts/generate_semantic_inventory.py \
  --changed-from a4483aaece5bc74ec3f969fd067229487022401b
uv run --extra test loopx canary smoke-suite --script semantic-vocabulary-drift-smoke.py
git diff --check a4483aaece5bc74ec3f969fd067229487022401b HEAD

Real successful writeback and replay compare the ACK's original obligation/Todo/Turn binding, every material file, run artifact, all durable JSONL and the actual canonical snapshot. The original Todo stays open; authority/revision/Todos/leases stay unchanged. A replay duplicates no persisted effect. Rejected writebacks preserve source/index/artifact/provider state; the existing paused-delivery audit is retained and compared. These are complete JSON-value comparisons with no removed fields, not stdout-whitespace comparisons.

The six scenarios cover: new probe plus proof accepted; evidence churn alone refused; new probe without proof refused; old blocker under another work item refused; inconsistent terminal stop refused; new terminal scope with matching no-followup/stop accepted. The two accepted cases require literal outcome lists containing only new_probe_family or coverage_backed_no_followup; another outcome cannot mask a broken delta rule.

Migration economics

Field Receipt at the final merge base
Canonical owner Before: Python semantic_progress_delta / _has_new_terminal_coverage derived novelty and TS chose obligation outcomes. After: progress_delta.ts and the existing replan_semantics.ts compose that entire qualification inside the existing effect request. The actual wire entrypoint rejects caller-precomputed observation_delta.
Legacy semantic code deleted Both Python decision functions are removed (107 definition lines). progress_observation.py has 121 gross deleted diff lines, which also include adapter reshaping; those totals are not interchangeable. The shared normalization/fingerprint codec is retained and is not counted as retired.
Bridge code added 29 classified added lines: 17 Python request/source/snapshot adapter lines; 9 native entrypoint/import lines; 2 existing-method snapshot allowlist entries; 1 dispatcher replacement. No new effect name, daemon, per-field RPC or product dual-run.
Cross-runtime calls Selected delta+outcome qualification remains 1→1. The complete facade with context validation and nonempty trigger checkpoint read remains 3→3, on first qualification. Successful idempotent CLI replay uses 0→0 qualifier requests; rejected retries remain 1→1. No claim that the entire refresh CLI uses one RPC. Actual CLI instrumentation confirms one qualify per first writeback.
Product-code net change Seven production files: +151/−126 = +25. Tests/typecheck config: +452/−221 = +231. Docs: +32/−12 = +20. No dependency/generated artifact change. The small net increase includes strict native boundary validation; it is not a LOC reduction claim.
Migration scaffolding Old Python pure-policy tests are moved to native pure tests with a recorded invariant mapping. Integration/codec tests stay. No Python oracle, test-only effect, temporary dual runner or private fixture enters product code. Disposable parity/mutation scripts remain outside the repository.
Facade exit semantic_delta_from_writeback retains source baseline/window selection, context/history codecs, shared current→prior→window normalization, Vision normalization and existing checkpoint adaptation. Delete those seams together with the remaining refresh writers, replan history/context readers, external-progress-review and Explore-evidence codec consumers. Do not reproduce their Python normalization or fingerprint algorithm in TS during this step.
Correctness and performance Real refresh CLI, File/SQLite, immutable base and exact candidate, normal installed wheel/sdist, complete JSON output and durable state, restart/replay, strict malformed inputs and a physical known-blocker mutation. Cold/warm/RSS and matched full-CLI measurements below; no frozen gate is relaxed.

Full console/distribution parity

Each row compares pinned base, frozen source, fresh normal wheel and fresh normal sdist. All four produce the same full JSON observation and durable state. qualify_scope=[False]; accepted first call/replay have qualifier counts 1/0. No output normalization.

Provider Scenario Fixture SHA-256 Full observation SHA-256
file advanced 61a20d9b0b53e57c9ac11ae2172b7e6e18a3f3954e5f1b1f9499b0d216ccf828 94c3079c9452e4fda6b6714ca6a5834c07445a8a7c2d91e7d3f2429589ba305a
file evidence_only e340874567b552e8cb3c3afe307c99028e2a6029978919a2e0dfdcf36964e2f9 47306a3dd5a1328dc4e98b179fc6f9d1004057fd57ee14bb767bb56f692740da
file advanced_no_evidence ee475d10bba6d4c124d98a58f3e0dc356ef1ec11f2a2e7c808baa62047a3c4ad 704607f51114e2e8821a2752595c637b21d24166c9001d7d210ec146ae9a987d
file known_blocker f0bfcae4ca59b89c7f915b44c67b4cd45ccee3c562b836e11270d4c202d570d8 200e7c8fc44f2ada0b26ce00a08d1bd0546cc8d08ec0b06a454bffb849df3524
file terminal_inconsistent 1ae88b2f9f69e31e375afe8f31965e9e1713b7bc7408c2d3aaf8c12dbdb652ef 53de616b58e3ba992e7e052d6744b27b048638f50f1f51a36e456f73a30c74b4
file terminal_stop 48a98bafff64b2631e8457bb0d05a3924428321e578bbff32af821e458619578 aae36c4905b1405fef36e7be17d114d1f484a925372b82d6375077511b2d8ee5
sqlite advanced 0ec96725131df8653469cfe6a1b82de8cec8c760eb73e7ff2795b399f2257095 ca08cb68d5beba1fafe0153b4984c314bfae9c3196bc1074b211e03a84ff7f98
sqlite evidence_only faf7b2f7ce2294dfd38fb0acc8486df494021bc27426ab08db1981cd0c774c7e 566f755940eaeb4138099edb8f41d1cadb6a10a367743d46c8f31fad6ab39c60
sqlite advanced_no_evidence aede5f2e10837c5ee3f6893584161fce821c5fe3a7dc7260beddfad760373d07 7f8e9d564cb35f3aebb20f2440362ca1e131375c541e5a5dcbd8b7333e4ca40f
sqlite known_blocker b034393a46730d6a02887ac36e9cfeae8975cf4f74466ba21b906a2950571669 c6acd875b94e650fbd5c87decff0488ba1c67f173f3c28462815a7de13075086
sqlite terminal_inconsistent 76a72df1196bfeb1ed6eba3ee134df1a3b1595dadd28c08d9461c03f4dd8f458 5f7dbe130ceaa2c4ae9049b0d696a5790c4b5f07c354814f5465993bd97996f5
sqlite terminal_stop c76a6f9250ccc02955100f2e2f8e808c57f6d3a3e842b0e2f94b79b4dd52c083 b4a9a4107153a37553f1f8738015e8c70846ca13f0d23473f587e0fd370368f3

Performance qualification

Matched source baseline/head on the same synthetic path. The reported p95 is the sorted sample at index floor(0.95*n). Order alternates each pair; no heavy checks were run concurrently. These are instrumented complete CLI wall times, including Python startup and real persistence. Negative cases warm both qualifiers. Positive cases restore the same seed and prime the real provider outside the timed first successful writeback.

Workload Provider / scenario Pairs Base p50 / p95 ms Head p50 / p95 ms p95 delta Original gate
Repeated refusal file / evidence_only 64 1290.900 / 1430.422 1296.575 / 1381.402 -49.020 ms / -3.427% within bounds
Repeated refusal file / known_blocker 64 1300.887 / 1403.354 1301.706 / 1437.111 +33.757 ms / +2.405% HOLD
Repeated refusal sqlite / evidence_only 64 1388.123 / 1715.096 1392.000 / 1661.316 -53.780 ms / -3.136% within bounds
Repeated refusal sqlite / known_blocker 64 1304.632 / 1544.972 1311.032 / 1483.867 -61.105 ms / -3.955% within bounds
First successful writeback file / advanced 32 1647.605 / 1824.182 1655.754 / 1878.589 +54.407 ms / +2.983% HOLD
First successful writeback sqlite / advanced 32 1643.620 / 1769.186 1631.996 / 1757.753 -11.433 ms / -0.646% within bounds

Disposition: not_met — owner review remains required. The thresholds remain greater than 5% or an unexplained additive 25 ms p95. No result is waived or called noise. Before approval, the runtime/migration owner must explain or remove each tail regression using the same complete CLI workload and unchanged bounds. The runs establish neither sustained adoption nor whole-program performance.

Runtime profile and actual CLI boundary

Scope Samples per revision Base p50 / p95 ms Candidate p50 / p95 ms
Cold complete facade, including managed startup 12 431.023 / 588.617 420.259 / 475.790
Warm qualifier RPC inside existing request scope 200 0.434 / 1.127 0.440 / 1.045
Warm complete facade inside existing request scope 200 1.477 / 2.673 1.411 / 2.901

Baseline managed RSS: 99.45 MiB idle; 102.18 MiB after 200 calls. Candidate managed RSS: 108.20 MiB idle; 111.11 MiB after 200 facade calls. These are separate bounded Linux profile runs, not interleaved improvement evidence. The cold row includes startup plus the complete three-request facade; it is not a pure Node spawn timer.

The facade records context validation, one qualifier, and trigger-checkpoint read: three requests per nonempty-context call. The selected delta+outcome qualifier remains one request; successful CLI replay makes zero qualifier requests. Shared codecs and the other two facade requests are still Python-owned orchestration.

The console refresh fallback does not have that command scope. Its actual measured qualifier RPC is shown separately:

Provider / scenario Base RPC p50 / p95 ms Head RPC p50 / p95 ms
file / evidence_only 14.098 / 16.809 14.510 / 16.378
file / known_blocker 14.129 / 16.578 14.479 / 17.559
sqlite / evidence_only 14.780 / 24.408 15.039 / 21.750
sqlite / known_blocker 14.116 / 18.240 14.318 / 16.233
file / advanced 14.995 / 17.735 15.816 / 21.908
sqlite / advanced 15.176 / 17.536 16.158 / 20.046

RPC timing includes the existing unscoped runtime-revision/fingerprint work. The prior Python delta is outside that RPC timer and the native delta is inside it, so RPC differences are not complete rule-cost differences. The scoped microbenchmark does not qualify the full CLI tail. No command-scope optimization is part of this PR.

An earlier direct compatibility-parser diagnostic also reported a +61.560 ms File evidence-only p95 tail (+4.36%). It remains a noncanonical diagnostic, not a console acceptance run and not a claimed improvement or explanation. The final protocol uses the actual published entrypoint and asserts the observed full-parser fallback. A failed hypothetical scope=True assertion on the base was a harness error, not a semantic test result; it was corrected before these final runs.

Reproduce the console CLI comparison

Pinned source comparison: base a4483aaece5bc74ec3f969fd067229487022401b; implementation head 02fbace7658b96489cf8be20dce6463c3d8c388d. Run the commands below on Linux with git, uv, Python 3.13.12, and the qualified Node.js 22.22.3 on PATH. Use a quiet machine. Run the three stages sequentially.

The receiver calls the published console target, loopx.entrypoint.main(None), after setting sys.argv. At these commits, refresh-state is absent from cli_runtime._SELECTED_COMMANDS. It therefore uses the full parser. The common dispatcher returns before the lifecycle handler, so qualify runs outside the command scope. The receiver records this fact; the harness requires qualify_scope == [False] for both revisions. It does not add a product scope or alter an admission gate. Calling the importable compatibility parser directly is not the console measurement.

The scripts fix only the shared observation/rollout clock codecs and PYTHONHASHSEED=0. They retain the complete parsed JSON output, fingerprints, receipt bindings, run artifacts and all persistent JSONL contents. They do not normalize away output fields. The existing deduplicated paused-delivery audit is retained and compared. This is JSON-value parity, not a claim that stdout whitespace was compared.

1. Create disposable worktrees and one test environment

Run from a LoopX Git clone containing the two commits. If needed, fetch main from upstream and the implementation branch from the author before creating these worktrees. Fetching the author branch makes the pinned implementation commit available even if a later documentation commit is at its tip.

set -euo pipefail
export LOOPX_USAGE_PING=0
repo_dir=$(git rev-parse --show-toplevel)
base_oid=a4483aaece5bc74ec3f969fd067229487022401b
head_oid=02fbace7658b96489cf8be20dce6463c3d8c388d
git -C "$repo_dir" fetch https://github.com/loopx-project/loopx.git main
git -C "$repo_dir" fetch https://github.com/hhyykk/loopx.git codex/ts-replan-progress-20261016
scratch_dir=$(mktemp -d "${TMPDIR:-/tmp}/loopx-replan-replay.XXXXXX")
base_tree="$scratch_dir/base"
head_tree="$scratch_dir/head"
evidence_dir="$scratch_dir/evidence"
mkdir -p "$evidence_dir"
git -C "$repo_dir" worktree add --detach "$base_tree" "$base_oid"
git -C "$repo_dir" worktree add --detach "$head_tree" "$head_oid"
test "$(node --version)" = v22.22.3
uv sync --project "$head_tree" --python 3.13.12 --extra test
python_bin="$head_tree/.venv/bin/python"

Save the two exact script blocks below as $evidence_dir/cli_receiver.py and $evidence_dir/qualify_cli.py. Both source variants use the same head test interpreter. PYTHONPATH selects the base or head package. The receiver verifies the imported package path.

"$python_bin" - "$base_tree" "$head_tree" "$evidence_dir/source-variants.json" <<'PY_DESCRIPTOR'
import json
from pathlib import Path
import sys
base_tree, head_tree, destination = map(Path, sys.argv[1:])
variants = {
    label: {"python": sys.executable, "pythonpath": str(tree), "expected": str(tree / "loopx")}
    for label, tree in (("base", base_tree), ("head", head_tree))
}
destination.write_text(json.dumps(variants, indent=2))
PY_DESCRIPTOR
for stage in parity negative happy; do
    mkdir -p "$evidence_dir/$stage"
    cp "$evidence_dir/cli_receiver.py" "$evidence_dir/$stage/cli_receiver.py"
done

2. Run full parity, then the two performance scopes

# Six scenarios, each on real File and SQLite authority, without timed samples.
cd "$head_tree"
"$python_bin" "$evidence_dir/qualify_cli.py" \
  "$head_tree" "$evidence_dir/parity" "$evidence_dir/source-variants.json" 0

# 64 paired samples per provider/scenario; both refusal paths are warmed first.
"$python_bin" "$evidence_dir/qualify_cli.py" \
  "$head_tree" "$evidence_dir/negative" "$evidence_dir/source-variants.json" 64

# 32 paired samples per provider; each restores the same owned synthetic seed.
"$python_bin" "$evidence_dir/qualify_cli.py" \
  "$head_tree" "$evidence_dir/happy" "$evidence_dir/source-variants.json" 32 advanced

0 checks all six scenarios: accepted new probe, evidence-only refusal, missing-evidence refusal, known-blocker refusal, inconsistent terminal refusal, and accepted terminal stop. The successful ACK must contain only the expected typed progress outcome; a fresh Vision path or successor cannot substitute. Replaying an accepted write must preserve its post-write files and authority snapshot.

The negative run times repeated refusals after warming both managed daemons. The positive run resets only its owned synthetic workspace, reads the actual authority to prime the provider outside the timer, then times the first successful CLI write. These are distinct workloads. Variant order alternates by iteration. Raw paired samples and complete observations remain under evidence_dir; the harness stops its own isolated managed runtimes after each successful stage.

cli_ms includes receiver process startup, instrumentation and the real console command. qualify_ms covers only the actual runtime request boundary. The old Python delta ran before that boundary; the new TypeScript delta runs inside it. Use full CLI time for the overall comparison. Neither metric is a claim about an uninstrumented cold console startup or a real-model Goal.

An assertion, non-JSON output, wrong package, changed scope, timeout, or unexpected exit is a qualification failure. Keep the evidence and diagnose it before continuing. A mutation is detected only when the expected product output/state assertion fails; a setup or scope failure does not prove sensitivity. The receiver metadata distinguishes those failures. Do not reuse fixture contents for production work.

Exact cli_receiver.py
"""Disposable real CLI receiver; deterministic observation clocks, no domain mocks."""
from collections import Counter
from datetime import datetime, timezone
import json
from pathlib import Path
import sys
import time

request_path, expected_prefix, metadata_path = map(Path, sys.argv[1:4])
request = json.loads(request_path.read_text())
import loopx
assert Path(loopx.__file__).resolve().is_relative_to(expected_prefix.resolve()), loopx.__file__
# Freeze only the shared clock codec, before consumers bind its functions.
from loopx.control_plane.runtime import time as clock
clock.now_utc = lambda: datetime(2026, 10, 16, 12, tzinfo=timezone.utc)
clock.now_local_iso = lambda: '2026-10-16T12:00:00+00:00'
from loopx import rollout_event_log
rollout_event_log._now_iso = lambda: '2026-10-16T12:00:00Z'
from loopx.control_plane import effect_runtime as runtime
counts = Counter()
qualify_ms = []
qualify_scope = []
actual = runtime.effect_runtime_request

def observed(method, params, **kwargs):
    operation = params.get('operation', '')
    counts[method + ':' + str(operation)] += 1
    if method == 'work_item.replan_semantics.project' and operation == 'qualify':
        qualify_scope.append(runtime._REQUEST_RUNTIME_REVISION.get() is not None)
    started = time.perf_counter()
    result = actual(method, params, **kwargs)
    if method == 'work_item.replan_semantics.project' and operation == 'qualify':
        qualify_ms.append((time.perf_counter() - started) * 1000)
    return result

runtime.effect_runtime_request = observed
started = time.perf_counter()
code = 0
try:
    if request.get('control') == 'stop':
        print(json.dumps(runtime.restart_effect_runtime(wait_for_exit=True)))
    elif request.get('control') == 'authority':
        from loopx.control_plane.coordination.canonical_snapshot import read_canonical_snapshot
        print(json.dumps(read_canonical_snapshot(rpc=runtime.effect_runtime_result,
            runtime_root=request['runtime'], goal_id=request['goal'], include_leases=True,
            projection_readback=None, timeout=20)))
    else:
        from loopx.entrypoint import main
        sys.argv = ['loopx', *request['args']]
        code = main()
finally:
    metadata_path.write_text(json.dumps({'module': loopx.__file__, 'code': code,
        'elapsed_ms': (time.perf_counter()-started)*1000,
        'counts': counts, 'qualify_ms': qualify_ms, 'qualify_scope':qualify_scope, 'entrypoint':'loopx.entrypoint.main'}))
raise SystemExit(code)
Exact qualify_cli.py
"""Bounded synthetic CLI source/distribution parity; all raw evidence stays local."""
import hashlib
import importlib.util
import json
import os
from pathlib import Path
import shutil
import statistics
import subprocess
import sys
import time

source, output, variants_file = map(Path, sys.argv[1:4])
samples = int(sys.argv[4])
variants = json.loads(variants_file.read_text())
sys.path.insert(0, str(source))
sys.path.insert(0, str(source/'tests/control_plane'))
spec = importlib.util.spec_from_file_location('replan_cli_fixture', source/'tests/control_plane/test_replan_progress_native_cli.py')
fixture_api = importlib.util.module_from_spec(spec)
spec.loader.exec_module(fixture_api)

def digest(value):
    return hashlib.sha256(json.dumps(value, sort_keys=True).encode()).hexdigest()

def call(label, request, cwd):
    variant = variants[label]
    runtime = output/'managed'/label
    runtime.mkdir(parents=True, exist_ok=True)
    args_file = output/'request.json'
    meta_file = output/'receiver-meta.json'
    args_file.write_text(json.dumps(request))
    env = {**os.environ, 'LOOPX_USAGE_PING':'0', 'PYTHONHASHSEED':'0', 'NODE_OPTIONS':'--experimental-sqlite',
           'PYTHONPATH':variant.get('pythonpath',''), 'TMPDIR':str(runtime), 'TEMP':str(runtime), 'TMP':str(runtime)}
    started = time.perf_counter()
    result = subprocess.run([variant['python'], str(output/'cli_receiver.py'),str(args_file),variant['expected'],str(meta_file)],
        cwd=cwd, env=env, text=True, capture_output=True, timeout=90)
    elapsed = (time.perf_counter()-started)*1000
    metadata = json.loads(meta_file.read_text())
    assert metadata['entrypoint']=='loopx.entrypoint.main'
    if metadata['qualify_ms']:
        assert metadata['qualify_scope']==[False],(label,'refresh-state fallback scope changed')
    assert result.returncode in (0,1), (label,result.returncode,result.stderr)
    packet = json.loads(result.stdout)
    return {'code':result.returncode,'packet':packet,'meta':metadata,'wall_ms':elapsed}

def stop(label):
    result=call(label, {'control':'stop'},output)
    assert result['code']==0

def report(values):
    return {'p50_ms':round(statistics.median(values),3),
            'p95_ms':round(sorted(values)[min(len(values)-1,int(len(values)*.95))],3)}

def files(fixture):
    result={key:fixture[key].read_text() for key in ('registry','state','index')}
    result['artifacts']={str(path.relative_to(fixture['index'].parent)):path.read_text()
        for path in sorted(fixture['index'].parent.iterdir()) if path.suffix in ('.json','.md')}
    result['journals']={str(path.relative_to(fixture['runtime'])):path.read_text()
        for path in sorted(fixture['runtime'].rglob('*.jsonl'))}
    return result

scenarios=('evidence_only','known_blocker') if samples else ('advanced','evidence_only','advanced_no_evidence','known_blocker','terminal_inconsistent','terminal_stop')
if len(sys.argv)>5:
    scenarios=tuple(sys.argv[5].split(','))
    assert set(scenarios)<=set(('advanced','evidence_only','advanced_no_evidence','known_blocker','terminal_inconsistent','terminal_stop'))
records=[]
for provider in ('file','sqlite'):
 for scenario in scenarios:
    name=provider+'-'+scenario
    workspace=output/'cases'/name
    seed=output/'seeds'/name
    workspace.parent.mkdir(parents=True,exist_ok=True)
    seed.parent.mkdir(parents=True,exist_ok=True)
    if workspace.exists(): shutil.rmtree(workspace)
    workspace.mkdir()
    fixture=fixture_api.make_progress_cli_fixture(workspace,provider,scenario)
    primary='head' if 'head' in variants else next(iter(variants))
    common=['--registry',str(fixture['registry']),'--runtime-root',str(fixture['runtime']),'--format','json']
    guard=['quota','should-run','--codex-app','--goal-id',fixture_api.GOAL,'--agent-id',fixture_api.AGENT,
           '--turn-instance-id',fixture_api.TURN,'--scan-path',str(fixture['project'])]
    assert call(primary,{'args':common+guard},fixture['project'])['packet']['decision']=='autonomous_replan_required'
    bound=call(primary,{'args':common+guard+['--todo-id',fixture_api.TODO]},fixture['project'])['packet']
    obligation=bound['autonomous_replan_obligation']
    before=call(primary,{'control':'authority','runtime':str(fixture['runtime']),'goal':fixture_api.GOAL},output)['packet']
    before_files=files(fixture)
    fixture_hash=digest({'authority':before,'files':before_files,'obligation':obligation})
    stop(primary)
    if seed.exists(): shutil.rmtree(seed)
    shutil.copytree(workspace,seed)
    observations={}
    timings={label:[] for label in variants}
    native={label:[] for label in variants}
    for label in variants:
        stop(label)
        shutil.rmtree(workspace);shutil.copytree(seed,workspace)
        result=call(label,{'args':common+fixture['refresh']},fixture['project'])
        assert result['meta']['counts'].get('work_item.replan_semantics.project:qualify')==1,(name,label,result)
        after=call(label,{'control':'authority','runtime':str(fixture['runtime']),'goal':fixture_api.GOAL},output)['packet']
        assert after==before,(name,label,'provider changed')
        after_files=files(fixture)
        if scenario in ('advanced','terminal_stop'):
            assert result['code']==0 and result['packet']['appended'] is True
            expected=['new_probe_family'] if scenario=='advanced' else ['coverage_backed_no_followup']
            delta=result['packet']['autonomous_replan_ack']['semantic_delta']
            assert delta['outcomes']==delta['satisfying_outcomes']==expected
            assert delta['obligation_id']==obligation['obligation_id']
            replay=call(label,{'args':common+fixture['refresh']},fixture['project'])
            assert replay['code']==0 and replay['packet']['idempotent_replay'] is True
            replay_qualify_calls=replay['meta']['counts'].get('work_item.replan_semantics.project:qualify',0)
            replay_files=files(fixture)
            replay_authority=call(label,{'control':'authority','runtime':str(fixture['runtime']),'goal':fixture_api.GOAL},output)['packet']
            assert replay_files==after_files,(name,label,'replay duplicated a persisted effect')
            assert replay_authority==after,(name,label,'replay changed provider authority')
            observations[label]={'code':result['code'],'packet':result['packet'],'files':after_files,
                                 'authority':after,'replay':replay['packet'],
                                 'post_replay_files':replay_files,'post_replay_authority':replay_authority,
                                 'qualify_calls':1,'qualify_scope':result['meta']['qualify_scope'],
                                 'replay_qualify_calls':replay_qualify_calls,
                                 'replay_qualify_scope':replay['meta']['qualify_scope']}
        else:
            assert result['code']==1 and result['packet']['appended'] is False,(name,label,'expected typed-progress refusal',result['code'])
            assert {k:v for k,v in after_files.items() if k!='journals'}=={k:v for k,v in before_files.items() if k!='journals'},(name,label,'rejected write changed source')
            observations[label]={'code':1,'packet':result['packet'],'files':after_files,'authority':after,'qualify_calls':1,'qualify_scope':result['meta']['qualify_scope']}
        (output/f'{name}-{label}-observation.json').write_text(json.dumps(observations[label],indent=2))
        stop(label)
    expected=next(iter(observations.values()))
    assert all(value==expected for value in observations.values()),name
    if samples:
        if expected['code']==0:
            # Restore only this owned synthetic seed; prime the real provider outside the timed CLI.
            for iteration in range(samples):
                order=list(variants) if iteration%2==0 else list(reversed(variants))
                for label in order:
                    stop(label)
                    shutil.rmtree(workspace);shutil.copytree(seed,workspace)
                    prime=call(label,{'control':'authority','runtime':str(fixture['runtime']),'goal':fixture_api.GOAL},output)
                    assert prime['packet']==before
                    result=call(label,{'args':common+fixture['refresh']},fixture['project'])
                    assert result['code']==0 and result['packet']==expected['packet'],(name,label)
                    assert result['meta']['counts'].get('work_item.replan_semantics.project:qualify')==1
                    assert files(fixture)==expected['files'],(name,label,'happy-path effects changed')
                    timings[label].append(result['wall_ms']);native[label].extend(result['meta']['qualify_ms'])
                    stop(label)
        else:
            # The existing paused audit is deduplicated; prime both daemons before timing.
            for label in variants:
                warmup=call(label,{'args':common+fixture['refresh']},fixture['project'])
                assert warmup['code']==1 and warmup['packet']==expected['packet'],(name,label,'warmup')
            for iteration in range(samples):
                order=list(variants) if iteration%2==0 else list(reversed(variants))
                for label in order:
                    result=call(label,{'args':common+fixture['refresh']},fixture['project'])
                    assert result['code']==1 and result['packet']==expected['packet'],(name,label)
                    assert result['meta']['counts'].get('work_item.replan_semantics.project:qualify')==1
                    timings[label].append(result['wall_ms']);native[label].extend(result['meta']['qualify_ms'])
            assert files(fixture)==expected['files']
            for label in variants:stop(label)
    records.append({'provider':provider,'scenario':scenario,'fixture_sha256':fixture_hash,
        'observation_sha256':digest(expected),'full_observation_parity':True,'normalization':[],'pythonhashseed':'0',
        'clock':'shared Python observation and rollout-event clock codecs fixed before imports; all event IDs/receipt bindings retained',
        'entrypoint':'loopx.entrypoint.main','qualify_scope':expected['qualify_scope'],'samples':samples,'raw_cli_ms':timings,'raw_qualify_ms':native,'cli_ms':{k:report(v) for k,v in timings.items()} if samples else {},
        'qualify_ms':{k:report(v) for k,v in native.items()} if samples else {}})
    (output/'cli-receipts.json').write_text(json.dumps(records,indent=2))
    print(json.dumps({k:v for k,v in records[-1].items() if not k.startswith('raw_')}),flush=True)

@mergify

mergify Bot commented Oct 16, 2026

Copy link
Copy Markdown

This pull request has merge conflicts with main and cannot be merged
until they are resolved. Please rebase or merge the base branch, @hhyykk.

Choose the remote for the base repository, not an out-of-date fork.
For a fork clone, first inspect git remote -v; upstream must point
to https://github.com/loopx-project/loopx.git. If it is absent, add it
with git remote add upstream https://github.com/loopx-project/loopx.git.
Then run:

git fetch upstream
git rebase upstream/main
# Resolve each conflict, git add the resolved files, then git rebase --continue.
git push --force-with-lease origin HEAD

For a same-repository clone whose origin points to
https://github.com/loopx-project/loopx.git, use origin instead of
upstream for fetch/rebase. If you prefer merging the base, use
git merge <base-remote>/main and push normally.

Keep the DCO Signed-off-by trailer on every commit when you rebase.
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Oct 16, 2026
Signed-off-by: aihop <4408344+hhyykk@users.noreply.github.com>
Signed-off-by: aihop <4408344+hhyykk@users.noreply.github.com>
Signed-off-by: aihop <4408344+hhyykk@users.noreply.github.com>
@hhyykk
hhyykk force-pushed the codex/ts-replan-progress-20261016 branch from 02fbace to ed1bd14 Compare October 16, 2026 07:04
@hhyykk

hhyykk commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Main synchronization and current-head validation

  • Synced main: b543d076995423544b0eeb1990d59d7480f48339.
  • New PR head: ed1bd14336e4c34038cfafdf0bc6b71a11d67b61.
  • Previous head/base: 02fbace7658b96489cf8be20dce6463c3d8c388d / a4483aaece5bc74ec3f969fd067229487022401b.
  • At the synchronization check, main is an ancestor and HEAD...main is 3 / 0. The final diff has 15 candidate files and three DCO commits. Main merged fix(replan): carry complete lifecycle facts through private snapshots #6615 while validation ran; one Python conflict was resolved to reuse its shared replan transport. Our duplicate size check and two allowlist edits are removed. Native novelty rules and normalization/error precedence are unchanged. No new product rule was added.

Current-main changes were inventoried separately: quota capture/checkpoint diagnostics, approved delivery-check presentation, #6615 complete replan snapshot transport, and unrelated benchmark/research/UI work. None duplicates progress novelty or changes its shared codec/qualifier owner. The refreshed frontend and packages include those upstream changes. The dedicated temporary base worktree is removed after qualification; the PR branch and other open PR worktrees remain.

New-head results

Check Result
Related Python integration plus current-main quota capture, complete replan transport and lifecycle recovery 151 passed, including 12 real module CLI File/SQLite cases and the 12,000-row history regression
Native rule/history/snapshot/current-main checkpoint tests 78 passed
Full control-plane typecheck, changed Python Ruff, diff check passed
Semantic vocabulary advisory and full smoke Final head passed in 89.8 s under the unchanged default 120 s budget. An intermediate-head run timed out at 120 s, then passed an isolated retry in 65.055 s; those intermediate observations remain versioned separately.
Fresh normal Chat build, wheel and sdist passed; each artifact installed into a fresh environment
Source/archive/installed bytes 17 / 17 product files changed by this PR or upstream main are equal in source, wheel, sdist and both fresh installations
Complete current-main/source/wheel/sdist CLI 12/12 backend/scenario rows × 4 variants match, including complete replay readback
New matched performance, soak, real-model journeys not_run; prior performance holds remain

The matrix compares all six scenarios on File/SQLite: novel probe accepted, evidence-only refused, new probe without proof refused, historical blocker refused, inconsistent terminal refused, matching terminal stop accepted. The original Todo remains open; canonical authority/revision/Todos/leases stay unchanged. Accepted replay is checked against all post-write files and journals plus the actual canonical snapshot. Fresh qualification/replay use 1 / 0 qualifier requests. The real public entrypoint is loopx.entrypoint.main; the refresh fallback records qualifier scope [False] on every variant. No output field is normalized away. Fixed clock codecs/hash seed are the same controls as the previous qualification.

Current-main/source/installed parity hashes

All four variants match the complete captured JSON value and durable state. No output normalization. Qualifier scope is [False]; accepted first-call/replay counts are 1/0.

Provider Scenario Fixture SHA-256 Complete observation SHA-256
file advanced 0de055d64bade94a43967b28890c410ac3b2252bf0078653f933082ecb88e1f6 a52ea495f35515be79a4e64469c6f0dbbd585d22cf7e211767206210ef436c51
file evidence_only 3185fe107444436e040a8d57139476d20726697bee35c98bef7209c50365fafa beb4c74224c83dc8862f71dad48ce85b1cc88e10f32d3c9e3068d1daf0eb141e
file advanced_no_evidence f60000dc33ff875f9270c9c0a62fb5cb54faf07ab11ac8978da39253c7ecbaa2 fd9be3ecd2de5320e95f9cf03f67b6ec75fcbeeecf179cb0eaedffa8bf855b21
file known_blocker 8900fb0bf21acfdb6da063bc8502a92b022b29e27aadcbc7033d0bce48fc36f4 d018f565205a0553f8cf458ffd3429fd8bf8cd39e2c67a19d0a0ea3ab406eb7b
file terminal_inconsistent 01a9ff92ca386a5fe15a6d0cc6483fda582a88bcb876aae4cb9985356d2dd961 81b3962f9e4bac40ac7d4a3e3ff1f4524dd266fbb268591a144e03502e18cf51
file terminal_stop 62299ed4b7569a2ae4b21f7a85f41502ffb54a5f7163f6d5abec1bd398988baf 6a127f5ccc1cda329d597b00b69a7cd5e4fedb9a7337cd685458c7feeeaae332
sqlite advanced 3ca9773e1db9711f05ed4a37cff165b1dcfa89efeb52b30843de6a8a049c9606 f87d4f904c6c31e90862d7d1b619993fd72c0c49ea2cc75c3678f2b086c7abd8
sqlite evidence_only 0b7a830697f8b81fa21c94c0e905501cf26a4b4b552cd167acbf85f858deb3e8 097ec621aca910c0f6ca769ccad13cd0b0b58142c011541a5fee2e7e12a09f19
sqlite advanced_no_evidence 6db60659661b94ac9ed1480d4a459d3caf61bd096ad1118e502f5d7f760b64a2 6a087154afcb1b101a4dac3271494b35385efb3778fc8b7f64777b3f480ca241
sqlite known_blocker 1bfa4dec1685342be0443fba03338186172e25db8ca72cdc42ff753b32eb68a8 873d64ddeb2ab7fe275b909cbaf0d9e84b19e744d9ad77b40e5137e6c2184948
sqlite terminal_inconsistent 71c1ed418eba12ce44a0658c53a7a593f67ea499ce5117c22b503e5408ece247 7700d7af2b8c66d9d4b97abb0b6a21c010c47d2a8eeb564dca79810f4caa8676
sqlite terminal_stop a218d3e975e792257a4f9fc7773648a75cd1d0773272837188ace8add7f1d16c d69ade37e32c729faaee0b2fbdf27ee26b3547ac631bae5dce069437b3d89e5b

Migration economics against synchronized main

Field Receipt
Canonical owner Before: Python progress novelty/terminal coverage plus the native outcome owner. After: native progress_delta.ts feeds existing replan_semantics.ts in-process. The wire entrypoint rejects precomputed observation_delta.
Legacy code deleted Both Python decision functions removed: 107 exact function-definition lines (16 + 91, including signatures/docstrings). Python gross diff deletion is 117. Earlier historical text counted one separator as a definition line; 107 is the corrected span, not a new code change. Shared codecs remain live.
Bridge added 18 classified lines: 8 Python normalized-fact adapter lines, 9 native entrypoint/import lines, 1 dispatcher replacement. Main's shared project_replan_semantics owns transport. The former manual size check and both allowlist additions are removed from this PR. No new effect, daemon, leaf RPC, fallback or dual-run.
Cross-runtime calls Selected delta+outcome qualifier remains 1→1; first CLI qualification/replay uses 1/0 qualifier calls. The nonempty-context/checkpoint facade remains 3→3 by its unchanged orchestration; historical instrumented profile measured that count. Current console parity instruments actual qualifier calls.
Product net change 5 files, +140/−122 = +18. Validation/config: 7 files, +452/−221 = +231. Docs: 3 files, +32/−12 = +20. No dependency or generated-file change. Strict native decoding remains in the product count; no net deletion claim.
Scaffolding Python pure-policy assertions move to native tests; integration/codec tests stay. Temporary parity/mutation tools are not committed. Durable CLI/regression tests express public or persisted behavior.
Facade exit Retire shared observation/fingerprint/history/Vision codecs and source/context/checkpoint adaptation with the remaining refresh writers, replan context/history readers, external-progress-review and Explore-evidence consumers. Keep one normalization/fingerprint owner until that cutover.
Correctness/performance New-base real File/SQLite source and installed-artifact parity, large history, malformed input and replay are versioned separately below. The original mutation and matched performance remain historical. New matched performance is unqualified; both old File p95 holds remain.

Historical limits remain open

The previous full validation and replay scripts are for old 02fbace / a448. They are retained as historical evidence, not relabeled as new-head runs. The two File p95 differences were +33.757 ms for known-blocker refusal and +54.407 ms for first successful writeback. Both exceed the unchanged unexplained additive 25 ms target. Current-head matched performance was not repeated; it remains unqualified and this rebase does not waive the holds.

The old oversized DSH decision-function failure also remains a review hold. The relevant source bytes are unchanged. No ratchet exception or unrelated repair was added.

Old-head CI completed after the original submission. TS/static, real PostgreSQL, Windows and DCO checks passed. Python Tests had browser and Stage2C failures. Release Artifacts failed its browser probe. Stage2C collection fails because test_chat_goal_storage.py imports the removed capture_present; the relevant files are unchanged on pinned main. Browser counts and HTTP400 assertions have unproven runtime attribution. Aggregate checks/pytest/merge-gate failures are not evidence that the whole pytest suite ran. Synchronized-head CI is a separate run; no claim that the old failures are fixed.

No local whole-repository suite, Windows/macOS, PostgreSQL or real-model journey was run during this sync. This update requests review; it grants no merge, deployment or provider promotion authority.

Reproduce the synchronized source comparison

Use Linux, Python 3.13.12, uv, and official Node.js 22.22.3 on PATH. Take the exact unchanged cli_receiver.py and qualify_cli.py blocks from the historical comment. Use the new pins and setup below, not that comment's old worktree pins. All fixture data and output paths are disposable and synthetic.

set -euo pipefail
export LOOPX_USAGE_PING=0
repo_dir=$(git rev-parse --show-toplevel)
base_oid=b543d076995423544b0eeb1990d59d7480f48339
head_oid=ed1bd14336e4c34038cfafdf0bc6b71a11d67b61
git -C "$repo_dir" fetch https://github.com/loopx-project/loopx.git main
git -C "$repo_dir" fetch https://github.com/hhyykk/loopx.git codex/ts-replan-progress-20261016
scratch_dir=$(mktemp -d "${TMPDIR:-/tmp}/loopx-sync-replay.XXXXXX")
base_tree="$scratch_dir/base"
head_tree="$scratch_dir/head"
evidence_dir="$scratch_dir/evidence"
mkdir -p "$evidence_dir"
git -C "$repo_dir" worktree add --detach "$base_tree" "$base_oid"
git -C "$repo_dir" worktree add --detach "$head_tree" "$head_oid"
test "$(node --version)" = v22.22.3
uv sync --project "$head_tree" --python 3.13.12 --extra test
python_bin="$head_tree/.venv/bin/python"
# Save the two unchanged scripts under evidence_dir before the next commands.
"$python_bin" - "$base_tree" "$head_tree" "$evidence_dir/variants.json" <<'PY_DESCRIPTOR'
import json
from pathlib import Path
import sys
base_tree, head_tree, destination = map(Path, sys.argv[1:])
destination.write_text(json.dumps({
    label: {"python": sys.executable, "pythonpath": str(tree), "expected": str(tree / "loopx")}
    for label, tree in (("base", base_tree), ("head", head_tree))
}, indent=2))
PY_DESCRIPTOR
cd "$head_tree"
npm ci --ignore-scripts
"$python_bin" "$evidence_dir/qualify_cli.py" \
  "$head_tree" "$evidence_dir" "$evidence_dir/variants.json" 0
uv run --extra test python -m pytest -q \
  tests/control_plane/test_progress_observation.py \
  tests/control_plane/test_external_progress_review.py \
  tests/control_plane/test_replan_writeback_projection.py \
  tests/control_plane/test_replan_context_evidence.py \
  tests/control_plane/test_replan_progress_native_cli.py \
  tests/control_plane/test_quota_decision_capture.py \
  tests/control_plane/test_replan_semantics_transport.py \
  tests/control_plane/test_lifecycle_guard_reentry.py
node --no-warnings --experimental-sqlite --experimental-strip-types --test \
  tests/control_plane_ts/progress_delta.test.ts \
  tests/control_plane_ts/replan_semantics.test.ts \
  tests/control_plane_ts/replan_history.test.ts \
  tests/control_plane_ts/effect_runtime_snapshot.test.ts \
  tests/control_plane_ts/checkpoint_artifacts.test.ts
npm run typecheck:control-plane
uv run --extra test loopx canary smoke-suite --script semantic-vocabulary-drift-smoke.py

@mergify mergify Bot removed the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Oct 16, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant