diff --git a/.github/workflows/optimizer1000.yml b/.github/workflows/optimizer1000.yml new file mode 100644 index 0000000000..2c1c1dce4e --- /dev/null +++ b/.github/workflows/optimizer1000.yml @@ -0,0 +1,54 @@ +name: Optimizer1000 Nightly + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + inputs: + investigate: + type: boolean + description: 'Investigate metrics' + default: false + update_processes: + type: boolean + description: 'Update processes based on learnings' + default: false + commit: + type: boolean + description: 'Run processes and commit' + default: false + +jobs: + optimize: + runs-on: ubuntu-latest + permissions: + contents: write + issues: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + - name: Install dependencies + run: npm install + - name: Build optimizer + run: | + cd tools/optimizer + npm install + - name: Run Optimizer1000 + env: + GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + npx tsx tools/optimizer/index.ts \ + ${{ github.event.inputs.investigate == 'true' && '--investigate' || '' }} \ + ${{ github.event.inputs.update_processes == 'true' && '--update-processes' || '' }} \ + ${{ github.event.inputs.commit == 'true' && '--commit' || '' }} + - name: Upload artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: optimizer-results + path: "*.csv" diff --git a/tools/optimizer/GEMINI.md b/tools/optimizer/GEMINI.md new file mode 100644 index 0000000000..f172935113 --- /dev/null +++ b/tools/optimizer/GEMINI.md @@ -0,0 +1,15 @@ +# Optimizer1000 - Instructions for Gemini CLI + +You are the engine behind the `optimizer1000`. You run in phases, and for each phase, you are given a specific `-AGENT.md` prompt. + +## How to Modify the Tool +- **Metrics**: To add a new metric, add a script in `metrics/scripts/` and document it in `metrics/METRICS.md`. +- **Investigations**: To add a deep-dive investigation, add a script in `investigations/scripts/` and document it in `investigations/INVESTIGATIONS.md`. +- **Processes**: To add an optimization process, add a script in `processes/scripts/` and document it in `processes/PROCESSES.md`. +- **Prompts**: You can update your own behavior by modifying the `*-AGENT.md` files in each directory. + +## Safety & Security +- Never modify product or tool code outside of `tools/optimizer/` unless the `commit` flag is explicitly enabled. +- All repository modifications should be proposed via PRs created with the `gh` CLI. +- Changes should prioritize transparency by logging all intended actions to CSV files. +- Always check the `metrics-before.csv` to understand the current state before recommending changes. diff --git a/tools/optimizer/index.ts b/tools/optimizer/index.ts new file mode 100644 index 0000000000..800e22ddcf --- /dev/null +++ b/tools/optimizer/index.ts @@ -0,0 +1,118 @@ +import { Command } from 'commander'; +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { execSync } from 'node:child_process'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +async function main() { + const program = new Command(); + program + .option('--investigate', 'Run investigation phase', false) + .option('--update-processes', 'Update processes based on learnings', false) + .option('--commit', 'Run processes and commit changes', false) + .parse(process.argv); + + const options = program.opts(); + + console.log('Optimizer1000 starting...'); + console.log('Options:', options); + + const rootDir = path.resolve(__dirname, '../..'); + + // Ensure history directory exists so agent doesn't fail listing it + await fs.mkdir(path.join(rootDir, 'history'), { recursive: true }); + + // 0. Fetch previous artifacts + try { + console.log('Checking for previous artifacts...'); + // Check if any run exists for the current branch + const branch = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8' }).trim(); + const runCheck = execSync(`gh run list --branch ${branch} --limit 1 --json databaseId --jq '.[0].databaseId' || true`, { encoding: 'utf-8' }).trim(); + + if (runCheck && runCheck !== '') { + console.log('Attempting to fetch previous artifacts into history/ (timeout 30s)...'); + await fs.mkdir(path.join(rootDir, 'history'), { recursive: true }); + // Download will fail gracefully if the artifact name doesn't match + execSync(`gh run download --name optimizer-results --pattern "*.csv" --dir history > /dev/null 2>&1 || true`, { + stdio: 'inherit', + timeout: 30000, + cwd: rootDir + }); + } else { + console.log('No previous runs found, skipping download.'); + } + } catch (err) { + console.warn('Artifact check/download skipped, proceeding with fresh state.'); + } + + // 1. Initial Metrics + await runPhase('metrics', { PRE_RUN: 'true' }, options); + + // 2. Investigation (Optional) + if (options.investigate) { + await runPhase('investigations', {}, options); + } + + // 3. Update Processes & Run + await runPhase('processes', { + UPDATE_PROCESSES: String(options.updateProcesses), + COMMIT: String(options.commit), + }, options); + + // 4. Final Metrics + await runPhase('metrics', { PRE_RUN: 'false' }, options); + + console.log('\nOptimizer1000 completed.'); +} + +async function runPhase(phaseDir: string, env: Record, options: any) { + console.log(`\n--- Phase: ${phaseDir} ---`); + const phasePath = path.join(__dirname, phaseDir); + + let promptFile: string | undefined; + try { + const files = await fs.readdir(phasePath); + promptFile = files.find(f => f.endsWith('-AGENT.md')); + } catch (err) { + console.warn(`Directory ${phaseDir} not found or inaccessible.`); + return; + } + + if (!promptFile) { + console.warn(`No agent prompt found in ${phaseDir}`); + return; + } + + const instructionsPath = path.join(phasePath, promptFile); + + const envString = Object.entries(env).map(([k, v]) => `${k}=${v}`).join('\n'); + const userPrompt = `Execution Context:\n${envString}\n\nPlease proceed with the ${phaseDir} tasks as defined in your instructions. Always output CSV files as requested.`; + + console.log(`Running agent with prompt: ${promptFile}`); + + // Resolve root to call the CLI binary + const rootDir = path.resolve(__dirname, '../..'); + + try { + // Run GCLI non-interactively with --yolo to bypass policies + const cliPath = path.join(rootDir, 'packages', 'cli'); + const command = `node ${cliPath} --prompt "${userPrompt}" --instructions-path "${instructionsPath}" --yolo`; + + execSync(command, { + stdio: 'inherit', + cwd: rootDir, + env: { ...process.env, ...env } + }); + } catch (err) { + console.error(`Error in phase ${phaseDir}:`, err.message); + } + + console.log(`\n--- Finished Phase: ${phaseDir} ---`); +} + +main().catch(err => { + console.error('Fatal error:', err); + process.exit(1); +}); diff --git a/tools/optimizer/investigations/INVESTIGATIONS-AGENT.md b/tools/optimizer/investigations/INVESTIGATIONS-AGENT.md new file mode 100644 index 0000000000..4230c3ee35 --- /dev/null +++ b/tools/optimizer/investigations/INVESTIGATIONS-AGENT.md @@ -0,0 +1,8 @@ +# Investigations Agent + +Your task is to investigate metrics to understand what is contributing to their current values. + +1. Analyze `metrics-before.csv` and compare it with any historical metrics in `history/` (e.g., `history/metrics-after.csv` from a previous run). +2. Run existing scripts in `investigations/scripts/` to gather more data. +3. If necessary, create NEW investigation scripts in `investigations/scripts/` to dig deeper (e.g., check issue labels, age, or assignees). +4. Document your findings in `investigations/INVESTIGATIONS.md`, noting if metrics are improving or worsening. diff --git a/tools/optimizer/investigations/INVESTIGATIONS.md b/tools/optimizer/investigations/INVESTIGATIONS.md new file mode 100644 index 0000000000..e119cca0f8 --- /dev/null +++ b/tools/optimizer/investigations/INVESTIGATIONS.md @@ -0,0 +1,6 @@ +# Deep-Dive Investigations + +This file documents ad hoc investigations performed to understand contributing factors to metrics. + +| Investigation | Metric | Script | Findings | +|---------------|--------|--------|----------| diff --git a/tools/optimizer/metrics/METRICS-AGENT.md b/tools/optimizer/metrics/METRICS-AGENT.md new file mode 100644 index 0000000000..5dbc4e4c8c --- /dev/null +++ b/tools/optimizer/metrics/METRICS-AGENT.md @@ -0,0 +1,9 @@ +# Metrics Agent + +Your task is to gather repository metrics. + +1. Check for historical data in the `history/` directory to understand previous trends. +2. Run all scripts in the `metrics/scripts/` directory. +3. Output the results to a `metrics-before.csv` file in the project root if this is the start of the run (determined by the presence of `PRE_RUN=true`), or `metrics-after.csv` in the root if it is the end (`PRE_RUN=false`). +4. For any targeted repository concept (e.g., issues), generate a `[concept]-before.csv` (or `-after.csv`) in the project root listing the items and their current state. +5. If a tool fails (e.g., policy denial or script error), report the exact error and DO NOT claim success for that specific task. Attempt to proceed with other scripts if possible. diff --git a/tools/optimizer/metrics/METRICS.md b/tools/optimizer/metrics/METRICS.md new file mode 100644 index 0000000000..955485d4d7 --- /dev/null +++ b/tools/optimizer/metrics/METRICS.md @@ -0,0 +1,7 @@ +# Repository Metrics + +This file documents the metrics tracked by `optimizer1000`. + +| Metric | Description | Script | Goal | +|--------|-------------|--------|------| +| open_issues | Number of open issues in the repo | `metrics/scripts/open_issues.js` | Lower is better | diff --git a/tools/optimizer/metrics/scripts/open_issues.js b/tools/optimizer/metrics/scripts/open_issues.js new file mode 100644 index 0000000000..2afe143300 --- /dev/null +++ b/tools/optimizer/metrics/scripts/open_issues.js @@ -0,0 +1,14 @@ +import { execSync } from 'node:child_process'; + +try { + const output = execSync('gh issue list --state open --limit 1000 --json number', { encoding: 'utf-8' }); + const issues = JSON.parse(output); + process.stdout.write(JSON.stringify({ + metric: 'open_issues', + value: issues.length, + timestamp: new Date().toISOString() + })); +} catch (err) { + process.stderr.write(err.message); + process.exit(1); +} diff --git a/tools/optimizer/package-lock.json b/tools/optimizer/package-lock.json new file mode 100644 index 0000000000..4ef5ba978b --- /dev/null +++ b/tools/optimizer/package-lock.json @@ -0,0 +1,631 @@ +{ + "name": "optimizer1000", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "optimizer1000", + "version": "1.0.0", + "dependencies": { + "@google/gemini-cli-sdk": "file:../../packages/sdk", + "commander": "^12.0.0", + "csv-writer": "^1.6.0" + }, + "devDependencies": { + "@types/node": "^20.12.7", + "tsx": "^4.20.3", + "typescript": "^5.4.5" + } + }, + "../../packages/sdk": { + "name": "@google/gemini-cli-sdk", + "version": "0.40.0-nightly.20260414.g5b1f7375a", + "license": "Apache-2.0", + "dependencies": { + "@google/gemini-cli-core": "file:../core", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.23.1" + }, + "devDependencies": { + "typescript": "^5.3.3", + "vitest": "^3.1.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@google/gemini-cli-sdk": { + "resolved": "../../packages/sdk", + "link": true + }, + "node_modules/@types/node": { + "version": "20.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", + "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/csv-writer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/csv-writer/-/csv-writer-1.6.0.tgz", + "integrity": "sha512-NOx7YDFWEsM/fTRAJjRpPp8t+MKRVvniAg9wQlUKx20MFrPs73WLJhFf5iteqrxNYnsy924K3Iroh3yNHeYd2g==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/tools/optimizer/package.json b/tools/optimizer/package.json new file mode 100644 index 0000000000..f2f0611136 --- /dev/null +++ b/tools/optimizer/package.json @@ -0,0 +1,17 @@ +{ + "name": "optimizer1000", + "version": "1.0.0", + "type": "module", + "scripts": { + "start": "tsx index.ts" + }, + "dependencies": { + "commander": "^12.0.0", + "csv-writer": "^1.6.0" + }, + "devDependencies": { + "tsx": "^4.20.3", + "typescript": "^5.4.5", + "@types/node": "^20.12.7" + } +} diff --git a/tools/optimizer/processes/PROCESSES-AGENT.md b/tools/optimizer/processes/PROCESSES-AGENT.md new file mode 100644 index 0000000000..5a4009f6dc --- /dev/null +++ b/tools/optimizer/processes/PROCESSES-AGENT.md @@ -0,0 +1,11 @@ +# Processes Agent + +Your task is to optimize repository metrics based on investigations and current state. + +1. Analyze `metrics-before.csv`, `investigations/INVESTIGATIONS.md`, and historical data in `history/`. +2. Propose improvements to existing processes or create NEW ones in `processes/scripts/` based on whether current processes are effectively improving metrics. +3. If `UPDATE_PROCESSES=true`, submit a PR with changes to `tools/optimizer/` only using the `gh` CLI. +4. Run all active processes documented in `processes/PROCESSES.md`. +5. If `COMMIT=true`, apply changes directly to the repository (e.g., triage issues, close stale PRs) using the `gh` CLI. +6. Regardless of `COMMIT` value, always generate `[concept]-after.csv` (e.g., `issues-after.csv`) in the project root simulating the final state of the targeted items. Use `[concept]-before.csv` as a baseline. +7. If any tool fails (e.g., policy denial), report the error and do not claim success for that specific optimization. diff --git a/tools/optimizer/processes/PROCESSES.md b/tools/optimizer/processes/PROCESSES.md new file mode 100644 index 0000000000..67cd99eb05 --- /dev/null +++ b/tools/optimizer/processes/PROCESSES.md @@ -0,0 +1,7 @@ +# Optimization Processes + +This file documents the automated processes run to improve repository metrics. + +| Process | Target Metric | Script | Description | +|---------|---------------|--------|-------------| +| triage_issues | open_issues | `processes/scripts/triage_issues.js` | Basic issue triage and labeling | diff --git a/tools/optimizer/tsconfig.json b/tools/optimizer/tsconfig.json new file mode 100644 index 0000000000..056700f344 --- /dev/null +++ b/tools/optimizer/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "outDir": "./dist" + }, + "include": ["**/*.ts"] +}