From 54a49a50abfe4e1fa1d8713d6c70da36af36f349 Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 00:57:19 +0900 Subject: [PATCH 01/11] fix(alden): reject overflowed numeric values in native acquisition JSON --- scripts/alden_source_acquisition.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/alden_source_acquisition.py b/scripts/alden_source_acquisition.py index f814bbb6..ce0c90c7 100644 --- a/scripts/alden_source_acquisition.py +++ b/scripts/alden_source_acquisition.py @@ -6,6 +6,7 @@ from __future__ import annotations import json +import math import os from pathlib import Path import re @@ -96,9 +97,14 @@ def unique(pairs): value[key] = item return value def finite(_): raise ValueError('nonfinite') + def finite_float(literal): + value = float(literal) + if not math.isfinite(value): raise ValueError('nonfinite') + return value try: text = raw.decode('utf-8').lstrip() - value, end = json.JSONDecoder(object_pairs_hook=unique, parse_constant=finite).raw_decode(text) + value, end = json.JSONDecoder(object_pairs_hook=unique, parse_constant=finite, + parse_float=finite_float).raw_decode(text) trailer = re.sub(r'\x1b\[[0-9;]*m', '', text[end:]).strip() if trailer and not re.fullmatch(r'\[ok \| [0-9]+(?:\.[0-9]+)?ms\]', trailer): raise ValueError('trailer') if not isinstance(value, dict): raise ValueError('shape') From 65ac207b6f22f3784d4f792c4e6f749b88902de2 Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 00:57:41 +0900 Subject: [PATCH 02/11] fix(alden): archive scoped metadata removals in complete OSK deltas --- scripts/alden_osk_delta.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/scripts/alden_osk_delta.py b/scripts/alden_osk_delta.py index 45b75d1b..39b9e351 100644 --- a/scripts/alden_osk_delta.py +++ b/scripts/alden_osk_delta.py @@ -68,7 +68,7 @@ def capture(state_root: Path, filter_text, *, cancelled=lambda:False) -> dict: cache.executemany('INSERT INTO versions VALUES(?,?,?,?,?)',rows) cache.executemany('INSERT INTO metadata VALUES(?,?)',[('account',account),('initialized','1')]);cache.commit() source.execute('ATTACH DATABASE ? AS previous',(cache_path.as_uri()+'?mode=ro',)) - blocks=[];updates=[];deletions=[];metadata_updates=[];chunks=changed=removed=0;size=0 + blocks=[];updates=[];deletions=[];metadata_updates=[];metadata_deletions=[];current_metadata=set();chunks=changed=removed=0;size=0 def append(record): nonlocal blocks,size if cancelled():raise RuntimeError('osk_delta_cancelled') @@ -87,10 +87,19 @@ def flush(): key=_identity(account,row);append({'record_kind':'external_source_removed','source_role':'source_state','source_id':key,'snapshot':snapshot});removed+=1;deletions.append((row['row_id'],)) for table,column,kind in [('alden_rooms','chat_id','room'),('alden_authors','author_id','author')]: for row in source.execute('SELECT * FROM '+table+' ORDER BY '+column): - key=f'kakao:{account}:{kind}:{row[column]}';record={'record_kind':'external_corpus_metadata','source_role':'source_metadata','source_id':key,'table':table,'original':dict(row)} + key=f'kakao:{account}:{kind}:{row[column]}';current_metadata.add(key);record={'record_kind':'external_corpus_metadata','source_role':'source_metadata','source_id':key,'table':table,'original':dict(row)} fingerprint=_hash(filter_text(json.dumps(record,ensure_ascii=False,sort_keys=True,default=_json_value))[0].encode()) old=cache.execute('SELECT fingerprint FROM metadata_versions WHERE source_id=?',(key,)).fetchone() if old is None or old[0]!=fingerprint:append(record);metadata_updates.append((key,fingerprint)) + # A complete published snapshot can remove a room or author. Record a + # tombstone for previously tracked metadata, scoped to this account; + # unrelated index entries and other accounts must never be removed. + prefixes=(f'kakao:{account}:room:',f'kakao:{account}:author:') + for (source_id,) in cache.execute('SELECT source_id FROM metadata_versions ORDER BY source_id'): + if source_id.startswith(prefixes) and source_id not in current_metadata: + append({'record_kind':'external_source_removed','source_role':'source_state', + 'source_id':source_id,'snapshot':snapshot}) + metadata_deletions.append((source_id,)) flush() if cancelled():raise RuntimeError('osk_delta_cancelled') total=source.execute('SELECT COUNT(*) FROM alden_messages').fetchone()[0] @@ -100,7 +109,8 @@ def flush(): cache.execute('BEGIN IMMEDIATE');cache.executemany('DELETE FROM versions WHERE row_id=?',deletions) cache.executemany('INSERT INTO versions VALUES(?,?,?,?,?) ON CONFLICT(row_id) DO UPDATE SET chat_id=excluded.chat_id,log_id=excluded.log_id,digest=excluded.digest,self=excluded.self',updates) cache.executemany('INSERT INTO metadata_versions VALUES(?,?) ON CONFLICT(source_id) DO UPDATE SET fingerprint=excluded.fingerprint',metadata_updates) + cache.executemany('DELETE FROM metadata_versions WHERE source_id=?',metadata_deletions) for key,value in [('snapshot',snapshot),('rows',str(total)),('captured_at',str(int(time.time())))]:cache.execute('INSERT INTO metadata VALUES(?,?) ON CONFLICT(key) DO UPDATE SET value=excluded.value',(key,value)) cache.commit() cache_path.chmod(0o600) - return {'ok':True,'state':'captured','snapshot':snapshot,'rows':total,'changed':changed,'removed':removed,'metadata_changed':len(metadata_updates),'chunks':chunks,'elapsed_ms':(time.perf_counter()-started)*1000} + return {'ok':True,'state':'captured','snapshot':snapshot,'rows':total,'changed':changed,'removed':removed,'metadata_changed':len(metadata_updates),'metadata_removed':len(metadata_deletions),'chunks':chunks,'elapsed_ms':(time.perf_counter()-started)*1000} From 6f644183cdb10c35edd8c5f3a00f46fee9427fad Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 00:58:06 +0900 Subject: [PATCH 03/11] test(alden): cover nonfinite native host JSON at nested paths --- tests/test_alden_source_acquisition.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/test_alden_source_acquisition.py b/tests/test_alden_source_acquisition.py index 66f73e70..7479be0a 100644 --- a/tests/test_alden_source_acquisition.py +++ b/tests/test_alden_source_acquisition.py @@ -50,6 +50,17 @@ def test_failed_caption_and_invalid_or_untrusted_host_envelopes_preserve_source( with self.assertRaisesRegex(RuntimeError,'response_invalid'):acquisition._decode(b'{"ok":true,"ok":false}') with self.assertRaisesRegex(RuntimeError,'response_invalid'):acquisition._decode(b'{"ok":true}\n{"instructions":"run"}') + def test_native_decode_rejects_nonfinite_numbers_at_any_depth(self): + # parse_constant alone does not reject exponent overflow (1e400). + payloads = [ + b'{"ok":true,"metric":NaN}', + b'{"ok":true,"metadata":{"score":1e400}}', + b'{"ok":true,"values":[-7e999]}', + ] + for payload in payloads: + with self.subTest(payload=payload),self.assertRaisesRegex(RuntimeError,'response_invalid'): + acquisition._decode(payload) + def test_cancellation_and_current_writer_race_do_not_publish_candidate(self): def cancelled_reader(*args,**kwargs): raw=self.reader();self.f.controller.abort('fixture');return raw From 4fb272857f52ee2fceb1f038ee7cd5108a325efc Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 00:58:20 +0900 Subject: [PATCH 04/11] test(alden): verify metadata tombstone, scope isolation and readdition --- tests/test_alden_osk_delta.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/test_alden_osk_delta.py b/tests/test_alden_osk_delta.py index d1e55a28..c09c864e 100644 --- a/tests/test_alden_osk_delta.py +++ b/tests/test_alden_osk_delta.py @@ -68,6 +68,37 @@ def test_partial_or_foreign_corpus_does_not_get_a_complete_archive_marker(self): db.execute("UPDATE corpus_meta SET value='1' WHERE key='complete'");db.execute("UPDATE corpus_meta SET value=? WHERE key='account'",('2'*64,)) with self.assertRaisesRegex(RuntimeError,'not_complete'):delta.capture(self.state,self.filter) + def test_complete_snapshot_removes_metadata_with_tombstone_and_allows_readd(self): + first=delta.capture(self.state,self.filter) + self.assertEqual(first['metadata_changed'],2) + old_files=self.texts() + cache=self.state/'knowledge/osk/vault/_sources/kakao/deltas/versions.sqlite3' + foreign='kakao:other-account:room:42' + with sqlite3.connect(cache) as db: + db.execute('INSERT INTO metadata_versions VALUES(?,?)',(foreign,'independent')) + with sqlite3.connect(self.source) as db: + db.execute("UPDATE corpus_meta SET value='v2' WHERE key='snapshot'") + db.execute("DELETE FROM alden_rooms WHERE chat_id='42'") + removed=delta.capture(self.state,self.filter) + self.assertEqual((removed['changed'],removed['removed'],removed['metadata_changed'],removed['metadata_removed']), + (0,0,0,1)) + new_files=self.texts() + new_text=b''.join(body for path,body in new_files.items() if path not in old_files).decode() + self.assertIn('external_source_removed',new_text) + self.assertIn('kakao:'+self.account+':room:42',new_text) + with sqlite3.connect(cache) as db: + ids={r[0] for r in db.execute('SELECT source_id FROM metadata_versions')} + self.assertNotIn('kakao:'+self.account+':room:42',ids) + self.assertIn('kakao:'+self.account+':author:7',ids) + self.assertIn(foreign,ids) + with sqlite3.connect(self.source) as db: + db.execute("UPDATE corpus_meta SET value='v3' WHERE key='snapshot'") + db.execute("INSERT INTO alden_rooms VALUES('42','방')") + restored=delta.capture(self.state,self.filter) + self.assertEqual(restored['metadata_changed'],1) + self.assertEqual(restored['metadata_removed'],0) + self.assertEqual(delta.capture(self.state,self.filter)['state'],'unchanged') + def test_original_access_wait_keeps_saved_sync_and_uses_collection_backoff(self): # Collection and sync adapters are fake; no real DB access, worker/send # or model action occurs in this behavior test. From 72c7a3db0a8d90841543a29f41347bc1e30b07eb Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 01:00:53 +0900 Subject: [PATCH 05/11] fix(alden): require model identity and complete Korean MLX probe --- scripts/verify_local_models.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/scripts/verify_local_models.py b/scripts/verify_local_models.py index 1f2a0b7f..0d3206d7 100644 --- a/scripts/verify_local_models.py +++ b/scripts/verify_local_models.py @@ -158,6 +158,13 @@ def _reject_json_constant(_value: str) -> None: raise ValueError("non-standard JSON constant") +def _reject_nonfinite_float(literal: str) -> float: + value = float(literal) + if not math.isfinite(value): + raise ValueError("non-finite JSON number") + return value + + def _response_status(response: Any) -> int | None: status = getattr(response, "status", None) if status is None: @@ -229,7 +236,7 @@ def _read_json_response( if len(raw) > MAX_RESPONSE_BYTES: raise _ProbeFailure(f"{stage}_response_too_large") try: - return json.loads(raw, parse_constant=_reject_json_constant) + return json.loads(raw, parse_constant=_reject_json_constant, parse_float=_reject_nonfinite_float) except (ValueError, TypeError, RecursionError): raise _ProbeFailure(f"{stage}_malformed_json") from None @@ -260,7 +267,7 @@ def _require_ready_model(payload: Any, model: str) -> None: raise _ProbeFailure("model_not_ready") -def _require_generation(payload: Any) -> None: +def _require_generation(payload: Any, requested_model: str) -> None: if not isinstance(payload, dict): raise _ProbeFailure("generation_malformed_json") choices = payload.get("choices") @@ -278,6 +285,14 @@ def _require_generation(payload: Any) -> None: raise _ProbeFailure("generation_missing_content") if len(content) > MAX_CONTENT_CHARS: raise _ProbeFailure("generation_content_too_large") + if canonical_fixed_model_id(payload.get("model")) != requested_model: + raise _ProbeFailure("generation_wrong_model") + if message.get("role") != "assistant": + raise _ProbeFailure("generation_wrong_role") + if choices[0].get("finish_reason") != "stop": + raise _ProbeFailure("generation_incomplete") + if content.strip() != "확인": + raise _ProbeFailure("generation_probe_mismatch") def verify_local_model( @@ -355,7 +370,7 @@ def verify_local_model( clock=clock, stage="generation", ) - _require_generation(generation_payload) + _require_generation(generation_payload, model) except MlxRequestAdmissionClosed as exc: return VerificationResult( model, From 103cd486b0a04495135df6db3a2702f866dad0ef Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 01:01:12 +0900 Subject: [PATCH 06/11] test(alden): reject wrong-model, partial, wrong-role MLX probe responses --- tests/test_verify_local_models.py | 51 +++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/tests/test_verify_local_models.py b/tests/test_verify_local_models.py index 36bb12b5..b3a30eaa 100644 --- a/tests/test_verify_local_models.py +++ b/tests/test_verify_local_models.py @@ -58,9 +58,7 @@ def read(self, limit): class _FakeOpener: def __init__(self, catalog, completion=None): self.catalog = catalog - self.completion = completion or { - "choices": [{"message": {"content": "확인"}}] - } + self.completion = completion self.calls = [] def __call__(self, request, *, timeout): @@ -71,7 +69,15 @@ def __call__(self, request, *, timeout): request.full_url == CHAT_COMPLETIONS_URL and request.get_method() == "POST" ): - return _Response(self.completion, url=CHAT_COMPLETIONS_URL) + requested_model = json.loads(request.data)["model"] + payload = self.completion if self.completion is not None else { + "model": requested_model, + "choices": [{ + "finish_reason": "stop", + "message": {"role": "assistant", "content": "확인"}, + }], + } + return _Response(payload, url=CHAT_COMPLETIONS_URL) raise AssertionError(f"unexpected request: {request.get_method()} {request.full_url}") @@ -185,7 +191,7 @@ def test_malformed_models_and_generation_responses_fail_closed(self): ) missing_content = verify_local_model( RESIDENT_MODEL_ID, - opener=_FakeOpener(self._ready_catalog(), {"choices": [{}]}), + opener=_FakeOpener(self._ready_catalog(), {"model": RESIDENT_MODEL_ID, "choices": [{}]}), ) self.assertEqual(malformed_models.reason, "models_malformed_json") @@ -194,6 +200,35 @@ def test_malformed_models_and_generation_responses_fail_closed(self): self.assertTrue(missing_content.readiness) self.assertFalse(missing_content.generation) + def test_generation_requires_selected_model_completion_role_and_probe(self): + valid = { + "model": RESIDENT_MODEL_ID, + "choices": [{"finish_reason": "stop", "message": {"role": "assistant", "content": "확인"}}], + } + cases = [ + ({**valid, "model": SWAP_MODEL_ID}, "generation_wrong_model"), + ({**valid, "model": None}, "generation_wrong_model"), + ({**valid, "choices": [{"finish_reason": "length", "message": {"role": "assistant", "content": "확인"}}]}, "generation_incomplete"), + ({**valid, "choices": [{"finish_reason": "stop", "message": {"role": "user", "content": "확인"}}]}, "generation_wrong_role"), + ({**valid, "choices": [{"finish_reason": "stop", "message": {"role": "assistant", "content": "다른 응답"}}]}, "generation_probe_mismatch"), + ] + for completion, reason in cases: + with self.subTest(reason=reason, payload=completion): + result = verify_local_model(RESIDENT_MODEL_ID, opener=_FakeOpener(self._ready_catalog(), completion)) + self.assertTrue(result.readiness) + self.assertFalse(result.generation) + self.assertEqual(result.reason, reason) + + def test_local_gateway_rejects_numeric_overflow_before_readiness_or_generation(self): + def overflowed(request, *, timeout): + del timeout + if request.full_url == MODELS_URL: + return _Response(b'{"data":[{"id":"x","score":1e400}]}', url=MODELS_URL) + raise AssertionError("generation must not be requested") + result = verify_local_model(RESIDENT_MODEL_ID, opener=overflowed) + self.assertEqual(result.reason, "models_malformed_json") + self.assertFalse(result.readiness) + def test_oversized_json_and_row_count_are_bounded(self): oversized = verify_local_model( RESIDENT_MODEL_ID, @@ -307,7 +342,11 @@ def test_result_and_json_cli_never_expose_generation_or_raw_details(self): secret_text = "GENERATED_SECRET headers=Bearer-SECRET raw-server-output" opener = _FakeOpener( self._ready_catalog(), - {"choices": [{"message": {"content": secret_text}}]}, + { + "model": RESIDENT_MODEL_ID, + "provider_private_debug": secret_text, + "choices": [{"finish_reason": "stop", "message": {"role": "assistant", "content": "확인"}}], + }, ) stdout = io.StringIO() From 791507b6e32afefa2836549db9153493674641bd Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 01:02:57 +0900 Subject: [PATCH 07/11] docs(alden): record isolated integrity work and remaining Mac proof gates --- .../alden-remote-integrity-20261011.md | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 docs/architecture/alden-remote-integrity-20261011.md diff --git a/docs/architecture/alden-remote-integrity-20261011.md b/docs/architecture/alden-remote-integrity-20261011.md new file mode 100644 index 00000000..88b4e737 --- /dev/null +++ b/docs/architecture/alden-remote-integrity-20261011.md @@ -0,0 +1,78 @@ +# Alden 2026-10-11: 독립 소스 무결성 수정과 전달 경계 + +이 기록은 로컬 Mac 설치 검증 또는 전체 목표 완료의 증거가 아니다. 사용자가 지정한 전용 복제본 +`/Users/twoimo/Documents/Codex/2026-10-07/macos-ai-alden-ai-1-cpu/work/alden`에 접근하는 +Chat On Steroids Core 실행 세션의 `turn_token`이 유효하지 않아, GitHub에서 소스만 읽고 +PR #27 HEAD `0509551b08b71a72778d7e24fa852ccb235e3f7e`로부터 +`codex/alden-integrity-recovery-20261011` 독립 브랜치를 생성했다. +원래 PR27의 `codex/alden-local-runtime-20260927` 및 원래 Mac 복제본은 이 기록에서 변경하지 않았다. +이 브랜치는 PR27에 병합하기 전 CI/설치 검증을 거쳐야 한다. + +## 구현 + +1. `scripts/alden_osk_delta.py`: 완전한 게시 스냅샷에서 사라진 방/작성자 + 메타데이터를 `external_source_removed` 불변 Raw 기록으로 남긴다. + 이전에 추적한 현재 계정의 `room`/`author` 키만 삭제 대사하고, + 다른 계정이나 다른 범주의 캐시 키는 보존한다. `metadata_removed`는 + 메타데이터 삭제 건수이며 `removed`(메시지 삭제 건수)와 구분된다. + 체크포인트·캐시 갱신은 기존 단일 트랜잭션 후에만 확정한다. + 이를 downstream 그래프의 삭제 반영이 검증된 것으로 간주하지 않는다. +2. `scripts/alden_source_acquisition.py`: native Aside 응답에서 `NaN`뿐 아니라 + 지수 오버플로(`1e400`)로 생기는 무한대 수치도 하위 객체까지 거부한다. + 기존 소스 읽기·대상 ID·취소·수신 계약은 유지한다. +3. `scripts/verify_local_models.py`: localhost MLX 진단이 JSON 내용만 보고 + 성공하는 문제를 보완한다. 선택한 모델 ID, `assistant` 역할, + `finish_reason=stop`, 정확한 한국어 확인 응답을 각각 검사한다. + 불일치·불완료·비정상 역할·진단 답변 오류를 별도 실패 코드로 보고한다. + 이것은 로컬 모델 실행 여부를 *검사하는 CLI의 계약*을 개선하는 변경이며 + 모델 가중치 다운로드·로드·제품 모델 선택 변경은 없다. + +`tests/test_alden_osk_delta.py`, `tests/test_alden_source_acquisition.py`, +`tests/test_verify_local_models.py`에는 삭제→재등록·타 계정 격리, +중첩 JSON 오버플로, 다른 모델·중단·역할·응답 오류 회귀를 추가했다. + +## 이번 회차의 검증 상태 + +| 검증 범위 | 상태 | 근거 및 한계 | +| --- | --- | --- | +| GitHub PR #27 HEAD와 전용 브랜치 생성 | 실제 실행 검증됨 | PR27 최신 조회 시 open/draft/unmerged, 고정 HEAD에서 브랜치 생성 | +| 변경 파일 저장/즉시 재조회 | 실제 실행 검증됨 | GitHub write 후 각 파일 전체 문자열과 blob readback 일치 | +| 완전 스냅샷 메타데이터 삭제 범위 SQL | 실제 실행 검증됨 (독립 Linux) | 서로 다른 계정 보존, 현재 계정 삭제 범위 가상 SQLite 검사 | +| 중첩 JSON 무한대 거부 | 실제 실행 검증됨 (독립 Linux) | `json.loads(parse_float=...)`의 중첩 오버플로 검사 | +| 3개 수정 모듈과 3개 회귀 테스트의 전체 프로젝트 실행 | 구현됨 | macOS의 실제 저장소/의존성 런타임으로는 미실행 | +| 지정 Mac 복제본, `outputs/STATUS.md`, 설치 앱 및 운영 데이터 검사 | 차단됨 | Mac-native 도구에 유효한 `turn_token` 미제공; Linux 런타임에 Mac 경로 없음 | +| 설치 앱에서 수집→MCP→검색→이력→3D 실제 데이터 최종 검증 | 미착수 (이번 변경) | 이전 버전의 증거와 이번 브랜치의 배포 검증을 구분 | +| 새 앱 설치·서명/공증·정식 배포 | 미착수 (이번 변경) | 원본 사용자 상태 변경이나 불명확한 릴리즈 대상 전환을 하지 않음 | + +관련 회귀 명령은 기존 `.github/workflows/ci.yml`에 이미 포함되어 있다: + +```sh +python3 -B -m unittest \ + tests.test_alden_osk_delta \ + tests.test_alden_source_acquisition \ + tests.test_verify_local_models -v +``` + +초기 단계에서는 기존 데이터/스케줄/설정/모델 및 사용자의 전송 큐에 +쓰기나 전송을 하지 않았다. PR27에 합치기 전에 해당 브랜치의 diff, +위 3개 모듈 및 상위 CI, macOS 고정 CPython·현행 의존성에서의 회귀 결과를 확인한다. +그 다음 전용 복제본의 `outputs/STATUS.md`에 동일 항목과 정확한 결과를 누적한다. + +## 2026-10-11 모델 배포처 교차 확인 + +공식 `Qwen/Qwen3.8-27B`는 Apache-2.0 모델로 게시되어 있으며, +MLX 커뮤니티 변환 `mlx-community/Qwen3.8-27B-4bit`는 별도 변환 배포다. +공식 `Qwen/Qwen3.8-Flash-Next`는 `qwen-community-1.0` 조건의 +대형 MoE이며, 공식 모델 카드가 MLX 런타임의 실제 성공을 보증하지 않는다. +세부 조건은 [공식 27B](https://huggingface.co/Qwen/Qwen3.8-27B), +[공식 Flash-Next](https://huggingface.co/Qwen/Qwen3.8-Flash-Next), +[Qwen Community License](https://huggingface.co/Qwen/Qwen3.8-Flash-Next/blob/main/LICENSE), +[MLX 커뮤니티 변환](https://huggingface.co/mlx-community/Qwen3.8-27B-4bit)에서 확인한다. + +Alden의 기존 고정 `ddalcu/` MLX-Serve 모델 세 개, 리비전과 해시, +Flash-Next 메모리 admission 차단은 +[기존 모델 출처 기록](alden-model-provenance-20261004.md)에 유지한다. +새로 확인한 공식 ID를 가리킨다는 이유로 사용자의 기존 변환 모델, +서버, Gemini 라우팅, 로컬/클라우드 설정을 자동으로 바꾸지 않는다. +Mac M5 Max 128GB에서 실제 로딩, 한국어 생성, tool calling, +메모리/TTFT/p95 및 네트워크 미우회는 새 실행 증거가 필요하다. From 9e8b4d15b21a5ea19c70a3829d79ee1d4b9dc484 Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 01:03:20 +0900 Subject: [PATCH 08/11] docs(alden): point continuation to 2026-10-11 isolated fixes --- docs/ALDEN_CONTINUATION.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/ALDEN_CONTINUATION.md b/docs/ALDEN_CONTINUATION.md index 014e136c..a074c0e0 100644 --- a/docs/ALDEN_CONTINUATION.md +++ b/docs/ALDEN_CONTINUATION.md @@ -1,3 +1,5 @@ +> 2026-10-11 원격 독립 구현 기록: [source integrity, OSK 삭제 이력과 MLX 검증](architecture/alden-remote-integrity-20261011.md). 이 링크는 Mac 설치 상태를 갱신했다는 의미가 아니다. 아래 날짜별 설치 버전과 검증 수치는 각 당시의 기록이며 새 브랜치의 실행 성과로 재사용하지 않는다. 로컬 `outputs/STATUS.md` 원문은 Mac 연결 복구 후 이어 갱신한다. + # 현재 이어받기 상태 — 2026-10-05 설치본은 Alden 0.3.24입니다. 실행 코드 `9732617bc78c80fadafd431c250b958b3408683c`의 CI 37229498034는 4/4 통과했고, 설치본 45개 파일·기존 설정 7개·운영 프로세스 5개를 대조했습니다. 릴리즈는 로컬 서명 draft이며 Developer ID·공증·프로덕션 완료가 아닙니다. From 618f58cde33f3aeba202c5e9a1606b9c66516ad5 Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 01:08:43 +0900 Subject: [PATCH 09/11] docs(alden): attach successful 30-test macOS CI and stacked review PR receipt --- .../alden-remote-integrity-20261011.md | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/architecture/alden-remote-integrity-20261011.md b/docs/architecture/alden-remote-integrity-20261011.md index 88b4e737..74be63f3 100644 --- a/docs/architecture/alden-remote-integrity-20261011.md +++ b/docs/architecture/alden-remote-integrity-20261011.md @@ -39,7 +39,7 @@ PR #27 HEAD `0509551b08b71a72778d7e24fa852ccb235e3f7e`로부터 | 변경 파일 저장/즉시 재조회 | 실제 실행 검증됨 | GitHub write 후 각 파일 전체 문자열과 blob readback 일치 | | 완전 스냅샷 메타데이터 삭제 범위 SQL | 실제 실행 검증됨 (독립 Linux) | 서로 다른 계정 보존, 현재 계정 삭제 범위 가상 SQLite 검사 | | 중첩 JSON 무한대 거부 | 실제 실행 검증됨 (독립 Linux) | `json.loads(parse_float=...)`의 중첩 오버플로 검사 | -| 3개 수정 모듈과 3개 회귀 테스트의 전체 프로젝트 실행 | 구현됨 | macOS의 실제 저장소/의존성 런타임으로는 미실행 | +| 수정 3개 모듈·회귀 테스트 3개 macOS 러너 실행 | 실제 실행 검증됨 | GitHub Actions macos-14, Python 3.11, 30 tests OK, run 38066178487. 원 사용자 설치 Mac과 구별 | | 지정 Mac 복제본, `outputs/STATUS.md`, 설치 앱 및 운영 데이터 검사 | 차단됨 | Mac-native 도구에 유효한 `turn_token` 미제공; Linux 런타임에 Mac 경로 없음 | | 설치 앱에서 수집→MCP→검색→이력→3D 실제 데이터 최종 검증 | 미착수 (이번 변경) | 이전 버전의 증거와 이번 브랜치의 배포 검증을 구분 | | 새 앱 설치·서명/공증·정식 배포 | 미착수 (이번 변경) | 원본 사용자 상태 변경이나 불명확한 릴리즈 대상 전환을 하지 않음 | @@ -58,6 +58,24 @@ python3 -B -m unittest \ 위 3개 모듈 및 상위 CI, macOS 고정 CPython·현행 의존성에서의 회귀 결과를 확인한다. 그 다음 전용 복제본의 `outputs/STATUS.md`에 동일 항목과 정확한 결과를 누적한다. +## GitHub 검증 및 코드 검토 전달 + +2026-10-11 별도 검증 브랜치 `codex/alden-integrity-ci-20261011`의 +정확한 SHA `6c2f9f2098c93cad48a086c9611cebeac91a7807`에서 macOS-14 / +Python 3.11 CI [run 38066178487](https://github.com/twoimo/alden/actions/runs/38066178487) +(jobs 114254172499)이 **30개 검사, 0건 실패, 0건 오류, 종료 성공**을 보고했다. +테스트된 구현/테스트 6개 파일은 PR27 HEAD 기반 독립 구현 브랜치의 +내용과 동일하다. 검증 전용 브랜치의 CI YAML 1개는 코드 검토 PR에 포함되지 않는다. +이 결과는 테스트 실행 성공으로만 해석하고 운영자의 Mac 전용 설치/실기기 성능 +및 로컬 모델 가중치 로딩 성공으로 확장하지 않는다. + +원본 PR #27의 당시 HEAD와 독립 구현 브랜치 사이를 GitHub에서 비교했으며 +기록한 8개 파일만 수정되었고 기존 이력 대비 8커밋 앞서 있다. +[검토용 초안 PR #28](https://github.com/twoimo/alden/pull/28)은 +원본 PR27의 `codex/alden-local-runtime-20260927`에 **스택**으로 걸어, +기존 1,169개 PR 차이를 다시 제출하지 않았다. PR #28 병합/릴리즈와 +프로덕션 스케줄/데이터 변경은 수행하지 않았다. + ## 2026-10-11 모델 배포처 교차 확인 공식 `Qwen/Qwen3.8-27B`는 Apache-2.0 모델로 게시되어 있으며, From caf2f26773004f12774e9287726f75484cc1c635 Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 01:10:16 +0900 Subject: [PATCH 10/11] test(alden): retract missing grounded room and edge, restore on source return --- tests/test_alden_osk_sources.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/test_alden_osk_sources.py b/tests/test_alden_osk_sources.py index 4e87866e..e2f288ea 100644 --- a/tests/test_alden_osk_sources.py +++ b/tests/test_alden_osk_sources.py @@ -109,6 +109,39 @@ def test_exact_current_records_are_immutable_versions_with_original_roles(self): updated=sources.ground_graph(state,graph,lambda text:(text,[]));self.assertNotEqual(updated['nodes'][0]['raw_sources'],derived['nodes'][0]['raw_sources']) for path,content in files.items():self.assertEqual(path.read_bytes(),content) + def test_removed_room_metadata_retracts_grounded_node_and_edge_until_restored(self): + with sqlite3.connect(self.snapshot) as db: + db.execute('CREATE TABLE alden_rooms(chat_id TEXT PRIMARY KEY,label TEXT)') + db.execute("INSERT INTO alden_rooms VALUES('42','보관된 방')") + state,source=self.ground_fixture() + room_key=f'kakao:{self.account}:room:42' + message_key=f'kakao:{self.account}:room:42:log:2' + graph={ + 'nodes':[ + {'id':'room-node','evidence':{'source_event_ids':[room_key]}}, + {'id':'message-node','evidence':{'source_event_ids':[message_key]}}, + ], + 'edges':[{'source':'room-node','target':'message-node','type':'linked'}], + } + initial=sources.ground_graph(state,graph,lambda text:(text,[])) + self.assertEqual({node['id'] for node in initial['nodes']},{'room-node','message-node'}) + self.assertEqual(initial['edge_count'],1) + retained={path:path.read_bytes() for path in + (state/'knowledge/osk/vault/_sources/kakao/current').glob('*.txt')} + with sqlite3.connect(source) as db: + db.execute("DELETE FROM alden_rooms WHERE chat_id='42'") + removed=sources.ground_graph(state,graph,lambda text:(text,[])) + self.assertEqual([node['id'] for node in removed['nodes']],['message-node']) + self.assertEqual(removed['edges'],[]) + self.assertEqual(removed['raw_grounding']['withheld_nodes'],1) + with sqlite3.connect(source) as db: + db.execute("INSERT INTO alden_rooms VALUES('42','보관된 방')") + restored=sources.ground_graph(state,graph,lambda text:(text,[])) + self.assertEqual({node['id'] for node in restored['nodes']},{'room-node','message-node'}) + self.assertEqual(restored['edge_count'],1) + for path,original in retained.items(): + self.assertEqual(path.read_bytes(),original) + def test_conflicting_source_identity_is_archived_but_withheld_from_learning(self): state,source=self.ground_fixture() with sqlite3.connect(source) as db:db.execute("UPDATE alden_messages SET log_id='2' WHERE id=3") From 1dfee9a13b1a7785a1f8534f2c1111286d036167 Mon Sep 17 00:00:00 2001 From: Yeonwoo Choi <32544727+twoimo@users.noreply.github.com> Date: Sun, 11 Oct 2026 01:11:28 +0900 Subject: [PATCH 11/11] docs(alden): record 40 passing macOS source-retraction regressions --- .../alden-remote-integrity-20261011.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/architecture/alden-remote-integrity-20261011.md b/docs/architecture/alden-remote-integrity-20261011.md index 74be63f3..1b859eb3 100644 --- a/docs/architecture/alden-remote-integrity-20261011.md +++ b/docs/architecture/alden-remote-integrity-20261011.md @@ -39,7 +39,7 @@ PR #27 HEAD `0509551b08b71a72778d7e24fa852ccb235e3f7e`로부터 | 변경 파일 저장/즉시 재조회 | 실제 실행 검증됨 | GitHub write 후 각 파일 전체 문자열과 blob readback 일치 | | 완전 스냅샷 메타데이터 삭제 범위 SQL | 실제 실행 검증됨 (독립 Linux) | 서로 다른 계정 보존, 현재 계정 삭제 범위 가상 SQLite 검사 | | 중첩 JSON 무한대 거부 | 실제 실행 검증됨 (독립 Linux) | `json.loads(parse_float=...)`의 중첩 오버플로 검사 | -| 수정 3개 모듈·회귀 테스트 3개 macOS 러너 실행 | 실제 실행 검증됨 | GitHub Actions macos-14, Python 3.11, 30 tests OK, run 38066178487. 원 사용자 설치 Mac과 구별 | +| OSK 삭제·근거 보류, Aside, MLX macOS 러너 테스트 | 실제 실행 검증됨 | GitHub Actions macos-14, Python 3.11, 40 tests OK, run 38066589911. 원 사용자 설치 Mac과 구별 | | 지정 Mac 복제본, `outputs/STATUS.md`, 설치 앱 및 운영 데이터 검사 | 차단됨 | Mac-native 도구에 유효한 `turn_token` 미제공; Linux 런타임에 Mac 경로 없음 | | 설치 앱에서 수집→MCP→검색→이력→3D 실제 데이터 최종 검증 | 미착수 (이번 변경) | 이전 버전의 증거와 이번 브랜치의 배포 검증을 구분 | | 새 앱 설치·서명/공증·정식 배포 | 미착수 (이번 변경) | 원본 사용자 상태 변경이나 불명확한 릴리즈 대상 전환을 하지 않음 | @@ -76,6 +76,19 @@ Python 3.11 CI [run 38066178487](https://github.com/twoimo/alden/actions/runs/38 기존 1,169개 PR 차이를 다시 제출하지 않았다. PR #28 병합/릴리즈와 프로덕션 스케줄/데이터 변경은 수행하지 않았다. +추가 확인: `tests/test_alden_osk_sources.py`에서 실제 현재 스냅샷에 +방 메타데이터가 존재하면 근거 노드·연결이 표출되고, 같은 원본이 +삭제되면 해당 노드 및 연결이 보류되며 재등록 뒤 복원되는 테스트를 추가했다. +기존 저장 좌표와 원본 raw 파일은 테스트 과정에서 보존된다. +이 테스트는 OSK 엔진의 현재 근거 재조회 경로이며 운영 MCP의 +삭제 전파나 설치된 Three.js 화면에서 물리적으로 이를 본 증거는 아니다. + +후속 [CI run 38066589911](https://github.com/twoimo/alden/actions/runs/38066589911), +검증 브랜치 SHA `a6c872c2de362f71540e20dbe6219d90839ada04`, +macOS-14/Python3.11, 총 **40개 테스트 성공** 및 OSK 삭제·재등록 +신규 시나리오 성공을 실제 job 114255363711 로그에서 확인했다. +이 비교의 40개 구현·테스트 부분은 검토 PR에서 해당 파일들과 동일하다. + ## 2026-10-11 모델 배포처 교차 확인 공식 `Qwen/Qwen3.8-27B`는 Apache-2.0 모델로 게시되어 있으며,