Skip to content

feat: [de-fork S1] baseline metrics + upstream-merge replay tooling#1013

Open
anandgupta42 wants to merge 5 commits into
mainfrom
defork/s1-baseline-replay
Open

feat: [de-fork S1] baseline metrics + upstream-merge replay tooling#1013
anandgupta42 wants to merge 5 commits into
mainfrom
defork/s1-baseline-replay

Conversation

@anandgupta42

@anandgupta42 anandgupta42 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

PINEAPPLE

Summary

Stage S1 of the de-fork spike (spec: docs/internal/2026-07-18-defork-spike-spec.md, Codex-consensus-approved). Builds the measurement foundation for shrinking the fork's upstream-shared footprint so future upstream merges get cheap. Zero product-behavior change — all new code is fork-owned tooling in script/upstream/.

Four tools sharing one taxonomy module:

  • taxonomy.ts — 3-bucket classification (upstream_shared / fork_owned / fork_added_outside_boundary) against the pinned v1.17.9 upstream tree, with upstream-existence precedence (10 .opencode/ overlap paths pinned by a generated oracle test).
  • census.ts — stack-based altimate_change marker-block parser reading from the git tree (not the working FS), versioned provenance-pinned JSON envelope, and a multiset {file,contentHash} ratchet (--check) with quantity-scoped committed exemptions.
  • divergence.ts — files/hunks/±lines vs the upstream base via git diff --numstat (git-exact; matches git --shortstat). Diff config is pinned (diff.algorithm=myers, interHunkContext=0, core.quotepath=false, --no-ext-diff --no-textconv, GIT_DIFF_OPTS stripped) so numbers reproduce across git environments.
  • replay.ts — explicit-base three-way merge via git merge-tree --write-tree --merge-base (object-db only, never mutates the working tree), with fail-closed region/binary reads; requires git ≥ 2.40.

Why: the last upstream bump (v1.4.0→v1.17.9) took a multi-week, 7-checkpoint campaign. Before shrinking the entangled surface we need a reproducible, gaming-resistant measure of it. The headline KPI is conflict surface on a replayed upstream merge, not marker count.

Baseline numbers (real runs, HEAD 8a50ec7f55 vs v1.17.9)

  • Census: 1,146 upstream-shared marker blocks / 244 files (+ 228 fork-owned, 236 misplaced-outside-boundary). 300 upstream_fix blocks (upstreaming candidates).
  • Divergence: 5,283 files, 21,162 hunks, +499,181/−740,989 (349 binary, 12 renames, 642 tests). Verified config-immune — yields the same numbers even under diff.algorithm=patience.
  • Replay vs v1.18.3: 651 conflicted paths — of which 118 have textual content conflicts totalling 466 <<<<<<< regions, and 4 are binary (2 PNG, 1 TTF, 1 WOFF2). Auto-merge: 212 attempted, 94 truly clean.

Test Plan

  • bun test in script/upstream: 155 pass / 0 fail (nesting, unmatched-marker handling, taxonomy overlap oracle, multiset ratchet pass+fail, envelope determinism, numstat ++/-- content regression, merge-tree parsing against a real fixture repo, honest replay metrics + rename-no-double-count).
  • Divergence pinned against git --shortstat ground truth; config-immunity verified (oracle holds under an injected diff.algorithm=patience).
  • Ratchet verified live: passes at baseline, fails on a synthetic net-new marker.
  • bunx tsc --noEmit -p script/upstream: clean. All script/upstream/*.ts are text (no NUL bytes).

Note: the CI census-ratchet wiring in .github/workflows/ci.yml lands in a small follow-up (that file is being co-edited by a sibling de-fork stage); this PR is the tooling + baselines.

Checklist

  • Tests added/updated
  • Documentation updated (spec + baselines README)
  • CHANGELOG updated — N/A (internal fork-owned tooling)

Closes #1010


Summary by cubic

Adds S1 de-fork baseline metrics and merge-replay tooling to measure and shrink our upstream-shared footprint. No product behavior changes; tooling lives in script/upstream/. CI now fetches the upstream base tag; the trace-golden subprocess wiring was removed on this branch.

  • New Features

    • taxonomy.ts: 3-bucket classifier (upstream_shared/fork_owned/fork_added_outside_boundary) against v1.17.9, with upstream-existence precedence and pinned overlap tests.
    • census.ts: parses altimate_change blocks from the git tree, emits a versioned JSON envelope, and enforces a multiset {file,contentHash} ratchet with quantity-scoped exemptions; unclosed markers fail unless allowlisted.
    • divergence.ts: counts files/hunks/±lines via git diff --numstat -M -z with pinned diff config for reproducible numbers.
    • replay.ts: simulates an explicit-base three-way merge via git merge-tree --write-tree --merge-base (no working-tree changes), attributes conflicts to census buckets; requires git ≥ 2.40.
    • Baselines under script/upstream/baselines/2026-07-18/ (census, divergence v1.17.9, replay v1.18.3). Snapshot: Census 1,146 shared blocks; Divergence 5,283 files, +499,181/−740,989; Replay 651 conflicted paths (118 textual, 4 binary), 94 clean auto-merges.
  • Bug Fixes

    • CI: fetches v1.17.9 tag; removed non-existent test/altimate/trace-golden/ subprocess path that broke this branch’s CI.
    • divergence.ts: reads taxonomy paths from the resolved upstreamBase.sha (not the movable ref) for consistent attribution.
    • census.ts: computeDiffBudget pins diff.renameLimit so rename detection stays on and counts remain stable.
    • refs.ts: improved missing-branch guidance to re-run against <remote>/<branch> (or fetch into a local ref).
    • refs.ts: dedups OIDs in readBlobsBatch to avoid buffer desync and blob map corruption.
    • Real-repo tests now skip when pinned upstream refs aren’t locally available (CI fetches --no-tags).
    • replay.ts: pinned core.quotepath=false, merge.renames, and renameLimit; all git calls use a sanitized env (GIT_DIFF_OPTS/GIT_EXTERNAL_DIFF stripped). Rejects census with mismatched upstreamBaseSha/taxonomyVersion.
    • divergence.ts: pinned diff.indentHeuristic=true and disabled diff.ignore*; parseNumstatZ fails closed on malformed/truncated records and non-numeric counts.
    • census.ts: validates each unclosed-marker allowlist entry; documents orphan-end tolerance.
    • Baselines README corrected to match census.json headline counts.

Written for commit 23b5a27. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added upstream tooling to generate deterministic divergence and replay “envelopes”, plus a census reporter with conflict categorization, change-budget reporting, and ratcheting with exemptions and allowlists.
  • Documentation
    • Documented generated upstream baseline “envelopes”, regeneration workflow, and CI/rendezvous behavior for marker-guard checks.
  • Tests
    • Added comprehensive Bun test suites covering census/divergence/replay pipelines, taxonomy rules, JSONC parsing, and Git repo/refs utilities.
  • Chores
    • Expanded CI to ensure required upstream tag content is available for marker-guard.

Stage S1 of the de-fork spike (docs/internal/2026-07-18-defork-spike-spec.md).
Measurement foundation for shrinking the fork's upstream-shared footprint —
zero product-behavior change; all new code is fork-owned tooling in
`script/upstream/`.

Tools (share one taxonomy module):
- `taxonomy.ts` — 3-bucket classification (`upstream_shared` / `fork_owned` /
  `fork_added_outside_boundary`) against the pinned `v1.17.9` upstream tree,
  upstream-existence precedence (10 `.opencode/` overlap paths pinned by a
  generated oracle test).
- `census.ts` — stack-based `altimate_change` block parser reading from the git
  tree (not the working FS), versioned provenance-pinned JSON envelope, and a
  multiset `{file,contentHash}` ratchet (`--check`) with quantity-scoped
  committed exemptions.
- `divergence.ts` — files/hunks/±lines vs the upstream base via
  `git diff --numstat` (git-exact; matches `git --shortstat`). Diff config is
  pinned (`diff.algorithm=myers`, `interHunkContext=0`, `core.quotepath=false`,
  `--no-ext-diff --no-textconv`, `GIT_DIFF_OPTS` stripped) so numbers reproduce
  across git environments. Baseline: 5283 files, +499181/-740989.
- `replay.ts` — explicit-base three-way merge via
  `git merge-tree --write-tree --merge-base` (object-db only, never mutates the
  working tree). Reports honest conflict surface: 651 conflicted paths, 118
  content files / 466 textual regions, 4 binary conflicts, and 94 truly-clean
  auto-merges (not the 212 attempts). Fail-closed region/binary reads; requires
  git >= 2.40.

Includes committed baselines, an empty exemptions file, a JSONC parser, and the
unclosed-marker allowlist. `refs.ts` runs all git via arg-vector `spawnSync`
(no shell interpolation).

Test Plan:
- `bun test` in `script/upstream`: 155 pass, 0 fail (nesting, unmatched-marker
  handling, taxonomy overlap oracle, multiset ratchet pass+fail, envelope
  determinism, numstat `++`/`--` content regression, merge-tree parsing against
  a real fixture repo, honest replay metrics).
- Divergence pinned against `git --shortstat` ground truth; verified
  config-immune (yields the oracle even under `diff.algorithm=patience`).
- Ratchet verified: passes at baseline, fails on a synthetic net-new marker.
- `bunx tsc --noEmit -p script/upstream`: clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@github-actions

Copy link
Copy Markdown

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 19, 2026

Copy link
Copy Markdown

This PR has 97,130 reviewable changed lines after ignored/generated files are excluded, above cubic's default 50,000-changed-line automatic review limit.

Most of the diff comes from:

  • script/upstream/baselines/2026-07-18/divergence-v1.17.9.json (~58,162 changed lines)
  • script/upstream/baselines/2026-07-18/census.json (~22,063 changed lines)
  • script/upstream/baselines/2026-07-18/replay-v1.18.3.json (~12,712 changed lines)
  • script/upstream/census.ts (~942 changed lines)
  • script/upstream/census.test.ts (~778 changed lines)

Comment @cubic-dev-ai review this to review it anyway. If the largest files are generated or fixture data, add them to your ignored files in review settings or ignorePatterns in cubic.yaml - cubic will then review the rest automatically. You can also raise this limit in review settings.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change adds local Git and JSONC utilities, taxonomy classification, deterministic census and divergence reports, merge replay analysis, comprehensive Bun tests, configuration allowlists, CI wiring, and generated upstream baseline artifacts.

Changes

Upstream de-fork tooling

Layer / File(s) Summary
Shared Git and JSONC utilities
script/upstream/utils/*
Adds local-only Git ref, tree, blob, repository-root, version, and JSONC parsing utilities.
Path and marker taxonomy
script/upstream/taxonomy.ts, script/upstream/taxonomy.test.ts
Adds upstream/fork bucket classification, category rules, upstream-fix detection, and taxonomy tests.
Census generation and ratcheting
script/upstream/census.ts, script/upstream/census.test.ts, script/upstream/*allowlist*, script/upstream/defork-exemptions.jsonc, .github/workflows/ci.yml
Adds deterministic marker census envelopes, allowlists, ratchets, exemptions, diff budgets, CLI modes, tests, and CI wiring.
Divergence reporting
script/upstream/divergence.ts, script/upstream/divergence.test.ts
Adds deterministic diff and hunk accounting, rename and binary parsing, taxonomy aggregation, CLI output, and invariant tests.
Merge replay and baselines
script/upstream/replay.ts, script/upstream/replay.test.ts, script/upstream/baselines/*
Adds explicit-base merge replay analysis, conflict metrics, census attribution, tests, generated results, and regeneration documentation.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ReplayCLI
  participant GitMergeTree
  participant GitObjectDatabase
  participant CensusEnvelope
  ReplayCLI->>GitMergeTree: Run explicit-base replay
  GitMergeTree-->>ReplayCLI: Return tree and conflict records
  ReplayCLI->>GitObjectDatabase: Read conflict stage blobs
  GitObjectDatabase-->>ReplayCLI: Return blob data
  ReplayCLI->>CensusEnvelope: Attribute conflict paths
  CensusEnvelope-->>ReplayCLI: Return bucket counts
Loading

Poem

A rabbit hops through trees of code,
Counts markers on the upstream road.
Conflicts bloom, then metrics gleam,
Git keeps watch beside the stream.
“What a tidy burrow!” says the hare.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements the S1 tooling and baselines, but it does not wire the census ratchet into marker-guard as required by #1010. Add the census-ratchet CI step to the existing marker-guard job and confirm the workflow enforces the baseline check.
Docstring Coverage ⚠️ Warning Docstring coverage is 64.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed All edits stay within the de-fork tooling, tests, baselines, docs, and CI support described by the PR objectives.
Title check ✅ Passed The title clearly summarizes the main change: baseline metrics and upstream-merge replay tooling for the de-fork work.
Description check ✅ Passed The description covers the issue, changes, rationale, verification, and checklist, though a few template sections are missing or not explicitly labeled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch defork/s1-baseline-replay

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

1 similar comment
@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
script/upstream/replay.ts (1)

453-467: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Optimize census block lookup to O(1).

Using .find() within the loop results in an O(N × M) operation. You can simplify the code, improve performance, and safely drop the non-null assertion by building a Map instead of a Set.

♻️ Proposed refactor
-  const censusFilesWithBlocks = new Set(census.blocks.map((b) => b.file))
+  const censusBucketByFile = new Map(census.blocks.map((b) => [b.file, b.bucket]))
   const counts = new Map<Bucket, number>()
   // Authoritative conflicted-path set = the stage-line paths (one entry per
   // conflicted path). Do NOT union in conflictMessage paths: a rename message
   // names BOTH the old and new path, which double-counts (that was the
   // 750-vs-651 discrepancy). The stage lines are the ground truth for "which
   // paths conflicted."
   const conflictedFilePaths = new Set(envelope.conflictedPaths.map((p) => p.path))
   for (const path of conflictedFilePaths) {
     // A conflicted path only gets attributed if it's a file the census
     // actually scanned marker blocks in; otherwise fall back to plain
     // taxonomy classification against the upstream tree.
-    const bucket = censusFilesWithBlocks.has(path) ? census.blocks.find((b) => b.file === path)!.bucket : classifyBucket(path, upstreamPaths)
+    const bucket = censusBucketByFile.get(path) ?? classifyBucket(path, upstreamPaths)
     counts.set(bucket, (counts.get(bucket) ?? 0) + 1)
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/upstream/replay.ts` around lines 453 - 467, Replace
censusFilesWithBlocks and the per-path census.blocks.find lookup in the
conflictedFilePaths loop with a Map keyed by block.file and containing each
block’s bucket. Use the mapped bucket when available, otherwise retain
classifyBucket(path, upstreamPaths), eliminating the non-null assertion while
preserving the existing counting behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@script/upstream/divergence.ts`:
- Around line 157-181: Update parseNumstatZ to fail closed on malformed input:
throw when a record head lacks either tab delimiter, throw when a rename/copy
record is missing either old- or new-path token instead of defaulting to empty
strings, and validate parsed added/deleted counts so NaN values are rejected
before records are emitted. Match the sibling census.ts parseNumstatZ
error-handling behavior while preserving valid binary, rename, and regular
records.

In `@script/upstream/replay.ts`:
- Around line 174-175: Update runMergeTree’s git merge-tree invocation to pass
Git’s -c core.quotepath=false configuration before the merge-tree subcommand,
ensuring emitted paths remain raw and consistent with ls-tree -z consumers.

In `@script/upstream/taxonomy.test.ts`:
- Around line 53-101: Refactor the overlap test in the “.opencode/ overlap
oracle” describe block to reuse the scoped path-listing helper from
utils/refs.ts instead of issuing inline git ls-tree and git ls-files execSync
calls. Ensure the helper uses the existing consistent reference/error handling
and supports listing .opencode/ paths for UPSTREAM_TAG and the current tree,
while preserving the overlap and classification assertions.
- Around line 1-15: Replace the inline execSync implementation in
loadUpstreamPaths with the shared utils/refs.ts loadPathsAtRef flow so ref
resolution goes through resolveRefOrThrow and preserves its actionable
missing-ref error. Ensure the test setup or CI fetches the v1.17.9 tag before
these tests execute, while keeping the existing Set<string> result expected by
the taxonomy tests.

In `@script/upstream/utils/refs.ts`:
- Around line 129-166: Update readBlobsBatch to deduplicate oids before
constructing the git cat-file --batch input, so git emits exactly one block per
processed OID. Iterate over the deduplicated list while parsing and remove the
map.has skip logic, preserving one returned content entry per unique OID and
keeping input-order processing intact.

---

Nitpick comments:
In `@script/upstream/replay.ts`:
- Around line 453-467: Replace censusFilesWithBlocks and the per-path
census.blocks.find lookup in the conflictedFilePaths loop with a Map keyed by
block.file and containing each block’s bucket. Use the mapped bucket when
available, otherwise retain classifyBucket(path, upstreamPaths), eliminating the
non-null assertion while preserving the existing counting behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2dc88003-4cb9-4f7b-a1a0-233545efeac4

📥 Commits

Reviewing files that changed from the base of the PR and between 8a50ec7 and 5cf1b67.

📒 Files selected for processing (18)
  • script/upstream/baselines/2026-07-18/census.json
  • script/upstream/baselines/2026-07-18/divergence-v1.17.9.json
  • script/upstream/baselines/2026-07-18/replay-v1.18.3.json
  • script/upstream/baselines/README.md
  • script/upstream/census.test.ts
  • script/upstream/census.ts
  • script/upstream/defork-exemptions.jsonc
  • script/upstream/divergence.test.ts
  • script/upstream/divergence.ts
  • script/upstream/replay.test.ts
  • script/upstream/replay.ts
  • script/upstream/taxonomy.test.ts
  • script/upstream/taxonomy.ts
  • script/upstream/unclosed-marker-allowlist.jsonc
  • script/upstream/utils/jsonc.test.ts
  • script/upstream/utils/jsonc.ts
  • script/upstream/utils/refs.ts
  • script/upstream/utils/repo-root.ts

Comment thread script/upstream/divergence.ts
Comment thread script/upstream/replay.ts Outdated
Comment on lines +1 to +15
import { describe, test, expect } from "bun:test"
import { execSync } from "child_process"
import { classifyBucket, classifyCategories, FORK_OWNED_ROOTS, UNATTRIBUTED, categoryRuleIds, isUpstreamFixLine } from "./taxonomy"

const REPO_ROOT = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim()
const UPSTREAM_TAG = "v1.17.9"

function loadUpstreamPaths(): Set<string> {
const out = execSync(`git ls-tree -r --name-only "${UPSTREAM_TAG}"`, {
cwd: REPO_ROOT,
encoding: "utf-8",
maxBuffer: 50 * 1024 * 1024,
})
return new Set(out.split("\n").filter((l) => l.length > 0))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Test setup duplicates refs.ts ref-resolution logic, and depends on a local tag that CI doesn't have.

loadUpstreamPaths() here re-implements utils/refs.ts#loadPathsAtRef via inline execSync, bypassing resolveRefOrThrow's designed behavior of failing with an actionable git fetch upstream tag v1.17.9 --no-tags message when the ref is missing locally. Per the pipeline failure logs, this is exactly what's happening in CI: git ls-tree -r --name-only "v1.17.9" -- .opencode/ fails with fatal: Not a valid object name v1.17.9 (surfaced at Line 55), producing a raw, unhelpful execSync crash instead of the friendly fetch instructions the rest of the toolset provides.

Reusing loadPathsAtRef/resolveRefOrThrow here would both remove the duplication and turn this CI failure into an actionable error; separately, the CI job (or a beforeAll) needs to ensure v1.17.9 is fetched before these tests run.

♻️ Suggested consolidation
-import { execSync } from "child_process"
+import { loadPathsAtRef } from "./utils/refs"
+import { resolveRepoRoot } from "./utils/repo-root"
 import { classifyBucket, classifyCategories, FORK_OWNED_ROOTS, UNATTRIBUTED, categoryRuleIds, isUpstreamFixLine } from "./taxonomy"

-const REPO_ROOT = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim()
+const REPO_ROOT = resolveRepoRoot()
 const UPSTREAM_TAG = "v1.17.9"

 function loadUpstreamPaths(): Set<string> {
-  const out = execSync(`git ls-tree -r --name-only "${UPSTREAM_TAG}"`, {
-    cwd: REPO_ROOT,
-    encoding: "utf-8",
-    maxBuffer: 50 * 1024 * 1024,
-  })
-  return new Set(out.split("\n").filter((l) => l.length > 0))
+  return loadPathsAtRef(UPSTREAM_TAG, REPO_ROOT)
 }
🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 1-1: Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execSync } from "child_process"
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/upstream/taxonomy.test.ts` around lines 1 - 15, Replace the inline
execSync implementation in loadUpstreamPaths with the shared utils/refs.ts
loadPathsAtRef flow so ref resolution goes through resolveRefOrThrow and
preserves its actionable missing-ref error. Ensure the test setup or CI fetches
the v1.17.9 tag before these tests execute, while keeping the existing
Set<string> result expected by the taxonomy tests.

Source: Pipeline failures

Comment thread script/upstream/taxonomy.test.ts Outdated
Comment on lines +53 to +101
describe(".opencode/ overlap oracle (generated from git ls-tree -r v1.17.9)", () => {
test("exactly 10 .opencode/ paths overlap between v1.17.9 and the current tree, and all classify upstream_shared", () => {
const upstreamOpencodePaths = execSync(`git ls-tree -r --name-only "${UPSTREAM_TAG}" -- .opencode/`, {
cwd: REPO_ROOT,
encoding: "utf-8",
})
.split("\n")
.filter((l) => l.length > 0)

const currentOpencodePaths = execSync("git ls-files .opencode/", {
cwd: REPO_ROOT,
encoding: "utf-8",
})
.split("\n")
.filter((l) => l.length > 0)

const currentSet = new Set(currentOpencodePaths)
const overlap = upstreamOpencodePaths.filter((p) => currentSet.has(p)).sort()

expect(overlap).toHaveLength(10)
expect(overlap).toEqual(
[
".opencode/.gitignore",
".opencode/command/commit.md",
".opencode/command/issues.md",
".opencode/command/learn.md",
".opencode/command/translate.md",
".opencode/opencode.jsonc",
".opencode/plugins/smoke-theme.json",
".opencode/plugins/tui-smoke.tsx",
".opencode/themes/.gitignore",
".opencode/tui.json",
].sort(),
)

const upstreamPaths = new Set(overlap)
expect(classifyBucket(".opencode/.gitignore", upstreamPaths)).toBe("upstream_shared")
expect(classifyBucket(".opencode/themes/.gitignore", upstreamPaths)).toBe("upstream_shared")
for (const p of overlap) {
expect(classifyBucket(p, upstreamPaths)).toBe("upstream_shared")
}
})

test("a .opencode/ path NOT in the overlap set classifies fork_owned", () => {
const upstreamPaths = loadUpstreamPaths()
// .opencode/skills/** is fork-authored and has no upstream counterpart.
expect(classifyBucket(".opencode/skills/dbt-snapshot/SKILL.md", upstreamPaths)).toBe("fork_owned")
})
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Same missing-tag dependency as above; also duplicates git-invocation logic instead of using utils/refs.ts.

This describe block runs two more inline git ls-tree/git ls-files execSync calls against UPSTREAM_TAG, hitting the same CI failure mode (missing local v1.17.9) confirmed by the pipeline logs. Consider factoring this scoped .opencode/-only listing through utils/refs.ts (e.g. a git ls-tree -r -z --name-only <ref> -- <path>-based helper) for consistent error handling, once the setup fix above is applied.

🧰 Tools
🪛 GitHub Actions: CI / 7_Marker Guard.txt

[error] 55-55: Test failed due to Git command error: git ls-tree -r --name-only "v1.17.9" -- .opencode/ returned fatal: Not a valid object name v1.17.9 (Command failed in execSync).

🪛 GitHub Actions: CI / Marker Guard

[error] 55-55: Test failed when executing command git ls-tree -r --name-only "v1.17.9" -- .opencode/. git reported: "fatal: Not a valid object name v1.17.9" leading to Command failed: ... in execSync.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/upstream/taxonomy.test.ts` around lines 53 - 101, Refactor the overlap
test in the “.opencode/ overlap oracle” describe block to reuse the scoped
path-listing helper from utils/refs.ts instead of issuing inline git ls-tree and
git ls-files execSync calls. Ensure the helper uses the existing consistent
reference/error handling and supports listing .opencode/ paths for UPSTREAM_TAG
and the current tree, while preserving the overlap and classification
assertions.

Source: Pipeline failures

Comment thread script/upstream/utils/refs.ts

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

Copy link
Copy Markdown

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: 5cf1b67b62

ℹ️ 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 on lines +17 to +18
This is also the **ratchet baseline** wired into CI (see
`.github/workflows/ci.yml`'s `marker-guard` job): `census.ts --check

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Wire the census ratchet into marker-guard

The baseline is documented as an active CI ratchet, but the inspected .github/workflows/ci.yml marker-guard job at lines 486-535 only runs the tests and analyze.ts --markers; it never invokes census.ts --check --baseline. Consequently, new marker blocks covered only by this multiset ratchet can merge while CI remains green, despite this documentation telling maintainers that they are blocked.

Useful? React with 👍 / 👎.

Comment thread script/upstream/replay.ts Outdated
Comment on lines +174 to +175
function runMergeTree(repoRoot: string, baseSha: string, oursSha: string, targetSha: string): { stdout: string; exitCode: number } {
const result = spawnSync("git", ["merge-tree", "--write-tree", "--merge-base", baseSha, oursSha, targetSha], {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Pin rename configuration for replay merges

When a runner has repository or global merge.renames or merge.renameLimit settings, this invocation inherits them, so rename/delete and file-location detection—and therefore the committed conflict counts—can differ for identical refs. The inspected git help --config explicitly lists merge.renames, merge.renameLimit, and merge.directoryRenames as merge configuration; pass explicit -c values as divergence.ts does for its diff settings so replay results are reproducible across environments.

Useful? React with 👍 / 👎.

Comment thread script/upstream/replay.ts
Comment on lines +446 to +447
export function attributeConflictsToCensus(envelope: ReplayEnvelope, census: CensusLike, upstreamPaths: ReadonlySet<string>): ConflictCategoryAttribution[] {
if (census.oursSha !== envelope.oursSha) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject censuses generated against a different upstream base

If --census was generated with the same oursSha but a different --upstream-base, this check accepts it even though every stored block bucket was classified against a different upstream path set. Line 465 then trusts those stale buckets for marker-bearing conflict paths while using the replay's current upstream set for other paths, producing internally inconsistent byBucket results; validate the census upstream-base SHA and taxonomy version in addition to oursSha.

Useful? React with 👍 / 👎.

Comment thread script/upstream/baselines/README.md Outdated
Comment on lines +15 to +16
1146 `upstream_shared` blocks across 244 files, 242 `fork_owned` blocks
across 89 files, 235 `fork_added_outside_boundary` blocks across 103 files.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Correct the census headline to match the committed envelope

These reported census results disagree with the adjacent committed census.json: its totals are 228 fork-owned blocks across 84 files and 236 outside-boundary blocks across 104 files, not 242/89 and 235/103. Anyone using this headline for de-fork planning or validating a regeneration receives different baseline metrics from the machine-readable source of truth.

Useful? React with 👍 / 👎.

Comment on lines +303 to +307
"v1.17.9→v1.18.3 replay reports honest regions + clean auto-merges",
() => {
const { resolveRepoRoot } = require("./utils/repo-root")
const repoRoot = resolveRepoRoot()
const env = buildReplay(repoRoot, "v1.17.9", "8a50ec7f55", "v1.18.3", { now: "2026-07-18T00:00:00.000Z" })

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Fetch the pinned upstream tag before running replay tests

This repository-level test requires a locally resolvable upstream v1.18.3, but the inspected marker-guard setup in .github/workflows/ci.yml:499-503 fetches the upstream remote with --no-tags. On a clean CI checkout without that upstream tag—which the new baseline README itself identifies as a supported state—buildReplay throws during ref resolution before reaching any assertion, causing the entire marker-guard test step to fail; fetch the exact tag or make the fixture self-contained.

Useful? React with 👍 / 👎.

Comment on lines +228 to +230
// Unquoted: split on " b/" — the last occurrence separates a/ from b/.
const idx = rest.lastIndexOf(" b/")
if (idx !== -1) return rest.slice(idx + 3)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid splitting unquoted diff headers at the last b-prefix

For a legal path containing b/, such as docs/a b/file.md, Git emits an unquoted header like diff --git a/docs/a b/file.md b/docs/a b/file.md even with the pinned core.quotepath=false. lastIndexOf(" b/") selects the occurrence inside the post-image path and returns only file.md, so the subsequent hunk-attribution consistency check throws instead of producing a divergence report; derive the path using the authoritative numstat entries or another unambiguous representation.

Useful? React with 👍 / 👎.

Comment thread script/upstream/census.ts
Comment on lines +418 to +421
const ours = resolveRefOrThrow(oursRef, repoRoot)
const upstreamBase = resolveRefOrThrow(upstreamBaseRef, repoRoot)
const upstreamPaths = loadPathsAtRef(upstreamBaseRef, repoRoot)
const filesAtRef = scanFilesAtRef(oursRef, repoRoot)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Read census trees through the resolved commit SHAs

When oursRef or upstreamBaseRef is a movable ref and another process updates it between resolution and these reads, the envelope records the earlier oursSha/tree and upstream SHA/tree but scans and classifies against the later ref contents. That silently violates the provenance-pinned contract and can create a baseline that cannot be reproduced from its recorded SHAs; pass ours.sha and upstreamBase.sha to the object-database reads after resolving them.

Useful? React with 👍 / 👎.

Comment thread script/upstream/census.ts
Comment on lines +248 to +253
export function loadUnclosedAllowlist(filePath: string): UnclosedMarkerAllowlistEntry[] {
if (!fs.existsSync(filePath)) return []
const raw = fs.readFileSync(filePath, "utf-8")
const parsed = parseJsonc(raw)
if (!Array.isArray(parsed)) throw new Error(`${filePath}: expected top-level JSON array`)
return parsed as UnclosedMarkerAllowlistEntry[]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate unclosed-marker allowlist entries before applying them

Unlike the exemption loader below, this loader casts arbitrary parsed objects directly to the allowlist type. An entry with the right file and startLine but no reason or approvedBy still suppresses a real unclosed marker, and a mistyped expires value becomes NaN, making the comparison at line 259 false and granting permanent suppression. Validate every field and reject invalid dates before the entries can bypass the census failure.

Useful? React with 👍 / 👎.

Comment thread script/upstream/census.ts
Comment on lines +520 to +522
function isExpired(exemption: Exemption, now: Date): boolean {
if (!exemption.expires) return false
return new Date(exemption.expires).getTime() < now.getTime()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Expire date-only exemptions after the documented date

For the documented YYYY-MM-DD form, JavaScript parses the value at midnight UTC, so an exemption with expires: "2026-12-31" is already considered expired for almost the entirety of December 31. This contradicts the interface's “after this date” contract and can make the ratchet unexpectedly fail during the stated final valid day; compare date-only values at the end of that day or document and enforce an instant-bearing timestamp.

Useful? React with 👍 / 👎.

Comment thread script/upstream/census.ts
})
continue
}
if (END_RE.test(line) && stack.length > 0) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Orphan altimate_change end markers are silently dropped.

The end-marker branch is guarded by && stack.length > 0, so an altimate_change end with no matching open block on the stack is ignored with no error and no count. This is asymmetric with the unclosed-start case, which assembleCensus fails closed on at census.ts:344. A stray end (e.g. an accidentally-deleted start whose end now dangles, or a copy-paste error) is masked silently, which can hide the very class of marker-drift bug this tool exists to catch. Either throw on a stack-underflow end (mirroring the unclosed-start contract) or document+test the intentional tolerance.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread script/upstream/census.ts
const raw = fs.readFileSync(filePath, "utf-8")
const parsed = parseJsonc(raw)
if (!Array.isArray(parsed)) throw new Error(`${filePath}: expected top-level JSON array`)
return parsed as UnclosedMarkerAllowlistEntry[]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: loadUnclosedAllowlist skips the per-entry shape validation that loadExemptions enforces.

loadExemptions runs every entry through validateExemption (rejecting malformed expires, non-integer startLine, etc.), but loadUnclosedAllowlist returns parsed as UnclosedMarkerAllowlistEntry[] with no checks. Concrete impact: isAllowlistedUnclosed at census.ts:259 does new Date(e.expires).getTime() < now.getTime(); if expires is a non-date string, getTime() returns NaN, the comparison is always false, so a typo silently makes the entry never expire (a permanent suppression of the unclosed throw). A malformed startLine similarly never matches. Add a validateUnclosedAllowlistEntry mirroring validateExemption and apply it per entry.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

// - --no-color / --no-ext-diff / --no-textconv: no ANSI in output, and do
// NOT let git launch external diff/textconv programs (a read-only report
// must not execute configured helpers).
const PINNED_DIFF_CONFIG = [

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: PINNED_DIFF_CONFIG doesn't pin diff.indentHeuristic (or the diff.ignore* family), undermining the "config-immunity" reproducibility claim.

The header comment (divergence.ts:40-43) and the PR description both promise byte-for-byte reproduction "regardless of the runner's git config," but diff.indentHeuristic (a hunk-boundary tie-breaker that runs on top of diff.algorithm=myers) is left inherited — a runner with diff.indentHeuristic=true produces a different headline hunk count (the PR's "21162 hunks" metric). Likewise diff.ignoreAllSpace/ignoreSpaceChange/ignoreSpaceAtEol/ignoreBlankLines default off but, if inherited as on, silently change the +/- counts. Add -c diff.indentHeuristic=false (and the four diff.ignore*=false) to PINNED_DIFF_CONFIG.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread script/upstream/replay.ts Outdated
* discard stdout on a non-zero exit.
*/
function runMergeTree(repoRoot: string, baseSha: string, oursSha: string, targetSha: string): { stdout: string; exitCode: number } {
const result = spawnSync("git", ["merge-tree", "--write-tree", "--merge-base", baseSha, oursSha, targetSha], {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: runMergeTree doesn't pass -c core.quotepath=false (or -z), so conflicted paths with non-ASCII or special bytes get C-string-quoted in git's output.

CONFLICT_PATH_LINE_RE at replay.ts:72 then captures the quoted form (e.g. "\347\211\214.png"), but census paths come from git ls-tree -r -z (utils/refs.ts:81) which are raw/unquoted — so attributeConflictsToCensus's lookup censusFilesWithBlocks.has(path) at replay.ts:465 silently misses and falls back to classifyBucket, producing wrong bucket counts with no thrown error. The sibling divergence.ts:60 pins core.quotepath=false for exactly this reason; replay.ts is the asymmetric outlier. Add -c core.quotepath=false (or parse -z output).


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread script/upstream/replay.ts Outdated
maxBuffer: 200 * 1024 * 1024,
// Pin locale so CONFLICT/Auto-merging message text (which we parse) is
// stable across environments.
env: { ...process.env, LC_ALL: "C" },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: merge-tree env inherits GIT_DIFF_OPTS / GIT_EXTERNAL_DIFF / GIT_CONFIG_*; only LC_ALL is pinned.

All three spawnSync calls in replay.ts (runMergeTree:181, countConflictRegions:224, countBinaryConflictPaths:396) use env: { ...process.env, LC_ALL: "C" } and spread the entire inherited environment. The sibling divergence.ts:82-87 defines sanitizedGitEnv() that additionally deletes GIT_DIFF_OPTS and GIT_EXTERNAL_DIFF precisely so inherited overrides can't perturb the parsed output. For replay, an inherited GIT_EXTERNAL_DIFF or GIT_CONFIG_PARAMETERS could change CONFLICT/Auto-merging message text or path resolution on a different runner, breaking the pinned test at replay.test.ts:310-318. Reuse/extract sanitizedGitEnv() and apply it to all three callsites.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread script/upstream/census.ts Outdated
// ── CLI ──────────────────────────────────────────────────────────────────

function parseArgs(argv: string[]) {
const args = { ...Object.fromEntries(argv.map((a, i) => [a, argv[i + 1]])) } as Record<string, string>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: args is built and immediately discarded (void args); it's dead code.

The flag and opt closures do all the real parsing by rescanning argv directly. The args object is never returned or read — void args exists only to silence the unused-variable lint. It's also a latent foot-gun: Object.fromEntries(argv.map((a, i) => [a, argv[i + 1]])) silently overwrites duplicate flag keys, which could mislead a future editor into thinking args is the source of truth. Delete both the args and void args lines.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread script/upstream/divergence.test.ts Outdated
expect(envelope.upstreamBaseTree).toMatch(/^[0-9a-f]{40}$/)
expect(envelope.oursTree).toMatch(/^[0-9a-f]{40}$/)
expect(envelope.diffOptions.renameLimit).toBe(20000)
expect(envelope.files.length).toBe(envelope.totals.files)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: This assertion is tautological and can never fail.

envelope.totals.files is set to files.length at divergence.ts:343, so this reduces to files.length === files.length. Replace with a meaningful invariant — e.g. that every entry in envelope.files has a unique path, or that binaryFiles + renameFiles + testFiles reconciles against files.filter(...).


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

export function classifyBucket(relPath: string, upstreamPaths: ReadonlySet<string>): Bucket {
const normalized = normalizePath(relPath)
if (upstreamPaths.has(normalized)) return "upstream_shared"
if (FORK_OWNED_ROOTS.some((pattern) => minimatch(normalized, pattern))) return "fork_owned"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: minimatch recompiles all 14 glob patterns on every call.

classifyBucket is invoked once per file by census.ts:145, census.ts:777, divergence.ts:294, and replay.ts:465 over a multi-thousand-file corpus, so the 14 patterns are recompiled ~14 × N times per run. Hoist const COMPILED = FORK_OWNED_ROOTS.map((p) => new minimatch.Minimatch(p)) to module scope and test COMPILED.some((m) => m.match(normalized)).


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread script/upstream/divergence.test.ts Outdated
})
})

describe("buildDivergence (real-repo, pinned against git --shortstat ground truth)", () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: The PR's "config-immunity" claim is not backed by a test in this block.

The PR description asserts "config-immunity verified — yields the same numbers even under diff.algorithm=patience", but this describe only contains a git --shortstat ground-truth test and a same-now determinism test — neither injects a diff config (diff.algorithm=patience, core.quotepath=true, diff.indentHeuristic=true, GIT_DIFF_OPTS=--unified=50) and re-runs. Combined with the unpinned knobs flagged at divergence.ts:52, a future regression that drops a -c flag would pass the entire suite. Add a test that injects an alternate config via GIT_CONFIG_PARAMETERS and asserts byte-identical envelopes.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

expect(env.totals.autoMergedAttempted).toBe(212)
expect(env.totals.autoMergedClean).toBe(94)
// 4 binary conflicts (2 PNG, 1 TTF, 1 WOFF2) otherwise hidden under modify/delete.
expect(env.totals.binaryConflictPaths).toBe(4)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: The fail-closed binary-read paths in countBinaryConflictPaths are not exercised.

countBinaryConflictPaths has two explicit fail-closed throws (replay.ts:407 "truncated cat-file output" and :411 "bad cat-file header" — the latter fires on a missing OID, since --batch prints <oid> missing and exits 0). Neither is covered by a constructed fixture; the pinned test here only asserts binaryConflictPaths === 4 against the real repo, so a regression that silently returns 0 (e.g. a future edit that swallows the header-mismatch) wouldn't be caught. The buildFixtureRepo helper creates no binary blob. Add a fixture that commits a PNG/TTF blob with a content or modify/delete conflict and asserts binaryConflictPaths >= 1.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Jul 19, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 4 Issues Found | Recommendation: Address before merge

Incremental pass over commit 23b5a27 ("address review round 3 — CI merge-blocker + reproducibility"). Three of four changed files are clean fixes for prior findings; one new SUGGESTION on census.ts's computeDiffBudget.

Resolved this round:

  • .github/workflows/ci.yml — removed nonexistent test/altimate/trace-golden/ from SUBPROCESS_PATHS (closes prior WARNING + codex P1 about the missing subprocess root)
  • script/upstream/divergence.ts:310loadPathsAtRef now reads from upstreamBase.sha instead of the movable ref (closes prior codex P2 "Read taxonomy paths from the resolved upstream SHA")
  • script/upstream/utils/refs.ts:62-66 — branch-fetch hint now explains that git fetch upstream <branch> only updates the remote-tracking ref and tells the operator to re-run against <remote>/<branch> (closes prior codex P2 "Make the branch fetch hint resolve the requested ref")

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 4
Issue Details (click to expand)

SUGGESTION

File Line Issue
script/upstream/census.ts 776 New this round — comment claims computeDiffBudget "Mirrors divergence.ts's PINNED_DIFF_CONFIG" but pins only diff.renameLimit (and with a different value, 999999 vs 20000); missing diff.ignore*, --no-ext-diff/--no-textconv, and sanitizedGitEnv()
script/upstream/taxonomy.ts 76 Prior — minimatch recompiles all 14 glob patterns per call across a multi-thousand-file corpus; hoist new minimatch.Minimatch(...) to module scope
script/upstream/divergence.test.ts 146 Prior — PR's "config-immunity" claim is not backed by an oracle test injecting diff.algorithm=patience / GIT_DIFF_OPTS=--unified=50 and asserting byte-identical envelopes
script/upstream/replay.test.ts 328 Prior — fail-closed binary-read throws in countBinaryConflictPaths are not exercised by any constructed fixture (only the real-repo === 4 assertion covers the happy path)
Files Reviewed this pass (4 files changed, 1 new issue)
  • .github/workflows/ci.yml — clean removal of nonexistent trace-golden/ subprocess path; resolves prior CI merge-blocker
  • script/upstream/census.tscomputeDiffBudget correctly pins diff.renameLimit (closes prior codex P2 rename-limit finding), but the added comment overstates the pinning scope (new SUGGESTION)
  • script/upstream/divergence.tsloadPathsAtRef(upstreamBase.sha, ...) correctly closes the TOOU between ref resolution and taxonomy read; comment explaining the race is accurate
  • script/upstream/utils/refs.ts — improved branch-fetch guidance is accurate (git fetch upstream <branch>upstream/<branch> remote-tracking ref; explicit :<ref> alternative for a local ref)

Fix these issues in Kilo Cloud

Previous Review Summaries (4 snapshots, latest commit 167c463)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 167c463)

Status: 4 Issues Found | Recommendation: Address before merge

Incremental pass over commit 167c463 ("address review round 2 — correctness, determinism, CI-safety"). No new issues introduced — every changed line is a correct fix for a prior finding. 7 of 11 prior findings resolved in this commit:

  • census.ts orphan end markers (now documented as intentional asymmetry)
  • census.ts loadUnclosedAllowlist per-entry validation (new validateUnclosedAllowlistEntry)
  • census.ts dead args object removed
  • divergence.ts PINNED_DIFF_CONFIG pins indentHeuristic + diff.ignore*
  • replay.ts runMergeTree passes core.quotepath=false + merge.renames + renameLimit, uses sanitizedGitEnv()
  • replay.ts attributeConflictsToCensus rejects mismatched upstreamBaseSha / taxonomyVersion
  • divergence.test.ts tautological files.length === totals.files replaced with meaningful reconciliation invariants
  • baselines/README.md census headline corrected to match census.json
  • utils/refs.ts dedupes input OIDs before cat-file --batch (closes buffer-desync landmine)

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 3
Issue Details (click to expand)

WARNING

File Line Issue
.github/workflows/ci.yml 151 SUBPROCESS_PATHS adds test/altimate/trace-golden/, which does not exist at this PR's HEAD — the trace-golden harness commit 337144a78 is not an ancestor; either fails the subprocess summary gate or silently skips the oracle

SUGGESTION

File Line Issue
script/upstream/taxonomy.ts 76 minimatch recompiles all 14 glob patterns per call across a multi-thousand-file corpus
script/upstream/divergence.test.ts 172 PR's "config-immunity" claim is not backed by an oracle test in the buildDivergence block (new assertions test data reconciliation, not config-invariance)
script/upstream/replay.test.ts 328 Fail-closed binary-read throws in countBinaryConflictPaths are not exercised by any constructed fixture
Files Reviewed this pass (8 files changed, 0 new issues)
  • script/upstream/baselines/README.md — census headline counts corrected to match census.json; matches committed source of truth
  • script/upstream/census.tsvalidateUnclosedAllowlistEntry correctly rejects malformed expires (would otherwise silently suppress permanently); orphan-end documentation added; dead args removed
  • script/upstream/divergence.test.tshasRefs skip guard + reconciliation invariants verified against FileDiffStat shape
  • script/upstream/divergence.tsindentHeuristic=true + diff.ignore*=false pins match git defaults; array shape verified
  • script/upstream/replay.test.tshasRefs skip guard verified (note: uses execSync+shell || true, stylistically inconsistent with divergence.test.ts's spawnSync variant but functionally correct)
  • script/upstream/replay.tssanitizedGitEnv() mirrors divergence.ts; -c options placed before merge-tree subcommand (correct git CLI shape); optional upstreamBaseSha/taxonomyVersion validation preserves backward compat
  • script/upstream/taxonomy.test.tsUPSTREAM_TAG_AVAILABLE skip guard verified
  • script/upstream/utils/refs.ts — input dedup correctly closes the buffer-offset desync; scanFilesAtRef (only caller) already dedupes too, so behavior is preserved

Fix these issues in Kilo Cloud

Previous review (commit 8dfb358)

Status: 11 Issues Found | Recommendation: Address before merge

Incremental pass over commit 8dfb3585 (the parseNumstatZ fail-closed + O(1) census-lookup fix). No new issues found in the changed lines — the fail-closed change is correct and well-tested, and the Map refactor preserves the original first-block-wins bucket semantics. All 11 prior findings remain unresolved (none were touched by this commit).

Overview

Severity Count
CRITICAL 0
WARNING 6
SUGGESTION 5
Issue Details (click to expand)

WARNING

File Line Issue
.github/workflows/ci.yml 151 SUBPROCESS_PATHS adds test/altimate/trace-golden/, which does not exist at this PR's HEAD — the trace-golden harness commit 337144a78 is not an ancestor; either fails the subprocess summary gate or silently skips the oracle
script/upstream/census.ts 161 Orphan altimate_change end markers silently dropped (asymmetric with unclosed-start throw)
script/upstream/census.ts 253 loadUnclosedAllowlist skips per-entry validation that loadExemptions enforces; malformed expires silently becomes permanent suppression
script/upstream/divergence.ts 52 PINNED_DIFF_CONFIG doesn't pin diff.indentHeuristic (or diff.ignore*), contradicting the "config-immunity" reproducibility claim
script/upstream/replay.ts 175 runMergeTree doesn't pass -c core.quotepath=false/-z; non-ASCII conflicted paths mis-bucket in census attribution (sibling divergence.ts pins it)
script/upstream/replay.ts 181 merge-tree env inherits GIT_DIFF_OPTS/GIT_EXTERNAL_DIFF/GIT_CONFIG_*; sibling divergence.ts strips them via sanitizedGitEnv()

SUGGESTION

File Line Issue
script/upstream/census.ts 804 Dead args object built and discarded via void args; pure redundant code
script/upstream/divergence.test.ts 163 Tautological assertion (files.length === files.length); can never fail
script/upstream/taxonomy.ts 76 minimatch recompiles all 14 glob patterns per call across a multi-thousand-file corpus
script/upstream/divergence.test.ts 146 PR's "config-immunity" claim is not backed by an oracle test in this block
script/upstream/replay.test.ts 318 Fail-closed binary-read throws in countBinaryConflictPaths are not exercised by any constructed fixture
Files Reviewed this pass (3 files changed, 0 new issues)
  • script/upstream/divergence.tsparseNumstatZ fail-closed change verified correct; 3 throw paths match tests
  • script/upstream/divergence.test.ts — 3 new tests; all assertions verified against implementation
  • script/upstream/replay.tsattributeConflictsToCensus O(1) Map refactor preserves prior first-block-wins semantics

Fix these issues in Kilo Cloud

Previous review (commit 9f96122)

Status: 11 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 6
SUGGESTION 5
Issue Details (click to expand)

WARNING

File Line Issue
.github/workflows/ci.yml 151 SUBPROCESS_PATHS adds test/altimate/trace-golden/, which does not exist at this PR's HEAD — the trace-golden harness commit 337144a78 is not an ancestor; either fails the subprocess summary gate or silently skips the oracle (new in this pass)
script/upstream/census.ts 161 Orphan altimate_change end markers silently dropped (asymmetric with unclosed-start throw)
script/upstream/census.ts 253 loadUnclosedAllowlist skips per-entry validation that loadExemptions enforces; malformed expires silently becomes permanent suppression
script/upstream/divergence.ts 52 PINNED_DIFF_CONFIG doesn't pin diff.indentHeuristic (or diff.ignore*), contradicting the "config-immunity" reproducibility claim
script/upstream/replay.ts 175 runMergeTree doesn't pass -c core.quotepath=false/-z; non-ASCII conflicted paths mis-bucket in census attribution (sibling divergence.ts pins it)
script/upstream/replay.ts 181 merge-tree env inherits GIT_DIFF_OPTS/GIT_EXTERNAL_DIFF/GIT_CONFIG_*; sibling divergence.ts strips them via sanitizedGitEnv()

SUGGESTION

File Line Issue
script/upstream/census.ts 804 Dead args object built and discarded via void args; pure redundant code
script/upstream/divergence.test.ts 163 Tautological assertion (files.length === files.length); can never fail
script/upstream/taxonomy.ts 76 minimatch recompiles all 14 glob patterns per call across a multi-thousand-file corpus
script/upstream/divergence.test.ts 146 PR's "config-immunity" claim is not backed by an oracle test in this block
script/upstream/replay.test.ts 318 Fail-closed binary-read throws in countBinaryConflictPaths are not exercised by any constructed fixture
Files Reviewed (7 files)
  • .github/workflows/ci.yml — 1 issue (new in this pass)
  • script/upstream/census.ts — 3 issues
  • script/upstream/divergence.ts — 1 issue
  • script/upstream/replay.ts — 2 issues
  • script/upstream/taxonomy.ts — 1 issue
  • script/upstream/divergence.test.ts — 2 issues
  • script/upstream/replay.test.ts — 1 issue

Fix these issues in Kilo Cloud

Previous review (commit 5cf1b67)

Status: 10 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 5
SUGGESTION 5
Issue Details (click to expand)

WARNING

File Line Issue
script/upstream/census.ts 161 Orphan altimate_change end markers silently dropped (asymmetric with unclosed-start throw)
script/upstream/census.ts 253 loadUnclosedAllowlist skips per-entry validation that loadExemptions enforces; malformed expires silently becomes permanent suppression
script/upstream/divergence.ts 52 PINNED_DIFF_CONFIG doesn't pin diff.indentHeuristic (or diff.ignore*), contradicting the "config-immunity" reproducibility claim
script/upstream/replay.ts 175 runMergeTree doesn't pass -c core.quotepath=false/-z; non-ASCII conflicted paths mis-bucket in census attribution (sibling divergence.ts pins it)
script/upstream/replay.ts 181 merge-tree env inherits GIT_DIFF_OPTS/GIT_EXTERNAL_DIFF/GIT_CONFIG_*; sibling divergence.ts strips them via sanitizedGitEnv()

SUGGESTION

File Line Issue
script/upstream/census.ts 804 Dead args object built and discarded via void args; pure redundant code
script/upstream/divergence.test.ts 163 Tautological assertion (files.length === files.length); can never fail
script/upstream/taxonomy.ts 76 minimatch recompiles all 14 glob patterns per call across a multi-thousand-file corpus
script/upstream/divergence.test.ts 146 PR's "config-immunity" claim is not backed by an oracle test in this block
script/upstream/replay.test.ts 318 Fail-closed binary-read throws in countBinaryConflictPaths are not exercised by any constructed fixture
Files Reviewed (16 code/config files; 3 JSON baselines skimmed as data)
  • script/upstream/census.ts — 3 issues
  • script/upstream/census.test.ts — clean
  • script/upstream/divergence.ts — 1 issue
  • script/upstream/divergence.test.ts — 2 issues
  • script/upstream/replay.ts — 2 issues
  • script/upstream/replay.test.ts — 1 issue
  • script/upstream/taxonomy.ts — 1 issue
  • script/upstream/taxonomy.test.ts — clean
  • script/upstream/utils/jsonc.ts — clean
  • script/upstream/utils/jsonc.test.ts — clean
  • script/upstream/utils/refs.ts — clean
  • script/upstream/utils/repo-root.ts — clean
  • script/upstream/defork-exemptions.jsonc — clean
  • script/upstream/unclosed-marker-allowlist.jsonc — clean
  • script/upstream/baselines/README.md — clean
  • script/upstream/baselines/2026-07-18/*.json — skimmed as generated data (not in review scope)

Notes

  • Scope: All 16 source/config files in script/upstream/ are new (added by this PR), so every issue below is on changed code. The three baselines/*.json files are treated as generated data and not line-reviewed.
  • Theme: The strongest findings are correctness asymmetries between sibling tools (replay.ts vs divergence.ts on config/env pinning; census.ts end-marker vs unclosed-start handling; loadUnclosedAllowlist vs loadExemptions validation). These are the kind of cross-file inconsistencies CI cannot catch.
  • What's solid: marker-block parser nesting, multiset ratchet math, fail-closed hunk-attribution throw in divergence.ts:323, the rename-no-double-count regression test in replay.test.ts:287, the upstream-existence precedence in classifyBucket, and the --shortstat ground-truth pinning are all correct.

Fix these issues in Kilo Cloud


Reviewed by glm-5.2 · Input: 63.5K · Output: 13.7K · Cached: 530.8K

Review guidance: REVIEW.md from base branch main

- `git fetch upstream tag v1.17.9` so the de-fork tooling can resolve the
  pinned upstream base ref in CI (the branch fetch above excludes tags).
- Adds `test/altimate/trace-golden/` to the dedicated subprocess test pass so
  the trace-golden live E2E oracle actually runs in CI (it's otherwise skipped
  by OPENCODE_SKIP_SUBPROCESS=1 in the main pass).

The census-ratchet CI step is deferred to a follow-up: census reads markers
from the git tree, and now that script/upstream/ is committed it scans its own
marker-checking tooling (analyze.ts, census.ts, ...) which legitimately contain
marker syntax as code. The ratchet needs census.ts to exclude its own tooling
directory from the scan first; tracked separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

Comment thread .github/workflows/ci.yml Outdated
# exit code. --timeout 90000 gives headroom for slow fs/spawn tests.)
SUBPROCESS_PATHS="test/cli/acp/ test/cli/smokes/ test/cli/serve/ test/cli/run/run-process.test.ts test/cli/mcp-add.test.ts test/cli/help/help-snapshots.test.ts"
# altimate_change start — wire trace-golden's E2E oracle into the dedicated subprocess pass (its cliIt.live scenario tests are skipped by OPENCODE_SKIP_SUBPROCESS=1 in the main pass above and were previously never run in CI at all)
SUBPROCESS_PATHS="test/cli/acp/ test/cli/smokes/ test/cli/serve/ test/cli/run/run-process.test.ts test/cli/mcp-add.test.ts test/cli/help/help-snapshots.test.ts test/altimate/trace-golden/"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: test/altimate/trace-golden/ does not exist at this PR's HEAD

This step runs with working-directory: packages/opencode, so the added path resolves to packages/opencode/test/altimate/trace-golden/ — which does not exist (neither does test/altimate/trace-golden/ at the repo root). The trace-golden harness lives in commit 337144a78 ("test: [de-fork] trace-golden e2e harness"), which is not an ancestor of this PR's HEAD (git merge-base --is-ancestor 337144a78 HEAD → false; git ls-tree -r HEAD has no trace-golden entry). Either bun test errors on the missing path (the subprocess pass then emits no N pass summary line, failing the gate at line 175) or it silently skips the path — in both cases the altimate_change start comment's claim of "wiring trace-golden's E2E oracle into the dedicated subprocess pass" is not realized by this PR. Land the harness commit in this PR, or drop the path from SUBPROCESS_PATHS until that lands.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

…ensus lookup

- `divergence.ts` `parseNumstatZ` now fails closed (throws) on a malformed
  record head, a truncated rename record, or a non-numeric count field —
  matching `census.ts`'s sibling parser. Silently skipping / substituting `""`
  could drop files and understate totals with no error (CodeRabbit).
- 3 new fail-closed tests locking that behavior down.
- `replay.ts` census attribution builds a `file → bucket` Map once instead of an
  O(n) `.find()` per conflicted path (CodeRabbit nit).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

2 similar comments
@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

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

Copy link
Copy Markdown

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: 8dfb358502

ℹ️ 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 .github/workflows/ci.yml Outdated
# exit code. --timeout 90000 gives headroom for slow fs/spawn tests.)
SUBPROCESS_PATHS="test/cli/acp/ test/cli/smokes/ test/cli/serve/ test/cli/run/run-process.test.ts test/cli/mcp-add.test.ts test/cli/help/help-snapshots.test.ts"
# altimate_change start — wire trace-golden's E2E oracle into the dedicated subprocess pass (its cliIt.live scenario tests are skipped by OPENCODE_SKIP_SUBPROCESS=1 in the main pass above and were previously never run in CI at all)
SUBPROCESS_PATHS="test/cli/acp/ test/cli/smokes/ test/cli/serve/ test/cli/run/run-process.test.ts test/cli/mcp-add.test.ts test/cli/help/help-snapshots.test.ts test/altimate/trace-golden/"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Remove the nonexistent trace-golden test root

In the inspected commit, repo-wide git ls-tree and rg searches find no test/altimate/trace-golden/ directory or generated artifact—only this workflow reference. Bun reports Failed to scan non-existent root directory for tests when given such a root, so the subprocess pass emits no pass summary and the workflow's later missing-summary check exits 1, making this CI job fail instead of running the intended oracle.

Useful? React with 👍 / 👎.

Comment thread script/upstream/replay.ts Outdated
* discard stdout on a non-zero exit.
*/
function runMergeTree(repoRoot: string, baseSha: string, oursSha: string, targetSha: string): { stdout: string; exitCode: number } {
const result = spawnSync("git", ["merge-tree", "--write-tree", "--merge-base", baseSha, oursSha, targetSha], {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Parse merge-tree output with NUL-delimited paths

When a conflicted Git path legally contains a newline, this line-oriented invocation emits a C-quoted stage path but physically splits the Auto-merging and CONFLICT messages across lines; the parser then extracts only the prefix before the newline and countConflictRegions fails to read the resulting bogus tree path. git merge-tree -h documents -z as separating paths with NUL characters, so request and parse that machine-readable format to support arbitrary repository paths.

Useful? React with 👍 / 👎.

Comment thread script/upstream/replay.ts
): { byPath: Record<string, number>; total: number } {
const byPath: Record<string, number> = {}
let total = 0
const CONFLICT_START_RE = /^<<<<<<< /

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor configurable conflict-marker lengths

When a conflicted file has Git's supported conflict-marker-size attribute set to anything other than the default seven, its merged blob starts with a different number of < characters, but this exact-seven regex counts zero regions. The gitattributes documentation specifies that conflict-marker-size controls marker length; therefore replay reports an understated conflict-surface KPI for such files instead of detecting the actual regions.

Useful? React with 👍 / 👎.

…CI-safety

Critical / major:
- `refs.ts` `readBlobsBatch`: dedup input OIDs so `cat-file --batch` emits one
  record per oid — a duplicate previously desynced the buffer offset and
  silently corrupted the returned blob map (CodeRabbit CRITICAL).
- Real-repo tests (`divergence`/`replay`/`taxonomy`) now `describe.skipIf` when
  the pinned upstream tags aren't resolvable — CI fetches `--no-tags`, so they'd
  throw during ref resolution on a clean checkout (CodeRabbit CRITICAL/P1).
- `replay.ts`: pin `core.quotepath=false` + `merge.renames`/`renameLimit` on
  merge-tree and route all 3 git calls through `sanitizedGitEnv()` (strips
  `GIT_DIFF_OPTS`/`GIT_EXTERNAL_DIFF`) — quoted paths were missing the census
  lookup and inherited env could perturb counts (CodeRabbit Major + WARNINGs).
- `divergence.ts`: pin `diff.indentHeuristic=true` (baseline's value) + the
  `diff.ignore*` family off, so the config-immunity claim holds for hunk/line
  counts (CodeRabbit WARNING).

Robustness / correctness:
- `divergence.ts` `parseNumstatZ` fails closed on malformed head / truncated
  rename / non-numeric counts (+ 3 tests); `replay.ts` census attribution uses
  an O(1) Map and rejects a census with a mismatched `upstreamBaseSha` /
  `taxonomyVersion` (not just `oursSha`).
- `census.ts`: validate every unclosed-marker-allowlist entry (a bad `expires`
  was a silent permanent suppression); document the intentional orphan-`end`
  tolerance; drop dead `parseArgs` `args`/`void args`.
- Fix `baselines/README.md` census headline to match the committed `census.json`
  (228/84 fork-owned, 236/104 outside-boundary); replace a tautological
  divergence test assertion with real invariants (unique paths + sub-tally
  reconciliation).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

1 similar comment
@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

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

Copy link
Copy Markdown

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: 167c463ed9

ℹ️ 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 script/upstream/census.ts Outdated
const head = resolveRefOrThrow(headRef, repoRoot)
const baseResolved = resolveRefOrThrow(base, repoRoot)

const result = spawnSync("git", ["diff", "--numstat", "-M", "-z", baseResolved.sha, head.sha], {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Pin the rename limit for diff-budget

When a repository or runner configures a low diff.renameLimit, this -M invocation can disable rename detection for a large change while still exiting successfully, so an upstream-file rename is counted as separate deletion/addition records and changes the reported file, bucket, and added-line budgets. The inspected git diff -h documents -l<n> as “limit rename attempts up to paths,” and git help --config lists diff.renameLimit; pass an explicit -l or -c diff.renameLimit=... as divergence.ts does.

Useful? React with 👍 / 👎.

Comment thread script/upstream/divergence.ts Outdated
): DivergenceEnvelope {
const upstreamBase = resolveRefOrThrow(upstreamBaseRef, repoRoot)
const ours = resolveRefOrThrow(oursRef, repoRoot)
const upstreamPaths = loadPathsAtRef(upstreamBaseRef, repoRoot)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Read taxonomy paths from the resolved upstream SHA

When upstreamBaseRef is a movable branch and another process updates it after line 304 resolves it, this read can use the new tree while the diff and recorded upstreamBaseSha/upstreamBaseTree still use the old commit. The resulting envelope then has reproducible diff totals but incorrect, non-reproducible byBucket attribution; load paths from upstreamBase.sha instead.

Useful? React with 👍 / 👎.

Comment thread script/upstream/utils/refs.ts Outdated
Comment on lines +63 to +64
` git fetch ${remoteHint} ${ref} --no-tags\n` +
`Then re-run this command.`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Make the branch fetch hint resolve the requested ref

For a missing unqualified branch such as main, following this advertised command commonly creates upstream/main and writes FETCH_HEAD, but it does not create a local main ref, so rerunning with the original --upstream-base main still fails. I verified this in a clean repository with the standard remote wildcard refspec; consistent with git fetch -h describing the argument as a <refspec>, the hint should either include an explicit destination ref or tell the operator to rerun using the resulting remote-tracking ref.

Useful? React with 👍 / 👎.

…cibility

- CRITICAL/P1 (fails CI on this branch): ci.yml's SUBPROCESS_PATHS referenced
  `test/altimate/trace-golden/`, but that directory does not exist on this S1
  branch (it lives on defork/trace-golden-e2e). `bun test` reports "Failed to
  scan non-existent root directory", the subprocess pass emits no summary, and
  the missing-summary guard exits 1. Remove the path here; its CI wiring
  correctly lands on the trace-golden PR where the directory exists.

- divergence.ts: read taxonomy paths from the RESOLVED `upstreamBase.sha`, not
  the (possibly movable) ref — a branch advanced between resolution and the
  ls-tree read would attribute buckets against a newer tree than the diff and
  the recorded SHA/tree used (reproducible totals, wrong byBucket).

- census.ts `computeDiffBudget`: pin `diff.renameLimit` so a low repo/runner
  config can't silently disable `-M` rename detection and miscount an
  upstream-file rename as a separate delete+add (skewing file/bucket/line
  budgets). Mirrors divergence.ts's PINNED_DIFF_CONFIG.

- refs.ts: the missing-branch fetch hint suggested `git fetch <remote> <branch>`
  which only updates the remote-tracking ref, not a local one, so re-running
  with the same unqualified name still failed. Reword to tell the operator to
  re-run against `<remote>/<branch>` (or fetch into an explicit local ref).

Deferred (pathological-input edge cases, documented for follow-up): merge-tree
NUL(`-z`) parsing for conflicted paths containing literal newlines, and honoring
a non-default `conflict-marker-size` gitattribute in region counting. 158 pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

1 similar comment
@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@script/upstream/replay.test.ts`:
- Around line 12-15: Replace the execSync call in hasRefs with spawnSync
imported from child_process, passing git arguments through an array rather than
interpolating a shell command. Remove the shell-level “|| true” fallback and
determine each reference’s validity from the spawned process exit status,
preserving the existing refs.every behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ebd29b74-24f7-4766-9ba6-e5928d2af202

📥 Commits

Reviewing files that changed from the base of the PR and between 8dfb358 and 23b5a27.

📒 Files selected for processing (9)
  • .github/workflows/ci.yml
  • script/upstream/baselines/README.md
  • script/upstream/census.ts
  • script/upstream/divergence.test.ts
  • script/upstream/divergence.ts
  • script/upstream/replay.test.ts
  • script/upstream/replay.ts
  • script/upstream/taxonomy.test.ts
  • script/upstream/utils/refs.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • script/upstream/baselines/README.md
  • script/upstream/taxonomy.test.ts
  • script/upstream/divergence.test.ts
  • script/upstream/utils/refs.ts
  • script/upstream/replay.ts
  • script/upstream/divergence.ts

Comment on lines +12 to +15
function hasRefs(...refs: string[]): boolean {
const root = resolveRepoRoot()
return refs.every((r) => execSync(`git rev-parse --verify --quiet "${r}^{commit}" || true`, { cwd: root, encoding: "utf-8" }).trim().length > 0)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Use spawnSync to prevent potential command injection and avoid shell syntax.

execSync with dynamic string interpolation is flagged by static analysis. While the current arguments are hardcoded, you can future-proof this helper and avoid relying on shell evaluation (|| true) by using spawnSync with an argument array and checking the process exit status.

(Remember to import spawnSync from "child_process" if you apply this fix).

🛡️ Proposed fix
 function hasRefs(...refs: string[]): boolean {
   const root = resolveRepoRoot()
-  return refs.every((r) => execSync(`git rev-parse --verify --quiet "${r}^{commit}" || true`, { cwd: root, encoding: "utf-8" }).trim().length > 0)
+  return refs.every((r) => {
+    const { status } = spawnSync("git", ["rev-parse", "--verify", "--quiet", `${r}^{commit}`], { cwd: root })
+    return status === 0
+  })
 }
🧰 Tools
🪛 OpenGrep (1.25.0)

[ERROR] 14-14: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/upstream/replay.test.ts` around lines 12 - 15, Replace the execSync
call in hasRefs with spawnSync imported from child_process, passing git
arguments through an array rather than interpolating a shell command. Remove the
shell-level “|| true” fallback and determine each reference’s validity from the
spawned process exit status, preserving the existing refs.every behavior.

Source: Linters/SAST tools

Comment thread script/upstream/census.ts
// Pin diff.renameLimit so a low repo/runner config can't silently disable rename
// detection (`-M` falls back to no detection past the limit), which would miscount an
// upstream-file rename as a separate delete+add and skew the file/bucket/line budget.
// Mirrors divergence.ts's PINNED_DIFF_CONFIG.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: The comment claims this "Mirrors divergence.ts's PINNED_DIFF_CONFIG" but the invocation pins only diff.renameLimit — and even that with a different value (999999 here vs RENAME_LIMIT = 20000 in divergence.ts).

divergence.ts#PINNED_DIFF_CONFIG additionally pins the diff.ignore* family (which directly changes the added/deleted counts this function returns), core.quotepath, diff.algorithm, diff.indentHeuristic, etc.; passes --no-ext-diff --no-textconv so a read-only report can't execute configured helpers; and wraps the call in sanitizedGitEnv() to strip inherited GIT_DIFF_OPTS/GIT_EXTERNAL_DIFF. Census's computeDiffBudget does none of those, so the same (base, head) pair can yield different budgets on a differently-configured runner — the exact asymmetry the new comment denies. Either share PINNED_DIFF_CONFIG + sanitizedGitEnv from divergence.ts, or scope the comment to renameLimit only.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

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

Copy link
Copy Markdown

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: 23b5a27cbd

ℹ️ 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 script/upstream/census.ts
// detection (`-M` falls back to no detection past the limit), which would miscount an
// upstream-file rename as a separate delete+add and skew the file/bucket/line budget.
// Mirrors divergence.ts's PINNED_DIFF_CONFIG.
["-c", "diff.renameLimit=999999", "diff", "--numstat", "-M", "-z", baseResolved.sha, head.sha],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Pin the diff algorithm for diff-budget

When a runner or repository sets diff.algorithm (for example, histogram), this invocation inherits it and can report different added-line budgets for the same commits. I checked Git 2.43's git help --config, which lists diff.algorithm, and reproduced a fixture where --numstat reported +3/-4 with Myers but +4/-5 with Histogram; pin the algorithm and other count-affecting diff options as divergence.ts does.

Useful? React with 👍 / 👎.

Comment thread script/upstream/census.ts
`Bucket/category classification rules changed since the baseline was generated — regenerate the baseline before running --check.`,
)
}
if (current.upstreamBaseRef !== baseline.upstreamBaseRef || current.upstreamBaseSha !== baseline.upstreamBaseSha) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Accept aliases for the same upstream commit

When the baseline records v1.17.9 but the current invocation uses an equivalent ref such as refs/tags/v1.17.9 or the resolved SHA, this condition rejects the check even though both refs resolve to the same immutable commit/tree and therefore produce identical bucket classification. Compare resolved identity rather than the user-supplied ref spelling so valid --upstream-base <ref> aliases do not block the ratchet.

Useful? React with 👍 / 👎.

Comment thread script/upstream/census.ts
let forkAddedOutsideBoundaryFilesChanged = 0
let addedLinesInUpstreamShared = 0
let addedLinesInUpstreamSharedNonTest = 0
const isTestPath = (p: string) => /(^|\/)(test|tests)\//.test(p) || /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(p)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exclude all recognized test paths from the non-test budget

When added upstream-shared lines live under a common test directory such as src/__tests__/, this predicate returns false and adds them to addedLinesInUpstreamSharedNonTest; it similarly misses test suffixes such as .test.mts. The sibling divergence metric explicitly recognizes __tests__ and arbitrary alphabetic test extensions, so the two reports disagree and a future S3 non-test threshold can reject test-only changes as production drift.

Useful? React with 👍 / 👎.

Comment thread script/upstream/census.ts
Comment on lines +446 to +448
const unclosedAllowlist =
opts.unclosedAllowlist ??
loadUnclosedAllowlist(opts.unclosedAllowlistPath ?? path.join(repoRoot, "script/upstream/unclosed-marker-allowlist.jsonc"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Load the default allowlist from the analyzed revision

When --ours points to an older commit and the working-tree allowlist has since changed, the census scans source files from the old tree but applies line-number suppressions from the current checkout. This can either fail a reproducible historical census after harmless line movement or suppress an unrelated unclosed marker that now occupies the same coordinate, while the envelope records only the analyzed commit/tree; load the default allowlist from the resolved ours revision or pin its identity in the provenance.

Useful? React with 👍 / 👎.

Comment thread script/upstream/census.ts
for (const relPath of sortedPaths) {
const content = filesAtRef.get(relPath)!
const { blocks, unclosed } = parseMarkerBlocks(relPath, content, upstreamPaths)
allBlocks.push(...blocks)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exclude allowlisted false positives from census totals

When an unclosed block matches the allowlist, it is still retained in allBlocks and therefore contributes to total, bucket, category, and file counts even though the committed allowlist explicitly identifies every entry as documentation or test-string false positives rather than real markers. The committed baseline consequently reports 34 such entries in totals.unclosed and includes them in its 1,610-block headline, corrupting the de-fork inventory; exclude applied false positives from the marker population or report them only in the separate application section.

Useful? React with 👍 / 👎.

@anandgupta42

Copy link
Copy Markdown
Contributor Author

Review comments addressed (2 rounds)

Thanks to @coderabbitai, @chatgpt-codex-connector, and @kilo-code-bot. Resolutions:

Round 2 — 167c463ed9

  • CRITICAL (CodeRabbit): refs.ts readBlobsBatch desynced the cat-file --batch buffer on duplicate OIDs — now dedups input OIDs.
  • CRITICAL/P1: real-repo tests (divergence/replay/taxonomy) now describe.skipIf when pinned upstream tags aren't resolvable (CI fetches --no-tags).
  • Major/WARNINGs: replay.ts pins core.quotepath=false + merge.renames/renameLimit and routes git through sanitizedGitEnv(); divergence.ts pins diff.indentHeuristic + the diff.ignore* family; parseNumstatZ now fails closed (+3 tests); O(1) census Map lookup; census upstreamBaseSha/taxonomyVersion validation; allowlist-entry validation; corrected baselines/README.md; replaced the tautological divergence assertion.

Round 3 — 23b5a27cbd

  • P1 (merge-blocker): ci.yml SUBPROCESS_PATHS referenced test/altimate/trace-golden/, which does not exist on this branch (it lives on the trace-golden PR) → the subprocess pass would fail on a nonexistent root. Removed here.
  • divergence.ts reads taxonomy paths from the resolved upstreamBase.sha, not the movable ref; census.ts pins diff.renameLimit; refs.ts fetch hint now points at a resolvable ref.

Deferred (documented in the round-3 commit body): merge-tree -z/NUL parsing for conflicted paths containing literal newlines, and non-default conflict-marker-size gitattribute handling — both pathological-input edge cases.

158 pass, typecheck clean.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@anandgupta42 Thanks for the thorough resolution summary. The fixes cover the reported correctness and CI-blocking concerns, and the two deferred pathological parsing cases are clearly scoped and documented.

🐇 ✅


✏️ Learnings added
Learnt from: anandgupta42
URL: https://github.com/AltimateAI/altimate-code/pull/1013

Timestamp: 2026-07-20T02:27:03.450Z
Learning: In `script/upstream/`, merge replay handling intentionally defers two documented pathological cases: conflicted paths containing literal newlines require NUL-delimited `git merge-tree` parsing, and conflict-region counting does not yet honor non-default `conflict-marker-size` gitattributes.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

De-fork spike S1: baseline metrics + upstream-merge replay harness

1 participant