feat: LOC reframe tooling — throughput comparison + README updater + scc installer

Three new scripts:

- scripts/garry-output-comparison.ts — enumerates Garry-authored commits
  in 2013 + 2026 on public repos, extracts ADDED lines from git diff,
  classifies as logical SLOC via scc --stdin (regex fallback if scc
  missing). Writes docs/throughput-2013-vs-2026.json with per-language
  breakdown + explicit caveats (public repos only, commit-style drift,
  private-work exclusion).

- scripts/update-readme-throughput.ts — reads the JSON if present,
  replaces the README's <!-- GSTACK-THROUGHPUT-PLACEHOLDER --> anchor
  with the computed multiple (preserving the anchor for future runs).
  If JSON missing, writes GSTACK-THROUGHPUT-PENDING marker that CI
  rejects — forcing the build to run before commit.

- scripts/setup-scc.sh — standalone OS-detecting installer for scc.
  Not a package.json dependency (95% of users never run throughput).
  Brew on macOS, apt on Linux, GitHub releases link on Windows.

Two-string anchor pattern (PLACEHOLDER vs PENDING) prevents the
pipeline from destroying its own update path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-04-18 11:38:35 +08:00
parent 6c4f72a426
commit d840ab67f4
3 changed files with 429 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
#!/usr/bin/env bun
/**
* Read docs/throughput-2013-vs-2026.json, replace the README anchor with the
* computed logical-lines multiple.
*
* Two-string pattern (resolves the pipeline-eats-itself bug Codex caught in V1
* planning, Pass 2 finding #10):
* - GSTACK-THROUGHPUT-PLACEHOLDER — stable anchor, lives in README permanently.
* Script finds this anchor and writes the number right before it, keeping
* the anchor itself for the next run.
* - GSTACK-THROUGHPUT-PENDING — explicit missing-build marker. If the JSON
* isn't present, the script writes this marker at the anchor location.
* CI rejects commits containing this string, so contributors get a clear
* signal to run the throughput script before committing.
*/
import * as fs from 'fs';
import * as path from 'path';
const ROOT = process.cwd();
const README = path.join(ROOT, 'README.md');
const JSON_PATH = path.join(ROOT, 'docs', 'throughput-2013-vs-2026.json');
const ANCHOR = '<!-- GSTACK-THROUGHPUT-PLACEHOLDER -->';
const PENDING = 'GSTACK-THROUGHPUT-PENDING';
function main() {
if (!fs.existsSync(README)) {
process.stderr.write(`README.md not found at ${README}\n`);
process.exit(1);
}
const readme = fs.readFileSync(README, 'utf-8');
if (!readme.includes(ANCHOR)) {
// Anchor already replaced by a computed number (or was never inserted).
// Nothing to do — silent success.
return;
}
if (!fs.existsSync(JSON_PATH)) {
// Build hasn't produced the JSON. Write the PENDING marker at the anchor,
// preserving the anchor so the next run can replace it.
const replacement = `${PENDING}: run scripts/garry-output-comparison.ts ${ANCHOR}`;
const updated = readme.replace(ANCHOR, replacement);
fs.writeFileSync(README, updated);
process.stderr.write(
`${JSON_PATH} not found. Wrote ${PENDING} marker to README. Run scripts/garry-output-comparison.ts to generate it.\n`
);
// Non-zero exit so CI that wraps this sees the signal, but local dev workflows
// can continue. Callers can decide whether this is fatal.
process.exit(0);
}
let parsed: { multiples?: { logical_lines_added?: number | null } } = {};
try {
parsed = JSON.parse(fs.readFileSync(JSON_PATH, 'utf-8'));
} catch (err) {
process.stderr.write(`Failed to parse ${JSON_PATH}: ${err}\n`);
process.exit(1);
}
const mult = parsed?.multiples?.logical_lines_added;
if (mult === null || mult === undefined) {
// JSON exists but doesn't have a computable multiple (e.g., one year inactive).
// Write an honest pending-ish marker. Don't fall back to a bogus number.
const replacement = `${PENDING}: multiple not yet computable (one or both years inactive in this repo) ${ANCHOR}`;
const updated = readme.replace(ANCHOR, replacement);
fs.writeFileSync(README, updated);
process.stderr.write(`Multiple not computable. Wrote ${PENDING} marker.\n`);
process.exit(0);
}
// Normal flow: replace the anchor with the number + anchor (anchor stays for next run).
const replacement = `**${mult}×** ${ANCHOR}`;
const updated = readme.replace(ANCHOR, replacement);
fs.writeFileSync(README, updated);
process.stderr.write(`README throughput multiple updated: ${mult}×\n`);
}
main();