feat: web, websocket 어댑터 추가 구현
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
from __future__ import annotations
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
root = Path(__file__).resolve().parent
|
||||
if (root / 'docs').exists():
|
||||
design = root / 'docs/superpowers/specs/2026-08-14-websocket-realtime-connection-platform-design.md'
|
||||
stable = root / 'docs/superpowers/plans/2026-08-14-websocket-realtime-connection-platform-implementation-plan.md'
|
||||
advanced = root / 'docs/superpowers/plans/2026-08-14-websocket-advanced-capabilities-expansion-plan.md'
|
||||
else:
|
||||
design = Path('/mnt/data/websocket-realtime-connection-platform-design.md')
|
||||
stable = Path('/mnt/data/websocket-realtime-connection-platform-implementation-plan.md')
|
||||
advanced = Path('/mnt/data/websocket-advanced-capabilities-expansion-plan.md')
|
||||
|
||||
checks = []
|
||||
def check(name, condition):
|
||||
checks.append((name, bool(condition)))
|
||||
|
||||
for path in (design, stable, advanced):
|
||||
check(f'exists:{path.name}', path.exists())
|
||||
if not path.exists():
|
||||
continue
|
||||
text = path.read_text(encoding='utf-8')
|
||||
check(f'code-fence:{path.name}', text.count('```') % 2 == 0)
|
||||
check(f'no-placeholders:{path.name}', not re.search(r'\b(TODO|TBD|FIXME)\b', text))
|
||||
check(f'nontrivial:{path.name}', len(text.splitlines()) > 300)
|
||||
|
||||
stable_text = stable.read_text(encoding='utf-8')
|
||||
advanced_text = advanced.read_text(encoding='utf-8')
|
||||
design_text = design.read_text(encoding='utf-8')
|
||||
|
||||
stable_tasks = [int(n) for n in re.findall(r'^### Task (\d+):', stable_text, re.M)]
|
||||
advanced_tasks = [int(n) for n in re.findall(r'^### Task (\d+):', advanced_text, re.M)]
|
||||
check('stable-task-sequence', stable_tasks == list(range(1, 54)))
|
||||
check('advanced-task-sequence', advanced_tasks == list(range(1, 23)))
|
||||
|
||||
for label, text, expected in [('stable', stable_text, 53), ('advanced', advanced_text, 22)]:
|
||||
sections = re.split(r'(?=^### Task \d+:)', text, flags=re.M)[1:]
|
||||
check(f'{label}-task-count', len(sections) == expected)
|
||||
for idx, section in enumerate(sections, 1):
|
||||
for token in ['**Files:**', '**Interfaces:**', '**Implementation requirements:**',
|
||||
'Step 1:', 'Step 2:', 'Step 3:', 'Step 4:', 'Step 5:',
|
||||
'git commit -m']:
|
||||
check(f'{label}-task-{idx}-{token}', token in section)
|
||||
|
||||
create_pattern = re.compile(r'^- Create: `([^`]+)`', re.M)
|
||||
stable_paths = create_pattern.findall(stable_text)
|
||||
advanced_paths = create_pattern.findall(advanced_text)
|
||||
check('stable-create-unique', len(stable_paths) == len(set(stable_paths)))
|
||||
check('advanced-create-unique', len(advanced_paths) == len(set(advanced_paths)))
|
||||
check('stable-advanced-create-disjoint', set(stable_paths).isdisjoint(set(advanced_paths)))
|
||||
|
||||
required_design = [
|
||||
'Inbound Evidence', 'Outbound Evidence', 'Connection Evidence',
|
||||
'hyeonworks.realtime.v1.json', 'ONE_TIME_TICKET',
|
||||
'APPLICATION_COMMITTED', 'WRITTEN_LOCALLY',
|
||||
'Outbound Queue·Backpressure', 'Nginx', 'Tomcat', 'Jetty',
|
||||
'Reactor Netty', 'WebSocket exactly-once', 'Appendix A'
|
||||
]
|
||||
for token in required_design:
|
||||
check(f'design-token:{token}', token in design_text)
|
||||
|
||||
required_stable = [
|
||||
'Commit 후 Response Loss', 'Slow Consumer', 'Browser Matrix',
|
||||
'MVC·WebFlux Stack 상호 배타성', 'Stable Release Gate'
|
||||
]
|
||||
for token in required_stable:
|
||||
check(f'stable-token:{token}', token in stable_text)
|
||||
|
||||
required_advanced = [
|
||||
'Resume Token', 'Messaging 기반 Durable Replay', 'STOMP 1.2',
|
||||
'RabbitMQ STOMP Broker Relay', 'HTTP/3 WebSocket Experimental',
|
||||
'GraphQL WebSocket Transport Bridge'
|
||||
]
|
||||
for token in required_advanced:
|
||||
check(f'advanced-token:{token}', token in advanced_text)
|
||||
|
||||
failed = [name for name, ok in checks if not ok]
|
||||
print(f'checks={len(checks)} passed={len(checks)-len(failed)} failed={len(failed)}')
|
||||
for name in failed:
|
||||
print('FAIL', name)
|
||||
sys.exit(1 if failed else 0)
|
||||
Reference in New Issue
Block a user