Record original-alignment implementation and traceability checkpoint
Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Capture current registration evidence; successful export is not acceptance."""
|
||||
import argparse
|
||||
from collections import Counter
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
MAPPING = 'docs/plans/original-completion-2026-09-29/execution/original_facility_mapping.json'
|
||||
BASELINE = 'docs/plans/original-completion-2026-09-29/execution/baseline-fetched-2026-09-29.txt'
|
||||
|
||||
def manifest():
|
||||
paths = [ROOT / MAPPING, ROOT / BASELINE, ROOT / 'tools/capture_facility_audit.gd', Path(__file__)]
|
||||
for directory in ('autoload', 'scripts', 'scenes', 'data'):
|
||||
paths.extend(p for p in (ROOT / directory).rglob('*') if p.suffix in ('.gd', '.tres', '.tscn', '.json'))
|
||||
return {str(p.relative_to(ROOT)): hashlib.sha256(p.read_bytes()).hexdigest() for p in sorted(set(paths))}
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--godot', default='godot')
|
||||
parser.add_argument('--output', required=True)
|
||||
args = parser.parse_args()
|
||||
out = Path(args.output).resolve()
|
||||
out.mkdir(parents=True, exist_ok=True)
|
||||
def save(name, value):
|
||||
(out / name).write_text(json.dumps(value, ensure_ascii=False, indent=2) + '\n')
|
||||
before = manifest()
|
||||
save('source-start.json', before)
|
||||
env = dict(os.environ, THE_TREE_FACILITY_AUDIT_PATH=str(out / 'runtime-facilities.json'))
|
||||
with (out / 'export.log').open('w') as log:
|
||||
result = subprocess.run([args.godot, '--headless', '--path', str(ROOT), '--script', 'res://tools/capture_facility_audit.gd'], env=env, stdout=log, stderr=subprocess.STDOUT, timeout=120)
|
||||
after = manifest()
|
||||
changes = [p for p in sorted(before.keys() | after.keys()) if before.get(p) != after.get(p)]
|
||||
save('source-end.json', after)
|
||||
save('source-change.json', changes)
|
||||
if result.returncode or changes:
|
||||
raise SystemExit('Audit capture failed or source changed; inspect logs.')
|
||||
data = json.loads((out / 'runtime-facilities.json').read_text())
|
||||
mapping = json.loads((ROOT / MAPPING).read_text())
|
||||
rows = data['original_facilities']
|
||||
if len(rows) != 30 or len({r['name'] for r in rows}) != 30 or [r['name'] for r in rows] != [r['name'] for r in mapping]:
|
||||
raise SystemExit('Original mapping coverage is invalid.')
|
||||
counts = Counter()
|
||||
mismatches = []
|
||||
for row in rows:
|
||||
definition = row['definition']
|
||||
row['registration_status'] = ('normal' if row['runtime_registered'] and row['palette_listed'] else 'definition_only' if definition else 'missing')
|
||||
counts[row['registration_status']] += 1
|
||||
row['full_acceptance'] = 'unproven'
|
||||
if definition:
|
||||
expected = [int(x) for x in row['original_size'].split('x')]
|
||||
layer = re.match(r'FRONT|BACK', row['original_layer_zone']).group()
|
||||
if definition['footprint'] != expected or definition['layer'] != layer:
|
||||
mismatches.append(row['name'])
|
||||
extra = sorted(set(data['normal_registry_ids']) - {r['definition_id'] for r in rows})
|
||||
unspecified = [r['name'] for r in rows if r['definition'] and r['definition']['customer_capacity'] < 0]
|
||||
summary = dict(original_count=30, registration_counts=dict(counts), normal_catalog_count=len(data['normal_registry_ids']), non_original_registry_ids=extra,
|
||||
dimension_or_layer_mismatches=mismatches, customer_limit_unset=unspecified,
|
||||
all_original_acceptance=False, scope='Registration and loaded definition values only. Not operation, save migration, assets, Windows or whole-spec acceptance.')
|
||||
save('summary.json', summary)
|
||||
save('classified-facilities.json', rows)
|
||||
labels = {'normal': '通常登録・パレット掲載', 'definition_only': '定義のみ', 'missing': '対応定義なし'}
|
||||
lines = ['# 原本30施設・現行登録監査', '',
|
||||
f"通常登録 {counts['normal']}、定義のみ {counts['definition_only']}、対応定義なし {counts['missing']}。通常登録全{len(data['normal_registry_ids'])}件のうち原本30施設以外は{len(extra)}件。",
|
||||
'', '登録状態と読込済み定義の監査。実営業・保存移行・完成資産・Windows・全要件の受入完了は証明しない。', '',
|
||||
f'対応定義の寸法・層の不一致: {len(mismatches)}件。人数専用上限が未設定: {len(unspecified)}件。capacityから人数値を転記していない。高層・背面・騒音・サービス条件は別途受入が必要。', '',
|
||||
'| 原本 | 施設 | ID | 登録 | 寸法 / 層 / ゾーン | 顧客人数上限 |', '|---|---|---|---|---|---|']
|
||||
for r in rows:
|
||||
d = r['definition']
|
||||
geometry = f"{d['footprint'][0]}×{d['footprint'][1]} / {d['layer']} / {d['zone']}" if d else '未定義'
|
||||
limit = str(d['customer_capacity']) if d and d['customer_capacity'] >= 0 else '未設定'
|
||||
lines.append(f"| {r['section']} | {r['name']} | {r['definition_id'] or '—'} | {labels[r['registration_status']]} | {geometry} | {limit} |")
|
||||
lines += ['', '## 未接続施設', '', '対応定義なし: ' + '、'.join(r['name'] for r in rows if r['registration_status']=='missing') + '。', '',
|
||||
'定義のみ: ' + '、'.join(r['name'] for r in rows if r['registration_status']=='definition_only') + '。', '',
|
||||
'## 次の受入', '', '未定義施設は寸法・層だけでなく経済値、人数、業務、通常操作、保存を接続する。登録済み施設は未設定人数とサービス属性、営業時間・停止・経路・客/職員行動を個別検証する。施設追加のたびにこの監査を再実行する。', '',
|
||||
'再現: `python3 tools/run_facility_audit.py --godot /opt/homebrew/bin/godot --output artifacts/facility-audit-current-2026-09-29`。原本SHA・入力ソースSHA・取得中の変更なしは同ディレクトリのsource-start/end/change.jsonを参照。', '']
|
||||
(out / 'REPORT.md').write_text('\n'.join(lines))
|
||||
print(json.dumps(summary, ensure_ascii=False))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user