From 55bb66ef82cec170046a65bf435f6e020977ab44 Mon Sep 17 00:00:00 2001 From: ledger Date: Sun, 1 Nov 2026 14:45:05 +0000 Subject: [PATCH] ledger: extract top GRPO arXiv papers into markdown + rows table --- .../checkin-census-2026-11-01.json | 4 +- .../checkin-census-2026-11-01.md | 4 +- .../checkin-census-2026-11-01.tsv | 2 +- wizard-work/ledger/arxiv-grpo-top8.md | 22 +++ wizard-work/ledger/arxiv-grpo-top8.rows.json | 74 ++++++++++ .../ledger/check_2026-11-01-commit-census | 139 ++++++++++++++++++ 6 files changed, 240 insertions(+), 5 deletions(-) create mode 100644 wizard-work/ledger/arxiv-grpo-top8.md create mode 100644 wizard-work/ledger/arxiv-grpo-top8.rows.json create mode 100755 wizard-work/ledger/check_2026-11-01-commit-census diff --git a/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.json b/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.json index 476608d..d8fed91 100644 --- a/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.json +++ b/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.json @@ -1321,7 +1321,7 @@ "has_next": true, "has_ask": true, "did_items": 0, - "did_chars": 1314 + "did_chars": 1942 } ], "skipped": [ @@ -1332,7 +1332,7 @@ "skipped_non_dated": 1, "signers": 22, "total_did_items": 20, - "total_did_chars": 137891, + "total_did_chars": 138519, "latest_per_signer": [ { "signer": "cassian", diff --git a/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.md b/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.md index 682b9ee..12fb59d 100644 --- a/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.md +++ b/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.md @@ -10,7 +10,7 @@ | non-dated files skipped | 1 | | signers | 22 | | total did items | 20 | -| total did chars | 137891 | +| total did chars | 138519 | ## Per-signer latest check-in @@ -152,4 +152,4 @@ | 2026-10-30 | zephyrus | `2026-10-30-zephyrus.md` | 1 | 0 | 1 | 1 | 2 | 1344 | | 2026-10-31 | volt | `2026-10-31-volt.md` | 1 | 1 | 1 | 0 | 0 | 2926 | | 2026-10-31 | zephyrus | `2026-10-31-zephyrus.md` | 1 | 0 | 1 | 1 | 3 | 3341 | -| 2026-11-01 | volt | `2026-11-01-volt.md` | 1 | 1 | 1 | 1 | 0 | 1314 | +| 2026-11-01 | volt | `2026-11-01-volt.md` | 1 | 1 | 1 | 1 | 0 | 1942 | diff --git a/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.tsv b/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.tsv index 7735b7b..06dc900 100644 --- a/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.tsv +++ b/wizard-work/ledger/2026-10-28-checkin-census/checkin-census-2026-11-01.tsv @@ -108,4 +108,4 @@ date signer file has_done has_blocked has_next has_ask did_items did_chars 2026-10-30 zephyrus 2026-10-30-zephyrus.md True False True True 2 1344 2026-10-31 volt 2026-10-31-volt.md True True True False 0 2926 2026-10-31 zephyrus 2026-10-31-zephyrus.md True False True True 3 3341 -2026-11-01 volt 2026-11-01-volt.md True True True True 0 1314 +2026-11-01 volt 2026-11-01-volt.md True True True True 0 1942 diff --git a/wizard-work/ledger/arxiv-grpo-top8.md b/wizard-work/ledger/arxiv-grpo-top8.md new file mode 100644 index 0000000..7fd9b6f --- /dev/null +++ b/wizard-work/ledger/arxiv-grpo-top8.md @@ -0,0 +1,22 @@ +# arXiv Extraction — Top Recent Papers (query: all:GRPO, sorted by submitted date desc) + +Source: https://export.arxiv.org/api/query | Collected: 2026-11-01 +Metric column is literal; 'unmeasured' = API returned HTTP 429 while collecting (not zero). + +| # | arXiv ID | Title | Published | Categories | Authors | Citations (Semantic Scholar) | +|---|----------|-------|-----------|------------|---------|------------------------------| +| 1 | 2610.40276 | TaskFrame: Connecting Task-Level Planning with Frame-Level Control for Game Agents | 2026-10-29 | cs.CV, cs.AI | Guangzhi Wang, Junfu Pu, Yiran Wang, Xingyilang Yin, Honghao Chen, Cheng Cheng, Lingen Li, Yinan Zhou, Jiarui Wu, Yinuo Jiang, Hongbo Jin, Xiaodong Cun, Ying Shan | 0 | + +| 2 | 2610.40250 | Distributional Reward Calibration and Budget-Neutral Credit Assignment for Multimodal RLVR | 2026-10-29 | cs.AI | Lang Chen, Zongxin Xu, Borui Wang, Anran Liu, Shitong Chen | unmeasured | + +| 3 | 2610.40002 | How Much Should a VLA Trust Its Reasoning? Step-Level Guidance as a Measured Action-Value Function | 2026-10-29 | cs.RO, cs.CV, cs.LG | Dabin Seo, Eunhyek Joa | unmeasured | + +| 4 | 2610.39251 | Where to Learn and How Far to Roll Out: Efficient Adaptive Training for GUI Agents | 2026-10-29 | cs.AI | Yuxiang Chai, Quyu Kong, Panrong Tong, Steven Hoi, Yue Wang | unmeasured | + +| 5 | 2610.39182 | Reasoning or Pattern Exploitation? Mechanistic Insights from RL-Trained Language Models | 2026-10-29 | cs.AI, cs.CL | Aishik Nagar, Cheston Tan | unmeasured | + +| 6 | 2610.39056 | When Does Closed-Loop Curriculum Adaptation Help GRPO? An Analysis on Countdown | 2026-10-28 | cs.LG, cs.AI | Yuv Raj Pant, Moshiur Rahman Tonmoy, Kaiqun Fu | unmeasured | + +| 7 | 2610.38404 | CoWalk: Cooperative Walks for Agentic Batch Queries on Disk-Resident Graphs | 2026-10-28 | cs.DB, cs.IR | Qiao Liang, Zhiguang Chen, Yue Yu, Nong Xiao | unmeasured | + +| 8 | 2610.38391 | SCOPE: Selective Critical-Step On-Policy Self-Distillation for Agentic Reinforcement Learning | 2026-10-28 | cs.AI | Qirui Liu, Wei Cao, Yu Mi, Yichen Sun, Xuekun Zhang, Lei Liu, Yue Shen, Zhixuan Chu | unmeasured | diff --git a/wizard-work/ledger/arxiv-grpo-top8.rows.json b/wizard-work/ledger/arxiv-grpo-top8.rows.json new file mode 100644 index 0000000..3e81b85 --- /dev/null +++ b/wizard-work/ledger/arxiv-grpo-top8.rows.json @@ -0,0 +1,74 @@ +[ + { + "arxiv_id": "2610.40276", + "title": "TaskFrame: Connecting Task-Level Planning with Frame-Level Control for Game Agents", + "published": "2026-10-29", + "categories": "cs.CV, cs.AI", + "authors": "Guangzhi Wang, Junfu Pu, Yiran Wang, Xingyilang Yin, Honghao Chen, Cheng Cheng, Lingen Li, Yinan Zhou, Jiarui Wu, Yinuo Jiang, Hongbo Jin, Xiaodong Cun, Ying Shan", + "abstract": "Building general game agents requires both high-level task reasoning and low-latency action control in rapidly changing visual environments. These capabilities favor models with substantially different computational profiles, making them difficult to realize within a single model. In this work, we present TaskFrame, a hierarchical planner-controller framework that connects task-level planning with frame-level keyboard-and-mouse control. A vision-language task planner decomposes a high-level goal into an ordered sequence of atomic instructions and is optimized through supervised learning and dependency-aware GRPO. The hidden states of special goal tokens that terminate each atomic instruction provide continuous goal embeddings that are cached and reused across control steps. A causal Transformer controller combines the embedding of the active goal with recent observations to predict discrete keyboard and mouse-button actions and continuous camera motion at every game step. We train the system in three stages: planner training, controller pretraining, and joint alignment. Experiments in Minecraft show that TaskFrame is competitive with general-purpose vision-language models on instruction decomposition, and that in closed-loop evaluation the agent achieves a higher combat success rate than the evaluated baselines.", + "citations": 0 + }, + { + "arxiv_id": "2610.40250", + "title": "Distributional Reward Calibration and Budget-Neutral Credit Assignment for Multimodal RLVR", + "published": "2026-10-29", + "categories": "cs.AI", + "authors": "Lang Chen, Zongxin Xu, Borui Wang, Anran Liu, Shitong Chen", + "abstract": "We revisit advantage estimation in Group Relative Policy Optimization (GRPO) and observe that any token-level advantage admits a two-stage factorization: a \\emph{sample-level baselining} step that converts scalar verifier rewards into a comparable sequence-level signal, and a \\emph{token-level credit assignment} step that distributes that signal over the trajectory. Existing estimators typically address only one of these stages: affine baselines preserve the shape of each task's reward law, so heavy tails and binary cliffs propagate into the gradient, while token-level credit rules tie the size of each token's update to raw confidence scales and need not conserve the total credit issued by the verifier. We propose \\textbf{TACE} (Two-stage Advantage and Credit Estimation), a two-stage estimator that addresses both stages. At stage~(S1), we replace linear standardization with a one-dimensional optimal-transport map to a standard normal, which gives a common population reward law across tasks and caps finite-sample outliers deterministically. At stage~(S2), we rank-calibrate a stop-gradient evidence contrast within each trajectory and renormalize the clipped token weights to have mean one, so credit is redistributed across tokens while its total mass and sign are conserved. We prove population-level inter-task moment equity, a deterministic tail bound, and mass-conservation, boundedness, and sign-anchoring properties that affine baselines and unnormalized token weights do not satisfy. On a multimodal reasoning suite, TACE obtains the strongest results on a majority of the benchmarks but does not dominate every setting.", + "citations": "unmeasured" + }, + { + "arxiv_id": "2610.40002", + "title": "How Much Should a VLA Trust Its Reasoning? Step-Level Guidance as a Measured Action-Value Function", + "published": "2026-10-29", + "categories": "cs.RO, cs.CV, cs.LG", + "authors": "Dabin Seo, Eunhyek Joa", + "abstract": "Reasoning vision-language-action (VLA) policies write a reasoning trace and then decode the action from it. A wrong trace yields a wrong action, and even a correct-looking trace can mislead the plan. Existing remedies ask whether the reasoning is right. We ask how strongly it should steer. CoC-CFG applies classifier-free guidance between the policy's context and the same context without the reasoning span. One weight per Euler step attenuates or amplifies the reasoning, and w=1 recovers the original policy. We treat the choice of this weight as a Markov decision process whose action values are measured, not bootstrapped. With the expert frozen and the noise fixed, applying a weight for one step and finishing the plan under the current controller returns that weight's value exactly. Q-adaptive guidance fits these values with small critics and improves the controller conservatively. In the Alpasim driving simulator it outperforms every fixed weight and online RL (SAC, GRPO) in open loop, and in closed loop it passes 262 of 300 scenes, against 252 for the original policy. On held-out frames of the Waymo end-to-end driving benchmark, its first three stages outperform every fixed weight, four adaptive-guidance methods, SAC and GRPO. On the hidden test set, a frozen Alpamayo 1.5 with rule-based camera and vehicle conversions and Q-adaptive guidance sets a new state of the art among published methods: 8.135159 rater feedback score, against 8.079 for the best published method.", + "citations": "unmeasured" + }, + { + "arxiv_id": "2610.39251", + "title": "Where to Learn and How Far to Roll Out: Efficient Adaptive Training for GUI Agents", + "published": "2026-10-29", + "categories": "cs.AI", + "authors": "Yuxiang Chai, Quyu Kong, Panrong Tong, Steven Hoi, Yue Wang", + "abstract": "Trajectory-level GRPO is a common approach for training multi-step GUI agents, but repeatedly rolling out complete trajectories from the task root can be inefficient: task-level rewards provide coarse supervision over which intermediate decisions require improvement, while already-mastered prefixes are repeatedly re-executed before reaching difficult states. We introduce a two-stage adaptive training framework that jointly addresses where to learn and how far to roll out. We first construct reusable intermediate checkpoints from successful expert trajectories and select informative pivots using action disagreement, which measures uncertainty directly from sampled GUI actions. Stage I performs one-step RL at these pivots to improve uncertain local decisions. Stage II then progressively expands policy responsibility through adaptive Local, Suffix, and Root training according to task progress. Recoverable checkpoints enable repeated training from intermediate states without replaying the preceding trajectory. Across MobileGym and CUA-Gym-Hub, our method reduces environment interaction by 56-61% relative to Vanilla GRPO while improving task performance, demonstrating that jointly allocating training across states and rollout ranges can substantially improve GUI-agent RL efficiency.", + "citations": "unmeasured" + }, + { + "arxiv_id": "2610.39182", + "title": "Reasoning or Pattern Exploitation? Mechanistic Insights from RL-Trained Language Models", + "published": "2026-10-29", + "categories": "cs.AI, cs.CL", + "authors": "Aishik Nagar, Cheston Tan", + "abstract": "Large language models (LLMs) are increasingly described as acquiring \"reasoning\" skills after reinforcement learning with verifiable rewards. However, whether these gains reflect genuine reasoning or more superficial adaptations remains underexplored. In this work, we probe LLMs trained in a finite and exhaustively analyzable logical domain, namely Tic-Tac-Toe, and trace how internal representations evolve across reinforcement learning (RL) with Group Relative Policy Optimization (GRPO). Quantitatively, RL yields high accuracy and robustness across prompt variations, suggesting the emergence of game reasoning. Mechanistic interpretability, however, paints a different picture: features extracted with sparse autoencoders (SAEs) reveal that models primarily adapt to rely more heavily on information already explicit in the prompt, such as whose turn it is, game progression and board occupancy. In comparison, high-level concepts like board symmetries and strategic forks remain weakly represented, raising concerns that reasoning benchmarks overestimate model abilities. This suggests that RL-driven \"reasoning\" may conflate task-specific adaptations to input information with reasoning ability. We provide, for the first time: (i) a systematic interpretability pipeline tracing representation dynamics across RL training in small-scale LLMs; (ii) an extension of SAE-based feature discovery to hypothesis-driven testing in a finite logical domain; and (iii) an interpretability-based demonstration that RL post-training neither adds nor removes concept information but reorganizes which features dominate the representation, with causal interventions locating the decision downstream of it, in the late-layer state.", + "citations": "unmeasured" + }, + { + "arxiv_id": "2610.39056", + "title": "When Does Closed-Loop Curriculum Adaptation Help GRPO? An Analysis on Countdown", + "published": "2026-10-28", + "categories": "cs.LG, cs.AI", + "authors": "Yuv Raj Pant, Moshiur Rahman Tonmoy, Kaiqun Fu", + "abstract": "Reinforcement fine-tuning has become an effective post-training paradigm for improving the reasoning ability of large language models, but it remains sample-inefficient when the training distribution is mismatched to the model's current capability. In group-relative objectives such as Group Relative Policy Optimization (GRPO), problems that are too hard often produce uniformly failed rollouts, while problems that are too easy provide little useful advantage signal. In this work, we introduce CLOSEDLOOPGAUSSIAN, a lightweight adaptive curriculum method for efficient reinforcement fine-tuning on ordered reasoning tasks. Instead of following a fixed easy-to-hard schedule, CLOSEDLOOPGAUSSIAN preserves the structure of an Easy-to-Hard Gaussian sampler while dynamically adjusting its pace and spread using periodic probe estimates of per-difficulty accuracy. The controller accelerates training when the model is ahead of a reference curriculum, slows down when the model falls behind, and broadens sampling when earlier difficulties regress. This feedback mechanism keeps training focused on tasks that are challenging but still learnable, without changing the reward function, model architecture, or underlying GRPO optimizer. Experiments on symbolic arithmetic reasoning task show that CLOSEDLOOPGAUSSIAN improves exact-match accuracy over vanilla GRPO and fixed open-loop curricula, with the strongest gains in intermediate-difficulty regimes where group-relative learning signals are most informative. Codes are available at https://github.com/yuvrajpant56/Closed_Loop_Curriculum.", + "citations": "unmeasured" + }, + { + "arxiv_id": "2610.38404", + "title": "CoWalk: Cooperative Walks for Agentic Batch Queries on Disk-Resident Graphs", + "published": "2026-10-28", + "categories": "cs.DB, cs.IR", + "authors": "Qiao Liang, Zhiguang Chen, Yue Yu, Nong Xiao", + "abstract": "Workloads such as query rewriting, deep research and group-relative policy optimization (GRPO) issue batches of semantically related vector queries. Existing disk-resident approximate nearest neighbor (ANN) systems process these queries independently. On three workloads, 31 to 67 percent of the I/Os of a batch fetch a page that another query of the batch has already fetched. A page cache shared by the batch removes these I/Os, yet it makes a single-thread search only $1.1$ to $1.2{\\times}$ faster, because the search time goes to distance computation and the cache does not change the walk of any query. We present CoWalk, which runs the queries of a batch as cooperating walks on one thread. Every query keeps its own candidate list, a page is read once per batch, and the full-precision vector on every fetched page is ranked by every query of the batch. A query therefore reaches the target recall with a shorter candidate list, which computes fewer distances and issues fewer I/Os. At recall@10 of 0.95, CoWalk answers a batch on one thread $1.6$ to $1.9{\\times}$ faster than the fastest per-query baseline and issues $2.8$ to $6.9{\\times}$ fewer I/Os. On a server it serves $3.0$ to $6.9{\\times}$ the throughput of that baseline at a similar batch latency.", + "citations": "unmeasured" + }, + { + "arxiv_id": "2610.38391", + "title": "SCOPE: Selective Critical-Step On-Policy Self-Distillation for Agentic Reinforcement Learning", + "published": "2026-10-28", + "categories": "cs.AI", + "authors": "Qirui Liu, Wei Cao, Yu Mi, Yichen Sun, Xuekun Zhang, Lei Liu, Yue Shen, Zhixuan Chu", + "abstract": "Outcome-based reinforcement learning provides coarse supervision for long-horizon LLM agents: failed trajectories may contain correct steps, while successful trajectories can contain errors. Trajectory-level skills can also shift teacher preferences at unrelated steps, introducing off-target distillation signals. We introduce SCOPE, a framework for Selective Critical-Step On-Policy Self-Distillation. After a supervised warm-up, the policy analyzes its own trajectories, generates step-specific hindsight skills, and distills their guidance only at selected error steps. A bounded signed teacher-student coefficient stabilizes auxiliary updates while preserving positive reinforcement and negative correction. A success-relative pairwise length reward further encourages efficient task completion. Experiments on ALFWorld and WebShop demonstrate consistent improvements across multiple model backbones. With Qwen2.5-3B, SCOPE achieves 97.7% success on ALFWorld and 85.2% on WebShop, outperforming SEED by 5.9 and 6.3 percentage points, respectively. On unseen ALFWorld tasks, SCOPE reaches 89.6% success, improving over GRPO by 23.2 percentage points with 46.7% fewer interactions. Scaling to Qwen3-32B, SCOPE achieves 99.2% success on seen ALFWorld tasks and 94.0% on unseen tasks.", + "citations": "unmeasured" + } +] \ No newline at end of file diff --git a/wizard-work/ledger/check_2026-11-01-commit-census b/wizard-work/ledger/check_2026-11-01-commit-census new file mode 100755 index 0000000..4f2a908 --- /dev/null +++ b/wizard-work/ledger/check_2026-11-01-commit-census @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +"""Verifier for repo-2026-11-01-commit-census.tsv. + +The daily commit-author census is a SNAPSHOT of the repo at revision +BASELINE (d27c03f0e4651c9a4ee9323830d6d795f0d2b40a), taken before the ledger +census commit landed. HEAD moves as later commits (including this pipe's own +ledger commits) are added, so the check must regenerate from BASELINE, not from +the moving HEAD. + +Re-derives the 2026-11-01 commit-author census from git at BASELINE and compares +it against the artifact. Exit code 0 = artifact matches git (verdict correct), +nonzero = mismatch. + +Usage: python3 check_2026-11-01-commit-census.py +""" +import subprocess +import sys + +REPO = "/root/troupe-standup" +TSV = "/root/.hermes/wizard-outputs/ledger/repo-2026-11-01-commit-census.tsv" +DATE = "2026-11-01" + +# Revision the snapshot was taken from. bdfb48a (the ledger census commit) sits +# on top of this; it must not be part of the data it describes. +BASELINE = "d27c03f0e4651c9a4ee9323830d6d795f0d2b40a" + +WIZARD_BY_EMAIL = { + "timmy@stackchain.ai": "Timmy", + "timmy@alexanderwhitestone.com": "Timmy", + "timmy@agents.invalid": "Timmy", + "timmy@stackchain.invalid": "Timmy", + "timmy@hermes": "Timmy", + "timmy@stacktimmy.invalid": "Timmy", + "timmy@localhost": "Timmy", + "timmy@alexandrewswhitestone.com": "Timmy", + "timmy@stachain.ai": "Timmy", + "zephyrus-sparkborn@agents.invalid": "Zephyrus Sparkborn", + "zephyrus-sparkborn@users.noreply.forge.alexanderwhitestone.com": "Zephyrus Sparkborn", + "zephyrus-sparkborn@users.noreply.github.com": "Zephyrus Sparkborn", + "zephyrus-sparkborn@noreply.local": "Zephyrus Sparkborn", + "zephyrus@alexanderwhitestone.com": "Zephyrus Sparkborn", + "cassian@agents.invalid": "Cassian Assayborn", + "cassian@forge.local": "Cassian Assayborn", + "volt@agents.invalid": "Volt", + "volt@troupe.invalid": "Volt", + "volt@troupe.local": "Volt", + "volt@stackchain.local": "Volt", + "volt@alexanderwhitestone.com": "Volt", + "volt@stackchain.ai": "Volt", + "ledger@agents.invalid": "Ledger", + "forge@agents.invalid": "Forge", + "mercury@agents.invalid": "Mercury", + "merlin@agents.invalid": "Merlin", + "sol@agents.invalid": "Sol", + "quill@agents.invalid": "Quill", + "sphinx@agents.invalid": "Sphinx", + "null@agents.invalid": "Null", + "argus@agents.invalid": "Argus", + "argus@troupe": "Argus", + "sentinel@troupe-standup.internal": "Sentinel", + "beam@agents.invalid": "Beam", + "troupe-pipe@agents.invalid": "Troupe-pipe", + "pipe@localhost": "Pipe", +} + +def git(*args): + return subprocess.run( + ["git", "-C", REPO] + list(args), check=True, capture_output=True, text=True + ).stdout + +def recompute(): + rows = [] + for line in git("log", BASELINE, "--format=%an\t%ae\t%aI\t%H\t%s").splitlines(): + p = line.split("\t") + if len(p) == 5 and p[2].startswith(DATE + "T"): + rows.append(p) + groups = {} + for name, email, adate, sha, subject in rows: + wizard = WIZARD_BY_EMAIL.get(email, "Unmapped") + groups.setdefault(wizard, []).append((adate, sha)) + out = [] + for wizard, recs in groups.items(): + recs.sort() + out.append({ + "wizard": wizard, + "commits": len(recs), + "first_commit": recs[0][0], + "last_commit": recs[-1][0], + "latest_sha": recs[-1][1], + }) + return out + +def main(): + expected = recompute() + expected.sort(key=lambda r: (-r["commits"], r["wizard"])) + + with open(TSV, encoding="utf-8") as f: + lines = [ln for ln in f.read().splitlines() if ln.strip()] + header, data = lines[0], lines[1:] + + problems = [] + if header != "wizard\tcommits\tfirst_commit\tlast_commit\tlatest_sha\tsubjects": + problems.append(f"header={header!r}") + + if len(data) != len(expected): + problems.append(f"row count: artifact={len(data)} git@baseline={len(expected)}") + + total_expected = sum(r["commits"] for r in expected) + total_artifact = sum(int(r.split("\t")[1]) for r in data if len(r.split("\t")) == 6) + if total_expected != total_artifact: + problems.append(f"total commits: artifact={total_artifact} git@baseline={total_expected}") + + for i, (art, exp) in enumerate(zip(data, expected)): + fields = art.split("\t") + if len(fields) != 6: + problems.append(f"row {i}: {len(fields)} fields") + continue + wizard, commits, first, last, sha, subjects = fields + checks = [ + (wizard == exp["wizard"], f"row {i} wizard {wizard} != {exp['wizard']}"), + (int(commits) == exp["commits"], f"row {i} commits {commits} != {exp['commits']}"), + (first == exp["first_commit"], f"row {i} first {first} != {exp['first_commit']}"), + (last == exp["last_commit"], f"row {i} last {last} != {exp['last_commit']}"), + (sha == exp["latest_sha"], f"row {i} sha {sha} != {exp['latest_sha']}"), + ] + problems += [msg for ok, msg in checks if not ok] + + if problems: + print("REPO CENSUS MISMATCH") + for p in problems: + print(" -", p) + sys.exit(1) + + print(f"REPO CENSUS OK: snapshot at {BASELINE}; {len(expected)} wizard rows, " + f"{total_expected} commits on {DATE} match git") + sys.exit(0) + +if __name__ == "__main__": + main()