Conversation
…aron 2026-05-01) Aaron's session-long correction: Otto kept reaching for inline `gh pr view + jq` chains to refresh world model on tick wake, while `tools/github/poll-pr-gate.ts` already existed (v1 2026-04-30, 5-AI peer convergence, task #355) and did exactly that job with structured output. Aaron 2026-05-01 verbatim: "dynamic bash is forgotten bash once useful but never amortized" + "write a batch version of the ts that calls this one — not bash, not .sh, not .ps1, not dyanamic bash." Three landings: 1. tools/github/poll-pr-gate-batch.ts (new) — wraps the single-PR script via async parallel spawn, bounded concurrency (default 4), aggregate JSON output with per-PR GateReport array + summary (byGate / byNextAction / byState / actionable / warnings). Modes: explicit PR numbers, `--all-open`, `--summary-only`. Literal "calls this one" wrap — no logic duplication, just orchestration. Live-tested on 5 merged PRs (concurrency=3): clean structured output, parallel coordination works. 2. CLAUDE.md — new wake-time bullet pointing at both tools/github/poll-pr-gate*.ts as canonical refresh- world-model tools (alongside verify-before-deferring, future-self-not-bound, never-be-idle, version-currency, substrate-or-it-didn't-happen). Updated existing BLOCKED-with-green-CI bullet to reference the TS script's structured fields (`gate`, `requiredChecks.failed`, `unresolvedThreads`) instead of inline `gh pr view + jq` patterns — the bad pattern is now retired from the load-bearing instruction. 3. memory/feedback_prefer_ts_scripts_over_dynamic_bash_*.md — extended with worked-example section pointing at both poll-pr-gate.ts and poll-pr-gate-batch.ts as the canonical amortized form. Second carved-sentence candidate: "Dynamic bash is forgotten bash — once useful but never amortized. The named TS script pays the amortization cost once; the named TS script is the substrate." Closes the goldfish-ontology loop on this specific failure mode: future-Otto encounters the wake-time pointer at CLAUDE.md scope (100% loaded every session) and can't miss the existence of the TS scripts. Reaching for inline `gh pr view + jq` after this is now an explicit violation, not an oversight. Composes with task #355 (5-AI peer convergence on poll-the-gate as executable script with fixtures). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: baaab52ade
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…de for poll-pr-gate*.ts Extends the dynamic-bash row description to point at the PR #1153 worked-example (poll-pr-gate.ts + poll-pr-gate-batch.ts as canonical refresh-world-model substrate) and surface the 2nd carved-sentence candidate from the body file. Clears the non-required `check memory/MEMORY.md paired edit` lint warning for PR #1153 and keeps the index current. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…1153 opened: poll-pr-gate-batch.ts + CLAUDE.md wake-time pointer) (#1154) Aaron's stacked directive closed the goldfish-ontology loop on the session-long bash-vs-TS drift. Three substrate landings on PR #1153: tools/github/poll-pr-gate-batch.ts (new, async parallel wrap of v1 single-PR script), CLAUDE.md wake-time bullet, memory file worked-example extension. Live-tested batch script on 26 open LFG PRs. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new Bun/TypeScript tool to batch-query PR “gate” status by orchestrating the existing single-PR poll-pr-gate.ts, and updates CLAUDE/memory docs to make these scripts the canonical “refresh world model” mechanism (instead of inline gh + jq).
Changes:
- Add
tools/github/poll-pr-gate-batch.tsto poll multiple PRs with bounded concurrency and emit aggregate JSON (per-PR reports + summary + errors). - Extend the TS-over-bash memory entry with a worked example referencing the poll-pr-gate scripts.
- Update
CLAUDE.mdwake-time guidance to point at the poll-pr-gate scripts and reference their structured output fields.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| tools/github/poll-pr-gate-batch.ts | New batch wrapper around poll-pr-gate.ts with concurrency control and aggregated JSON output. |
| memory/feedback_prefer_ts_scripts_over_dynamic_bash_for_conversation_ux_dst_in_ts_aaron_2026_05_01.md | Adds worked example + carved sentence candidate reinforcing TS-script canonicalization. |
| CLAUDE.md | Adds wake-time pointer to poll-pr-gate scripts and updates BLOCKED-with-green-CI guidance to reference JSON fields. |
…pi --paginate` (Codex P2) Codex 2026-05-01 review on PR #1153 thread #L201: > --all-open silently truncates results to the first 1000 PRs > because gh pr list is called with a fixed --limit 1000 and > no pagination/follow-up fetch. In repositories that exceed > 1000 open PRs, the batch summary and actionable set become > incomplete without any warning, which can misclassify queue > health and skip blocked PRs. Valid finding. Fix: replace with `gh api --paginate /repos/{owner}/{repo}/pulls?state=open&per_page=100`. Pagination follows Link headers automatically; each page emits a JSON array on its own stdout line; concatenation produces the full PR-number set with no silent truncation. Live-tested on LFG queue: returns full 27-PR set (was 26 prior query + #1153 newly open) with no truncation. Per-page count of 100 (GitHub max) minimizes round-trip overhead. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…lFn (Aaron 2026-05-01) Aaron 2026-05-01: *"and you can DST it"* — exercise the DST-grade-A capability that the TS port unlocks (per memory/feedback_prefer_ts_scripts_over_dynamic_bash_*.md Why-3: "DST is bascically impossible there [in bash], not in ts"). Two changes: 1. Refactor `pollAllBounded` to take an injectable `pollFn` (defaulted to the real `pollOne`). Exports `summarize`, `pollAllBounded`, and the public type surface (`GateReport`, `BatchSummary`, `BatchReport`, `PollOutcome`, `PollError`, `CheckCounts`) so tests can construct synthetic inputs deterministically. 2. New `tools/github/poll-pr-gate-batch.test.ts` — 10 tests in 152ms, zero `gh` spawns, zero network, zero clock dependencies. All inputs fixed; all outputs verifiable under the DST contract (same input → same output, every run, every machine). Coverage: - `summarize`: empty input, multi-axis counting, actionable exclusion contract (none/verify-merge filtered), per-PR-prefixed warnings, input-order preservation. - `pollAllBounded`: input-order preserved across out-of-order resolution (staggered timeout test verifies workers race correctly), concurrency bound respected (peak in-flight == N), worker-count clamping when PRs < concurrency, empty input edge case, error propagation without exception cascade. The error-propagation test encodes a load-bearing invariant: a single PR failure (auth, rate-limit, JSON parse) MUST NOT cascade and lose other PRs' results. Errors surface as `PollOutcome.error` so the caller partitions success/failure deterministically — that's the DST-grade-A guarantee bash couldn't carry. Worked-example proof for the dynamic-bash memory file's load-bearing claim: TS unlocks DST coverage that bash structurally cannot achieve. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5848fa1612
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Adds a batch/parallel “poll PR gate” tool to refresh GitHub PR status across many PRs in one call, and updates operational docs/memory to point to the TS tooling instead of ad-hoc gh ... | jq chains.
Changes:
- Introduces
tools/github/poll-pr-gate-batch.tsto runpoll-pr-gate.tsin parallel with bounded concurrency and aggregate JSON output. - Adds deterministic tests for the orchestration (
pollAllBounded) and summarization (summarize) logic. - Updates
CLAUDE.md+ memory docs/index to promote the TS scripts as the canonical “refresh world model” mechanism.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/github/poll-pr-gate-batch.ts | New batch polling CLI that spawns the existing single-PR tool and aggregates results |
| tools/github/poll-pr-gate-batch.test.ts | Adds deterministic tests for bounded concurrency + aggregation behavior |
| memory/feedback_prefer_ts_scripts_over_dynamic_bash_for_conversation_ux_dst_in_ts_aaron_2026_05_01.md | Extends memory with a worked example pointing to the new batch tool |
| memory/MEMORY.md | Updates the memory index entry to reference the worked example and tools |
| CLAUDE.md | Adds/updates wake-time guidance to use poll-pr-gate TS tooling for gate refresh |
…sona-on-current-state-surface rule PR #1153 review threads from Codex + Copilot: (1) Copilot: requireValue accepts -h as a value when prefix is just `--`. `--owner -h` would silently consume `-h` as the flag value. Fix: reject any value starting with `-` (matches pattern in tools/github/check-github-status.ts). (2) Copilot: spawn() with explicit stdio:['ignore','pipe','pipe'] gives TypeScript nullable child.stdout/stderr, breaking strict tsc. Fix: omit stdio (default ['pipe','pipe','pipe']) and explicitly close child.stdin since we never write to it. Now streams are non-null typed. (3) Copilot + Codex (P1/P2 dup): listOpenPRs assumed `gh api --paginate` emits one JSON array per stdout line, but page bodies for REST endpoints can be pretty-printed across multiple lines. Line-split-then-parse would fail with fragments like `[`. Fix: use `--jq '.[].number'` to project each page to one PR number per line — line-oriented primitive output is unambiguous regardless of page-body formatting. (4) Copilot: CLAUDE.md and tools/github/poll-pr-gate-batch.ts header used named persona attribution ("Aaron 2026-05-01") on current-state surfaces. Per the persona-name rule documented in CLAUDE.md itself ("On current-state surfaces — code, skill bodies, behavioural docs, public prose — use role-refs, not persona names"), full attribution lineage belongs in memory/ files (history surface). Fix: replace "Aaron 2026-05-01" with "the human maintainer 2026-05-01" in CLAUDE.md bullet + de-name the script header (the verbatim quote was removed; lineage pointer to memory file remains). Tests: 10 pass / 0 fail / 158ms — DST coverage holds across the 4-change refactor. Live-tested `--all-open` on LFG queue: 29 PRs with full structured aggregate. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ck (PRs #1153 +2 commits, #1155 opened) (#1156) Three landings this tick: (1) Codex P2 fix on poll-pr-gate-batch.ts (`gh api --paginate` replaces `gh pr list --limit 1000` to handle queues over 1000 PRs without silent truncation). (2) DST test suite: 10 tests in 152ms, zero gh spawns, exercises pure functions + injectable pollFn — worked-example proof for the dynamic-bash memo's load-bearing claim "DST is achievable in TS." (3) New SQLSharp-bun-ts-pattern memory file (PR #1155) capturing Aaron's external-anchor lesson: super-strongly-typed dependencies-as-interface DI pattern, not js-in-ts failure mode. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…r rejects (Copilot P0) Copilot P0 on PR #1153: pollAllBounded would reject if pollFn threw or returned a rejected promise — contradicts the function's own "must never throw" contract and would abort the whole batch on a single unexpected failure. Fix: wrap `await pollFn(...)` in try/catch inside the worker loop. Convert any rejection into a PollOutcome.error entry with exitCode -1 and stderr "pollFn rejected: <message>". Promise.all on the workers now always resolves regardless of pollFn's behavior. New test asserts the invariant: a synthetic Promise.reject from one of the PRs becomes a PollOutcome.error in the right slot, and the other PRs' results land normally. Test count: 11 / 0 / 131ms. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a Bun/TypeScript batch wrapper around the existing single-PR GitHub gate polling script, and updates wake-time guidance/docs to point contributors at the canonical scripts rather than ad-hoc gh + jq chains.
Changes:
- Add
tools/github/poll-pr-gate-batch.tsto poll many PRs with bounded concurrency and emit aggregate JSON (summary + per-PR reports + per-PR errors). - Add deterministic Bun tests for batch orchestration (
pollAllBounded) and summary aggregation (summarize). - Update
CLAUDE.md+ memory documentation/index to point at the poll-pr-gate scripts as the canonical “refresh world model” tooling.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/github/poll-pr-gate-batch.ts | New batch polling CLI wrapping poll-pr-gate.ts, adds bounded concurrency + aggregate JSON output. |
| tools/github/poll-pr-gate-batch.test.ts | New Bun tests covering summary aggregation + bounded-concurrency orchestration with injected pollFn. |
| memory/feedback_prefer_ts_scripts_over_dynamic_bash_for_conversation_ux_dst_in_ts_aaron_2026_05_01.md | Extends the memory entry with a worked example pointing at the new batch tool. |
| memory/MEMORY.md | Updates the memory index entry to reference the worked example + new batch script. |
| CLAUDE.md | Adds wake-time guidance to use the TS scripts, and updates the BLOCKED-with-green-CI instruction to reference structured fields from poll-pr-gate.ts. |
|
|
||
| export async function main(argv: string[]): Promise<number> { | ||
| const args = parseArgs(argv); | ||
| const prs = args.allOpen ? listOpenPRs(args.owner, args.repo) : args.prs; |
| // Per Aaron 2026-05-01 (the rule this tool was written to satisfy): | ||
| // *"DST is bascically impossible there [in bash], not in ts."* These | ||
| // tests are the worked-example proof that a TS tool ported from a bash | ||
| // equivalent can carry DST grade-A coverage that the bash form | ||
| // structurally cannot. |
| const pollFn = (pr: number): Promise<PollOutcome> => | ||
| new Promise((res) => { | ||
| // First-in-last-out staggered delay: PR 1 takes longest, | ||
| // PR 5 finishes first. If outcomes were appended in | ||
| // completion order, the order would be [5,4,3,2,1] not [1..5]. | ||
| const delay = (6 - pr) * 5; | ||
| setTimeout(() => { | ||
| completionOrder.push(pr); | ||
| res({ number: pr, report: mkReport({ number: pr }) }); | ||
| }, delay); | ||
| }); | ||
| const outcomes = await pollAllBounded([1, 2, 3, 4, 5], "o", "r", 5, pollFn); | ||
| expect(outcomes.map((o) => o.number)).toEqual([1, 2, 3, 4, 5]); | ||
| // And confirm the staggered scheduling actually ran out-of-order: |
| level so it is 100% loaded at every wake. Full reasoning: | ||
| `memory/feedback_otto_357_no_directives_aaron_makes_autonomy_first_class_accountability_mine_2026_04_27.md`. | ||
| - **Refresh world model via `tools/github/poll-pr-gate.ts` | ||
| / `poll-pr-gate-batch.ts` — never inline |
…PRs #1153 +2 commits, #1155 +1 commit) (#1157) Three commits across two PRs draining 11 unresolved review threads (1 outdated + 10 real-fix from Codex + Copilot): - 6b8c743 (#1153): 4 fixes — requireValue rejects `-` prefix, spawn drops explicit stdio for non-null typing, listOpenPRs uses --jq for line-oriented output, de-name attribution per persona-on-current-state-surface rule - 9e12f3f (#1153): try/catch around pollFn — orchestrator never rejects (Copilot P0). New DST test asserts invariant. - cea6017 (#1155): MEMORY.md dup-row removal + de-absolute SQLSharp path All threads resolved. Both PRs now wait-ci with no warnings. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…ith fixtures" gap (#1158) Task #355 promised "Poll-the-gate as executable script with fixtures" — the fixture set (7 JSON files under tools/github/fixtures/) landed in v1, but no test runner exercised them. The fixtures were unused infrastructure. This commit closes the gap. Two minimal changes: (1) tools/github/poll-pr-gate.ts: add `export` to PullRequestData, CheckCounts, GateReport, buildReport, and loadFixture so they can be imported into the test file. Pure additive — no behavior change, CLI surface unchanged. (2) tools/github/poll-pr-gate.test.ts (new): fixture-driven DST suite. 28 tests / 162 expects / 51ms / zero gh spawns. Per-fixture coverage: - clean-armed-auto-merge.json → CLEAN gate, autoMerge armed - blocked-by-threads.json → BLOCKED with resolve-threads (the exact scenario the BLOCKED-with-green-CI wake-time bullet targets) - dirty-auto-merge-armed.json → DIRTY gate, rebase next action - behind-needs-rebase.json → BEHIND collapses to DIRTY (Copilot P0 from v1 hardening) - non-required-failure-warning.json → v1 hardening's load-bearing case: non-required check failure produces warning, not gate failure - status-context-error.json → StatusContext ERROR maps to blocking conclusion (Codex P1 normalization) - unknown-mergeability-pending-recompute.json → UNKNOWN mergeStateStatus surfaces honestly Cross-fixture invariants (test.each across all 7): - checks counts are non-negative integers - requiredChecks counts bounded by total checks (subset invariant) - nextAction consistent with gate state (DIRTY→rebase, MERGED→verify-merge, CLOSED→none, requiredChecks.failed>0 → fix-failed-checks) Worked-example proof — paired with the batch tool's DST suite landed in PR #1153, the v1 single-PR script now also carries DST grade-A coverage. Both halves of task #355's deliverable ("executable script" + "with fixtures") are now substrate. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…un/ts DI pattern (Aaron 2026-05-01) Aaron 2026-05-01 four-message clarification stack pointed at `../SQLSharp` as the bun/ts best-practices anchor — distinct from DST anchor (a different repo carries that), this is the "super strongly typed" pattern Otto should write toward. The discriminating axis is "not js-in-ts failure mode" — TS that carries design invariants in compiler-checked types vs TS that is JS with .ts extension and any escapes. Pattern (from `../SQLSharp/tools/automation/format/format-repo.ts`): 1. `Dependencies` interface for every external call surface (typeof X-keyed against production import). 2. `defaultDependencies` const wires production deps once. 3. Top-level functions take (args, options, deps?) triple. 4. Tests pass synthetic deps — no monkeypatching, no mock frameworks, just structural DI compiler-checked. 5. No any. No implicit any. Discriminated unions. readonly array params. Exhaustive type checks. Memory file documents: pattern definition + how-to-apply + worked-example gap analysis on poll-pr-gate-batch.ts (which landed PR #1153 with only `pollFn` injectable; full pattern would extract `spawnSync`, `process.exit`, `process.stdout`, `new Date()` to a BatchPollDependencies interface). Follow-up refactor target tracked. Composes with: - prefer-TS-over-bash (this rule names the target shape) - DST-grade-A pull-to-sibling-repo (SQLSharp IS one of the high-credibility instances of that rule) - detect-changes/parallel-optimization sibling-repo anchor (different anchor, different domain, same discipline) - post-install-TS strategy (TS is the target language; this rule names what good TS looks like) Carved sentence candidate: "Super-strongly-typed TS, not js-in-ts. Every external call surface in an interface. Every function takes its dependencies. The default const wires production; the test constructs the synthetic. The pattern IS the DST achievability vehicle." Pair-edit: MEMORY.md row added per memory-index-integrity rule. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…un/ts DI pattern (Aaron 2026-05-01) Aaron 2026-05-01 four-message clarification stack pointed at `../SQLSharp` as the bun/ts best-practices anchor — distinct from DST anchor (a different repo carries that), this is the "super strongly typed" pattern Otto should write toward. The discriminating axis is "not js-in-ts failure mode" — TS that carries design invariants in compiler-checked types vs TS that is JS with .ts extension and any escapes. Pattern (from `../SQLSharp/tools/automation/format/format-repo.ts`): 1. `Dependencies` interface for every external call surface (typeof X-keyed against production import). 2. `defaultDependencies` const wires production deps once. 3. Top-level functions take (args, options, deps?) triple. 4. Tests pass synthetic deps — no monkeypatching, no mock frameworks, just structural DI compiler-checked. 5. No any. No implicit any. Discriminated unions. readonly array params. Exhaustive type checks. Memory file documents: pattern definition + how-to-apply + worked-example gap analysis on poll-pr-gate-batch.ts (which landed PR #1153 with only `pollFn` injectable; full pattern would extract `spawnSync`, `process.exit`, `process.stdout`, `new Date()` to a BatchPollDependencies interface). Follow-up refactor target tracked. Composes with: - prefer-TS-over-bash (this rule names the target shape) - DST-grade-A pull-to-sibling-repo (SQLSharp IS one of the high-credibility instances of that rule) - detect-changes/parallel-optimization sibling-repo anchor (different anchor, different domain, same discipline) - post-install-TS strategy (TS is the target language; this rule names what good TS looks like) Carved sentence candidate: "Super-strongly-typed TS, not js-in-ts. Every external call surface in an interface. Every function takes its dependencies. The default const wires production; the test constructs the synthetic. The pattern IS the DST achievability vehicle." Pair-edit: MEMORY.md row added per memory-index-integrity rule. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…un/ts DI pattern (Aaron 2026-05-01) (#1155) * memory(ts-pattern): SQLSharp external anchor — super-strongly-typed bun/ts DI pattern (Aaron 2026-05-01) Aaron 2026-05-01 four-message clarification stack pointed at `../SQLSharp` as the bun/ts best-practices anchor — distinct from DST anchor (a different repo carries that), this is the "super strongly typed" pattern Otto should write toward. The discriminating axis is "not js-in-ts failure mode" — TS that carries design invariants in compiler-checked types vs TS that is JS with .ts extension and any escapes. Pattern (from `../SQLSharp/tools/automation/format/format-repo.ts`): 1. `Dependencies` interface for every external call surface (typeof X-keyed against production import). 2. `defaultDependencies` const wires production deps once. 3. Top-level functions take (args, options, deps?) triple. 4. Tests pass synthetic deps — no monkeypatching, no mock frameworks, just structural DI compiler-checked. 5. No any. No implicit any. Discriminated unions. readonly array params. Exhaustive type checks. Memory file documents: pattern definition + how-to-apply + worked-example gap analysis on poll-pr-gate-batch.ts (which landed PR #1153 with only `pollFn` injectable; full pattern would extract `spawnSync`, `process.exit`, `process.stdout`, `new Date()` to a BatchPollDependencies interface). Follow-up refactor target tracked. Composes with: - prefer-TS-over-bash (this rule names the target shape) - DST-grade-A pull-to-sibling-repo (SQLSharp IS one of the high-credibility instances of that rule) - detect-changes/parallel-optimization sibling-repo anchor (different anchor, different domain, same discipline) - post-install-TS strategy (TS is the target language; this rule names what good TS looks like) Carved sentence candidate: "Super-strongly-typed TS, not js-in-ts. Every external call surface in an interface. Every function takes its dependencies. The default const wires production; the test constructs the synthetic. The pattern IS the DST achievability vehicle." Pair-edit: MEMORY.md row added per memory-index-integrity rule. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(memory): remove duplicate MEMORY.md row + de-absolute SQLSharp path (Codex P1, Copilot P0) Two findings on PR #1155: (1) Codex P1 + Copilot P0 (duplicate finding): MEMORY.md had two rows for the dynamic-bash memory file (line 12 older form + line 14 extended form with worked-example footer). The duplicate was a cherry-pick artifact: my SQLSharp-row cherry-pick onto fresh main applied the row-add cleanly but git's 3-way merge also re-added the dynamic-bash row in its updated form rather than editing the original. The audit lint (tools/hygiene/audit-memory-index-duplicates.sh) enforces "one row per memory file" — Codex/Copilot caught the violation. Fix: remove the older (shorter) duplicate row. Keep the newer row with the worked-example footer pointing at poll-pr-gate*.ts. Memory index now satisfies the one-row-per-file invariant. (2) Copilot: caused_by referenced absolute filesystem path /Users/acehack/Documents/src/repos/SQLSharp/... — host- specific, not reproducible for other readers. Fix: replace with sibling-repo-relative `../SQLSharp/...` and note the absolute-path rationale inline. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(sqlsharp memo): use real package.json script names + drop hard-coded line numbers + reconcile identifier naming (3 Copilot threads) Three Copilot review threads on PR #1155: (1) 'bun run validate:typescript' doesn't exist in this repo's package.json. Replace with the actual scripts (bun run lint:typescript / typecheck / test:typescript). Add note: 'Check package.json for canonical names; don't trust generic command names.' (2) Hard-coded external line numbers ('formatRepo.ts line 14-26') drift as the external repo evolves. Replace with directional reference ('the FormatRepoDependencies interface near the top of the file') + pointer to verify via 'git -C ../SQLSharp log'. (3) Identifier inconsistency between formatRepo.ts (body) and format-repo.ts (frontmatter), and between defaultFormatRepoDependencies and formatRepoDependencies. Reconcile to format-repo.ts throughout + clarify the const is named defaultFormatRepoDependencies in the canonical file (using schematic 'default*Dependencies' for the rule itself). Pattern: hard-coded references to external repo state drift; use directional language + verification pointers instead. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…t (Claude.ai 2026-05-01) Claude.ai's calibrated follow-up to the refresh-before-decide packet identified Otto's narrow-refresh failure mode empirically: - 5:32pm refresh: 4 PRs - 5:37pm refresh: same 4 PRs - 5:40pm-5:50pm refresh: 2-3 PRs across 6 consecutive ticks - 5:50pm: PR #1170 'appeared out of nowhere' because prior 4 ticks' refresh scope didn't include it The narrow-refresh pattern hides cross-cutting state changes — PRs from other harnesses, auto-merge cascades, backlog deltas, claim file inventory, recent merges, branch state, pending CI runs. `poll-pr-gate-batch.ts` is correctly-scoped per its design (per-PR detail). The gap is the cross-cutting view. This row specs `tools/refresh-github-worldview/refresh.ts` — supersets poll-pr-gate-batch (calls it internally for per-PR detail), adds 5+ cross-cutting queries, two-layer print discipline, DST-grade-A test coverage with fixtures. Composes with refresh-before-decide memo (PR #1171), poll-pr-gate-batch (PR #1153), SQLSharp DI pattern memo (PR #1155). Phase 2+ deferred (Mirror/Beacon ratio gate, 22 named failure modes, DST scenario suite, pre-DORA metrics, dual-PM mode-selection) — each is its own future row. Per Claude.ai's caution: this row is the filing-not-implementation step. Don't context-switch mid-PR-cycle; let it flow through standard claim protocol when queue is quiet. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…t (Claude.ai 2026-05-01) (#1173) * backlog(B-0159): refresh-github-worldview cross-cutting refresh script (Claude.ai 2026-05-01) Claude.ai's calibrated follow-up to the refresh-before-decide packet identified Otto's narrow-refresh failure mode empirically: - 5:32pm refresh: 4 PRs - 5:37pm refresh: same 4 PRs - 5:40pm-5:50pm refresh: 2-3 PRs across 6 consecutive ticks - 5:50pm: PR #1170 'appeared out of nowhere' because prior 4 ticks' refresh scope didn't include it The narrow-refresh pattern hides cross-cutting state changes — PRs from other harnesses, auto-merge cascades, backlog deltas, claim file inventory, recent merges, branch state, pending CI runs. `poll-pr-gate-batch.ts` is correctly-scoped per its design (per-PR detail). The gap is the cross-cutting view. This row specs `tools/refresh-github-worldview/refresh.ts` — supersets poll-pr-gate-batch (calls it internally for per-PR detail), adds 5+ cross-cutting queries, two-layer print discipline, DST-grade-A test coverage with fixtures. Composes with refresh-before-decide memo (PR #1171), poll-pr-gate-batch (PR #1153), SQLSharp DI pattern memo (PR #1155). Phase 2+ deferred (Mirror/Beacon ratio gate, 22 named failure modes, DST scenario suite, pre-DORA metrics, dual-PM mode-selection) — each is its own future row. Per Claude.ai's caution: this row is the filing-not-implementation step. Don't context-switch mid-PR-cycle; let it flow through standard claim protocol when queue is quiet. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(B-0159): Deepseek refinements — delta-diff, provenance, stale_assumptions, perf target, tiered fallback (2026-05-01) Deepseek follow-up review identified 7 critical refinements: (1) Delta-diff over current-state-dump — Otto's deeper failure isn't refresh-not-run, it's refresh-not-integrated. Saw 27 open PRs at 5:37pm, noted count, moved on. Snapshot persistence at .zeta/refresh-snapshot.json enables actual deltas. (2) Provenance per PR — self / peer-call / maintainer / unknown. Computed mechanically from author. Unknowns are highest-priority signal. (3) stale_assumptions field — most operationally valuable. Refresh reports surprises, not just state. 'PR #X expected to merge by now, why hasn't it?' (4) Single JSON with summary field — match Otto's existing pattern (poll-pr-gate-batch.ts produces both layers in one output). Maintainer reads same JSON Claude reads; mismatch debuggable at boundary. (5) Performance target <5s typical tick + tiered fallback (degrade to poll-pr-gate-batch + 'stale at <timestamp>' if exceeded). Prevents bottleneck. (6) Backlog-row delta as git-derived (git diff --name-only HEAD~1 HEAD -- docs/backlog/), not frontmatter timestamps. Avoids B-0098-class metadata drift. (7) Recent merges via git log + post-hoc author bucketing. Unknown-author = highest priority. Plus refresh frequency recommendations + composing with poll-the-gate / manufactured-patience / never-idle / pre-commit lint for refresh artifacts. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(B-0159): add required YAML frontmatter (Codex P1 + Copilot dup) Codex P1 + Copilot duplicate finding on PR #1173: backlog rows require frontmatter (id, priority, status, title, created, last_updated) per tools/backlog/README.md schema. The .github/workflows/backlog-index-integrity.yml gate blocks PRs touching docs/backlog/** without it. Fix: add YAML frontmatter matching the canonical shape used by sibling P1 rows (B-0156 style). Includes depends_on: [B-0156] since the unified refresh script is part of the broader TS-standardization trajectory. Two additional Copilot dangling-pointer findings on the same PR: - docs/research/2026-05-01-claudeai-backlog-driven-dual-pm-loop-with-refresh-discipline.md - memory/feedback_refresh_before_decide_invariant_two_layer_print_dx_claudeai_2026_05_01.md Both were dangling at PR-open time because they were on PR #1171 which had not merged. PR #1171 has now merged to main; rebasing this branch resolves both. The branch is now up-to-date with origin/main and the cross-references resolve. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * substrate(B-0159): peer-AI absorption + git-native/github-state two-layer split (Aaron + 4 peer reviewers 2026-05-01) Two artifacts: (1) docs/research/2026-05-01-peer-ai-followup-reviews-on-b-0159-refresh-script.md — verbatim preservation of 4 peer-AI reviews (Ani / Alexa / Gemini / Amara) per substrate-or-it-didn't-happen + GOVERNANCE §33 trigger (multi-AI review packet preserve verbatim FIRST). Includes carved blades, cross-peer convergence (4/4 agree on aggregator-not-replacement + two-layer output + don't-context-switch + compose-with-existing-disciplines), and divergence preserved as alternatives (tool naming, snapshot persistence path). (2) B-0159 backlog row updated with two architectural decisions: ARCHITECTURE — TWO-LAYER GIT-NATIVE + GITHUB-API SPLIT (Aaron 2026-05-01 calibration of Amara's repo-state rename): - Layer 1: tools/repo-state/repo-state.ts — git-native, portable across hosts. Pure git ops + filesystem (backlog, claims, branch state, dirty flag). - Layer 2: tools/github/github-state.ts — wraps repo-state + poll-pr-gate-batch + adds GitHub API (PRs, CI, threads, reviews, workflows). GitHub-native. - Composes with feedback_git_native_vs_github_native_plural_host_pluggable_adapters_2026_04_23.md and feedback_first_class_for_us_not_for_our_host_*. PEER-AI CONSOLIDATED REQUIREMENTS: - Ani: idempotency + fail-closed (exit 10 on dirty/rebase), --raw flag, noise filter - Alexa: success criteria per phase, staleness detection, rollback procedures, cross-harness coordination, performance benchmarking - Gemini: macro/micro framing, strict sequence (don't context switch) - Amara: aggregator-not-replacement, flow metrics, unknown/unavailable per-source states, modular collectN() functions, persisted snapshot at .state/<layer>/last.json, --since/--write-state flags Aaron's calibration in same packet on time-estimation: 'you can't tell time without something like the previous state files you get how long thing took wrong all the time.' My 'X minutes' estimates throughout session are unanchored. Same persisted-snapshot mechanism that enables deltas would also anchor real durations. Filing as separate substrate target for next tick (time-estimation requires external timestamps, not internal feel). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(B-0159): --since placement + output-contract reconciliation (Codex P2 + Copilot P1) Two real findings on PR #1173: 1. Codex P2: `git log --since="..."` after `--` pathspec doesn't filter per git-log man page (options must precede pathspecs). Reordered to `git log --oneline --diff-filter=A --since="<ts>" -- docs/backlog/`. 2. Codex P2 + Copilot P1 (dup): output-format contradiction — row described two separate stdout passes (raw-then-interpretation) AND single JSON with `summary` field. Reconciled per Deepseek's single-JSON design: `summary` object IS the interpretation layer alongside raw arrays in one JSON document, one invocation. Mismatch between summary and underlying arrays is the bug class. Supersedes the two-pass framing earlier in the row. Two earlier dangling-pointer Copilot threads on this PR are now satisfied by main since #1171 landed (docs/research/2026-05-01-claudeai-backlog-driven-dual-pm-loop-with-refresh-discipline.md + memory/feedback_refresh_before_decide_invariant_two_layer_print_dx_claudeai_2026_05_01.md both exist on main). --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…nates pages without newlines so split('\\n')-then-parse silently dropped continuation pages on PRs with >100 review threads
Symptom: PR #1702 reported "JSON parse error: Unable to parse JSON
string" on first 200 bytes of valid-looking JSON. Root cause: `gh
api graphql --paginate` emits concatenated JSON objects with no
separator (3612 chars, 0 newlines for a 2-page response), unlike
the REST flavor of --paginate which is line-oriented. The previous
implementation split by '\\n' which produced one giant unparseable
"line" containing concatenated JSON pages.
Same failure class as poll-pr-gate-batch.ts:226 (Codex P2 + Copilot
P1 on PR #1153, 2026-05-01) — that one was fixed via `--jq` to
project to a primitive. For graphql-threads the structure is
nested (pageInfo + nodes), so manual pagination via endCursor is
the cleaner fix.
Verified: PR #1702 now reports unresolvedThreads=97 (was silently
dropped to <100 before). Composes with the post-force-push outdated
review thread rule -- explains why PR #1702 has stayed BLOCKED
with green CI.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
tools/github/poll-pr-gate-batch.ts(new) — async parallel wrap of v1 single-PRpoll-pr-gate.tswith bounded concurrency (default 4), aggregate JSON output (per-PRGateReport[]+ summary aggregate:byGate,byNextAction,byState,actionable,warnings). Modes: explicit PR list,--all-open,--summary-only. Literal "calls this one" wrap — no logic duplication, just orchestration.CLAUDE.md— new wake-time bullet pointing at bothtools/github/poll-pr-gate.ts+poll-pr-gate-batch.tsas canonical refresh-world-model tools (alongside verify-before-deferring, future-self-not-bound, never-be-idle, version-currency, substrate-or-it-didn't-happen). Updated existing BLOCKED-with-green-CI bullet to reference the TS script's structured fields (gate,requiredChecks.failed,unresolvedThreads) instead of inlinegh pr view + jqpatterns.memory/feedback_prefer_ts_scripts_over_dynamic_bash_*.md— extended with worked-example section pointing at both poll-pr-gate*.ts as canonical amortized form. Second carved-sentence candidate: "Dynamic bash is forgotten bash — once useful but never amortized. The named TS script pays the amortization cost once; the named TS script is the substrate."Aaron 2026-05-01 verbatim:
Closes the goldfish-ontology loop on the session-long failure mode (reaching for inline
gh pr view + jqwhile the v1 TS script already existed). Future-Otto encounters the wake-time pointer at CLAUDE.md scope (100% loaded every session) and can't miss the existence of the TS scripts.Composes with task #355 (5-AI peer convergence on poll-the-gate as executable script with fixtures); this is the multi-PR extension of v1.
Test plan
🤖 Generated with Claude Code