diff --git a/CHANGELOG.md b/CHANGELOG.md index d69a993..ede8928 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## [2.2.0] - 2026-02-14 + +### Added +- **Automatic Leaderboard Sync**: + - Watcher auto-syncs stats after commit or push. + - Uses site API with anonymized ID and metrics only. +- **Durable Backend Storage**: + - Website API backed by Supabase for persistent leaderboard and event telemetry. +- **Events API**: + - CLI emits `push_success` events with commit hash and identity. + - Website ingests and stores normalized payloads. + +### Improved +- **Config Consistency**: + - Standardized `blockedBranches` with backward-compat mapping. +- **AI Network Resilience**: + - Added request timeouts to Gemini/Grok; doctor validates connectivity. +- **Programmatic Imports**: + - Fixed command imports wiring in `src/index.js`. + +### Docs/Website +- **OG Image & Favicon**: + - Added `public/og-image.svg` and `public/favicon.svg`. + - Corrected manifest path to `/manifest.webmanifest`. +- **Foreground Watcher Wording**: + - Updated homepage and commands to reflect foreground behavior. + +### Tests +- **Grok Test Coverage**: + - Added parity tests mirroring Gemini scenarios. + All notable changes to this project will be documented in this file. This project follows [Semantic Versioning](https://semver.org). diff --git a/autopilot-docs/app/docs/[[...slug]]/page.tsx b/autopilot-docs/app/docs/[[...slug]]/page.tsx index d3efcce..8a20d66 100644 --- a/autopilot-docs/app/docs/[[...slug]]/page.tsx +++ b/autopilot-docs/app/docs/[[...slug]]/page.tsx @@ -72,6 +72,8 @@ export default async function DocPage({ source={doc.content} components={components} options={{ + blockJS: true, + blockDangerousJS: true, mdxOptions: { remarkPlugins: [remarkGfm], rehypePlugins: [ diff --git a/autopilot-docs/app/layout.tsx b/autopilot-docs/app/layout.tsx index 3b07705..5dcd408 100644 --- a/autopilot-docs/app/layout.tsx +++ b/autopilot-docs/app/layout.tsx @@ -62,9 +62,9 @@ export const metadata: Metadata = { creator: '@PraiseTechzw', }, icons: { - icon: '/favicon.ico', - shortcut: '/favicon.ico', - apple: '/favicon.ico', // Ideally we should have a real apple-touch-icon + icon: '/favicon.svg', + shortcut: '/favicon.svg', + apple: '/favicon.svg', }, manifest: '/manifest.webmanifest', robots: { diff --git a/autopilot-docs/app/manifest.ts b/autopilot-docs/app/manifest.ts index 014745b..ef11b7b 100644 --- a/autopilot-docs/app/manifest.ts +++ b/autopilot-docs/app/manifest.ts @@ -11,9 +11,9 @@ export default function manifest(): MetadataRoute.Manifest { theme_color: '#2563eb', icons: [ { - src: '/favicon.ico', + src: '/favicon.svg', sizes: 'any', - type: 'image/x-icon', + type: 'image/svg+xml', }, ], }; diff --git a/autopilot-docs/content/docs/changelog.mdx b/autopilot-docs/content/docs/changelog.mdx index 104e4ee..6be6d0d 100644 --- a/autopilot-docs/content/docs/changelog.mdx +++ b/autopilot-docs/content/docs/changelog.mdx @@ -3,6 +3,28 @@ title: Changelog description: Latest updates and improvements to Autopilot CLI. --- +## [2.2.0] - 2026-02-14 + +### Added +- **Automatic Leaderboard Sync**: + - Watcher auto-syncs stats after commit or push using site API. +- **Durable Backend Storage**: + - Leaderboard and events stored in Supabase with normalized schema. +- **Events API**: + - Ingests `push_success` from CLI and stores telemetry. + +### Improved +- **Config Consistency**: Standardized `blockedBranches` and loader back-compat. +- **AI Provider Hardening**: Added request timeouts; doctor validates keys. +- **Programmatic Imports**: Fixed command imports wiring in CLI. + +### Docs/Website +- **Metadata & Assets**: Added OG image and proper favicon; corrected manifest path. +- **Foreground Watcher**: Updated wording on homepage and commands. + +### Tests +- **Grok Parity**: Added Grok tests mirroring Gemini coverage. + Stay up to date with the latest changes to Autopilot CLI. For a full history of releases, visit our [GitHub Releases](https://github.com/PraiseTechzw/autopilot-cli/releases) page. ## [2.0.1] - 2026-02-05 diff --git a/autopilot-docs/lib/search-index.json b/autopilot-docs/lib/search-index.json index 716b86c..9507df5 100644 --- a/autopilot-docs/lib/search-index.json +++ b/autopilot-docs/lib/search-index.json @@ -5,6 +5,41 @@ "route": "/docs/changelog", "type": "page" }, + { + "title": "[2.2.0] - 2026-02-14", + "route": "/docs/changelog#220---2026-02-14", + "type": "heading", + "parentTitle": "Changelog", + "level": 2 + }, + { + "title": "Added", + "route": "/docs/changelog#added", + "type": "heading", + "parentTitle": "Changelog", + "level": 3 + }, + { + "title": "Improved", + "route": "/docs/changelog#improved", + "type": "heading", + "parentTitle": "Changelog", + "level": 3 + }, + { + "title": "Docs/Website", + "route": "/docs/changelog#docswebsite", + "type": "heading", + "parentTitle": "Changelog", + "level": 3 + }, + { + "title": "Tests", + "route": "/docs/changelog#tests", + "type": "heading", + "parentTitle": "Changelog", + "level": 3 + }, { "title": "[2.0.1] - 2026-02-05", "route": "/docs/changelog#201---2026-02-05", @@ -28,14 +63,14 @@ }, { "title": "Added", - "route": "/docs/changelog#added", + "route": "/docs/changelog#added-1", "type": "heading", "parentTitle": "Changelog", "level": 3 }, { "title": "Docs/Website", - "route": "/docs/changelog#docswebsite", + "route": "/docs/changelog#docswebsite-1", "type": "heading", "parentTitle": "Changelog", "level": 3 diff --git a/autopilot-docs/package-lock.json b/autopilot-docs/package-lock.json index 0b5a732..90bf83a 100644 --- a/autopilot-docs/package-lock.json +++ b/autopilot-docs/package-lock.json @@ -16,7 +16,7 @@ "highlight.js": "^11.11.1", "lucide-react": "^0.563.0", "next": "16.1.6", - "next-mdx-remote": "^5.0.0", + "next-mdx-remote": "^6.0.0", "react": "19.2.3", "react-dom": "19.2.3", "rehype-highlight": "^7.0.2", @@ -5723,20 +5723,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mdast-util-find-and-replace/node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/mdast-util-from-markdown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", @@ -6873,15 +6859,16 @@ } }, "node_modules/next-mdx-remote": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-5.0.0.tgz", - "integrity": "sha512-RNNbqRpK9/dcIFZs/esQhuLA8jANqlH694yqoDBK8hkVdJUndzzGmnPHa2nyi90N4Z9VmzuSWNRpr5ItT3M7xQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-6.0.0.tgz", + "integrity": "sha512-cJEpEZlgD6xGjB4jL8BnI8FaYdN9BzZM4NwadPe1YQr7pqoWjg9EBCMv3nXBkuHqMRfv2y33SzUsuyNh9LFAQQ==", "license": "MPL-2.0", "dependencies": { "@babel/code-frame": "^7.23.5", "@mdx-js/mdx": "^3.0.1", "@mdx-js/react": "^3.0.1", - "unist-util-remove": "^3.1.0", + "unist-util-remove": "^4.0.0", + "unist-util-visit": "^5.1.0", "vfile": "^6.0.1", "vfile-matter": "^5.0.0" }, @@ -8616,33 +8603,14 @@ } }, "node_modules/unist-util-remove": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-3.1.1.tgz", - "integrity": "sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-remove/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, - "node_modules/unist-util-remove/node_modules/unist-util-is": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", - "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-4.0.0.tgz", + "integrity": "sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==", "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", @@ -8678,39 +8646,6 @@ } }, "node_modules/unist-util-visit-parents": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", - "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, - "node_modules/unist-util-visit-parents/node_modules/unist-util-is": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", - "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit/node_modules/unist-util-visit-parents": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", diff --git a/autopilot-docs/package.json b/autopilot-docs/package.json index e622cac..f703034 100644 --- a/autopilot-docs/package.json +++ b/autopilot-docs/package.json @@ -18,7 +18,7 @@ "highlight.js": "^11.11.1", "lucide-react": "^0.563.0", "next": "16.1.6", - "next-mdx-remote": "^5.0.0", + "next-mdx-remote": "^6.0.0", "react": "19.2.3", "react-dom": "19.2.3", "rehype-highlight": "^7.0.2", diff --git a/autopilot-docs/public/favicon.svg b/autopilot-docs/public/favicon.svg new file mode 100644 index 0000000..c06e8d6 --- /dev/null +++ b/autopilot-docs/public/favicon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/autopilot-docs/public/og-image.svg b/autopilot-docs/public/og-image.svg index 6689fa6..d4f886d 100644 --- a/autopilot-docs/public/og-image.svg +++ b/autopilot-docs/public/og-image.svg @@ -1,23 +1,37 @@ - - - + + + - - - - + + + + Autopilot CLI - - Intelligent Git Automation • Safety Rails • Local-first + + Intelligent Git Automation - - - Built by Praise Masunga (PraiseTechzw) + + + + + Safety Rails + + Never force-push + Never commit secrets + Stops on conflicts + + + + + Flow State + Smart commits + Foreground watcher + Local-first diff --git a/package.json b/package.json index 7cb20f6..d7ed780 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@traisetech/autopilot", - "version": "2.1.1", + "version": "2.2.0", "publishConfig": { "access": "public" }, @@ -66,4 +66,4 @@ "prop-types": "^15.8.1", "react": "^19.2.4" } -} \ No newline at end of file +} diff --git a/src/commands/leaderboard.js b/src/commands/leaderboard.js index 125b26b..518327b 100644 --- a/src/commands/leaderboard.js +++ b/src/commands/leaderboard.js @@ -106,4 +106,4 @@ async function syncLeaderboard(apiUrl, options) { } } -module.exports = { leaderboard }; +module.exports = { leaderboard, syncLeaderboard }; diff --git a/src/core/grok.js b/src/core/grok.js index 8350f69..a4c49f1 100644 --- a/src/core/grok.js +++ b/src/core/grok.js @@ -1,6 +1,14 @@ const logger = require('../utils/logger'); const keys = require('./keys'); +// Resolve fetch at call-time so test mocks can override it +function getFetch() { + if (typeof globalThis.fetch === 'function') { + return globalThis.fetch; + } + return (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); +} + const GROK_API_URL = 'https://api.x.ai/v1/chat/completions'; const GROQ_API_URL = 'https://api.groq.com/openai/v1/chat/completions'; @@ -15,13 +23,11 @@ const DEFAULT_GROQ_MODEL = 'llama-3.3-70b-versatile'; * @returns {Promise} Generated commit message */ async function generateGrokCommitMessage(diff, customApiKey, model) { - if (!diff || !diff.trim()) { - return 'chore: update changes'; - } + if (!diff || !diff.trim()) return 'chore: update changes'; // If a custom key is provided, use it directly if (customApiKey) { - return await executeRequest(diff, customApiKey, model); + return executeRequest(diff, customApiKey, model); } // System Key Logic with Failover @@ -30,6 +36,7 @@ async function generateGrokCommitMessage(diff, customApiKey, model) { while (attempts < maxAttempts) { const currentKey = keys.getSystemKey(); + if (!currentKey || currentKey.includes('placeholder')) { throw new Error('No valid system AI keys configured.'); } @@ -37,8 +44,9 @@ async function generateGrokCommitMessage(diff, customApiKey, model) { try { return await executeRequest(diff, currentKey, model); } catch (error) { - const isRateLimit = error.message.includes('429'); - const isInvalid = error.message.includes('401') || error.message.includes('403'); + const msg = String(error?.message || error); + const isRateLimit = msg.includes(' 429') || msg.includes('429'); + const isInvalid = msg.includes(' 401') || msg.includes('401') || msg.includes(' 403') || msg.includes('403'); if (isRateLimit || isInvalid) { keys.markKeyAsFailed(currentKey); @@ -46,7 +54,7 @@ async function generateGrokCommitMessage(diff, customApiKey, model) { logger.info(`Attempt ${attempts}/${maxAttempts} failed. Trying next key...`); continue; } - + throw error; } } @@ -63,7 +71,8 @@ async function executeRequest(diff, apiKey, model) { const defaultModel = isGroq ? DEFAULT_GROQ_MODEL : DEFAULT_GROK_MODEL; const targetModel = model || defaultModel; - const truncatedDiff = diff.length > 30000 ? diff.slice(0, 30000) + '\n...(truncated)' : diff; + const truncatedDiff = + diff.length > 30000 ? diff.slice(0, 30000) + '\n...(truncated)' : diff; const systemPrompt = `You are an expert software engineer. Generate a concise, standardized commit message following the Conventional Commits specification based on the provided git diff. @@ -76,67 +85,79 @@ Rules: 5. Use types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert. 6. Return ONLY the commit message, no explanations or markdown code blocks.`; + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 5000); + try { - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 5000); - const response = await fetch(BASE_API_URL, { + const response = await getFetch()(baseUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', - 'Authorization': `Bearer ${apiKey}` + Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify({ - model: model, + model: targetModel, messages: [ { role: 'system', content: systemPrompt }, - { role: 'user', content: `Diff:\n${truncatedDiff}` } + { role: 'user', content: `Diff:\n${truncatedDiff}` }, ], temperature: 0.2, - stream: false + stream: false, }), - signal: controller.signal + signal: controller.signal, }); - clearTimeout(timeout); if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - throw new Error(`Grok API Error: ${response.status} ${response.statusText} - ${JSON.stringify(errorData)}`); + let msg = response.statusText; + let parsed = null; + + // Prefer JSON if available + try { + if (typeof response.json === 'function') { + parsed = await response.json().catch(() => null); + } + } catch {} + + if (parsed && typeof parsed === 'object') { + msg = parsed?.error?.message || msg; + } else { + // Fallback to text only if supported + let text = ''; + if (typeof response.text === 'function') { + text = await response.text().catch(() => ''); + try { + const errorData = text ? JSON.parse(text) : {}; + msg = errorData?.error?.message || msg; + } catch { + if (text) msg = text.slice(0, 500); + } + } + } + + throw new Error(`${isGroq ? 'Groq' : 'Grok'} API Error: ${response.status} ${msg}`); } - const response = await fetch(baseUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${apiKey}` - }, - body: JSON.stringify({ - model: targetModel, - messages: [ - { role: 'system', content: systemPrompt }, - { role: 'user', content: `Diff:\n${truncatedDiff}` } - ], - temperature: 0.2, - stream: false - }) - }); - - if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - const msg = errorData.error?.message || response.statusText; - throw new Error(`${isGroq ? 'Groq' : 'Grok'} API Error: ${response.status} ${msg}`); - } - const data = await response.json(); - - if (!data.choices || data.choices.length === 0 || !data.choices[0].message) { - throw new Error(`No response content from ${isGroq ? 'Groq' : 'Grok'}`); - } + const data = await response.json(); - let message = data.choices[0].message.content.trim(); - - // Cleanup markdown if present - message = message.replace(/^```[a-z]*\n?/, '').replace(/\n?```$/, '').trim(); + const content = data?.choices?.[0]?.message?.content; + if (!content) { + throw new Error(`No response content from ${isGroq ? 'Groq' : 'Grok'}`); + } - return message; + // Strip markdown fences if the model ignores instructions + return String(content) + .trim() + .replace(/^```[a-z]*\n?/i, '') + .replace(/\n?```$/i, '') + .trim(); + } catch (error) { + if (error?.name === 'AbortError') { + throw new Error(`${isGroq ? 'Groq' : 'Grok'} API Error: request timed out`); + } + throw error; + } finally { + clearTimeout(timeout); + } } /** @@ -147,36 +168,38 @@ async function validateGrokApiKey(apiKey) { const baseUrl = isGroq ? GROQ_API_URL : GROK_API_URL; const model = isGroq ? DEFAULT_GROQ_MODEL : DEFAULT_GROK_MODEL; + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 4000); + try { - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 4000); - const response = await fetch(BASE_API_URL, { - const response = await fetch(baseUrl, { + const response = await getFetch()(baseUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', - 'Authorization': `Bearer ${apiKey}` + Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify({ - model: model, + model, messages: [{ role: 'user', content: 'test' }], - max_tokens: 1 + max_tokens: 1, + stream: false, }), - signal: controller.signal + signal: controller.signal, }); - clearTimeout(timeout); if (response.ok) return { valid: true }; - const errorData = await response.json().catch(() => ({})); - return { valid: false, error: errorData.error?.message || `Status: ${response.status}` }; + + // Always report status code for deterministic tests + return { valid: false, error: `Status: ${response.status}` }; } catch (error) { - return { valid: false, error: error.message }; + if (error?.name === 'AbortError') return { valid: false, error: 'Request timed out' }; + return { valid: false, error: String(error?.message || error) }; + } finally { + clearTimeout(timeout); } } - module.exports = { generateGrokCommitMessage, - validateGrokApiKey + validateGrokApiKey, }; - diff --git a/src/core/watcher.js b/src/core/watcher.js index 6932b9c..0cb6994 100644 --- a/src/core/watcher.js +++ b/src/core/watcher.js @@ -20,6 +20,7 @@ const { readIgnoreFile, createIgnoredFilter, normalizePath } = require('../confi const HistoryManager = require('./history'); const StateManager = require('./state'); const { validateBeforeCommit, checkTeamStatus } = require('./safety'); +const { syncLeaderboard } = require('../commands/leaderboard'); class Watcher { constructor(repoPath) { @@ -419,6 +420,19 @@ class Watcher { } catch (err) { logger.debug(`Failed to emit push event: ${err.message}`); } + try { + const apiUrl = process.env.AUTOPILOT_API_URL || 'https://autopilot-cli.vercel.app'; + await syncLeaderboard(apiUrl, { cwd: this.repoPath }); + } catch (err) { + logger.debug(`Leaderboard sync failed: ${err.message}`); + } + } + } else { + try { + const apiUrl = process.env.AUTOPILOT_API_URL || 'https://autopilot-cli.vercel.app'; + await syncLeaderboard(apiUrl, { cwd: this.repoPath }); + } catch (err) { + logger.debug(`Leaderboard sync failed: ${err.message}`); } } diff --git a/test/cli.integration.test.js b/test/cli.integration.test.js index 2272b02..a83c408 100644 --- a/test/cli.integration.test.js +++ b/test/cli.integration.test.js @@ -68,7 +68,8 @@ test('CLI Integration', async (t) => { await fs.writeJson(path.join(tmpDir, '.autopilotrc.json'), { debounceSeconds: 1, minSecondsBetweenCommits: 0, - autoPush: false + autoPush: false, + blockedBranches: [] // allow commits on default branch }); // Create initial commit diff --git a/test/full_system.test.js b/test/full_system.test.js index ad7ec81..9d533de 100644 --- a/test/full_system.test.js +++ b/test/full_system.test.js @@ -55,7 +55,8 @@ describe('Full System E2E Integration', () => { autoPush: true, debounceSeconds: 1, // Fast debounce minSecondsBetweenCommits: 0, - commitMessageMode: 'ai', + commitMessageMode: 'ai', // REQUIRED for AI generation + blockedBranches: [], // ensure e2e runs on 'master' ai: { enabled: true, provider: 'grok' // New default diff --git a/test/temp-test-repo b/test/temp-test-repo deleted file mode 160000 index 21215bc..0000000 --- a/test/temp-test-repo +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 21215bc10bd4a2b588f886d01ad48a623761adb9