{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "josh-sync configuration", "description": "Configuration for bidirectional monorepo ↔ subrepo sync via josh-proxy", "type": "object", "required": ["schema_version", "josh", "targets", "bot"], "properties": { "schema_version": { "type": "integer", "const": 2, "description": "Schema version. Required. Must be 2 for josh-sync v2.x configs." }, "josh": { "type": "object", "required": ["proxy_url", "monorepo_path", "monorepo_url"], "properties": { "proxy_url": { "type": "string", "description": "Josh-proxy URL (no trailing slash)", "pattern": "^https?://" }, "monorepo_path": { "type": "string", "description": "Repo path as josh-proxy sees it (org/repo)" }, "monorepo_url": { "type": "string", "description": "Monorepo git clone URL — git@host:org/repo.git (SSH) or https://host/org/repo.git. The gitea host is derived from this URL." }, "monorepo_auth": { "type": "string", "enum": ["https", "ssh"], "default": "https", "description": "Auth method for cloning the monorepo. SSH uses the user's ssh-agent / ~/.ssh/config; HTTPS injects ${SYNC_BOT_USER}:${SYNC_BOT_TOKEN} into the URL." } } }, "targets": { "type": "array", "minItems": 1, "items": { "type": "object", "required": ["name", "subfolder", "subrepo_url", "branches"], "properties": { "name": { "type": "string", "description": "Unique target identifier" }, "subfolder": { "type": "string", "description": "Monorepo subfolder path" }, "josh_filter": { "type": "string", "description": "Josh filter expression (auto-derived from subfolder if omitted)", "pattern": "^:" }, "subrepo_url": { "type": "string", "description": "External subrepo git URL (HTTPS or SSH)" }, "subrepo_auth": { "type": "string", "enum": ["https", "ssh"], "default": "https", "description": "Auth method for subrepo" }, "subrepo_token_var": { "type": "string", "description": "Env var name for per-target HTTPS token (default: SUBREPO_TOKEN)" }, "subrepo_ssh_key_var": { "type": "string", "description": "Env var name for per-target SSH key (default: SUBREPO_SSH_KEY)" }, "branches": { "type": "object", "description": "Branch mapping: mono_branch → subrepo_branch", "additionalProperties": { "type": "string" } }, "forward_only": { "type": "array", "items": { "type": "string" }, "default": [], "description": "Branches that only sync mono → subrepo (never reverse)" }, "exclude": { "type": "array", "items": { "type": "string" }, "default": [], "description": "File/directory patterns to exclude from sync via josh :exclude filter. Josh pattern syntax: 'dir/' for directories, '*.ext' for globs, '**/dir/' for nested matches. Patterns are embedded inline in the josh-proxy URL." }, "history_lock": { "type": "string", "enum": ["rewrite", "preserve"], "description": "Onboarding strategy override. 'preserve' selects the non-destructive adopt strategy (keeps subrepo history via an adoption merge); 'rewrite' selects the destructive reset strategy (force-pushes josh-filtered history). When omitted, `josh-sync onboard` auto-detects: subrepos with branches → adopt, empty subrepos → reset. The CLI flag `--mode={reset,adopt}` overrides this." } } } }, "bot": { "type": "object", "required": ["name", "email", "trailer"], "properties": { "name": { "type": "string", "description": "Git commit author name for sync commits" }, "email": { "type": "string", "description": "Git commit author email" }, "trailer": { "type": "string", "description": "Git trailer key for loop prevention" } } } } }