Files
junhong_cmp_fiber/scripts/context-health.sh
2026-08-18 16:30:16 +08:00

89 lines
3.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/zsh
set -euo pipefail
ROOT=${0:A:h:h}
cd "$ROOT"
openspec doctor --json | grep -q '"healthy": true'
openspec validate --all >/dev/null
for forbidden in .planning .scratch .sisyphus CONTEXT.md specs; do
[[ ! -e "$forbidden" ]] || { print -u2 "禁止目录或文件仍存在:$forbidden"; exit 1; }
done
[[ -z "$(find "$HOME/.codex/skills" -maxdepth 1 -name 'gsd-*' -print 2>/dev/null)" ]]
[[ -z "$(find "$HOME/.codex/agents" -maxdepth 1 -name 'gsd-*' -print 2>/dev/null)" ]]
[[ -z "$(command -v omx 2>/dev/null || true)" ]]
! grep -RIlE 'oh-my-codex|OMX:' AGENTS.md CLAUDE.md .agents .claude >/dev/null 2>&1
[[ -z "$(find . -type f -name '*_test.go' -not -path './.git/*' -print)" ]]
[[ ! -e tests ]]
[[ ! -e internal/testutil ]]
[[ ! -e scripts/benchmark ]]
[[ -z "$(find scripts -type f -name 'test_*' -print 2>/dev/null)" ]]
python3 - <<'PY'
from pathlib import Path
import json, re, sys
files=[Path('AGENTS.md'),Path('CLAUDE.md'),Path('README.md'),Path('ARCHITECTURE.md'),*Path('docs').rglob('*.md'),*Path('openspec').rglob('*.md')]
bad=[]
for p in files:
for link in re.findall(r'\[[^]]*\]\(([^)]+)\)', p.read_text(errors='ignore')):
target=link.split('#')[0]
if not target or '://' in target or target.startswith('mailto:'):
continue
if not (p.parent/target).resolve().exists():
bad.append(f'{p}: {link}')
if bad:
print('失效链接:\n'+'\n'.join(bad), file=sys.stderr)
raise SystemExit(1)
spec_requirements=set()
indexed_routes=set()
for spec in Path('openspec/specs').glob('*/spec.md'):
text=spec.read_text()
if re.search(r'^### Requirement: .*接口集合$', text, re.M):
raise SystemExit(f'接口集合仍被用作行为 Requirement{spec}')
names=re.findall(r'^### Requirement: (.+)$', text, re.M)
if not names:
raise SystemExit(f'Capability 缺少行为 Requirement{spec}')
spec_requirements.update(f'{spec.parent.name}::{name}' for name in names)
indexed_routes.update(f'{method} {path}' for method,path in re.findall(r'`(GET|POST|PUT|PATCH|DELETE) ([^`]+)`', text))
evidence_dir=Path('docs/verification/context-reset')
evidence=json.loads((evidence_dir/'requirement-evidence.json').read_text())
matrix=json.loads((evidence_dir/'entry-capability-requirement-matrix.json').read_text())
evidence_requirements={f"{row['capability']}::{row['requirement']}" for row in evidence}
if evidence_requirements != spec_requirements:
raise SystemExit('Requirement 证据链与 Specs 不一致')
matrix_http={row['entry'] for row in matrix if row['entry_type']=='http'}
if matrix_http != indexed_routes:
raise SystemExit('HTTP Route 与可达操作索引双向覆盖不一致')
linked={name for row in matrix for name in row['requirements']}
if linked != spec_requirements:
raise SystemExit('入口矩阵未双向覆盖全部行为 Requirement')
worker_source=Path('pkg/queue/handler.go').read_text()+Path('cmd/worker/main.go').read_text()
registered={'constants.'+name for name in re.findall(r'(?:HandleFunc|Register)\(constants\.(TaskType\w+|OutboxEventType\w+)', worker_source)}
matrix_async={row['entry'] for row in matrix if row['entry_type']=='async'}
if matrix_async != registered:
raise SystemExit('异步注册入口与证据矩阵双向覆盖不一致')
PY
tmpdir=$(mktemp -d)
generated=docs/admin-openapi.yaml
had_generated=0
if [[ -f "$generated" ]]; then
had_generated=1
cp "$generated" "$tmpdir/original.yaml"
fi
cleanup_generated() {
if (( had_generated )); then cp "$tmpdir/original.yaml" "$generated"; else rm -f "$generated"; fi
rm -rf "$tmpdir"
}
trap cleanup_generated EXIT
go run cmd/gendocs/main.go >/dev/null 2>&1
cp "$generated" "$tmpdir/first.yaml"
go run cmd/gendocs/main.go >/dev/null 2>&1
cmp -s "$tmpdir/first.yaml" "$generated" || { print -u2 'OpenAPI 连续生成结果不一致'; exit 1; }
print 'Context 健康检查通过'