diff --git a/README.md b/README.md index 0ead0dcbf..eda46f450 100644 --- a/README.md +++ b/README.md @@ -115,9 +115,9 @@ Use the [guided setup](#install-ecc) or [native plugin commands](#claude-code-de SerpApi: Web Search API

-Past sponsors: Atlas Cloud +Past sponsors: Atlas Cloud · Mike Morgan (inactive) -Community sponsors: Mike Morgan · @jasonwu513 · @1anter · @massimotodaro · @meadmccabe +Community sponsors: @jasonwu513 · @1anter · @massimotodaro · @meadmccabe Become a Sponsor · Sponsor Tiers · Sponsorship Program diff --git a/SPONSORS.md b/SPONSORS.md index bb63534d6..ed332cba1 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -25,12 +25,12 @@ Run or self-host any open-source model. Itô partners with ECC on compute, while | Sponsor | Active period | |---------|---------------| | [**Atlas Cloud**](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=ECC) | 2026 | +| [Mike Morgan](https://github.com/mikejmorgan-ai) (inactive) | 2026 | ## Team Sponsors — $200/mo | Sponsor | Since | |---------|-------| -| [Mike Morgan](https://github.com/mikejmorgan-ai) | 2026 | *[Become a Team sponsor](https://github.com/sponsors/affaan-m) to be listed in SPONSORS.md.* diff --git a/docs/ATLAS-CLOUD-GUIDE.md b/docs/ATLAS-CLOUD-GUIDE.md index 83163c5b7..efefcfd7d 100644 --- a/docs/ATLAS-CLOUD-GUIDE.md +++ b/docs/ATLAS-CLOUD-GUIDE.md @@ -1,5 +1,7 @@ # Atlas Cloud — LLM Provider Guide +> Sponsor status: Atlas Cloud is a past sponsor. This status change leaves the documented integration unchanged. + [Atlas Cloud](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=everything-claude-code) is a full-modal AI inference platform providing an OpenAI-compatible API for 59+ LLM models, image generation, and video generation. > Run or self-host any open-source model instead of using a managed API. Itô is ECC's preferred compute sponsor: [open the Itô dashboard to sign in and rent or manage GPUs](https://compute.itomarkets.com). Any GPU provider works. That sponsorship link is passive: it does not invoke an RFQ, reserve capacity, provision compute, or configure serving. Separately, the opt-in `ecc ito find` bridge invokes the explicitly configured canonical Itô CLI and submits a live authenticated RFQ; it does not reserve capacity. Managed inference through Itô is not live yet. diff --git a/docs/es/SPONSORS.md b/docs/es/SPONSORS.md index 54a9e0acc..51f2f4bbd 100644 --- a/docs/es/SPONSORS.md +++ b/docs/es/SPONSORS.md @@ -18,10 +18,15 @@ Gracias a todos los que financian el trabajo de código abierto de ECC. Tu patro | Patrocinador | Desde | |---------|-------| -| [Mike Morgan](https://github.com/mikejmorgan-ai) | 2026 | *[Conviértete en patrocinador Team](https://github.com/sponsors/affaan-m) para obtener un logo pequeño y 5 asientos de ECC Pro.* +## Patrocinadores anteriores + +| Patrocinador | Período activo | +|---------|---------------| +| [Mike Morgan](https://github.com/mikejmorgan-ai) (inactivo) | 2026 | + ## Patrocinadores Pro — $50/mes *[Conviértete en patrocinador Pro](https://github.com/sponsors/affaan-m) para aparecer aquí con tu nombre en la fila de patrocinadores del README principal.* diff --git a/docs/uk-UA/README.md b/docs/uk-UA/README.md index 2264fd591..f76959dc6 100644 --- a/docs/uk-UA/README.md +++ b/docs/uk-UA/README.md @@ -104,13 +104,13 @@

CodeRabbit    Greptile    - Atlas Cloud    Moonshot AI - Kimi    Itô Markets    SerpApi: Web Search API

-Спонсори спільноти: Mike Morgan · @jasonwu513 · @1anter · @massimotodaro · @meadmccabe +Спонсори спільноти: @jasonwu513 · @1anter · @massimotodaro · @meadmccabe +Минулі спонсори: Atlas Cloud · Mike Morgan (неактивний) Стати спонсором · Рівні спонсорства · Програма спонсорства @@ -737,6 +737,7 @@ ECC також постачає розширені керовані адапте - **Ціль встановлення Kimi Code** (`--target kimi`): ECC встановлюється нативно в Kimi Code CLI від [Moonshot AI](https://www.moonshot.ai) - **Самостійний хостинг на GPU**: перевірений шлях з [Itô](https://compute.itomarkets.com), бажаним обчислювальним спонсором ECC, включно з опційним мостом RFQ `ecc ito find` (деталі та розкриття вище в опціях встановлення) - **Moonshot AI (Kimi), Itô та Atlas Cloud** тепер публічні спонсори +- **Поточний статус спонсорства:** Atlas Cloud є минулим спонсором. Оголошення вище збережено як історичний запис випуску 2.1. - **Цілі встановлення Hermes + OpenClaw**, посібник з навігації Codex, консолідовані хуки PostToolUse та зміцнення ланцюжка поставок ### Поточна розробка: Уніфікованe сховище пам'яті diff --git a/tests/scripts/ito-compute-sponsor.test.js b/tests/scripts/ito-compute-sponsor.test.js index 2210a11c6..96db621c0 100644 --- a/tests/scripts/ito-compute-sponsor.test.js +++ b/tests/scripts/ito-compute-sponsor.test.js @@ -114,6 +114,211 @@ function extractNamedTable(content, ariaLabel) { return match[1]; } +const README_SPONSOR_LABELS = { + "en": { + "active": "Partners and sponsors", + "community": "Community sponsors:", + "past": "Past sponsors:", + "inactive": "inactive" + }, + "uk": { + "active": "\u041f\u0430\u0440\u0442\u043d\u0435\u0440\u0438 \u0442\u0430 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0438", + "community": "\u0421\u043f\u043e\u043d\u0441\u043e\u0440\u0438 \u0441\u043f\u0456\u043b\u044c\u043d\u043e\u0442\u0438:", + "past": "\u041c\u0438\u043d\u0443\u043b\u0456 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0438:", + "inactive": "\u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0439" + } +}; + +const CURRENT_SPONSOR_TIERS = [ + 'Strategic Sponsors', 'Business Sponsors', 'Team Sponsors', + 'Pro Sponsors', 'Builder Sponsors', 'Supporters', +]; +const SPANISH_SPONSOR_TIERS = [ + 'Patrocinadores Empresariales', 'Patrocinadores Business', 'Patrocinadores Team', + 'Patrocinadores Pro', 'Patrocinadores Builder', 'Supporters', +]; +const FORMER_SPONSOR_PATTERN = /Atlas Cloud|atlascloud|Mike Morgan|mikejmorgan-ai/i; +const ATLAS_STATUS_NOTE = '> Sponsor status: Atlas Cloud is a past sponsor. This status change leaves the documented integration unchanged.'; +const ATLAS_GUIDE_HEADING = '# Atlas Cloud \u2014 LLM Provider Guide'; +const MIKE_LINK = '[Mike Morgan](https://github.com/mikejmorgan-ai)'; + +function requiredRegion(content, opening, closing) { + assert.strictEqual(content.split(opening).length - 1, 1, `Expected one opening: ${opening}`); + const start = content.indexOf(opening); + const end = content.indexOf(closing, start + opening.length); + assert.ok(end > start, `Missing or reversed closing: ${closing}`); + const body = content.slice(start + opening.length, end); + assert.doesNotMatch(body, /`, '

'); + const community = requiredRegion(content, `${labels.community}`, ''); + const past = requiredRegion(content, `${labels.past}`, ''); + assert.ok(active.end < community.start && active.end < past.start, 'Current logo region must precede sponsor rows'); + assert.doesNotMatch(active.body, FORMER_SPONSOR_PATTERN); + assert.doesNotMatch(community.body, FORMER_SPONSOR_PATTERN); + for (const current of ['CodeRabbit', 'Greptile', 'Moonshot', 'compute.itomarkets.com', 'SerpApi']) { + assert.ok(active.body.includes(current), `Missing current sponsor ${current}`); + } + for (const current of ['jasonwu513', '1anter', 'massimotodaro', 'meadmccabe']) { + assert.ok(community.body.includes(`https://github.com/${current}`), `Missing community sponsor ${current}`); + } + assertPastSponsorEntries(past.body, labels.inactive, true); +} + +function assertSponsorRoster(content, spanish = false) { + const headings = [...content.matchAll(/^## (.+)$/gm)]; + const sections = headings.map((heading, index) => ({ + title: heading[1], + body: content.slice(heading.index + heading[0].length, headings[index + 1]?.index ?? content.length), + })); + const pastTitle = spanish ? 'Patrocinadores anteriores' : 'Past Sponsors'; + const past = sections.filter(section => section.title === pastTitle); + assert.strictEqual(past.length, 1, 'Expected exactly one past sponsor section'); + const tiers = spanish ? SPANISH_SPONSOR_TIERS : CURRENT_SPONSOR_TIERS; + for (const tier of tiers) { + const matches = sections.filter(section => section.title === tier || section.title.startsWith(`${tier} \u2014 `)); + assert.strictEqual(matches.length, 1, `Expected one current tier ${tier}`); + assert.doesNotMatch(matches[0].body, FORMER_SPONSOR_PATTERN, `Former sponsor remains in ${tier}`); + } + assertPastSponsorEntries(past[0].body, spanish ? 'inactivo' : 'inactive', !spanish); + if (spanish) assert.doesNotMatch(content, /Atlas Cloud|atlascloud/i); + else { + const business = sections.find(section => section.title === 'Business Sponsors').body; + for (const current of ['CodeRabbit', 'Greptile', 'Moonshot', 'compute.itomarkets.com', 'SerpApi']) { + assert.ok(business.includes(current), `Missing current Business sponsor ${current}`); + } + } +} + +function assertAtlasStatusPlacement(content) { + assert.ok(content.startsWith(`${ATLAS_GUIDE_HEADING}\n\n${ATLAS_STATUS_NOTE}\n\n`), 'Status note must immediately follow H1 and one blank line'); +} + +function readmeSponsorFixture(locale) { + const labels = README_SPONSOR_LABELS[locale]; + const active = `

CodeRabbit Greptile Moonshot compute.itomarkets.com SerpApi

`; + const past = `${labels.past} Atlas Cloud Mike Morgan (${labels.inactive})`; + const community = `${labels.community} ${['jasonwu513', '1anter', 'massimotodaro', 'meadmccabe'].map(name => `${name}`).join(' ')}`; + return [active, past, community].join('\n\n'); +} + +function sponsorRosterFixture(spanish = false) { + const tiers = spanish ? SPANISH_SPONSOR_TIERS : CURRENT_SPONSOR_TIERS; + const sections = tiers.map(tier => `## ${tier}\n\n${tier === 'Business Sponsors' ? 'CodeRabbit Greptile Moonshot compute.itomarkets.com SerpApi' : 'Current entries'}\n`); + const past = spanish + ? `## Patrocinadores anteriores\n\n${MIKE_LINK} (inactivo) | 2026\n` + : `## Past Sponsors\n\n[Atlas Cloud](https://www.atlascloud.ai/) | 2026\n${MIKE_LINK} (inactive) | 2026\n`; + sections.splice(2, 0, past); // Current Team and later tiers occur after Past. + return sections.join('\n'); +} + +function sponsorDocsTests() { + const tests = [ + ['English README keeps former sponsors out of both current regions', () => assertReadmeSponsorStatus(read('README.md'), 'en')], + ['Ukrainian README keeps former sponsors out of both current regions', () => assertReadmeSponsorStatus(read('docs/uk-UA/README.md'), 'uk')], + ['canonical roster separates past entries from every current tier', () => assertSponsorRoster(read('SPONSORS.md'))], + ['Spanish roster moves only inactive Mike out of current tiers', () => assertSponsorRoster(read('docs/es/SPONSORS.md'), true)], + ['Atlas status note immediately follows the guide heading', () => assertAtlasStatusPlacement(read('docs/ATLAS-CLOUD-GUIDE.md'))], + ]; + for (const locale of ['en', 'uk']) { + const fixture = readmeSponsorFixture(locale); + const labels = README_SPONSOR_LABELS[locale]; + const start = `

`; + const community = `${labels.community}`; + const past = `${labels.past}`; + tests.push([`${locale} fixture allows past before or after community`, () => { + assertReadmeSponsorStatus(fixture, locale); + const [active, pastRow, communityRow] = fixture.split('\n\n'); + assertReadmeSponsorStatus([active, communityRow, pastRow].join('\n\n'), locale); + }]); + const mutations = [ + ['missing active marker', fixture.replace(start, '

')], + ['missing closing marker', fixture.replace('

', '')], + ['reversed closing marker', `

${fixture.replace('

', '')}`], + ['duplicate active marker', `${fixture}\n${start}Extra

`], + ['duplicate community marker', `${fixture}\n${community}Extra`], + ['duplicate past marker', `${fixture}\n${past}Extra`], + ['missing community marker', fixture.replace(community, '')], + ['missing past marker', fixture.replace(past, '')], + ['Atlas in current logos', fixture.replace(start, `${start}Atlas Cloud `)], + ['Mike in current logos', fixture.replace(start, `${start}mikejmorgan-ai `)], + ['Mike in current community', fixture.replace(community, `${community}Mike Morgan `)], + ['Atlas in current community', fixture.replace(community, `${community}atlascloud `)], + ['missing past Mike', fixture.replace('Mike Morgan', 'Former sponsor')], + ['missing past status', fixture.replace(` (${labels.inactive})`, '')], + ['missing past Atlas', fixture.replace('Atlas Cloud', 'Former organization')], + ['past before active closes', fixture.replace('

', '').replace(past, `${past}

`)], + ]; + for (const [name, mutated] of mutations) { + tests.push([`${locale} sponsor checker rejects ${name}`, () => { + assertReadmeSponsorStatus(fixture, locale); + assert.notStrictEqual(mutated, fixture); + assert.throws(() => assertReadmeSponsorStatus(mutated, locale)); + }]); + } + } + for (const spanish of [false, true]) { + const locale = spanish ? 'es' : 'en'; + const fixture = sponsorRosterFixture(spanish); + const tiers = spanish ? SPANISH_SPONSOR_TIERS : CURRENT_SPONSOR_TIERS; + const past = spanish ? 'Patrocinadores anteriores' : 'Past Sponsors'; + tests.push([`${locale} roster fixture accepts current tiers on both sides of Past`, () => assertSponsorRoster(fixture, spanish)]); + for (const tier of tiers) { + for (const identity of ['Atlas Cloud', 'mikejmorgan-ai']) { + tests.push([`${locale} roster rejects ${identity} in ${tier}`, () => { + assertSponsorRoster(fixture, spanish); + const mutated = fixture.replace(`## ${tier}\n`, `## ${tier}\n${identity}\n`); + assert.notStrictEqual(mutated, fixture); + assert.throws(() => assertSponsorRoster(mutated, spanish)); + }]); + } + } + for (const [name, mutated] of [ + ['missing past section', fixture.replace(`## ${past}`, '## Archive')], + ['duplicate past section', `${fixture}\n## ${past}\n`], + ['missing current tier', fixture.replace(`## ${tiers[2]}`, '## Other')], + ['duplicate current tier', `${fixture}\n## ${tiers[2]}\n`], + ['missing past Mike', fixture.replace('Mike Morgan', 'Former sponsor')], + ['missing inactive status', fixture.replace(spanish ? '(inactivo)' : '(inactive)', '')], + ]) { + tests.push([`${locale} roster checker rejects ${name}`, () => { + assertSponsorRoster(fixture, spanish); + assert.notStrictEqual(mutated, fixture); + assert.throws(() => assertSponsorRoster(mutated, spanish)); + }]); + } + } + const guide = `${ATLAS_GUIDE_HEADING}\n\n${ATLAS_STATUS_NOTE}\n\nProvider documentation.\n`; + tests.push(['guide fixture accepts the immediate undated status note', () => assertAtlasStatusPlacement(guide)]); + for (const [name, mutated] of [ + ['content between heading and note', guide.replace(`\n\n${ATLAS_STATUS_NOTE}`, `\n\nUnrelated content.\n\n${ATLAS_STATUS_NOTE}`)], + ['note after provider description', `${ATLAS_GUIDE_HEADING}\n\nProvider documentation.\n\n${ATLAS_STATUS_NOTE}\n\n`], + ['missing heading', guide.replace(ATLAS_GUIDE_HEADING, '')], + ['unsupported dated note', guide.replace('Sponsor status:', 'Sponsor status (2026-09-10):')], + ]) { + tests.push([`guide checker rejects ${name}`, () => { + assertAtlasStatusPlacement(guide); + assert.throws(() => assertAtlasStatusPlacement(mutated)); + }]); + } + return tests; +} + function main() { console.log('\n=== Testing Ito compute-sponsor surface ===\n'); @@ -459,7 +664,12 @@ function main() { }], ]; - for (const [name, fn] of tests) { + const docsOnly = process.argv.includes('--sponsor-docs-only'); + const docsTests = sponsorDocsTests(); + const selectedTests = docsOnly ? docsTests : [...tests, ...docsTests]; + if (docsOnly) console.log(`Sponsor docs only: ${docsTests.length} pure cases; ${tests.length} unrelated callbacks omitted.`); + + for (const [name, fn] of selectedTests) { if (runTest(name, fn)) { passed += 1; } else {