Skip to content

tools(github): batch poll-pr-gate.ts + CLAUDE.md wake-time pointer (Aaron 2026-05-01)#1153

Merged
AceHack merged 6 commits intomainfrom
otto/poll-pr-gate-batch-2026-05-01
May 1, 2026
Merged

tools(github): batch poll-pr-gate.ts + CLAUDE.md wake-time pointer (Aaron 2026-05-01)#1153
AceHack merged 6 commits intomainfrom
otto/poll-pr-gate-batch-2026-05-01

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented May 1, 2026

Summary

  • tools/github/poll-pr-gate-batch.ts (new) — async parallel wrap of v1 single-PR poll-pr-gate.ts with bounded concurrency (default 4), aggregate JSON output (per-PR GateReport[] + 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 both tools/github/poll-pr-gate.ts + poll-pr-gate-batch.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.
  • 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:

"thdse look good but are dynamic not ts shaped"
"dynamic bash is forgotten bash once useful but never amotorized"
"write a bactch version of the ts that calls this one — not bash, not .sh, not .ps1, not dyanamic bash"

Closes the goldfish-ontology loop on the session-long failure mode (reaching for inline gh pr view + jq while 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

  • `bun tools/github/poll-pr-gate-batch.ts --help` prints usage
  • `bun tools/github/poll-pr-gate-batch.ts --concurrency 2 --summary-only 1152 1145 1130` returns clean structured JSON for 3 merged PRs
  • `bun tools/github/poll-pr-gate-batch.ts --all-open --summary-only` returns 26 open LFG PRs with byGate / byNextAction / actionable / warnings aggregates (live tested 2026-05-01)
  • Parent commit applies cleanly to latest main (cherry-picked from prior branch)

🤖 Generated with Claude Code

…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>
Copilot AI review requested due to automatic review settings May 1, 2026 20:24
@AceHack AceHack enabled auto-merge (squash) May 1, 2026 20:25
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread tools/github/poll-pr-gate-batch.ts Outdated
…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>
AceHack added a commit that referenced this pull request May 1, 2026
…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>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.ts to 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.md wake-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.

Comment thread tools/github/poll-pr-gate-batch.ts Outdated
Comment thread tools/github/poll-pr-gate-batch.ts Outdated
Comment thread CLAUDE.md Outdated
AceHack and others added 2 commits May 1, 2026 16:28
…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>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread tools/github/poll-pr-gate-batch.ts Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.ts to run poll-pr-gate.ts in 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

Comment thread tools/github/poll-pr-gate-batch.ts Outdated
Comment thread tools/github/poll-pr-gate-batch.ts
Comment thread tools/github/poll-pr-gate-batch.ts Outdated
…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>
AceHack added a commit that referenced this pull request May 1, 2026
…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>
Copilot AI review requested due to automatic review settings May 1, 2026 20:41
@AceHack AceHack merged commit bdc8ae0 into main May 1, 2026
29 checks passed
@AceHack AceHack deleted the otto/poll-pr-gate-batch-2026-05-01 branch May 1, 2026 20:44
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.ts to 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;
Comment on lines +9 to +13
// 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.
Comment on lines +120 to +133
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:
Comment thread CLAUDE.md
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
AceHack added a commit that referenced this pull request May 1, 2026
…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>
AceHack added a commit that referenced this pull request May 1, 2026
…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>
AceHack added a commit that referenced this pull request May 1, 2026
…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>
AceHack added a commit that referenced this pull request May 1, 2026
…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>
AceHack added a commit that referenced this pull request May 1, 2026
…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>
AceHack added a commit that referenced this pull request May 1, 2026
…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>
AceHack added a commit that referenced this pull request May 1, 2026
…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>
AceHack added a commit that referenced this pull request May 6, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants