All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m25s
89 lines
3.9 KiB
Bash
Executable File
89 lines
3.9 KiB
Bash
Executable File
#!/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 "$(git ls-files .lh-harness)" ]]
|
||
[[ -z "$(find . -type f -name '*_test.go' -not -path './.git/*' -not -path './.lh-harness/*' -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('.lh-harness/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 健康检查通过'
|