Record Text workspace publication and exact Git readback

This commit is contained in:
2026-09-12 22:05:07 -07:00
parent 2df7f580aa
commit b4b860f277
7 changed files with 3334 additions and 0 deletions
@@ -0,0 +1,27 @@
{
"scope": "All four experiment manifests and every referenced payload equal staged Git blobs and working originals, including ignored raw logs explicitly staged.",
"files": 617,
"archives": [
{
"path": "harness/experiments/text-find-selection-20260913",
"payloads": 25,
"manifestSha256": "4580d8cbc2f0347f1ebc1448728af6ef8885f6ebbd4c2d2dbe0c41eac97fb283"
},
{
"path": "harness/experiments/text-workspace-initial-20260913",
"payloads": 106,
"manifestSha256": "991d54095f5466b717aefde99682e0c7d3136091bdf5525d8f21c0629d3cb0a4"
},
{
"path": "harness/experiments/text-workspace-native2-20260913",
"payloads": 367,
"manifestSha256": "3ddabcf26828afe2aee882bdfbac26d0f3e6003e6c22f1575bb5bfdf12dcb01a"
},
{
"path": "harness/experiments/text-workspace-native3-20260913",
"payloads": 115,
"manifestSha256": "07c765910f3d7bda3e298b32f6a12feb578214c61c241b0ac0cebc6c46e28db8"
}
],
"gitTree": "06c902ae05241729c3db7fe7b05be5df054d9506"
}
@@ -0,0 +1,37 @@
{
"atUtc": "2026-09-13T05:02:47.529317+00:00",
"commit": "2df7f580aa4bd728a728c83ac10e6ccc956ef069",
"scope": "Exact selected committed source/evidence bytes downloaded from Gitea; complete source and evidence membership are separately verified against the committed Git tree.",
"files": [
{
"path": "crates/oa-desktop/src/app.rs",
"bytes": 223370,
"sha256": "4f4c1bb5f832601a072b5cd406a75731982e8b9955ee6af39a93f124496938f9"
},
{
"path": "crates/oa-desktop/src/app/source_symbols.rs",
"bytes": 21421,
"sha256": "d81914a553114d85452d973a1edb175843d27154b3f9b9fc4cbc5049d423abe4"
},
{
"path": "harness/text-workspace-verified-20260913.md",
"bytes": 9473,
"sha256": "6db2995be4ee411599c654899b23182a027136cdd60b803e4c08417323b45d44"
},
{
"path": "harness/experiments/text-workspace-native3-20260913/manifest.json",
"bytes": 24309,
"sha256": "07c765910f3d7bda3e298b32f6a12feb578214c61c241b0ac0cebc6c46e28db8"
},
{
"path": "harness/experiments/text-workspace-native3-20260913/attempt-6/inputs.zip",
"bytes": 2198569,
"sha256": "960c2ebeab73af1fbf593268e4dc1687011588da86d808e039a6fd28658ec347"
},
{
"path": "harness/experiments/text-workspace-native3-20260913/attempt-6/tests-stdout.log",
"bytes": 98579,
"sha256": "6cf95c3bf0fd8efcbf753ab7788a02be461fab8b6621aa924e64e47f260097d4"
}
]
}
@@ -0,0 +1,26 @@
"""Read back selected published source/evidence bytes from the exact Gitea commit."""
from pathlib import Path
from datetime import datetime, timezone
import hashlib
import json
import subprocess
import urllib.request
ROOT = Path('C:/ar-text-9e8r6t')
COMMIT = '2df7f580aa4bd728a728c83ac10e6ccc956ef069'
BASE = 'http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/raw/commit/' + COMMIT + '/'
FILES = ['crates/oa-desktop/src/app.rs', 'crates/oa-desktop/src/app/source_symbols.rs', 'harness/text-workspace-verified-20260913.md', 'harness/experiments/text-workspace-native3-20260913/manifest.json', 'harness/experiments/text-workspace-native3-20260913/attempt-6/inputs.zip', 'harness/experiments/text-workspace-native3-20260913/attempt-6/tests-stdout.log']
records = []
for name in FILES:
expected = subprocess.check_output(['git', 'show', COMMIT + ':' + name], cwd=ROOT)
with urllib.request.urlopen(BASE + name, timeout=45) as response:
raw = response.read()
assert response.status == 200
assert raw == expected, 'Published content differs: ' + name
records.append({'path': name, 'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()})
result = {'atUtc': datetime.now(timezone.utc).isoformat(), 'commit': COMMIT, 'scope': 'Exact selected committed source/evidence bytes downloaded from Gitea; complete source and evidence membership are separately verified against the committed Git tree.', 'files': records}
dest = Path(__file__).resolve().parent / 'publication-readback.json'
with dest.open('x', encoding='utf-8', newline='\n') as out:
json.dump(result, out, indent=2)
out.write('\n')
print(json.dumps(result))
@@ -0,0 +1,41 @@
"""Require every manifest-bound evidence payload to survive the Git index."""
from pathlib import Path
import hashlib
import json
import subprocess
import sys
ROOT = Path('C:/ar-text-9e8r6t')
SETS = ['text-find-selection-20260913', 'text-workspace-initial-20260913', 'text-workspace-native2-20260913', 'text-workspace-native3-20260913']
expected = {}
sets = []
for label in SETS:
base = 'harness/experiments/' + label
manifest_path = ROOT / base / 'manifest.json'
raw = manifest_path.read_bytes()
manifest = json.loads(raw)
rows = manifest['files']
sets.append({'path': base, 'payloads': len(rows), 'manifestSha256': hashlib.sha256(raw).hexdigest()})
expected[base + '/manifest.json'] = {'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()}
for row in rows:
name = base + '/' + row['path']
assert name not in expected
expected[name] = row
names = sorted(expected)
raw = subprocess.check_output(['git', 'cat-file', '--batch'], input=''.join(':' + name + '\n' for name in names).encode(), cwd=ROOT)
offset = 0
for name in names:
end = raw.index(b'\n', offset)
header = raw[offset:end].split()
assert len(header) == 3 and header[1] == b'blob', ('Missing staged payload', name, header)
size = int(header[2])
blob = raw[end + 1:end + 1 + size]
offset = end + size + 2
assert size == expected[name]['bytes'] and hashlib.sha256(blob).hexdigest() == expected[name]['sha256'], ('Staged archive payload differs', name)
assert blob == (ROOT / name).read_bytes(), ('Working archive differs', name)
assert offset == len(raw)
receipt = {'scope': 'All four experiment manifests and every referenced payload equal staged Git blobs and working originals, including ignored raw logs explicitly staged.', 'files': len(names), 'archives': sets, 'gitTree': subprocess.check_output(['git', 'write-tree'], cwd=ROOT).decode().strip()}
with Path(sys.argv[1]).open('x', encoding='utf-8', newline='\n') as out:
json.dump(receipt, out, indent=2)
out.write('\n')
print(json.dumps(receipt))
@@ -0,0 +1,38 @@
"""Verify the staged source and all staged changes against measured working bytes."""
from pathlib import Path
import hashlib
import json
import subprocess
import sys
ROOT = Path('C:/ar-text-9e8r6t')
SCOPES = ['Cargo.toml', 'Cargo.lock', 'crates', 'build', '.cargo', 'docs', 'examples', 'harness/fixtures']
capture = json.loads((ROOT / '.local/text-workspace-gates-20260912/attempt-6/inputs.json').read_text(encoding='utf-8'))
source_names = subprocess.check_output(['git', 'ls-files', '-z', '--cached', '--', *SCOPES], cwd=ROOT).split(b'\0')
source_names = sorted(set(name.decode() for name in source_names if name))
assert source_names == [row['path'] for row in capture['files']]
changed = subprocess.check_output(['git', 'diff', '--cached', '--name-only', '-z'], cwd=ROOT).split(b'\0')
names = sorted(set(source_names) | {name.decode() for name in changed if name})
payload = ''.join(':' + name + '\n' for name in names).encode()
raw = subprocess.check_output(['git', 'cat-file', '--batch'], input=payload, cwd=ROOT)
offset = 0
source_expected = {row['path']: row for row in capture['files']}
verified = []
for name in names:
end = raw.index(b'\n', offset)
header = raw[offset:end].split()
assert len(header) == 3 and header[1] == b'blob', (name, header)
size = int(header[2])
blob = raw[end + 1:end + 1 + size]
offset = end + size + 2
digest = hashlib.sha256(blob).hexdigest()
assert blob == (ROOT / name).read_bytes(), 'Index differs from working bytes: ' + name
if name in source_expected:
assert size == source_expected[name]['bytes'] and digest == source_expected[name]['sha256'], 'Index differs from tested source: ' + name
verified.append({'path': name, 'bytes': size, 'sha256': digest, 'gitBlob': header[0].decode()})
assert offset == len(raw)
output = Path(sys.argv[1])
with output.open('x', encoding='utf-8', newline='\n') as stream:
json.dump({'scope': 'Precommit index bytes equal tested source plus all staged working changes; no new runtime execution.', 'sourceArchiveSha256': capture['archiveSha256'], 'testedSourceFiles': len(source_names), 'verified': verified}, stream, indent=2)
stream.write('\n')
print(json.dumps({'sourceFiles': len(source_names), 'allVerifiedFiles': len(verified), 'receipt': str(output)}))
@@ -2,6 +2,8 @@
The Text workspace now keeps editing space available, puts References/Problems/Status in a compact supporting drawer, and retains source selection through Find, Back and file return. Successive Escapes dismiss Actions, Find and the drawer separately. This is the bounded contribution for [issue 13](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/13), based on `cbc49a7802fb1bba0dd284fd904c700a0703ae70`. Combined integration and packaging belong to [issue 27](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/27); this report does not accept that union or the full OA/SA release.
Published code/evidence snapshot: **[2df7f580aa4bd728a728c83ac10e6ccc956ef069](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/commit/2df7f580aa4bd728a728c83ac10e6ccc956ef069)** on `codex/text-workspace-9e8r6t`. All [526 committed source inputs](experiments/text-workspace-followup-review-20260913/source-commit-verification.json) match the tested capture. All [617 manifest/payload files](experiments/text-workspace-followup-review-20260913/archived-index-verification.json) match Git tree `06c902ae05241729c3db7fe7b05be5df054d9506`; 80 raw logs excluded by the default ignore rule were explicitly included before publication. [Direct Gitea readback](experiments/text-workspace-followup-review-20260913/publication-readback.json) on September 13 at 05:02:47 UTC matched the exact published App/focus source, report, input ZIP, native manifest and full-test log. Later publication-record documentation does not change that tested code snapshot.
## Behavior and design
The [interaction contract](text-workspace-interaction-contract-20260912.md) owns the precise layout, authority and lifecycle rules. Five permanent sibling slots keep the actual sensor/highlighter/editor in place. Supporting information is available on demand; opening Find or changing a drawer does not rebuild editor content. Grouped references retain full paths, query context and scroll. Stale data remains readable but cannot authorize a source jump. Diagnostic and reference actions bind their original publication and drawer visit; mounted input guards consume a release after its pressed row has been replaced or hidden.