Publish verified navigation Windows prerelease checkpoint

This commit is contained in:
2026-09-12 03:58:54 -07:00
parent f5e1c734da
commit be7a8cd8d7
43 changed files with 2575 additions and 28 deletions
+26 -25
View File
@@ -1,6 +1,6 @@
# Integrated checkpoint — first release
Updated 2026-09-11 by Codex-9e8r6t `/root`, Windows host.
Updated 2026-09-12 by Codex-9e8r6t `/root`, Windows host.
**Full OA/SA release acceptance is incomplete. Linux work remains user-paused.**
[PROJECT_GOAL.md](../PROJECT_GOAL.md) owns the application requirements.
@@ -10,41 +10,42 @@ Instruction synchronization `b70bf1d` preserves the user specification and
## Delivered Windows milestone
[Contextual authoring prerelease](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/tag/v0.2.0-preview.contextual.20260911)
was published and read back at 17:03:29 UTC. Extract the whole ZIP and run
[Source navigation prerelease](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/tag/v0.2.0-preview.navigation.20260911)
was published and read back on September 12 at 10:54:02 UTC. Extract the whole ZIP and run
`arcadia-studio.exe`; keep its sibling `libunwind.dll`. Studio, the optional REST
server, examples, offline help and dependency notices are included.
The tag points to verified source checkpoint **b2c3e540**. Exact raw-input
reconstruction **d5650309** is distinct from the original build commit. The
package pairs GUI5657 with the unchanged, separately verified EFEE server.
The tag points to exact raw-input reconstruction **802855f7**, based on corrected
source **33c6d83** and distinct from the original build capture. The
package pairs GUI B183 with the unchanged, separately verified EFEE server.
All 559 package files and all three downloaded release assets were verified.
The binaries use the development profile; this is a prerelease.
The GUI supports named behavior creation and contextual missing-source creation
without abandoning the parent draft. All 679 desktop tests passed, with focused
layout checks, strict desktop Clippy, formatting and a matching build. Real
Windows workflows verified minimum-size layout, recovery/cancellation, lifeline
and state-machine creation, one-step Undo/Redo and exact source/identity reopen.
Fresh package acceptance additionally verified Home/help, native Open and
contextual Create/Save/Close with complete model/source/identity comparison.
Independent packaged-server checks cover exact API content and persistence
across process restart. These are bounded milestone results.
The GUI adds Definition/References/Back for current Text drafts and corrects
repair/recovery saved-state handling. All 755 desktop tests passed (one ignored),
with strict Clippy, formatting and a matching build. Earlier navigation native
checks cover minimum-size interaction, ambiguous/partial scope and the 30-file
engineering workflow; the corrected binary separately passed repair/rollback,
Close/Cancel and exact Save checks. Fresh package acceptance verified Home/help,
native Open, navigation, edit/Undo, Apply, Save and complete saved-model/source
equality. Independent server checks verified exact API content and persistence
across restart. Each result retains its specific build and workflow scope.
Authoritative records:
- [Publication, artifacts and limitations](release-contextual-source-prerelease-published-20260911.md)
- [Per-binary preparation](release-contextual-source-prerelease-preparation-20260911.md)
and [independent archive/server review](release-contextual-source-prerelease-review-20260911.md)
- [Fresh native package acceptance](release-contextual-source-prerelease-gui-20260911.md)
and [broader GUI5657 native acceptance](release-contextual-source-native-v2-20260911.md)
- [Publication, artifacts and limitations](release-navigation-prerelease-published-20260912.md)
- [Per-binary preparation](release-navigation-prerelease-preparation-20260911.md)
and [independent archive/server review](release-navigation-prerelease-review-20260911.md)
- [Fresh native package acceptance](release-navigation-prerelease-native-20260911.md)
and [integrated navigation evidence](release-text-navigation-integrated-20260911.md)
- [Previous contextual authoring milestone](release-contextual-source-prerelease-published-20260911.md)
- [Verified code/evidence checkpoint](release-postboot-checkpoint-review-20260911.md)
- [Standalone CLI prerelease](release-cli-prerelease-published-20260911.md),
supplying checked source stabilization and typed alias rename separately
## Material unfinished scope
Current-draft Definition/References/Back is implemented in source checkpoint
Current-draft Definition/References/Back was implemented in source checkpoint
**[36db9356](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/commit/36db9356cce3c7614ae37eec9fe17678ca210afe)**.
The [initial native trial](release-text-navigation-native-initial-20260911.md)
found four interaction defects. Their [correction](release-text-navigation-native-corrections-20260911.md)
@@ -59,15 +60,15 @@ at **33c6d83** passes the full 755-test suite, strict Clippy and matching GUI B1
build. Its [native repair verification](release-text-repair-save-native-v4-20260911.md)
passed missing-include and duplicate-alias repairs plus interrupted-save rollback:
Apply/Recover retain unsaved status, Close warns, Cancel retains work, and explicit
Save yields exact complete model/identity/source equality. Package acceptance
remains separate and required.
Save yields exact complete model/identity/source equality. The fresh package
passed its separate native and independent server checks and is now delivered above.
The [integrated evaluation](release-text-navigation-integrated-20260911.md) links
exact input archives, earlier full-test scope and independent findings.
The published contextual preview remains unchanged.
The integrated release does not yet contain newer peer canvas/chooser and
The integrated release does not yet contain Text alias rename, newer peer canvas/chooser and
scenario-lifetime work, complete constraints/calculations, dimensional quantities,
maintained model libraries, or the new source-navigation contribution.
maintained model libraries.
Those additions require coherent graphical/text/REST realization and validation.
Some scenario forms retain old scroll positions and dense labels remain crowded.
Local SA action/state/reuse/fragment and supplementary camera/focus tasks retain
@@ -0,0 +1,199 @@
{
"files": [
{
"path": ".gitattributes",
"bytes": 9,
"sha256": "8b9c3028d6467ff3be7c793141927841d70f47f52d0590677438f488ca154992"
},
{
"path": "ORIGINALS.json",
"bytes": 9733,
"sha256": "1c6eedd5a7c0937eda5961db48d1107fd4b005d47c026936d248b7aa1d86a300"
},
{
"path": "payload/publication/acceptance-records-push-result.json",
"bytes": 401,
"sha256": "e7dde009c2cdc1dba5e9b06fc386db8e3adeec8346eb029a70b3cee9236e0736"
},
{
"path": "payload/publication/adapter-manifest.json",
"bytes": 910,
"sha256": "3361bb96a496bf903360ea2dd656d3104c237d51b6b66c0de43594aaaa19db3a"
},
{
"path": "payload/publication/before-source-advance/publish.py",
"bytes": 13250,
"sha256": "a18a2d5e996d2d61975292be77f22a7a09725036a853a3bea86f8803b90a4ed5"
},
{
"path": "payload/publication/before-source-advance/push-tag.py",
"bytes": 3471,
"sha256": "e73e351fd6322e51e8cadc016cdf9a0650022cd0a9aba816019744abcafdf6de"
},
{
"path": "payload/publication/bindings.json",
"bytes": 199,
"sha256": "2a62d2da16aff59ecaa69942a00600c0f38e25392f1f2e38890f3cd089f7ffd8"
},
{
"path": "payload/publication/inspect-source.py",
"bytes": 1236,
"sha256": "9fe346f28a8728b944ba20be054fa274e88c7c5924fe19827992181ac0a80f57"
},
{
"path": "payload/publication/publish.py",
"bytes": 13475,
"sha256": "2e2f5286b958479e27d113cf65036ca1bf3af4c2380a0985d82bfc2d793cabdd"
},
{
"path": "payload/publication/push-acceptance-records.py",
"bytes": 2927,
"sha256": "7410f81939c52e8ba5d2996e972dee30ccaa653f2568bd93c77867268f923283"
},
{
"path": "payload/publication/push-records.py",
"bytes": 2916,
"sha256": "79d642ab8623955eb21b22524abf70f29cca880f8b5de531989ab2a8197089da"
},
{
"path": "payload/publication/push-tag.py",
"bytes": 3503,
"sha256": "5911ecb7924596918e59ab983952e7094b122dc21008b7913b4d1dc017683a27"
},
{
"path": "payload/publication/README.md",
"bytes": 6355,
"sha256": "2548bafceb07d36f3b191cc40a7a003deb1c059ba53802a5f4d78b9e032ce420"
},
{
"path": "payload/publication/records-push-result.json",
"bytes": 401,
"sha256": "82dd46896da4cc58d7d97910d7b0bb22675c36213b8880f62ca9b7a90aa66377"
},
{
"path": "payload/publication/release-created.json",
"bytes": 171,
"sha256": "7af9592828169705117a60c21b50dc2f867a80b4c85c68842f5fc319928d88ae"
},
{
"path": "payload/publication/RELEASE-NOTES.draft.md",
"bytes": 2678,
"sha256": "fde884c107796f399943a37949041eb2edd306398e34d53c36fd466dc3f0ea0b"
},
{
"path": "payload/publication/RELEASE-NOTES.md",
"bytes": 2309,
"sha256": "9361105c8bb9f939f0ea931edb107ad21acd7acdcc2d9424f0f0b20d62f980bd"
},
{
"path": "payload/publication/runs/create-first-20260912/events.jsonl",
"bytes": 167,
"sha256": "e89af2674fa0fc4e7cdfaf6bfcd3047e171045f1845728ce78818492cff10473"
},
{
"path": "payload/publication/runs/create-first-20260912/result.json",
"bytes": 950,
"sha256": "fe9ffc9e99c74dfd683fe11ea977c6a7d3977c99609d3129102a30e42b7daf47"
},
{
"path": "payload/publication/runs/inspect-resume-20260912/result.json",
"bytes": 349,
"sha256": "7d7ef56624ebf00e660a39130a925d1d0a3c33091b28cac827740d3272e90aa1"
},
{
"path": "payload/publication/runs/publish-first-20260912/events.jsonl",
"bytes": 97,
"sha256": "a86022ef2d331ce2d807ea593d3f195d92a3405b78d8bfec2c661e205f687497"
},
{
"path": "payload/publication/runs/publish-first-20260912/result.json",
"bytes": 2321,
"sha256": "7e72416c6a9a31021e3cdfd9ac3177b8928cdcb9e33386885e3d7d90c132a44a"
},
{
"path": "payload/publication/runs/tag-first-20260912/result.json",
"bytes": 596,
"sha256": "32786e97599229d77c088d8ab70478b64f0567488bbb39f84f636cf6d89c1a87"
},
{
"path": "payload/publication/runs/tag-inspected-source-20260912/events.jsonl",
"bytes": 183,
"sha256": "1e430044803d1fd949e70bdd96f769c3cbc6073281adc36f3c387ecd8d70fd47"
},
{
"path": "payload/publication/runs/tag-inspected-source-20260912/result.json",
"bytes": 666,
"sha256": "fb35c50a4c9c5bfba241843abecd9c7e0ced5f8b79c7b2baa58433e33f66cc2c"
},
{
"path": "payload/publication/runs/upload-first-20260912/events.jsonl",
"bytes": 1416,
"sha256": "d18b4392b1a1db6e37cc8b461cb89c5c9c13ae24608844a5b325a6f93dbc57e0"
},
{
"path": "payload/publication/runs/upload-first-20260912/result.json",
"bytes": 2159,
"sha256": "b56b35b08ee82d3aa7c60d9cc30e2b9d931a62442d5c3ebe17e0ce737feaada8"
},
{
"path": "payload/publication/source-advance-inspection.json",
"bytes": 16352,
"sha256": "dc20d2eee4dedc310a3989fc377e99e915a5010c51995b1e968eecb3fac106c5"
},
{
"path": "payload/publication/VALIDATION.md",
"bytes": 6987,
"sha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2"
},
{
"path": "payload/publication/verify-index.py",
"bytes": 1510,
"sha256": "4427c4d7e1774e71e5794feba833135d2624084dc591584ccdce5473841bbac8"
},
{
"path": "payload/review/followup-bindings.json",
"bytes": 1422,
"sha256": "5244d69552f6d60f46e74007b4a4ef914853866e95ffa376a5d4fad59b5a6507"
},
{
"path": "payload/review/FOLLOWUP.md",
"bytes": 3628,
"sha256": "9a0f4d0a1c436d6386fdffd9114ec85327b539896257692f9a0bda95cee69bb3"
},
{
"path": "payload/review/review-bindings.json",
"bytes": 1016,
"sha256": "f42e0318058cf07150a51cae72fe4de5e3ee9d5dcced65a21e9c2e86fe54d81b"
},
{
"path": "payload/review/REVIEW.md",
"bytes": 4873,
"sha256": "771112967011ed2aad5e3c4c1c42307bfacb645076bad6f3840505c5ea7a0d48"
},
{
"path": "payload/review/source-advance-bindings.json",
"bytes": 1757,
"sha256": "ff7124a6c55d6567ab3a746d8cda91b780be81142bf664b2426f023909d942c9"
},
{
"path": "payload/review/SOURCE-ADVANCE.md",
"bytes": 2460,
"sha256": "7e129c5da19056f1e853be019e71dcd1ca51a30c8c26653cc77109f97b3efc5e"
},
{
"path": "README.md",
"bytes": 2387,
"sha256": "a4624d19041894ebc7c392bf5722f2af16f6fcb333c68d32ecb7189e123f0653"
},
{
"path": "reconstructed/original-reviewed-publish.py",
"bytes": 13133,
"sha256": "e679a84845303db6582753b525bb3c2d184e6139e5651560fce8c876eae42c99"
},
{
"path": "verify.py",
"bytes": 3818,
"sha256": "4ba2e95baef75e01e6f4d35a48fa3c7429d6b3cea6b1192e41801dda557a8635"
}
]
}
@@ -0,0 +1,209 @@
{
"scope": "Byte-exact readback of original publication and independent review files; reconstructed file is separately labeled and not an original retained execution snapshot.",
"files": [
{
"path": "payload/publication/acceptance-records-push-result.json",
"source": ".local/navigation-prerelease-publication-20260911/acceptance-records-push-result.json",
"bytes": 401,
"sha256": "e7dde009c2cdc1dba5e9b06fc386db8e3adeec8346eb029a70b3cee9236e0736"
},
{
"path": "payload/publication/adapter-manifest.json",
"source": ".local/navigation-prerelease-publication-20260911/adapter-manifest.json",
"bytes": 910,
"sha256": "3361bb96a496bf903360ea2dd656d3104c237d51b6b66c0de43594aaaa19db3a"
},
{
"path": "payload/publication/before-source-advance/publish.py",
"source": ".local/navigation-prerelease-publication-20260911/before-source-advance/publish.py",
"bytes": 13250,
"sha256": "a18a2d5e996d2d61975292be77f22a7a09725036a853a3bea86f8803b90a4ed5"
},
{
"path": "payload/publication/before-source-advance/push-tag.py",
"source": ".local/navigation-prerelease-publication-20260911/before-source-advance/push-tag.py",
"bytes": 3471,
"sha256": "e73e351fd6322e51e8cadc016cdf9a0650022cd0a9aba816019744abcafdf6de"
},
{
"path": "payload/publication/bindings.json",
"source": ".local/navigation-prerelease-publication-20260911/bindings.json",
"bytes": 199,
"sha256": "2a62d2da16aff59ecaa69942a00600c0f38e25392f1f2e38890f3cd089f7ffd8"
},
{
"path": "payload/publication/inspect-source.py",
"source": ".local/navigation-prerelease-publication-20260911/inspect-source.py",
"bytes": 1236,
"sha256": "9fe346f28a8728b944ba20be054fa274e88c7c5924fe19827992181ac0a80f57"
},
{
"path": "payload/publication/publish.py",
"source": ".local/navigation-prerelease-publication-20260911/publish.py",
"bytes": 13475,
"sha256": "2e2f5286b958479e27d113cf65036ca1bf3af4c2380a0985d82bfc2d793cabdd"
},
{
"path": "payload/publication/push-acceptance-records.py",
"source": ".local/navigation-prerelease-publication-20260911/push-acceptance-records.py",
"bytes": 2927,
"sha256": "7410f81939c52e8ba5d2996e972dee30ccaa653f2568bd93c77867268f923283"
},
{
"path": "payload/publication/push-records.py",
"source": ".local/navigation-prerelease-publication-20260911/push-records.py",
"bytes": 2916,
"sha256": "79d642ab8623955eb21b22524abf70f29cca880f8b5de531989ab2a8197089da"
},
{
"path": "payload/publication/push-tag.py",
"source": ".local/navigation-prerelease-publication-20260911/push-tag.py",
"bytes": 3503,
"sha256": "5911ecb7924596918e59ab983952e7094b122dc21008b7913b4d1dc017683a27"
},
{
"path": "payload/publication/README.md",
"source": ".local/navigation-prerelease-publication-20260911/README.md",
"bytes": 6355,
"sha256": "2548bafceb07d36f3b191cc40a7a003deb1c059ba53802a5f4d78b9e032ce420"
},
{
"path": "payload/publication/records-push-result.json",
"source": ".local/navigation-prerelease-publication-20260911/records-push-result.json",
"bytes": 401,
"sha256": "82dd46896da4cc58d7d97910d7b0bb22675c36213b8880f62ca9b7a90aa66377"
},
{
"path": "payload/publication/release-created.json",
"source": ".local/navigation-prerelease-publication-20260911/release-created.json",
"bytes": 171,
"sha256": "7af9592828169705117a60c21b50dc2f867a80b4c85c68842f5fc319928d88ae"
},
{
"path": "payload/publication/RELEASE-NOTES.draft.md",
"source": ".local/navigation-prerelease-publication-20260911/RELEASE-NOTES.draft.md",
"bytes": 2678,
"sha256": "fde884c107796f399943a37949041eb2edd306398e34d53c36fd466dc3f0ea0b"
},
{
"path": "payload/publication/RELEASE-NOTES.md",
"source": ".local/navigation-prerelease-publication-20260911/RELEASE-NOTES.md",
"bytes": 2309,
"sha256": "9361105c8bb9f939f0ea931edb107ad21acd7acdcc2d9424f0f0b20d62f980bd"
},
{
"path": "payload/publication/runs/create-first-20260912/events.jsonl",
"source": ".local/navigation-prerelease-publication-20260911/runs/create-first-20260912/events.jsonl",
"bytes": 167,
"sha256": "e89af2674fa0fc4e7cdfaf6bfcd3047e171045f1845728ce78818492cff10473"
},
{
"path": "payload/publication/runs/create-first-20260912/result.json",
"source": ".local/navigation-prerelease-publication-20260911/runs/create-first-20260912/result.json",
"bytes": 950,
"sha256": "fe9ffc9e99c74dfd683fe11ea977c6a7d3977c99609d3129102a30e42b7daf47"
},
{
"path": "payload/publication/runs/inspect-resume-20260912/result.json",
"source": ".local/navigation-prerelease-publication-20260911/runs/inspect-resume-20260912/result.json",
"bytes": 349,
"sha256": "7d7ef56624ebf00e660a39130a925d1d0a3c33091b28cac827740d3272e90aa1"
},
{
"path": "payload/publication/runs/publish-first-20260912/events.jsonl",
"source": ".local/navigation-prerelease-publication-20260911/runs/publish-first-20260912/events.jsonl",
"bytes": 97,
"sha256": "a86022ef2d331ce2d807ea593d3f195d92a3405b78d8bfec2c661e205f687497"
},
{
"path": "payload/publication/runs/publish-first-20260912/result.json",
"source": ".local/navigation-prerelease-publication-20260911/runs/publish-first-20260912/result.json",
"bytes": 2321,
"sha256": "7e72416c6a9a31021e3cdfd9ac3177b8928cdcb9e33386885e3d7d90c132a44a"
},
{
"path": "payload/publication/runs/tag-first-20260912/result.json",
"source": ".local/navigation-prerelease-publication-20260911/runs/tag-first-20260912/result.json",
"bytes": 596,
"sha256": "32786e97599229d77c088d8ab70478b64f0567488bbb39f84f636cf6d89c1a87"
},
{
"path": "payload/publication/runs/tag-inspected-source-20260912/events.jsonl",
"source": ".local/navigation-prerelease-publication-20260911/runs/tag-inspected-source-20260912/events.jsonl",
"bytes": 183,
"sha256": "1e430044803d1fd949e70bdd96f769c3cbc6073281adc36f3c387ecd8d70fd47"
},
{
"path": "payload/publication/runs/tag-inspected-source-20260912/result.json",
"source": ".local/navigation-prerelease-publication-20260911/runs/tag-inspected-source-20260912/result.json",
"bytes": 666,
"sha256": "fb35c50a4c9c5bfba241843abecd9c7e0ced5f8b79c7b2baa58433e33f66cc2c"
},
{
"path": "payload/publication/runs/upload-first-20260912/events.jsonl",
"source": ".local/navigation-prerelease-publication-20260911/runs/upload-first-20260912/events.jsonl",
"bytes": 1416,
"sha256": "d18b4392b1a1db6e37cc8b461cb89c5c9c13ae24608844a5b325a6f93dbc57e0"
},
{
"path": "payload/publication/runs/upload-first-20260912/result.json",
"source": ".local/navigation-prerelease-publication-20260911/runs/upload-first-20260912/result.json",
"bytes": 2159,
"sha256": "b56b35b08ee82d3aa7c60d9cc30e2b9d931a62442d5c3ebe17e0ce737feaada8"
},
{
"path": "payload/publication/source-advance-inspection.json",
"source": ".local/navigation-prerelease-publication-20260911/source-advance-inspection.json",
"bytes": 16352,
"sha256": "dc20d2eee4dedc310a3989fc377e99e915a5010c51995b1e968eecb3fac106c5"
},
{
"path": "payload/publication/VALIDATION.md",
"source": ".local/navigation-prerelease-publication-20260911/VALIDATION.md",
"bytes": 6987,
"sha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2"
},
{
"path": "payload/publication/verify-index.py",
"source": ".local/navigation-prerelease-publication-20260911/verify-index.py",
"bytes": 1510,
"sha256": "4427c4d7e1774e71e5794feba833135d2624084dc591584ccdce5473841bbac8"
},
{
"path": "payload/review/followup-bindings.json",
"source": ".local/navigation-publication-review-20260912/followup-bindings.json",
"bytes": 1422,
"sha256": "5244d69552f6d60f46e74007b4a4ef914853866e95ffa376a5d4fad59b5a6507"
},
{
"path": "payload/review/FOLLOWUP.md",
"source": ".local/navigation-publication-review-20260912/FOLLOWUP.md",
"bytes": 3628,
"sha256": "9a0f4d0a1c436d6386fdffd9114ec85327b539896257692f9a0bda95cee69bb3"
},
{
"path": "payload/review/review-bindings.json",
"source": ".local/navigation-publication-review-20260912/review-bindings.json",
"bytes": 1016,
"sha256": "f42e0318058cf07150a51cae72fe4de5e3ee9d5dcced65a21e9c2e86fe54d81b"
},
{
"path": "payload/review/REVIEW.md",
"source": ".local/navigation-publication-review-20260912/REVIEW.md",
"bytes": 4873,
"sha256": "771112967011ed2aad5e3c4c1c42307bfacb645076bad6f3840505c5ea7a0d48"
},
{
"path": "payload/review/source-advance-bindings.json",
"source": ".local/navigation-publication-review-20260912/source-advance-bindings.json",
"bytes": 1757,
"sha256": "ff7124a6c55d6567ab3a746d8cda91b780be81142bf664b2426f023909d942c9"
},
{
"path": "payload/review/SOURCE-ADVANCE.md",
"source": ".local/navigation-publication-review-20260912/SOURCE-ADVANCE.md",
"bytes": 2460,
"sha256": "7e129c5da19056f1e853be019e71dcd1ca51a30c8c26653cc77109f97b3efc5e"
}
]
}
@@ -0,0 +1,9 @@
# Navigation publication evidence
[Publication report](../../release-navigation-prerelease-published-20260912.md) records the completed root-owned publication. This archive preserves 34 original files, 103,111 bytes, copied and read back exactly from `.local/navigation-prerelease-publication-20260911` and `.local/navigation-publication-review-20260912`. The whitelist retains scripts, notes/draft, validation, bindings, predecessor helpers, source advance inspection, three static review stages, push receipts and all attempt receipts/events. Executables, ZIP, caches and profiles are excluded.
`payload/publication/README.md` and `adapter-manifest.json` describe initial unexecuted/unbound preparation. Their historical status and initial hashes are intentionally unchanged. `payload/review/FOLLOWUP.md` records the optimization-guard correction and text review; `SOURCE-ADVANCE.md` records the later exact branch-head adjustment while retaining the original tag target. Final execution receipts establish later outcomes. Those old manifests do not purport to hash the current final helper.
`reconstructed/original-reviewed-publish.py` is a byte-proved reconstruction, **not a retained original executed file**. Removing exactly the early optimization refusal and its following blank line from the preserved pre-source-advance helper reproduces SHA256 `e679a84845303db6582753b525bb3c2d184e6139e5651560fce8c876eae42c99`, the original review/adapter pin. The original complete initial file was not retained; its reconstructed bytes must not imply execution. Original unbound bindings also were not retained as a separate file; historical review hashes establish their recorded identity, not current binding content.
`ORIGINALS.json` SHA256 is `1c6eedd5a7c0937eda5961db48d1107fd4b005d47c026936d248b7aa1d86a300`. `MANIFEST.json` binds every archive file except itself. `python verify.py` reads archive bytes and recorded relationships only; it writes nothing, imports no archived helper, and accesses no credentials, application, network, original package or source checkout. It does not repeat publication or claim independent remote readback. Raw `.gitattributes` preserves original CRLF/LF bytes; a Git whitespace check should use `git -c core.whitespace=cr-at-eol diff --check` so retained CRLF is not misclassified. Integration and exact Git blob verification remain root-owned.
@@ -0,0 +1,43 @@
# Navigation publication adapters — unexecuted preparation
Prepared by Codex-9e8r6t `/root/linux_readiness`; **root is the sole executor**. This directory contains no publication, upload or tag result. The existing `RELEASE-NOTES.draft.md` was read and preserved unchanged. Its pending marker is deliberately unsuitable for publication. These helpers are a fresh adaptation of the previously executed contextual `publish.py` and `push-tag.py`; no contextual release ID, attempt receipt, note hash or validation hash is reused.
## Fixed identity and final binding
- Reserved tag: `v0.2.0-preview.navigation.20260911`.
- Published raw-source target: `802855f7e6f2f00a107a12196b458b267f586b8d`, branch `codex/navigation-repair-prerelease-source-20260911`.
- Package: `.local/nav-repair-retry-20260911/packages/ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip`, exactly 32,971,712 bytes, SHA256 `d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1`.
- Its `.zip.sha256` file: SHA256 `435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac`; its text must bind the exact ZIP filename/hash.
- Root must finish and review `RELEASE-NOTES.md` and `VALIDATION.md` from actual native/independent acceptance. Then set their lowercase SHA256 values in `bindings.json`. Both hashes are currently **null**; all mutating actions refuse before reading credentials or making network requests. No automatic binding or acceptance inference is provided. Existing draft pending markers are rejected.
`releaseId` is initially null. A successful create writes an exclusive `release-created.json` immediately, identifying ownership. After an uncertain create without that receipt, root must inspect the remote release and deliberately bind its reviewed ID before retry; matching a tag or name alone never grants authority to edit an unrelated release. A mismatch between configured ID and saved creation ID refuses. Final notes must match the draft body exactly; amendments require a separately reviewed update, not a silent overwrite.
## Root-only sequence after final acceptance
Use bundled Python 3.11+ from repository cwd. Each command needs a new simple `--attempt` name; the exclusive per-action attempt directory preserves events and its final success/failure receipt. These examples **have not been run**:
```text
python .local/navigation-prerelease-publication-20260911/publish.py inspect --attempt initial
python .local/navigation-prerelease-publication-20260911/push-tag.py --attempt first
python .local/navigation-prerelease-publication-20260911/publish.py create --attempt first
python .local/navigation-prerelease-publication-20260911/publish.py upload --attempt first
python .local/navigation-prerelease-publication-20260911/publish.py publish --attempt first
```
`inspect` is read-only and does not require final hashes. It records the reserved release/tag state without calling that acceptance. It does not grant permission to adopt an existing release.
`push-tag.py` is a distinct normal, nonforce push from the isolated reconstruction repository. It checks the exact source branch/target and release collisions; it creates only the reserved remote tag, never a local tag or unrelated ref. An existing annotated tag is accepted only when its peeled commit is the exact target. A conflicting tag refuses. Creating/checking the tag first avoids repeating the contextual publish failure caused by a missing remote tag. No global Git configuration changes occur.
`create` requires the tag and published source branch already resolve exactly. It scans authenticated releases, including drafts, for tag collisions and creates a hash-bound **draft prerelease** only when absent. It never edits a foreign existing release. The bounded scan refuses rather than assuming absence beyond 1,000 releases.
`upload` accepts only an owned draft and exactly three permitted asset names: ZIP, ZIP.sha256 and VALIDATION.md. All local bytes are hashed first. Existing assets are downloaded and compared byte-for-byte before reuse; unexpected names, duplicate names/IDs, wrong sizes or changed bytes refuse without deletion/replacement. A missing upload is read back immediately, and final API metadata plus all three downloads must match.
`publish` downloads and verifies all three assets afresh, rechecks source/tag/release ownership and exact notes, and only then changes draft to false. Final API metadata, actual tag target, asset IDs/names/sizes and downloaded hashes are checked again. An uncertain previous publish may be recognized as already public only after all the same checks pass. The tag remains a prerelease, not a stable release claim.
## Failures, credentials and limits
No retry is automatic. An upload connection reset may mean the remote upload succeeded; a failed create or publish may also have changed remote state. Preserve the attempt, inspect, and use a new attempt name. Existing matching assets can be reused after fresh downloads. An incomplete final receipt is not a pass. A process kill can leave only the earlier flushed event log, so inspect after interruption as well. There is no release deletion, asset overwrite, force push, rollback, or inferred success.
Credentials are loaded only into process memory from the configured Gitea connection. API requests allow only the exact known origin and reject redirects; Git receives authorization through process-local environment configuration with inherited Git configuration/trace variables removed. Error receipts redact secrets; no credential is written to helper files or Git config. HTTP transport is the existing configured Gitea endpoint; this adapter does not change it.
Compared with the old contextual scripts: dynamic owned release ID replaces hard-coded release3; final note/validation pins are intentionally unbound; exact tag creation is preflighted separately; collision scans include drafts; every attempt has fresh evidence; already-uploaded bytes are checked before reuse; publication repeats downloads before and after visibility change. Runtime/network fault behavior is not claimed by static preparation. Root must obtain independent source review before executing. Source publication already passed elsewhere, but this directory has not published a tag/release or uploaded an asset. Linux/WSL remains paused.
@@ -0,0 +1,44 @@
# Source navigation — Windows development preview
PUBLICATION-PENDING: this draft is not a release or an acceptance claim for a package.
Navigate between declarations and references in the Textual model using F12,
Shift+F12 and Alt+Left. Included source files, Unicode names and unsaved drafts
are supported. Ambiguous declarations require an explicit choice; incomplete
scope is shown. Navigation preserves the accepted model and editing history.
This preview also corrects source-panel movement during diagnostic refresh,
Find dismissal/focus, an empty panel after Back, Windows system-menu input,
and repair/recovery cases that could incorrectly report changes as saved.
Applying repaired text keeps it unsaved until its destination is actually saved.
Extract the whole Windows ZIP and run `arcadia-studio.exe`. Keep
`libunwind.dll` beside both executables. Examples, offline help, documentation
and the optional REST server are included. Read START-HERE.txt and VALIDATION.md.
Verified before packaging: 755 Windows desktop tests passed (one ignored),
strict Clippy and a matching desktop build. Native checks cover declaration and
reference navigation, ambiguous/partial scope, minimum-size interaction and the
30-file engineering example. The repaired build separately passed invalid-file
repair and interrupted-save rollback, Close/Cancel protection and exact saved
model/identity/source comparisons. Each result retains its recorded build scope.
The produced ZIP contains 559 files, is 32,971,712 bytes, and has SHA256
`d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1`.
Producer file/checksum/notice/documentation checks passed. Independent archive,
package launch, server persistence and publication are pending and must be
inserted from their actual receipts before this draft is used.
This is an unfinished development prerelease. Text alias rename is not yet
implemented. Newer peer canvas/lifecycle contributions, full quantities and
calculations/constraints, maintained libraries and complete OA/SA acceptance
remain outside this milestone. Linux/WSL work remains user-paused. These binaries
are unoptimized development builds.
Desktop source: 33c6d83e9ba9a5b1310b1b627d7c40affcbcf15c, with exact raw build
inputs preserved separately. The optional server is the unchanged September 7
EFEE artifact with its own source/build records; it was not rebuilt from the
navigation desktop source. Exact raw-source reconstruction
`802855f7e6f2f00a107a12196b458b267f586b8d` is published on
`codex/navigation-repair-prerelease-source-20260911`; it is distinct from the
original build's captured HEAD. Final release tag publication remains pending.
@@ -0,0 +1,15 @@
# Source navigation — Windows development preview
Navigate between declarations and references in the Textual model with **F12**, **Shift+F12** and **Alt+Left**. Navigation follows included files and current drafts, supports Unicode names, asks you to choose ambiguous declarations, and identifies incomplete or stale results.
This preview also fixes source-panel movement during diagnostic refresh, Find dismissal and focus, an empty panel after Back, Windows system-menu input, and repair/recovery cases that could incorrectly report changes as saved. Applying repaired text keeps it unsaved until its destination is saved.
Download and extract the whole Windows ZIP, then run **arcadia-studio.exe**. Keep `libunwind.dll` beside the executables. Examples, offline engineering help, documentation and the optional REST server are included. Read `START-HERE.txt` and the separate `VALIDATION.md` release attachment for launch commands and verification scope.
Verified: 755 desktop tests passed (one ignored), strict Clippy and a matching desktop build. Native checks cover navigation and the 30-file engineering example on the preceding navigation build, repair/rollback on the corrected build, and a fresh launch of this exact package with navigation, edit/Undo, Apply, Save and complete saved-model/source comparison. Independent package and server checks passed, including complete model/source persistence through restart. The packaged desktop exited with code 0; all 559 package files stayed unchanged.
This is an **unfinished development prerelease**, with unoptimized binaries. Text alias rename, newer peer canvas/lifecycle changes, complete quantities/calculations/constraints, maintained libraries and full OA/SA acceptance remain unfinished or outside this milestone. Linux/WSL work remains user-paused.
The tag identifies exact desktop input reconstruction `802855f7e6f2f00a107a12196b458b267f586b8d`, based on corrected source `33c6d83e9ba9a5b1310b1b627d7c40affcbcf15c`. The optional server is the unchanged September 7 artifact with separately recorded source provenance; it was not rebuilt from the navigation source. See `VALIDATION.md` for the distinct build scopes and evidence links.
ZIP: 32,971,712 bytes; SHA256 `d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1`.
@@ -0,0 +1,51 @@
# Navigation preview — Windows validation
Version: `v0.2.0-preview.navigation.20260911`. Evaluated on Windows on 2026-09-11 by Codex-9e8r6t /root, with independent artifact/server review by /root/behavior_audit. This is a development milestone; full application acceptance is incomplete.
## Run
Extract the entire `ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip` into a writable folder. Run `arcadia-studio.exe`, keeping the bundled `libunwind.dll` beside both executables. No Rust compiler or machine PATH change was needed in the tested runtime. Home and Engineering guide provide offline help; examples are under `examples/`.
For the multi-file engineering walkthrough, copy the complete `examples/release1` folder to your working area and open its `project.arcadia`. Retain the supporting evidence files. Consult its README before editing.
Optional server, from PowerShell in the extracted folder:
```powershell
.\arcadia-server.exe --bind 127.0.0.1:8080 --data-dir "$env:LOCALAPPDATA\ArcadiaStudio\server-data"
```
Server documentation is `docs/server.md`; API definitions are `docs/openapi.json` and `docs/api.html`. The source checkout, rather than this binary ZIP, is required for Cargo or Docker build commands. Build prerequisites and commands are in the source's `docs/windows-packaging.md`; the recorded toolchain and actual development profile are identified in `package.json` and the evidence below.
## Artifact identity
| Item | SHA256 | Bytes |
| --- | --- | ---: |
| ZIP | `d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1` | 32,971,712 |
| arcadia-studio.exe | `b183ef31f16b3986538b3f2aba8435eab45978635c47f99ca01be6e72b168848` | 113,206,272 |
| arcadia-server.exe | `efeeb89c0d2e0f93df4472cb3e9f48b2b722a37ae1043c90a5a56f2e845fe665` | 39,743,488 |
| libunwind.dll | `f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4` | 190,976 |
The ZIP contains 559 files. Its companion `.zip.sha256` has SHA256 `435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac`. Internal `SHA256SUMS.txt` covers the other 558 files.
The tag targets [802855f7](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/src/commit/802855f7e6f2f00a107a12196b458b267f586b8d), preserving all 500 raw desktop build inputs, including 15 measured newline restorations. It is a reconstruction, not the original build commit: the build captured `eeeaa126` plus the repair delta, subsequently committed at [33c6d83](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/commit/33c6d83e9ba9a5b1310b1b627d7c40affcbcf15c).
The server retains its separate September 7 source/build record. Its 120 core/server source files match the historical tar and published [b2c3e540](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/src/commit/b2c3e54001fc19a05423bcd5808ceea78d13ff59). The current desktop core changes `language.rs` and adds outline tests. The server was not rebuilt from this tag. Neither an optimized nor a reproducible binary build is claimed.
## Verification and limits
- Corrected desktop source: 755 tests passed, zero failed, one ignored; strict all-target desktop Clippy, formatting and matching development GUI build passed. All 500 inputs remained unchanged across the recorded gates.
- Earlier matching navigation build: real F12/References/Back, ambiguity and incomplete source scope, focus/dismissal fixes, minimum-size interaction and a 30-Arcadia-file engineering example passed. Exact saved model, identities and source comparisons passed. This earlier native run found the repair saved-state defect subsequently fixed in this package.
- Corrected B183 build: missing-include and duplicate-alias repairs remain unsaved after Apply, Close warns, Cancel retains work, and Save yields exact full-model/source equality. Actual interrupted-save rollback restores disk while retaining accepted changes visibly unsaved; its final Save also passes. These checks used a separate copy of the same executable.
- Independent ZIP/extraction gate: 6,002 checks passed, including all 559 files, CRCs, checksums, safe paths, exact source reconstruction and binary provenance, documentation/examples and dependency notices. The 266-package notice inventory covers the 263 historical registry dependencies.
- Packaged server: 1,801 checks passed for help/version, health/readiness, exact OpenAPI, creation and retrieval of one Unicode-named empty project, complete Project/SourceBundle/revision/ETag and durable JSON, then exact persistence through restart. Both owned server processes were explicitly terminated after acknowledged persistence (Windows exit 1); this was not a graceful-drain test or comprehensive API editing test.
- Packaged desktop: fresh private profile and real Open of the four-file Unicode fixture; offline guide, F12 to the included declaration, Shift+F12 showing the one actual reference, Back, temporary comment edit with dirty/stale indicators, Ctrl+Z, Apply and explicit Save passed. The full comparison verified the model, identities, four reachable sources and four exact disk files. Eleven original captures are preserved. This package trial used a 1440×900 client and did not repeat minimum-size or larger engineering trials.
- Runtime closure: all 126 observed desktop modules were from Windows or the package. The native window closed normally. The original closure verifier's image-path query failed without retaining a Win32 error; a separate read-only query then verified the same process creation had exited with code 0. All 559 package files and the original ZIP remained unchanged. The first verifier failure is retained separately.
Text alias rename is not implemented in this desktop milestone. Newer peer canvas/lifecycle contributions, full quantities/calculations/constraints, maintained model libraries, comprehensive OA/SA graphical/text/REST parity, remaining engineering workflows and final independent application review are not accepted by this release. Linux/WSL setup, diagnostics, builds and checks remain paused by the user.
## Evidence
- [Producer preparation and source provenance](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/src/commit/c5ea82ed5019183e3b33f6a397b28725757e93fb/harness/release-navigation-prerelease-preparation-20260911.md), including the failed first checkout and successful reviewed retry.
- [Independent artifact and server review](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/src/branch/codex/release1-9e8r6t/harness/release-navigation-prerelease-review-20260911.md).
- [Packaged native acceptance](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/src/branch/codex/release1-9e8r6t/harness/release-navigation-prerelease-native-20260911.md).
- [Integrated navigation evidence](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/src/branch/codex/release1-9e8r6t/harness/release-text-navigation-integrated-20260911.md), linking prior navigation and corrected repair trials.
@@ -0,0 +1,9 @@
{
"started": "2026-09-12T10:51:43.290051+00:00",
"target": "f5e1c734dadd6e0203288065dac7b2e3f140cacf",
"ref": "refs/heads/codex/release1-9e8r6t",
"before": "9613cf71aa039d1efcd561a39a4a874c04639181\trefs/heads/codex/release1-9e8r6t",
"after": "f5e1c734dadd6e0203288065dac7b2e3f140cacf\trefs/heads/codex/release1-9e8r6t",
"success": true,
"finished": "2026-09-12T10:51:46.491114+00:00"
}
@@ -0,0 +1,31 @@
{
"scope": "Static AST/JSON/hash readback only; helpers not imported or executed, no network/tag/release/upload operation",
"bindingsUnbound": true,
"files": [
{
"path": "publish.py",
"bytes": 13133,
"sha256": "e679a84845303db6582753b525bb3c2d184e6139e5651560fce8c876eae42c99"
},
{
"path": "push-tag.py",
"bytes": 3471,
"sha256": "e73e351fd6322e51e8cadc016cdf9a0650022cd0a9aba816019744abcafdf6de"
},
{
"path": "bindings.json",
"bytes": 75,
"sha256": "f9422e26fc54ed3fce87f7454ea0399d4a65ed2aa43e3dad0a0a07d97e63c3a2"
},
{
"path": "README.md",
"bytes": 6355,
"sha256": "2548bafceb07d36f3b191cc40a7a003deb1c059ba53802a5f4d78b9e032ce420"
},
{
"path": "RELEASE-NOTES.draft.md",
"bytes": 2678,
"sha256": "fde884c107796f399943a37949041eb2edd306398e34d53c36fd466dc3f0ea0b"
}
]
}
@@ -0,0 +1,255 @@
"""Root-executed, hash-bound draft/upload/publication. Import has no side effects."""
if not __debug__:
raise RuntimeError('Publication requires Python assertions; optimized execution is refused.')
import argparse
from datetime import datetime, timezone
import hashlib
import json
from pathlib import Path
import re
import tomllib
import urllib.error
import urllib.parse
import urllib.request
import uuid
HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[1]
ORIGIN = 'http://217.177.34.108:3000'
API = ORIGIN + '/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio'
TAG = 'v0.2.0-preview.navigation.20260911'
TARGET = '802855f7e6f2f00a107a12196b458b267f586b8d'
BRANCH = 'codex/navigation-repair-prerelease-source-20260911'
TITLE = 'Source navigation — Windows development preview'
ZIP = 'ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip'
PACKAGE = ROOT / '.local/nav-repair-retry-20260911/packages'
ZIP_SHA = 'd7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1'
CHECKSUM_SHA = '435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac'
def now():
return datetime.now(timezone.utc).isoformat()
def digest(raw):
return hashlib.sha256(raw).hexdigest()
def read(path):
return json.loads(path.read_text(encoding='utf-8'))
def exclusive(path, value):
with path.open('x', encoding='utf-8', newline='\n') as stream:
json.dump(value, stream, indent=2, ensure_ascii=False)
stream.write('\n')
class Attempt:
def __init__(self, action, name):
assert re.fullmatch(r'[a-z0-9][a-z0-9-]{0,47}', name), 'Use a fresh simple attempt name'
self.path = HERE / 'runs' / (action + '-' + name)
self.path.mkdir(parents=True, exist_ok=False)
self.value = {'started': now(), 'action': action, 'tag': TAG, 'target': TARGET, 'success': False}
def event(self, step, **fields):
event = {'atUtc': now(), 'step': step, **fields}
with (self.path / 'events.jsonl').open('a', encoding='utf-8', newline='\n') as stream:
stream.write(json.dumps(event, ensure_ascii=False) + '\n')
def finish(self):
self.value['finished'] = now()
exclusive(self.path / 'result.json', self.value)
print(json.dumps(self.value, ensure_ascii=False), flush=True)
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
raise RuntimeError('Unexpected redirect; authorization not forwarded')
class Client:
def __init__(self):
config = tomllib.loads((Path.home() / '.codex/config.toml').read_text(encoding='utf-8'))
self.token = config['mcp_servers']['gitea']['env']['GITEA_ACCESS_TOKEN']
self.opener = urllib.request.build_opener(urllib.request.ProxyHandler({}), NoRedirect)
def redact(self, text):
return text.replace(self.token, '[redacted]')
def request(self, url, data=None, method=None, headers=None, binary=False, missing=False):
parsed = urllib.parse.urlsplit(url)
expected = urllib.parse.urlsplit(ORIGIN)
assert (parsed.scheme, parsed.netloc) == (expected.scheme, expected.netloc)
assert parsed.username is None and parsed.password is None
request = urllib.request.Request(url, data=data, method=method,
headers={'Authorization': 'token ' + self.token, **(headers or {})})
try:
with self.opener.open(request, timeout=120) as response:
body = response.read()
return body if binary else json.loads(body)
except urllib.error.HTTPError as error:
detail = self.redact(error.read(2000).decode('utf-8', 'replace'))
if missing and error.code == 404:
return None
raise RuntimeError(f'HTTP {error.code}: {detail}') from None
def json(self, url, value, method):
return self.request(url, json.dumps(value).encode('utf-8'), method,
{'Content-Type': 'application/json'})
def release(self):
# Listing authenticated drafts catches a reserved-tag collision even
# before a server has made its Git tag visible to the by-tag endpoint.
matches = []
for page in range(1, 21):
items = self.request(API + f'/releases?limit=50&page={page}')
assert isinstance(items, list)
matches.extend(item for item in items if item['tag_name'] == TAG)
if len(items) < 50:
break
else:
raise RuntimeError('Release collision scan exceeded its bound')
assert len(matches) <= 1, 'Multiple releases claim the reserved tag'
return matches[0] if matches else None
def tag(self):
return self.request(API + '/tags/' + urllib.parse.quote(TAG, safe=''), missing=True)
def inputs():
bindings = read(HERE / 'bindings.json')
for key in ('notesSha256', 'validationSha256'):
assert isinstance(bindings[key], str) and re.fullmatch(r'[0-9a-f]{64}', bindings[key]), 'Final notes and VALIDATION hashes must be reviewed and bound first'
notes = (HERE / 'RELEASE-NOTES.md').read_bytes()
validation = (HERE / 'VALIDATION.md').read_bytes()
assert digest(notes) == bindings['notesSha256']
assert digest(validation) == bindings['validationSha256']
for raw in (notes, validation):
text = raw.decode('utf-8')
assert all(marker not in text for marker in ('PUBLICATION-PENDING', 'PACKAGE-RUNTIME-ACCEPTANCE-PENDING'))
assets = {ZIP: (PACKAGE / ZIP).read_bytes(), ZIP + '.sha256': (PACKAGE / (ZIP + '.sha256')).read_bytes(), 'VALIDATION.md': validation}
assert len(assets[ZIP]) == 32971712 and digest(assets[ZIP]) == ZIP_SHA
assert digest(assets[ZIP + '.sha256']) == CHECKSUM_SHA
assert assets[ZIP + '.sha256'].decode('utf-8').strip() == ZIP_SHA + ' ' + ZIP
return bindings, notes.decode('utf-8'), assets
def source_and_tag(client, require_tag=True):
branch = client.request(API + '/branches/' + urllib.parse.quote(BRANCH, safe=''))
assert branch['commit']['id'] == TARGET, 'Published source branch changed'
tag = client.tag()
if tag is None:
assert not require_tag, 'Run the separately reviewed nonforce tag helper first'
else:
assert tag['name'] == TAG and tag['commit']['sha'] == TARGET, 'Tag collision'
return tag
def owned_release(value, bindings, notes):
expected_id = bindings.get('releaseId')
state = HERE / 'release-created.json'
if state.exists():
saved = read(state)
assert saved['tag'] == TAG and saved['target'] == TARGET
assert expected_id in (None, saved['releaseId'])
expected_id = saved['releaseId']
assert expected_id is not None and value['id'] == expected_id, 'Existing release is not bound to this run; inspect and review before setting releaseId'
assert value['tag_name'] == TAG and value['target_commitish'] == TARGET
assert value['prerelease'] is True and value['name'] == TITLE and value['body'] == notes
def verify_assets(client, release_id, assets, allow_missing=False):
remote = client.request(API + f'/releases/{release_id}/assets')
names = [item['name'] for item in remote]
assert len(names) == len(set(names)) and len({a['id'] for a in remote}) == len(remote)
assert set(names) <= set(assets)
if not allow_missing:
assert set(names) == set(assets), 'Exactly three assets required'
verified = []
for item in remote:
expected = assets[item['name']]
assert item['size'] == len(expected)
received = client.request(item['browser_download_url'], binary=True)
assert received == expected, 'Existing asset bytes differ; no overwrite or deletion permitted'
verified.append({'id': item['id'], 'name': item['name'], 'bytes': len(received), 'sha256': digest(received), 'url': item['browser_download_url']})
return verified
def main():
parser = argparse.ArgumentParser()
parser.add_argument('action', choices=('inspect', 'create', 'upload', 'publish'))
parser.add_argument('--attempt', required=True)
args = parser.parse_args()
attempt = Attempt(args.action, args.attempt)
client = None
try:
if args.action == 'inspect':
client = Client()
release, tag = client.release(), client.tag()
attempt.value.update(success=True, release=release, remoteTag=tag,
scope='Read-only inspection; no acceptance or mutation')
return
bindings, notes, assets = inputs()
attempt.value['bindings'] = bindings
attempt.value['assetHashes'] = {name: digest(raw) for name, raw in assets.items()}
client = Client()
source_and_tag(client)
release = client.release()
if args.action == 'create':
if release is not None:
owned_release(release, bindings, notes)
assert release['draft'] is True
attempt.event('existing-owned-draft', releaseId=release['id'])
else:
assert not (HERE / 'release-created.json').exists() and bindings.get('releaseId') is None
attempt.event('create-request-started')
release = client.json(API + '/releases', {'tag_name': TAG, 'target_commitish': TARGET,
'name': TITLE, 'body': notes, 'draft': True, 'prerelease': True}, 'POST')
assert release['tag_name'] == TAG and release['target_commitish'] == TARGET and release['draft'] is True
# Persist ownership immediately; a failed readback can be retried safely.
exclusive(HERE / 'release-created.json', {'releaseId': release['id'], 'tag': TAG, 'target': TARGET, 'atUtc': now()})
attempt.event('created-draft', releaseId=release['id'])
fresh = client.release()
owned_release(fresh, bindings, notes)
assert fresh['draft'] is True
verify_assets(client, fresh['id'], assets, allow_missing=True)
else:
assert release is not None, 'Create the hash-bound draft first'
owned_release(release, bindings, notes)
endpoint = API + f'/releases/{release["id"]}'
if args.action == 'upload':
assert release['draft'] is True, 'Never upload into a public release'
existing = verify_assets(client, release['id'], assets, allow_missing=True)
for name, raw in assets.items():
if any(item['name'] == name for item in existing):
attempt.event('existing-asset-verified', name=name, sha256=digest(raw))
continue
boundary = 'ArcadiaNavigation' + uuid.uuid4().hex
prefix = (f'--{boundary}\r\nContent-Disposition: form-data; name="attachment"; filename="{name}"\r\nContent-Type: application/octet-stream\r\n\r\n').encode()
attempt.event('upload-request-started', name=name, sha256=digest(raw))
result = client.request(endpoint + '/assets?' + urllib.parse.urlencode({'name': name}),
prefix + raw + f'\r\n--{boundary}--\r\n'.encode(), 'POST',
{'Content-Type': 'multipart/form-data; boundary=' + boundary})
assert result['name'] == name and result['size'] == len(raw)
assert client.request(result['browser_download_url'], binary=True) == raw
attempt.event('uploaded-and-downloaded', name=name, assetId=result['id'], sha256=digest(raw))
attempt.value['assets'] = verify_assets(client, release['id'], assets)
else:
# Download all three afresh immediately before changing visibility.
before = verify_assets(client, release['id'], assets)
source_and_tag(client)
fresh = client.release()
owned_release(fresh, bindings, notes)
if fresh['draft']:
attempt.event('publish-request-started', releaseId=fresh['id'])
client.json(endpoint, {'draft': False, 'prerelease': True, 'body': notes}, 'PATCH')
final = client.release()
owned_release(final, bindings, notes)
assert final['draft'] is False
source_and_tag(client)
after = verify_assets(client, final['id'], assets)
assert sorted(before, key=lambda x: x['id']) == sorted(after, key=lambda x: x['id'])
attempt.value.update(assets=after, url=final['html_url'], publishedAt=final['published_at'])
fresh = client.release()
owned_release(fresh, bindings, notes)
attempt.value.update(success=True, releaseId=fresh['id'], draft=fresh['draft'], prerelease=True)
except BaseException as error:
message = str(error)
attempt.value['error'] = client.redact(message) if client else message
attempt.value['remoteOutcome'] = 'May be partial if a request started; inspect before retry. No automatic overwrite/delete.'
raise
finally:
attempt.finish()
if __name__ == '__main__':
main()
@@ -0,0 +1,73 @@
"""Separately authorized normal push of exactly the reserved tag; no release mutation."""
import argparse
import base64
import os
import subprocess
from publish import BRANCH, ORIGIN, ROOT, TAG, TARGET, Attempt, Client, inputs, owned_release, source_and_tag
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--attempt', required=True)
args = parser.parse_args()
attempt = Attempt('tag', args.attempt)
client = None
credential = ''
try:
bindings, notes, _ = inputs()
attempt.value['bindings'] = bindings
client = Client()
source_and_tag(client, require_tag=False)
release = client.release()
if release is not None:
owned_release(release, bindings, notes)
assert release['draft'] is True, 'Do not modify tags of a published release'
username = client.request(ORIGIN + '/api/v1/user')['login']
credential = base64.b64encode((username + ':' + client.token).encode()).decode()
env = {key: value for key, value in os.environ.items() if not key.startswith('GIT_')}
env.update({'GIT_TERMINAL_PROMPT': '0', 'GIT_CONFIG_COUNT': '4',
'GIT_CONFIG_KEY_0': 'credential.helper', 'GIT_CONFIG_VALUE_0': '',
'GIT_CONFIG_KEY_1': 'http.' + ORIGIN + '/.extraHeader', 'GIT_CONFIG_VALUE_1': 'Authorization: Basic ' + credential,
'GIT_CONFIG_KEY_2': 'http.followRedirects', 'GIT_CONFIG_VALUE_2': 'false',
'GIT_CONFIG_KEY_3': 'http.proxy', 'GIT_CONFIG_VALUE_3': ''})
source = ROOT / '.local/nav-repair-retry-20260911/source'
remote = ORIGIN + '/sorokin.oleg.edu/ARCADIA-Studio.git'
ref = 'refs/tags/' + TAG
def git(*args):
result = subprocess.run(['git', *args], cwd=source, env=env, capture_output=True, text=True, timeout=120)
if result.returncode:
raise RuntimeError(f'Git exit {result.returncode}: ' + client.redact(result.stderr).replace(credential, '[redacted]'))
return result.stdout.strip()
def check_remote_tag():
output = git('ls-remote', remote, ref, ref + '^{}')
records = {line.split()[1]: line.split()[0] for line in output.splitlines()}
assert set(records) <= {ref, ref + '^{}'}
if records:
assert records.get(ref + '^{}', records.get(ref)) == TARGET, 'Remote tag collision'
return output
assert git('rev-parse', TARGET + '^{commit}') == TARGET
assert git('ls-remote', remote, 'refs/heads/' + BRANCH).split()[0] == TARGET
before = check_remote_tag()
attempt.value['before'] = before
if not before:
attempt.event('tag-push-started', ref=ref, target=TARGET)
git('push', remote, TARGET + ':' + ref)
after = check_remote_tag()
assert after
source_and_tag(client)
attempt.value.update(success=True, after=after, scope='One nonforce exact tag; no local tag/branch/index or release mutation')
except BaseException as error:
message = str(error)
if client:
message = client.redact(message)
if credential:
message = message.replace(credential, '[redacted]')
attempt.value.update(error=message, remoteOutcome='Inspect after any uncertain push; no force or automatic retry')
raise
finally:
attempt.finish()
if __name__ == '__main__':
main()
@@ -0,0 +1,5 @@
{
"notesSha256": "9361105c8bb9f939f0ea931edb107ad21acd7acdcc2d9424f0f0b20d62f980bd",
"validationSha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2",
"releaseId": null
}
@@ -0,0 +1,21 @@
"""Read-only inspection of source branch advancement after preflight refusal."""
from datetime import datetime, timezone
import json
from pathlib import Path
import urllib.parse
from publish import Client, API, BRANCH, TARGET
HERE = Path(__file__).resolve().parent
path = HERE / 'source-advance-inspection.json'
if path.exists():
raise RuntimeError('Preserve the previous inspection')
client = Client()
branch = client.request(API + '/branches/' + urllib.parse.quote(BRANCH, safe=''))
head = branch['commit']['id']
comparison = client.request(API + '/compare/' + TARGET + '...' + head)
target = client.request(API + '/git/commits/' + TARGET)
result = {'atUtc': datetime.now(timezone.utc).isoformat(), 'target': TARGET, 'branchHead': head, 'branch': branch, 'targetCommit': target, 'comparison': comparison}
with path.open('x', encoding='utf-8', newline='\n') as out:
json.dump(result, out, ensure_ascii=False, indent=2)
out.write('\n')
print(json.dumps({'branchHead': head, 'targetCommit': target.get('sha'), 'comparisonKeys': list(comparison), 'files': comparison.get('files'), 'commits': [{'sha': c.get('sha'), 'message': c.get('commit', {}).get('message')} for c in comparison.get('commits', [])]}, ensure_ascii=False))
@@ -0,0 +1,258 @@
"""Root-executed, hash-bound draft/upload/publication. Import has no side effects."""
if not __debug__:
raise RuntimeError('Publication requires Python assertions; optimized execution is refused.')
import argparse
from datetime import datetime, timezone
import hashlib
import json
from pathlib import Path
import re
import tomllib
import urllib.error
import urllib.parse
import urllib.request
import uuid
HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[1]
ORIGIN = 'http://217.177.34.108:3000'
API = ORIGIN + '/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio'
TAG = 'v0.2.0-preview.navigation.20260911'
TARGET = '802855f7e6f2f00a107a12196b458b267f586b8d'
BRANCH = 'codex/navigation-repair-prerelease-source-20260911'
SOURCE_BRANCH_HEAD = '0c9ee1505774a0f64c5f3a58b0da64a4673d5000'
TITLE = 'Source navigation — Windows development preview'
ZIP = 'ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip'
PACKAGE = ROOT / '.local/nav-repair-retry-20260911/packages'
ZIP_SHA = 'd7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1'
CHECKSUM_SHA = '435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac'
def now():
return datetime.now(timezone.utc).isoformat()
def digest(raw):
return hashlib.sha256(raw).hexdigest()
def read(path):
return json.loads(path.read_text(encoding='utf-8'))
def exclusive(path, value):
with path.open('x', encoding='utf-8', newline='\n') as stream:
json.dump(value, stream, indent=2, ensure_ascii=False)
stream.write('\n')
class Attempt:
def __init__(self, action, name):
assert re.fullmatch(r'[a-z0-9][a-z0-9-]{0,47}', name), 'Use a fresh simple attempt name'
self.path = HERE / 'runs' / (action + '-' + name)
self.path.mkdir(parents=True, exist_ok=False)
self.value = {'started': now(), 'action': action, 'tag': TAG, 'target': TARGET, 'success': False}
def event(self, step, **fields):
event = {'atUtc': now(), 'step': step, **fields}
with (self.path / 'events.jsonl').open('a', encoding='utf-8', newline='\n') as stream:
stream.write(json.dumps(event, ensure_ascii=False) + '\n')
def finish(self):
self.value['finished'] = now()
exclusive(self.path / 'result.json', self.value)
print(json.dumps(self.value, ensure_ascii=False), flush=True)
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
raise RuntimeError('Unexpected redirect; authorization not forwarded')
class Client:
def __init__(self):
config = tomllib.loads((Path.home() / '.codex/config.toml').read_text(encoding='utf-8'))
self.token = config['mcp_servers']['gitea']['env']['GITEA_ACCESS_TOKEN']
self.opener = urllib.request.build_opener(urllib.request.ProxyHandler({}), NoRedirect)
def redact(self, text):
return text.replace(self.token, '[redacted]')
def request(self, url, data=None, method=None, headers=None, binary=False, missing=False):
parsed = urllib.parse.urlsplit(url)
expected = urllib.parse.urlsplit(ORIGIN)
assert (parsed.scheme, parsed.netloc) == (expected.scheme, expected.netloc)
assert parsed.username is None and parsed.password is None
request = urllib.request.Request(url, data=data, method=method,
headers={'Authorization': 'token ' + self.token, **(headers or {})})
try:
with self.opener.open(request, timeout=120) as response:
body = response.read()
return body if binary else json.loads(body)
except urllib.error.HTTPError as error:
detail = self.redact(error.read(2000).decode('utf-8', 'replace'))
if missing and error.code == 404:
return None
raise RuntimeError(f'HTTP {error.code}: {detail}') from None
def json(self, url, value, method):
return self.request(url, json.dumps(value).encode('utf-8'), method,
{'Content-Type': 'application/json'})
def release(self):
# Listing authenticated drafts catches a reserved-tag collision even
# before a server has made its Git tag visible to the by-tag endpoint.
matches = []
for page in range(1, 21):
items = self.request(API + f'/releases?limit=50&page={page}')
assert isinstance(items, list)
matches.extend(item for item in items if item['tag_name'] == TAG)
if len(items) < 50:
break
else:
raise RuntimeError('Release collision scan exceeded its bound')
assert len(matches) <= 1, 'Multiple releases claim the reserved tag'
return matches[0] if matches else None
def tag(self):
return self.request(API + '/tags/' + urllib.parse.quote(TAG, safe=''), missing=True)
def inputs():
bindings = read(HERE / 'bindings.json')
for key in ('notesSha256', 'validationSha256'):
assert isinstance(bindings[key], str) and re.fullmatch(r'[0-9a-f]{64}', bindings[key]), 'Final notes and VALIDATION hashes must be reviewed and bound first'
notes = (HERE / 'RELEASE-NOTES.md').read_bytes()
validation = (HERE / 'VALIDATION.md').read_bytes()
assert digest(notes) == bindings['notesSha256']
assert digest(validation) == bindings['validationSha256']
for raw in (notes, validation):
text = raw.decode('utf-8')
assert all(marker not in text for marker in ('PUBLICATION-PENDING', 'PACKAGE-RUNTIME-ACCEPTANCE-PENDING'))
assets = {ZIP: (PACKAGE / ZIP).read_bytes(), ZIP + '.sha256': (PACKAGE / (ZIP + '.sha256')).read_bytes(), 'VALIDATION.md': validation}
assert len(assets[ZIP]) == 32971712 and digest(assets[ZIP]) == ZIP_SHA
assert digest(assets[ZIP + '.sha256']) == CHECKSUM_SHA
assert assets[ZIP + '.sha256'].decode('utf-8').strip() == ZIP_SHA + ' ' + ZIP
return bindings, notes.decode('utf-8'), assets
def source_and_tag(client, require_tag=True):
branch = client.request(API + '/branches/' + urllib.parse.quote(BRANCH, safe=''))
assert branch['commit']['id'] == SOURCE_BRANCH_HEAD, 'Published source branch changed'
target_commit = client.request(API + '/git/commits/' + TARGET)
assert target_commit['sha'] == TARGET, 'Exact source snapshot is unavailable'
tag = client.tag()
if tag is None:
assert not require_tag, 'Run the separately reviewed nonforce tag helper first'
else:
assert tag['name'] == TAG and tag['commit']['sha'] == TARGET, 'Tag collision'
return tag
def owned_release(value, bindings, notes):
expected_id = bindings.get('releaseId')
state = HERE / 'release-created.json'
if state.exists():
saved = read(state)
assert saved['tag'] == TAG and saved['target'] == TARGET
assert expected_id in (None, saved['releaseId'])
expected_id = saved['releaseId']
assert expected_id is not None and value['id'] == expected_id, 'Existing release is not bound to this run; inspect and review before setting releaseId'
assert value['tag_name'] == TAG and value['target_commitish'] == TARGET
assert value['prerelease'] is True and value['name'] == TITLE and value['body'] == notes
def verify_assets(client, release_id, assets, allow_missing=False):
remote = client.request(API + f'/releases/{release_id}/assets')
names = [item['name'] for item in remote]
assert len(names) == len(set(names)) and len({a['id'] for a in remote}) == len(remote)
assert set(names) <= set(assets)
if not allow_missing:
assert set(names) == set(assets), 'Exactly three assets required'
verified = []
for item in remote:
expected = assets[item['name']]
assert item['size'] == len(expected)
received = client.request(item['browser_download_url'], binary=True)
assert received == expected, 'Existing asset bytes differ; no overwrite or deletion permitted'
verified.append({'id': item['id'], 'name': item['name'], 'bytes': len(received), 'sha256': digest(received), 'url': item['browser_download_url']})
return verified
def main():
parser = argparse.ArgumentParser()
parser.add_argument('action', choices=('inspect', 'create', 'upload', 'publish'))
parser.add_argument('--attempt', required=True)
args = parser.parse_args()
attempt = Attempt(args.action, args.attempt)
client = None
try:
if args.action == 'inspect':
client = Client()
release, tag = client.release(), client.tag()
attempt.value.update(success=True, release=release, remoteTag=tag,
scope='Read-only inspection; no acceptance or mutation')
return
bindings, notes, assets = inputs()
attempt.value['bindings'] = bindings
attempt.value['assetHashes'] = {name: digest(raw) for name, raw in assets.items()}
client = Client()
source_and_tag(client)
release = client.release()
if args.action == 'create':
if release is not None:
owned_release(release, bindings, notes)
assert release['draft'] is True
attempt.event('existing-owned-draft', releaseId=release['id'])
else:
assert not (HERE / 'release-created.json').exists() and bindings.get('releaseId') is None
attempt.event('create-request-started')
release = client.json(API + '/releases', {'tag_name': TAG, 'target_commitish': TARGET,
'name': TITLE, 'body': notes, 'draft': True, 'prerelease': True}, 'POST')
assert release['tag_name'] == TAG and release['target_commitish'] == TARGET and release['draft'] is True
# Persist ownership immediately; a failed readback can be retried safely.
exclusive(HERE / 'release-created.json', {'releaseId': release['id'], 'tag': TAG, 'target': TARGET, 'atUtc': now()})
attempt.event('created-draft', releaseId=release['id'])
fresh = client.release()
owned_release(fresh, bindings, notes)
assert fresh['draft'] is True
verify_assets(client, fresh['id'], assets, allow_missing=True)
else:
assert release is not None, 'Create the hash-bound draft first'
owned_release(release, bindings, notes)
endpoint = API + f'/releases/{release["id"]}'
if args.action == 'upload':
assert release['draft'] is True, 'Never upload into a public release'
existing = verify_assets(client, release['id'], assets, allow_missing=True)
for name, raw in assets.items():
if any(item['name'] == name for item in existing):
attempt.event('existing-asset-verified', name=name, sha256=digest(raw))
continue
boundary = 'ArcadiaNavigation' + uuid.uuid4().hex
prefix = (f'--{boundary}\r\nContent-Disposition: form-data; name="attachment"; filename="{name}"\r\nContent-Type: application/octet-stream\r\n\r\n').encode()
attempt.event('upload-request-started', name=name, sha256=digest(raw))
result = client.request(endpoint + '/assets?' + urllib.parse.urlencode({'name': name}),
prefix + raw + f'\r\n--{boundary}--\r\n'.encode(), 'POST',
{'Content-Type': 'multipart/form-data; boundary=' + boundary})
assert result['name'] == name and result['size'] == len(raw)
assert client.request(result['browser_download_url'], binary=True) == raw
attempt.event('uploaded-and-downloaded', name=name, assetId=result['id'], sha256=digest(raw))
attempt.value['assets'] = verify_assets(client, release['id'], assets)
else:
# Download all three afresh immediately before changing visibility.
before = verify_assets(client, release['id'], assets)
source_and_tag(client)
fresh = client.release()
owned_release(fresh, bindings, notes)
if fresh['draft']:
attempt.event('publish-request-started', releaseId=fresh['id'])
client.json(endpoint, {'draft': False, 'prerelease': True, 'body': notes}, 'PATCH')
final = client.release()
owned_release(final, bindings, notes)
assert final['draft'] is False
source_and_tag(client)
after = verify_assets(client, final['id'], assets)
assert sorted(before, key=lambda x: x['id']) == sorted(after, key=lambda x: x['id'])
attempt.value.update(assets=after, url=final['html_url'], publishedAt=final['published_at'])
fresh = client.release()
owned_release(fresh, bindings, notes)
attempt.value.update(success=True, releaseId=fresh['id'], draft=fresh['draft'], prerelease=True)
except BaseException as error:
message = str(error)
attempt.value['error'] = client.redact(message) if client else message
attempt.value['remoteOutcome'] = 'May be partial if a request started; inspect before retry. No automatic overwrite/delete.'
raise
finally:
attempt.finish()
if __name__ == '__main__':
main()
@@ -0,0 +1,57 @@
"""Publish only the current reviewed records branch, with exact readback."""
import base64
from datetime import datetime, timezone
import json
import os
from pathlib import Path
import subprocess
import tomllib
import urllib.request
BASE = Path(__file__).resolve().parent
ROOT = BASE.parents[1]
TARGET = 'f5e1c734dadd6e0203288065dac7b2e3f140cacf'
REF = 'refs/heads/codex/release1-9e8r6t'
REMOTE = 'http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio.git'
RESULT = BASE / 'acceptance-records-push-result.json'
assert not RESULT.exists()
token = tomllib.loads((Path.home() / '.codex/config.toml').read_text(encoding='utf-8'))['mcp_servers']['gitea']['env']['GITEA_ACCESS_TOKEN']
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
raise RuntimeError('Unexpected redirect')
opener = urllib.request.build_opener(urllib.request.ProxyHandler({}), NoRedirect)
with opener.open(urllib.request.Request('http://217.177.34.108:3000/api/v1/user', headers={'Authorization': 'token ' + token}), timeout=30) as response:
username = json.load(response)['login']
credential = base64.b64encode((username + ':' + token).encode()).decode()
env = {k: v for k, v in os.environ.items() if not k.startswith(('GIT_TRACE', 'GIT_CONFIG_', 'GIT_CURL_VERBOSE'))}
env.update({'GIT_TERMINAL_PROMPT': '0', 'GIT_CONFIG_COUNT': '4',
'GIT_CONFIG_KEY_0': 'credential.helper', 'GIT_CONFIG_VALUE_0': '',
'GIT_CONFIG_KEY_1': 'http.http://217.177.34.108:3000/.extraHeader',
'GIT_CONFIG_VALUE_1': 'Authorization: Basic ' + credential,
'GIT_CONFIG_KEY_2': 'http.followRedirects', 'GIT_CONFIG_VALUE_2': 'false',
'GIT_CONFIG_KEY_3': 'http.proxy', 'GIT_CONFIG_VALUE_3': ''})
def redact(value):
return value.replace(token, '[redacted]').replace(credential, '[redacted]')
def git(*args):
result = subprocess.run(['git', *args], cwd=ROOT, env=env, capture_output=True, text=True, timeout=120)
if result.returncode:
raise RuntimeError(f'Git exit {result.returncode}: ' + redact(result.stderr))
return result.stdout.strip()
record = {'started': datetime.now(timezone.utc).isoformat(), 'target': TARGET, 'ref': REF}
try:
assert git('rev-parse', 'HEAD') == TARGET
assert git('symbolic-ref', 'HEAD') == REF
record['before'] = git('ls-remote', REMOTE, REF)
git('push', REMOTE, TARGET + ':' + REF)
record['after'] = git('ls-remote', REMOTE, REF)
assert record['after'].split()[0] == TARGET
record['success'] = True
except BaseException as error:
record.update({'success': False, 'error': redact(str(error))})
raise
finally:
record['finished'] = datetime.now(timezone.utc).isoformat()
with RESULT.open('x', encoding='utf-8', newline='\n') as out:
json.dump(record, out, indent=2)
out.write('\n')
print(json.dumps(record, indent=2), flush=True)
@@ -0,0 +1,57 @@
"""Publish only the current reviewed records branch, with exact readback."""
import base64
from datetime import datetime, timezone
import json
import os
from pathlib import Path
import subprocess
import tomllib
import urllib.request
BASE = Path(__file__).resolve().parent
ROOT = BASE.parents[1]
TARGET = 'c5ea82ed5019183e3b33f6a397b28725757e93fb'
REF = 'refs/heads/codex/release1-9e8r6t'
REMOTE = 'http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio.git'
RESULT = BASE / 'records-push-result.json'
assert not RESULT.exists()
token = tomllib.loads((Path.home() / '.codex/config.toml').read_text(encoding='utf-8'))['mcp_servers']['gitea']['env']['GITEA_ACCESS_TOKEN']
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
raise RuntimeError('Unexpected redirect')
opener = urllib.request.build_opener(urllib.request.ProxyHandler({}), NoRedirect)
with opener.open(urllib.request.Request('http://217.177.34.108:3000/api/v1/user', headers={'Authorization': 'token ' + token}), timeout=30) as response:
username = json.load(response)['login']
credential = base64.b64encode((username + ':' + token).encode()).decode()
env = {k: v for k, v in os.environ.items() if not k.startswith(('GIT_TRACE', 'GIT_CONFIG_', 'GIT_CURL_VERBOSE'))}
env.update({'GIT_TERMINAL_PROMPT': '0', 'GIT_CONFIG_COUNT': '4',
'GIT_CONFIG_KEY_0': 'credential.helper', 'GIT_CONFIG_VALUE_0': '',
'GIT_CONFIG_KEY_1': 'http.http://217.177.34.108:3000/.extraHeader',
'GIT_CONFIG_VALUE_1': 'Authorization: Basic ' + credential,
'GIT_CONFIG_KEY_2': 'http.followRedirects', 'GIT_CONFIG_VALUE_2': 'false',
'GIT_CONFIG_KEY_3': 'http.proxy', 'GIT_CONFIG_VALUE_3': ''})
def redact(value):
return value.replace(token, '[redacted]').replace(credential, '[redacted]')
def git(*args):
result = subprocess.run(['git', *args], cwd=ROOT, env=env, capture_output=True, text=True, timeout=120)
if result.returncode:
raise RuntimeError(f'Git exit {result.returncode}: ' + redact(result.stderr))
return result.stdout.strip()
record = {'started': datetime.now(timezone.utc).isoformat(), 'target': TARGET, 'ref': REF}
try:
assert git('rev-parse', 'HEAD') == TARGET
assert git('symbolic-ref', 'HEAD') == REF
record['before'] = git('ls-remote', REMOTE, REF)
git('push', REMOTE, TARGET + ':' + REF)
record['after'] = git('ls-remote', REMOTE, REF)
assert record['after'].split()[0] == TARGET
record['success'] = True
except BaseException as error:
record.update({'success': False, 'error': redact(str(error))})
raise
finally:
record['finished'] = datetime.now(timezone.utc).isoformat()
with RESULT.open('x', encoding='utf-8', newline='\n') as out:
json.dump(record, out, indent=2)
out.write('\n')
print(json.dumps(record, indent=2), flush=True)
@@ -0,0 +1,73 @@
"""Separately authorized normal push of exactly the reserved tag; no release mutation."""
import argparse
import base64
import os
import subprocess
from publish import BRANCH, ORIGIN, ROOT, TAG, TARGET, SOURCE_BRANCH_HEAD, Attempt, Client, inputs, owned_release, source_and_tag
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--attempt', required=True)
args = parser.parse_args()
attempt = Attempt('tag', args.attempt)
client = None
credential = ''
try:
bindings, notes, _ = inputs()
attempt.value['bindings'] = bindings
client = Client()
source_and_tag(client, require_tag=False)
release = client.release()
if release is not None:
owned_release(release, bindings, notes)
assert release['draft'] is True, 'Do not modify tags of a published release'
username = client.request(ORIGIN + '/api/v1/user')['login']
credential = base64.b64encode((username + ':' + client.token).encode()).decode()
env = {key: value for key, value in os.environ.items() if not key.startswith('GIT_')}
env.update({'GIT_TERMINAL_PROMPT': '0', 'GIT_CONFIG_COUNT': '4',
'GIT_CONFIG_KEY_0': 'credential.helper', 'GIT_CONFIG_VALUE_0': '',
'GIT_CONFIG_KEY_1': 'http.' + ORIGIN + '/.extraHeader', 'GIT_CONFIG_VALUE_1': 'Authorization: Basic ' + credential,
'GIT_CONFIG_KEY_2': 'http.followRedirects', 'GIT_CONFIG_VALUE_2': 'false',
'GIT_CONFIG_KEY_3': 'http.proxy', 'GIT_CONFIG_VALUE_3': ''})
source = ROOT / '.local/nav-repair-retry-20260911/source'
remote = ORIGIN + '/sorokin.oleg.edu/ARCADIA-Studio.git'
ref = 'refs/tags/' + TAG
def git(*args):
result = subprocess.run(['git', *args], cwd=source, env=env, capture_output=True, text=True, timeout=120)
if result.returncode:
raise RuntimeError(f'Git exit {result.returncode}: ' + client.redact(result.stderr).replace(credential, '[redacted]'))
return result.stdout.strip()
def check_remote_tag():
output = git('ls-remote', remote, ref, ref + '^{}')
records = {line.split()[1]: line.split()[0] for line in output.splitlines()}
assert set(records) <= {ref, ref + '^{}'}
if records:
assert records.get(ref + '^{}', records.get(ref)) == TARGET, 'Remote tag collision'
return output
assert git('rev-parse', TARGET + '^{commit}') == TARGET
assert git('ls-remote', remote, 'refs/heads/' + BRANCH).split()[0] == SOURCE_BRANCH_HEAD
before = check_remote_tag()
attempt.value['before'] = before
if not before:
attempt.event('tag-push-started', ref=ref, target=TARGET)
git('push', remote, TARGET + ':' + ref)
after = check_remote_tag()
assert after
source_and_tag(client)
attempt.value.update(success=True, after=after, scope='One nonforce exact tag; no local tag/branch/index or release mutation')
except BaseException as error:
message = str(error)
if client:
message = client.redact(message)
if credential:
message = message.replace(credential, '[redacted]')
attempt.value.update(error=message, remoteOutcome='Inspect after any uncertain push; no force or automatic retry')
raise
finally:
attempt.finish()
if __name__ == '__main__':
main()
@@ -0,0 +1,9 @@
{
"started": "2026-09-11T21:30:36.710783+00:00",
"target": "c5ea82ed5019183e3b33f6a397b28725757e93fb",
"ref": "refs/heads/codex/release1-9e8r6t",
"before": "8cf64cedb242a859aafebf93a8abc6dbc03f869a\trefs/heads/codex/release1-9e8r6t",
"after": "c5ea82ed5019183e3b33f6a397b28725757e93fb\trefs/heads/codex/release1-9e8r6t",
"success": true,
"finished": "2026-09-11T21:30:41.350051+00:00"
}
@@ -0,0 +1,6 @@
{
"releaseId": 4,
"tag": "v0.2.0-preview.navigation.20260911",
"target": "802855f7e6f2f00a107a12196b458b267f586b8d",
"atUtc": "2026-09-12T10:52:54.353585+00:00"
}
@@ -0,0 +1,2 @@
{"atUtc": "2026-09-12T10:52:54.129275+00:00", "step": "create-request-started"}
{"atUtc": "2026-09-12T10:52:54.355136+00:00", "step": "created-draft", "releaseId": 4}
@@ -0,0 +1,21 @@
{
"started": "2026-09-12T10:52:52.795669+00:00",
"action": "create",
"tag": "v0.2.0-preview.navigation.20260911",
"target": "802855f7e6f2f00a107a12196b458b267f586b8d",
"success": true,
"bindings": {
"notesSha256": "9361105c8bb9f939f0ea931edb107ad21acd7acdcc2d9424f0f0b20d62f980bd",
"validationSha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2",
"releaseId": null
},
"assetHashes": {
"ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip": "d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1",
"ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip.sha256": "435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac",
"VALIDATION.md": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2"
},
"releaseId": 4,
"draft": true,
"prerelease": true,
"finished": "2026-09-12T10:52:54.913299+00:00"
}
@@ -0,0 +1,11 @@
{
"started": "2026-09-12T10:48:02.393627+00:00",
"action": "inspect",
"tag": "v0.2.0-preview.navigation.20260911",
"target": "802855f7e6f2f00a107a12196b458b267f586b8d",
"success": true,
"release": null,
"remoteTag": null,
"scope": "Read-only inspection; no acceptance or mutation",
"finished": "2026-09-12T10:48:04.190605+00:00"
}
@@ -0,0 +1 @@
{"atUtc": "2026-09-12T10:53:54.264100+00:00", "step": "publish-request-started", "releaseId": 4}
@@ -0,0 +1,46 @@
{
"started": "2026-09-12T10:53:46.108648+00:00",
"action": "publish",
"tag": "v0.2.0-preview.navigation.20260911",
"target": "802855f7e6f2f00a107a12196b458b267f586b8d",
"success": true,
"bindings": {
"notesSha256": "9361105c8bb9f939f0ea931edb107ad21acd7acdcc2d9424f0f0b20d62f980bd",
"validationSha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2",
"releaseId": null
},
"assetHashes": {
"ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip": "d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1",
"ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip.sha256": "435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac",
"VALIDATION.md": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2"
},
"assets": [
{
"id": 10,
"name": "ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip",
"bytes": 32971712,
"sha256": "d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1",
"url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/download/v0.2.0-preview.navigation.20260911/ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip"
},
{
"id": 11,
"name": "ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip.sha256",
"bytes": 144,
"sha256": "435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac",
"url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/download/v0.2.0-preview.navigation.20260911/ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip.sha256"
},
{
"id": 12,
"name": "VALIDATION.md",
"bytes": 6987,
"sha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2",
"url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/download/v0.2.0-preview.navigation.20260911/VALIDATION.md"
}
],
"url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/tag/v0.2.0-preview.navigation.20260911",
"publishedAt": "2026-09-12T10:52:54Z",
"releaseId": 4,
"draft": false,
"prerelease": true,
"finished": "2026-09-12T10:54:02.303380+00:00"
}
@@ -0,0 +1,15 @@
{
"started": "2026-09-12T10:49:06.593269+00:00",
"action": "tag",
"tag": "v0.2.0-preview.navigation.20260911",
"target": "802855f7e6f2f00a107a12196b458b267f586b8d",
"success": false,
"bindings": {
"notesSha256": "9361105c8bb9f939f0ea931edb107ad21acd7acdcc2d9424f0f0b20d62f980bd",
"validationSha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2",
"releaseId": null
},
"error": "Published source branch changed",
"remoteOutcome": "Inspect after any uncertain push; no force or automatic retry",
"finished": "2026-09-12T10:49:07.347988+00:00"
}
@@ -0,0 +1 @@
{"atUtc": "2026-09-12T10:52:34.108413+00:00", "step": "tag-push-started", "ref": "refs/tags/v0.2.0-preview.navigation.20260911", "target": "802855f7e6f2f00a107a12196b458b267f586b8d"}
@@ -0,0 +1,16 @@
{
"started": "2026-09-12T10:52:31.651088+00:00",
"action": "tag",
"tag": "v0.2.0-preview.navigation.20260911",
"target": "802855f7e6f2f00a107a12196b458b267f586b8d",
"success": true,
"bindings": {
"notesSha256": "9361105c8bb9f939f0ea931edb107ad21acd7acdcc2d9424f0f0b20d62f980bd",
"validationSha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2",
"releaseId": null
},
"before": "",
"after": "802855f7e6f2f00a107a12196b458b267f586b8d\trefs/tags/v0.2.0-preview.navigation.20260911",
"scope": "One nonforce exact tag; no local tag/branch/index or release mutation",
"finished": "2026-09-12T10:52:41.774830+00:00"
}
@@ -0,0 +1,6 @@
{"atUtc": "2026-09-12T10:53:04.341786+00:00", "step": "upload-request-started", "name": "ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip", "sha256": "d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1"}
{"atUtc": "2026-09-12T10:53:16.801573+00:00", "step": "uploaded-and-downloaded", "name": "ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip", "assetId": 10, "sha256": "d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1"}
{"atUtc": "2026-09-12T10:53:16.801573+00:00", "step": "upload-request-started", "name": "ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip.sha256", "sha256": "435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac"}
{"atUtc": "2026-09-12T10:53:17.274519+00:00", "step": "uploaded-and-downloaded", "name": "ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip.sha256", "assetId": 11, "sha256": "435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac"}
{"atUtc": "2026-09-12T10:53:17.274933+00:00", "step": "upload-request-started", "name": "VALIDATION.md", "sha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2"}
{"atUtc": "2026-09-12T10:53:17.736171+00:00", "step": "uploaded-and-downloaded", "name": "VALIDATION.md", "assetId": 12, "sha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2"}
@@ -0,0 +1,44 @@
{
"started": "2026-09-12T10:53:02.732676+00:00",
"action": "upload",
"tag": "v0.2.0-preview.navigation.20260911",
"target": "802855f7e6f2f00a107a12196b458b267f586b8d",
"success": true,
"bindings": {
"notesSha256": "9361105c8bb9f939f0ea931edb107ad21acd7acdcc2d9424f0f0b20d62f980bd",
"validationSha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2",
"releaseId": null
},
"assetHashes": {
"ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip": "d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1",
"ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip.sha256": "435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac",
"VALIDATION.md": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2"
},
"assets": [
{
"id": 10,
"name": "ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip",
"bytes": 32971712,
"sha256": "d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1",
"url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/download/v0.2.0-preview.navigation.20260911/ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip"
},
{
"id": 11,
"name": "ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip.sha256",
"bytes": 144,
"sha256": "435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac",
"url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/download/v0.2.0-preview.navigation.20260911/ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip.sha256"
},
{
"id": 12,
"name": "VALIDATION.md",
"bytes": 6987,
"sha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2",
"url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/download/v0.2.0-preview.navigation.20260911/VALIDATION.md"
}
],
"releaseId": 4,
"draft": true,
"prerelease": true,
"finished": "2026-09-12T10:53:30.861814+00:00"
}
@@ -0,0 +1,458 @@
{
"atUtc": "2026-09-12T10:50:09.871742+00:00",
"target": "802855f7e6f2f00a107a12196b458b267f586b8d",
"branchHead": "0c9ee1505774a0f64c5f3a58b0da64a4673d5000",
"branch": {
"name": "codex/navigation-repair-prerelease-source-20260911",
"commit": {
"id": "0c9ee1505774a0f64c5f3a58b0da64a4673d5000",
"message": "Sync agent instructions from main\n",
"url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/commit/0c9ee1505774a0f64c5f3a58b0da64a4673d5000",
"author": {
"name": "sorokin.oleg.edu",
"email": "sorokin.oleg.edu@gmail.com",
"username": "sorokin.oleg.edu"
},
"committer": {
"name": "sorokin.oleg.edu",
"email": "sorokin.oleg.edu@gmail.com",
"username": "sorokin.oleg.edu"
},
"verification": {
"verified": false,
"reason": "gpg.error.not_signed_commit",
"signature": "",
"signer": null,
"payload": ""
},
"timestamp": "2026-09-12T13:43:34+03:00",
"added": null,
"removed": null,
"modified": null
},
"protected": false,
"required_approvals": 0,
"enable_status_check": false,
"status_check_contexts": [],
"user_can_push": true,
"user_can_merge": true,
"effective_branch_protection_name": ""
},
"targetCommit": {
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/802855f7e6f2f00a107a12196b458b267f586b8d",
"sha": "802855f7e6f2f00a107a12196b458b267f586b8d",
"created": "2026-09-11T14:09:23-07:00",
"html_url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/commit/802855f7e6f2f00a107a12196b458b267f586b8d",
"commit": {
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/802855f7e6f2f00a107a12196b458b267f586b8d",
"author": {
"name": "Codex-9e8r6t",
"email": "codex-9e8r6t@local.invalid",
"date": "2026-09-11T14:09:23-07:00"
},
"committer": {
"name": "Codex-9e8r6t",
"email": "codex-9e8r6t@local.invalid",
"date": "2026-09-11T14:09:23-07:00"
},
"message": "Preserve exact navigation prerelease GUI inputs\n",
"tree": {
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/trees/802855f7e6f2f00a107a12196b458b267f586b8d",
"sha": "802855f7e6f2f00a107a12196b458b267f586b8d",
"created": "2026-09-11T14:09:23-07:00"
},
"verification": {
"verified": false,
"reason": "gpg.error.not_signed_commit",
"signature": "",
"signer": null,
"payload": ""
}
},
"author": null,
"committer": null,
"parents": [
{
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/33c6d83e9ba9a5b1310b1b627d7c40affcbcf15c",
"sha": "33c6d83e9ba9a5b1310b1b627d7c40affcbcf15c",
"created": "0001-01-01T00:00:00Z"
}
],
"files": [
{
"filename": ".gitattributes",
"status": "modified"
},
{
"filename": "crates/oa-desktop/src/behavior/creation.rs",
"status": "modified"
},
{
"filename": "crates/oa-desktop/src/behavior/scenario/workspace.rs",
"status": "modified"
},
{
"filename": "crates/oa-desktop/src/behavior/topology/contextual.rs",
"status": "modified"
},
{
"filename": "crates/oa-desktop/src/guide.rs",
"status": "modified"
},
{
"filename": "crates/oa-desktop/src/semantic_review/artifacts_view.rs",
"status": "modified"
},
{
"filename": "crates/oa-desktop/src/semantic_review/attachments_view.rs",
"status": "modified"
},
{
"filename": "crates/oa-desktop/src/semantic_review/keyed.rs",
"status": "modified"
},
{
"filename": "crates/oa-desktop/src/semantic_review/keyed_rows.rs",
"status": "modified"
},
{
"filename": "crates/oa-desktop/src/semantic_review/keyed_tests.rs",
"status": "modified"
},
{
"filename": "crates/oa-desktop/src/semantic_review/ordered.rs",
"status": "modified"
},
{
"filename": "docs/api.html",
"status": "modified"
},
{
"filename": "docs/api.rst",
"status": "modified"
},
{
"filename": "docs/language.html",
"status": "modified"
},
{
"filename": "docs/openapi.json",
"status": "modified"
},
{
"filename": "harness/fixtures/rest-coverage/coverage-probe.json",
"status": "modified"
}
],
"stats": {
"total": 47111,
"additions": 23564,
"deletions": 23547
}
},
"comparison": {
"total_commits": 3,
"commits": [
{
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/0c9ee1505774a0f64c5f3a58b0da64a4673d5000",
"sha": "0c9ee1505774a0f64c5f3a58b0da64a4673d5000",
"created": "2026-09-12T13:43:34+03:00",
"html_url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/commit/0c9ee1505774a0f64c5f3a58b0da64a4673d5000",
"commit": {
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/0c9ee1505774a0f64c5f3a58b0da64a4673d5000",
"author": {
"name": "sorokin.oleg.edu",
"email": "sorokin.oleg.edu@gmail.com",
"date": "2026-09-12T13:43:34+03:00"
},
"committer": {
"name": "sorokin.oleg.edu",
"email": "sorokin.oleg.edu@gmail.com",
"date": "2026-09-12T13:43:34+03:00"
},
"message": "Sync agent instructions from main\n",
"tree": {
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/trees/0c9ee1505774a0f64c5f3a58b0da64a4673d5000",
"sha": "0c9ee1505774a0f64c5f3a58b0da64a4673d5000",
"created": "2026-09-12T13:43:34+03:00"
},
"verification": {
"verified": false,
"reason": "gpg.error.not_signed_commit",
"signature": "",
"signer": null,
"payload": ""
}
},
"author": {
"id": 1,
"login": "sorokin.oleg.edu",
"login_name": "",
"source_id": 0,
"full_name": "",
"email": "1+sorokin.oleg.edu@noreply.localhost",
"avatar_url": "http://217.177.34.108:3000/avatars/e0b01a363497e41a43cfbbe954da533d",
"html_url": "http://217.177.34.108:3000/sorokin.oleg.edu",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2026-09-10T13:33:26Z",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "sorokin.oleg.edu"
},
"committer": {
"id": 1,
"login": "sorokin.oleg.edu",
"login_name": "",
"source_id": 0,
"full_name": "",
"email": "1+sorokin.oleg.edu@noreply.localhost",
"avatar_url": "http://217.177.34.108:3000/avatars/e0b01a363497e41a43cfbbe954da533d",
"html_url": "http://217.177.34.108:3000/sorokin.oleg.edu",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2026-09-10T13:33:26Z",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "sorokin.oleg.edu"
},
"parents": [
{
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/4d046ae5ee96d88f68e26d58038ee6fcb4854f42",
"sha": "4d046ae5ee96d88f68e26d58038ee6fcb4854f42",
"created": "0001-01-01T00:00:00Z"
}
],
"files": [
{
"filename": "AGENTS.md",
"status": "modified"
}
],
"stats": {
"total": 14,
"additions": 4,
"deletions": 10
}
},
{
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/4d046ae5ee96d88f68e26d58038ee6fcb4854f42",
"sha": "4d046ae5ee96d88f68e26d58038ee6fcb4854f42",
"created": "2026-09-12T13:40:17+03:00",
"html_url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/commit/4d046ae5ee96d88f68e26d58038ee6fcb4854f42",
"commit": {
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/4d046ae5ee96d88f68e26d58038ee6fcb4854f42",
"author": {
"name": "sorokin.oleg.edu",
"email": "sorokin.oleg.edu@gmail.com",
"date": "2026-09-12T13:40:17+03:00"
},
"committer": {
"name": "sorokin.oleg.edu",
"email": "sorokin.oleg.edu@gmail.com",
"date": "2026-09-12T13:40:17+03:00"
},
"message": "Sync agent instructions from main\n",
"tree": {
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/trees/4d046ae5ee96d88f68e26d58038ee6fcb4854f42",
"sha": "4d046ae5ee96d88f68e26d58038ee6fcb4854f42",
"created": "2026-09-12T13:40:17+03:00"
},
"verification": {
"verified": false,
"reason": "gpg.error.not_signed_commit",
"signature": "",
"signer": null,
"payload": ""
}
},
"author": {
"id": 1,
"login": "sorokin.oleg.edu",
"login_name": "",
"source_id": 0,
"full_name": "",
"email": "1+sorokin.oleg.edu@noreply.localhost",
"avatar_url": "http://217.177.34.108:3000/avatars/e0b01a363497e41a43cfbbe954da533d",
"html_url": "http://217.177.34.108:3000/sorokin.oleg.edu",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2026-09-10T13:33:26Z",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "sorokin.oleg.edu"
},
"committer": {
"id": 1,
"login": "sorokin.oleg.edu",
"login_name": "",
"source_id": 0,
"full_name": "",
"email": "1+sorokin.oleg.edu@noreply.localhost",
"avatar_url": "http://217.177.34.108:3000/avatars/e0b01a363497e41a43cfbbe954da533d",
"html_url": "http://217.177.34.108:3000/sorokin.oleg.edu",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2026-09-10T13:33:26Z",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "sorokin.oleg.edu"
},
"parents": [
{
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/0611926acf3ddc3c02759ca01482873520a329bd",
"sha": "0611926acf3ddc3c02759ca01482873520a329bd",
"created": "0001-01-01T00:00:00Z"
}
],
"files": [
{
"filename": "AGENTS.md",
"status": "modified"
}
],
"stats": {
"total": 10,
"additions": 9,
"deletions": 1
}
},
{
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/0611926acf3ddc3c02759ca01482873520a329bd",
"sha": "0611926acf3ddc3c02759ca01482873520a329bd",
"created": "2026-09-12T13:15:52+03:00",
"html_url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/commit/0611926acf3ddc3c02759ca01482873520a329bd",
"commit": {
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/0611926acf3ddc3c02759ca01482873520a329bd",
"author": {
"name": "sorokin.oleg.edu",
"email": "sorokin.oleg.edu@gmail.com",
"date": "2026-09-12T13:15:52+03:00"
},
"committer": {
"name": "sorokin.oleg.edu",
"email": "sorokin.oleg.edu@gmail.com",
"date": "2026-09-12T13:15:52+03:00"
},
"message": "Sync agent instructions from main\n",
"tree": {
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/trees/0611926acf3ddc3c02759ca01482873520a329bd",
"sha": "0611926acf3ddc3c02759ca01482873520a329bd",
"created": "2026-09-12T13:15:52+03:00"
},
"verification": {
"verified": false,
"reason": "gpg.error.not_signed_commit",
"signature": "",
"signer": null,
"payload": ""
}
},
"author": {
"id": 1,
"login": "sorokin.oleg.edu",
"login_name": "",
"source_id": 0,
"full_name": "",
"email": "1+sorokin.oleg.edu@noreply.localhost",
"avatar_url": "http://217.177.34.108:3000/avatars/e0b01a363497e41a43cfbbe954da533d",
"html_url": "http://217.177.34.108:3000/sorokin.oleg.edu",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2026-09-10T13:33:26Z",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "sorokin.oleg.edu"
},
"committer": {
"id": 1,
"login": "sorokin.oleg.edu",
"login_name": "",
"source_id": 0,
"full_name": "",
"email": "1+sorokin.oleg.edu@noreply.localhost",
"avatar_url": "http://217.177.34.108:3000/avatars/e0b01a363497e41a43cfbbe954da533d",
"html_url": "http://217.177.34.108:3000/sorokin.oleg.edu",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2026-09-10T13:33:26Z",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "sorokin.oleg.edu"
},
"parents": [
{
"url": "http://217.177.34.108:3000/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio/git/commits/802855f7e6f2f00a107a12196b458b267f586b8d",
"sha": "802855f7e6f2f00a107a12196b458b267f586b8d",
"created": "0001-01-01T00:00:00Z"
}
],
"files": [
{
"filename": "AGENTS.md",
"status": "modified"
}
],
"stats": {
"total": 14,
"additions": 10,
"deletions": 4
}
}
]
}
}
@@ -0,0 +1,29 @@
"""Compare every staged archive Git blob to its reviewed working file."""
import json
from pathlib import Path
import subprocess
import sys
ROOT = Path(__file__).resolve().parents[2]
for folder in sys.argv[1:]:
path = (ROOT / folder).resolve()
if not path.is_relative_to(ROOT / 'harness/experiments'):
raise RuntimeError('Expected a harness evidence archive')
relative = path.relative_to(ROOT).as_posix()
paths = subprocess.check_output(['git', 'ls-files', '-z', '--', relative], cwd=ROOT).decode().split('\0')[:-1]
actual = {p.relative_to(ROOT).as_posix() for p in path.rglob('*') if p.is_file()}
if not paths or set(paths) != actual:
raise RuntimeError('Staged file membership differs: ' + relative)
raw = subprocess.run(['git', 'cat-file', '--batch'], input=''.join(':' + p + '\n' for p in paths).encode(), capture_output=True, check=True, cwd=ROOT).stdout
cursor = total = 0
for item in paths:
end = raw.index(b'\n', cursor)
_, kind, size = raw[cursor:end].split()
length = int(size)
if kind != b'blob' or raw[end + 1:end + 1 + length] != (ROOT / item).read_bytes() or raw[end + 1 + length:end + 2 + length] != b'\n':
raise RuntimeError('Git blob differs: ' + item)
total += length
cursor = end + 2 + length
if cursor != len(raw):
raise RuntimeError('Unexpected batch data')
print(json.dumps({'archive': relative, 'rawGitBlobs': len(paths), 'bytes': total, 'allExact': True}))
@@ -0,0 +1,19 @@
# Corrected adapter and final-text consistency review
Codex-9e8r6t `/root/publication_review`, 2026-09-12. This follow-up preserves the original `REVIEW.md` and `review-bindings.json` unchanged. Root applied the code correction; this reviewer changed no publication script, release text, binding or adapter manifest. Static reading, in-memory text comparison and file hashing only; no helper execution/import, network or credential access.
## Original finding resolved
`publish.py` now has an explicit `if not __debug__: raise RuntimeError(...)` immediately after its module docstring and before imports. Optimized execution refuses before credentials, network, attempt receipts or publication operations. `push-tag.py` imports that module and inherits the refusal. Removing exactly the new guard block in memory reproduces the original reviewed SHA256 `e679a84845303db6582753b525bb3c2d184e6139e5651560fce8c876eae42c99`; no other byte change exists. The corrected file is bound in `followup-bindings.json`. The original P2 is resolved by static inspection, without claiming a runtime test.
## Final release text
No substantive inconsistency found in the reviewed `RELEASE-NOTES.md` or `VALIDATION.md` snapshots. They distinguish reconstructed raw desktop inputs, corrected build, earlier native scopes, this exact package trial, historical server provenance, development profile, server termination versus graceful drain, and incomplete application acceptance.
Compared with `harness/release-navigation-prerelease-review-20260911.md` and its archived `payload/README.md`: exact ZIP/binary identities, 559 files, 500 desktop inputs, 15 newline restorations, 755/0/1 desktop results, 6,002 artifact checks, 1,801 server checks, 266/263 notice inventory, historical server scope and full persistence match. The integrated navigation report confirms the earlier 30-file trial and subsequent corrected repair/rollback scopes.
Compared with `.local/navigation-repair-package-native-20260911/trial/`: launch records identify the independent package extraction and private profile; `checkpoints/navigation-final-saved/result.json` records oracle967 exit 0 after root-observed Save; 11 capture pairs preserve the reported workflow stages. `loaded-modules.json` records 126 modules and no unexpected paths. `closed-readonly-process.json` identifies the original creation filetime, no PID reuse, and queried exit code 0. `closed-readonly.json` reports PASS and complete unchanged package; `after-close-readonly-package.json` has 559 files, unchanged D722 ZIP and no added, removed or changed files. The original failed image-path query is preserved in `original-close-observation.json` without an invented Win32 error. This is consistency review of existing evidence, not independent reenactment or GUI acceptance.
Release notes and validation have no pending acceptance marker and are ready for root's exact hash binding. `bindings.json` remained null at this review. The native evidence report linked in validation was still being prepared by root and absent locally at readback; publish that report and its evidence before release visibility, then verify the published link. Remote link availability was not checked by this network-free review.
Readiness: corrected adapter and reviewed texts are ready for binding and the reserved sequential publication workflow. Remaining publication work belongs to root: final manifest/bindings, native record publication, current remote ownership checks and actual publication/readback. The original single-writer race limitation still applies; no new locking or atomicity claim is made.
@@ -0,0 +1,21 @@
# Independent static publication review
Reviewer: Codex-9e8r6t `/root/publication_review`, 2026-09-12. Root owns issue 6 and publication. Reviewed only the four files recorded in `review-bindings.json`; scripts were neither executed nor imported. No network, credentials, tag, release, upload, or reviewed-file mutation was performed. Files were read and hashed; this report is the only new review artifact alongside its bindings. Current remote state and final acceptance text were outside this review.
## Finding requiring a controlled execution decision
**P2 — Optimization removes the safety boundary.** `publish.py:113-124`, `129-147`, `152-161`, `188-238` and the corresponding tag-helper checks use Python `assert` for input acceptance, ownership, collision detection, and remote readback. With `python -O` or a nonzero `PYTHONOPTIMIZE`, these statements disappear. For example, final files can be present while both configured hashes remain null and `inputs()` still returns; `assert client.request(...) == raw` at line 221 also removes the download itself. The mutating sequence can consequently operate without the reviewed guards. The README's unconditional claim that unbound hashes refuse before network access does not hold for optimized execution.
Recommended small fix: reject `not __debug__` with an explicit `if`/`raise` at module initialization in `publish.py`, before any credential or network operation; the tag helper imports this module and inherits the rejection. Alternatively, root can explicitly enforce and record nonoptimized execution for every invocation, including absence of inherited `PYTHONOPTIMIZE`. No fix was made by this reviewer. Ordinary nonoptimized execution retains the reviewed checks.
## Static conclusions
- Final notes and validation are intentionally unbound in this snapshot. Under nonoptimized execution, mutation refuses before constructing `Client`; the exact pending markers are rejected, and both final texts must match independently entered SHA256 values. Semantic acceptance remains root's review responsibility.
- The source branch and existing tag must resolve to exact commit `802855f7e6f2f00a107a12196b458b267f586b8d`. The separate tag helper uses one explicit nonforce refspec and accepts annotated tags only at the exact peeled commit. A concurrent conflicting tag creation makes the normal push fail rather than replace it.
- Release enumeration checks the reserved tag including authenticated draft listings, with a fail-closed page bound. Existing release adoption requires an explicit bound ID or the exclusive successful-create receipt; a matching tag/title alone does not authorize mutation. Final title, body, prerelease status, tag and target must match.
- Exactly three named local assets are allowed. ZIP size/hash and checksum content/hash are fixed; validation bytes are hash-bound. Existing remote assets must have unique names/IDs, expected sizes, and identical downloaded bytes. Uploads are read back; publication downloads all three before visibility change and again afterwards, comparing IDs/names/sizes/hashes/URLs. No deletion or replacement endpoint exists.
- Lost create responses require inspected manual ID adoption; successful creation persists ownership before later readback. Lost upload responses can be reconciled by fresh byte verification. Already-public publication retries repeat the checks. Attempts have exclusive directories and report uncertain remote outcomes; no automatic retry, force push or rollback occurs.
- Credentials are read from the configured connection, used in memory/request headers and a child-process environment, and not explicitly written to helper files, git config or command arguments. API origin checks and redirect refusal limit forwarding; Git redirect following is disabled and inherited `GIT_` environment configuration is removed. This is a static data-flow conclusion, not dynamic fault-injection evidence. The pre-existing HTTP endpoint is unchanged.
- Race limitation: draft/assets/ownership checks and later writes are separate requests, and there is no shared lock or conditional server write. A second writer could publish during the upload loop or alter assets between the prepublication check and PATCH. Root's reserved, sequential single-executor workflow is therefore a necessary operating assumption. Postchecks detect many changes but cannot promise that incorrect state was never briefly public. This is not a request for broader locking infrastructure for this one-off operation.
Readiness: structurally suitable for the coordinated one-off publication after root binds and reviews the final two files, resolves the optimization guard decision, and verifies current remote ownership/tag state. This review does not claim publication, runtime validation, current Gitea state, final-note acceptance, or asset availability.
@@ -0,0 +1,16 @@
# Exact source-branch head adjustment review
Codex-9e8r6t `/root/publication_review`, 2026-09-12. Static review only; no helper execution/import, network, credential access, or publication-file mutation. Earlier review snapshots remain preserved.
**Accepted; no new blocking finding.** Root's first tag attempt refused at the source branch check. Its preserved `runs/tag-first-20260912/result.json` reports `success: false` and `Published source branch changed`; control-flow inspection places that failure before tag push. No successful push is inferred.
The supplied `source-advance-inspection.json` records exactly three single-parent commits from `0c9ee1505774a0f64c5f3a58b0da64a4673d5000` through `4d046ae5ee96d88f68e26d58038ee6fcb4854f42` and `0611926acf3ddc3c02759ca01482873520a329bd` to the original `802855f7e6f2f00a107a12196b458b267f586b8d`. Each intervening commit lists only modified `AGENTS.md`. The target API record still identifies the exact original target SHA. This is review of root's stored remote response, not an independent network readback.
The two preserved predecessor helpers match the hashes accepted in `FOLLOWUP.md`. In-memory exact text reconstruction verifies that the current changes consist only of:
- `publish.py` adds fixed `SOURCE_BRANCH_HEAD = 0c9ee...`, compares the branch with that head, and fetches `/git/commits/TARGET` with an exact returned SHA check.
- `push-tag.py` imports that new constant and uses it for its independent Git branch readback.
`TARGET` remains `802855...` for the tag target, nonforce push refspec, source commit, ownership receipts and release metadata. There is no generic descendant acceptance, source branch mutation, force push or implicit retargeting. Any further branch movement still refuses. The prior optimization guard remains intact. The immutable tagged input snapshot and package provenance therefore retain their previous scope.
The final notes and validation hashes are unchanged from the accepted text review. `bindings.json` now contains exactly those hashes with null release ID. The corrected helpers and exact input binding are ready for a fresh root-owned attempt under the previously reviewed sequential workflow. This does not claim that attempt ran or succeeded. The adapter README's original exact-source-branch wording is superseded for this execution by this scoped revision record: source branch head is `0c9ee...`, while the release tag remains `802855...`.
@@ -0,0 +1,17 @@
{
"reviewer": "Codex-9e8r6t /root/publication_review",
"reviewDate": "2026-09-12",
"originalFinding": "Resolved by early explicit non-assert optimization refusal; static verification only",
"method": "Read-only static text/evidence comparison and SHA256; no reviewed-script execution/import or network",
"files": [
{ "path": ".local/navigation-prerelease-publication-20260911/publish.py", "sha256": "a18a2d5e996d2d61975292be77f22a7a09725036a853a3bea86f8803b90a4ed5" },
{ "path": ".local/navigation-prerelease-publication-20260911/push-tag.py", "sha256": "e73e351fd6322e51e8cadc016cdf9a0650022cd0a9aba816019744abcafdf6de" },
{ "path": ".local/navigation-prerelease-publication-20260911/bindings.json", "sha256": "f9422e26fc54ed3fce87f7454ea0399d4a65ed2aa43e3dad0a0a07d97e63c3a2" },
{ "path": ".local/navigation-prerelease-publication-20260911/README.md", "sha256": "2548bafceb07d36f3b191cc40a7a003deb1c059ba53802a5f4d78b9e032ce420" },
{ "path": ".local/navigation-prerelease-publication-20260911/RELEASE-NOTES.md", "sha256": "9361105c8bb9f939f0ea931edb107ad21acd7acdcc2d9424f0f0b20d62f980bd" },
{ "path": ".local/navigation-prerelease-publication-20260911/VALIDATION.md", "sha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2" }
],
"finalTextsConsistentWithReviewedEvidence": true,
"actualPublicationHashesBound": false,
"remoteAvailabilityVerified": false
}
@@ -0,0 +1,26 @@
{
"reviewer": "Codex-9e8r6t /root/publication_review",
"reviewDate": "2026-09-12",
"method": "Static file reading and SHA256 only; no reviewed-script execution/import or network access",
"files": [
{
"path": ".local/navigation-prerelease-publication-20260911/publish.py",
"sha256": "e679a84845303db6582753b525bb3c2d184e6139e5651560fce8c876eae42c99"
},
{
"path": ".local/navigation-prerelease-publication-20260911/push-tag.py",
"sha256": "e73e351fd6322e51e8cadc016cdf9a0650022cd0a9aba816019744abcafdf6de"
},
{
"path": ".local/navigation-prerelease-publication-20260911/bindings.json",
"sha256": "f9422e26fc54ed3fce87f7454ea0399d4a65ed2aa43e3dad0a0a07d97e63c3a2"
},
{
"path": ".local/navigation-prerelease-publication-20260911/README.md",
"sha256": "2548bafceb07d36f3b191cc40a7a003deb1c059ba53802a5f4d78b9e032ce420"
}
],
"finalNotesBound": false,
"finalValidationBound": false,
"runtimeOrNetworkEvidenceProduced": false
}
@@ -0,0 +1,19 @@
{
"reviewer": "Codex-9e8r6t /root/publication_review",
"reviewDate": "2026-09-12",
"decision": "Accepted exact inspected branch-head adjustment; immutable release target unchanged",
"sourceBranchHead": "0c9ee1505774a0f64c5f3a58b0da64a4673d5000",
"target": "802855f7e6f2f00a107a12196b458b267f586b8d",
"exactIntendedTextDeltaVerified": true,
"files": [
{ "path": ".local/navigation-prerelease-publication-20260911/publish.py", "sha256": "2e2f5286b958479e27d113cf65036ca1bf3af4c2380a0985d82bfc2d793cabdd" },
{ "path": ".local/navigation-prerelease-publication-20260911/push-tag.py", "sha256": "5911ecb7924596918e59ab983952e7094b122dc21008b7913b4d1dc017683a27" },
{ "path": ".local/navigation-prerelease-publication-20260911/bindings.json", "sha256": "2a62d2da16aff59ecaa69942a00600c0f38e25392f1f2e38890f3cd089f7ffd8" },
{ "path": ".local/navigation-prerelease-publication-20260911/RELEASE-NOTES.md", "sha256": "9361105c8bb9f939f0ea931edb107ad21acd7acdcc2d9424f0f0b20d62f980bd" },
{ "path": ".local/navigation-prerelease-publication-20260911/VALIDATION.md", "sha256": "9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2" },
{ "path": ".local/navigation-prerelease-publication-20260911/source-advance-inspection.json", "sha256": "dc20d2eee4dedc310a3989fc377e99e915a5010c51995b1e968eecb3fac106c5" },
{ "path": ".local/navigation-prerelease-publication-20260911/before-source-advance/publish.py", "sha256": "a18a2d5e996d2d61975292be77f22a7a09725036a853a3bea86f8803b90a4ed5" },
{ "path": ".local/navigation-prerelease-publication-20260911/before-source-advance/push-tag.py", "sha256": "e73e351fd6322e51e8cadc016cdf9a0650022cd0a9aba816019744abcafdf6de" }
],
"runtimeOrNetworkEvidenceProduced": false
}
@@ -0,0 +1,252 @@
"""Root-executed, hash-bound draft/upload/publication. Import has no side effects."""
import argparse
from datetime import datetime, timezone
import hashlib
import json
from pathlib import Path
import re
import tomllib
import urllib.error
import urllib.parse
import urllib.request
import uuid
HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[1]
ORIGIN = 'http://217.177.34.108:3000'
API = ORIGIN + '/api/v1/repos/sorokin.oleg.edu/ARCADIA-Studio'
TAG = 'v0.2.0-preview.navigation.20260911'
TARGET = '802855f7e6f2f00a107a12196b458b267f586b8d'
BRANCH = 'codex/navigation-repair-prerelease-source-20260911'
TITLE = 'Source navigation — Windows development preview'
ZIP = 'ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip'
PACKAGE = ROOT / '.local/nav-repair-retry-20260911/packages'
ZIP_SHA = 'd7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1'
CHECKSUM_SHA = '435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac'
def now():
return datetime.now(timezone.utc).isoformat()
def digest(raw):
return hashlib.sha256(raw).hexdigest()
def read(path):
return json.loads(path.read_text(encoding='utf-8'))
def exclusive(path, value):
with path.open('x', encoding='utf-8', newline='\n') as stream:
json.dump(value, stream, indent=2, ensure_ascii=False)
stream.write('\n')
class Attempt:
def __init__(self, action, name):
assert re.fullmatch(r'[a-z0-9][a-z0-9-]{0,47}', name), 'Use a fresh simple attempt name'
self.path = HERE / 'runs' / (action + '-' + name)
self.path.mkdir(parents=True, exist_ok=False)
self.value = {'started': now(), 'action': action, 'tag': TAG, 'target': TARGET, 'success': False}
def event(self, step, **fields):
event = {'atUtc': now(), 'step': step, **fields}
with (self.path / 'events.jsonl').open('a', encoding='utf-8', newline='\n') as stream:
stream.write(json.dumps(event, ensure_ascii=False) + '\n')
def finish(self):
self.value['finished'] = now()
exclusive(self.path / 'result.json', self.value)
print(json.dumps(self.value, ensure_ascii=False), flush=True)
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
raise RuntimeError('Unexpected redirect; authorization not forwarded')
class Client:
def __init__(self):
config = tomllib.loads((Path.home() / '.codex/config.toml').read_text(encoding='utf-8'))
self.token = config['mcp_servers']['gitea']['env']['GITEA_ACCESS_TOKEN']
self.opener = urllib.request.build_opener(urllib.request.ProxyHandler({}), NoRedirect)
def redact(self, text):
return text.replace(self.token, '[redacted]')
def request(self, url, data=None, method=None, headers=None, binary=False, missing=False):
parsed = urllib.parse.urlsplit(url)
expected = urllib.parse.urlsplit(ORIGIN)
assert (parsed.scheme, parsed.netloc) == (expected.scheme, expected.netloc)
assert parsed.username is None and parsed.password is None
request = urllib.request.Request(url, data=data, method=method,
headers={'Authorization': 'token ' + self.token, **(headers or {})})
try:
with self.opener.open(request, timeout=120) as response:
body = response.read()
return body if binary else json.loads(body)
except urllib.error.HTTPError as error:
detail = self.redact(error.read(2000).decode('utf-8', 'replace'))
if missing and error.code == 404:
return None
raise RuntimeError(f'HTTP {error.code}: {detail}') from None
def json(self, url, value, method):
return self.request(url, json.dumps(value).encode('utf-8'), method,
{'Content-Type': 'application/json'})
def release(self):
# Listing authenticated drafts catches a reserved-tag collision even
# before a server has made its Git tag visible to the by-tag endpoint.
matches = []
for page in range(1, 21):
items = self.request(API + f'/releases?limit=50&page={page}')
assert isinstance(items, list)
matches.extend(item for item in items if item['tag_name'] == TAG)
if len(items) < 50:
break
else:
raise RuntimeError('Release collision scan exceeded its bound')
assert len(matches) <= 1, 'Multiple releases claim the reserved tag'
return matches[0] if matches else None
def tag(self):
return self.request(API + '/tags/' + urllib.parse.quote(TAG, safe=''), missing=True)
def inputs():
bindings = read(HERE / 'bindings.json')
for key in ('notesSha256', 'validationSha256'):
assert isinstance(bindings[key], str) and re.fullmatch(r'[0-9a-f]{64}', bindings[key]), 'Final notes and VALIDATION hashes must be reviewed and bound first'
notes = (HERE / 'RELEASE-NOTES.md').read_bytes()
validation = (HERE / 'VALIDATION.md').read_bytes()
assert digest(notes) == bindings['notesSha256']
assert digest(validation) == bindings['validationSha256']
for raw in (notes, validation):
text = raw.decode('utf-8')
assert all(marker not in text for marker in ('PUBLICATION-PENDING', 'PACKAGE-RUNTIME-ACCEPTANCE-PENDING'))
assets = {ZIP: (PACKAGE / ZIP).read_bytes(), ZIP + '.sha256': (PACKAGE / (ZIP + '.sha256')).read_bytes(), 'VALIDATION.md': validation}
assert len(assets[ZIP]) == 32971712 and digest(assets[ZIP]) == ZIP_SHA
assert digest(assets[ZIP + '.sha256']) == CHECKSUM_SHA
assert assets[ZIP + '.sha256'].decode('utf-8').strip() == ZIP_SHA + ' ' + ZIP
return bindings, notes.decode('utf-8'), assets
def source_and_tag(client, require_tag=True):
branch = client.request(API + '/branches/' + urllib.parse.quote(BRANCH, safe=''))
assert branch['commit']['id'] == TARGET, 'Published source branch changed'
tag = client.tag()
if tag is None:
assert not require_tag, 'Run the separately reviewed nonforce tag helper first'
else:
assert tag['name'] == TAG and tag['commit']['sha'] == TARGET, 'Tag collision'
return tag
def owned_release(value, bindings, notes):
expected_id = bindings.get('releaseId')
state = HERE / 'release-created.json'
if state.exists():
saved = read(state)
assert saved['tag'] == TAG and saved['target'] == TARGET
assert expected_id in (None, saved['releaseId'])
expected_id = saved['releaseId']
assert expected_id is not None and value['id'] == expected_id, 'Existing release is not bound to this run; inspect and review before setting releaseId'
assert value['tag_name'] == TAG and value['target_commitish'] == TARGET
assert value['prerelease'] is True and value['name'] == TITLE and value['body'] == notes
def verify_assets(client, release_id, assets, allow_missing=False):
remote = client.request(API + f'/releases/{release_id}/assets')
names = [item['name'] for item in remote]
assert len(names) == len(set(names)) and len({a['id'] for a in remote}) == len(remote)
assert set(names) <= set(assets)
if not allow_missing:
assert set(names) == set(assets), 'Exactly three assets required'
verified = []
for item in remote:
expected = assets[item['name']]
assert item['size'] == len(expected)
received = client.request(item['browser_download_url'], binary=True)
assert received == expected, 'Existing asset bytes differ; no overwrite or deletion permitted'
verified.append({'id': item['id'], 'name': item['name'], 'bytes': len(received), 'sha256': digest(received), 'url': item['browser_download_url']})
return verified
def main():
parser = argparse.ArgumentParser()
parser.add_argument('action', choices=('inspect', 'create', 'upload', 'publish'))
parser.add_argument('--attempt', required=True)
args = parser.parse_args()
attempt = Attempt(args.action, args.attempt)
client = None
try:
if args.action == 'inspect':
client = Client()
release, tag = client.release(), client.tag()
attempt.value.update(success=True, release=release, remoteTag=tag,
scope='Read-only inspection; no acceptance or mutation')
return
bindings, notes, assets = inputs()
attempt.value['bindings'] = bindings
attempt.value['assetHashes'] = {name: digest(raw) for name, raw in assets.items()}
client = Client()
source_and_tag(client)
release = client.release()
if args.action == 'create':
if release is not None:
owned_release(release, bindings, notes)
assert release['draft'] is True
attempt.event('existing-owned-draft', releaseId=release['id'])
else:
assert not (HERE / 'release-created.json').exists() and bindings.get('releaseId') is None
attempt.event('create-request-started')
release = client.json(API + '/releases', {'tag_name': TAG, 'target_commitish': TARGET,
'name': TITLE, 'body': notes, 'draft': True, 'prerelease': True}, 'POST')
assert release['tag_name'] == TAG and release['target_commitish'] == TARGET and release['draft'] is True
# Persist ownership immediately; a failed readback can be retried safely.
exclusive(HERE / 'release-created.json', {'releaseId': release['id'], 'tag': TAG, 'target': TARGET, 'atUtc': now()})
attempt.event('created-draft', releaseId=release['id'])
fresh = client.release()
owned_release(fresh, bindings, notes)
assert fresh['draft'] is True
verify_assets(client, fresh['id'], assets, allow_missing=True)
else:
assert release is not None, 'Create the hash-bound draft first'
owned_release(release, bindings, notes)
endpoint = API + f'/releases/{release["id"]}'
if args.action == 'upload':
assert release['draft'] is True, 'Never upload into a public release'
existing = verify_assets(client, release['id'], assets, allow_missing=True)
for name, raw in assets.items():
if any(item['name'] == name for item in existing):
attempt.event('existing-asset-verified', name=name, sha256=digest(raw))
continue
boundary = 'ArcadiaNavigation' + uuid.uuid4().hex
prefix = (f'--{boundary}\r\nContent-Disposition: form-data; name="attachment"; filename="{name}"\r\nContent-Type: application/octet-stream\r\n\r\n').encode()
attempt.event('upload-request-started', name=name, sha256=digest(raw))
result = client.request(endpoint + '/assets?' + urllib.parse.urlencode({'name': name}),
prefix + raw + f'\r\n--{boundary}--\r\n'.encode(), 'POST',
{'Content-Type': 'multipart/form-data; boundary=' + boundary})
assert result['name'] == name and result['size'] == len(raw)
assert client.request(result['browser_download_url'], binary=True) == raw
attempt.event('uploaded-and-downloaded', name=name, assetId=result['id'], sha256=digest(raw))
attempt.value['assets'] = verify_assets(client, release['id'], assets)
else:
# Download all three afresh immediately before changing visibility.
before = verify_assets(client, release['id'], assets)
source_and_tag(client)
fresh = client.release()
owned_release(fresh, bindings, notes)
if fresh['draft']:
attempt.event('publish-request-started', releaseId=fresh['id'])
client.json(endpoint, {'draft': False, 'prerelease': True, 'body': notes}, 'PATCH')
final = client.release()
owned_release(final, bindings, notes)
assert final['draft'] is False
source_and_tag(client)
after = verify_assets(client, final['id'], assets)
assert sorted(before, key=lambda x: x['id']) == sorted(after, key=lambda x: x['id'])
attempt.value.update(assets=after, url=final['html_url'], publishedAt=final['published_at'])
fresh = client.release()
owned_release(fresh, bindings, notes)
attempt.value.update(success=True, releaseId=fresh['id'], draft=fresh['draft'], prerelease=True)
except BaseException as error:
message = str(error)
attempt.value['error'] = client.redact(message) if client else message
attempt.value['remoteOutcome'] = 'May be partial if a request started; inspect before retry. No automatic overwrite/delete.'
raise
finally:
attempt.finish()
if __name__ == '__main__':
main()
@@ -0,0 +1,50 @@
"""Read only archive bytes and recorded receipt relationships; never publish."""
from pathlib import Path
import hashlib
import json
BASE = Path(__file__).resolve().parent
def sha(p):
return hashlib.sha256(p.read_bytes()).hexdigest()
def read(p):
return json.loads((BASE/p).read_text(encoding='utf-8'))
def check(ok, label):
if not ok:
raise SystemExit('FAIL: '+label)
manifest = read('MANIFEST.json')
check({p.relative_to(BASE).as_posix() for p in BASE.rglob('*') if p.is_file()} - {'MANIFEST.json'} == {r['path'] for r in manifest['files']}, 'file set')
for r in manifest['files']:
p = BASE/r['path']
check(p.resolve().is_relative_to(BASE) and p.stat().st_size == r['bytes'] and sha(p) == r['sha256'], r['path'])
check(sha(BASE/'ORIGINALS.json') == '1c6eedd5a7c0937eda5961db48d1107fd4b005d47c026936d248b7aa1d86a300', 'original whitelist pin')
originals = read('ORIGINALS.json')['files']
check(len(originals) == 34, 'original count')
for r in originals:
check(sha(BASE/r['path']) == r['sha256'] and (BASE/r['path']).stat().st_size == r['bytes'], 'original '+r['path'])
p = 'payload/publication/'
target = '802855f7e6f2f00a107a12196b458b267f586b8d'
tag = 'v0.2.0-preview.navigation.20260911'
bindings = read(p+'bindings.json')
check(sha(BASE/p/'RELEASE-NOTES.md') == bindings['notesSha256'], 'notes binding')
check(sha(BASE/p/'VALIDATION.md') == bindings['validationSha256'], 'validation binding')
failed = read(p+'runs/tag-first-20260912/result.json')
check(failed['success'] is False and failed['error'] == 'Published source branch changed', 'failed first preflight')
for attempt in ['tag-inspected-source-20260912','create-first-20260912','upload-first-20260912','publish-first-20260912']:
r = read(p+'runs/'+attempt+'/result.json')
check(r['success'] is True and r['target'] == target and r['tag'] == tag, attempt)
upload = read(p+'runs/upload-first-20260912/result.json')
published = read(p+'runs/publish-first-20260912/result.json')
check(published['releaseId'] == read(p+'release-created.json')['releaseId'] == 4 and published['draft'] is False and published['prerelease'] is True, 'published prerelease ownership')
check(upload['assets'] == published['assets'] and len(published['assets']) == 3, 'asset consistency')
expected = [(10,32971712,'d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1'),(11,144,'435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac'),(12,6987,'9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2')]
check([(a['id'],a['bytes'],a['sha256']) for a in published['assets']] == expected, 'asset pins')
check(published['finished'] == '2026-09-12T10:54:02.303380+00:00', 'terminal publication time')
raw = (BASE/p/'before-source-advance/publish.py').read_bytes()
guard = b"if not __debug__:\n raise RuntimeError('Publication requires Python assertions; optimized execution is refused.')\n\n"
check(raw.count(guard) == 1, 'exact reconstruction guard')
reconstructed = BASE/'reconstructed/original-reviewed-publish.py'
check(reconstructed.read_bytes() == raw.replace(guard,b'',1) and sha(reconstructed) == 'e679a84845303db6582753b525bb3c2d184e6139e5651560fce8c876eae42c99', 'byte-proved reconstruction')
check('SOURCE_BRANCH_HEAD = ' in (BASE/p/'publish.py').read_text(encoding='utf-8') and '0c9ee1505774a0f64c5f3a58b0da64a4673d5000' in (BASE/p/'publish.py').read_text(encoding='utf-8'), 'separate source branch pin')
check(read(p+'acceptance-records-push-result.json')['target'] == 'f5e1c734dadd6e0203288065dac7b2e3f140cacf' and read(p+'acceptance-records-push-result.json')['success'], 'acceptance record push')
print('PASS publication archive: 34 originals; exact reconstructed initial adapter; failed preflight retained; tag/release 4/three asset receipt relationships. No network or runtime work rerun.')
@@ -0,0 +1,47 @@
# Published navigation Windows prerelease
[v0.2.0-preview.navigation.20260911](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/tag/v0.2.0-preview.navigation.20260911) is published as Gitea release 4 with `draft: false`, `prerelease: true`. Root's actual publish command ended successfully; final metadata, exact tag target and all three asset downloads passed at **2026-09-12 10:54:02.303380 UTC**. The publish PATCH began at 10:53:54.264100 UTC. The API's `publishedAt: 10:52:54Z` is the draft-creation timestamp and is not evidence of public visibility at that earlier time.
This is a bounded Windows development milestone, not final application acceptance. The [published validation](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/download/v0.2.0-preview.navigation.20260911/VALIDATION.md) gives launch instructions, provenance, verification and known limitations; its exact bytes are also [archived](experiments/navigation-prerelease-publication-20260912/payload/publication/VALIDATION.md).
## Download and launch
Download the [Windows ZIP](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/download/v0.2.0-preview.navigation.20260911/ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip) and [checksum](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/releases/download/v0.2.0-preview.navigation.20260911/ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm.zip.sha256). Extract the complete ZIP into a writable folder and run `arcadia-studio.exe`, retaining `libunwind.dll` beside the executables. No Rust compiler or machine PATH change was required in the tested Windows runtime. Home and Engineering guide provide offline help. Copy all of `examples/release1` into a working area before opening its `project.arcadia`; keep its supporting evidence files.
Optional server from PowerShell in the extracted folder:
```powershell
.\arcadia-server.exe --bind 127.0.0.1:8080 --data-dir "$env:LOCALAPPDATA\ArcadiaStudio\server-data"
```
Consult `docs/server.md` and `docs/openapi.json` for server use. Cargo/Docker builds require the source checkout, not only the binary ZIP; `docs/windows-packaging.md` records build prerequisites. The binary uses the recorded development profile; optimized or reproducible binary output is not claimed.
## Exact published bytes and provenance
| Asset ID | Asset | Bytes | SHA256 |
| --- | --- | ---: | --- |
| 10 | Windows ZIP | 32,971,712 | `d7228c542f162663933ea002739a78c722bcca41e437df63b7c868ea2af201f1` |
| 11 | ZIP.sha256 | 144 | `435b6fff3fbc1640b4db31c5d848dbcde101aa54cc86fe0eef9c8da6a501ccac` |
| 12 | VALIDATION.md | 6,987 | `9abcb45e665e2bf553a6ef91f1e73fd403d7c9552b01962d0d9713cf52660ff2` |
The 559-file package contains B183…8848 Studio, historical EFEE…E665 server and F456…E7D4 DLL. The tag points exactly to [802855f7e6f2f00a107a12196b458b267f586b8d](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/src/commit/802855f7e6f2f00a107a12196b458b267f586b8d), the reconstruction of all 500 raw desktop build inputs, including 15 measured newline restorations. The actual build captured `eeeaa126` plus the repair delta later committed as `33c6d83`; reconstruction is not the original build commit. The server retains its separately verified September 7 provenance and was not rebuilt from this tag. [Producer evidence](release-navigation-prerelease-preparation-20260911.md) and [independent review](release-navigation-prerelease-review-20260911.md) give exact binary hashes and source relationships.
## Publication sequence and retained failure
The initial tag preflight at 10:49:06–07 UTC refused because the published source branch moved. It did not reach tag push. Root's stored inspection found exactly three single-parent commits modifying only `AGENTS.md`, with inspected branch head `0c9ee1505774a0f64c5f3a58b0da64a4673d5000`. The independently reviewed adjustment pins that exact branch head separately from the unchanged `802855…` tag target, rather than accepting arbitrary descendants or moving source. [Source-advance review](experiments/navigation-prerelease-publication-20260912/payload/review/SOURCE-ADVANCE.md) preserves the evidence and narrow correction.
Root published acceptance records at `f5e1c734dadd6e0203288065dac7b2e3f140cacf` before release visibility and reports exact remote Git blob readback of both native and independent reports. The archived acceptance push receipt independently records the successful branch push; the blob readback is attributed to root's tool observation rather than invented as a separate raw receipt.
The fresh nonforce tag attempt passed at 10:52:41 UTC. Root created owned draft release 4, uploaded assets 10/11/12 and downloaded each for exact byte verification, finishing at 10:53:30 UTC. Publication downloaded and verified all assets again before changing visibility, then rechecked final metadata/tag/assets/download hashes. The terminal receipt at 10:54:02 UTC records success with the same three asset identities and public prerelease state. No foreign release adoption, replacement asset, forced tag or silent version substitution occurred in this sequence. Later fresh MCP metadata readback, shared records and integration are root-owned and are not claimed by this archive.
## Accepted scope and limitations
The corrected desktop gates recorded 755 passing tests, zero failed, one ignored, strict all-target Clippy, formatting and a matching development build. Independent artifact review passed 6,002 checks; packaged server review passed 1,801 checks including exact Unicode project persistence across restart. Server processes were explicitly terminated after acknowledged persistence (Windows exit 1); graceful drain and comprehensive API editing were not tested.
[Packaged native acceptance](release-navigation-prerelease-native-20260911.md) records real Windows Open of the four-source Unicode fixture, offline guide, F12, one lexical reference excluding prose/comments, Back, dirty/stale feedback, Undo, Apply and explicit Save. Exact model, identities, four reachable sources and four disk files matched. All 126 modules were under Windows or package paths. The original closure helper failed without capturing the Win32 error; a separate query established the same process creation exited with code 0 and unchanged ZIP/full package map. The original failure remains distinct. This package trial used a 1440×900 client and did not repeat the earlier minimum-size, 30-file engineering or corrected repair/rollback trials linked in [integrated navigation evidence](release-text-navigation-integrated-20260911.md).
Text alias rename is not implemented. Newer peer canvas/lifecycle work, full quantities/calculations/constraints, maintained model libraries, comprehensive OA/SA graphical/text/REST parity, remaining engineering workflows and final independent application review are not accepted by this release. Linux/WSL setup, diagnostics, builds and checks remain paused by the user.
## Preserved publication evidence
[Archive](experiments/navigation-prerelease-publication-20260912/README.md) preserves 34 original files (103,111 bytes), exact final notes/validation/bindings, initial historical adapter manifest/README, predecessor helpers, three static review stages, source inspection and failed/successful attempt records. An explicitly labeled reconstruction reproduces the initial reviewed E679…2C99 adapter hash; it is not represented as a retained original execution snapshot. The read-only archive verifier checks hashes and receipt relationships without importing publication code or accessing network, credentials, applications or original packages. No runtime, server, package or GUI tests were repeated during archival.
@@ -124,7 +124,11 @@ at `33c6d83` passed all 755 desktop tests, strict Clippy and matching GUI B183.
Its [native recheck](release-text-repair-save-native-v4-20260911.md) passed both
invalid-source repairs and actual interrupted-save rollback, with retained
unsaved state, Close/Cancel protection and three exact final saved-model/source
comparisons. Package acceptance remains separate. All raw inputs and failed
comparisons. The separate [packaged native trial](release-navigation-prerelease-native-20260911.md)
and [independent archive/server review](release-navigation-prerelease-review-20260911.md)
also passed. The [navigation Windows prerelease](release-navigation-prerelease-published-20260912.md)
was delivered on September 12, with exact tag/source and all three downloaded
asset readbacks. All raw inputs and failed
attempts retain their original scopes.
- [Component and prepared fixture archive](experiments/text-navigation-components-20260911/README.md)
@@ -138,8 +142,8 @@ ambiguous and missing-include repair cases, and the 30-reachable-file release1
engineering walkthrough. The existing pinned oracle compares the complete saved
Project, identities, reachable SourceBundle and physical Arcadia files; it does
not export full-model JSON. Preparation passes establish fixture integrity only.
Actual newly built GUI interaction, final saved-oracle comparison and packaged
delivery require their own recorded results.
Actual GUI interaction, final saved-oracle comparisons and packaged delivery
are recorded in the subsequent native and publication reports linked above.
The published contextual preview remains unchanged. Its separately built EFEE
server retains its earlier provenance; it must not be described as built from