From 4b2dc76a04de3479cd8fa5b5ed8a00a8c9c673ef Mon Sep 17 00:00:00 2001 From: Operator & Codex Date: Wed, 6 May 2026 10:54:27 +0200 Subject: [PATCH] Add git domain to explanation grounder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Build: pass | Tests: pass — 40 passed (3 files) --- Build: pass | Tests: pass — 2191 passed (648 files) --- src/explanation-grounder.test.ts | 42 +++++++++++++++-- src/explanation-grounder.ts | 77 +++++++++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/src/explanation-grounder.test.ts b/src/explanation-grounder.test.ts index 4de0ee3..98d65be 100644 --- a/src/explanation-grounder.test.ts +++ b/src/explanation-grounder.test.ts @@ -1,6 +1,12 @@ import { describe, expect, it } from 'vitest'; -import { DB_RUNTIME, SUBNET_BASE } from './config.js'; +import { + CODE_HOSTING_MODE, + DB_RUNTIME, + GIT_JAIL_NAME, + GIT_LOCAL_URL, + SUBNET_BASE, +} from './config.js'; import { buildExplanationGrounding, detectExplanationDomains, @@ -19,10 +25,16 @@ describe('detectExplanationDomains', () => { expect( detectExplanationDomains('explain the db jail layout in this project'), ).toEqual(['jails']); + expect( + detectExplanationDomains('how does git work in this project'), + ).toEqual(['git']); + expect( + detectExplanationDomains('explain the Forgejo setup here'), + ).toEqual(['git']); }); it('falls through when no explanation domain matches yet', () => { - expect(detectExplanationDomains('how does git work')).toEqual([]); + expect(detectExplanationDomains('restart nginx')).toEqual([]); }); }); @@ -47,8 +59,32 @@ describe('buildExplanationGrounding', () => { expect(context).toContain('controlplane runs on the host as part of the main service'); }); + it('builds a git grounding pack from runtime facts and canonical sources', async () => { + const context = await buildExplanationGrounding( + 'how does git work in this project', + ); + + expect(context).toContain('Domain: git'); + expect(context).toContain(`CODE_HOSTING_MODE=${CODE_HOSTING_MODE}`); + expect(context).toContain(`git jail name: ${GIT_JAIL_NAME}`); + expect(context).toContain(`configured local git URL: ${GIT_LOCAL_URL}`); + expect(context).toContain('Prefer Forgejo over older Gitea wording'); + expect(context).toContain( + 'Do not say this install is in gitea/Forgejo mode unless CODE_HOSTING_MODE explicitly says so', + ); + expect(context).toContain( + 'Treat GIT_LOCAL_URL as the configured local workflow URL, not proof that this checkout already has that remote added.', + ); + expect(context).toContain('setup/git.ts'); + expect(context).toContain('docs/public/operate/git-storage.md'); + expect(context).toContain( + 'docs/public/architecture/freebsd-jail-implementation.md', + ); + expect(context).toContain('Git Service today uses Forgejo as the shared git web/API implementation'); + }); + it('returns empty when no registered explanation domain matches', async () => { - await expect(buildExplanationGrounding('how does git work')).resolves.toBe( + await expect(buildExplanationGrounding('restart nginx')).resolves.toBe( '', ); }); diff --git a/src/explanation-grounder.ts b/src/explanation-grounder.ts index 06d589d..e7d8352 100644 --- a/src/explanation-grounder.ts +++ b/src/explanation-grounder.ts @@ -2,7 +2,23 @@ import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; -import { DB_RUNTIME, RUNTIME_ID, SUBNET_BASE } from './config.js'; +import { + CODE_HOSTING_MODE, + CODE_SERVICE_INTERNAL_DOMAIN, + DB_RUNTIME, + FEATURE_GIT, + FEATURE_GITEA, + FORGEJO_DB_NAME, + GIT_DEFAULT_REPO_NAME, + GIT_JAIL_IP, + GIT_JAIL_NAME, + GIT_LOCAL_URL, + GIT_MIRROR_URLS, + GIT_STORAGE_ROOT, + REMOTE_GIT_URL, + RUNTIME_ID, + SUBNET_BASE, +} from './config.js'; import { getJailIp, getJailRegistry } from './jail-registry.js'; import { SERVICE_NAME } from './platform-identity.js'; import { isExplanationPrompt } from './report-intent.js'; @@ -99,6 +115,65 @@ const EXPLANATION_DOMAINS = { }, ], }, + git: { + aliases: [ + /\bgit\b/i, + /\bforgejo\b/i, + /\bcode\s+service\b/i, + /\brepo\b/i, + /\brepos\b/i, + /\bmirror\b/i, + /\bmirrors\b/i, + /\bremote\b/i, + ], + buildRuntimeFacts: () => [ + `- CODE_HOSTING_MODE=${CODE_HOSTING_MODE}`, + `- FEATURE_GIT=${FEATURE_GIT ? 'YES' : 'NO'}`, + `- FEATURE_GITEA=${FEATURE_GITEA ? 'YES' : 'NO'}`, + `- DB_RUNTIME=${DB_RUNTIME}`, + `- git jail name: ${GIT_JAIL_NAME}`, + `- git jail IP: ${GIT_JAIL_IP}`, + `- git hostname: ${CODE_SERVICE_INTERNAL_DOMAIN}`, + `- repo root inside jail: ${GIT_STORAGE_ROOT}`, + `- default repo name: ${GIT_DEFAULT_REPO_NAME}`, + `- primary upstream remote: ${REMOTE_GIT_URL}`, + `- configured local git URL: ${GIT_LOCAL_URL || '(unset)'}`, + `- extra mirror remotes: ${GIT_MIRROR_URLS.length > 0 ? GIT_MIRROR_URLS.join(', ') : '(none)'}`, + `- Forgejo database name: ${FORGEJO_DB_NAME}`, + '- Git Service is a shared platform service; root installs use system_git unless explicitly overridden', + ], + instructions: [ + 'Prefer Forgejo over older Gitea wording when describing the current shared git web/API implementation.', + 'Distinguish plain git storage in the git jail from the optional Forgejo application layer.', + 'Do not say this install is in gitea/Forgejo mode unless CODE_HOSTING_MODE explicitly says so; FEATURE_GITEA=YES only means the optional Forgejo layer is enabled in config.', + 'Treat GIT_LOCAL_URL as the configured local workflow URL, not proof that this checkout already has that remote added.', + 'If DB_RUNTIME=host, say Forgejo would use host PostgreSQL rather than implying a separate db jail or Data Service is live.', + ], + sources: [ + { + label: 'setup/git.ts', + loader: () => + extractMarkdownSection( + 'setup/git.ts', + '/**', + 'function repoNameFromRemote', + ), + }, + { + label: 'docs/public/operate/git-storage.md', + loader: () => readRepoFile('docs/public/operate/git-storage.md'), + }, + { + label: 'docs/public/architecture/freebsd-jail-implementation.md', + loader: () => + extractMarkdownSection( + 'docs/public/architecture/freebsd-jail-implementation.md', + '### `git`', + '### `cms`', + ), + }, + ], + }, } satisfies Record; type ExplanationDomainKey = keyof typeof EXPLANATION_DOMAINS;