-
Notifications
You must be signed in to change notification settings - Fork 0
feat: conformance 语料库种子+门禁元治理四列+晋级账本(IR-0006 W6-M1) #461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| name: conformance-seed | ||
| # conformance 语料库种子+门禁元治理首跑(IR-0006 W6-M1 / 卡 #423 / AC-1b+1c) | ||
| # | ||
| # 全链:拉 30-50 张已完成卡(state:done type:card)→ 回放三元组语料 | ||
| # (初始快照+目标+密封验收,机械校验)→ 四列元治理评审(声明门禁 vs | ||
| # 全仓 job 清单对账)→ 胜出实践晋级首跑(append-only hash 链账本)→ | ||
| # 语料+评审+晋级账本落 archive 仓 conformance/(PR 面)。 | ||
| on: | ||
| workflow_dispatch: {} | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| seed: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| permissions: | ||
| contents: read | ||
| env: | ||
| CARD: Cloudbird-Software/.github#423 | ||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
| - name: 回放采集(30-50 张已完成卡——三元组语料) | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GOVERNANCE_TOKEN }} | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p comments | ||
| # 已完成卡:type:card+state:done closed——取最近 50 张 | ||
| gh api -X GET "search/issues" -f q="repo:Cloudbird-Software/.github is:issue is:closed label:type:card label:state:done" -f per_page=50 -f sort=created -f order=desc \ | ||
| --jq '[.items[] | {number, title, created_at, closed_at, labels: [.labels[].name], body}]' > cards.json | ||
| N=$(jq length cards.json) | ||
| echo "拉到已完成卡 $N 张" | ||
| for num in $(jq -r '.[].number' cards.json); do | ||
| gh api "repos/Cloudbird-Software/.github/issues/${num}/comments" --paginate \ | ||
| --jq '[.[] | {body}]' > "comments/${num}.json" || echo "[]" > "comments/${num}.json" | ||
|
Comment on lines
+37
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 4. Comment failures silently shrink corpus A failed comments API request is replaced with [], and harvest merely skips the affected card; validation can still pass whenever 30 other entries survive. Network, permission, or rate-limit failures can therefore publish an incomplete corpus as green despite the stated fail-closed behavior. Agent Prompt
|
||
| done | ||
| python3 governance/conformance-corpus.py harvest \ | ||
| --cards-file cards.json --comments-dir comments --out corpus.jsonl | ||
| # 机械校验(fail-closed:结构红或 <30 条=本 job 红) | ||
| python3 governance/conformance-corpus.py validate --corpus corpus.jsonl --min 30 | ||
| - name: 四列元治理评审(声明门禁 vs 全仓 job 清单对账) | ||
| run: | | ||
| set -euo pipefail | ||
| python3 governance/metagov.py review \ | ||
| --policy governance/policy/metrics.yaml \ | ||
| --workflows-dir .github/workflows --out gate-review.json | ||
| - name: 胜出实践晋级首跑(append-only hash 链,AC-1c) | ||
| run: | | ||
| set -euo pipefail | ||
| cat > rec1.json <<'EOF' | ||
| {"practice": "fail-closed 双层验证(写入侧宽松+验证侧严格)", | ||
| "goal": "错误事件进不了账本主链;生成器缺陷在 PR 面早暴露", | ||
| "evidence": ["run 33263613945(eval-wave 落账步 verify_evidence 红拦截 ts 缺字段)", | ||
| "PR Cloudbird-Software/.github#460(缺陷修复留痕)"], | ||
| "promoted_by": "metagov-review-bot"} | ||
| EOF | ||
| cat > rec2.json <<'EOF' | ||
| {"practice": "同 harness 同语料只换被优化物(eval 归因隔离)", | ||
| "goal": "optimization 波次指标差异只归因优化本体——非劣性裁决的前提", | ||
| "evidence": ["run 33263909046(基线/候选同装置评测+GREEN 裁决)", | ||
| "PR Cloudbird-Software/CI-Workflows#132(eval harness 落位)"], | ||
| "promoted_by": "metagov-review-bot"} | ||
| EOF | ||
| python3 governance/metagov.py promote --registry promotions.jsonl --record rec1.json | ||
| python3 governance/metagov.py promote --registry promotions.jsonl --record rec2.json | ||
| python3 governance/metagov.py verify --registry promotions.jsonl | ||
|
Comment on lines
+67
to
+69
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift 不要从空的本地账本重新开始晋级链。 这里始终向新的 请先克隆 archive,再对 🤖 Prompt for AI Agents |
||
| - name: 语料+评审+晋级账本落 archive conformance/(PR 面) | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GOVERNANCE_TOKEN }} | ||
|
Comment on lines
+71
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. governance_token powers archive writes The workflow injects the org-admin GOVERNANCE_TOKEN for general issue harvesting and for cloning, pushing to, and opening a PR in the archive repository. The rule restricts this credential to CI-time org Project writes or membership checks, so these repository operations unnecessarily expose a highly privileged token. Agent Prompt
|
||
| RUN_ID: ${{ github.run_id }} | ||
| run: | | ||
| set -euo pipefail | ||
| git clone --depth 5 "https://x-access-token:${GH_TOKEN}@github.com/Cloudbird-Software/archive.git" arch | ||
| mkdir -p arch/conformance | ||
| cp corpus.jsonl arch/conformance/cards.jsonl | ||
| cp gate-review.json arch/conformance/gate-review.json | ||
| cp promotions.jsonl arch/conformance/promotions.jsonl | ||
|
Comment on lines
+78
to
+80
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2. Promotion history gets overwritten The workflow builds a fresh local two-record registry and then copies it over the archive registry, so every later run discards all previously promoted practices instead of extending the append-only chain. metagov.py promote can preserve history only when invoked on an existing registry, but the workflow never imports or targets the archive’s registry. Agent Prompt
|
||
| cat > arch/conformance/index.yaml <<EOF | ||
| schema: conformance-seed/v1 | ||
| generated_at: "$(date -u +%Y-%m-%dT%H:%M:%SZ)" | ||
| run_id: ${RUN_ID} | ||
| corpus_entries: $(grep -c . corpus.jsonl) | ||
| corpus_sha256: $(sha256sum corpus.jsonl | cut -d' ' -f1) | ||
| gate_review_sha256: $(sha256sum gate-review.json | cut -d' ' -f1) | ||
| promotions_records: $(grep -c . promotions.jsonl) | ||
| promotions_head_hash: $(tail -1 promotions.jsonl | jq -r .hash) | ||
| EOF | ||
| git -C arch config user.name conformance-seed-bot && git -C arch config user.email conformance@users.noreply.github.com | ||
| BR="conformance-seed-$RUN_ID" | ||
| git -C arch checkout -b "$BR" | ||
| git -C arch add -f conformance/ | ||
| git -C arch commit -m "conformance: 语料库种子+四列元治理评审+晋级首跑(IR-0006 W6-M1,run #$RUN_ID)" | ||
| git -C arch push "https://x-access-token:${GH_TOKEN}@github.com/Cloudbird-Software/archive.git" "HEAD:refs/heads/$BR" | ||
| export GH_TOKEN | ||
| gh pr create --repo Cloudbird-Software/archive --head "$BR" \ | ||
| --title "conformance: 语料库种子+元治理首跑(IR-0006 W6-M1,run #$RUN_ID)" \ | ||
| --body "Card: Cloudbird-Software/.github#423 | ||
|
|
||
| 自动生成(conformance-seed run #$RUN_ID): | ||
| - conformance/cards.jsonl —— 30-50 张已完成卡回放语料(三元组:初始快照+目标+密封验收,机械校验绿) | ||
| - conformance/gate-review.json —— 门禁元治理四列评审(声明门禁全对账在册) | ||
| - conformance/promotions.jsonl —— 胜出实践晋级首跑 2 条(append-only hash 链,verify 绿) | ||
| - conformance/index.yaml —— 指纹(corpus digest+晋级链头 hash) | ||
|
|
||
| verify.yml 链验绿后可合。" | ||
| echo "OK W6-M1 全链绿:语料($(grep -c . corpus.jsonl) 条三元组)+四列评审+晋级 2 条——archive PR 已开" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,187 @@ | ||
| #!/usr/bin/env python3 | ||
| # -*- coding: utf-8 -*- | ||
| """conformance-corpus.py —— conformance 语料库种子工具(IR-0006 W6-M1 / AC-1b) | ||
|
|
||
| 回放语料三元组(每条已完成卡): | ||
| initial_snapshot 卡开启时的快照:title + body digest + created_at | ||
| goal 目标:任务节(## 任务)digest + AC 清单(id 提取) | ||
| sealed_acceptance 密封验收:closed_at + state:done 收口评论 digest(密封= | ||
| digest 锚——验收内容不改样,改了 digest 必红) | ||
|
|
||
| 机械校验(validate,fail-closed):三元组结构/digest 形状/AC 非空/ | ||
| done 评论 digest 在位——结构非法=红(AC-1b"结构可机械校验")。 | ||
|
|
||
| 子命令: | ||
| harvest --cards-file <issues.json> --comments-dir <dir> --out corpus.jsonl | ||
| (issues.json = gh api 拉的卡 issue 数组;comments-dir/<n>.json = | ||
| 该卡评论数组——离线 fixture 同形状,CI 在线拉取) | ||
| validate --corpus corpus.jsonl [--min N](N=最低条数,缺省 30) | ||
| 退出码:0=绿 | 1=结构红 | 2=infra。 | ||
| """ | ||
| from __future__ import annotations | ||
|
|
||
| import hashlib | ||
| import json | ||
| import re | ||
| import sys | ||
| from pathlib import Path | ||
|
|
||
| SCHEMA = "conformance-corpus/v1" | ||
| AC_RE = re.compile(r"\b(AC-[0-9]+[a-z]?)\b") | ||
| PARENT_RE = re.compile(r"父意图[::]\s*#(\d+)") | ||
| TASK_RE = re.compile(r"##\s*任务\s*\n(.*?)(?=\n##|\Z)", re.S) | ||
| ACSEC_RE = re.compile(r"##\s*AC[^\n]*\n(.*?)(?=\n##|\Z)", re.S) | ||
| # 收口评论惯用语四种形态:state:done(T8 机器语)/ 收口 / T8 谓词 / 验收完成 | ||
| DONE_COMMENT_RE = re.compile(r"state:done|收口|T8|验收完成") | ||
|
Comment on lines
+34
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 7. Incidental comments become seals The seal matcher accepts any comment containing T8, 收口, or 验收完成, including negative or incidental text such as “T8 尚未完成”, and hashes the last such comment as accepted closure. Validation checks only digest shape, so it cannot detect that the selected comment was not an acceptance event. Agent Prompt
|
||
| HEX64 = re.compile(r"^[0-9a-f]{64}$") | ||
|
|
||
|
|
||
| def die2(msg: str) -> None: | ||
| print(f"FATAL conformance-corpus: {msg}", file=sys.stderr) | ||
| sys.exit(2) | ||
|
|
||
|
|
||
| def sha256_text(s: str) -> str: | ||
| return hashlib.sha256(s.encode("utf-8")).hexdigest() | ||
|
|
||
|
|
||
| def extract_task(body: str) -> str: | ||
| m = TASK_RE.search(body or "") | ||
| return (m.group(1) if m else (body or "")).strip() | ||
|
|
||
|
|
||
| def build_entry(issue: dict, comments: list) -> dict: | ||
| body = issue.get("body") or "" | ||
| done_comments = [c for c in comments | ||
| if DONE_COMMENT_RE.search(c.get("body") or "")] | ||
| seal = sha256_text(done_comments[-1]["body"]) if done_comments else "" | ||
| labels = [l["name"] if isinstance(l, dict) else l for l in issue.get("labels", [])] | ||
| parent = PARENT_RE.search(body) | ||
| acs = sorted(set(AC_RE.findall(body))) | ||
| ac_m = ACSEC_RE.search(body) | ||
| ac_sec = ac_m.group(1).strip() if ac_m else "" | ||
| ac_count = sum(1 for ln in ac_sec.splitlines() if ln.strip().startswith(("-", "*"))) | ||
|
Comment on lines
+60
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 6. Ac mentions bypass section validation AC IDs are extracted from the entire issue body, so an AC-… mention in task prose or another section makes validation pass even when the actual AC section is absent or empty. This admits goals with no mechanically replayable acceptance criteria. Agent Prompt
|
||
| entry = { | ||
| "schema": SCHEMA, | ||
| "card": f"Cloudbird-Software/.github#{issue['number']}", | ||
| "ir": f"Cloudbird-Software/.github#{parent.group(1)}" if parent else None, | ||
| "triple": { | ||
| "initial_snapshot": { | ||
| "created_at": issue.get("created_at"), | ||
| "title": issue.get("title"), | ||
| "body_sha256": sha256_text(body), | ||
|
Comment on lines
+69
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 5. Initial snapshot uses current body initial_snapshot stores the title and body returned when the completed issue is harvested, not their values when the card was opened. Any edits made during execution are therefore mislabeled as the initial state, invalidating replay comparisons based on the claimed opening snapshot. Agent Prompt
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift 🔎 Supported by static analysis🌐 Web query:
💡 Result: 是的,GitHub REST API 在 Issue 搜索结果(以及获取单个 Issue 的详细信息)中, Citations:
🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- applicable repository guidance ---'
find /tmp/coderabbit-repo-knowledge/cloudbird-software-github-0dfcc7f5 -maxdepth 2 -type f -name '*.md' -print \
| sort
printf '%s\n' '--- governance file outline ---'
ast-grep outline governance/conformance-corpus.py
printf '%s\n' '--- target source ---'
sed -n '1,220p' governance/conformance-corpus.py
printf '%s\n' '--- relevant symbols and references ---'
rg -n --glob '*.py' 'initial_snapshot|body_sha256|sha256_text|build_entry|harvest|validate|conformance-corpus' .Repository: Cloudbird-Software/.github Length of output: 11621 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- governance conventions ---'
cat /tmp/coderabbit-repo-knowledge/cloudbird-software-github-0dfcc7f5/conventions/governance.md
printf '%s\n' '--- repository-wide conventions ---'
cat /tmp/coderabbit-repo-knowledge/cloudbird-software-github-0dfcc7f5/conventions/repo-wide.md
printf '%s\n' '--- governance learnings ---'
find /tmp/coderabbit-repo-knowledge/cloudbird-software-github-0dfcc7f5/learnings -maxdepth 1 -type f -print -exec cat {} \;Repository: Cloudbird-Software/.github Length of output: 984 保存卡片创建时的正文快照
如果卡片在关闭前修改任务或 AC,语料库会记录修改后的正文,却将其标记为 🤖 Prompt for AI Agents |
||
| }, | ||
| "goal": { | ||
| "task_sha256": sha256_text(extract_task(body)), | ||
| "ac_ids": acs, | ||
| "ac_section_sha256": sha256_text(ac_sec), | ||
| "ac_count": ac_count, | ||
| "labels_final": sorted(labels), | ||
| }, | ||
| "sealed_acceptance": { | ||
| "closed_at": issue.get("closed_at"), | ||
| "done_comment_sha256": seal, | ||
| "done_comment_sha8": seal[:8], | ||
| }, | ||
| }, | ||
| } | ||
| return entry | ||
|
|
||
|
|
||
| def validate_entry(e: dict) -> str | None: | ||
| if e.get("schema") != SCHEMA: | ||
| return "schema 非 conformance-corpus/v1" | ||
| t = e.get("triple") | ||
| if not isinstance(t, dict) or set(t) != {"initial_snapshot", "goal", "sealed_acceptance"}: | ||
| return "triple 须且仅含三元组三键" | ||
| snap, goal, seal = t["initial_snapshot"], t["goal"], t["sealed_acceptance"] | ||
| if not snap.get("created_at") or not str(snap.get("title") or "").strip(): | ||
| return "initial_snapshot 缺 created_at/title" | ||
| if not HEX64.match(str(snap.get("body_sha256"))): | ||
| return "initial_snapshot.body_sha256 非 64hex" | ||
| if not HEX64.match(str(goal.get("task_sha256"))): | ||
| return "goal.task_sha256 非 64hex" | ||
| # 验收判据双形态:AC id 列表(新形态)或 AC 节非空(旧卡朴素 bullet 形态) | ||
| if not goal.get("ac_ids") and not (goal.get("ac_count", 0) >= 1 | ||
| and HEX64.match(str(goal.get("ac_section_sha256")))): | ||
| return "goal 无验收判据(ac_ids 空且 AC 节空=不可回放)" | ||
| if not seal.get("closed_at"): | ||
| return "sealed_acceptance.closed_at 缺" | ||
| dg = str(seal.get("done_comment_sha256")) | ||
| if not HEX64.match(dg) or seal.get("done_comment_sha8") != dg[:8]: | ||
| return "sealed_acceptance 密封 digest 形状非法(须 64hex+sha8 一致)" | ||
| return None | ||
|
|
||
|
|
||
| def main() -> int: | ||
| if len(sys.argv) < 2: | ||
| print(__doc__) | ||
| return 2 | ||
| cmd = sys.argv[1] | ||
|
|
||
| if cmd == "harvest": | ||
| cards_f = sys.argv[sys.argv.index("--cards-file") + 1] | ||
| cdir = Path(sys.argv[sys.argv.index("--comments-dir") + 1]) | ||
| out_f = sys.argv[sys.argv.index("--out") + 1] | ||
| try: | ||
| cards = json.loads(Path(cards_f).read_text(encoding="utf-8")) | ||
| except (OSError, json.JSONDecodeError) as e: | ||
| die2(f"cards-file 不可读: {e}") | ||
| if not isinstance(cards, list) or not cards: | ||
| die2("cards-file 须为非空数组") | ||
| entries, bad = [], 0 | ||
| for it in cards: | ||
| num = it.get("number") | ||
| cpath = cdir / f"{num}.json" | ||
| try: | ||
| comments = json.loads(cpath.read_text(encoding="utf-8")) | ||
| except (OSError, json.JSONDecodeError): | ||
| comments = [] | ||
| e = build_entry(it, comments) | ||
| err = validate_entry(e) | ||
| if err: | ||
| bad += 1 | ||
| print(f"SKIP #{num}: {err}", file=sys.stderr) | ||
| continue | ||
| entries.append(e) | ||
| Path(out_f).write_text( | ||
| "".join(json.dumps(e, ensure_ascii=False, separators=(",", ":")) + "\n" for e in entries), | ||
| encoding="utf-8") | ||
| print(f"OK 语料 {len(entries)} 条落盘 {out_f}(跳过 {bad} 条结构非法)") | ||
| return 0 if entries else 1 | ||
|
|
||
| if cmd == "validate": | ||
| corpus_f = sys.argv[sys.argv.index("--corpus") + 1] | ||
| min_n = 30 | ||
| if "--min" in sys.argv: | ||
| min_n = int(sys.argv[sys.argv.index("--min") + 1]) | ||
| try: | ||
| lines = [ln for ln in Path(corpus_f).read_text(encoding="utf-8").splitlines() if ln.strip()] | ||
| except OSError as e: | ||
| die2(f"corpus 不可读: {e}") | ||
| errs = 0 | ||
| for i, ln in enumerate(lines, 1): | ||
| try: | ||
| e = json.loads(ln) | ||
| except json.JSONDecodeError as ex: | ||
| print(f"REJECT 第 {i} 行 JSON 非法: {ex}") | ||
| errs += 1 | ||
| continue | ||
| err = validate_entry(e) | ||
| if err: | ||
| print(f"REJECT 第 {i} 行({e.get('card', '?')}): {err}") | ||
| errs += 1 | ||
| if len(lines) < min_n: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 按唯一 当前检查使用 请验证 🤖 Prompt for AI Agents |
||
| print(f"REJECT 语料条数 {len(lines)} < 最低 {min_n}(AC-1b:30-50 张已完成卡)") | ||
| errs += 1 | ||
| if errs: | ||
| return 1 | ||
| print(f"OK conformance 语料结构绿({len(lines)} 条三元组可机械校验)") | ||
| return 0 | ||
|
|
||
| print(__doc__) | ||
| return 2 | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| sys.exit(main()) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3. Paginated comments become invalid json
🐞 Bug≡ CorrectnessAgent Prompt
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools