Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/pre-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Pre-Merge Checks

on:
pull_request:
branches:
- main
push:
branches:
- main

permissions:
contents: read

concurrency:
group: pre-merge-${{ github.ref }}
cancel-in-progress: true

jobs:
pre-merge:
timeout-minutes: 30
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'

Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Install deps
run: npm ci

- name: Run pre-merge gate
run: npm run premerge
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22.14.0'
node-version-file: '.nvmrc'
registry-url: 'https://registry.npmjs.org'

- name: Install deps
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/ricky-evals.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ permissions:
pull-requests: write

env:
NODE_VERSION: "22.14.0"
NPM_CONFIG_FUND: "false"
RICKY_EVAL_OPENROUTER_MODEL: openai/gpt-oss-120b:free

Expand All @@ -70,7 +69,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
node-version-file: '.nvmrc'
cache: npm
cache-dependency-path: package-lock.json

Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20
22.14.0
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ Ricky is a single-package npm repo with a flat `src/` tree. npm is the only supp
npm install # install dependencies for the single root package
npm run typecheck # typecheck src, tests, workflows, and scripts
npm test # bundle the CLI and run the repo test suite + proof tests
npm run premerge # run typecheck, full tests, and the local auto-fix ladder e2e
npm start # launch the CLI from src/surfaces/cli/commands/cli-main.ts
```

Expand All @@ -164,6 +165,7 @@ npm scripts (canonical ordering matches `package.json`):
- `npm run build` — alias for `bundle`; produces `dist/ricky.js`
- `npm run typecheck` — typecheck the flat `src/` tree plus workflows/proofs/scripts
- `npm test` — bundle the CLI, then run the full test suite and proof tests
- `npm run premerge` — run typecheck, the full test suite, and `test/local-auto-fix-workflow-failures.e2e.test.ts` as an explicit pre-merge regression gate
- `npm start` — launch the interactive CLI from `src/surfaces/cli/commands/cli-main.ts`
- `npm run dev` — alias for `npm start`
- `npm run evals` — compile and run the Ricky eval suite
Expand All @@ -180,7 +182,7 @@ npm scripts (canonical ordering matches `package.json`):
- checkpoint state lives under `.workflow-artifacts/state/overnight/<queue-mode>/checkpoint.env` (legacy `.workflow-artifacts/overnight-state/...` checkpoints are still imported automatically)
- `npm run prepack` — build before package packing (runs automatically on `npm pack` and `npm publish`)

Node and npm versions are pinned: `engines.node = ">=20"`, `packageManager = "npm@11.11.0"`, `engine-strict=true` in `.npmrc`, and `.nvmrc = 20`. There is no Yarn, pnpm, or other package-manager surface — npm is the default and only path.
Node and npm versions are pinned: `engines.node = ">=22.14.0"`, `packageManager = "npm@11.11.0"`, `engine-strict=true` in `.npmrc`, and `.nvmrc = 22.14.0`. There is no Yarn, pnpm, or other package-manager surface — npm is the default and only path.

Note: `prpm.lock` at the repo root is **not** an npm artifact. It tracks AI-agent skills installed under `.agents/skills/` via the `prpm` skill registry, and it is referenced by `test/flat-layout-proof/` to verify that legacy Claude skill mirrors stay removed. Treat it as orthogonal to npm.

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
},
"packageManager": "npm@11.11.0",
"engines": {
"node": ">=20"
"node": ">=22.14.0"
},
"type": "module",
"bin": {
Expand All @@ -42,6 +42,7 @@
"build": "npm run bundle",
"typecheck": "tsc --noEmit",
"test": "npm run bundle && vitest run",
"premerge": "npm run typecheck && npm test && npx vitest run test/local-auto-fix-workflow-failures.e2e.test.ts",
"evals:compile": "node scripts/evals/compile-ricky-evals.mjs",
"evals": "npm run evals:compile && node scripts/evals/run-ricky-evals.mjs",
"evals:provider": "npm run build && npm run evals -- --provider --executor openrouter",
Expand Down
2 changes: 1 addition & 1 deletion src/surfaces/cli/flows/local-run-monitor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ describe('local run monitor', () => {
if (child.exitCode === null) child.kill('SIGKILL');
await rm(cwd, { recursive: true, force: true });
}
});
}, 20_000);

it('defaults run state under the repo .workflow-artifacts directory', () => {
const cwd = '/workspace/customer-repo';
Expand Down
2 changes: 1 addition & 1 deletion test/flat-layout-proof/flat-layout-proof.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,6 @@ describe('Ricky flat src layout proof', () => {
evaluateFlatLayoutProof();
const elapsed = performance.now() - start;

expect(elapsed).toBeLessThan(1000);
expect(elapsed).toBeLessThan(2000);
});
});
5 changes: 4 additions & 1 deletion test/package-proof/package-layout-proof.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ describe('Ricky package layout and npm-default proof', () => {
'npm-default-package-manifest',
[
'package.json packageManager: npm@',
'package.json engines.node: >=22.14.0',
'package.json workspaces declared: false',
'package-lock.json present: true',
'alternative lockfiles present: (none)',
Expand All @@ -49,6 +50,7 @@ describe('Ricky package layout and npm-default proof', () => {
'.npmrc exists: true',
'.nvmrc exists: true',
'.npmrc declares engine-strict=true: true',
'.nvmrc value: 22.14.0',
],
],
[
Expand All @@ -72,9 +74,10 @@ describe('Ricky package layout and npm-default proof', () => {
[
'package-script-allowlist',
[
'required scripts: batch, build, bundle, clean, dev, evals, evals:compare, evals:compile, evals:list, evals:opencode, evals:provider, evals:summary, overnight, prepack, start, test, typecheck',
'required scripts: batch, build, bundle, clean, dev, evals, evals:compare, evals:compile, evals:list, evals:opencode, evals:provider, evals:summary, overnight, premerge, prepack, start, test, typecheck',
'missing required scripts: (none)',
'unexpected extra scripts: (none)',
'premerge runs local auto-fix ladder e2e: true',
],
],
[
Expand Down
20 changes: 19 additions & 1 deletion test/package-proof/package-layout-proof.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const REQUIRED_PACKAGE_SCRIPTS = [
'build',
'typecheck',
'test',
'premerge',
'start',
'dev',
'evals',
Expand Down Expand Up @@ -411,20 +412,37 @@ export function getPackageLayoutProofCases(): PackageLayoutProofCase[] {
const required = [...REQUIRED_PACKAGE_SCRIPTS].sort();
const missing = required.filter((name) => typeof scripts[name] !== 'string' || (scripts[name] as string).length === 0);
const extra = declared.filter((name) => !required.includes(name as (typeof REQUIRED_PACKAGE_SCRIPTS)[number]));
const premerge = typeof scripts.premerge === 'string' ? scripts.premerge : '';
const premergeRunsTypecheck = premerge.includes('npm run typecheck');
const premergeRunsFullSuite = premerge.includes('npm test');
const premergeRunsAutoFixLadder = premerge.includes('test/local-auto-fix-workflow-failures.e2e.test.ts');

return result(
'package-script-allowlist',
[missing.length === 0, extra.length === 0],
[
missing.length === 0,
extra.length === 0,
premergeRunsTypecheck,
premergeRunsFullSuite,
premergeRunsAutoFixLadder,
],
[
`required scripts: ${required.join(', ')}`,
`declared scripts: ${declared.join(', ')}`,
`missing required scripts: ${missing.join(', ') || '(none)'}`,
`unexpected extra scripts: ${extra.join(', ') || '(none)'}`,
`package.json scripts.premerge: ${premerge || '(missing)'}`,
`premerge runs typecheck: ${premergeRunsTypecheck}`,
`premerge runs full test suite: ${premergeRunsFullSuite}`,
`premerge runs local auto-fix ladder e2e: ${premergeRunsAutoFixLadder}`,
],
[],
[
...missing.map((name) => `Missing required npm script: ${name}`),
...extra.map((name) => `Unexpected npm script not in canonical allowlist: ${name}`),
...(premergeRunsTypecheck ? [] : ['package.json scripts.premerge does not run npm run typecheck']),
...(premergeRunsFullSuite ? [] : ['package.json scripts.premerge does not run npm test']),
...(premergeRunsAutoFixLadder ? [] : ['package.json scripts.premerge does not run the local auto-fix workflow ladder e2e']),
],
);
},
Expand Down
Loading