@theholocron/cli 3.34.5 → 3.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capabilities/index.d.mts +31 -1
- package/dist/cli.mjs +239 -99
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/package.json +3 -3
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["getKeyringToken","defaultImporter","SKIP_DIRS","defaultWalkFiles","preflight","defaultExec","defaultExec","printNextSteps","deriveDefaults","render","render","render","render","render","render","render","render","render","render","render","render","render","render","render","render","render","renderPackageJson","renderTsconfigJson","renderVitestConfig","renderEslintConfig","renderTsdownConfig","renderReadme","renderAuth","renderRest","renderVerifyToken","renderPluginIndex","renderCapability","renderHelpers","renderAuthTest","renderRestTest","renderVerifyTokenTest","renderCapabilityTest","renderIndexTest","renderValidateScript","deriveDefaults","defaultExec","lintYml","testYml","typecheckYml","codeqlYml","reviewYml","postReleaseYml","releaseYml","staleYml","syncYml","greetingsYml","dependenciesYml","bookkeepingYml","auditYml","deployYml","ProviderApiError","DEPENDABOT_CONFIG","autoCommitAction","installAction","setupAction","setupNodeAction","auditWorkflow","bookkeepingWorkflow","codeqlWorkflow","dependenciesWorkflow","deployWorkflow","cleanupPreviewWorkflow","deployPreviewWorkflow","greetingsWorkflow","lintWorkflow","postReleaseWorkflow","releaseWorkflow","reviewWorkflow","staleWorkflow","syncBroadcastWorkflow","tagWorkflow","syncGithubWorkflow","syncWorkflow","testWorkflow","typecheckWorkflow"],"sources":["../src/env.ts","../src/keyring.ts","../src/auth-resolver.ts","../src/capabilities/index.ts","../src/config.ts","../src/ui/progress.ts","../src/ui/style.ts","../src/commands/auth.ts","../src/commands/clone.ts","../src/loader.ts","../src/commands/deploy.ts","../src/commands/doctor.ts","../src/commands/new.ts","../src/commands/npm-bump-versions.ts","../src/commands/npm-publish-initial.ts","../src/commands/plugin-create/template-inputs.ts","../src/commands/plugin-create/templates/auth.ts","../src/commands/plugin-create/templates/auth-test.ts","../src/commands/plugin-create/templates/capability.ts","../src/commands/plugin-create/templates/capability-test.ts","../src/commands/plugin-create/templates/eslint-config.ts","../src/commands/plugin-create/templates/helpers.ts","../src/commands/plugin-create/templates/index-test.ts","../src/commands/plugin-create/templates/package-json.ts","../src/commands/plugin-create/templates/plugin-index.ts","../src/commands/plugin-create/templates/readme.ts","../src/commands/plugin-create/templates/rest.ts","../src/commands/plugin-create/templates/rest-test.ts","../src/commands/plugin-create/templates/tsconfig-json.ts","../src/commands/plugin-create/templates/tsdown-config.ts","../src/commands/plugin-create/templates/validate-script.ts","../src/commands/plugin-create/templates/verify-token.ts","../src/commands/plugin-create/templates/verify-token-test.ts","../src/commands/plugin-create/templates/vitest-config.ts","../src/commands/plugin-create/index.ts","../src/commands/secret-set.ts","../src/commands/secrets-sync.ts","../src/commands/dependabot.yml","../src/commands/workflows/audit.yml","../src/commands/workflows/bookkeeping.yml","../src/commands/workflows/codeql.yml","../src/commands/workflows/dependencies.yml","../src/commands/workflows/deploy.yml","../src/commands/workflows/greetings.yml","../src/commands/workflows/lint.yml","../src/commands/workflows/post-release.yml","../src/commands/workflows/release.yml","../src/commands/workflows/review.yml","../src/commands/workflows/stale.yml","../src/commands/workflows/sync.yml","../src/commands/workflows/test.yml","../src/commands/workflows/typecheck.yml","../src/commands/setup-workflows.ts","../src/commands/setup.ts","../src/commands/skills.ts","../src/commands/sync-readme.ts","../src/commands/sync.ts","../src/templates/actions/auto-commit.yml","../src/templates/actions/install.yml","../src/templates/actions/setup.yml","../src/templates/actions/setup-node.yml","../src/templates/workflows/audit.yml","../src/templates/workflows/bookkeeping.yml","../src/templates/workflows/cleanup-preview.yml","../src/templates/workflows/codeql.yml","../src/templates/workflows/dependencies.yml","../src/templates/workflows/deploy.yml","../src/templates/workflows/deploy-preview.yml","../src/templates/workflows/greetings.yml","../src/templates/workflows/lint.yml","../src/templates/workflows/post-release.yml","../src/templates/workflows/release.yml","../src/templates/workflows/review.yml","../src/templates/workflows/stale.yml","../src/templates/workflows/sync.yml","../src/templates/workflows/sync-broadcast.yml","../src/templates/workflows/sync-github.yml","../src/templates/workflows/tag.yml","../src/templates/workflows/test.yml","../src/templates/workflows/typecheck.yml","../src/templates/index.ts","../src/commands/sync-github.ts","../src/commands/upgrade-node.ts","../src/load-config.ts","../src/telemetry.ts","../src/token-args.ts","../src/update-notifier.ts","../src/cli.ts"],"sourcesContent":["export interface EnvLookup {\n\tget(key: string): string | undefined;\n\tfirst(...keys: string[]): string | undefined;\n}\n\nexport function createEnvLookup(source: NodeJS.ProcessEnv = process.env): EnvLookup {\n\treturn {\n\t\tget(key: string): string | undefined {\n\t\t\treturn source[key] || undefined;\n\t\t},\n\t\tfirst(...keys: string[]): string | undefined {\n\t\t\tfor (const key of keys) {\n\t\t\t\tconst val = source[key];\n\t\t\t\tif (val) return val;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n","/**\n * Keyring-backed bootstrap credential store.\n *\n * Every holocron plugin's bootstrap token (the one it needs before it\n * can talk to its vendor's API) can be stored in the OS keyring under\n * a single reverse-DNS service scope. Managed via `holocron auth`\n * subcommands; consulted at position 4 in every plugin's auth\n * precedence chain (after --token / HOLOCRON_<X>_TOKEN / <native>_TOKEN).\n *\n * See `.notes/tech-auth-bootstrap.spec.md` for the design rationale.\n *\n * Failure model: keyring access is best-effort. Platforms without a\n * supported credential store (some Linux CI images, sandboxed\n * environments) will throw from the underlying library. Every export\n * here catches and returns a null/empty result rather than propagating\n * — the plugin's precedence chain then falls through to\n * env-var-only paths, which is exactly how CI is meant to work.\n */\n\nimport { Entry, findCredentials } from \"@napi-rs/keyring\";\n\nconst SERVICE = \"com.theholocron.cli\";\n\n/**\n * Store or overwrite a bootstrap token for a provider. Returns true on\n * success, false when the underlying keyring is unsupported or errored.\n */\nexport function setToken(provider: string, token: string): boolean {\n\ttry {\n\t\tnew Entry(SERVICE, provider).setPassword(token);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Read the bootstrap token for a provider. Returns `null` for both\n * \"not stored\" and \"keyring unavailable\" — callers can treat them the\n * same way (fall through to env-var precedence).\n */\nexport function getToken(provider: string): string | null {\n\ttry {\n\t\treturn new Entry(SERVICE, provider).getPassword();\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Delete a stored token. Returns true when a token was removed, false\n * when there was nothing to delete or the keyring is unavailable.\n * Distinguishing the two cases isn't worth the surface area — the\n * command output makes the situation clear either way.\n */\nexport function deleteToken(provider: string): boolean {\n\ttry {\n\t\treturn new Entry(SERVICE, provider).deletePassword();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * List provider slugs with a stored token in this service scope.\n * Uses the library's `findCredentials(service)` — supported on all\n * platforms the underlying credential store supports.\n */\nexport function listStoredProviders(): string[] {\n\ttry {\n\t\treturn findCredentials(SERVICE).map((c) => c.account);\n\t} catch {\n\t\treturn [];\n\t}\n}\n","// Re-exported from @theholocron/http — the canonical home for HTTP primitives.\n// createResolveToken is wrapped here to inject the keyring backend so plugins\n// don't need to pass it explicitly.\nimport {\n\tAuthError,\n\tcreateResolveToken as _createResolveToken,\n\ttype ResolveTokenConfig as _ResolveTokenConfig,\n\ttype ResolveTokenInput,\n} from \"@theholocron/http-client\";\n\nimport { createEnvLookup } from \"./env.js\";\nimport { getToken as getKeyringToken } from \"./keyring.js\";\n\nexport { AuthError, type ResolveTokenInput };\n\nexport type ResolveTokenConfig = Omit<_ResolveTokenConfig, \"getKeyringToken\">;\n\n/** Wraps `createResolveToken` from `@theholocron/http` and injects the\n * system keyring so plugins stay at a one-liner call site. */\nexport function createResolveToken(config: ResolveTokenConfig): (input?: ResolveTokenInput) => string {\n\treturn _createResolveToken({ ...config, getKeyringToken });\n}\n\nexport interface FeatureResolverConfig {\n\t/** Env var name for this feature, e.g. `\"HOLOCRON_ISSUES_TOKEN\"`. */\n\tenvName: string;\n\t/** Keyring account key, e.g. `\"github.issues\"`. */\n\tkeyringKey: string;\n}\n\n/**\n * Build a strict, single-feature token resolver.\n *\n * Resolution chain: `--token flag → envName env var → keyring(keyringKey)`.\n * No broad-token fallback — if the feature-specific token is absent the\n * operation fails with a message naming the exact env var to set.\n */\nexport function createFeatureResolver(config: FeatureResolverConfig): (input?: ResolveTokenInput) => string {\n\treturn function resolveFeatureToken(input: ResolveTokenInput = {}): string {\n\t\tconst env = createEnvLookup(input.env);\n\t\tconst keyring = input.keyring ?? getKeyringToken;\n\t\tconst token = input.cliToken || env.get(config.envName) || keyring(config.keyringKey);\n\t\tif (!token) {\n\t\t\tthrow new AuthError(\n\t\t\t\t`no GitHub token found for this operation. Pass --token <PAT>, ` +\n\t\t\t\t\t`set ${config.envName}, or run: holocron auth set ${config.keyringKey} <PAT>`\n\t\t\t);\n\t\t}\n\t\treturn token;\n\t};\n}\n","/**\n * Capability interfaces — the contracts that providers implement.\n *\n * Each capability has a stable key (`'source'`, `'ci'`, …) and a\n * cardinality (`'single'` = one provider; `'many'` = several active\n * at once). The cardinality is part of the type contract via\n * `CardinalityFor<K>` so config resolution + command code can branch\n * statically.\n *\n * See `.notes/tech-architecture.spec.md` for the design narrative\n * (status: proposed, issue: #74).\n */\n\nexport type CapabilityKey =\n\t| \"source\"\n\t| \"ci\"\n\t| \"secrets\"\n\t| \"environments\"\n\t| \"issues\"\n\t| \"deployment\"\n\t| \"storage\"\n\t| \"auth\"\n\t| \"vault\"\n\t| \"dns\"\n\t| \"tooling\"\n\t| \"notifications\"\n\t| \"analytics\"\n\t| \"observability\";\n\nexport type Cardinality = \"single\" | \"many\";\n\nexport const CARDINALITY = {\n\tsource: \"single\",\n\tci: \"single\",\n\tsecrets: \"single\",\n\tenvironments: \"single\",\n\tissues: \"single\",\n\tdeployment: \"single\",\n\tstorage: \"single\",\n\tauth: \"single\",\n\tvault: \"single\",\n\tdns: \"single\",\n\ttooling: \"many\",\n\tnotifications: \"many\",\n\tanalytics: \"many\",\n\tobservability: \"many\",\n} as const satisfies Record<CapabilityKey, Cardinality>;\n\n/**\n * No capabilities are strictly required — repos without secrets (e.g. org\n * community health repos) legitimately omit vault. Plugins validate their\n * own requirements at call time.\n */\nexport const REQUIRED_CAPABILITIES: readonly CapabilityKey[] = [] as const;\n\n// ───────────────────────────────────────────────────────────────────────\n// Common shapes\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface ProviderIdentity {\n\treadonly key: CapabilityKey;\n\treadonly providerName: string;\n}\n\nexport { ProviderApiError } from \"@theholocron/http-client\";\n\n// ───────────────────────────────────────────────────────────────────────\n// source — repos, branches, PRs, rulesets, settings, workflow files\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface Ruleset {\n\tid: number;\n\tname: string;\n\tenforcement: \"active\" | \"evaluate\" | \"disabled\";\n\ttarget?: string;\n}\n\nexport interface RepoSettings {\n\tallow_squash_merge?: boolean;\n\tallow_merge_commit?: boolean;\n\tallow_rebase_merge?: boolean;\n\tallow_auto_merge?: boolean;\n\t/** Always suggest updating PR branches when the base branch has new commits. */\n\tallow_update_branch?: boolean;\n\tdelete_branch_on_merge?: boolean;\n\tdefault_branch?: string;\n\thas_issues?: boolean;\n\thas_discussions?: boolean;\n\thas_projects?: boolean;\n\thas_wiki?: boolean;\n}\n\nexport interface RepoRef {\n\towner: string;\n\tname: string;\n\tdefaultBranch: string;\n}\n\nexport interface LabelDef {\n\treadonly name: string;\n\treadonly color: string;\n\treadonly description: string;\n}\n\nexport type TeamPermission = \"pull\" | \"triage\" | \"push\" | \"maintain\" | \"admin\";\n\n/** Shorthand `\"slug\"` defaults to `push` permission. */\nexport type TeamEntry = string | { slug: string; permission: TeamPermission };\n\nexport interface Source extends ProviderIdentity {\n\treadonly key: \"source\";\n\n\t/** Auth sanity-check. Throws ProviderApiError on auth failure. */\n\twhoami(): Promise<{ login: string }>;\n\n\tgetRepo(): Promise<RepoRef>;\n\n\t// Rulesets / branch protection\n\tlistRulesets(): Promise<Ruleset[]>;\n\tcreateRuleset(payload: Record<string, unknown>): Promise<Ruleset>;\n\tupdateRuleset(id: number, payload: Record<string, unknown>): Promise<Ruleset>;\n\n\t// Repo settings\n\tupdateRepoSettings(settings: RepoSettings): Promise<void>;\n\n\t/**\n\t * Classic branch protection — fallback for private repos on free plans\n\t * where the Rulesets API (requires Team+) returns 403.\n\t */\n\tprotectBranch(branch: string, payload: Record<string, unknown>): Promise<void>;\n\n\t// Security toggles (idempotent; flip-or-noop)\n\tenableVulnerabilityAlerts(): Promise<void>;\n\tenableAutomatedSecurityFixes(): Promise<void>;\n\tenableSecretScanning(): Promise<void>;\n\tenablePrivateVulnerabilityReporting(): Promise<void>;\n\t/**\n\t * Enables the dependency graph and automatic dependency snapshot\n\t * submission. Also enables secret-scanning validity checks and\n\t * non-provider pattern detection — these require GitHub Advanced\n\t * Security at the org level; the call is accepted but may be a no-op\n\t * until that is configured.\n\t */\n\tenableDependencyGraph(): Promise<void>;\n\n\t/**\n\t * Enables CodeQL default setup with the extended query suite and\n\t * `threat_model: all` (scans both remote and local exploit paths).\n\t * Triggers a new analysis run; returns the run id.\n\t */\n\tenableCodeScanning(): Promise<string>;\n\n\t/**\n\t * Disables CodeQL default setup. Required when the repo uses an advanced\n\t * CodeQL workflow instead — GitHub rejects SARIF from advanced workflows\n\t * while default setup is active.\n\t */\n\tdisableDefaultCodeScanning(): Promise<void>;\n\n\t// Workflow files — local YAML files in `.github/workflows/` (or\n\t// equivalent). These are conceptually repo content; providers may\n\t// throw `NotImplementedError` if the underlying VCS has no notion\n\t// of declarative CI files.\n\tlistWorkflowFiles(): Promise<string[]>;\n\treadWorkflowFile(name: string): Promise<string | null>;\n\twriteWorkflowFile(name: string, contents: string): Promise<void>;\n\tremoveWorkflowFile(name: string): Promise<void>;\n\n\t/**\n\t * Write an arbitrary file relative to the repo root. Used for\n\t * provisioning config files that live outside `.github/workflows/`\n\t * (e.g. `.github/dependabot.yml`).\n\t */\n\twriteRepoFile(path: string, contents: string): Promise<void>;\n\n\t/**\n\t * Idempotently sync repo labels to a canonical set. Creates missing\n\t * labels, patches color/description drift, deletes stale labels.\n\t * Optional — providers that have no label concept omit this.\n\t */\n\tsyncLabels?(canonical: ReadonlyArray<LabelDef>, stale: ReadonlyArray<string>): Promise<string>;\n\n\t/**\n\t * Set org-level custom property values on the repo.\n\t * Optional — providers that don't support custom properties omit this.\n\t */\n\tsyncProperties?(values: Record<string, string>): Promise<string>;\n\n\t/**\n\t * Replace the repo's topic set with the supplied list.\n\t * Optional — providers that don't support topics omit this.\n\t */\n\tsyncTopics?(topics: string[]): Promise<string>;\n\n\t/**\n\t * Sync GitHub team repository access. String shorthand defaults to `push`.\n\t * Optional — providers without a team concept omit this.\n\t */\n\tsyncTeams?(teams: TeamEntry[]): Promise<string>;\n\n\t/**\n\t * Set the repository description.\n\t * Optional — providers that don't support setting descriptions omit this.\n\t */\n\tsyncDescription?(description: string): Promise<string>;\n\n\t/**\n\t * Set the repository homepage URL (the \"Website\" field on the repo landing page).\n\t * Optional — providers that don't support setting a homepage omit this.\n\t */\n\tsyncHomepage?(homepage: string): Promise<string>;\n\n\t/**\n\t * Enable or update GitHub Pages for the repository.\n\t * Idempotent: POST to create, PUT to update existing settings.\n\t * Requires HOLOCRON_DEPLOY_TOKEN (pages:write + repo scope) — passed\n\t * explicitly because it is a different PAT from the main admin token.\n\t * Optional — providers without a Pages concept omit this.\n\t */\n\tconfigurePages?(config: PagesConfig, token: string): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Pages\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface PagesConfig {\n\t/** GitHub Pages build source. */\n\tbuild: \"workflow\" | \"branch\";\n\t/**\n\t * Custom domain / CNAME (e.g. \"docs.theholocron.dev\").\n\t * When set and `homepage` is absent in holocron.config, setup derives\n\t * homepage as `https://{domain}/`.\n\t */\n\tdomain?: string;\n\t/** Enforce HTTPS. Only effective once the custom domain is DNS-verified. */\n\thttps?: boolean;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// ci — workflow runs (history + status only)\n// ───────────────────────────────────────────────────────────────────────\n\nexport type CiRunStatus = \"queued\" | \"in_progress\" | \"completed\" | \"cancelled\" | \"failure\" | \"success\" | \"skipped\";\n\nexport interface CiRun {\n\tid: string | number;\n\tworkflowName: string;\n\tbranch: string;\n\tsha: string;\n\tstatus: CiRunStatus;\n\turl: string;\n\tstartedAt: string;\n\tcompletedAt?: string;\n}\n\nexport interface CiRunFilter {\n\tbranch?: string;\n\tstatus?: CiRunStatus;\n\tlimit?: number;\n}\n\nexport interface Ci extends ProviderIdentity {\n\treadonly key: \"ci\";\n\tlistRuns(filter?: CiRunFilter): Promise<CiRun[]>;\n\tgetRun(id: string | number): Promise<CiRun>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// secrets — CI/platform secrets sync destination (multi-scope)\n// ───────────────────────────────────────────────────────────────────────\n\nexport type SecretScope =\n\t| { kind: \"repo\" }\n\t| { kind: \"environment\"; name: string }\n\t| { kind: \"organization\"; name: string };\n\nexport interface Secrets extends ProviderIdentity {\n\treadonly key: \"secrets\";\n\n\t/** List secret NAMES (not values) at the given scope. */\n\tlistSecrets(scope: SecretScope): Promise<string[]>;\n\n\t/** Idempotent upsert. Adapter handles encryption. */\n\tsetSecret(scope: SecretScope, name: string, value: string): Promise<void>;\n\n\tdeleteSecret(scope: SecretScope, name: string): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// environments — named deployment environments\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface EnvironmentReviewer {\n\ttype: \"User\" | \"Team\";\n\t/** Numeric id — GitHub's reviewer API silently ignores login strings. */\n\tid: number;\n}\n\nexport interface Environment {\n\tname: string;\n\treviewers?: EnvironmentReviewer[];\n\twaitTimer?: number;\n\tpreventSelfReview?: boolean;\n}\n\nexport interface Environments extends ProviderIdentity {\n\treadonly key: \"environments\";\n\tlistEnvironments(): Promise<Environment[]>;\n\tupsertEnvironment(env: Environment): Promise<void>;\n\tdeleteEnvironment(name: string): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// issues — tracker\n// ───────────────────────────────────────────────────────────────────────\n\nexport type LifecycleSlot = \"inProgress\" | \"inReview\" | \"done\";\n\nexport type StatusCategory = \"open\" | \"in-progress\" | \"in-review\" | \"done\" | \"other\";\n\nexport interface TrackerUser {\n\tid: string;\n\tdisplayName: string;\n\temailAddress?: string;\n}\n\nexport interface Issue {\n\t/** Human-readable key — \"#42\" for GitHub, \"RANDO-42\" for Jira. */\n\tkey: string;\n\t/** Internal opaque id. */\n\tid: string;\n\tsummary: string;\n\tbody?: string;\n\tstatus: string;\n\tstatusCategory: StatusCategory;\n\tassignee: TrackerUser | null;\n\tupdated: string;\n\turl?: string;\n}\n\nexport interface IssueSearchFilter {\n\t/** Restrict to issues assigned to a specific id, or 'currentUser'. */\n\tassignee?: string | \"currentUser\";\n\t/** Exclude issues in the `done` category. */\n\topenOnly?: boolean;\n\t/** Max number of issues to return. Adapters apply a sensible default. */\n\tlimit?: number;\n}\n\nexport interface LifecycleResult {\n\t/** False when no API write happened (already at target state). */\n\ttransitioned: boolean;\n\t/** Status name the issue is in after this call. */\n\tstatus: string;\n\t/** Adapter-specific note (e.g., \"label set\" / \"closed (completed)\"). */\n\tvia?: string;\n}\n\nexport interface TrackerDoctorReport {\n\t/** \"Authenticated as ...\" subject for the spinner. */\n\tauthedAs: string;\n\t/** Free-form \"Project: RANDO\" / \"Repo: rando-id/rando\" identifier. */\n\tprojectLabel: string;\n\t/** Status values the adapter exposes. */\n\tstatuses: Array<{ name: string; category: StatusCategory }>;\n\t/**\n\t * Per-lifecycle-slot readiness check. `resolved` indicates whether\n\t * the configured value actually maps to something the tracker\n\t * recognizes; the `note` is the rendered explanation.\n\t */\n\tlifecycle: Array<{\n\t\tslot: LifecycleSlot;\n\t\tvalue: string | null;\n\t\tresolved: boolean;\n\t\tnote: string;\n\t}>;\n}\n\nexport interface Issues extends ProviderIdentity {\n\treadonly key: \"issues\";\n\n\t/** Currently-authenticated user. */\n\tgetMyself(): Promise<TrackerUser>;\n\n\tsearch(filter: IssueSearchFilter): Promise<Issue[]>;\n\tget(key: string): Promise<Issue>;\n\n\tcreate(input: {\n\t\tsummary: string;\n\t\tbody?: string;\n\t\tlabels?: string[];\n\t\t/** Numeric id or exact title (case-insensitive). */\n\t\tmilestone?: string;\n\t}): Promise<{ key: string }>;\n\n\t/** Idempotent — `transitioned: false` if the issue is already at the target. */\n\ttransition(key: string, slot: LifecycleSlot): Promise<LifecycleResult>;\n\n\tcomment(key: string, body: string): Promise<void>;\n\n\tdoctor(): Promise<TrackerDoctorReport>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// deployment — preview/prod deploy targets\n// ───────────────────────────────────────────────────────────────────────\n\n/** Env-var scope on the deploy platform. */\nexport type DeploymentTarget = \"development\" | \"preview\" | \"production\";\n\n/**\n * Named deployment trigger target — `undefined` means a branch\n * preview (no named environment).\n */\nexport type DeploymentTrigger = \"production\" | \"staging\";\n\nexport interface DeploymentProject {\n\tid: string;\n\tname: string;\n\tframework?: string;\n\t/** True when the project is linked to a Git provider. */\n\tgitLinked?: boolean;\n\trootDirectory?: string | null;\n}\n\nexport interface DeploymentProjectSettings {\n\tpreviewDeploymentsDisabled?: boolean;\n\t/** Vercel-specific: whether the GitHub integration creates deployments\n\t * for every push (false → only on-demand triggers). */\n\tgitProviderCreateDeployments?: boolean;\n}\n\nexport interface DeploymentRecord {\n\tid: string;\n\turl: string;\n\t/** Branch this deployment was made from (null if not git-sourced). */\n\tbranch: string | null;\n\t/** Named environment if one was targeted; undefined for branch previews. */\n\ttarget?: DeploymentTrigger;\n\tstatus: \"queued\" | \"building\" | \"ready\" | \"error\" | \"cancelled\";\n}\n\nexport interface Deployment extends ProviderIdentity {\n\treadonly key: \"deployment\";\n\n\tlistProjects(): Promise<DeploymentProject[]>;\n\t/** Create if missing, otherwise return existing. Idempotent. */\n\tensureProject(input: {\n\t\tname: string;\n\t\tframework?: string;\n\t\t/** \"owner/repo\" — passed when linking to a Git provider. */\n\t\trepo?: string;\n\t\trootDirectory?: string;\n\t}): Promise<DeploymentProject>;\n\n\tupdateProjectSettings(projectId: string, settings: DeploymentProjectSettings): Promise<DeploymentProject>;\n\n\t// Env vars on the deploy platform (Vercel-style: per-target).\n\tlistEnvVars(projectId: string, target: DeploymentTarget): Promise<string[]>;\n\tsetEnvVar(projectId: string, target: DeploymentTarget, name: string, value: string): Promise<void>;\n\n\t/**\n\t * Kick off a deployment of the given branch. Omit `target` for a\n\t * branch preview; pass `'production'` / `'staging'` to deploy into\n\t * a named environment.\n\t */\n\ttriggerDeployment(input: {\n\t\tprojectId: string;\n\t\tbranch: string;\n\t\ttarget?: DeploymentTrigger;\n\t}): Promise<DeploymentRecord>;\n\n\tgetDeployment(deploymentId: string): Promise<DeploymentRecord>;\n\n\t/**\n\t * Add a custom domain (or wildcard) to the project. Idempotent — no-op\n\t * when the domain is already present. Optional: providers without a custom\n\t * domain API omit this (e.g. Vercel manages domains separately).\n\t */\n\tensureCustomDomain?(projectId: string, hostname: string): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// storage — DB / object / file store\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface StorageBranch {\n\tid: string;\n\tname: string;\n\t/** Parent branch id; null for the root/main branch. */\n\tparentId: string | null;\n\tcreatedAt: string;\n}\n\nexport interface ConnectionStringOptions {\n\t/** Use the pooled (PgBouncer) URL when available. Defaults to false. */\n\tpooled?: boolean;\n}\n\nexport interface Storage extends ProviderIdentity {\n\treadonly key: \"storage\";\n\n\t/**\n\t * Connection string for the given scope. Scope is provider-specific:\n\t *\n\t * - branch-based providers (Neon, PlanetScale): scope = branch\n\t * name or id\n\t * - flat providers (single Postgres instance): scope is ignored\n\t *\n\t * Callers (or the orchestrator) decide how a deploy target maps to\n\t * a scope; the storage plugin doesn't own that mapping.\n\t */\n\tgetConnectionString(scope: string, options?: ConnectionStringOptions): Promise<string>;\n\n\t// Branch operations (optional — flat providers can omit).\n\tlistBranches?(): Promise<StorageBranch[]>;\n\tcreateBranch?(input: { name: string; from?: string }): Promise<StorageBranch>;\n\tdestroyBranch?(branch: string): Promise<void>;\n\t/** Restore one branch to match another (e.g., reset preview → main). */\n\tresetBranch?(input: { branch: string; from: string }): Promise<void>;\n\n\t/**\n\t * Provider-specific feature toggle. For Postgres providers this is\n\t * `CREATE EXTENSION IF NOT EXISTS ...` per branch.\n\t */\n\tenableExtension?(input: { branch: string; extension: string }): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// auth — identity provider\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface AuthDescription {\n\tprovider: string;\n\t/** Env-var names the app needs at runtime (CLERK_PUBLISHABLE_KEY, etc.). */\n\tenvKeys: string[];\n}\n\nexport interface AuthIdentity {\n\tprovider: string;\n\t/** Provider-specific health signal (user count, role, account name, etc.). */\n\tdetails?: Record<string, unknown>;\n}\n\nexport interface AuthUser {\n\tid: string;\n\temail: string;\n}\n\nexport interface CreateAuthUserInput {\n\temail: string;\n\tpassword: string;\n\tfirstName?: string;\n\tlastName?: string;\n}\n\nexport interface WebhookDashboardInfo {\n\turl: string;\n}\n\nexport interface Auth extends ProviderIdentity {\n\treadonly key: \"auth\";\n\n\t/** Env-var keys the runtime app needs. */\n\tdescribe(): Promise<AuthDescription>;\n\n\t/** Reachability probe — proves the configured key works. */\n\twhoami(): Promise<AuthIdentity>;\n\n\t// Optional capabilities — providers implement what they support.\n\n\t/** Idempotent webhook backend provisioning (Clerk: Svix app). */\n\tensureWebhookApp?(): Promise<{ alreadyExists: boolean }>;\n\n\t/** Deep-link to the provider's webhook config dashboard. */\n\tgetWebhookDashboardUrl?(): Promise<WebhookDashboardInfo>;\n\n\t/** Seed a user (test fixtures, admin bootstrap). */\n\tcreateUser?(input: CreateAuthUserInput): Promise<AuthUser>;\n\n\t/** Wire the auth provider's webhook into the project's repo. */\n\tsyncWebhook?(input: { repo: string; secretRef: string }): Promise<void>;\n}\n\n// ── Normalized webhook events (cross-provider sync) ──────────────────\n//\n// Plugins implementing `auth` may also expose a `parseWebhook` utility\n// (NOT a capability method — exported alongside the plugin's\n// createPlugin) that translates the vendor's webhook payload into one\n// of these normalized event shapes. Your app's webhook handler then\n// reads the normalized event and is vendor-agnostic:\n//\n// import { parseWebhook } from '@theholocron/holocron-plugin-clerk'\n// import type { AuthEvent } from '@theholocron/cli'\n//\n// app.post('/webhooks/clerk', async (req) => {\n// const event: AuthEvent = await parseWebhook({\n// body: req.body,\n// headers: req.headers,\n// signingSecret: process.env.CLERK_WEBHOOK_SECRET!,\n// })\n// await db.users.upsert(event.user)\n// })\n//\n// Swap clerk for another auth plugin → change one import line; the\n// handler logic stays the same.\n\nexport type AuthEventType = \"user.created\" | \"user.updated\" | \"user.deleted\";\n\nexport interface NormalizedAuthUser {\n\tid: string;\n\temail: string;\n\tfirstName?: string | null;\n\tlastName?: string | null;\n\t/** Provider-native fields preserved verbatim for consumers that need them. */\n\traw?: Record<string, unknown>;\n}\n\nexport interface AuthEvent {\n\ttype: AuthEventType;\n\tuser: NormalizedAuthUser;\n\t/** ISO timestamp of when the event occurred. */\n\toccurredAt: string;\n}\n\nexport interface ParseWebhookInput {\n\t/** Raw request body (string or Buffer). */\n\tbody: string | Buffer;\n\t/** Incoming HTTP headers — needed for signature verification. */\n\theaders: Record<string, string | string[] | undefined>;\n\t/** The signing secret the auth provider issued for this webhook endpoint. */\n\tsigningSecret: string;\n}\n\nexport class WebhookVerificationError extends Error {\n\toverride name = \"WebhookVerificationError\";\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// vault — REQUIRED source-of-truth for secrets\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface EnsureResult {\n\t/** True when the resource already existed (idempotent no-op). */\n\talreadyExists: boolean;\n}\n\nexport interface Vault extends ProviderIdentity {\n\treadonly key: \"vault\";\n\n\t/**\n\t * Read a secret by reference. The reference format is\n\t * provider-specific (1P: \"op://Vault/Item/field\"; HashiCorp Vault:\n\t * \"kv/path#field\"; etc.). Adapters validate the reference shape.\n\t */\n\tread(reference: string): Promise<string>;\n\n\t/** Write or update a secret. */\n\twrite(reference: string, value: string): Promise<void>;\n\n\t/** List secret keys available to the project. */\n\tlist(): Promise<string[]>;\n\n\t/**\n\t * Optional environment notion within the vault (e.g., 1P\n\t * Environments — named KEY=VALUE bundles). Adapters without\n\t * environments return [].\n\t */\n\tenvironments?(): Promise<string[]>;\n\n\t/**\n\t * Optional bulk read of an environment's KEY=VALUE pairs. Powers\n\t * the `holocron secrets sync` flow where the orchestrator pulls a\n\t * whole environment from the vault then fans the values out to\n\t * destinations (CI secrets, deployment env vars, local .env).\n\t */\n\treadEnvironment?(environmentId: string): Promise<Record<string, string>>;\n\n\t/**\n\t * Optional — create the top-level project container in the vault\n\t * if it does not exist. Idempotent: `alreadyExists: true` when the\n\t * project was already there. Providers whose data model has no\n\t * project notion (or that gate this behind a paid tier) omit this.\n\t */\n\tensureProject?(name: string): Promise<EnsureResult>;\n\n\t/**\n\t * Optional — create a named environment/config inside a project\n\t * (e.g., Doppler config `dev` / `stg` / `prd`). Idempotent.\n\t * Providers whose data model has a single flat namespace omit this.\n\t */\n\tensureEnvironment?(project: string, name: string): Promise<EnsureResult>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// dns — DNS record management\n// ───────────────────────────────────────────────────────────────────────\n\nexport type DnsRecordType = \"A\" | \"AAAA\" | \"CNAME\" | \"TXT\" | \"MX\" | \"NS\" | \"SRV\" | \"CAA\";\n\nexport interface DnsRecord {\n\tid?: string;\n\ttype: DnsRecordType;\n\tname: string;\n\tcontent: string;\n\tttl?: number;\n\tpriority?: number;\n}\n\nexport interface Dns extends ProviderIdentity {\n\treadonly key: \"dns\";\n\tlistRecords(domain: string): Promise<DnsRecord[]>;\n\tupsertRecord(domain: string, record: DnsRecord): Promise<DnsRecord>;\n\tdeleteRecord(domain: string, id: string): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Multi-provider capabilities — many can be active at once\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface ToolingDoctorReport {\n\tok: boolean;\n\tmessage: string;\n}\n\nexport interface Tooling extends ProviderIdentity {\n\treadonly key: \"tooling\";\n\n\t/** Sync the tool's authoritative state from the repo. */\n\tsync(): Promise<void>;\n\n\tdoctor(): Promise<ToolingDoctorReport>;\n}\n\nexport interface Notifications extends ProviderIdentity {\n\treadonly key: \"notifications\";\n\n\t/**\n\t * Send a message. `channel` is provider-specific (Slack channel id,\n\t * Discord webhook url-name, etc.); adapters resolve from config.\n\t */\n\tsend(channel: string, message: string): Promise<void>;\n}\n\nexport interface Analytics extends ProviderIdentity {\n\treadonly key: \"analytics\";\n\t/** Returns the env var names the app reads at runtime for this provider. */\n\tdescribe(): Promise<{ provider: string; envKeys: string[] }>;\n\twhoami?(): Promise<{ org: string }>;\n\tensureProject?(name: string): Promise<{ token: string; alreadyExists: boolean }>;\n}\n\nexport interface Observability extends ProviderIdentity {\n\treadonly key: \"observability\";\n\t/** Returns the env var names the app reads at runtime for this provider. */\n\tdescribe(): Promise<{ provider: string; envKeys: string[] }>;\n\twhoami?(): Promise<{ org: string }>;\n\tensureProject?(input: { name: string; platform?: string }): Promise<{ dsn: string; alreadyExists: boolean }>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Capability map (key → implementation type) + cardinality helpers\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface CapabilityImpls {\n\tsource: Source;\n\tci: Ci;\n\tsecrets: Secrets;\n\tenvironments: Environments;\n\tissues: Issues;\n\tdeployment: Deployment;\n\tstorage: Storage;\n\tauth: Auth;\n\tvault: Vault;\n\tdns: Dns;\n\ttooling: Tooling;\n\tnotifications: Notifications;\n\tanalytics: Analytics;\n\tobservability: Observability;\n}\n\nexport type CardinalityFor<K extends CapabilityKey> = (typeof CARDINALITY)[K];\n\n/** Resolved runtime shape: single → one impl; many → array. */\nexport type ResolvedCapability<K extends CapabilityKey> =\n\tCardinalityFor<K> extends \"many\" ? CapabilityImpls[K][] : CapabilityImpls[K];\n\nexport function isMulti<K extends CapabilityKey>(key: K): CardinalityFor<K> extends \"many\" ? true : false {\n\treturn (CARDINALITY[key] === \"many\") as CardinalityFor<K> extends \"many\" ? true : false;\n}\n","/**\n * `holocron.config.json` schema, parser, and provider resolution.\n *\n * ESLint-style entry forms:\n *\n * \"source\": \"github\" ← single, short\n * \"deployment\": [\"vercel\", { team: \"rando\" }] ← single, with options\n * \"notifications\": [\"slack\", \"discord\"] ← multi, short\n * \"notifications\": [\n * [\"slack\", { channel: \"#ops\" }],\n * [\"discord\", { webhook: \"env:HOOK\" }]\n * ] ← multi, with options\n *\n * Discriminator: an array entry is a `[provider, options]` tuple when\n * the length is 2 AND element[1] is a non-array, non-null object.\n * Otherwise it's a multi-provider list (string[] or tuple[]).\n *\n * Validation rules:\n * - `vault` is REQUIRED (every project has secrets somewhere)\n * - Entries for `'many'` capabilities are normalized to an array of\n * normalized tuples; entries for `'single'` capabilities are\n * normalized to one tuple\n * - Tokens / secret values never appear in config — providers read\n * them from env (or pull from `vault` at runtime)\n */\n\nimport {\n\ttype CapabilityKey,\n\tCARDINALITY,\n\ttype PagesConfig,\n\tREQUIRED_CAPABILITIES,\n\ttype TeamEntry,\n\ttype TeamPermission,\n} from \"./capabilities/index.js\";\n\n// ───────────────────────────────────────────────────────────────────────\n// Raw config (what users write in holocron.config.json)\n// ───────────────────────────────────────────────────────────────────────\n\nexport type ProviderOptions = Record<string, unknown>;\n\n/**\n * The shape a capability config package's default export must satisfy.\n * Config packages let teams share a pre-bundled provider + options across\n * repos (Level 1 of the shareable-configs story, issue #75).\n *\n * @example\n * // @acme/holocron-vault/index.ts\n * import type { CapabilityConfigPackage } from '@theholocron/cli'\n * export default {\n * provider: '1password',\n * options: { vault: 'acme-app' },\n * } satisfies CapabilityConfigPackage\n */\nexport interface CapabilityConfigPackage {\n\tprovider: string;\n\toptions?: ProviderOptions;\n}\n\nexport type SingleEntry = string | [provider: string, options: ProviderOptions];\n\nexport type MultiEntry = Array<string | [provider: string, options: ProviderOptions]>;\n\nexport type RawProviderEntry = SingleEntry | MultiEntry;\n\nexport type RawProvidersConfig = Partial<Record<CapabilityKey, RawProviderEntry>>;\n\nexport type RepoProtection = \"balanced\" | \"strict\" | \"none\";\n\nexport type { PagesConfig, TeamEntry, TeamPermission };\n\n/**\n * Raw `docs` config as written by the user. `build` is optional so the\n * field can be declared without committing to a build type yet; setup\n * will error if `docs` is present but `build` is absent.\n */\nexport interface DocsConfig {\n\t/**\n\t * GitHub Pages build source.\n\t * \"workflow\" → GitHub Actions (PUT { build_type: \"workflow\" })\n\t * \"branch\" → classic gh-pages branch (PUT { build_type: \"legacy\", source: { branch: \"gh-pages\", path: \"/\" } })\n\t * When absent, Pages is not managed by `holocron setup`.\n\t */\n\tbuild?: \"workflow\" | \"branch\";\n\t/**\n\t * Custom domain / CNAME (e.g. \"docs.theholocron.dev\").\n\t * When set and `homepage` is not explicitly provided, setup derives\n\t * `homepage` as `https://{domain}/` for package.json and the repo website field.\n\t */\n\tdomain?: string;\n\t/** Enforce HTTPS. Only effective once the custom domain is DNS-verified. */\n\thttps?: boolean;\n}\n\nexport interface RepoProperties {\n\tlifecycle?: \"active\" | \"experimental\" | \"deprecated\";\n\topen_source?: boolean;\n\truntime_environment?: \"node\" | \"browser\" | \"universal\" | \"none\";\n\tuses_external_packages?: boolean;\n}\n\nexport interface RepoConfig {\n\t/** \"owner/name\" — the GitHub repository coordinate. Derived from the git remote when absent. */\n\tname?: string;\n\t/**\n\t * Branch protection preset applied by `holocron setup`. When omitted,\n\t * no protection is applied and no `branch_protection_level` property is set.\n\t */\n\tprotection?: RepoProtection;\n\t/** CI check context names required on the default branch (only used when `protection` is \"strict\"). */\n\trequiredChecks?: string[];\n\t/**\n\t * GitHub teams granted repository access. Synced by `holocron setup`, which\n\t * also writes `.github/CODEOWNERS` for teams with write-or-higher permission.\n\t * String shorthand defaults to `push` (Write).\n\t */\n\tteams?: TeamEntry[];\n\t/** GitHub topics set on the repository. */\n\ttopics?: string[];\n\t/** GitHub custom properties synced to the org dashboard. */\n\tproperties?: RepoProperties;\n}\n\nexport interface AppConfig {\n\tname: string;\n\tpath: string;\n\tkind?: string;\n}\n\nexport interface DoctorConfig {\n\tchecks?: string[];\n}\n\nexport interface EnvConfig {\n\t/**\n\t * Namespace prefixes used by this project's env vars.\n\t * Listed from least- to most-specific (cascade model — last wins).\n\t * Tooling reads this to generate `.env.example`, validate required\n\t * vars, and produce documentation. Runtime code passes the same\n\t * value to `createEnvParser({ namespaces })` from `@theholocron/env-utils`.\n\t *\n\t * @example\n\t * // Project-only prefix\n\t * namespaces: [\"CLI_TEMPLATE\"]\n\t *\n\t * // Org-wide defaults + project-specific overrides\n\t * namespaces: [\"HOLOCRON\", \"MY_CLI\"]\n\t */\n\tnamespaces?: string[];\n}\n\n/**\n * A single Chromatic project entry in a monorepo `run-chromatic` config.\n * Each entry produces one matrix job in CI, publishing to a separate Chromatic project.\n *\n * The `tokenName` maps to a repository secret named `CHROMATIC_PROJECT_TOKEN_<TOKENNAME>`.\n * Additional fields correspond to chromaui/action inputs and are passed through directly.\n *\n * @see https://www.chromatic.com/docs/monorepos/\n */\nexport interface ChromaticProjectConfig {\n\t/**\n\t * Secret suffix. The CI job reads `CHROMATIC_PROJECT_TOKEN_<tokenName>`.\n\t * Must be uppercase (e.g. `\"WEB\"`, `\"UI\"`).\n\t */\n\ttokenName: string;\n\t/**\n\t * Path to run the Chromatic build from, relative to the repo root.\n\t * Typically the package directory (e.g. `\"apps/web\"`, `\"packages/ui\"`).\n\t */\n\tworkingDir: string;\n\t/**\n\t * Script name to build Storybook. Defaults to `\"build:storybook\"`.\n\t * Must accept `--output-dir` pass-through (use `turbo run … --` at root).\n\t */\n\tbuildScript?: string;\n\t/**\n\t * Path to the Storybook folder relative to `workingDir`, for TurboSnap.\n\t * Tells Chromatic where to find `.storybook/` when the Storybook config\n\t * is in a subdirectory. Corresponds to `--storybook-base-dir`.\n\t */\n\tstorybookBaseDir?: string;\n\t/**\n\t * Glob patterns of files/dirs that should NOT trigger a TurboSnap bailout\n\t * when changed. Useful for ignoring non-UI changes in a monorepo\n\t * (e.g. `\"./packages/!(ui)/**\"` to focus TurboSnap on the UI package).\n\t * Corresponds to `--untraced`. Accepts a single glob string or array.\n\t */\n\tuntraced?: string | string[];\n\t/**\n\t * Glob patterns matching story files to snapshot. When set, only matching\n\t * stories are captured. Corresponds to `--only-story-files`.\n\t * Cannot be combined with `onlyStoryNames`.\n\t */\n\tonlyStoryFiles?: string;\n\t/**\n\t * Exit with code 0 even when visual changes are detected.\n\t * Useful during initial setup before baselines are approved.\n\t * Corresponds to `--exit-zero-on-changes`.\n\t */\n\texitZeroOnChanges?: boolean;\n}\n\n/**\n * A single Storybook app in a deploy workflow config.\n * `name` becomes the sandbox sub-path (`_site/sandbox/<name>/`).\n * `path` is the working directory relative to the repo root; defaults to `\".\"` (repo root) when omitted.\n */\nexport interface StorybookDeployProject {\n\tname?: string;\n\tpath?: string;\n}\n\n/**\n * Typed `with:` inputs for reusable workflows.\n *\n * `run-chromatic` accepts either a plain boolean (single-project) or a\n * `ChromaticProjectConfig[]` object (multi-project monorepo).\n *\n * `docs` / `storybook` are high-level deploy shorthand that `holocron setup`\n * translates to `type` / `storybook-projects` before writing the thin caller.\n * They also drive automatic `paths:` derivation so you never need to write\n * `paths:` manually for deploy entries.\n */\nexport type WorkflowWithConfig = Record<string, unknown> & {\n\t\"run-chromatic\"?: boolean | { projects: ChromaticProjectConfig[] };\n\t/**\n\t * Docs deployment shorthand. `true` uses the org-standard `docs/` directory;\n\t * `{ path: \"custom\" }` uses a custom directory. Both derive a `paths:` entry automatically.\n\t */\n\tdocs?: true | { path: string };\n\t/** Storybook apps to deploy alongside docs. Each entry's `path` is appended to `paths:`. */\n\tstorybook?: StorybookDeployProject[];\n};\n\nexport interface HolocronConfig {\n\t/** Project name. Derived from package.json when absent. */\n\tname?: string;\n\tdescription?: string;\n\t/** Project homepage URL. Synced to package.json#homepage and the GitHub repo's website field by `holocron sync`. */\n\thomepage?: string;\n\t/**\n\t * Active org name for namespaced keyring lookup. When set, token resolution\n\t * tries `<service>.<org>` before the unnamespaced `<service>` fallback, so\n\t * a single machine can hold credentials for multiple GitHub orgs without\n\t * collision. Overridden by `--org` CLI flag or `HOLOCRON_ORG` env var.\n\t */\n\torg?: string;\n\t/**\n\t * Org canonical domain (e.g. `\"theholocron.dev\"`). Subdomains are derived\n\t * from this — `preview: true` on a deploy workflow resolves the preview base\n\t * domain as `preview.<domain>`, giving URLs like `<repo>-pr-<n>.<domain>`.\n\t */\n\tdomain?: string;\n\t/**\n\t * Repository identity and metadata. When set, `PluginLoader` injects\n\t * `repo.name` into every plugin's `RuntimeContext.repo` so plugins that\n\t * need a repo (github, etc.) don't require `--repo` on every invocation.\n\t * `--repo` on the command line still overrides.\n\t */\n\trepo?: RepoConfig;\n\t/**\n\t * CI workflow names to install as thin wrappers during `holocron setup`.\n\t * Each name maps to a reusable workflow in `theholocron/.github`.\n\t * Use the object form to pass `with:` inputs to the reusable workflow.\n\t *\n\t * Supported values: \"lint\" | \"test\" | \"typecheck\" | \"codeql\" | \"review\" |\n\t * \"release\" | \"tag\" | \"stale\" | \"greetings\" | \"dependencies\" | \"bookkeeping\" | \"audit\" |\n\t * \"deploy\"\n\t *\n\t * `holocron setup` writes `.github/workflows/<name>.yml` for each entry,\n\t * calling the corresponding reusable workflow in `theholocron/.github`.\n\t * Files are overwritten on each run — they are generated artifacts.\n\t *\n\t * ### deploy workflow\n\t * Use `docs` and/or `storybook` in `with:` — setup derives `paths:` automatically.\n\t * `docs: true` uses the org-standard `docs/` directory; `docs: { path: \"custom\" }` overrides it.\n\t *\n\t * ```ts\n\t * // Docs only (standard layout)\n\t * { name: \"deploy\", with: { docs: true } }\n\t *\n\t * // Docs + monorepo storybooks\n\t * {\n\t * name: \"deploy\",\n\t * with: {\n\t * docs: true,\n\t * storybook: [\n\t * { name: \"web\", path: \"apps/web\" },\n\t * { name: \"ui\", path: \"packages/ui\" },\n\t * ],\n\t * },\n\t * }\n\t *\n\t * // Non-standard docs location\n\t * { name: \"deploy\", with: { docs: { path: \"packages/site\" } } }\n\t * ```\n\t *\n\t * ### run-chromatic\n\t * For a single-project repo, use `\"run-chromatic\": true` with a\n\t * `CHROMATIC_PROJECT_TOKEN` repository secret.\n\t *\n\t * For monorepos with multiple Storybooks, use the object form:\n\t * ```ts\n\t * \"run-chromatic\": {\n\t * projects: [\n\t * { tokenName: \"WEB\", workingDir: \"apps/web\" },\n\t * { tokenName: \"UI\", workingDir: \"packages/ui\" },\n\t * ]\n\t * }\n\t * ```\n\t * Each `tokenName` maps to a repository secret named\n\t * `CHROMATIC_PROJECT_TOKEN_<TOKENNAME>`. `holocron setup` expands this\n\t * to the flat `run-chromatic: true` + `chromatic-projects: <json>` inputs\n\t * that the reusable workflow accepts.\n\t *\n\t * @example\n\t * [\"lint\", { \"name\": \"release\", \"with\": { \"run-build\": false } }]\n\t * { \"name\": \"deploy\", \"with\": { \"docs\": true } }\n\t */\n\tworkflows?: Array<string | { name: string; with?: WorkflowWithConfig; paths?: string[] }>;\n\tproviders: RawProvidersConfig;\n\tapps?: AppConfig[];\n\tdoctor?: DoctorConfig;\n\t/**\n\t * Agent runtime that determines where skills are installed by `holocron setup`.\n\t * Skills are installed to `.agents/skills/<name>/` (canonical) with a\n\t * relative symlink at the agent-specific path:\n\t * - `\"claude\"` → `.claude/skills/<name>` → `../../.agents/skills/<name>`\n\t * - `\"codex\"` | `\"gemini\"` → logged as unsupported; skipped gracefully.\n\t */\n\tagent?: \"claude\" | \"codex\" | \"gemini\";\n\t/**\n\t * Skill names from `@theholocron/skills` to install during `holocron setup`.\n\t * Installed paths are gitignored and managed by setup — do not commit them.\n\t *\n\t * @example\n\t * [\"git-safety\", \"pr-workflow\", \"commit-standards\"]\n\t */\n\tskills?: string[];\n\t/**\n\t * GitHub Pages configuration. When present, `holocron setup` calls the\n\t * Pages API using `HOLOCRON_DEPLOY_TOKEN` (requires `pages:write` + `repo` scope).\n\t * When absent, Pages is left as-is.\n\t *\n\t * @example\n\t * { build: \"workflow\", domain: \"docs.theholocron.dev\", https: true }\n\t */\n\tdocs?: DocsConfig;\n\t/**\n\t * Environment variable namespace configuration.\n\t * Declares the prefix(es) this project uses for its env vars so that\n\t * tooling can generate `.env.example`, validate required vars, and\n\t * produce accurate documentation without hard-coding prefix strings.\n\t *\n\t * @example\n\t * { namespaces: [\"HOLOCRON\", \"MY_CLI\"] }\n\t */\n\tenv?: EnvConfig;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Resolved config (what the runtime sees after parsing)\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface ResolvedTuple {\n\tprovider: string;\n\t/** Resolved package name (`@theholocron/holocron-plugin-<provider>` for short refs). */\n\tpackageName: string;\n\toptions: ProviderOptions;\n}\n\nexport type ResolvedProviderEntry =\n\t| { cardinality: \"single\"; tuple: ResolvedTuple }\n\t| { cardinality: \"many\"; tuples: ResolvedTuple[] };\n\nexport type ResolvedProvidersConfig = Partial<Record<CapabilityKey, ResolvedProviderEntry>>;\n\nexport interface ResolvedHolocronConfig {\n\tname: string;\n\tdescription?: string;\n\thomepage?: string;\n\torg?: string;\n\tdomain?: string;\n\trepo?: RepoConfig;\n\tworkflows?: Array<string | { name: string; with?: WorkflowWithConfig; paths?: string[] }>;\n\tproviders: ResolvedProvidersConfig;\n\tapps: AppConfig[];\n\tdoctor: DoctorConfig;\n\tagent?: \"claude\" | \"codex\" | \"gemini\";\n\tskills?: string[];\n\t/** Resolved Pages config. `build` is guaranteed present when this field exists. */\n\tdocs?: PagesConfig;\n\tenv?: EnvConfig;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Errors\n// ───────────────────────────────────────────────────────────────────────\n\nexport class ConfigError extends Error {\n\toverride name = \"ConfigError\";\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Helpers\n// ───────────────────────────────────────────────────────────────────────\n\nconst PLUGIN_PREFIX = \"@theholocron/holocron-plugin-\";\nconst COMMUNITY_PREFIX = \"holocron-plugin-\";\n\n/**\n * Resolve `\"github\"` → `\"@theholocron/holocron-plugin-github\"`.\n * Fully-qualified names (scoped or not) are honored verbatim, which\n * is how third-party plugins published outside the org work.\n */\nexport function resolvePluginPackage(provider: string): string {\n\tif (!provider) throw new ConfigError(\"provider name is empty\");\n\tif (provider.startsWith(\"@\")) return provider;\n\tif (provider.startsWith(COMMUNITY_PREFIX)) return provider;\n\tif (provider.includes(\"/\")) return provider;\n\treturn PLUGIN_PREFIX + provider;\n}\n\n/** A bare `[provider, options]` tuple, with both elements present? */\nfunction isOptionsTuple(value: unknown): value is [string, ProviderOptions] {\n\tif (!Array.isArray(value)) return false;\n\tif (value.length !== 2) return false;\n\tif (typeof value[0] !== \"string\") return false;\n\tconst opt = value[1];\n\treturn typeof opt === \"object\" && opt !== null && !Array.isArray(opt);\n}\n\nfunction normalizeEntry(entry: string | [string, ProviderOptions]): ResolvedTuple {\n\tif (typeof entry === \"string\") {\n\t\treturn { provider: entry, packageName: resolvePluginPackage(entry), options: {} };\n\t}\n\tconst [provider, options] = entry;\n\treturn { provider, packageName: resolvePluginPackage(provider), options };\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Parse / resolve\n// ───────────────────────────────────────────────────────────────────────\n\nexport function resolveEntry(key: CapabilityKey, raw: RawProviderEntry): ResolvedProviderEntry {\n\tconst cardinality = CARDINALITY[key];\n\n\t// Single short form: \"github\"\n\tif (typeof raw === \"string\") {\n\t\tif (cardinality === \"many\") {\n\t\t\tthrow new ConfigError(`\\`${key}\\` accepts multiple providers; wrap a single one in an array: [\"${raw}\"]`);\n\t\t}\n\t\treturn { cardinality: \"single\", tuple: normalizeEntry(raw) };\n\t}\n\n\tif (!Array.isArray(raw)) {\n\t\tthrow new ConfigError(`\\`${key}\\` entry must be a string or array, got ${typeof raw}`);\n\t}\n\n\t// Single options tuple: [\"vercel\", { team: \"rando\" }]\n\tif (isOptionsTuple(raw)) {\n\t\tif (cardinality === \"many\") {\n\t\t\t// Same shape, but cardinality forces multi — promote to one-element list\n\t\t\treturn { cardinality: \"many\", tuples: [normalizeEntry(raw)] };\n\t\t}\n\t\treturn { cardinality: \"single\", tuple: normalizeEntry(raw) };\n\t}\n\n\t// Multi list — array of strings, tuples, or a mix\n\tif (cardinality === \"single\") {\n\t\tthrow new ConfigError(\n\t\t\t`\\`${key}\\` accepts exactly one provider; got a multi-provider list with ${raw.length} entries`\n\t\t);\n\t}\n\n\tconst tuples = raw.map((entry, idx) => {\n\t\tif (typeof entry === \"string\") return normalizeEntry(entry);\n\t\tif (isOptionsTuple(entry)) return normalizeEntry(entry);\n\t\tthrow new ConfigError(`\\`${key}[${idx}]\\` must be a provider string or [provider, options] tuple`);\n\t});\n\n\treturn { cardinality: \"many\", tuples };\n}\n\nexport function resolveConfig(raw: HolocronConfig): ResolvedHolocronConfig {\n\tif (!raw.name) {\n\t\tthrow new ConfigError(\"`name` is required\");\n\t}\n\tif (!raw.providers || typeof raw.providers !== \"object\") {\n\t\tthrow new ConfigError(\"`providers` block is required\");\n\t}\n\n\tconst providers: ResolvedProvidersConfig = {};\n\tfor (const [key, entry] of Object.entries(raw.providers)) {\n\t\tif (entry === undefined) continue;\n\t\tproviders[key as CapabilityKey] = resolveEntry(key as CapabilityKey, entry as RawProviderEntry);\n\t}\n\n\tfor (const required of REQUIRED_CAPABILITIES) {\n\t\tif (!providers[required]) {\n\t\t\tthrow new ConfigError(`required capability \\`${required}\\` is missing from providers`);\n\t\t}\n\t}\n\n\t// Validate docs and narrow build to required\n\tlet docs: PagesConfig | undefined;\n\tif (raw.docs !== undefined) {\n\t\tif (!raw.docs.build) {\n\t\t\tthrow new ConfigError(\"`docs.build` is required when `docs` is set\");\n\t\t}\n\t\tdocs = raw.docs as PagesConfig;\n\t}\n\n\t// Derive homepage from docs.domain when not explicitly set\n\tconst homepage = raw.homepage ?? (docs?.domain ? `https://${docs.domain}/` : undefined);\n\n\treturn {\n\t\tname: raw.name,\n\t\tdescription: raw.description,\n\t\thomepage,\n\t\torg: raw.org,\n\t\tdomain: raw.domain,\n\t\trepo: raw.repo,\n\t\tworkflows: raw.workflows,\n\t\tproviders,\n\t\tapps: raw.apps ?? [],\n\t\tdoctor: raw.doctor ?? {},\n\t\tagent: raw.agent,\n\t\tskills: raw.skills,\n\t\tdocs,\n\t\tenv: raw.env,\n\t};\n}\n","import ora from \"ora\";\n\n/**\n * Runs `fn`, showing an ora spinner for its duration in TTY environments.\n * In non-TTY environments (CI, pipes, tests) the spinner is skipped entirely.\n */\nexport async function withSpinner<T>(label: string, fn: () => Promise<T>): Promise<T> {\n\tif (!process.stdout.isTTY) {\n\t\treturn fn();\n\t}\n\tconst spinner = ora(label).start();\n\ttry {\n\t\tconst result = await fn();\n\t\tspinner.succeed();\n\t\treturn result;\n\t} catch (err) {\n\t\tspinner.fail();\n\t\tthrow err;\n\t}\n}\n","import chalk from \"chalk\";\n\nexport const style = {\n\tsuccess: (msg: string) => `${chalk.green(\"✓\")} ${msg}`,\n\twarn: (msg: string) => `${chalk.yellow(\"⚠\")} ${msg}`,\n\tfail: (msg: string) => `${chalk.red(\"✗\")} ${msg}`,\n\tstep: (msg: string) => `${chalk.cyan(\"→\")} ${msg}`,\n\thint: (msg: string) => chalk.dim(msg),\n\tdim: (msg: string) => chalk.dim(msg),\n\theader: (msg: string) => chalk.bold(msg),\n};\n","/**\n * `holocron auth <subcommand>` — manage bootstrap credentials in the\n * OS keyring.\n *\n * Subcommands:\n * auth set <provider> [token] verify + store\n * auth unset <provider> remove\n * auth check <provider> re-verify a stored token\n * auth list every provider with a stored entry\n *\n * See `.notes/tech-auth-bootstrap.spec.md`.\n *\n * Verification lives in each plugin as a top-level `verifyToken(token)`\n * export. The auth command dynamically imports\n * `@theholocron/holocron-plugin-<provider>` and calls it. Plugins that\n * don't export `verifyToken` can still store — with a warning — because\n * \"no verify path\" shouldn't block credential storage.\n */\n\nimport { resolvePluginPackage } from \"../config.js\";\nimport { deleteToken, getToken, listStoredProviders, setToken } from \"../keyring.js\";\nimport { withSpinner } from \"../ui/progress.js\";\nimport { style } from \"../ui/style.js\";\n\n// ── Plugin-level export shapes (mirrored on every plugin) ────────────\n\nexport interface VerifyTokenSuccess {\n\tok: true;\n\t/** \"workplace: acme\" / \"user: cnewton@x\" — surfaced in success output. */\n\tsubject: string;\n}\n\nexport interface VerifyTokenFailure {\n\tok: false;\n\t/** Reason the token was rejected. Surfaces to the operator. */\n\tmessage: string;\n}\n\nexport type VerifyTokenResult = VerifyTokenSuccess | VerifyTokenFailure;\n\ninterface AuthPluginModule {\n\tverifyToken?: (token: string) => Promise<VerifyTokenResult>;\n\t/** One-line hint printed when no token was supplied. */\n\tAUTH_HINT?: string;\n}\n\nexport type AuthImporter = (packageName: string) => Promise<AuthPluginModule>;\n\nconst defaultImporter: AuthImporter = async (pkg) => (await import(pkg)) as AuthPluginModule;\n\n// ── Common types ─────────────────────────────────────────────────────\n\nexport type AuthPrint = (line: string) => void;\n\nexport interface AuthCommandStatus {\n\tstatus: \"ok\" | \"fail\" | \"skip\";\n\tmessage?: string;\n}\n\n// ── Token resolution ─────────────────────────────────────────────────\n\n/**\n * Resolve a token from (positional → HOLOCRON_<X> → vendor-native env).\n * Keyring is NOT consulted here — `auth set` writes TO the keyring, so\n * pulling FROM it would just re-store the same value.\n */\nexport function resolveAuthSetToken(input: {\n\tprovider: string;\n\tpositional?: string;\n\tenv?: NodeJS.ProcessEnv;\n}): string | null {\n\tconst env = input.env ?? process.env;\n\tconst upper = input.provider.toUpperCase();\n\tconst holocronKey = `HOLOCRON_${upper}_TOKEN`;\n\treturn input.positional || env[holocronKey] || env[upper + \"_TOKEN\"] || null;\n}\n\n// ── Subcommands ──────────────────────────────────────────────────────\n\nexport interface RunAuthSetInput {\n\tprovider: string;\n\tpositional?: string;\n\tenv?: NodeJS.ProcessEnv;\n\timporter?: AuthImporter;\n\tprint?: AuthPrint;\n\t/** When set, stores the token under `<provider>.<org>` in the keyring. */\n\torg?: string;\n}\n\nexport async function runAuthSet(input: RunAuthSetInput): Promise<AuthCommandStatus> {\n\tconst print = input.print ?? ((l: string) => console.log(l));\n\tconst importer = input.importer ?? defaultImporter;\n\tconst { provider } = input;\n\tconst keyringKey = input.org ? `${provider}.${input.org}` : provider;\n\n\tconst token = resolveAuthSetToken({ provider, positional: input.positional, env: input.env });\n\n\t// Feature sub-keys (e.g. \"github.read\") are stored directly — there is no\n\t// per-feature plugin package to load for verification.\n\tconst isFeatureKey = provider.includes(\".\");\n\tconst packageName = isFeatureKey ? null : resolvePluginPackage(provider);\n\n\tif (!token) {\n\t\tprint(style.fail(`no token supplied for \\`${keyringKey}\\`.`));\n\t\tprint(style.hint(` pass as positional arg: holocron auth set ${provider} <token>`));\n\t\tif (!isFeatureKey) {\n\t\t\tprint(\n\t\t\t\tstyle.hint(` or via env: HOLOCRON_${provider.toUpperCase()}_TOKEN / ${provider.toUpperCase()}_TOKEN`)\n\t\t\t);\n\t\t\tconst hint = await tryLoadHint(importer, packageName!);\n\t\t\tif (hint) {\n\t\t\t\tprint(style.hint(` hint: ${hint}`));\n\t\t\t}\n\t\t}\n\t\treturn { status: \"fail\", message: \"no token supplied\" };\n\t}\n\n\t// Verify via the plugin if it exports verifyToken (skipped for feature sub-keys).\n\tlet subject: string | undefined;\n\tif (!isFeatureKey && packageName) {\n\t\ttry {\n\t\t\tconst module = await importer(packageName);\n\t\t\tif (typeof module.verifyToken === \"function\") {\n\t\t\t\tconst verified = await module.verifyToken(token);\n\t\t\t\tif (!verified.ok) {\n\t\t\t\t\tprint(style.fail(`token rejected by ${provider}: ${verified.message}`));\n\t\t\t\t\tif (module.AUTH_HINT) print(style.hint(` hint: ${module.AUTH_HINT}`));\n\t\t\t\t\treturn { status: \"fail\", message: verified.message };\n\t\t\t\t}\n\t\t\t\tsubject = verified.subject;\n\t\t\t} else {\n\t\t\t\tprint(style.warn(`${provider} plugin has no verifyToken; storing without verification`));\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\tprint(style.warn(`cannot verify token — failed to load ${packageName}: ${msg}`));\n\t\t\tprint(\n\t\t\t\tstyle.hint(` storing token anyway; run 'holocron auth check ${provider}' once the plugin is installed`)\n\t\t\t);\n\t\t}\n\t}\n\n\tconst stored = setToken(keyringKey, token);\n\tif (!stored) {\n\t\tprint(style.fail(`keyring unavailable — token not stored. Use env vars instead.`));\n\t\treturn { status: \"fail\", message: \"keyring unavailable\" };\n\t}\n\n\tprint(style.success(`stored ${keyringKey} token${subject ? ` (${subject})` : \"\"}`));\n\treturn { status: \"ok\", ...(subject ? { message: subject } : {}) };\n}\n\nexport interface RunAuthUnsetInput {\n\tprovider: string;\n\tprint?: AuthPrint;\n}\n\nexport function runAuthUnset(input: RunAuthUnsetInput): AuthCommandStatus {\n\tconst print = input.print ?? ((l: string) => console.log(l));\n\tconst removed = deleteToken(input.provider);\n\tif (removed) {\n\t\tprint(style.success(`removed ${input.provider} token`));\n\t\treturn { status: \"ok\" };\n\t}\n\tprint(style.dim(`no stored token for ${input.provider}`));\n\treturn { status: \"skip\", message: \"nothing to remove\" };\n}\n\nexport interface RunAuthCheckInput {\n\tprovider: string;\n\timporter?: AuthImporter;\n\tprint?: AuthPrint;\n\t/** Set to false to suppress the ora spinner (e.g. when called from runAuthList). */\n\tshowSpinner?: boolean;\n\t/** When set, checks the token stored under `<provider>.<org>` in the keyring. */\n\torg?: string;\n}\n\nexport async function runAuthCheck(input: RunAuthCheckInput): Promise<AuthCommandStatus> {\n\tconst print = input.print ?? ((l: string) => console.log(l));\n\tconst importer = input.importer ?? defaultImporter;\n\tconst { provider } = input;\n\tconst keyringKey = input.org ? `${provider}.${input.org}` : provider;\n\n\tconst token = getToken(keyringKey);\n\tif (!token) {\n\t\tprint(style.dim(`no stored token for ${keyringKey}`));\n\t\treturn { status: \"skip\", message: \"no stored token\" };\n\t}\n\n\t// Feature sub-keys have no plugin to verify against — report stored only.\n\tif (provider.includes(\".\")) {\n\t\tprint(style.success(`${keyringKey}: token stored (feature key — no plugin verification)`));\n\t\treturn { status: \"ok\", message: \"stored\" };\n\t}\n\n\tconst packageName = resolvePluginPackage(provider);\n\ttry {\n\t\tconst module = await importer(packageName);\n\t\tif (typeof module.verifyToken !== \"function\") {\n\t\t\tprint(style.warn(`${keyringKey}: token stored (plugin has no verifyToken; can't confirm validity)`));\n\t\t\treturn { status: \"ok\", message: \"stored, unverified\" };\n\t\t}\n\t\tconst verify = () => module.verifyToken!(token);\n\t\tconst verified =\n\t\t\tinput.showSpinner !== false ? await withSpinner(`Verifying ${keyringKey} token…`, verify) : await verify();\n\t\tif (verified.ok) {\n\t\t\tprint(style.success(`${keyringKey}: ok — ${verified.subject}`));\n\t\t\treturn { status: \"ok\", message: verified.subject };\n\t\t}\n\t\tprint(style.fail(`${keyringKey}: rejected — ${verified.message}`));\n\t\tif (module.AUTH_HINT) print(style.hint(` hint: ${module.AUTH_HINT}`));\n\t\treturn { status: \"fail\", message: verified.message };\n\t} catch (err) {\n\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\tprint(style.fail(`${keyringKey}: cannot verify — ${msg}`));\n\t\treturn { status: \"fail\", message: msg };\n\t}\n}\n\nexport interface RunAuthListInput {\n\timporter?: AuthImporter;\n\tprint?: AuthPrint;\n}\n\nexport async function runAuthList(input: RunAuthListInput = {}): Promise<AuthCommandStatus> {\n\tconst print = input.print ?? ((l: string) => console.log(l));\n\tconst importer = input.importer ?? defaultImporter;\n\tconst providers = listStoredProviders();\n\n\tif (providers.length === 0) {\n\t\tprint(style.dim(\"no stored tokens.\"));\n\t\tprint(style.hint(\"run: holocron auth set <provider> <token>\"));\n\t\treturn { status: \"ok\", message: \"none\" };\n\t}\n\n\tfor (const provider of providers.sort()) {\n\t\tconst check = await runAuthCheck({ provider, importer, print: () => {}, showSpinner: false });\n\t\tconst label = `${provider}${check.message ? ` — ${check.message}` : \"\"}`;\n\t\tif (check.status === \"ok\") print(` ${style.success(label)}`);\n\t\telse if (check.status === \"fail\") print(` ${style.fail(label)}`);\n\t\telse print(` ${style.dim(`· ${label}`)}`);\n\t}\n\treturn { status: \"ok\" };\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nasync function tryLoadHint(importer: AuthImporter, packageName: string): Promise<string | null> {\n\ttry {\n\t\tconst module = await importer(packageName);\n\t\treturn module.AUTH_HINT ?? null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n","import { spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nimport { style } from \"../ui/style.js\";\n\nfunction encodeTokenForGitHttpAuth(token: string): string {\n\tconst trimmed = token.trim();\n\tif (!trimmed) throw new Error(\"empty token\");\n\t// eslint-disable-next-line no-control-regex\n\tif (/[\\u0000-\\u001F\\u007F\\s]/.test(trimmed)) {\n\t\tthrow new Error(\"token contains whitespace or control characters\");\n\t}\n\treturn encodeURIComponent(trimmed);\n}\n\ninterface GitHubRepo {\n\tname: string;\n\tfull_name: string;\n\tclone_url: string;\n\tarchived: boolean;\n}\n\ntype ExecFn = (cmd: string, args: string[], opts: { cwd: string }) => { status: number | null };\n\nexport interface RunCloneInput {\n\torg: string;\n\t/** Parent directory to clone into. Defaults to ~/Code/<org>. */\n\tdir?: string;\n\ttoken: string;\n\tdryRun?: boolean;\n\tfetch?: typeof globalThis.fetch;\n\texec?: ExecFn;\n\tprint?: (line: string) => void;\n}\n\nexport interface CloneReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n\tcloned: number;\n\tskipped: number;\n\tfailed: number;\n\tmessage?: string;\n}\n\nasync function listOrgRepos(org: string, token: string, fetchFn: typeof globalThis.fetch): Promise<GitHubRepo[]> {\n\tconst repos: GitHubRepo[] = [];\n\tlet url: string | null = `https://api.github.com/orgs/${org}/repos?per_page=100&type=all`;\n\n\twhile (url) {\n\t\tconst res = await fetchFn(url, {\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\tAccept: \"application/vnd.github+json\",\n\t\t\t\t\"X-GitHub-Api-Version\": \"2022-11-28\",\n\t\t\t},\n\t\t});\n\n\t\tif (!res.ok) {\n\t\t\tthrow new Error(`GitHub API ${res.status}: ${res.statusText} — check that the token has org:read scope`);\n\t\t}\n\n\t\trepos.push(...((await res.json()) as GitHubRepo[]));\n\n\t\tconst link = res.headers.get(\"link\");\n\t\tconst next = link?.match(/<([^>]+)>;\\s*rel=\"next\"/);\n\t\turl = next ? next[1] : null;\n\t}\n\n\treturn repos;\n}\n\nexport async function runClone(input: RunCloneInput): Promise<CloneReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst fetchFn = input.fetch ?? globalThis.fetch;\n\tconst dryRun = input.dryRun ?? false;\n\tconst targetDir = resolve(input.dir ?? join(homedir(), \"Code\", input.org));\n\tconst exec: ExecFn =\n\t\tinput.exec ??\n\t\t((cmd, args, opts) => {\n\t\t\tconst r = spawnSync(cmd, args, { cwd: opts.cwd, stdio: \"inherit\" });\n\t\t\treturn { status: r.status };\n\t\t});\n\n\tprint(style.header(`Holocron clone — org=${input.org} → ${targetDir}${dryRun ? \" (dry-run)\" : \"\"}`));\n\n\tif (!existsSync(targetDir)) {\n\t\tif (dryRun) {\n\t\t\tprint(style.dim(` would create ${targetDir}`));\n\t\t} else {\n\t\t\tmkdirSync(targetDir, { recursive: true });\n\t\t}\n\t}\n\n\tlet repos: GitHubRepo[];\n\ttry {\n\t\trepos = await listOrgRepos(input.org, input.token, fetchFn);\n\t} catch (err) {\n\t\treturn {\n\t\t\tstatus: \"fail\",\n\t\t\tcloned: 0,\n\t\t\tskipped: 0,\n\t\t\tfailed: 0,\n\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t};\n\t}\n\n\tlet cloned = 0;\n\tlet skipped = 0;\n\tlet failed = 0;\n\n\tfor (const repo of repos) {\n\t\t// Strip leading dot so hidden repos (e.g. .github) are visible in Finder.\n\t\tconst dirName = repo.name.startsWith(\".\") ? repo.name.slice(1) : repo.name;\n\t\tconst dest = join(targetDir, dirName);\n\n\t\tif (existsSync(dest)) {\n\t\t\tprint(style.dim(` skip ${repo.full_name}`));\n\t\t\tskipped++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (dryRun) {\n\t\t\tprint(style.dim(` would clone ${repo.full_name} → ${dest}`));\n\t\t\tcloned++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tprint(style.step(` clone ${repo.full_name}`));\n\t\tconst { clone_url } = repo;\n\t\tif (!clone_url.startsWith(\"https://github.com/\")) {\n\t\t\tprint(style.fail(` failed ${repo.full_name} — unexpected clone URL: ${clone_url}`));\n\t\t\tfailed++;\n\t\t\tcontinue;\n\t\t}\n\t\tlet encodedToken: string;\n\t\ttry {\n\t\t\tencodedToken = encodeTokenForGitHttpAuth(input.token);\n\t\t} catch (err) {\n\t\t\tprint(\n\t\t\t\tstyle.fail(\n\t\t\t\t\t` failed ${repo.full_name} — invalid token format: ${err instanceof Error ? err.message : String(err)}`\n\t\t\t\t)\n\t\t\t);\n\t\t\tfailed++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst authedUrl = `https://x-access-token:${encodedToken}@github.com/${clone_url.slice(\"https://github.com/\".length)}`;\n\t\tconst result = exec(\"git\", [\"clone\", \"--\", authedUrl, dest], { cwd: targetDir });\n\n\t\tif (result.status !== 0) {\n\t\t\tprint(style.fail(` failed ${repo.full_name}`));\n\t\t\tfailed++;\n\t\t} else {\n\t\t\tprint(style.success(` cloned ${repo.name}`));\n\t\t\tcloned++;\n\t\t}\n\t}\n\n\tconst summary = `${cloned} cloned, ${skipped} skipped, ${failed} failed`;\n\tprint(\n\t\tdryRun\n\t\t\t? style.dim(`\\n dry-run: ${summary}`)\n\t\t\t: failed > 0\n\t\t\t\t? style.fail(`\\n ${summary}`)\n\t\t\t\t: style.success(`\\n ${summary}`)\n\t);\n\n\treturn {\n\t\tstatus: dryRun ? \"dry-run\" : failed > 0 ? \"fail\" : \"ok\",\n\t\tcloned,\n\t\tskipped,\n\t\tfailed,\n\t};\n}\n","/**\n * `PluginLoader` — loads provider plugins per the resolved config and\n * builds a typed capability registry the runtime can query.\n *\n * Flow:\n * 1. Walk `config.providers[*]` from `resolveConfig()`\n * 2. For each entry, dynamic-import the resolved package name\n * (`@theholocron/holocron-plugin-<provider>` by default)\n * 3. Call the package's exported `createPlugin(options)` to get a\n * plugin object whose `capabilities` map holds factories\n * 4. Invoke the matching capability factory and stash the impl in\n * the registry — single-cardinality entries hold one impl,\n * many-cardinality entries hold an array\n *\n * A package may instead export a capability config (see\n * `CapabilityConfigPackage` in config.ts). The loader detects the shape\n * at import time and re-resolves to the underlying plugin, merging the\n * preset options with any per-project overrides from the config file\n * (project options win, mirroring ESLint's `extends` precedence).\n *\n * Loader keeps NO knowledge of vendor tokens. Each plugin reads its\n * own env vars (`HOLOCRON_ADMIN_TOKEN`, `HOLOCRON_VERCEL_TOKEN`, etc.)\n * inside its `createPlugin`. That keeps the loader vendor-agnostic\n * and the auth story per-plugin explicit.\n *\n * `importer` is injectable so tests don't need real network or\n * sibling packages installed.\n */\n\nimport type { CapabilityKey, CardinalityFor, ResolvedCapability } from \"./capabilities/index.js\";\nimport { CARDINALITY } from \"./capabilities/index.js\";\nimport type { CapabilityConfigPackage, ResolvedHolocronConfig, ResolvedTuple } from \"./config.js\";\nimport { resolvePluginPackage } from \"./config.js\";\n\n/**\n * Per-invocation context every plugin receives, on top of its own\n * config-time options. Kept intentionally narrow.\n */\nexport interface RuntimeContext {\n\t/** \"owner/name\" — the repo this invocation is operating on. */\n\trepo?: string;\n\t/** Absolute path to the working repo root. */\n\trepoRoot: string;\n\t/**\n\t * When true, commands print what they WOULD mutate instead of\n\t * actually calling capability mutators. Set by the global\n\t * `--dry-run` flag. Capabilities themselves are unaware — the check\n\t * lives at the command layer.\n\t */\n\tdryRun?: boolean;\n\t/**\n\t * Token passed via bare `--token <value>`. Used as fallback for all\n\t * plugins when no matching entry exists in `cliTokens`.\n\t */\n\tcliToken?: string;\n\t/**\n\t * Per-provider tokens from `--token vendor=value` pairs. The loader\n\t * routes each entry to the matching plugin (by `tuple.provider`) as\n\t * its `cliToken`, falling back to `cliToken` for unmatched providers.\n\t * Plugins never receive this map — they always see a single `cliToken`.\n\t */\n\tcliTokens?: Record<string, string>;\n\t/**\n\t * Active org name for namespaced keyring lookup. Resolved from\n\t * `--org` flag → `HOLOCRON_ORG` env var → `org` in config, then\n\t * injected here so plugins receive it via their options\n\t * (which extend `ResolveTokenInput`) without any per-plugin change.\n\t */\n\torg?: string;\n}\n\n/**\n * The shape every plugin's default-or-named export must satisfy:\n * `createPlugin(opts)` returns an object with capability factories.\n */\nexport interface LoadedPlugin {\n\tname: string;\n\tcapabilities: Partial<{\n\t\t[K in CapabilityKey]: () => unknown;\n\t}>;\n}\n\nexport interface PluginModule {\n\tcreatePlugin: (opts: Record<string, unknown>) => LoadedPlugin;\n}\n\n/** Returns `unknown` — the loader type-narrows inside `loadOne`. */\nexport type PluginImporter = (packageName: string) => Promise<unknown>;\n\nexport class LoaderError extends Error {\n\toverride name = \"LoaderError\";\n}\n\nexport class PluginLoader {\n\tprivate readonly registry = new Map<CapabilityKey, unknown>();\n\n\tconstructor(\n\t\tprivate readonly config: ResolvedHolocronConfig,\n\t\tprivate readonly context: RuntimeContext,\n\t\tprivate readonly importer: PluginImporter = defaultImporter\n\t) {}\n\n\t/** Imports every configured plugin and builds the capability registry. */\n\tasync load(): Promise<void> {\n\t\tconst entries = Object.entries(this.config.providers) as Array<\n\t\t\t[CapabilityKey, ResolvedHolocronConfig[\"providers\"][CapabilityKey]]\n\t\t>;\n\n\t\tfor (const [key, entry] of entries) {\n\t\t\tif (!entry) continue;\n\t\t\tif (entry.cardinality === \"single\") {\n\t\t\t\tthis.registry.set(key, await this.loadOne(key, entry.tuple));\n\t\t\t} else {\n\t\t\t\tconst impls = [];\n\t\t\t\tfor (const tuple of entry.tuples) {\n\t\t\t\t\timpls.push(await this.loadOne(key, tuple));\n\t\t\t\t}\n\t\t\t\tthis.registry.set(key, impls);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Type-safe lookup. Single-cardinality keys return one impl;\n\t * many-cardinality keys return an array. `ResolvedCapability<K>`\n\t * encodes the split via the `CARDINALITY` map.\n\t */\n\tget<K extends CapabilityKey>(key: K): ResolvedCapability<K> {\n\t\tconst impl = this.registry.get(key);\n\t\tif (impl === undefined) {\n\t\t\tthrow new LoaderError(`capability \\`${key}\\` is not loaded — is it declared in holocron.config.json?`);\n\t\t}\n\t\treturn impl as ResolvedCapability<K>;\n\t}\n\n\t/** Whether a capability has been loaded. */\n\thas<K extends CapabilityKey>(key: K): boolean {\n\t\treturn this.registry.has(key);\n\t}\n\n\t/** All capability keys currently loaded. Useful for the doctor command. */\n\tloadedKeys(): CapabilityKey[] {\n\t\treturn Array.from(this.registry.keys());\n\t}\n\n\t/** Internal — invoke a plugin's capability factory and return the impl. */\n\tprivate async loadOne(key: CapabilityKey, tuple: ResolvedTuple): Promise<unknown> {\n\t\tconst mod = await this.importer(tuple.packageName).catch((err: unknown) => {\n\t\t\tthrow new LoaderError(\n\t\t\t\t`failed to import \\`${tuple.packageName}\\` for capability \\`${key}\\`: ${\n\t\t\t\t\terr instanceof Error ? err.message : String(err)\n\t\t\t\t}`\n\t\t\t);\n\t\t});\n\n\t\t// Plugin package: exports createPlugin(opts) → { capabilities }\n\t\tif (isPluginModule(mod)) {\n\t\t\t// Resolve the effective token for this specific plugin.\n\t\t\t// cliTokens[provider] wins over the bare cliToken fallback.\n\t\t\tconst effectiveToken = this.context.cliTokens?.[tuple.provider] ?? this.context.cliToken;\n\n\t\t\t// Precedence (later wins): project-level defaults from config →\n\t\t\t// runtime context (CLI flags: --repo, --token) → per-plugin\n\t\t\t// resolved token → tuple options (per-plugin overrides in config).\n\t\t\t// cliTokens is explicitly cleared so the map never reaches plugins.\n\t\t\tconst plugin = mod.createPlugin({\n\t\t\t\t...this.projectDefaults(),\n\t\t\t\t...this.context,\n\t\t\t\t...(effectiveToken !== undefined ? { cliToken: effectiveToken } : {}),\n\t\t\t\tcliTokens: undefined,\n\t\t\t\t...tuple.options,\n\t\t\t});\n\t\t\tconst factory = plugin.capabilities[key];\n\t\t\tif (typeof factory !== \"function\") {\n\t\t\t\tthrow new LoaderError(`\\`${tuple.packageName}\\` does not implement the \\`${key}\\` capability`);\n\t\t\t}\n\t\t\treturn factory();\n\t\t}\n\n\t\t// Capability config package: default export is { provider, options? }.\n\t\t// Re-resolve to the underlying plugin; preset options are the base,\n\t\t// per-project tuple options override them (ESLint extends precedence).\n\t\tif (isCapabilityConfigModule(mod)) {\n\t\t\tconst cap = (mod as { default: CapabilityConfigPackage }).default;\n\t\t\treturn this.loadOne(key, {\n\t\t\t\tprovider: cap.provider,\n\t\t\t\tpackageName: resolvePluginPackage(cap.provider),\n\t\t\t\toptions: { ...cap.options, ...tuple.options },\n\t\t\t});\n\t\t}\n\n\t\tthrow new LoaderError(\n\t\t\t`\\`${tuple.packageName}\\` does not export \\`createPlugin(options)\\` or a capability config ({ provider, options? })`\n\t\t);\n\t}\n\n\t/**\n\t * Project-level defaults that get merged into every plugin's options\n\t * unless overridden by the CLI context or per-plugin tuple options.\n\t * See `.notes/tech-setup-and-config.spec.md` §Design.\n\t */\n\tprivate projectDefaults(): Partial<RuntimeContext> {\n\t\tconst defaults: Partial<RuntimeContext> = {};\n\t\tif (this.config.repo?.name) defaults.repo = this.config.repo.name;\n\t\treturn defaults;\n\t}\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\n/** Default importer — native dynamic import. */\nconst defaultImporter: PluginImporter = async (pkg) => {\n\treturn import(pkg);\n};\n\nfunction isPluginModule(mod: unknown): mod is PluginModule {\n\treturn typeof (mod as PluginModule).createPlugin === \"function\";\n}\n\nfunction isCapabilityConfigModule(mod: unknown): mod is { default: CapabilityConfigPackage } {\n\tconst def = (mod as { default?: unknown }).default;\n\treturn typeof (def as CapabilityConfigPackage)?.provider === \"string\";\n}\n\n/** Convenience re-export so callers can compute counts without importing CARDINALITY directly. */\nexport function cardinalityOf<K extends CapabilityKey>(key: K): CardinalityFor<K> {\n\treturn CARDINALITY[key];\n}\n","/**\n * `holocron deploy` — trigger a deployment via the configured\n * `deployment` capability.\n *\n * Errors clearly when `deployment` isn't loaded (no provider declared\n * in `holocron.config.json`). Returns the resulting deployment record\n * so callers can print the URL + status.\n *\n * Dry-run skips the actual triggerDeployment call but still verifies\n * the deployment capability is present, so operators can sanity-check\n * the wiring without spinning up a build.\n */\n\nimport type { Deployment, DeploymentRecord, DeploymentTrigger } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport { withSpinner } from \"../ui/progress.js\";\nimport { style } from \"../ui/style.js\";\n\nexport type DeployPrintLine = (line: string) => void;\n\nexport interface RunDeployInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** Vendor project id (e.g., Vercel prj_*). Required. */\n\tprojectId: string;\n\t/** Git branch to deploy. */\n\tbranch: string;\n\t/** Named target — `undefined` means branch preview. */\n\ttarget?: DeploymentTrigger;\n\tloader?: PluginLoader;\n\tprint?: DeployPrintLine;\n}\n\nexport interface DeployReport {\n\t/** Null in dry-run mode (no actual deployment was triggered). */\n\tdeployment: DeploymentRecord | null;\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n\tmessage?: string;\n}\n\nexport async function runDeploy(input: RunDeployInput): Promise<DeployReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait loader.load();\n\n\tconst dryRun = input.context.dryRun ?? false;\n\n\tprint(\n\t\tstyle.header(\n\t\t\t`Holocron deploy — branch=${input.branch}${\n\t\t\t\tinput.target ? `, target=${input.target}` : \" (preview)\"\n\t\t\t}${dryRun ? \" (dry-run)\" : \"\"}`\n\t\t)\n\t);\n\n\tif (!loader.has(\"deployment\")) {\n\t\tthrow new Error(\n\t\t\t\"deployment capability is not configured — add a `deployment` provider to holocron.config.json\"\n\t\t);\n\t}\n\tconst deploy = loader.get(\"deployment\") as Deployment;\n\n\tif (dryRun) {\n\t\tconst message = `would: ${deploy.providerName}.triggerDeployment(projectId=${input.projectId}, branch=${input.branch}${\n\t\t\tinput.target ? `, target=${input.target}` : \"\"\n\t\t})`;\n\t\tprint(` ${style.dim(`… ${message}`)}`);\n\t\treturn { deployment: null, status: \"dry-run\", message };\n\t}\n\n\ttry {\n\t\tconst record = await withSpinner(`Deploying ${input.branch}${input.target ? ` → ${input.target}` : \"\"}…`, () =>\n\t\t\tdeploy.triggerDeployment({\n\t\t\t\tprojectId: input.projectId,\n\t\t\t\tbranch: input.branch,\n\t\t\t\t...(input.target ? { target: input.target } : {}),\n\t\t\t})\n\t\t);\n\t\tprint(` ${style.success(`${record.status} — ${record.url}`)}`);\n\t\treturn { deployment: record, status: \"ok\" };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tprint(` ${style.fail(message)}`);\n\t\treturn { deployment: null, status: \"fail\", message };\n\t}\n}\n","/**\n * `holocron doctor` — load the config, instantiate every capability,\n * print a per-capability readiness report.\n *\n * Each capability gets a smoke check appropriate to its surface:\n * source → `whoami()`\n * issues → `doctor()` (rich report)\n * secrets → `listSecrets({ kind: 'repo' })`\n * ci → `listRuns({ limit: 1 })`\n * others → just \"loaded\" (no smoke endpoint defined yet)\n *\n * Output is plain text via a passed-in `print` function so tests can\n * capture lines without ANSI / spinner noise.\n */\n\nimport type { Auth, Ci, Issues, Secrets, Source, Vault } from \"../capabilities/index.js\";\nimport { CARDINALITY } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport { withSpinner } from \"../ui/progress.js\";\nimport { style } from \"../ui/style.js\";\n\nexport type DoctorPrintLine = (line: string) => void;\n\nexport type DoctorStatus = \"ok\" | \"fail\" | \"skip\";\n\nexport interface DoctorRow {\n\tcapability: string;\n\tprovider: string;\n\tstatus: DoctorStatus;\n\tmessage: string;\n}\n\nexport interface DoctorReport {\n\trows: DoctorRow[];\n\tsummary: { ok: number; fail: number; skip: number };\n}\n\nexport interface RunDoctorInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** Lets tests inject mock plugins; defaults to native dynamic import. */\n\tloader?: PluginLoader;\n\tprint?: DoctorPrintLine;\n}\n\nexport async function runDoctor(input: RunDoctorInput): Promise<DoctorReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait withSpinner(\"Loading plugins…\", () => loader.load());\n\n\tconst rows: DoctorRow[] = [];\n\tconst config = input.loaded.resolved;\n\n\tprint(style.header(`Holocron doctor — ${config.name}`));\n\tprint(style.dim(` config: ${input.loaded.filepath}`));\n\tprint(\"\");\n\n\tfor (const key of loader.loadedKeys()) {\n\t\tconst cardinality = CARDINALITY[key];\n\t\tconst entry = config.providers[key];\n\t\tconst providers =\n\t\t\tentry?.cardinality === \"many\"\n\t\t\t\t? entry.tuples.map((t) => t.provider)\n\t\t\t\t: entry?.cardinality === \"single\"\n\t\t\t\t\t? [entry.tuple.provider]\n\t\t\t\t\t: [];\n\n\t\tif (cardinality === \"many\") {\n\t\t\tconst impls = loader.get(key) as unknown as unknown[];\n\t\t\timpls.forEach((_impl, idx) => {\n\t\t\t\trows.push({\n\t\t\t\t\tcapability: key,\n\t\t\t\t\tprovider: providers[idx] ?? \"?\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"loaded (no smoke check defined for this capability)\",\n\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\tconst impl = loader.get(key) as unknown;\n\t\t\tconst row = await smokeCheck(key, providers[0] ?? \"?\", impl);\n\t\t\trows.push(row);\n\t\t}\n\t}\n\n\t// Render rows\n\tfor (const row of rows) {\n\t\tconst label = `${pad(row.capability, 14)} via ${pad(row.provider, 14)} ${row.message}`;\n\t\tif (row.status === \"ok\") print(` ${style.success(label)}`);\n\t\telse if (row.status === \"fail\") print(` ${style.fail(label)}`);\n\t\telse print(` ${style.dim(`· ${label}`)}`);\n\t}\n\n\tconst summary = rows.reduce(\n\t\t(acc, r) => {\n\t\t\tacc[r.status] += 1;\n\t\t\treturn acc;\n\t\t},\n\t\t{ ok: 0, fail: 0, skip: 0 }\n\t);\n\n\tconst summaryLine = `${summary.ok} ok, ${summary.fail} fail, ${summary.skip} skipped`;\n\tprint(\"\");\n\tprint(summary.fail > 0 ? style.fail(summaryLine) : style.success(summaryLine));\n\n\treturn { rows, summary };\n}\n\n// ── smoke checks ────────────────────────────────────────────────────\n\nasync function smokeCheck(key: string, provider: string, impl: unknown): Promise<DoctorRow> {\n\ttry {\n\t\tswitch (key) {\n\t\t\tcase \"source\": {\n\t\t\t\tconst result = await (impl as Source).whoami();\n\t\t\t\treturn mk(key, provider, \"ok\", `whoami: ${result.login}`);\n\t\t\t}\n\t\t\tcase \"issues\": {\n\t\t\t\tconst report = await (impl as Issues).doctor();\n\t\t\t\treturn mk(\n\t\t\t\t\tkey,\n\t\t\t\t\tprovider,\n\t\t\t\t\t\"ok\",\n\t\t\t\t\t`${report.authedAs} / ${report.projectLabel} (${countResolvedLifecycle(report)})`\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase \"secrets\": {\n\t\t\t\tconst names = await (impl as Secrets).listSecrets({ kind: \"repo\" });\n\t\t\t\treturn mk(key, provider, \"ok\", `repo secrets: ${names.length} configured`);\n\t\t\t}\n\t\t\tcase \"ci\": {\n\t\t\t\tconst runs = await (impl as Ci).listRuns({ limit: 1 });\n\t\t\t\treturn mk(\n\t\t\t\t\tkey,\n\t\t\t\t\tprovider,\n\t\t\t\t\t\"ok\",\n\t\t\t\t\truns.length === 0 ? \"no recent runs\" : `most recent: ${runs[0]!.workflowName} (${runs[0]!.status})`\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase \"vault\": {\n\t\t\t\tconst keys = await (impl as Vault).list();\n\t\t\t\treturn mk(key, provider, \"ok\", `${keys.length} keys available`);\n\t\t\t}\n\t\t\tcase \"auth\": {\n\t\t\t\tconst desc = await (impl as Auth).describe();\n\t\t\t\treturn mk(key, provider, \"ok\", `provider: ${desc.provider}; env keys: ${desc.envKeys.join(\", \")}`);\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn mk(key, provider, \"skip\", \"loaded (no smoke check defined for this capability)\");\n\t\t}\n\t} catch (err) {\n\t\treturn mk(key, provider, \"fail\", err instanceof Error ? err.message : String(err));\n\t}\n}\n\nfunction countResolvedLifecycle(report: Awaited<ReturnType<Issues[\"doctor\"]>>): string {\n\tconst resolved = report.lifecycle.filter((l) => l.resolved).length;\n\treturn `${resolved}/${report.lifecycle.length} lifecycle slots ready`;\n}\n\nfunction mk(capability: string, provider: string, status: DoctorStatus, message: string): DoctorRow {\n\treturn { capability, provider, status, message };\n}\n\nfunction pad(s: string, width: number): string {\n\treturn s.length >= width ? s : s + \" \".repeat(width - s.length);\n}\n","/**\n * `holocron new <type> <name>` — create a GitHub repo from a template and\n * bootstrap it by replacing all template-slug casing variants with the new\n * project name, then generate a `holocron.config.ts` from the answers given\n * during the interactive wizard.\n *\n * Flow:\n * 1. Preflight — verify `gh` CLI is available.\n * 2. Resolve type, name, description, homepage, vault/deployment/agent options.\n * 3. `gh repo create <org>/<name> --template <org>/<type>-template --private --clone`\n * → clones to `<cwd>/<name>/`\n * 4. Detect template slug from cloned package.json.\n * 5. Replace all casing variants of the slug across every text file.\n * 6. Replace `<description>` and `<homepage>` placeholders.\n * 7. Generate and write `holocron.config.ts` based on wizard answers.\n * 8. Commit the patched files (-s for DCO).\n * 9. Unless --no-verify: `pnpm install` in the new repo.\n * 10. Print next steps.\n */\n\nimport { execFileSync, spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\n// ── Public API ────────────────────────────────────────────────────────\n\nexport type VaultProvider = \"doppler\" | \"1password\" | \"infisical\" | \"none\";\nexport type DeploymentProvider = \"vercel\" | \"none\";\nexport type AgentChoice = \"claude\" | \"none\";\nexport type RuntimeEnvironment = \"node\" | \"browser\" | \"universal\" | \"none\";\n\nexport interface RunNewInput {\n\ttype: string;\n\tname: string;\n\tdescription?: string;\n\thomepage?: string;\n\tvaultProvider?: VaultProvider;\n\tvaultProject?: string;\n\tvaultConfig?: string;\n\tdeploymentProvider?: DeploymentProvider;\n\tagent?: AgentChoice;\n\truntimeEnvironment?: RuntimeEnvironment;\n\tprotection?: string;\n\topenSource?: boolean;\n\tusesExternalPackages?: boolean;\n\ttopics?: string[];\n\tskills?: string[];\n\t/** Mark the new repo as a GitHub template repository. */\n\tisTemplate?: boolean;\n\t/** GitHub org that owns both the template and the new repo. Default: \"theholocron\". */\n\torg?: string;\n\t/** GitHub admin token forwarded to `holocron setup` during verify. */\n\ttoken?: string;\n\tdryRun?: boolean;\n\tnoVerify?: boolean;\n\t/** Parent directory where the repo will be cloned. Default: process.cwd(). */\n\tcwd?: string;\n\tprint?: (line: string) => void;\n\t/** Injectable subprocess runner for testing. */\n\texec?: (cmd: string, args: string[], opts: { cwd: string; stdio: \"inherit\"; env?: Record<string, string> }) => void;\n\t/** Injectable file writer for testing. */\n\twriteFile?: (filepath: string, content: string) => void;\n\t/** Injectable file reader for testing (returns utf-8 string). */\n\treadFile?: (filepath: string) => string;\n\t/** Injectable directory walker for testing (returns absolute paths). */\n\twalkFiles?: (dir: string) => string[];\n}\n\nexport interface NewReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n\trepoDir?: string;\n\tfilesPatched?: string[];\n\tmessage?: string;\n}\n\nexport class NewError extends Error {\n\toverride name = \"NewError\";\n}\n\n// ── Case derivation ───────────────────────────────────────────────────\n\nfunction cap(word: string): string {\n\treturn word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();\n}\n\n/**\n * Derive all common casing variants of a kebab-case slug (e.g.\n * \"cli-template\") and map each to the corresponding form of a\n * kebab-case name (e.g. \"my-tool\").\n *\n * Returns search→replacement pairs, deduplicating single-word slugs\n * that would otherwise produce identical entries.\n */\nexport function deriveVariants(slug: string, name: string): Array<[string, string]> {\n\tconst sw = slug.split(\"-\");\n\tconst nw = name.split(\"-\");\n\n\tconst pairs: Array<[string, string]> = [\n\t\t[slug, name],\n\t\t[sw.join(\"_\"), nw.join(\"_\")],\n\t\t[sw.join(\"_\").toUpperCase(), nw.join(\"_\").toUpperCase()],\n\t\t[sw.map(cap).join(\"\"), nw.map(cap).join(\"\")],\n\t\t[sw[0]!.toLowerCase() + sw.slice(1).map(cap).join(\"\"), nw[0]!.toLowerCase() + nw.slice(1).map(cap).join(\"\")],\n\t\t[sw.map(cap).join(\" \"), nw.map(cap).join(\" \")],\n\t];\n\n\tconst seen = new Set<string>();\n\treturn pairs.filter(([s]) => {\n\t\tif (seen.has(s)) return false;\n\t\tseen.add(s);\n\t\treturn true;\n\t});\n}\n\n// ── Input helpers ─────────────────────────────────────────────────────\n\n/** Validate a repo name: must be lowercase kebab-case. Returns `true` on success or an error string. */\nexport function validateRepoName(v: string): true | string {\n\treturn /^[a-z][a-z0-9-]*$/.test(v.trim()) ? true : \"Must be lowercase kebab-case (e.g. my-tool)\";\n}\n\n/** Parse a comma-separated topics string into a trimmed, non-empty array. */\nexport function parseTopics(raw: string | undefined): string[] {\n\treturn raw\n\t\t? String(raw)\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((t) => t.trim())\n\t\t\t\t.filter(Boolean)\n\t\t: [];\n}\n\n// ── Config generation ─────────────────────────────────────────────────\n\nexport interface HolocronConfigOptions {\n\tname: string;\n\ttype: string;\n\torg?: string;\n\tdescription?: string;\n\thomepage?: string;\n\tvaultProvider?: VaultProvider;\n\tvaultProject?: string;\n\tvaultConfig?: string;\n\tdeploymentProvider?: DeploymentProvider;\n\tagent?: AgentChoice;\n\truntimeEnvironment?: RuntimeEnvironment;\n\tprotection?: string;\n\topenSource?: boolean;\n\tusesExternalPackages?: boolean;\n\ttopics?: string[];\n\tskills?: string[];\n}\n\n/**\n * Generate the content of `holocron.config.ts` for a newly-scaffolded repo.\n * Uses the `node()` preset from `@theholocron/holocron-config` as the baseline\n * and layers in the provider/agent choices made during the wizard.\n */\nexport function generateHolocronConfig(opts: HolocronConfigOptions): string {\n\tconst lines: string[] = [\n\t\t`import { defineConfig } from \"@theholocron/cli\";`,\n\t\t`import { node } from \"@theholocron/holocron-config\";`,\n\t\t``,\n\t\t`const { repo, workflows, providers } = node();`,\n\t\t`export default defineConfig({`,\n\t];\n\n\tif (opts.description) lines.push(`\\tdescription: ${JSON.stringify(opts.description)},`);\n\tif (opts.homepage) lines.push(`\\thomepage: ${JSON.stringify(opts.homepage)},`);\n\n\tconst topics = opts.topics?.length ? opts.topics : [];\n\tconst hasRuntimeOverride = opts.runtimeEnvironment != null && opts.runtimeEnvironment !== \"node\";\n\tconst hasFullRepo = opts.org != null;\n\n\tif (hasFullRepo) {\n\t\t// Full explicit repo block when org is known (always the case from the CLI).\n\t\tconst repoName = `${opts.org}/${opts.name}`;\n\t\tlines.push(`\\trepo: {`);\n\t\tlines.push(`\\t\\tname: ${JSON.stringify(repoName)},`);\n\t\tlines.push(`\\t\\tteams: [{ slug: \"gatekeepers\", permission: \"maintain\" }],`);\n\t\tlines.push(`\\t\\ttopics: ${JSON.stringify(topics)},`);\n\t\tlines.push(`\\t\\t...repo,`);\n\t\tif (opts.protection && opts.protection !== \"strict\") {\n\t\t\tlines.push(`\\t\\tprotection: ${JSON.stringify(opts.protection)},`);\n\t\t}\n\t\tconst propParts: string[] = [];\n\t\tif (hasRuntimeOverride) propParts.push(`runtime_environment: ${JSON.stringify(opts.runtimeEnvironment)}`);\n\t\tif (opts.openSource === false) propParts.push(`open_source: false`);\n\t\tif (opts.usesExternalPackages === false) propParts.push(`uses_external_packages: false`);\n\t\tif (propParts.length > 0) {\n\t\t\tlines.push(`\\t\\tproperties: { ...repo.properties, ${propParts.join(\", \")} },`);\n\t\t}\n\t\tlines.push(`\\t},`);\n\t} else if (topics.length > 0 || hasRuntimeOverride) {\n\t\tlines.push(`\\trepo: {`);\n\t\tif (topics.length > 0) lines.push(`\\t\\ttopics: ${JSON.stringify(topics)},`);\n\t\tlines.push(`\\t\\t...repo,`);\n\t\tif (hasRuntimeOverride) {\n\t\t\tlines.push(\n\t\t\t\t`\\t\\tproperties: { ...repo.properties, runtime_environment: ${JSON.stringify(opts.runtimeEnvironment)} },`\n\t\t\t);\n\t\t}\n\t\tlines.push(`\\t},`);\n\t} else {\n\t\tlines.push(`\\trepo,`);\n\t}\n\n\tlines.push(`\\tworkflows,`);\n\n\tconst hasVault = opts.vaultProvider && opts.vaultProvider !== \"none\";\n\tconst hasDeployment = opts.deploymentProvider && opts.deploymentProvider !== \"none\";\n\n\tif (hasVault || hasDeployment) {\n\t\tlines.push(`\\tproviders: {`);\n\t\tlines.push(`\\t\\t...providers,`);\n\t\tif (opts.vaultProvider === \"doppler\") {\n\t\t\tconst proj = JSON.stringify(opts.vaultProject ?? opts.name);\n\t\t\tconst cfg = JSON.stringify(opts.vaultConfig ?? \"dev\");\n\t\t\tlines.push(`\\t\\tvault: [\"doppler\", { project: ${proj}, config: ${cfg} }],`);\n\t\t} else if (opts.vaultProvider === \"1password\") {\n\t\t\tconst vault = JSON.stringify(opts.vaultProject ?? opts.name);\n\t\t\tlines.push(`\\t\\tvault: [\"1password\", { vault: ${vault} }],`);\n\t\t} else if (opts.vaultProvider === \"infisical\") {\n\t\t\tconst proj = JSON.stringify(opts.vaultProject ?? opts.name);\n\t\t\tlines.push(`\\t\\tvault: [\"infisical\", { project: ${proj} }],`);\n\t\t}\n\t\tif (opts.deploymentProvider === \"vercel\") {\n\t\t\tlines.push(`\\t\\tdeployment: \"vercel\",`);\n\t\t}\n\t\tlines.push(`\\t},`);\n\t} else {\n\t\tlines.push(`\\tproviders,`);\n\t}\n\n\tif (opts.agent && opts.agent !== \"none\") {\n\t\tlines.push(`\\tagent: ${JSON.stringify(opts.agent)},`);\n\t}\n\n\tif (opts.skills?.length) {\n\t\tlines.push(`\\tskills: ${JSON.stringify(opts.skills)},`);\n\t}\n\n\tlines.push(`});`);\n\tlines.push(``);\n\n\treturn lines.join(\"\\n\");\n}\n\n// ── File discovery ────────────────────────────────────────────────────\n\nconst SKIP_DIRS = new Set([\".git\", \"node_modules\", \"dist\", \".turbo\"]);\n\nfunction defaultWalkFiles(dir: string): string[] {\n\tconst results: string[] = [];\n\tfor (const entry of readdirSync(dir)) {\n\t\tif (SKIP_DIRS.has(entry)) continue;\n\t\tconst full = path.join(dir, entry);\n\t\tconst stat = statSync(full);\n\t\tif (stat.isDirectory()) results.push(...defaultWalkFiles(full));\n\t\telse if (stat.isFile()) results.push(full);\n\t}\n\treturn results;\n}\n\nfunction isBinary(content: string): boolean {\n\tfor (let i = 0; i < Math.min(content.length, 8000); i++) {\n\t\tif (content.charCodeAt(i) === 0) return true;\n\t}\n\treturn false;\n}\n\n// ── Patching ──────────────────────────────────────────────────────────\n\nfunction patchFiles(\n\tdir: string,\n\tvariants: Array<[string, string]>,\n\tdescription: string | undefined,\n\thomepage: string | undefined,\n\truntimeEnvironment: string | undefined,\n\tprint: (line: string) => void,\n\treadFn: (p: string) => string,\n\twriteFn: (p: string, c: string) => void,\n\twalkFn: (d: string) => string[]\n): string[] {\n\tconst patched: string[] = [];\n\tfor (const filepath of walkFn(dir)) {\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = readFn(filepath);\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tif (isBinary(content)) continue;\n\n\t\tconst original = content;\n\t\tfor (const [search, replacement] of variants) {\n\t\t\tcontent = content.split(search).join(replacement);\n\t\t}\n\t\tif (description !== undefined) {\n\t\t\tcontent = content.split(\"<description>\").join(description);\n\t\t\t// Also replace the content of <!-- holocron:description --> blocks so\n\t\t\t// the README description marker is updated even when the template has\n\t\t\t// real prose rather than a bare <description> placeholder.\n\t\t\tcontent = content.replace(\n\t\t\t\t/(<!-- holocron:description -->)[\\s\\S]*?(<!-- \\/holocron:description -->)/g,\n\t\t\t\t`$1\\n${description}\\n$2`\n\t\t\t);\n\t\t}\n\t\tif (homepage !== undefined) {\n\t\t\tcontent = content.split(\"<homepage>\").join(homepage);\n\t\t}\n\t\tif (runtimeEnvironment !== undefined) {\n\t\t\tcontent = content.split(\"<runtime_environment>\").join(runtimeEnvironment);\n\t\t}\n\t\t// Strip template-only blocks — sections relevant only to the template\n\t\t// repo itself (e.g. \"Getting Started\" scaffolding instructions) that\n\t\t// should not appear in projects generated from the template.\n\t\tcontent = content.replace(\n\t\t\t/\\n?<!-- holocron:template-only -->[\\s\\S]*?<!-- \\/holocron:template-only -->\\n?/g,\n\t\t\t\"\"\n\t\t);\n\n\t\tif (content !== original) {\n\t\t\twriteFn(filepath, content);\n\t\t\tprint(` ✓ ${path.relative(dir, filepath)}`);\n\t\t\tpatched.push(filepath);\n\t\t}\n\t}\n\treturn patched;\n}\n\n// ── Preflight ─────────────────────────────────────────────────────────\n\nfunction preflight(): void {\n\tconst result = spawnSync(\"gh\", [\"--version\"], { encoding: \"utf8\" });\n\tif (result.error != null || result.status !== 0) {\n\t\tthrow new NewError(\"`gh` CLI is not installed or not on PATH. Install it from https://cli.github.com\");\n\t}\n}\n\n// ── Defaults ──────────────────────────────────────────────────────────\n\nfunction defaultExec(\n\tcmd: string,\n\targs: string[],\n\topts: { cwd: string; stdio: \"inherit\"; env?: Record<string, string> }\n): void {\n\texecFileSync(cmd, args, {\n\t\tcwd: opts.cwd,\n\t\tstdio: opts.stdio,\n\t\t...(opts.env && Object.keys(opts.env).length > 0 ? { env: { ...process.env, ...opts.env } } : {}),\n\t});\n}\n\nfunction keychainLookup(key: string): string | undefined {\n\tconst result = spawnSync(\"security\", [\"find-generic-password\", \"-s\", \"com.theholocron.cli\", \"-a\", key, \"-w\"], {\n\t\tencoding: \"utf8\",\n\t});\n\treturn result.status === 0 ? result.stdout?.trim() || undefined : undefined;\n}\n\nfunction defaultReadFile(filepath: string): string {\n\treturn readFileSync(filepath, \"utf-8\");\n}\n\nfunction defaultWriteFile(filepath: string, content: string): void {\n\tmkdirSync(path.dirname(filepath), { recursive: true });\n\twriteFileSync(filepath, content, \"utf-8\");\n}\n\n// ── Orchestrator ──────────────────────────────────────────────────────\n\nexport async function runNew(input: RunNewInput): Promise<NewReport> {\n\tconst cwd = input.cwd ?? process.cwd();\n\tconst org = input.org ?? \"theholocron\";\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst execFn = input.exec ?? defaultExec;\n\tconst readFn = input.readFile ?? defaultReadFile;\n\tconst writeFn = input.writeFile ?? defaultWriteFile;\n\tconst walkFn = input.walkFiles ?? defaultWalkFiles;\n\n\tpreflight();\n\n\tconst templateRepo = `${org}/${input.type}-template`;\n\tconst newRepo = `${org}/${input.name}`;\n\tconst repoDir = path.join(cwd, input.name);\n\n\tif (input.dryRun) {\n\t\tprint(` Would create ${newRepo} from template ${templateRepo}`);\n\t\tprint(` Would clone to ${repoDir}`);\n\t\tprint(` Would patch all casing variants of \"${input.type}-template\" → \"${input.name}\"`);\n\t\tif (input.description) print(` Would replace <description> → \"${input.description}\"`);\n\t\tif (input.homepage) print(` Would replace <homepage> → \"${input.homepage}\"`);\n\t\tif (input.runtimeEnvironment) print(` Would replace <runtime_environment> → \"${input.runtimeEnvironment}\"`);\n\t\tprint(` Would generate holocron.config.ts`);\n\t\treturn { status: \"dry-run\" };\n\t}\n\n\tif (existsSync(repoDir)) {\n\t\tthrow new NewError(`\\`${repoDir}\\` already exists — delete it or pick a different name.`);\n\t}\n\n\tprint(` Creating ${newRepo} from template ${templateRepo}…`);\n\tconst visibility = input.openSource ? \"--public\" : \"--private\";\n\ttry {\n\t\texecFn(\"gh\", [\"repo\", \"create\", newRepo, `--template=${templateRepo}`, visibility, \"--clone\"], {\n\t\t\tcwd,\n\t\t\tstdio: \"inherit\",\n\t\t});\n\t} catch (err) {\n\t\tthrow new NewError(`gh repo create failed: ${err instanceof Error ? err.message : String(err)}`);\n\t}\n\n\tif (input.isTemplate) {\n\t\ttry {\n\t\t\texecFn(\"gh\", [\"repo\", \"edit\", newRepo, \"--template=true\"], { cwd, stdio: \"inherit\" });\n\t\t} catch {\n\t\t\t// non-fatal — template flag can be set manually in repo settings\n\t\t}\n\t}\n\n\t// gh repo create --template does not reliably honor --public/--private on all\n\t// plan/org combinations, so set visibility explicitly after creation.\n\ttry {\n\t\texecFn(\"gh\", [\"repo\", \"edit\", newRepo, `--visibility=${input.openSource ? \"public\" : \"private\"}`], {\n\t\t\tcwd,\n\t\t\tstdio: \"inherit\",\n\t\t});\n\t} catch {\n\t\t// non-fatal — visibility can be changed manually in repo settings\n\t}\n\n\t// Detect template slug from cloned package.json\n\tlet templateSlug = `${input.type}-template`;\n\tconst pkgJsonPath = path.join(repoDir, \"package.json\");\n\tif (existsSync(pkgJsonPath)) {\n\t\ttry {\n\t\t\tconst pkg = JSON.parse(readFn(pkgJsonPath)) as { name?: string };\n\t\t\tif (typeof pkg.name === \"string\") {\n\t\t\t\ttemplateSlug = pkg.name.split(\"/\").at(-1) || templateSlug;\n\t\t\t}\n\t\t} catch {\n\t\t\t// fall back to derived slug\n\t\t}\n\t}\n\n\tprint(` Detected template slug: ${templateSlug}`);\n\tprint(` Patching files…`);\n\n\tconst variants = deriveVariants(templateSlug, input.name);\n\t// Prepend the full org/slug pair so GitHub URLs and scoped package names\n\t// use the correct org. Must come before the slug-only pairs so it takes\n\t// priority — e.g. \"@theholocron/node-template\" becomes \"@<org>/<name>\"\n\t// rather than \"@theholocron/<name>\".\n\tvariants.unshift([`theholocron/${templateSlug}`, `${org}/${input.name}`]);\n\tconst filesPatched = patchFiles(\n\t\trepoDir,\n\t\tvariants,\n\t\tinput.description,\n\t\tinput.homepage,\n\t\tinput.runtimeEnvironment,\n\t\tprint,\n\t\treadFn,\n\t\twriteFn,\n\t\twalkFn\n\t);\n\n\tprint(` ${filesPatched.length} file${filesPatched.length === 1 ? \"\" : \"s\"} patched`);\n\n\t// Always overwrite description and homepage in package.json directly,\n\t// regardless of whether the template used placeholders or real values.\n\tif (input.description !== undefined || input.homepage !== undefined) {\n\t\ttry {\n\t\t\tconst pkg = JSON.parse(readFn(pkgJsonPath)) as Record<string, unknown>;\n\t\t\tif (input.description !== undefined) pkg[\"description\"] = input.description;\n\t\t\tif (input.homepage !== undefined) pkg[\"homepage\"] = input.homepage;\n\t\t\twriteFn(pkgJsonPath, JSON.stringify(pkg, null, 2) + \"\\n\");\n\t\t\tprint(` ✓ package.json (description/homepage)`);\n\t\t} catch {\n\t\t\t// non-fatal — placeholder replacement already covered it\n\t\t}\n\t}\n\n\t// Update the root tsconfig.json \"display\" field by parsing the JSON directly\n\t// rather than relying on a <display_name> placeholder. Templates can use their\n\t// real human-readable display name; we always overwrite it with the title-case\n\t// of the new repo name on scaffolding.\n\tconst displayName = input.name.split(\"-\").map(cap).join(\" \");\n\tconst rootTsconfigPath = path.join(repoDir, \"tsconfig.json\");\n\ttry {\n\t\tconst tsconfig = JSON.parse(readFn(rootTsconfigPath)) as Record<string, unknown>;\n\t\tif (typeof tsconfig[\"display\"] === \"string\") {\n\t\t\ttsconfig[\"display\"] = displayName;\n\t\t\twriteFn(rootTsconfigPath, JSON.stringify(tsconfig, null, 2) + \"\\n\");\n\t\t\tprint(` ✓ tsconfig.json (display)`);\n\t\t}\n\t} catch {\n\t\t// non-fatal — no tsconfig or no display field\n\t}\n\n\t// Generate and write holocron.config.ts\n\tconst configContent = generateHolocronConfig({\n\t\tname: input.name,\n\t\ttype: input.type,\n\t\torg,\n\t\tdescription: input.description,\n\t\thomepage: input.homepage,\n\t\tvaultProvider: input.vaultProvider,\n\t\tvaultProject: input.vaultProject,\n\t\tvaultConfig: input.vaultConfig,\n\t\tdeploymentProvider: input.deploymentProvider,\n\t\tagent: input.agent,\n\t\truntimeEnvironment: input.runtimeEnvironment,\n\t\tprotection: input.protection,\n\t\topenSource: input.openSource,\n\t\tusesExternalPackages: input.usesExternalPackages,\n\t\ttopics: input.topics,\n\t\tskills: input.skills,\n\t});\n\tconst configPath = path.join(repoDir, \"holocron.config.ts\");\n\twriteFn(configPath, configContent);\n\tprint(` Generated holocron.config.ts`);\n\n\texecFn(\"git\", [\"add\", \"-A\"], { cwd: repoDir, stdio: \"inherit\" });\n\texecFn(\"git\", [\"commit\", \"-s\", \"-m\", `chore: bootstrap from ${templateSlug}`], {\n\t\tcwd: repoDir,\n\t\tstdio: \"inherit\",\n\t});\n\n\tif (!input.noVerify) {\n\t\tprint(\"\");\n\t\tprint(\" Installing dependencies…\");\n\t\ttry {\n\t\t\texecFn(\"pnpm\", [\"install\"], { cwd: repoDir, stdio: \"inherit\" });\n\t\t} catch (err) {\n\t\t\tprint(` ✗ pnpm install failed — ${err instanceof Error ? err.message : String(err)}`);\n\t\t\treturn {\n\t\t\t\tstatus: \"fail\",\n\t\t\t\trepoDir,\n\t\t\t\tfilesPatched,\n\t\t\t\tmessage: \"pnpm install failed; inspect output above\",\n\t\t\t};\n\t\t}\n\n\t\tprint(\"\");\n\t\tprint(\" Running holocron setup…\");\n\t\ttry {\n\t\t\tconst setupArgs: string[] = [\"setup\"];\n\t\t\tconst setupEnv: Record<string, string> = {};\n\n\t\t\t// Admin token: drives rulesets, repo settings, workflows, Pages.\n\t\t\t// Prefer the value forwarded via --token; fall back to keychain.\n\t\t\tconst adminToken = input.token ?? keychainLookup(\"github.admin\");\n\t\t\tif (adminToken) setupArgs.push(\"--token\", adminToken);\n\n\t\t\t// Org token: drives team assignments and custom properties.\n\t\t\t// Skip keychain if already in env (subprocess inherits it anyway).\n\t\t\tif (!process.env[\"HOLOCRON_ORG_TOKEN\"]) {\n\t\t\t\tconst orgToken = keychainLookup(\"github.org\");\n\t\t\t\tif (orgToken) setupEnv[\"HOLOCRON_ORG_TOKEN\"] = orgToken;\n\t\t\t}\n\n\t\t\t// Deploy token: drives GitHub Pages configuration.\n\t\t\tif (!process.env[\"HOLOCRON_DEPLOY_TOKEN\"]) {\n\t\t\t\tconst deployToken = keychainLookup(\"github.deploy\");\n\t\t\t\tif (deployToken) setupEnv[\"HOLOCRON_DEPLOY_TOKEN\"] = deployToken;\n\t\t\t}\n\n\t\t\texecFn(\"holocron\", setupArgs, { cwd: repoDir, stdio: \"inherit\", env: setupEnv });\n\t\t} catch {\n\t\t\tprint(\" ✗ holocron setup failed — run it manually after checking your config\");\n\t\t}\n\t}\n\n\tprint(\"\");\n\tprint(` Scaffolded ${newRepo} (${filesPatched.length} file${filesPatched.length === 1 ? \"\" : \"s\"} patched).`);\n\tprint(\"\");\n\tprint(\" Next:\");\n\tprint(` 1. cd ${repoDir}`);\n\tif (input.noVerify) {\n\t\tprint(` 2. pnpm install`);\n\t\tprint(` 3. holocron setup # wire up secrets, teams, labels, etc.`);\n\t\tprint(` 4. git push -u origin HEAD`);\n\t} else {\n\t\tprint(` 2. git push -u origin HEAD`);\n\t}\n\n\treturn { status: \"ok\", repoDir, filesPatched };\n}\n","import { readdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface RunNpmBumpVersionsInput {\n\t/** Next version string (e.g., \"4.2.0\" or \"2.0.0-alpha.1\"). */\n\tversion: string;\n\t/** Working directory (monorepo root). Defaults to process.cwd(). */\n\tcwd?: string;\n\t/** Print what would change without writing anything. */\n\tdryRun?: boolean;\n\tprint?: (line: string) => void;\n\t/** Injectable for testing. */\n\treadFile?: (path: string) => string;\n\twriteFile?: (path: string, content: string) => void;\n\tlistDir?: (path: string) => string[];\n\tisDir?: (path: string) => boolean;\n}\n\nexport type BumpVersionsStatus = \"ok\" | \"fail\" | \"dry-run\";\n\nexport interface NpmBumpVersionsReport {\n\tstatus: BumpVersionsStatus;\n\tbumped: readonly string[];\n\tskipped: readonly string[];\n\tmessage?: string;\n}\n\nexport async function runNpmBumpVersions(input: RunNpmBumpVersionsInput): Promise<NpmBumpVersionsReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst cwd = input.cwd ?? process.cwd();\n\tconst { version, dryRun = false } = input;\n\tconst readFile = input.readFile ?? ((p: string) => readFileSync(p, \"utf8\"));\n\tconst writeFile = input.writeFile ?? ((p: string, c: string) => writeFileSync(p, c));\n\tconst listDir = input.listDir ?? ((p: string) => readdirSync(p) as string[]);\n\tconst isDir = input.isDir ?? ((p: string) => statSync(p).isDirectory());\n\n\tconst bumped: string[] = [];\n\tconst skipped: string[] = [];\n\n\tprint(`Bumping monorepo to ${version}${dryRun ? \" (dry-run)\" : \"\"}…`);\n\n\tfunction bumpFile(absPath: string, label: string): void {\n\t\tlet pkg: Record<string, unknown>;\n\t\ttry {\n\t\t\tpkg = JSON.parse(readFile(absPath)) as Record<string, unknown>;\n\t\t} catch {\n\t\t\tprint(` ✗ could not parse ${label}`);\n\t\t\treturn;\n\t\t}\n\t\tconst old = pkg.version as string;\n\t\tif (!dryRun) {\n\t\t\tpkg.version = version;\n\t\t\twriteFile(absPath, JSON.stringify(pkg, null, 2) + \"\\n\");\n\t\t}\n\t\tprint(` ${dryRun ? \"~\" : \"✓\"} ${label}: ${old} → ${version}`);\n\t\tbumped.push(label);\n\t}\n\n\t// Root is always bumped — private means \"don't publish\", not \"don't version\".\n\tbumpFile(join(cwd, \"package.json\"), \"root\");\n\n\tconst packagesDir = join(cwd, \"packages\");\n\tlet entries: string[];\n\ttry {\n\t\tentries = listDir(packagesDir);\n\t} catch {\n\t\t// No packages/ dir — single-package repo; root bump is sufficient.\n\t\treturn { status: dryRun ? \"dry-run\" : \"ok\", bumped, skipped };\n\t}\n\n\tfor (const entry of entries) {\n\t\tconst pkgDir = join(packagesDir, entry);\n\t\ttry {\n\t\t\tif (!isDir(pkgDir)) continue;\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tconst pkgFile = join(pkgDir, \"package.json\");\n\t\tlet pkg: Record<string, unknown>;\n\t\ttry {\n\t\t\tpkg = JSON.parse(readFile(pkgFile)) as Record<string, unknown>;\n\t\t} catch {\n\t\t\tprint(` ! skipping packages/${entry}: no package.json or malformed JSON`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (pkg.private) {\n\t\t\tprint(` · skipping private package packages/${entry}`);\n\t\t\tskipped.push(`packages/${entry}`);\n\t\t\tcontinue;\n\t\t}\n\t\tbumpFile(pkgFile, `packages/${entry}`);\n\t}\n\n\treturn { status: dryRun ? \"dry-run\" : \"ok\", bumped, skipped };\n}\n","/**\n * `holocron npm publish-initial` — bottles up the chicken-and-egg\n * bootstrap that every new npm-published holocron monorepo hits.\n *\n * npm requires a package to exist before Trusted Publishing can be\n * configured on it. So the first publish has to happen outside the\n * OIDC flow — using either a browser-auth session (`npm login\n * --auth-type=web`) or an ephemeral automation token. This command\n * runs the publish step + tells you exactly what to do next.\n *\n * Workflow:\n *\n * $ npm login --auth-type=web # one-time, browser-based\n * $ pnpm install --frozen-lockfile\n * $ pnpm build\n * $ pnpm exec tsx packages/cli/src/cli.ts npm publish-initial\n *\n * The command itself only handles the publish step + the post-publish\n * Trusted Publisher setup reminder. `pnpm install` + `pnpm build`\n * stay outside the command (no pnpm-inside-pnpm).\n *\n * If `NPM_TOKEN` is detected in env, the command prints a final\n * \"revoke this token at <url>\" reminder — same pattern as `rando vc\n * setup` for the ephemeral GH admin PAT.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type PublishInitialPrint = (line: string) => void;\n\nexport type PublishExecResult = {\n\texitCode: number;\n\tstdout: string;\n\tstderr: string;\n};\n\nexport interface RunNpmPublishInitialInput {\n\t/** Working directory (the monorepo root). Defaults to process.cwd(). */\n\tcwd?: string;\n\t/** Distribution tag for the publish. Defaults to `'alpha'`. */\n\ttag?: string;\n\t/** Skip the actual publish; print what would happen. */\n\tdryRun?: boolean;\n\t/**\n\t * One-time password (TOTP) from your authenticator app. Required if\n\t * your npm account has \"Require 2FA for read and write\" enabled.\n\t * Reused across all 7 sequential publishes — they fire within a few\n\t * seconds, comfortably inside the TOTP window.\n\t */\n\totp?: string;\n\tprint?: PublishInitialPrint;\n\t/**\n\t * Injectable command runner. Defaults to `spawnSync` with\n\t * `stdio: ['inherit', 'pipe', 'pipe']` so interactive prompts\n\t * (e.g., npm OTP) still work.\n\t *\n\t * Returns exit code + captured stdout/stderr.\n\t */\n\texec?: (cmd: string, args: string[], opts: { cwd: string }) => Promise<PublishExecResult>;\n\t/** Env vars; passed in for testability. Defaults to process.env. */\n\tenv?: NodeJS.ProcessEnv;\n\t/**\n\t * Override the list of package names shown in the Trusted Publisher\n\t * next-steps output. Auto-discovered from packages/*\\/package.json\n\t * when omitted.\n\t */\n\tpackages?: readonly string[];\n\t/**\n\t * Override the repo name shown in the Trusted Publisher next-steps\n\t * output. Auto-detected from `git remote get-url origin` when omitted.\n\t */\n\trepoName?: string;\n}\n\nexport type PublishInitialStatus = \"ok\" | \"fail\" | \"dry-run\";\n\nexport interface NpmPublishInitialReport {\n\tstatus: PublishInitialStatus;\n\tmessage?: string;\n\t/** Packages that the publish step targeted. */\n\tpackageNames: readonly string[];\n}\n\nexport async function runNpmPublishInitial(input: RunNpmPublishInitialInput = {}): Promise<NpmPublishInitialReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst cwd = input.cwd ?? process.cwd();\n\tconst tag = input.tag ?? \"alpha\";\n\tconst dryRun = input.dryRun ?? false;\n\tconst otp = input.otp;\n\tconst env = input.env ?? process.env;\n\tconst exec = input.exec ?? defaultExec;\n\n\t// Build the publish args once — shared between dry-run preview and\n\t// the real call so what we print is exactly what we'd run.\n\tconst publishArgs = [\n\t\t\"-r\",\n\t\t\"--filter=./packages/*\",\n\t\t\"publish\",\n\t\t\"--access\",\n\t\t\"public\",\n\t\t\"--no-git-checks\",\n\t\t\"--tag\",\n\t\ttag,\n\t\t...(otp ? [\"--otp\", otp] : []),\n\t];\n\n\tprint(`Holocron npm publish-initial${dryRun ? \" (dry-run)\" : \"\"}`);\n\tprint(` cwd: ${cwd}`);\n\tprint(` tag: ${tag}`);\n\tif (otp) print(` otp: <${otp.length} chars>`);\n\tprint(\"\");\n\n\t// ── 1. Verify npm auth ──────────────────────────────────────────────\n\tprint(\" → verifying npm auth (`npm whoami`)…\");\n\tconst whoami = await exec(\"npm\", [\"whoami\"], { cwd });\n\tif (whoami.exitCode !== 0) {\n\t\tconst message =\n\t\t\t\"npm is not authenticated. Run `npm login --auth-type=web` (browser flow, no token stored) or `npm login`, then re-run this command.\";\n\t\tprint(` ✗ ${message}`);\n\t\tconst packageNames = input.packages ?? discoverPublicPackages(cwd);\n\t\treturn { status: \"fail\", message, packageNames };\n\t}\n\tconst whoamiName = whoami.stdout.trim() || \"<unknown>\";\n\tprint(` ✓ authed as ${whoamiName}`);\n\n\t// ── 2. Resolve dynamic values needed for next-steps ─────────────────\n\tconst packageNames = input.packages ?? discoverPublicPackages(cwd);\n\tconst repoName = input.repoName ?? (await resolveRepoName(cwd, exec));\n\n\t// ── 3. Publish ──────────────────────────────────────────────────────\n\tif (dryRun) {\n\t\tprint(\"\");\n\t\tprint(\" … (dry-run) skipping actual publish\");\n\t\tprint(` would run: pnpm ${publishArgs.join(\" \")}`);\n\t\tprintNextSteps(print, env, packageNames, repoName);\n\t\treturn { status: \"dry-run\", message: \"dry-run — no publish executed\", packageNames };\n\t}\n\n\tprint(\"\");\n\tprint(\" → publishing all public @theholocron/* packages…\");\n\tconst publish = await exec(\"pnpm\", publishArgs, { cwd });\n\tif (publish.exitCode !== 0) {\n\t\tconst message = `publish failed (exit ${publish.exitCode}): ${publish.stderr.trim() || publish.stdout.trim() || \"no output\"}`;\n\t\tprint(` ✗ ${message}`);\n\t\t// Detect EOTP and surface the --otp hint right at the failure.\n\t\tif (publish.stdout.includes(\"EOTP\") || publish.stderr.includes(\"EOTP\")) {\n\t\t\tprint(\"\");\n\t\t\tprint(\" → hint: your npm account requires 2FA for writes. Re-run with `--otp <code>`:\");\n\t\t\tprint(` pnpm exec tsx packages/cli/src/cli.ts npm publish-initial --otp <6-digit-code>`);\n\t\t}\n\t\treturn { status: \"fail\", message, packageNames };\n\t}\n\tprint(\" ✓ publish complete\");\n\n\t// ── 4. Next-step reminders ──────────────────────────────────────────\n\tprintNextSteps(print, env, packageNames, repoName);\n\treturn { status: \"ok\", packageNames };\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nfunction discoverPublicPackages(cwd: string): readonly string[] {\n\tconst packagesDir = join(cwd, \"packages\");\n\tif (!existsSync(packagesDir)) return [];\n\treturn readdirSync(packagesDir, { withFileTypes: true })\n\t\t.filter((e) => e.isDirectory())\n\t\t.flatMap((e) => {\n\t\t\tconst pkgPath = join(packagesDir, e.name, \"package.json\");\n\t\t\tif (!existsSync(pkgPath)) return [];\n\t\t\ttry {\n\t\t\t\tconst pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as {\n\t\t\t\t\tname?: string;\n\t\t\t\t\tprivate?: boolean;\n\t\t\t\t};\n\t\t\t\treturn !pkg.private && pkg.name ? [pkg.name] : [];\n\t\t\t} catch {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t});\n}\n\nasync function resolveRepoName(cwd: string, exec: NonNullable<RunNpmPublishInitialInput[\"exec\"]>): Promise<string> {\n\tconst result = await exec(\"git\", [\"remote\", \"get-url\", \"origin\"], { cwd });\n\tif (result.exitCode !== 0) return \"unknown\";\n\t// Matches both HTTPS (https://github.com/org/repo.git) and\n\t// SSH (git@github.com:org/repo.git) remote URL formats.\n\tconst match = /[/:]([^/:]+?)(?:\\.git)?$/.exec(result.stdout.trim());\n\treturn match?.[1] ?? \"unknown\";\n}\n\nfunction printNextSteps(\n\tprint: PublishInitialPrint,\n\tenv: NodeJS.ProcessEnv,\n\tpackageNames: readonly string[],\n\trepoName: string\n): void {\n\tprint(\"\");\n\tprint(\" → next: configure Trusted Publisher for each package on npm:\");\n\tfor (const name of packageNames) {\n\t\tprint(` https://www.npmjs.com/package/${name}/access`);\n\t}\n\tprint(` Publisher: GitHub Actions Org: theholocron Repo: ${repoName} Workflow: release.yml`);\n\n\tif (env.NPM_TOKEN) {\n\t\tprint(\"\");\n\t\tprint(\" → cleanup: $NPM_TOKEN was used. Revoke it now (no API for self-revoke; UI-only):\");\n\t\tprint(\" https://www.npmjs.com/settings/~/tokens\");\n\t}\n}\n\nconst defaultExec: NonNullable<RunNpmPublishInitialInput[\"exec\"]> = async (cmd, args, opts) => {\n\tconst result = spawnSync(cmd, args, {\n\t\tcwd: opts.cwd,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"inherit\", \"pipe\", \"pipe\"],\n\t});\n\treturn {\n\t\texitCode: result.status ?? -1,\n\t\tstdout: result.stdout ?? \"\",\n\t\tstderr: result.stderr ?? \"\",\n\t};\n};\n","/**\n * Shared input record for every template module.\n *\n * Every template exports `(inputs: TemplateInputs) => string` and reads\n * from this record. Keeping the surface small + typechecked lets the\n * templates stay dumb string builders while the command layer handles\n * normalization + defaulting from user input.\n */\n\nimport type { CapabilityKey } from \"../../capabilities/index.js\";\n\nexport interface TemplateInputs {\n\t/** Package slug — e.g., \"clerk\". Lowercase, kebab-case. */\n\tslug: string;\n\t/** Vendor display name — e.g., \"Clerk\". PascalCase. */\n\tvendorName: string;\n\t/** Vendor slug UPPERCASED — e.g., \"CLERK\". Used for env var names + class prefixes. */\n\tvendorUpper: string;\n\t/** Capability the plugin implements — one of the 14 known keys. */\n\tcapability: CapabilityKey;\n\t/** Capability implementation class name — e.g., \"ClerkAuth\". PascalCase. */\n\tcapabilityClass: string;\n\t/** Holocron-namespaced env var — defaults to `HOLOCRON_<VENDOR_UPPER>_TOKEN`. */\n\ttokenEnv: string;\n\t/** Vendor-native env var — e.g., \"CLERK_SECRET_KEY\". */\n\tvendorEnv: string;\n\t/** REST base URL — e.g., \"https://api.clerk.com/v1\". */\n\tbaseUrl: string;\n\t/** Transport. Only \"rest\" is supported in Phase 1 (spec: #77). */\n\ttransport: \"rest\";\n}\n\n/** Derive the standard defaults from a slug + vendor name. */\nexport function deriveDefaults(input: {\n\tslug: string;\n\tvendorName: string;\n\tcapability: CapabilityKey;\n}): Pick<TemplateInputs, \"vendorUpper\" | \"capabilityClass\" | \"tokenEnv\" | \"transport\"> {\n\tconst vendorUpper = input.slug.toUpperCase().replace(/-/g, \"_\");\n\tconst capability = input.capability;\n\tconst capabilityClass = `${input.vendorName}${capability.charAt(0).toUpperCase() + capability.slice(1)}`;\n\treturn {\n\t\tvendorUpper,\n\t\tcapabilityClass,\n\t\ttokenEnv: `HOLOCRON_${vendorUpper}_TOKEN`,\n\t\ttransport: \"rest\",\n\t};\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `import { AuthError, createResolveToken, type ResolveTokenInput } from \"@theholocron/cli\";\n\nexport { AuthError };\nexport type { ResolveTokenInput };\n\nexport const resolveToken = createResolveToken({\n\\tenvName: \"${inputs.tokenEnv}\",\n\\tvendorEnvName: \"${inputs.vendorEnv}\",\n\\tkeyringService: \"${inputs.slug}\",\n\\terrorMessage:\n\\t\\t\"no ${inputs.vendorName} token found. Pass --token <TOKEN>, set ${inputs.tokenEnv} / ${inputs.vendorEnv}, \" +\n\\t\\t\"or run: holocron auth set ${inputs.slug} <TOKEN>\",\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `import { describe, expect, it } from \"vitest\";\n\nimport { AuthError, resolveToken } from \"../auth.js\";\n\nconst noKeyring = () => null;\n\ndescribe(\"resolveToken\", () => {\n\tit(\"prefers --token over env vars + keyring\", () => {\n\t\texpect(\n\t\t\tresolveToken({\n\t\t\t\tcliToken: \"flag\",\n\t\t\t\tenv: { ${inputs.tokenEnv}: \"hlc\", ${inputs.vendorEnv}: \"vendor\" },\n\t\t\t\tkeyring: () => \"kr\",\n\t\t\t})\n\t\t).toBe(\"flag\");\n\t});\n\n\tit(\"prefers ${inputs.tokenEnv} over ${inputs.vendorEnv}\", () => {\n\t\texpect(\n\t\t\tresolveToken({\n\t\t\t\tenv: { ${inputs.tokenEnv}: \"hlc\", ${inputs.vendorEnv}: \"vendor\" },\n\t\t\t\tkeyring: noKeyring,\n\t\t\t})\n\t\t).toBe(\"hlc\");\n\t});\n\n\tit(\"falls back to ${inputs.vendorEnv} when ${inputs.tokenEnv} is unset\", () => {\n\t\texpect(resolveToken({ env: { ${inputs.vendorEnv}: \"vendor\" }, keyring: noKeyring })).toBe(\"vendor\");\n\t});\n\n\tit(\"falls back to keyring when env vars are unset\", () => {\n\t\texpect(resolveToken({ env: {}, keyring: (p) => (p === \"${inputs.slug}\" ? \"kr\" : null) })).toBe(\"kr\");\n\t});\n\n\tit(\"throws AuthError with a helpful message when nothing is set\", () => {\n\t\ttry {\n\t\t\tresolveToken({ env: {}, keyring: noKeyring });\n\t\t\tthrow new Error(\"should have thrown\");\n\t\t} catch (err) {\n\t\t\texpect(err).toBeInstanceOf(AuthError);\n\t\t\texpect((err as Error).message).toMatch(/${inputs.tokenEnv}/);\n\t\t\texpect((err as Error).message).toMatch(/holocron auth set ${inputs.slug}/);\n\t\t}\n\t});\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst clientClass = `${inputs.vendorName}RestClient`;\n\tconst capabilityInterface = inputs.capability.charAt(0).toUpperCase() + inputs.capability.slice(1);\n\treturn `/**\n * \\`${inputs.capability}\\` capability for ${inputs.vendorName}.\n *\n * Methods are STUBS — implement them against ${inputs.vendorName}'s\n * REST API per the \\`${capabilityInterface}\\` interface contract in\n * \\`@theholocron/cli\\`.\n *\n * TODO once you've stubbed the interface methods, restore the type\n * import + \\`implements\\` clause:\n * import type { ${capabilityInterface} } from \"@theholocron/cli\";\n * export class ${inputs.capabilityClass} implements ${capabilityInterface} { ... }\n */\n\nimport type { ${clientClass} } from \"../rest.js\";\n\nexport class ${inputs.capabilityClass} {\n\treadonly key = \"${inputs.capability}\" as const;\n\treadonly providerName = \"${inputs.slug}\";\n\n\tconstructor(private readonly rest: ${clientClass}) {}\n\n\t// TODO: implement the ${capabilityInterface} interface methods\n\t// (see \\`packages/cli/src/capabilities/index.ts\\`). Each method\n\t// should hit a specific ${inputs.vendorName} REST endpoint via\n\t// \\`this.rest.request(...)\\`. Once methods are stubbed, add\n\t// \\`implements ${capabilityInterface}\\` to the class declaration\n\t// above and remove the \\`as unknown as\\` cast in src/index.ts.\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst clientClass = `${inputs.vendorName}RestClient`;\n\treturn `import { describe, it } from \"vitest\";\n\nimport { ${inputs.capabilityClass} } from \"../capabilities/${inputs.capability}.js\";\nimport { ${clientClass} } from \"../rest.js\";\nimport { stubFetch } from \"./helpers.js\";\n\n// Stub client used by the constructor smoke test. Real capability\n// tests replace this with per-method stubs once implementations land.\nfunction makeCapability() {\n\tconst stub = stubFetch([]);\n\tconst rest = new ${clientClass}({ token: \"t\", fetch: stub.fetch });\n\treturn new ${inputs.capabilityClass}(rest);\n}\n\ndescribe(\"${inputs.capabilityClass}\", () => {\n\tit(\"constructs with a REST client\", () => {\n\t\tmakeCapability();\n\t});\n\n\t// TODO: implement one test per ${inputs.capability} capability method\n\t// as you fill in the class stubs. See other plugins for reference\n\t// patterns:\n\t// - REST behaviors (URL / method / body / query) via \\`stub.calls\\`\n\t// - Error paths via \\`stubFetch([{ status: 4xx, body: {...} }])\\`\n\t// - Idempotency (409 handling for ensure* methods, if applicable)\n\tit.todo(\"implement per-method tests\");\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(_inputs: TemplateInputs): string {\n\treturn `import root from \"../../eslint.config.js\";\n\nexport default [\n\t...root,\n\t{\n\t\tignores: [\"dist/**\", \"coverage/**\"],\n\t},\n];\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(_inputs: TemplateInputs): string {\n\treturn `import { vi, type Mock } from \"vitest\";\n\nexport interface FetchCall {\n\turl: string;\n\tmethod: string;\n\theaders: Record<string, string>;\n\tbody: unknown;\n}\n\nexport interface FetchStub {\n\tfetch: typeof fetch;\n\tcalls: FetchCall[];\n\tmock: Mock;\n}\n\nexport function stubFetch(responses: Array<{ status?: number; body?: unknown; text?: string }>): FetchStub {\n\tconst calls: FetchCall[] = [];\n\tlet i = 0;\n\tconst mock = vi.fn(async (input: string | URL, init?: RequestInit) => {\n\t\tconst url = typeof input === \"string\" ? input : input.toString();\n\t\tconst body = typeof init?.body === \"string\" ? safeJsonParse(init.body) : (init?.body ?? null);\n\t\tcalls.push({\n\t\t\turl,\n\t\t\tmethod: (init?.method ?? \"GET\").toUpperCase(),\n\t\t\theaders: (init?.headers as Record<string, string>) ?? {},\n\t\t\tbody,\n\t\t});\n\t\tconst next = responses[i++] ?? { status: 200, body: {} };\n\t\tconst status = next.status ?? 200;\n\t\tif (status === 204 || status === 205 || status === 304) {\n\t\t\treturn new Response(null, { status });\n\t\t}\n\t\tconst text = next.text ?? (typeof next.body === \"string\" ? next.body : JSON.stringify(next.body ?? {}));\n\t\treturn new Response(text, { status });\n\t});\n\treturn { fetch: mock as unknown as typeof fetch, calls, mock };\n}\n\nfunction safeJsonParse(s: string): unknown {\n\ttry {\n\t\treturn JSON.parse(s);\n\t} catch {\n\t\treturn s;\n\t}\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `import { describe, expect, it } from \"vitest\";\n\nimport { AUTH_HINT, createPlugin } from \"../index.js\";\nimport { stubFetch } from \"./helpers.js\";\n\ndescribe(\"createPlugin\", () => {\n\tit(\"wires the ${inputs.capability} capability against the given fetch + token\", () => {\n\t\tconst stub = stubFetch([]);\n\t\tconst plugin = createPlugin({\n\t\t\tcliToken: \"test-token\",\n\t\t\tfetch: stub.fetch,\n\t\t});\n\t\texpect(plugin.name).toBe(\"@theholocron/holocron-plugin-${inputs.slug}\");\n\t\texpect(typeof plugin.capabilities.${inputs.capability}).toBe(\"function\");\n\t});\n});\n\ndescribe(\"AUTH_HINT\", () => {\n\tit(\"mentions the holocron auth set command\", () => {\n\t\texpect(AUTH_HINT).toMatch(/holocron auth set ${inputs.slug}/);\n\t});\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `{\n \"name\": \"@theholocron/holocron-plugin-${inputs.slug}\",\n \"version\": \"2.0.0-alpha.1\",\n \"description\": \"Holocron plugin for ${inputs.vendorName}. Implements the ${inputs.capability} capability against ${inputs.vendorName}'s REST API, plus exports verifyToken + AUTH_HINT for \\`holocron auth\\`.\",\n \"homepage\": \"https://github.com/theholocron/holocron/tree/main/packages/holocron-plugin-${inputs.slug}#readme\",\n \"bugs\": \"https://github.com/theholocron/holocron/issues\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/theholocron/holocron.git\",\n \"directory\": \"packages/holocron-plugin-${inputs.slug}\"\n },\n \"license\": \"MIT\",\n \"author\": \"Newton Koumantzelis\",\n \"type\": \"module\",\n \"main\": \"./src/index.ts\",\n \"exports\": {\n \".\": \"./src/index.ts\"\n },\n \"scripts\": {\n \"build\": \"tsdown\",\n \"lint\": \"eslint .\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"validate\": \"tsx scripts/validate.mjs\"\n },\n \"peerDependencies\": {\n \"@theholocron/cli\": \"workspace:*\"\n },\n \"devDependencies\": {\n \"@theholocron/cli\": \"workspace:*\",\n \"@theholocron/tsconfig\": \"catalog:\",\n \"@tsconfig/node-lts\": \"catalog:\",\n \"@vitest/coverage-v8\": \"catalog:\",\n \"eslint\": \"catalog:\",\n \"globals\": \"catalog:\",\n \"typescript\": \"catalog:\",\n \"vitest\": \"catalog:\",\n \"tsdown\": \"catalog:\",\n \"tsx\": \"catalog:\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"main\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.mts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.mts\",\n \"import\": \"./dist/index.mjs\",\n \"default\": \"./dist/index.mjs\"\n }\n }\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ]\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst clientClass = `${inputs.vendorName}RestClient`;\n\t// Camel-case capability name is used as the factory function name.\n\tconst capabilityInterface = inputs.capability.charAt(0).toUpperCase() + inputs.capability.slice(1);\n\treturn `/**\n * \\`@theholocron/holocron-plugin-${inputs.slug}\\` — entrypoint.\n *\n * Implements the \\`${inputs.capability}\\` capability against ${inputs.vendorName}'s\n * REST API. Also exports \\`verifyToken\\` + \\`AUTH_HINT\\` for\n * \\`holocron auth\\`. See README for auth + config docs.\n *\n * TODO: once you fill in the ${inputs.capabilityClass} methods and add\n * \\`implements ${capabilityInterface}\\` to the class, add the type import:\n * import type { ${capabilityInterface} } from \"@theholocron/cli\";\n * and set \\`: ${capabilityInterface}\\` as the factory return type below.\n */\n\nimport { resolveToken, type ResolveTokenInput } from \"./auth.js\";\nimport { ${inputs.capabilityClass} } from \"./capabilities/${inputs.capability}.js\";\nimport { ${clientClass} } from \"./rest.js\";\n\nexport interface ${inputs.vendorName}PluginOptions extends ResolveTokenInput {\n\t/** Override base URL for tests. */\n\tbaseUrl?: string;\n\t/** Override \\`fetch\\` for tests. */\n\tfetch?: typeof fetch;\n}\n\nexport interface PluginContext {\n\toptions: ${inputs.vendorName}PluginOptions;\n\trest: ${clientClass};\n}\n\nexport function createContext(options: ${inputs.vendorName}PluginOptions): PluginContext {\n\tconst token = resolveToken(options);\n\tconst restOpts: ConstructorParameters<typeof ${clientClass}>[0] = { token };\n\tif (options.baseUrl !== undefined) restOpts.baseUrl = options.baseUrl;\n\tif (options.fetch !== undefined) restOpts.fetch = options.fetch;\n\treturn {\n\t\toptions,\n\t\trest: new ${clientClass}(restOpts),\n\t};\n}\n\nexport function ${inputs.capability}(ctx: PluginContext) {\n\t// Return type inferred at scaffold time — the class doesn't yet\n\t// \\`implements ${capabilityInterface}\\`. Add the type import + the\n\t// \\`: ${capabilityInterface}\\` annotation once methods are stubbed.\n\treturn new ${inputs.capabilityClass}(ctx.rest);\n}\n\nexport function createPlugin(options: ${inputs.vendorName}PluginOptions) {\n\tconst ctx = createContext(options);\n\treturn {\n\t\tname: \"@theholocron/holocron-plugin-${inputs.slug}\",\n\t\tcapabilities: {\n\t\t\t${inputs.capability}: () => ${inputs.capability}(ctx),\n\t\t},\n\t};\n}\n\n/**\n * One-line hint printed by \\`holocron auth set ${inputs.slug}\\` when no\n * token is supplied or the supplied token is rejected. Edit this to\n * point operators at the specific ${inputs.vendorName} docs path for\n * generating a token.\n */\nexport const AUTH_HINT =\n\t\"generate a ${inputs.vendorName} API token, then run: holocron auth set ${inputs.slug} <TOKEN>\";\n\n// ── Public re-exports ────────────────────────────────────────────────\n\nexport * from \"./auth.js\";\nexport { ${clientClass} } from \"./rest.js\";\nexport { ${inputs.capabilityClass} } from \"./capabilities/${inputs.capability}.js\";\nexport { verifyToken } from \"./verify-token.js\";\nexport type { VerifyTokenResult, VerifyTokenSuccess, VerifyTokenFailure } from \"./verify-token.js\";\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `<!-- editorconfig-checker-disable-file -->\n\n# \\`@theholocron/holocron-plugin-${inputs.slug}\\`\n\n${inputs.vendorName} plugin for [Holocron](../cli). Implements the\n\\`${inputs.capability}\\` capability against [${inputs.vendorName}'s REST API](${inputs.baseUrl}),\nplus exports \\`verifyToken\\` + \\`AUTH_HINT\\` for use by \\`holocron auth\\`.\n\n## Install\n\n\\`\\`\\`bash\npnpm add -D @theholocron/holocron-plugin-${inputs.slug}@alpha\n\\`\\`\\`\n\n## Auth\n\nToken resolution order (matches the standard 4-step precedence set by\n\\`.notes/tech-auth-bootstrap.spec.md\\`):\n\n1. \\`--token <TOKEN>\\` flag on the holocron invocation\n2. \\`${inputs.tokenEnv}\\` env var (preferred — explicit intent)\n3. \\`${inputs.vendorEnv}\\` env var (${inputs.vendorName}-native)\n4. **Keyring** — \\`com.theholocron.cli\\` service, account \\`${inputs.slug}\\`\n5. \\`AuthError\\` naming all four options + the bootstrap hint\n\n## Setup\n\n\\`\\`\\`bash\n# Generate a ${inputs.vendorName} API token (see vendor docs), then:\nholocron auth set ${inputs.slug} <TOKEN>\nholocron auth check ${inputs.slug} # verify\n\\`\\`\\`\n\n## Config\n\n\\`\\`\\`jsonc\n{\n\t\"providers\": {\n\t\t\"${inputs.capability}\": \"${inputs.slug}\",\n\t},\n}\n\\`\\`\\`\n\nPlugin options extend \\`ResolveTokenInput\\` — add whatever ${inputs.vendorName}-\nspecific options you need here (project id, workspace slug, etc.) via\nthe tuple form:\n\n\\`\\`\\`jsonc\n{\n\t\"providers\": {\n\t\t\"${inputs.capability}\": [\"${inputs.slug}\", { \"baseUrl\": \"${inputs.baseUrl}\" }],\n\t},\n}\n\\`\\`\\`\n\n## What's implemented\n\nTODO: fill in as capability methods land.\n\n## Status\n\n**\\`v2.0.0-alpha.1\\`** — scaffolded via \\`holocron plugin create\\`.\nNot yet published; capability methods are stubs.\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst factoryName = `create${inputs.vendorName}RestClient`;\n\treturn `import { createRestClient, type RequestOptions, type RestClient } from \"@theholocron/cli\";\n\nexport type { RequestOptions, RestClient };\n\nexport function ${factoryName}(opts: {\n\\ttoken: string;\n\\tbaseUrl?: string;\n\\tfetch?: typeof fetch;\n}): RestClient {\n\\treturn createRestClient({\n\\t\\tbaseUrl: opts.baseUrl ?? \"${inputs.baseUrl}\",\n\\t\\ttoken: opts.token,\n\\t\\tvendor: \"${inputs.vendorName}\",\n\\t\\tfetch: opts.fetch,\n\\t});\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst factoryName = `create${inputs.vendorName}RestClient`;\n\treturn `import { ProviderApiError } from \"@theholocron/cli\";\nimport { describe, expect, it } from \"vitest\";\n\nimport { ${factoryName} } from \"../rest.js\";\nimport { stubFetch } from \"./helpers.js\";\n\ndescribe(\"${factoryName}\", () => {\n\\tit(\"sends bearer + accept headers and returns the parsed body\", async () => {\n\\t\\tconst stub = stubFetch([{ status: 200, body: { ok: true } }]);\n\\t\\tconst client = ${factoryName}({ token: \"t\", fetch: stub.fetch });\n\\t\\tconst res = await client.request<{ ok: boolean }>(\"/me\");\n\\t\\texpect(res.ok).toBe(true);\n\\t\\texpect(stub.calls[0]?.headers[\"authorization\"]).toBe(\"Bearer t\");\n\\t\\texpect(stub.calls[0]?.headers[\"accept\"]).toBe(\"application/json\");\n\\t});\n\n\\tit(\"serializes body as JSON and sets content-type when present\", async () => {\n\\t\\tconst stub = stubFetch([{ status: 200, body: {} }]);\n\\t\\tconst client = ${factoryName}({ token: \"t\", fetch: stub.fetch });\n\\t\\tawait client.request<unknown>(\"/resource\", { method: \"POST\", body: { name: \"demo\" } });\n\\t\\texpect(stub.calls[0]?.method).toBe(\"POST\");\n\\t\\texpect(stub.calls[0]?.headers[\"content-type\"]).toBe(\"application/json\");\n\\t\\texpect(stub.calls[0]?.body).toEqual({ name: \"demo\" });\n\\t});\n\n\\tit(\"returns undefined on 204\", async () => {\n\\t\\tconst stub = stubFetch([{ status: 204 }]);\n\\t\\tconst client = ${factoryName}({ token: \"t\", fetch: stub.fetch });\n\\t\\texpect(await client.request<unknown>(\"/whatever\")).toBeUndefined();\n\\t});\n\n\\tit(\"throws ProviderApiError with the HTTP status on non-2xx\", async () => {\n\\t\\tconst stub = stubFetch([{ status: 401, body: { messages: [\"invalid\"] } }]);\n\\t\\tconst client = ${factoryName}({ token: \"bad\", fetch: stub.fetch });\n\\t\\tconst err = await client.request<unknown>(\"/me\").catch((e: unknown) => e);\n\\t\\texpect(err).toBeInstanceOf(ProviderApiError);\n\\t\\texpect((err as ProviderApiError).status).toBe(401);\n\\t});\n\n\\tit(\"wraps transport-level failures with status 0\", async () => {\n\\t\\tconst throwing: typeof fetch = async () => { throw new TypeError(\"fetch failed\"); };\n\\t\\tconst client = ${factoryName}({ token: \"t\", fetch: throwing });\n\\t\\tconst err = await client.request<unknown>(\"/me\").catch((e: unknown) => e);\n\\t\\texpect(err).toBeInstanceOf(ProviderApiError);\n\\t\\texpect((err as ProviderApiError).status).toBe(0);\n\\t});\n\n\\tit(\"trims trailing slashes from the base URL\", () => {\n\\t\\tconst client = ${factoryName}({ token: \"t\", baseUrl: \"${inputs.baseUrl}//\" });\n\\t\\texpect(client.baseUrl).toBe(\"${inputs.baseUrl}\");\n\\t});\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `{\n \"display\": \"Holocron Plugin: ${inputs.vendorName}\",\n \"extends\": \"@tsconfig/node-lts/tsconfig.json\",\n \"compilerOptions\": {\n \"baseUrl\": \"./\",\n \"outDir\": \"./dist\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n },\n \"include\": [\"src/**/*.ts\"],\n \"exclude\": [\"node_modules\", \"dist\"]\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(_inputs: TemplateInputs): string {\n\treturn `import { defineConfig } from \"tsdown\";\n\nexport default defineConfig({\n\tentry: [\"src/index.ts\"],\n\tformat: \"esm\",\n\tdts: true,\n\tclean: true,\n\tdeps: { neverBundle: [/^@theholocron\\\\//] },\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\n/**\n * Scaffolds `scripts/validate.mjs` — a smoke-test the operator runs\n * against a live vendor account to verify the plugin's REST endpoints,\n * auth, and response parsing all work in reality (the unit tests only\n * exercise stubbed HTTP responses). READ-ONLY BY DESIGN.\n *\n * Convention: every plugin ships this script + a matching `validate`\n * entry in `package.json`'s scripts block, so operators run\n * `pnpm --filter @theholocron/holocron-plugin-<slug> validate`.\n * Capability-specific args (project id, workspace, etc.) come from\n * positional command-line arguments; the plugin author fills in the\n * exact shape per their vendor.\n *\n * Includes a `hintFor(message)` helper the operator customizes with\n * vendor-specific \"here's the likely fix\" guidance for common error\n * shapes (401 / 403 / 404 / network / 5xx). Points users at docs and\n * setup steps rather than leaving them staring at a raw stack trace.\n */\nexport function render(inputs: TemplateInputs): string {\n\treturn `#!/usr/bin/env node\n/**\n * Read-only smoke test for @theholocron/holocron-plugin-${inputs.slug} against\n * a live ${inputs.vendorName} account.\n *\n * READ-ONLY BY DESIGN. Never calls write(), or bootstrap methods\n * (\\`ensureProject\\`, \\`ensureEnvironment\\`, etc.). Any ERROR line means\n * the plugin needs adjusting — the \\`hintFor\\` helper below points at\n * the most likely fix per error shape.\n *\n * Auth: reads the ${inputs.vendorName} token from holocron's keyring —\n * you must have run \\`pnpm holocron auth set ${inputs.slug} <TOKEN>\\` first.\n *\n * Usage:\n * pnpm --filter @theholocron/holocron-plugin-${inputs.slug} validate <arg1> [arg2] ...\n *\n * TODO: replace the positional args below with whatever your\n * capability's methods need (e.g., project id, environment slug,\n * secret name). Adapt the test steps to your capability's method\n * surface. Model on \\`packages/holocron-plugin-infisical/scripts/validate.mjs\\`.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars -- filled in by operator\nimport { AuthError, createPlugin, resolveToken, verifyToken } from \"../src/index.ts\";\n\nconst args = process.argv.slice(2);\n\nif (args.length === 0) {\n\tconsole.error(\"usage: pnpm --filter @theholocron/holocron-plugin-${inputs.slug} validate <args>\");\n\tprocess.exit(2);\n}\n\n// Use the plugin's own auth resolution so the validate script honors\n// the same 4-step precedence as the plugin's runtime:\n// --token → ${inputs.tokenEnv} → ${inputs.vendorEnv} → keyring\n// (--token isn't available here since this is a bare Node script;\n// the other three all work.)\nlet token;\ntry {\n\ttoken = resolveToken();\n} catch (err) {\n\tif (err instanceof AuthError) {\n\t\tconsole.error(err.message);\n\t\tconsole.error(\" see: packages/holocron-plugin-${inputs.slug}/README.md#setup\");\n\t\tprocess.exit(2);\n\t}\n\tthrow err;\n}\n\nconsole.log(\"Validating @theholocron/holocron-plugin-${inputs.slug} (READ-ONLY)\");\nconsole.log(\"\");\n\n// ── 1. verifyToken ─────────────────────────────────────────────────\nconsole.log(\"[1/N] verifyToken\");\nconst verifyResult = await verifyToken(token);\nconsole.log(\\` \\${verifyResult.ok ? \"✓\" : \"✗\"} \\${JSON.stringify(verifyResult)}\\`);\nif (!verifyResult.ok) {\n\tconst hint = hintFor(verifyResult.message);\n\tif (hint) console.log(\\` hint: \\${hint}\\`);\n}\nconsole.log(\"\");\n\n// ── 2..N. capability method calls ──────────────────────────────────\n// TODO: implement one \\`runStep\\`-wrapped call per meaningful read-side\n// capability method. Model on the infisical validate.mjs. Never call\n// write / ensure* / other mutating paths.\n//\n// Example:\n// console.log(\"[2/N] vault.list()\");\n// await runStep(async () => {\n// const keys = await vault.list();\n// console.log(\\` ✓ \\${keys.length} secrets\\`);\n// });\n\nconsole.log(\"Done. Fill in capability method calls above before shipping.\");\n\n// ── helpers ────────────────────────────────────────────────────────\n\n/** Wrap a capability call, print ERROR + hint on failure. */\nasync function runStep(body) {\n\ttry {\n\t\tawait body();\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tconsole.log(\\` ✗ ERROR: \\${message}\\`);\n\t\tconst hint = hintFor(message);\n\t\tif (hint) console.log(\\` hint: \\${hint}\\`);\n\t}\n}\n\n/**\n * Point the operator at the most likely fix based on the error shape.\n * Generic defaults below — CUSTOMIZE per your vendor's docs URLs and\n * common permission/config gotchas.\n */\nfunction hintFor(message) {\n\tif (/→ 401/.test(message)) {\n\t\treturn \"token invalid — regenerate per ${inputs.vendorName}'s docs (see README §Setup)\";\n\t}\n\tif (/→ 403/.test(message)) {\n\t\treturn \"token authenticates but lacks scope — check the token/identity has permissions on the resource\";\n\t}\n\tif (/→ 404/.test(message)) {\n\t\treturn \"endpoint or resource not found — verify your positional args match a real resource\";\n\t}\n\tif (/fetch failed|status: 0|network/i.test(message)) {\n\t\treturn \"network error — check the base URL (${inputs.baseUrl}) and connectivity\";\n\t}\n\tif (/→ 5\\\\d\\\\d/.test(message)) {\n\t\treturn \"server error — vendor-side. Retry, and check the vendor's status page if persistent\";\n\t}\n\treturn null;\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst clientClass = `${inputs.vendorName}RestClient`;\n\treturn `/**\n * \\`verifyToken\\` — plugin-level export used by \\`holocron auth set\\` +\n * \\`holocron auth check\\`. Hits a lightweight whoami-style endpoint\n * and translates the response into the normalized \\`VerifyTokenResult\\`\n * shape.\n *\n * Kept as a standalone function (not a capability method) so the auth\n * command can call it without initializing the full plugin — plugin\n * construction requires an already-resolved token, which is exactly\n * what we don't have yet at bootstrap time.\n *\n * TODO: replace \\`/me\\` with the ${inputs.vendorName} equivalent of a\n * \"check my token\" endpoint. Common shapes: \\`/user\\`, \\`/whoami\\`,\n * \\`/me\\`, \\`/account\\`.\n */\n\nimport { ${clientClass} } from \"./rest.js\";\n\nexport interface VerifyTokenSuccess {\n\tok: true;\n\tsubject: string;\n}\n\nexport interface VerifyTokenFailure {\n\tok: false;\n\tmessage: string;\n}\n\nexport type VerifyTokenResult = VerifyTokenSuccess | VerifyTokenFailure;\n\ninterface MeResponse {\n\t/** Adjust to whatever ${inputs.vendorName}'s whoami endpoint returns. */\n\tname?: string;\n\temail?: string;\n\tid?: string;\n}\n\nexport interface VerifyTokenOptions {\n\tbaseUrl?: string;\n\tfetch?: typeof fetch;\n}\n\nexport async function verifyToken(token: string, opts: VerifyTokenOptions = {}): Promise<VerifyTokenResult> {\n\tconst restOpts: ConstructorParameters<typeof ${clientClass}>[0] = { token };\n\tif (opts.baseUrl !== undefined) restOpts.baseUrl = opts.baseUrl;\n\tif (opts.fetch !== undefined) restOpts.fetch = opts.fetch;\n\tconst rest = new ${clientClass}(restOpts);\n\ttry {\n\t\tconst me = await rest.request<MeResponse>(\"/me\");\n\t\t// Optional chaining because \\`me\\` is \\`undefined\\` on 204 / empty body.\n\t\tconst subject = me?.email ?? me?.name ?? me?.id ?? \"unknown\";\n\t\treturn { ok: true, subject: \\`user @ \\${subject}\\` };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\treturn { ok: false, message };\n\t}\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(_inputs: TemplateInputs): string {\n\treturn `import { describe, expect, it } from \"vitest\";\n\nimport { verifyToken } from \"../verify-token.js\";\nimport { stubFetch } from \"./helpers.js\";\n\ndescribe(\"verifyToken\", () => {\n\tit(\"returns ok with a subject when /me returns 200\", async () => {\n\t\tconst stub = stubFetch([{ status: 200, body: { email: \"user@example.com\" } }]);\n\t\tconst result = await verifyToken(\"token\", { fetch: stub.fetch });\n\t\texpect(result.ok).toBe(true);\n\t\tif (result.ok) {\n\t\t\texpect(result.subject).toMatch(/user@example.com/);\n\t\t}\n\t});\n\n\tit(\"returns ok:false with the error message on 401\", async () => {\n\t\tconst stub = stubFetch([{ status: 401, body: { messages: [\"Invalid token\"] } }]);\n\t\tconst result = await verifyToken(\"bad\", { fetch: stub.fetch });\n\t\texpect(result.ok).toBe(false);\n\t\tif (!result.ok) {\n\t\t\texpect(result.message).toMatch(/→ 401/);\n\t\t}\n\t});\n\n\tit(\"returns ok:false when the network layer throws\", async () => {\n\t\tconst throwing: typeof fetch = async () => {\n\t\t\tthrow new TypeError(\"network down\");\n\t\t};\n\t\tconst result = await verifyToken(\"t\", { fetch: throwing });\n\t\texpect(result.ok).toBe(false);\n\t\tif (!result.ok) {\n\t\t\texpect(result.message).toMatch(/network down/);\n\t\t}\n\t});\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(_inputs: TemplateInputs): string {\n\treturn `import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n\ttest: {\n\t\tenvironment: \"node\",\n\t\tglobals: false,\n\t\tcoverage: {\n\t\t\tprovider: \"v8\",\n\t\t\treporter: [\"text\", \"html\", \"json-summary\"],\n\t\t\tinclude: [\"src/**/*.ts\"],\n\t\t\texclude: [\"src/**/__tests__/**\", \"src/**/*.test.ts\", \"src/index.ts\"],\n\t\t\tthresholds: { lines: 0, functions: 0, branches: 0, statements: 0 },\n\t\t},\n\t},\n});\n`;\n}\n","/**\n * `holocron plugin create <slug> <vendor>` — scaffold a new plugin\n * package matching the proven template.\n *\n * Design: see `.notes/tool-plugin-create.spec.md`.\n *\n * Flow:\n * 1. Preflight — verify CWD is a workspace root (pnpm-workspace.yaml\n * + packages/ dir present).\n * 2. Slug collision — packages/holocron-plugin-<slug>/ must not exist.\n * 3. Capability sanity — must be one of the 14 known keys; warn for\n * many-cardinality caps.\n * 4. Generate — for each template, write to\n * packages/holocron-plugin-<slug>/<path>.\n * 5. Verify (unless --no-verify) — runs pnpm install +\n * pnpm --filter <pkg> typecheck lint test.\n * 6. Print next steps.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { CapabilityKey } from \"../../capabilities/index.js\";\nimport { CARDINALITY } from \"../../capabilities/index.js\";\nimport { deriveDefaults, type TemplateInputs } from \"./template-inputs.js\";\nimport { render as renderAuth } from \"./templates/auth.js\";\nimport { render as renderAuthTest } from \"./templates/auth-test.js\";\nimport { render as renderCapability } from \"./templates/capability.js\";\nimport { render as renderCapabilityTest } from \"./templates/capability-test.js\";\nimport { render as renderEslintConfig } from \"./templates/eslint-config.js\";\nimport { render as renderHelpers } from \"./templates/helpers.js\";\nimport { render as renderIndexTest } from \"./templates/index-test.js\";\nimport { render as renderPackageJson } from \"./templates/package-json.js\";\nimport { render as renderPluginIndex } from \"./templates/plugin-index.js\";\nimport { render as renderReadme } from \"./templates/readme.js\";\nimport { render as renderRest } from \"./templates/rest.js\";\nimport { render as renderRestTest } from \"./templates/rest-test.js\";\nimport { render as renderTsconfigJson } from \"./templates/tsconfig-json.js\";\nimport { render as renderTsdownConfig } from \"./templates/tsdown-config.js\";\nimport { render as renderValidateScript } from \"./templates/validate-script.js\";\nimport { render as renderVerifyToken } from \"./templates/verify-token.js\";\nimport { render as renderVerifyTokenTest } from \"./templates/verify-token-test.js\";\nimport { render as renderVitestConfig } from \"./templates/vitest-config.js\";\n\n// ── Public API ──────────────────────────────────────────────────────\n\n// ── Wizard resolver ───────────────────────────────────────────────────\n\nexport interface PluginCreateWizardArgs {\n\tcapability?: string;\n\tvendorEnv?: string;\n\tbaseUrl?: string;\n}\n\nexport interface PluginCreateWizardPrompts {\n\tselectCapability: () => Promise<string>;\n\tinputVendorEnv: () => Promise<string>;\n\tinputBaseUrl: () => Promise<string>;\n}\n\n/**\n * Resolve `capability`, `vendorEnv`, and `baseUrl` from argv or by calling\n * the supplied prompt functions for any that are absent. Extracted from\n * `cli.ts` so the resolution logic is unit-testable.\n */\nexport async function resolvePluginCreateInputs(\n\targs: PluginCreateWizardArgs,\n\tprompts: PluginCreateWizardPrompts\n): Promise<{ capability: CapabilityKey; vendorEnv: string; baseUrl: string }> {\n\tconst capability = (args.capability ?? (await prompts.selectCapability())) as CapabilityKey;\n\tconst vendorEnv = args.vendorEnv ?? (await prompts.inputVendorEnv());\n\tconst baseUrl = args.baseUrl ?? (await prompts.inputBaseUrl());\n\treturn { capability, vendorEnv, baseUrl };\n}\n\n// ── Run input / report ────────────────────────────────────────────────\n\nexport interface RunPluginCreateInput {\n\t/** Package slug, e.g., \"clerk\". Kebab-case. */\n\tslug: string;\n\t/** Vendor display name, e.g., \"Clerk\". PascalCase. */\n\tvendorName: string;\n\t/** Capability the plugin implements — one of the 14 known keys. */\n\tcapability: CapabilityKey;\n\t/** Vendor-native env var, e.g., \"CLERK_SECRET_KEY\". */\n\tvendorEnv: string;\n\t/** REST base URL, e.g., \"https://api.clerk.com/v1\". */\n\tbaseUrl: string;\n\t/** Optional token env override. Defaults to `HOLOCRON_<VENDOR>_TOKEN`. */\n\ttokenEnv?: string;\n\t/** Print steps without writing files. */\n\tdryRun?: boolean;\n\t/** Skip the post-scaffold pnpm install/typecheck/lint/test. */\n\tnoVerify?: boolean;\n\t/** Working directory (workspace root). Defaults to `process.cwd()`. */\n\tcwd?: string;\n\t/** Injection point for tests / dry-run wiring. Defaults to fs write. */\n\twriteFile?: (filepath: string, content: string) => void;\n\t/** Print fn — captures orchestrator output. Defaults to console.log. */\n\tprint?: (line: string) => void;\n\t/** Injectable subprocess runner for testing. Defaults to execFileSync. */\n\texec?: (cmd: string, args: string[], opts: { cwd: string; stdio: \"inherit\" }) => void;\n}\n\nexport interface PluginCreateReport {\n\tstatus: \"ok\" | \"fail\";\n\tpackagePath: string;\n\tfilesWritten: string[];\n\tmessage?: string;\n}\n\nexport class PluginCreateError extends Error {\n\toverride name = \"PluginCreateError\";\n}\n\n// ── Templates registry ──────────────────────────────────────────────\n\ninterface TemplateEntry {\n\t/** Path relative to the plugin package root. */\n\tpath: string;\n\trender: (inputs: TemplateInputs) => string;\n}\n\nconst TEMPLATES: TemplateEntry[] = [\n\t// Config (5)\n\t{ path: \"package.json\", render: renderPackageJson },\n\t{ path: \"tsconfig.json\", render: renderTsconfigJson },\n\t{ path: \"vitest.config.ts\", render: renderVitestConfig },\n\t{ path: \"eslint.config.js\", render: renderEslintConfig },\n\t{ path: \"tsdown.config.ts\", render: renderTsdownConfig },\n\t// Docs (1)\n\t{ path: \"README.md\", render: renderReadme },\n\t// Source (5) — capability path uses the dynamic capability slug.\n\t{ path: \"src/auth.ts\", render: renderAuth },\n\t{ path: \"src/rest.ts\", render: renderRest },\n\t{ path: \"src/verify-token.ts\", render: renderVerifyToken },\n\t{ path: \"src/index.ts\", render: renderPluginIndex },\n\t{ path: \"src/capabilities/{{capability}}.ts\", render: renderCapability },\n\t// Tests (6)\n\t{ path: \"src/__tests__/helpers.ts\", render: renderHelpers },\n\t{ path: \"src/__tests__/auth.test.ts\", render: renderAuthTest },\n\t{ path: \"src/__tests__/rest.test.ts\", render: renderRestTest },\n\t{ path: \"src/__tests__/verify-token.test.ts\", render: renderVerifyTokenTest },\n\t{ path: \"src/__tests__/{{capability}}.test.ts\", render: renderCapabilityTest },\n\t{ path: \"src/__tests__/index.test.ts\", render: renderIndexTest },\n\t// Live-account validation script (1) — read-only smoke test.\n\t{ path: \"scripts/validate.mjs\", render: renderValidateScript },\n];\n\n/** Replace `{{capability}}` in a template path with the actual capability key. */\nfunction resolvePath(template: string, inputs: TemplateInputs): string {\n\treturn template.replace(/\\{\\{capability\\}\\}/g, inputs.capability);\n}\n\n// ── Orchestrator ────────────────────────────────────────────────────\n\nexport function runPluginCreate(input: RunPluginCreateInput): PluginCreateReport {\n\tconst cwd = input.cwd ?? process.cwd();\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst write = input.writeFile ?? defaultWrite;\n\n\tpreflight(cwd);\n\tvalidateSlug(input.slug);\n\tvalidateVendorName(input.vendorName);\n\n\tconst packageDir = path.join(cwd, \"packages\", `holocron-plugin-${input.slug}`);\n\tif (existsSync(packageDir)) {\n\t\tthrow new PluginCreateError(`\\`${packageDir}\\` already exists — edit in place or pick a different slug.`);\n\t}\n\n\tvalidateCapability(input.capability, print);\n\n\tconst derived = deriveDefaults({\n\t\tslug: input.slug,\n\t\tvendorName: input.vendorName,\n\t\tcapability: input.capability,\n\t});\n\tconst inputs: TemplateInputs = {\n\t\tslug: input.slug,\n\t\tvendorName: input.vendorName,\n\t\tvendorUpper: derived.vendorUpper,\n\t\tcapability: input.capability,\n\t\tcapabilityClass: derived.capabilityClass,\n\t\ttokenEnv: input.tokenEnv ?? derived.tokenEnv,\n\t\tvendorEnv: input.vendorEnv,\n\t\t// Normalize: strip trailing slashes so the embedded value in the\n\t\t// generated rest-test.ts matches what the client trims at runtime.\n\t\tbaseUrl: trimTrailingSlashes(input.baseUrl),\n\t\ttransport: derived.transport,\n\t};\n\n\tconst filesWritten: string[] = [];\n\tprint(`Scaffolding @theholocron/holocron-plugin-${inputs.slug}${input.dryRun ? \" (dry-run)\" : \"\"}`);\n\tprint(` → ${packageDir}`);\n\tfor (const template of TEMPLATES) {\n\t\tconst resolvedPath = resolvePath(template.path, inputs);\n\t\tconst filepath = path.join(packageDir, resolvedPath);\n\t\tconst content = template.render(inputs);\n\t\tif (input.dryRun) {\n\t\t\tprint(` … would write ${resolvedPath} (${content.length} bytes)`);\n\t\t} else {\n\t\t\twrite(filepath, content);\n\t\t\tprint(` ✓ ${resolvedPath}`);\n\t\t}\n\t\tfilesWritten.push(resolvedPath);\n\t}\n\n\tif (!input.dryRun && !input.noVerify) {\n\t\tconst execFn = input.exec ?? defaultExec;\n\t\tconst pkg = `@theholocron/holocron-plugin-${inputs.slug}`;\n\t\tprint(\"\");\n\t\tprint(\" Verifying scaffold…\");\n\t\ttry {\n\t\t\texecFn(\"pnpm\", [\"install\", \"--frozen-lockfile=false\"], { cwd, stdio: \"inherit\" });\n\t\t\texecFn(\"pnpm\", [\"--filter\", pkg, \"typecheck\"], { cwd, stdio: \"inherit\" });\n\t\t\texecFn(\"pnpm\", [\"--filter\", pkg, \"lint\"], { cwd, stdio: \"inherit\" });\n\t\t\texecFn(\"pnpm\", [\"--filter\", pkg, \"test\"], { cwd, stdio: \"inherit\" });\n\t\t\tprint(\" ✓ scaffold verified\");\n\t\t} catch (err) {\n\t\t\tprint(` ✗ verify failed — ${err instanceof Error ? err.message : String(err)}`);\n\t\t\treturn {\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tpackagePath: packageDir,\n\t\t\t\tfilesWritten,\n\t\t\t\tmessage: \"post-scaffold verify failed; inspect output above\",\n\t\t\t};\n\t\t}\n\t}\n\n\tif (!input.dryRun) {\n\t\tprintNextSteps(print, inputs);\n\t}\n\n\treturn { status: \"ok\", packagePath: packageDir, filesWritten };\n}\n\n// ── Internals ───────────────────────────────────────────────────────\n\nfunction preflight(cwd: string): void {\n\tif (!existsSync(path.join(cwd, \"pnpm-workspace.yaml\"))) {\n\t\tthrow new PluginCreateError(\n\t\t\t`\\`pnpm-workspace.yaml\\` not found in \\`${cwd}\\`. Run \\`holocron plugin create\\` from the monorepo root.`\n\t\t);\n\t}\n\tif (!existsSync(path.join(cwd, \"packages\"))) {\n\t\tthrow new PluginCreateError(`\\`packages/\\` directory not found in \\`${cwd}\\`.`);\n\t}\n}\n\n/**\n * npm-package-name conventions: kebab-case, starts with lowercase\n * letter. Rejecting numeric-prefixed slugs also sidesteps the\n * `env.HOLOCRON_1FOO_TOKEN` invalid-identifier trap in the auth\n * template.\n */\nconst SLUG_RE = /^[a-z][a-z0-9-]*$/;\n\nfunction validateSlug(slug: string): void {\n\tif (!SLUG_RE.test(slug)) {\n\t\tthrow new PluginCreateError(\n\t\t\t`invalid slug \"${slug}\" — must be kebab-case: lowercase letter followed by lowercase letters, digits, or hyphens. ` +\n\t\t\t\t`Examples: \"clerk\", \"cloud-flare\", \"doppler\".`\n\t\t);\n\t}\n}\n\n/** PascalCase — starts with uppercase, alphanumeric only. */\nconst VENDOR_NAME_RE = /^[A-Z][a-zA-Z0-9]*$/;\n\nfunction validateVendorName(name: string): void {\n\tif (!VENDOR_NAME_RE.test(name)) {\n\t\tthrow new PluginCreateError(\n\t\t\t`invalid vendor name \"${name}\" — must be PascalCase: starts with uppercase, alphanumeric only. ` +\n\t\t\t\t`Examples: \"Clerk\", \"CloudFlare\", \"Doppler\".`\n\t\t);\n\t}\n}\n\n/**\n * Trim trailing slashes with a plain loop (no regex — matches the\n * rest.ts template's own trimming to stay ReDoS-safe under CodeQL).\n */\nfunction trimTrailingSlashes(url: string): string {\n\tlet out = url;\n\twhile (out.endsWith(\"/\")) out = out.slice(0, -1);\n\treturn out;\n}\n\nfunction validateCapability(capability: CapabilityKey, print: (line: string) => void): void {\n\tif (!(capability in CARDINALITY)) {\n\t\tthrow new PluginCreateError(\n\t\t\t`\\`${capability}\\` is not a known capability. See \\`packages/cli/src/capabilities/index.ts\\`.`\n\t\t);\n\t}\n\tif (CARDINALITY[capability] === \"many\") {\n\t\tprint(\n\t\t\t` ! ${capability} is a many-cardinality capability — multiple providers can be active at once. ` +\n\t\t\t\t\"Confirm your config wiring accordingly.\"\n\t\t);\n\t}\n}\n\nfunction defaultWrite(filepath: string, content: string): void {\n\tmkdirSync(path.dirname(filepath), { recursive: true });\n\twriteFileSync(filepath, content, \"utf8\");\n}\n\nfunction defaultExec(cmd: string, args: string[], opts: { cwd: string; stdio: \"inherit\" }): void {\n\texecFileSync(cmd, args, { cwd: opts.cwd, stdio: opts.stdio });\n}\n\nfunction printNextSteps(print: (line: string) => void, inputs: TemplateInputs): void {\n\tprint(\"\");\n\tprint(` Scaffolded @theholocron/holocron-plugin-${inputs.slug} (18 files).`);\n\tprint(\"\");\n\tprint(\" Next:\");\n\tprint(\n\t\t` 1. pnpm install # picks up the workspace package`\n\t);\n\tprint(` 2. pnpm --filter @theholocron/holocron-plugin-${inputs.slug} typecheck # green`);\n\tprint(` 3. pnpm --filter @theholocron/holocron-plugin-${inputs.slug} lint # green`);\n\tprint(\n\t\t` 4. pnpm --filter @theholocron/holocron-plugin-${inputs.slug} test # green (stubs pass, real tests are it.todo)`\n\t);\n\tprint(` 5. Implement ${inputs.capabilityClass} methods in src/capabilities/${inputs.capability}.ts`);\n\tprint(` 6. Replace it.todo(...) with real tests in src/__tests__/${inputs.capability}.test.ts`);\n\tprint(\" 7. Commit + push when capability is functionally complete.\");\n}\n","/**\n * `holocron secret set` — one-shot single-secret push.\n *\n * Complements `holocron secrets sync` (bulk vault → destinations) for\n * ad-hoc scenarios:\n * - Bootstrap secrets (e.g., NPM_TOKEN on theholocron/holocron itself\n * before the rest of the setup exists)\n * - One-off rotations that don't warrant a vault sync\n * - Setting secrets the vault doesn't track\n *\n * Value source resolution (in priority order):\n * 1. Positional `value` argument\n * 2. `--from-stdin` reads from stdin\n * 3. `--from-env <NAME>` reads from the named env var\n * 4. Implicit: env var matching the secret name (e.g., `NPM_TOKEN`)\n *\n * Errors clearly when no value can be sourced.\n */\n\nimport type { Secrets, SecretScope } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\n\nexport type SecretSetPrint = (line: string) => void;\n\nexport interface RunSecretSetInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** Secret name (e.g., `NPM_TOKEN`). */\n\tname: string;\n\t/** Secret value. If absent, resolves via stdin / env. */\n\tvalue?: string;\n\t/** Read from stdin instead of positional or env var. */\n\tfromStdin?: boolean;\n\t/** Read from a specific env var rather than implicit-by-name. */\n\tfromEnv?: string;\n\t/** Defaults to `{ kind: 'repo' }`. */\n\tscope?: SecretScope;\n\tloader?: PluginLoader;\n\tprint?: SecretSetPrint;\n\t/** Lets tests inject a stdin reader. Defaults to reading process.stdin. */\n\treadStdin?: () => Promise<string>;\n}\n\nexport interface SecretSetReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n\tname: string;\n\tscope: SecretScope;\n\tmessage?: string;\n}\n\nexport async function runSecretSet(input: RunSecretSetInput): Promise<SecretSetReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait loader.load();\n\n\tconst dryRun = input.context.dryRun ?? false;\n\tconst scope: SecretScope = input.scope ?? { kind: \"repo\" };\n\n\tif (!loader.has(\"secrets\")) {\n\t\tthrow new Error(\"`secrets` capability is not configured — add a `secrets` provider to holocron.config.json\");\n\t}\n\n\t// Resolve the value to push, surfacing a clear error when none can be sourced.\n\tconst value = await resolveValue(input);\n\tif (!value) {\n\t\tthrow new Error(\n\t\t\t`no value for secret \\`${input.name}\\` — pass it positionally, via --from-stdin, --from-env <NAME>, or set $${input.name} in the environment`\n\t\t);\n\t}\n\n\tprint(`Holocron secret set — ${input.name} (${describeScope(scope)})${dryRun ? \" (dry-run)\" : \"\"}`);\n\n\tif (dryRun) {\n\t\tconst message = `would: secrets.setSecret(${describeScope(scope)}, ${input.name}, <${value.length} chars>)`;\n\t\tprint(` … ${message}`);\n\t\treturn { status: \"dry-run\", name: input.name, scope, message };\n\t}\n\n\ttry {\n\t\tconst secrets = loader.get(\"secrets\") as Secrets;\n\t\tawait secrets.setSecret(scope, input.name, value);\n\t\tprint(` ✓ set ${input.name} via ${secrets.providerName}`);\n\t\treturn { status: \"ok\", name: input.name, scope };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tprint(` ✗ ${message}`);\n\t\treturn { status: \"fail\", name: input.name, scope, message };\n\t}\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nasync function resolveValue(input: RunSecretSetInput): Promise<string | undefined> {\n\tif (input.value) return input.value;\n\tif (input.fromStdin) {\n\t\tconst reader = input.readStdin ?? defaultReadStdin;\n\t\tconst text = await reader();\n\t\treturn text.replace(/\\r?\\n$/, \"\"); // trim trailing newline\n\t}\n\tconst env = process.env;\n\tif (input.fromEnv) {\n\t\treturn env[input.fromEnv];\n\t}\n\t// Implicit: env var with the same name as the secret.\n\treturn env[input.name];\n}\n\nasync function defaultReadStdin(): Promise<string> {\n\tconst chunks: Buffer[] = [];\n\treturn new Promise<string>((resolve, reject) => {\n\t\tprocess.stdin.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n\t\tprocess.stdin.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf8\")));\n\t\tprocess.stdin.on(\"error\", reject);\n\t});\n}\n\nfunction describeScope(scope: SecretScope): string {\n\tif (scope.kind === \"repo\") return \"scope=repo\";\n\tif (scope.kind === \"environment\") return `scope=environment:${scope.name}`;\n\treturn `scope=organization:${scope.name}`;\n}\n","/**\n * `holocron secrets sync` — vault → destinations.\n *\n * Reads a named environment from the configured `vault` (1P\n * Environment / similar) as KEY=VALUE pairs, then fans those values\n * out to the configured destinations:\n *\n * - `secrets` capability (e.g., GH Actions secrets) — repo-scope\n * - `deployment` capability (e.g., Vercel env vars) — per-target\n * - local `.env` file (optional, planned for v5.1 — currently skipped\n * with a soft \"not yet\" note)\n *\n * Per-secret routing rules:\n *\n * - All keys go to `secrets` (CI needs them)\n * - All keys go to `deployment` for each target the caller asks for\n * (defaults: production + preview)\n *\n * The vault MUST implement `readEnvironment(envId)` (optional method).\n * If it doesn't, the command errors with a hint to populate the keys\n * individually via `holocron secret set` (also planned for v5.1).\n */\n\nimport type { Deployment, DeploymentTarget, Secrets, Vault } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport { withSpinner } from \"../ui/progress.js\";\nimport { style } from \"../ui/style.js\";\n\nexport type SyncPrintLine = (line: string) => void;\n\nexport type SyncRowStatus = \"ok\" | \"fail\" | \"dry-run\" | \"skip\";\n\nexport interface SyncRow {\n\tdestination: string;\n\t/** e.g., `target=production` for deployment, `scope=repo` for secrets. */\n\tscope: string;\n\tkey: string;\n\tstatus: SyncRowStatus;\n\tmessage?: string;\n}\n\nexport interface SyncReport {\n\trows: SyncRow[];\n\tsummary: { ok: number; fail: number; skip: number; dryRun: number };\n}\n\nexport interface RunSecretsSyncInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** Vault environment id to read. */\n\tenvironmentId: string;\n\t/** Deployment targets to sync to. Defaults to ['production', 'preview']. */\n\ttargets?: DeploymentTarget[];\n\t/** Vercel project id (or equivalent). Required if `deployment` is loaded. */\n\tprojectId?: string;\n\tloader?: PluginLoader;\n\tprint?: SyncPrintLine;\n}\n\nexport async function runSecretsSync(input: RunSecretsSyncInput): Promise<SyncReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait withSpinner(\"Loading plugins…\", () => loader.load());\n\n\tconst dryRun = input.context.dryRun ?? false;\n\tconst targets = input.targets ?? ([\"production\", \"preview\"] as DeploymentTarget[]);\n\n\tprint(style.header(`Holocron secrets sync — environment ${input.environmentId}${dryRun ? \" (dry-run)\" : \"\"}`));\n\tprint(style.dim(` vault: ${vaultProviderName(loader)}`));\n\tprint(\"\");\n\n\t// ── Read the vault ─────────────────────────────────────────────────\n\tconst vault = loader.get(\"vault\") as Vault;\n\tif (!vault.readEnvironment) {\n\t\tthrow new Error(\n\t\t\t`vault provider (${vault.providerName}) does not implement readEnvironment — sync needs bulk env reads`\n\t\t);\n\t}\n\tconst envVars = await withSpinner(`Reading vault environment ${input.environmentId}…`, () =>\n\t\tvault.readEnvironment!(input.environmentId)\n\t);\n\tconst keys = Object.keys(envVars).sort();\n\tprint(style.step(`read ${keys.length} keys from vault`));\n\tprint(\"\");\n\n\tconst rows: SyncRow[] = [];\n\n\t// ── Push to `secrets` (CI/Actions secrets) ─────────────────────────\n\tif (loader.has(\"secrets\")) {\n\t\tconst secrets = loader.get(\"secrets\") as Secrets;\n\t\tprint(style.step(\"secrets (repo scope)\"));\n\t\tfor (const key of keys) {\n\t\t\trows.push(\n\t\t\t\tawait runRow(`secrets:${secrets.providerName}`, \"scope=repo\", key, dryRun, async () => {\n\t\t\t\t\tawait secrets.setSecret({ kind: \"repo\" }, key, envVars[key]!);\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatRow(rows[rows.length - 1]!));\n\t\t}\n\t}\n\n\t// ── Push to `deployment` (Vercel env vars) ─────────────────────────\n\tif (loader.has(\"deployment\")) {\n\t\tconst deploy = loader.get(\"deployment\") as Deployment;\n\t\tif (!input.projectId) {\n\t\t\tprint(style.step(\"deployment\"));\n\t\t\tconst row: SyncRow = {\n\t\t\t\tdestination: `deployment:${deploy.providerName}`,\n\t\t\t\tscope: \"no projectId\",\n\t\t\t\tkey: \"(all)\",\n\t\t\t\tstatus: \"skip\",\n\t\t\t\tmessage: \"projectId required for deployment env-var sync (pass --project-id)\",\n\t\t\t};\n\t\t\trows.push(row);\n\t\t\tprint(formatRow(row));\n\t\t} else {\n\t\t\tfor (const target of targets) {\n\t\t\t\tprint(style.step(`deployment (target=${target})`));\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\trows.push(\n\t\t\t\t\t\tawait runRow(`deployment:${deploy.providerName}`, `target=${target}`, key, dryRun, async () => {\n\t\t\t\t\t\t\tawait deploy.setEnvVar(input.projectId!, target, key, envVars[key]!);\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tprint(formatRow(rows[rows.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tconst summary = rows.reduce(\n\t\t(acc, r) => {\n\t\t\tif (r.status === \"ok\") acc.ok += 1;\n\t\t\telse if (r.status === \"fail\") acc.fail += 1;\n\t\t\telse if (r.status === \"skip\") acc.skip += 1;\n\t\t\telse if (r.status === \"dry-run\") acc.dryRun += 1;\n\t\t\treturn acc;\n\t\t},\n\t\t{ ok: 0, fail: 0, skip: 0, dryRun: 0 }\n\t);\n\n\tprint(\"\");\n\tconst summaryLine = `${summary.ok} ok, ${summary.fail} fail, ${summary.skip} skipped${\n\t\tdryRun ? `, ${summary.dryRun} would-do` : \"\"\n\t}`;\n\tprint(summary.fail > 0 ? style.fail(summaryLine) : style.success(summaryLine));\n\n\treturn { rows, summary };\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nasync function runRow(\n\tdestination: string,\n\tscope: string,\n\tkey: string,\n\tdryRun: boolean,\n\tbody: () => Promise<void>\n): Promise<SyncRow> {\n\tif (dryRun) {\n\t\treturn { destination, scope, key, status: \"dry-run\" };\n\t}\n\ttry {\n\t\tawait body();\n\t\treturn { destination, scope, key, status: \"ok\" };\n\t} catch (err) {\n\t\treturn {\n\t\t\tdestination,\n\t\t\tscope,\n\t\t\tkey,\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t};\n\t}\n}\n\nfunction formatRow(row: SyncRow): string {\n\tconst detail = row.message ? style.dim(` (${row.message})`) : \"\";\n\tconst label = `${row.key}${detail}`;\n\tif (row.status === \"ok\") return ` ${style.success(label)}`;\n\tif (row.status === \"fail\") return ` ${style.fail(label)}`;\n\tif (row.status === \"dry-run\") return ` ${style.dim(`… ${label}`)}`;\n\treturn ` ${style.dim(`· ${label}`)}`;\n}\n\nfunction vaultProviderName(loader: PluginLoader): string {\n\tif (!loader.has(\"vault\")) return \"<missing>\";\n\treturn (loader.get(\"vault\") as Vault).providerName;\n}\n","version: 2\nupdates:\n - package-ecosystem: npm\n directory: /\n schedule:\n interval: weekly\n commit-message:\n prefix: \"chore(deps)\"\n prefix-development: \"chore(deps-dev)\"\n groups:\n security-patches:\n applies-to: security-updates\n patterns:\n - \"*\"\n all-dependencies:\n update-types:\n - minor\n - patch\n\n - package-ecosystem: github-actions\n directory: /\n schedule:\n interval: weekly\n commit-message:\n prefix: \"chore(deps)\"\n groups:\n all-actions:\n patterns:\n - \"*\"\n","name: Audit\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\npermissions:\n contents: read\n\njobs:\n audit:\n uses: theholocron/.github/.github/workflows/audit.yml@main\n secrets: inherit\n","name: Bookkeeping\n\non: # yamllint disable-line rule:truthy\n pull_request:\n types:\n - opened\n - edited\n\npermissions:\n contents: read\n issues: write\n pull-requests: write\n\njobs:\n bookkeeping:\n uses: theholocron/.github/.github/workflows/bookkeeping.yml@main\n secrets: inherit\n","name: CodeQL\n\non: # yamllint disable-line rule:truthy\n push:\n branches:\n - main\n pull_request:\n branches:\n - main\n schedule:\n - cron: \"0 0 * * 1\"\n\npermissions:\n actions: read\n contents: read\n security-events: write\n\njobs:\n codeql:\n uses: theholocron/.github/.github/workflows/codeql.yml@main\n secrets: inherit\n","name: Dependencies\n\non: # yamllint disable-line rule:truthy\n pull_request:\n\npermissions:\n contents: write\n pull-requests: write\n\njobs:\n dependencies:\n uses: theholocron/.github/.github/workflows/dependencies.yml@main\n secrets: inherit\n","name: Deploy\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main]\n workflow_dispatch:\n\nconcurrency:\n group: pages\n cancel-in-progress: false\n\npermissions:\n contents: read\n pages: write\n id-token: write\n\njobs:\n deploy:\n name: Deploy\n uses: theholocron/.github/.github/workflows/deploy.yml@main\n secrets: inherit\n","name: Greetings\n\non: # yamllint disable-line rule:truthy\n pull_request:\n issues:\n\npermissions:\n issues: write\n pull-requests: write\n\njobs:\n greetings:\n uses: theholocron/.github/.github/workflows/greetings.yml@main\n secrets: inherit\n","name: Lint\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\nconcurrency:\n group: lint-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: write\n issues: write\n statuses: write\n\njobs:\n lint:\n name: Lint\n uses: theholocron/.github/.github/workflows/lint.yml@main\n secrets: inherit\n with:\n enable-auto-commit: true\n","name: Post-release Sync\n\non: # yamllint disable-line rule:truthy\n release:\n types: [published]\n\npermissions:\n contents: read\n\njobs:\n broadcast:\n name: Post-release Sync\n uses: theholocron/.github/.github/workflows/post-release.yml@main\n secrets: inherit\n","name: Release\n\non: # yamllint disable-line rule:truthy\n push:\n branches:\n - main\n - alpha\n workflow_dispatch:\n\npermissions:\n contents: write\n id-token: write\n issues: write\n pull-requests: write\n\nconcurrency:\n group: ${{ github.workflow }}-${{ github.ref }}\n cancel-in-progress: false\n\njobs:\n release:\n uses: theholocron/.github/.github/workflows/release.yml@main\n secrets: inherit\n","name: Review\n\non: # yamllint disable-line rule:truthy\n pull_request:\n\nconcurrency:\n group: review-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n checks: write\n pull-requests: write\n\njobs:\n review:\n name: Review\n uses: theholocron/.github/.github/workflows/review.yml@main\n secrets: inherit\n","name: Stale\n\non: # yamllint disable-line rule:truthy\n schedule:\n - cron: \"30 1 * * *\"\n\npermissions:\n contents: write\n issues: write\n pull-requests: write\n\njobs:\n stale:\n uses: theholocron/.github/.github/workflows/stale.yml@main\n secrets: inherit\n","name: Sync\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main]\n paths:\n - holocron.config.ts\n - package.json\n - pnpm-workspace.yaml\n workflow_dispatch:\n inputs:\n steps:\n description: \"Sync steps to run (default: all)\"\n type: string\n required: false\n\nconcurrency:\n group: sync-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: write\n pull-requests: write\n\njobs:\n sync:\n name: Sync\n uses: theholocron/.github/.github/workflows/sync.yml@main\n with:\n steps: ${{ inputs.steps }}\n secrets: inherit\n","name: Test\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\nconcurrency:\n group: test-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n id-token: write\n statuses: write\n\njobs:\n test:\n name: Test\n uses: theholocron/.github/.github/workflows/test.yml@main\n with:\n run-unit: true\n secrets: inherit\n","name: Typecheck\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\nconcurrency:\n group: typecheck-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n\njobs:\n typecheck:\n name: Typecheck\n uses: theholocron/.github/.github/workflows/typecheck.yml@main\n secrets: inherit\n","/**\n * Thin workflow wrapper templates for `holocron setup`.\n *\n * Each entry is a complete `.github/workflows/<name>.yml` that delegates\n * to the corresponding reusable `ci-<name>.yml` in `theholocron/.github`.\n * Files are overwritten on each setup run — they are generated artifacts.\n */\n\nexport { default as DEPENDABOT_CONFIG } from \"./dependabot.yml\";\n\nimport auditYml from \"./workflows/audit.yml\";\nimport bookkeepingYml from \"./workflows/bookkeeping.yml\";\nimport codeqlYml from \"./workflows/codeql.yml\";\nimport dependenciesYml from \"./workflows/dependencies.yml\";\nimport deployYml from \"./workflows/deploy.yml\";\nimport greetingsYml from \"./workflows/greetings.yml\";\nimport lintYml from \"./workflows/lint.yml\";\nimport postReleaseYml from \"./workflows/post-release.yml\";\nimport releaseYml from \"./workflows/release.yml\";\nimport reviewYml from \"./workflows/review.yml\";\nimport staleYml from \"./workflows/stale.yml\";\nimport syncYml from \"./workflows/sync.yml\";\nimport testYml from \"./workflows/test.yml\";\nimport typecheckYml from \"./workflows/typecheck.yml\";\n\n/**\n * Header prepended to every auto-generated workflow thin caller.\n *\n * Used by both `holocron setup` (initial creation) and `holocron sync-github`\n * (subsequent updates) so the header is always identical regardless of which\n * command last wrote the file.\n *\n * @param source - path within theholocron/holocron that owns the template\n * @param forPrimary - true only when writing to theholocron/.github itself\n */\nexport function workflowHeader(source = \"packages/cli/src/commands/setup-workflows.ts\", forPrimary = false): string {\n\tconst doNotEdit = forPrimary\n\t\t? `# AUTO-GENERATED — do not edit in theholocron/.github directly.`\n\t\t: `# AUTO-GENERATED — do not edit directly.`;\n\treturn [\n\t\tdoNotEdit,\n\t\t`# Source: theholocron/holocron · ${source}`,\n\t\t`# Tool: holocron sync-github`,\n\t\t`# Changes: edit source in theholocron/holocron and push to alpha or main.`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\nexport function scaffoldHeader(source = \"packages/cli/src/commands/setup.ts\"): string {\n\treturn [\n\t\t`# Scaffolded by holocron setup — edit this file freely.`,\n\t\t`# Source: theholocron/holocron · ${source}`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\nexport const WORKFLOW_TEMPLATES: Record<string, string> = {\n\tlint: lintYml,\n\ttest: testYml,\n\ttypecheck: typecheckYml,\n\tcodeql: codeqlYml,\n\treview: reviewYml,\n\t\"post-release\": postReleaseYml,\n\trelease: releaseYml,\n\tstale: staleYml,\n\tsync: syncYml,\n\tgreetings: greetingsYml,\n\tdependencies: dependenciesYml,\n\tbookkeeping: bookkeepingYml,\n\taudit: auditYml,\n\tdeploy: deployYml,\n};\n\nexport const KNOWN_WORKFLOWS = new Set(Object.keys(WORKFLOW_TEMPLATES));\n\n/**\n * GitHub check context name each CI workflow produces on a PR.\n *\n * The format is \"{caller-workflow-name} / {reusable-job-name}\". The caller\n * job's own `name:` field does NOT appear in the external check name — only\n * the calling workflow's top-level `name:` and the inner reusable-workflow\n * job name matter. Only workflows that gate merges are listed here.\n */\nexport const WORKFLOW_CHECK_CONTEXTS: Partial<Record<string, string>> = {\n\tlint: \"Lint / Lint entire codebase\",\n\ttest: \"Test / Run tests and collect coverage\",\n\ttypecheck: \"Typecheck / tsc --noEmit\",\n};\n\n/**\n * Generate the thin caller content for a workflow, optionally injecting or\n * merging `with:` overrides into the jobs block.\n *\n * Two strategies are used depending on the template:\n * - Templates that already have a `with:` block (e.g. lint):\n * the override entries are merged in, replacing existing keys and appending\n * new ones.\n * - Templates that end with ` secrets: inherit`: a new `with:` block is\n * injected immediately before `secrets: inherit`.\n * If neither pattern matches the template, a warning is emitted and the\n * base template is returned unchanged.\n */\nexport function generateThinCallerContent(\n\tname: string,\n\twithOverrides?: Record<string, unknown>,\n\tadditionalPaths?: string[]\n): string {\n\tconst base = WORKFLOW_TEMPLATES[name];\n\tif (!base) return \"\";\n\n\t// YAML treats bare [ and { as sequence/mapping nodes; single-quote them so\n\t// values like JSON arrays are kept as strings.\n\tconst yamlScalar = (v: unknown): string => {\n\t\tif (v === true) return \"true\";\n\t\tif (v === false) return \"false\";\n\t\tconst s = String(v);\n\t\treturn s.startsWith(\"[\") || s.startsWith(\"{\") ? `'${s}'` : s;\n\t};\n\tconst fmt = (k: string, v: unknown) => ` ${k}: ${yamlScalar(v)}`;\n\n\tlet result = base;\n\n\t// Append extra push.paths entries after an existing paths: block (deduplicating), or\n\t// insert a fresh paths: block after `branches: [main]` when the template has none.\n\tif (additionalPaths && additionalPaths.length > 0) {\n\t\tconst pathsBlockRe = /( {4}paths:\\n)((?:[ ]{6}- [^\\n]+\\n)+)/;\n\t\tif (pathsBlockRe.test(result)) {\n\t\t\tresult = result.replace(pathsBlockRe, (_, header, existing) => {\n\t\t\t\tconst existingPaths = new Set([...existing.matchAll(/- (.+)/g)].map((m) => m[1]));\n\t\t\t\tconst newEntries = additionalPaths\n\t\t\t\t\t.filter((p) => !existingPaths.has(p))\n\t\t\t\t\t.map((p) => ` - ${p}\\n`)\n\t\t\t\t\t.join(\"\");\n\t\t\t\treturn header + existing + newEntries;\n\t\t\t});\n\t\t} else {\n\t\t\tconst pathsBlock = ` paths:\\n${additionalPaths.map((p) => ` - ${p}\\n`).join(\"\")}`;\n\t\t\tresult = result.replace(/( {4}branches: \\[main\\]\\n)/, `$1${pathsBlock}`);\n\t\t}\n\t}\n\n\tif (!withOverrides || Object.keys(withOverrides).length === 0) return result;\n\n\t// If the template already has a with: block, merge overrides into it.\n\t// Existing keys are replaced; new keys are appended.\n\tconst withBlockRe = /( {4}with:\\n)((?:[ ]{6}[^\\n]+\\n)*)/;\n\tconst existingMatch = result.match(withBlockRe);\n\tif (existingMatch) {\n\t\tconst existingEntries = new Map(\n\t\t\texistingMatch[2]\n\t\t\t\t.split(\"\\n\")\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.map((line) => {\n\t\t\t\t\tconst m = line.match(/^ {6}([^:]+):\\s*(.*)/);\n\t\t\t\t\treturn m ? ([m[1].trim(), m[2].trim()] as [string, string]) : null;\n\t\t\t\t})\n\t\t\t\t.filter((e): e is [string, string] => e !== null)\n\t\t);\n\t\tfor (const [k, v] of Object.entries(withOverrides)) {\n\t\t\texistingEntries.set(k, yamlScalar(v));\n\t\t}\n\t\tconst merged = [...existingEntries.entries()].map(([k, v]) => ` ${k}: ${v}`).join(\"\\n\");\n\t\treturn result.replace(withBlockRe, ` with:\\n${merged}\\n`);\n\t}\n\n\t// No existing with: block — inject before ` secrets: inherit` at end.\n\tconst withBlock = Object.entries(withOverrides)\n\t\t.map(([k, v]) => fmt(k, v))\n\t\t.join(\"\\n\");\n\tconst injected = result.replace(/ {4}secrets: inherit\\n$/, ` with:\\n${withBlock}\\n secrets: inherit\\n`);\n\tif (injected === result) {\n\t\tconsole.warn(`[generateThinCallerContent] could not inject with: overrides into \"${name}\" template`);\n\t}\n\treturn injected;\n}\n\nexport interface PreviewConfig {\n\t/** Cloudflare Pages project name shared across all repos for previews. */\n\tproject: string;\n\t/**\n\t * Base domain for preview URLs (e.g. `\"preview.theholocron.dev\"`).\n\t * When set, `holocron setup` automatically provisions:\n\t * - Cloudflare Pages custom domain `*.<domain>` on the project\n\t * - DNS wildcard CNAME `*.<domain>` → `<project>.pages.dev`\n\t *\n\t * Preview URLs resolve as `<repo>-pr-<n>.<domain>`.\n\t */\n\tdomain?: string;\n}\n\n/** Org-level context used to derive preview defaults from `preview: true`. */\nexport interface OrgContext {\n\t/** GitHub org name — becomes the prefix of the default project: `<org>-preview`. */\n\torg?: string;\n\t/** Org canonical domain — becomes `preview.<domain>` for the default preview domain. */\n\tdomain?: string;\n\t/** Project name — injected as the `name` input to the deploy reusable when `docs: true`. */\n\trepoName?: string;\n}\n\n/**\n * Extract the Cloudflare Pages preview config from a deploy workflow's `with:` object.\n *\n * Accepts three forms:\n * - `preview: true` — derive both project and domain from org context\n * - `preview: { project: \"...\" }` — explicit project; domain derived from context if omitted\n * - `preview: { project: \"...\", domain: \"...\" }` — fully explicit\n *\n * Returns null when `preview:` is absent, false, or can't be resolved.\n */\nexport function extractPreviewConfig(raw: Record<string, unknown>, ctx: OrgContext = {}): PreviewConfig | null {\n\tconst preview = raw[\"preview\"];\n\tif (!preview) return null;\n\n\t// preview: true — derive both values from org context\n\tif (preview === true) {\n\t\tconst project = ctx.org ? `${ctx.org}-preview` : null;\n\t\tconst domain = ctx.domain ? `preview.${ctx.domain}` : undefined;\n\t\tif (!project) return null;\n\t\treturn { project, ...(domain ? { domain } : {}) };\n\t}\n\n\tif (typeof preview !== \"object\") return null;\n\tconst p = preview as Record<string, unknown>;\n\n\tconst project =\n\t\ttypeof p[\"project\"] === \"string\" && p[\"project\"] ? p[\"project\"] : ctx.org ? `${ctx.org}-preview` : null;\n\tif (!project) return null;\n\n\tconst domain =\n\t\ttypeof p[\"domain\"] === \"string\" && p[\"domain\"] ? p[\"domain\"] : ctx.domain ? `preview.${ctx.domain}` : undefined;\n\n\treturn { project, ...(domain ? { domain } : {}) };\n}\n\n/**\n * Generate the full thin-caller YAML for a `deploy.yml` that handles both\n * production (push to main → GitHub Pages) and preview (pull_request →\n * Cloudflare Pages) in a single file.\n *\n * Both jobs receive the same docs/storybook `with:` inputs. If the per-repo\n * config supplies `cloudflare-project` it is forwarded; otherwise the reusable\n * falls back to the `CLOUDFLARE_PAGES_PROJECT` org variable — set that once and\n * all repos with a `deploy` workflow get previews without per-repo config.\n */\nexport function generateCombinedDeployContent(\n\tdeployWith: Record<string, unknown>,\n\tpaths: string[],\n\tpreview: Pick<PreviewConfig, \"project\">\n): string {\n\tconst yamlScalar = (v: unknown): string => {\n\t\tif (v === true) return \"true\";\n\t\tif (v === false) return \"false\";\n\t\tconst s = String(v);\n\t\treturn s.startsWith(\"[\") || s.startsWith(\"{\") ? `'${s}'` : s;\n\t};\n\tconst withLines = (entries: Record<string, unknown>) =>\n\t\tObject.entries(entries)\n\t\t\t.map(([k, v]) => ` ${k}: ${yamlScalar(v)}`)\n\t\t\t.join(\"\\n\");\n\n\tconst pathsBlock = paths.length > 0 ? ` paths:\\n${paths.map((p) => ` - ${p}\\n`).join(\"\")}` : \"\";\n\n\tconst previewWith = { ...deployWith, \"cloudflare-project\": preview.project };\n\n\tconst deployWithBlock = Object.keys(deployWith).length > 0 ? ` with:\\n${withLines(deployWith)}\\n` : \"\";\n\t// previewWith always has at least cloudflare-project, so the block is never empty.\n\tconst previewWithBlock = ` with:\\n${withLines(previewWith)}\\n`;\n\n\tconst cleanupWithBlock = ` with:\\n cloudflare-project: ${preview.project}`;\n\n\treturn [\n\t\t`name: Deploy`,\n\t\t``,\n\t\t`on: # yamllint disable-line rule:truthy`,\n\t\t` push:`,\n\t\t` branches: [main]`,\n\t\t...(pathsBlock ? [`${pathsBlock}`] : []),\n\t\t` pull_request:`,\n\t\t` branches: [main]`,\n\t\t` types: [opened, synchronize, reopened, closed]`,\n\t\t...(pathsBlock ? [`${pathsBlock}`] : []),\n\t\t` workflow_dispatch:`,\n\t\t``,\n\t\t`concurrency:`,\n\t\t` group: $\\{{ github.event_name == 'pull_request' && format('deploy-preview-{0}', github.event.pull_request.number) || 'pages' }}`,\n\t\t` cancel-in-progress: $\\{{ github.event_name == 'pull_request' && github.event.action != 'closed' }}`,\n\t\t``,\n\t\t`permissions:`,\n\t\t` contents: read`,\n\t\t` deployments: write`,\n\t\t` pages: write`,\n\t\t` id-token: write`,\n\t\t` pull-requests: write`,\n\t\t``,\n\t\t`jobs:`,\n\t\t` deploy:`,\n\t\t` name: Deploy`,\n\t\t` if: \\${{ github.event_name != 'pull_request' }}`,\n\t\t` uses: theholocron/.github/.github/workflows/deploy.yml@main`,\n\t\t...(deployWithBlock ? [deployWithBlock.trimEnd()] : []),\n\t\t` secrets: inherit`,\n\t\t``,\n\t\t` preview:`,\n\t\t` name: Deploy Preview`,\n\t\t` if: \\${{ github.event_name == 'pull_request' && github.event.action != 'closed' }}`,\n\t\t` uses: theholocron/.github/.github/workflows/deploy-preview.yml@main`,\n\t\tpreviewWithBlock.trimEnd(),\n\t\t` secrets: inherit`,\n\t\t``,\n\t\t` cleanup:`,\n\t\t` name: Clean up Preview`,\n\t\t` if: \\${{ github.event_name == 'pull_request' && github.event.action == 'closed' }}`,\n\t\t` uses: theholocron/.github/.github/workflows/cleanup-preview.yml@main`,\n\t\tcleanupWithBlock,\n\t\t` secrets: inherit`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\n/**\n * Expand structured with-values to flat GitHub Actions inputs before\n * generating the thin caller. Handles:\n * - deploy shorthand: docs/storybook → type + storybook-projects\n * - preview: stripped (handled separately via extractPreviewConfig)\n * - run-chromatic object → run-chromatic: true + chromatic-projects\n * - plain arrays → JSON-stringified for YAML scalar quoting\n *\n * Used by both `holocron setup` and `sync-workflow-templates`.\n */\nexport function normalizeWorkflowWith(raw: Record<string, unknown>, repoName?: string): Record<string, unknown> {\n\tconst result = { ...raw };\n\tdelete result[\"preview\"];\n\n\tconst hasDocs = raw[\"docs\"] === true || (raw[\"docs\"] !== null && typeof raw[\"docs\"] === \"object\");\n\tconst storybookProjects = raw[\"storybook\"];\n\tif (hasDocs) {\n\t\tresult[\"type\"] = \"docs\";\n\t\tdelete result[\"docs\"];\n\t\t// Derive the `name` input (selects @theholocron/<name>-site) from caller context\n\t\t// when not already set explicitly in the config.\n\t\tif (!result[\"name\"] && repoName) result[\"name\"] = repoName;\n\t}\n\tif (Array.isArray(storybookProjects)) {\n\t\tif (!hasDocs) result[\"type\"] = \"storybook\";\n\t\tresult[\"storybook-projects\"] = JSON.stringify(\n\t\t\t(storybookProjects as Array<{ name: string; path?: string }>).map(({ name, path = \".\" }) => ({\n\t\t\t\tname,\n\t\t\t\tworkingDir: path,\n\t\t\t}))\n\t\t);\n\t\tdelete result[\"storybook\"];\n\t}\n\n\tconst runChromatic = raw[\"run-chromatic\"];\n\tif (runChromatic !== null && typeof runChromatic === \"object\" && \"projects\" in runChromatic) {\n\t\tresult[\"run-chromatic\"] = true;\n\t\tconst projects = (runChromatic as { projects: Record<string, unknown>[] }).projects.map((p) => ({\n\t\t\t...p,\n\t\t\t...(Array.isArray(p.untraced) ? { untraced: (p.untraced as string[]).join(\"\\n\") } : {}),\n\t\t}));\n\t\tresult[\"chromatic-projects\"] = JSON.stringify(projects);\n\t}\n\tfor (const [k, v] of Object.entries(result)) {\n\t\tif (Array.isArray(v)) result[k] = JSON.stringify(v);\n\t}\n\treturn result;\n}\n\n/**\n * Derive on.push.paths entries from the deploy with: shorthand.\n * Used by both `holocron setup` and `sync-workflow-templates`.\n */\nexport function deriveDeployPaths(raw: Record<string, unknown>): string[] {\n\tconst paths: string[] = [];\n\tconst docs = raw[\"docs\"];\n\tif (docs === true) {\n\t\tpaths.push(\"docs/**\");\n\t\tpaths.push(\"astro.config.ts\");\n\t\tpaths.push(\"pnpm-workspace.yaml\");\n\t\tpaths.push(\"pnpm-lock.yaml\");\n\t} else if (docs !== null && typeof docs === \"object\" && \"path\" in docs) {\n\t\tconst p = (docs as { path: string }).path;\n\t\tif (p && p !== \".\") paths.push(`${p}/**`);\n\t}\n\tconst storybookProjects = raw[\"storybook\"];\n\tif (Array.isArray(storybookProjects)) {\n\t\tfor (const s of storybookProjects as Array<{ path?: string }>) {\n\t\t\tconst p = s.path || \".\";\n\t\t\tif (p === \".\") {\n\t\t\t\tpaths.push(\"src/**\");\n\t\t\t\tpaths.push(\".storybook/**\");\n\t\t\t} else {\n\t\t\t\tpaths.push(`${p}/**`);\n\t\t\t}\n\t\t}\n\t}\n\treturn paths;\n}\n","/**\n * `holocron setup` — orchestrates per-capability setup actions across\n * every plugin loaded from `holocron.config.json`.\n *\n * Per CLAUDE.md soft-skip: each step is wrapped in a try/catch and\n * failures don't abort subsequent capabilities. The summary at the end\n * reports counts so the operator can see what worked + what didn't.\n *\n * Per the Standards: when `ctx.dryRun` is true, mutating calls are\n * replaced with \"would\" log lines. Read-only probes (e.g.,\n * `vault.list`) still run so the operator sees real state.\n *\n * The orchestrator knows about specific capability methods by name\n * (e.g., `source.enableVulnerabilityAlerts`). This deliberate coupling\n * makes the \"what does setup do\" contract explicit and concrete —\n * decoupling via a per-capability `setupSteps()` method would be more\n * extensible but pushes the same knowledge into N plugins instead of\n * one central place.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { access, copyFile, mkdir, readdir, readFile, rm, stat, symlink, unlink, writeFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, relative } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { AuthError, createFeatureResolver } from \"../auth-resolver.js\";\nimport type {\n\tAuth,\n\tDeployment,\n\tDns,\n\tEnvironments,\n\tRepoSettings,\n\tSource,\n\tTooling,\n\tVault,\n} from \"../capabilities/index.js\";\nimport { ProviderApiError } from \"../capabilities/index.js\";\nimport { ConfigError } from \"../config.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport { withSpinner } from \"../ui/progress.js\";\nimport { style } from \"../ui/style.js\";\nimport {\n\tDEPENDABOT_CONFIG,\n\tderiveDeployPaths,\n\textractPreviewConfig,\n\tgenerateCombinedDeployContent,\n\tgenerateThinCallerContent,\n\tKNOWN_WORKFLOWS,\n\tnormalizeWorkflowWith,\n\tscaffoldHeader,\n\tWORKFLOW_CHECK_CONTEXTS,\n\tworkflowHeader,\n} from \"./setup-workflows.js\";\n\n// ── .editorconfig ────────────────────────────────────────────────────\n// Canonical editor settings shared across all theholocron repos.\n// Kept in sync via `holocron setup` so drift (e.g. missing yaml glob)\n// is corrected automatically.\nfunction editorconfigContent(): string {\n\treturn [\n\t\tworkflowHeader(\"packages/cli/src/commands/setup.ts\"),\n\t\t`root = true`,\n\t\t``,\n\t\t`[*]`,\n\t\t`end_of_line = lf`,\n\t\t`charset = utf-8`,\n\t\t`trim_trailing_whitespace = true`,\n\t\t`insert_final_newline = true`,\n\t\t`indent_style = tab`,\n\t\t`indent_size = 4`,\n\t\t``,\n\t\t`[.gitattributes]`,\n\t\t`indent_style = space`,\n\t\t`indent_size = 2`,\n\t\t``,\n\t\t`[*.{json,yml,yaml}]`,\n\t\t`indent_style = space`,\n\t\t`indent_size = 2`,\n\t\t``,\n\t\t`[*.{md,mdx}]`,\n\t\t`trim_trailing_whitespace = false`,\n\t\t``,\n\t\t`[.*{rc,ignore}]`,\n\t\t`indent_style = space`,\n\t\t`indent_size = 2`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\n// ── codecov.yml ──────────────────────────────────────────────────────\n// Generates the codecov.yml for a monorepo workspace. Each package under\n// packages/ becomes an individual_component entry so Codecov shows\n// per-package coverage in PR comments and the UI.\n//\n// When a codecov.yml already exists, only the individual_components block is\n// replaced — everything else (coverage thresholds, comments, etc.) is left\n// untouched. The name field uses the directory slug, not the npm package name,\n// so the org scope (@theholocron/) is never included.\n\nexport interface WorkspacePackage {\n\tslug: string;\n\tname: string;\n}\n\nconst INDIVIDUAL_COMPONENTS_MARKER = \" individual_components:\";\n\nfunction codecovComponentBlock(packages: WorkspacePackage[]): string {\n\tif (packages.length === 0) return \"\\n []\\n\";\n\treturn (\n\t\t\"\\n\" +\n\t\tpackages\n\t\t\t.flatMap(({ slug }) => [\n\t\t\t\t` - component_id: ${slug}`,\n\t\t\t\t` name: \"${slug}\"`,\n\t\t\t\t` paths:`,\n\t\t\t\t` - packages/${slug}/**`,\n\t\t\t\t``,\n\t\t\t])\n\t\t\t.join(\"\\n\")\n\t);\n}\n\nexport function mergeCodecovComponents(existing: string, packages: WorkspacePackage[]): string {\n\tconst idx = existing.indexOf(INDIVIDUAL_COMPONENTS_MARKER);\n\tif (idx === -1) return existing;\n\treturn existing.slice(0, idx + INDIVIDUAL_COMPONENTS_MARKER.length) + codecovComponentBlock(packages);\n}\n\nexport function codecovContent(packages: WorkspacePackage[]): string {\n\treturn (\n\t\t[\n\t\t\tscaffoldHeader(),\n\t\t\t`codecov:`,\n\t\t\t` require_ci_to_pass: true`,\n\t\t\t``,\n\t\t\t`coverage:`,\n\t\t\t` precision: 2`,\n\t\t\t` round: down`,\n\t\t\t` status:`,\n\t\t\t` project:`,\n\t\t\t` default:`,\n\t\t\t` target: auto`,\n\t\t\t` threshold: 2%`,\n\t\t\t` patch:`,\n\t\t\t` default:`,\n\t\t\t` target: 80%`,\n\t\t\t``,\n\t\t\t`comment:`,\n\t\t\t` layout: \"reach,diff,flags,components\"`,\n\t\t\t` behavior: default`,\n\t\t\t` require_changes: true`,\n\t\t\t``,\n\t\t\t`component_management:`,\n\t\t\t` default_rules:`,\n\t\t\t` statuses:`,\n\t\t\t` - type: patch`,\n\t\t\t` target: 80%`,\n\t\t\t` individual_components:`,\n\t\t].join(\"\\n\") + codecovComponentBlock(packages)\n\t);\n}\n\nasync function readWorkspacePackages(repoRoot: string): Promise<WorkspacePackage[]> {\n\tconst packagesDir = join(repoRoot, \"packages\");\n\tconst entries = await readdir(packagesDir, { withFileTypes: true }).catch(() => null);\n\tif (!entries) return [];\n\tconst packages: WorkspacePackage[] = [];\n\tfor (const entry of entries) {\n\t\tif (!entry.isDirectory()) continue;\n\t\ttry {\n\t\t\tconst raw = await readFile(join(packagesDir, entry.name, \"package.json\"), \"utf8\");\n\t\t\tconst pkg = JSON.parse(raw) as { name?: string };\n\t\t\tif (typeof pkg.name === \"string\") {\n\t\t\t\tpackages.push({ slug: entry.name, name: pkg.name });\n\t\t\t}\n\t\t} catch {\n\t\t\t// no package.json or invalid JSON — skip\n\t\t}\n\t}\n\treturn packages.sort((a, b) => a.slug.localeCompare(b.slug));\n}\n\n// ── .editorconfig-checker.json ───────────────────────────────────────\n// Canonical exclusions for editorconfig-checker. LICENSE files use a\n// non-standard format and must be excluded; public/ is generated output.\nconst EDITORCONFIG_CHECKER_CONFIG =\n\tJSON.stringify(\n\t\t{\n\t\t\tVersion: \"v3.7.0\",\n\t\t\tVerbose: false,\n\t\t\tFormat: \"\",\n\t\t\tDebug: false,\n\t\t\tIgnoreDefaults: false,\n\t\t\tSpacesAfterTabs: false,\n\t\t\tNoColor: false,\n\t\t\tExclude: [\"(^|.+/)LICENSE$\", \"^public/.*\", \"\\\\.md$\", \"\\\\.mdx$\"],\n\t\t\tAllowedContentTypes: [],\n\t\t\tPassedFiles: [],\n\t\t\tDisable: {\n\t\t\t\tEndOfLine: false,\n\t\t\t\tIndentation: false,\n\t\t\t\tInsertFinalNewline: false,\n\t\t\t\tTrimTrailingWhitespace: false,\n\t\t\t\tIndentSize: false,\n\t\t\t\tMaxLineLength: false,\n\t\t\t},\n\t\t},\n\t\tnull,\n\t\t2\n\t) + \"\\n\";\n\n// ── alex config ──────────────────────────────────────────────────────\n// Canonical allow-list for the alex prose linter. Shared across all\n// theholocron repos via `holocron setup` so the list only needs to be\n// updated here.\nconst ALEX_CONFIG =\n\tJSON.stringify({ allow: [\"dead\", \"failure\", \"failures\", \"hook\", \"hooks\", \"husky\", \"period\"] }, null, 2) + \"\\n\";\n\n// ── devmoji config ───────────────────────────────────────────────────\n// Delegates to @theholocron/devmoji-config so all repos share a single\n// source of truth for emoji mappings. Lives at the repo root so it is\n// picked up for every package in the monorepo.\n// Must be .cjs because devmoji uses require() and repos set \"type\":\"module\".\n// eslint-disable comment suppresses no-undef for module.exports / require\n// in ESLint flat configs that use recommended-module globals.\nfunction devmojiConfigContent(): string {\n\treturn [\n\t\t`/* eslint-disable */`,\n\t\t`// devmoji.config.cjs — generated by holocron setup, do not edit`,\n\t\t`// https://github.com/folke/devmoji`,\n\t\t`const { defineConfig } = require(\"@theholocron/devmoji-config\");`,\n\t\t`module.exports = defineConfig();`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\n// ── .husky/prepare-commit-msg hook ───────────────────────────────────\n// 1. Validates that git user.name and user.email are configured.\n// 2. Appends the DCO Signed-off-by trailer (required on every commit).\n// 3. Runs devmoji to add an emoji to the commit subject.\n// Note: --lint is intentionally omitted. prepare-commit-msg fires before\n// the editor opens, so --lint would reject the still-empty message on\n// interactive `git commit`. Validation is handled by commitlint in commit-msg.\nfunction prepareCommitMsgHookContent(): string {\n\treturn [\n\t\t`#!/bin/sh`,\n\t\t``,\n\t\t`NAME=$(git config user.name)`,\n\t\t`EMAIL=$(git config user.email)`,\n\t\t``,\n\t\t`if [ -z \"$NAME\" ]; then`,\n\t\t`\\techo \"empty git config user.name\"`,\n\t\t`\\texit 1`,\n\t\t`fi`,\n\t\t``,\n\t\t`if [ -z \"$EMAIL\" ]; then`,\n\t\t`\\techo \"empty git config user.email\"`,\n\t\t`\\texit 1`,\n\t\t`fi`,\n\t\t``,\n\t\t`git interpret-trailers --if-exists doNothing --trailer \\\\`,\n\t\t`\\t\"Signed-off-by: $NAME <$EMAIL>\" \\\\`,\n\t\t`\\t--in-place \"$1\"`,\n\t\t``,\n\t\t`npx devmoji -e`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\n// ── canonical label set ──────────────────────────────────────────────\n// Single source of truth for labels across all theholocron repos.\n// `syncLabels` (holocron-plugin-github) diffs against these and\n// creates/updates/deletes as needed.\nexport const CANONICAL_LABELS = [\n\t{ name: \"bug\", color: \"d73a4a\", description: \"Something isn't working\" },\n\t{ name: \"chore\", color: \"ededed\", description: \"Maintenance, no user-facing change\" },\n\t{ name: \"ci\", color: \"0075ca\", description: \"CI/CD pipeline changes\" },\n\t{ name: \"dependencies\", color: \"0366d6\", description: \"Dependency update\" },\n\t{ name: \"documentation\", color: \"0075ca\", description: \"Documentation only\" },\n\t{ name: \"duplicate\", color: \"cfd3d7\", description: \"Already reported\" },\n\t{ name: \"enhancement\", color: \"a2eeef\", description: \"New feature or request\" },\n\t{ name: \"good first issue\", color: \"7057ff\", description: \"Good for newcomers\" },\n\t{ name: \"help wanted\", color: \"008672\", description: \"Extra attention needed\" },\n\t{ name: \"invalid\", color: \"e4e669\", description: \"Doesn't seem right\" },\n\t{ name: \"performance\", color: \"fbca04\", description: \"Performance improvement\" },\n\t{ name: \"question\", color: \"d876e3\", description: \"Further information requested\" },\n\t{ name: \"refactor\", color: \"cfd3d7\", description: \"Code restructuring\" },\n\t{ name: \"released\", color: \"ededed\", description: \"Included in a release\" },\n\t{ name: \"test\", color: \"bfd4f2\", description: \"Test-related changes\" },\n\t{ name: \"triage\", color: \"e4e669\", description: \"Needs investigation\" },\n\t{ name: \"wontfix\", color: \"ffffff\", description: \"Won't be addressed\" },\n] as const;\n\nexport const STALE_LABELS = [\n\t\"github_actions\",\n\t\"javascript\",\n\t\"autorelease: pending\",\n\t\"autorelease: tagged\",\n\t\"released on @alpha\",\n];\n\n// ── labeler config template ──────────────────────────────────────────\n// Maps Conventional Commit title prefixes to standard GitHub label names.\n// Written when bookkeeping is in the workflows list; read by the\n// github/issue-labeler action inside the bookkeeping reusable workflow.\n// Only applied to pull requests (CC-style regexes don't suit free-form\n// issue titles; sync-labels would strip manually applied labels on issues).\nfunction labelerConfig(): string {\n\treturn [\n\t\tworkflowHeader(\"packages/cli/src/commands/setup.ts\"),\n\t\t`bug:`,\n\t\t` - '^fix'`,\n\t\t``,\n\t\t`chore:`,\n\t\t` - '^chore(?!\\\\(deps)'`,\n\t\t``,\n\t\t`ci:`,\n\t\t` - '^ci'`,\n\t\t``,\n\t\t`dependencies:`,\n\t\t` - '^chore\\\\(deps'`,\n\t\t``,\n\t\t`documentation:`,\n\t\t` - '^docs'`,\n\t\t``,\n\t\t`enhancement:`,\n\t\t` - '^feat'`,\n\t\t``,\n\t\t`performance:`,\n\t\t` - '^perf'`,\n\t\t``,\n\t\t`refactor:`,\n\t\t` - '^refactor'`,\n\t\t``,\n\t\t`test:`,\n\t\t` - '^test'`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\n// ── repo policy presets ───────────────────────────────────────────────\n\nconst RULESET_NAME = \"holocron-default-branch\";\n\nconst BALANCED_REPO_SETTINGS: RepoSettings = {\n\tallow_squash_merge: true,\n\tallow_merge_commit: false,\n\tallow_rebase_merge: false,\n\tallow_auto_merge: true,\n\tallow_update_branch: true,\n\tdelete_branch_on_merge: true,\n\thas_issues: true,\n\thas_discussions: true,\n\thas_projects: true,\n\thas_wiki: false,\n\t// web_commit_signoff_required is intentionally omitted: GitHub rejects this\n\t// field when the organization already enforces it at org level (422). Org-level\n\t// enforcement already covers every repo — no per-repo override is needed.\n};\n\nfunction buildClassicProtectionPayload(requiredChecks: string[] = []): Record<string, unknown> {\n\treturn {\n\t\trequired_status_checks: requiredChecks.length > 0 ? { strict: false, contexts: requiredChecks } : null,\n\t\tenforce_admins: false,\n\t\trequired_pull_request_reviews: {\n\t\t\trequired_approving_review_count: 0,\n\t\t\tdismiss_stale_reviews: false,\n\t\t\trequire_code_owner_reviews: false,\n\t\t},\n\t\trestrictions: null,\n\t\tallow_force_pushes: false,\n\t\tallow_deletions: false,\n\t};\n}\n\nfunction buildRulesetPayload(requiredChecks: string[] = []): Record<string, unknown> {\n\tconst rules: Record<string, unknown>[] = [\n\t\t{ type: \"deletion\" },\n\t\t{ type: \"non_fast_forward\" },\n\t\t{\n\t\t\ttype: \"pull_request\",\n\t\t\tparameters: {\n\t\t\t\trequired_approving_review_count: 0,\n\t\t\t\tdismiss_stale_reviews_on_push: false,\n\t\t\t\trequire_code_owner_review: false,\n\t\t\t\trequire_last_push_approval: false,\n\t\t\t\trequired_review_thread_resolution: true,\n\t\t\t},\n\t\t},\n\t];\n\tif (requiredChecks.length > 0) {\n\t\trules.push({\n\t\t\ttype: \"required_status_checks\",\n\t\t\tparameters: {\n\t\t\t\trequired_status_checks: requiredChecks.map((context) => ({ context })),\n\t\t\t\tstrict_required_status_checks_policy: false,\n\t\t\t},\n\t\t});\n\t}\n\treturn {\n\t\tname: RULESET_NAME,\n\t\ttarget: \"branch\",\n\t\tenforcement: \"active\",\n\t\t// Repository admins (role 4) can bypass — required for semantic-release\n\t\t// and other automation that pushes directly to the default branch.\n\t\tbypass_actors: [{ actor_id: 4, actor_type: \"RepositoryRole\", bypass_mode: \"always\" }],\n\t\tconditions: { ref_name: { include: [\"~DEFAULT_BRANCH\"], exclude: [] } },\n\t\trules,\n\t};\n}\n\n// ── branch protection helper ─────────────────────────────────────────────────\n// Tries the modern Rulesets API first, falls back to classic branch protection\n// if rulesets return 403 (requires GitHub Team+ on private repos), and gracefully\n// skips if both APIs are unavailable (GitHub Free on private repos).\n\nasync function upsertBranchProtection(\n\tsource: Source,\n\tdryRun: boolean,\n\trequiredChecks: string[]\n): Promise<SetupStepResult> {\n\tconst step = `upsert ruleset ${RULESET_NAME}`;\n\tif (dryRun) return { capability: \"source\", step, status: \"dry-run\" };\n\n\t// Attempt 1: modern rulesets\n\ttry {\n\t\tconst existing = await source.listRulesets();\n\t\tconst found = existing.find((r) => r.name === RULESET_NAME);\n\t\tif (found) {\n\t\t\tawait source.updateRuleset(found.id, buildRulesetPayload(requiredChecks));\n\t\t\treturn { capability: \"source\", step, status: \"ok\", message: \"updated\" };\n\t\t}\n\t\tawait source.createRuleset(buildRulesetPayload(requiredChecks));\n\t\treturn { capability: \"source\", step, status: \"ok\", message: \"created\" };\n\t} catch (err) {\n\t\tif (!(err instanceof ProviderApiError) || err.status !== 403) {\n\t\t\treturn {\n\t\t\t\tcapability: \"source\",\n\t\t\t\tstep,\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t};\n\t\t}\n\t}\n\n\t// Attempt 2: classic branch protection (free-plan fallback)\n\ttry {\n\t\tconst repo = await source.getRepo();\n\t\tawait source.protectBranch(repo.defaultBranch, buildClassicProtectionPayload(requiredChecks));\n\t\treturn { capability: \"source\", step, status: \"ok\", message: `classic protection on ${repo.defaultBranch}` };\n\t} catch (err) {\n\t\tif (err instanceof ProviderApiError && err.status === 403) {\n\t\t\treturn {\n\t\t\t\tcapability: \"source\",\n\t\t\t\tstep,\n\t\t\t\tstatus: \"skip\",\n\t\t\t\tmessage: \"branch protection unavailable on private repos without GitHub Pro/Team\",\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tcapability: \"source\",\n\t\t\tstep,\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t};\n\t}\n}\n\nexport type SetupPrintLine = (line: string) => void;\n\nexport type SetupStatus = \"ok\" | \"fail\" | \"skip\" | \"dry-run\";\n\n/** Why a step failed with HTTP 403. */\nexport type FailReason = \"permissions\" | \"plan\";\n\nexport interface SetupStepResult {\n\tcapability: string;\n\tstep: string;\n\tstatus: SetupStatus;\n\tmessage?: string;\n\t/** Set when status === \"fail\" and the error was a 403. */\n\treason?: FailReason;\n}\n\nexport interface SetupReport {\n\tsteps: SetupStepResult[];\n\tsummary: { ok: number; fail: number; skip: number; dryRun: number };\n}\n\nexport interface RunSetupInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** Lets tests inject a pre-loaded loader; defaults to native dynamic import. */\n\tloader?: PluginLoader;\n\tprint?: SetupPrintLine;\n\t/** Injectable keyring backend. Tests pass `() => null` to skip real OS keychain lookups. */\n\tkeyring?: (key: string) => string | null;\n}\n\nexport async function runSetup(input: RunSetupInput): Promise<SetupReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait withSpinner(\"Loading plugins…\", () => loader.load());\n\n\tconst config = input.loaded.resolved;\n\tconst dryRun = input.context.dryRun ?? false;\n\tconst steps: SetupStepResult[] = [];\n\tconst repo = config.repo;\n\tconst effectivePreset = repo?.protection;\n\n\tprint(style.header(`Holocron setup — ${config.name}${dryRun ? \" (dry-run)\" : \"\"}`));\n\tprint(style.dim(` config: ${input.loaded.filepath}`));\n\tprint(\"\");\n\n\t// ── source: security toggles + repo policy ──────────────────────────\n\tif (loader.has(\"source\")) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tprint(style.step(\"source\"));\n\t\t// Secret scanning on public repos is always on (422); private vuln\n\t\t// reporting doesn't exist on public repos (404). Treat both as skip so\n\t\t// a public-repo setup doesn't report spurious failures.\n\t\tconst SECURITY_SKIP_CODES: Partial<Record<string, number[]>> = {\n\t\t\tenableSecretScanning: [422],\n\t\t\tenablePrivateVulnerabilityReporting: [404],\n\t\t};\n\t\tfor (const method of [\n\t\t\t\"enableVulnerabilityAlerts\",\n\t\t\t\"enableAutomatedSecurityFixes\",\n\t\t\t\"enableSecretScanning\",\n\t\t\t\"enablePrivateVulnerabilityReporting\",\n\t\t\t\"enableDependencyGraph\",\n\t\t] as const) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\n\t\t\t\t\t\"source\",\n\t\t\t\t\tmethod,\n\t\t\t\t\tdryRun,\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\tawait source[method]();\n\t\t\t\t\t},\n\t\t\t\t\t{ skipCodes: SECURITY_SKIP_CODES[method] }\n\t\t\t\t)\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tconst usesAdvancedCodeQL = (config.workflows ?? [])\n\t\t\t.map((e) => (typeof e === \"string\" ? e : e.name))\n\t\t\t.includes(\"codeql\");\n\t\tsteps.push(\n\t\t\tawait runStep(\n\t\t\t\t\"source\",\n\t\t\t\tusesAdvancedCodeQL ? \"disableDefaultCodeScanning\" : \"enableCodeScanning\",\n\t\t\t\tdryRun,\n\t\t\t\tasync () => {\n\t\t\t\t\tif (usesAdvancedCodeQL) {\n\t\t\t\t\t\tawait source.disableDefaultCodeScanning();\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn await source.enableCodeScanning();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t)\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\n\t\tif (effectivePreset && effectivePreset !== \"none\") {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"source\", \"updateRepoSettings\", dryRun, async () => {\n\t\t\t\t\tawait source.updateRepoSettings(BALANCED_REPO_SETTINGS);\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\n\t\t\tconst configuredWorkflowNames = [\n\t\t\t\t...new Set((config.workflows ?? []).map((entry) => (typeof entry === \"string\" ? entry : entry.name))),\n\t\t\t];\n\t\t\tconst requiredChecks =\n\t\t\t\teffectivePreset === \"strict\"\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t\"DCO\",\n\t\t\t\t\t\t\t...configuredWorkflowNames.flatMap((name) => {\n\t\t\t\t\t\t\t\tconst ctx = WORKFLOW_CHECK_CONTEXTS[name];\n\t\t\t\t\t\t\t\treturn ctx ? [ctx] : [];\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(repo?.requiredChecks ?? []),\n\t\t\t\t\t\t]\n\t\t\t\t\t: [];\n\t\t\tsteps.push(await upsertBranchProtection(source, dryRun, requiredChecks));\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── source: workflow thin wrappers ──────────────────────────────────\n\t// normalizeWorkflowWith and deriveDeployPaths are imported from setup-workflows.ts\n\t// so they're shared with sync-github.ts.\n\n\tconst workflows = config.workflows;\n\tif (loader.has(\"source\") && workflows && workflows.length > 0) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tprint(style.step(\"workflows\"));\n\t\tfor (const entry of workflows) {\n\t\t\tconst name = typeof entry === \"string\" ? entry : entry.name;\n\t\t\tconst rawWith = typeof entry === \"object\" ? entry.with : undefined;\n\t\t\tconst withOverrides = rawWith ? normalizeWorkflowWith(rawWith, config.name) : undefined;\n\t\t\tconst explicitPaths = typeof entry === \"object\" ? entry.paths : undefined;\n\t\t\tconst additionalPaths =\n\t\t\t\texplicitPaths ??\n\t\t\t\t(name === \"deploy\" && rawWith ? deriveDeployPaths(rawWith as Record<string, unknown>) : undefined);\n\n\t\t\t// Enforce that the test workflow has at least one test type enabled.\n\t\t\t// This check lives here so it fails at setup time rather than silently\n\t\t\t// producing a CI job that never runs any tests.\n\t\t\tif (name === \"test\" && withOverrides) {\n\t\t\t\tconst runUnit = withOverrides[\"run-unit\"];\n\t\t\t\tconst runStorybook = withOverrides[\"run-storybook\"];\n\t\t\t\tconst unitDisabled = runUnit === false;\n\t\t\t\tconst storybookDisabled = runStorybook === false;\n\t\t\t\tconst neitherEnabled = unitDisabled && storybookDisabled;\n\t\t\t\tif (neitherEnabled) {\n\t\t\t\t\tthrow new ConfigError(\n\t\t\t\t\t\t'test workflow: at least one of \"run-unit\" or \"run-storybook\" must be true. ' +\n\t\t\t\t\t\t\t\"Library repos use run-unit: true; UI/Storybook repos use run-storybook: true.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!KNOWN_WORKFLOWS.has(name)) {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\tstep: `write workflow ${name}`,\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: `unknown workflow \"${name}\" — no template available`,\n\t\t\t\t});\n\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// deploy + preview: → combined thin caller (single file, two jobs).\n\t\t\t// preview: true derives project + domain from config.org / config.docs.\n\t\t\tif (name === \"deploy\" && rawWith) {\n\t\t\t\tconst previewCfg = extractPreviewConfig(rawWith as Record<string, unknown>, {\n\t\t\t\t\torg: config.org,\n\t\t\t\t\tdomain: config.domain,\n\t\t\t\t});\n\t\t\t\tif (previewCfg) {\n\t\t\t\t\tconst paths = additionalPaths!;\n\t\t\t\t\tsteps.push(\n\t\t\t\t\t\tawait runStep(\"source\", \"write workflow deploy (with preview)\", dryRun, async () => {\n\t\t\t\t\t\t\tawait source.writeWorkflowFile(\n\t\t\t\t\t\t\t\t\"deploy.yml\",\n\t\t\t\t\t\t\t\tworkflowHeader() + generateCombinedDeployContent(withOverrides!, paths, previewCfg)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"source\", `write workflow ${name}`, dryRun, async () => {\n\t\t\t\t\tawait source.writeWorkflowFile(\n\t\t\t\t\t\t`${name}.yml`,\n\t\t\t\t\t\tworkflowHeader() + generateThinCallerContent(name, withOverrides, additionalPaths)\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── source: labeler config ───────────────────────────────────────────\n\tif (\n\t\tloader.has(\"source\") &&\n\t\t(config.workflows ?? []).map((e) => (typeof e === \"string\" ? e : e.name)).includes(\"bookkeeping\")\n\t) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .github/labeler.yml\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\".github/labeler.yml\", labelerConfig());\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t}\n\n\t// ── source: dependabot config ────────────────────────────────────────\n\tif (loader.has(\"source\") && effectivePreset !== \"none\") {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .github/dependabot.yml\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\n\t\t\t\t\t\".github/dependabot.yml\",\n\t\t\t\t\tworkflowHeader(\"packages/cli/src/commands/setup.ts\") + DEPENDABOT_CONFIG\n\t\t\t\t);\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t}\n\n\t// ── source: alex config ───────────────────────────────────────────────\n\t// Always written — not gated on protection since all prose benefits from\n\t// a consistent allow-list. Update ALEX_CONFIG above to propagate changes.\n\tif (loader.has(\"source\")) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .alexrc.json\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\".alexrc.json\", ALEX_CONFIG);\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .editorconfig\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\".editorconfig\", editorconfigContent());\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .editorconfig-checker.json\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\".editorconfig-checker.json\", EDITORCONFIG_CHECKER_CONFIG);\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write devmoji.config.cjs\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\"devmoji.config.cjs\", devmojiConfigContent());\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .husky/prepare-commit-msg\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\".husky/prepare-commit-msg\", prepareCommitMsgHookContent());\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t{\n\t\t\tconst configuredWorkflowNames = (config.workflows ?? []).map((e) => (typeof e === \"string\" ? e : e.name));\n\t\t\tconst hasTestWorkflow = configuredWorkflowNames.includes(\"test\");\n\t\t\tconst packages = await readWorkspacePackages(input.context.repoRoot);\n\t\t\tconst existing = await readFile(join(input.context.repoRoot, \"codecov.yml\"), \"utf8\").catch(() => null);\n\t\t\tif (!hasTestWorkflow && existing == null) {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\tstep: \"write codecov.yml\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"no test workflow configured\",\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runStep(\"source\", \"write codecov.yml\", dryRun, async () => {\n\t\t\t\t\t\tconst content =\n\t\t\t\t\t\t\texisting != null ? mergeCodecovComponents(existing, packages) : codecovContent(packages);\n\t\t\t\t\t\tawait source.writeRepoFile(\"codecov.yml\", content);\n\t\t\t\t\t\treturn packages.length > 0 ? `${packages.length} components` : \"no components\";\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (source.syncLabels) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"source\", \"sync labels\", dryRun, async () => {\n\t\t\t\t\treturn source.syncLabels!(CANONICAL_LABELS, STALE_LABELS);\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tconst properties: Record<string, string> = {};\n\n\t\tif (effectivePreset && effectivePreset !== \"none\") properties[\"branch_protection_level\"] = effectivePreset;\n\n\t\tconst isMonorepo = await access(join(input.context.repoRoot, \"pnpm-workspace.yaml\"))\n\t\t\t.then(() => true)\n\t\t\t.catch(() => false);\n\t\tproperties[\"monorepo\"] = String(isMonorepo);\n\n\t\tconst manual = repo?.properties ?? {};\n\t\tif (manual.lifecycle) properties[\"lifecycle\"] = manual.lifecycle;\n\t\tif (manual.open_source !== undefined) properties[\"open_source\"] = String(manual.open_source);\n\t\tif (manual.runtime_environment) properties[\"runtime_environment\"] = manual.runtime_environment;\n\t\tif (manual.uses_external_packages !== undefined)\n\t\t\tproperties[\"uses_external_packages\"] = String(manual.uses_external_packages);\n\n\t\tif (source.syncProperties) {\n\t\t\tsteps.push(await runStep(\"source\", \"sync properties\", dryRun, () => source.syncProperties!(properties)));\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tconst topics = repo?.topics ?? [];\n\t\tif (topics.length > 0 && source.syncTopics) {\n\t\t\tsteps.push(await runStep(\"source\", \"sync topics\", dryRun, () => source.syncTopics!(topics)));\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (config.description && source.syncDescription) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"source\", \"sync description\", dryRun, () => source.syncDescription!(config.description!))\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (config.homepage && source.syncHomepage) {\n\t\t\tsteps.push(await runStep(\"source\", \"sync homepage\", dryRun, () => source.syncHomepage!(config.homepage!)));\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tconst teams = repo?.teams ?? [];\n\t\tif (teams.length > 0) {\n\t\t\tif (source.syncTeams) {\n\t\t\t\t// 422 means the team is already assigned — desired state is in place,\n\t\t\t\t// so treat it as an idempotent success (skip) rather than a failure.\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runStep(\"source\", \"sync teams\", dryRun, () => source.syncTeams!(teams), { skipCodes: [422] })\n\t\t\t\t);\n\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\n\t\t\t\t// Only split on \"/\" so a bare repo name (no owner prefix) yields an\n\t\t\t\t// empty org and silently skips the CODEOWNERS write rather than\n\t\t\t\t// producing an invalid \"* @reponame/slug\" entry.\n\t\t\t\tconst repoCoord = input.context.repo ?? repo?.name ?? \"\";\n\t\t\t\tconst org = repoCoord.includes(\"/\") ? repoCoord.split(\"/\")[0]! : \"\";\n\t\t\t\tconst writeableTeams = teams\n\t\t\t\t\t.map((t) => (typeof t === \"string\" ? { slug: t, permission: \"push\" as const } : t))\n\t\t\t\t\t.filter((t) => [\"push\", \"maintain\", \"admin\"].includes(t.permission));\n\t\t\t\tif (org && writeableTeams.length > 0) {\n\t\t\t\t\tsteps.push(\n\t\t\t\t\t\tawait runStep(\"source\", \"write .github/CODEOWNERS\", dryRun, async () => {\n\t\t\t\t\t\t\tconst content = writeableTeams.map((t) => `* @${org}/${t.slug}`).join(\"\\n\") + \"\\n\";\n\t\t\t\t\t\t\tawait source.writeRepoFile(\".github/CODEOWNERS\", content);\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\tstep: \"sync teams\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"provider does not implement syncTeams\",\n\t\t\t\t});\n\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── environments ────────────────────────────────────────────────────\n\tif (loader.has(\"environments\")) {\n\t\tconst envs = loader.get(\"environments\") as Environments;\n\t\tprint(style.step(\"environments\"));\n\t\tfor (const envName of [\"staging\", \"production\"]) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"environments\", `upsert ${envName}`, dryRun, async () => {\n\t\t\t\t\tawait envs.upsertEnvironment({ name: envName });\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── docs: configure GitHub Pages ────────────────────────────────────\n\tif (loader.has(\"source\") && config.docs) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tconst resolveDeployToken = createFeatureResolver({\n\t\t\tenvName: \"HOLOCRON_DEPLOY_TOKEN\",\n\t\t\tkeyringKey: \"github.deploy\",\n\t\t});\n\t\tlet deployToken: string | undefined;\n\t\ttry {\n\t\t\tdeployToken = resolveDeployToken({ keyring: input.keyring });\n\t\t} catch (err) {\n\t\t\tif (!(err instanceof AuthError)) throw err;\n\t\t}\n\t\tprint(style.step(\"docs\"));\n\t\tif (!deployToken) {\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"source\",\n\t\t\t\tstep: \"configure GitHub Pages\",\n\t\t\t\tstatus: \"skip\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"no deploy token found — set HOLOCRON_DEPLOY_TOKEN or run: holocron auth set github.deploy <PAT>\",\n\t\t\t});\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t} else if (source.configurePages) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"source\", \"configure GitHub Pages\", dryRun, async () => {\n\t\t\t\t\tawait source.configurePages!(config.docs!, deployToken);\n\t\t\t\t\tconst parts: string[] = [config.docs!.build];\n\t\t\t\t\tif (config.docs!.domain) parts.push(`domain: ${config.docs!.domain}`);\n\t\t\t\t\tif (config.docs!.https) parts.push(\"https: enforced\");\n\t\t\t\t\treturn parts.join(\", \");\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── deployment: ensure project + preview infrastructure ─────────────\n\tif (loader.has(\"deployment\")) {\n\t\tconst deploy = loader.get(\"deployment\") as Deployment;\n\t\tprint(style.step(\"deployment\"));\n\n\t\t// Resolve preview config first so we know whether the deployment capability\n\t\t// is being used exclusively for preview infrastructure or for a direct deploy.\n\t\tconst deployEntry = (config.workflows ?? [])\n\t\t\t.map((e) => (typeof e === \"string\" ? { name: e } : e))\n\t\t\t.find((e) => e.name === \"deploy\");\n\t\tconst previewCfg = deployEntry?.with\n\t\t\t? extractPreviewConfig(deployEntry.with as Record<string, unknown>, {\n\t\t\t\t\torg: config.org,\n\t\t\t\t\tdomain: config.domain,\n\t\t\t\t})\n\t\t\t: null;\n\n\t\t// Only provision the main project when the repo is directly deploying to\n\t\t// Cloudflare Pages (no preview config). When preview: is set, the deployment\n\t\t// provider is used solely for preview infrastructure — creating a project\n\t\t// named after the repo would be an unwanted side-effect.\n\t\tif (!previewCfg) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"deployment\", `ensureProject ${config.name}`, dryRun, async () => {\n\t\t\t\t\tawait deploy.ensureProject({ name: config.name });\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (previewCfg) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"deployment\", `ensureProject ${previewCfg.project}`, dryRun, async () => {\n\t\t\t\t\tawait deploy.ensureProject({ name: previewCfg.project });\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (previewCfg?.domain && deploy.ensureCustomDomain) {\n\t\t\t// CF Pages accepts the apex domain, not a wildcard — branch deployments\n\t\t\t// then resolve automatically as <repo>-pr-<n>.<domain>.\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"deployment\", `ensureCustomDomain ${previewCfg.domain}`, dryRun, async () => {\n\t\t\t\t\tawait deploy.ensureCustomDomain!(previewCfg.project, previewCfg.domain!);\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (previewCfg?.domain && loader.has(\"dns\")) {\n\t\t\tconst dns = loader.get(\"dns\") as Dns;\n\t\t\tconst wildcardDomain = `*.${previewCfg.domain}`;\n\t\t\t// Apex CNAME so preview.theholocron.dev itself resolves.\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"dns\", `upsertRecord ${previewCfg.domain}`, dryRun, async () => {\n\t\t\t\t\tawait dns.upsertRecord(previewCfg.domain!, {\n\t\t\t\t\t\ttype: \"CNAME\",\n\t\t\t\t\t\tname: previewCfg.domain!,\n\t\t\t\t\t\tcontent: `${previewCfg.project}.pages.dev`,\n\t\t\t\t\t\tttl: 1,\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t// Wildcard CNAME so <repo>-pr-<n>.preview.theholocron.dev resolves.\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"dns\", `upsertRecord ${wildcardDomain}`, dryRun, async () => {\n\t\t\t\t\tawait dns.upsertRecord(previewCfg.domain!, {\n\t\t\t\t\t\ttype: \"CNAME\",\n\t\t\t\t\t\tname: wildcardDomain,\n\t\t\t\t\t\tcontent: `${previewCfg.project}.pages.dev`,\n\t\t\t\t\t\tttl: 1,\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── auth: ensure webhook app (optional method) ──────────────────────\n\tif (loader.has(\"auth\")) {\n\t\tconst auth = loader.get(\"auth\") as Auth;\n\t\tprint(style.step(\"auth\"));\n\t\tif (auth.ensureWebhookApp) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"auth\", \"ensureWebhookApp\", dryRun, async () => {\n\t\t\t\t\tconst result = await auth.ensureWebhookApp!();\n\t\t\t\t\treturn `webhook ${result.alreadyExists ? \"exists\" : \"created\"}`;\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t} else {\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"auth\",\n\t\t\t\tstep: \"ensureWebhookApp\",\n\t\t\t\tstatus: \"skip\",\n\t\t\t\tmessage: \"provider does not implement ensureWebhookApp\",\n\t\t\t});\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── vault: bootstrap project + configs, then read-only probe ───────\n\tif (loader.has(\"vault\")) {\n\t\tconst vault = loader.get(\"vault\") as Vault;\n\t\tprint(style.step(\"vault\"));\n\n\t\t// ensureProject — providers that have a top-level container.\n\t\tif (vault.ensureProject) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"vault\", `ensureProject ${config.name}`, dryRun, async () => {\n\t\t\t\t\tconst result = await vault.ensureProject!(config.name);\n\t\t\t\t\treturn `project ${result.alreadyExists ? \"exists\" : \"created\"}`;\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\t// ensureEnvironment — providers with a project/config split\n\t\t// (Doppler configs, Infisical environments, etc.). Canonical\n\t\t// names; per-project overrides live in the plugin's options.\n\t\tif (vault.ensureEnvironment) {\n\t\t\tfor (const envName of [\"dev\", \"stg\", \"prd\"]) {\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runStep(\"vault\", `ensureEnvironment ${envName}`, dryRun, async () => {\n\t\t\t\t\t\tconst result = await vault.ensureEnvironment!(config.name, envName);\n\t\t\t\t\t\treturn `${envName} ${result.alreadyExists ? \"exists\" : \"created\"}`;\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t}\n\t\t}\n\n\t\t// Read-only reachability probe. Runs even under --dry-run.\n\t\ttry {\n\t\t\tconst keys = await vault.list();\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"vault\",\n\t\t\t\tstep: \"list\",\n\t\t\t\tstatus: \"ok\",\n\t\t\t\tmessage: `${keys.length} keys available`,\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"vault\",\n\t\t\t\tstep: \"list\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t});\n\t\t}\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t}\n\n\t// ── tooling: sync each (many cardinality) ───────────────────────────\n\tif (loader.has(\"tooling\")) {\n\t\tconst tools = loader.get(\"tooling\") as Tooling[];\n\t\tprint(style.step(\"tooling\"));\n\t\tfor (const tool of tools) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"tooling\", `${tool.providerName}.sync`, dryRun, async () => {\n\t\t\t\t\tawait tool.sync();\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── skills: install agent skills from registry ──────────────────────\n\t// Pure local fs operation — no source plugin required. Reads skill dirs\n\t// from the installed @theholocron/skills package and copies them to the\n\t// agent-specific location, then gitignores the installed paths.\n\tif (config.skills && config.skills.length > 0 && config.agent) {\n\t\tprint(style.step(\"skills\"));\n\t\tif (!(config.agent in AGENT_SYMLINK_PATHS)) {\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"skills\",\n\t\t\t\tstep: \"install skills\",\n\t\t\t\tstatus: \"skip\",\n\t\t\t\tmessage: `agent \"${config.agent}\" has no known skill install path`,\n\t\t\t});\n\t\t} else {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"skills\", \"install skills\", dryRun, async () => {\n\t\t\t\t\treturn await installSkills({\n\t\t\t\t\t\tagent: config.agent!,\n\t\t\t\t\t\tskills: config.skills!,\n\t\t\t\t\t\trepoRoot: input.context.repoRoot,\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t}\n\n\tconst summary = steps.reduce(\n\t\t(acc, s) => {\n\t\t\tif (s.status === \"ok\") acc.ok += 1;\n\t\t\telse if (s.status === \"fail\") acc.fail += 1;\n\t\t\telse if (s.status === \"skip\") acc.skip += 1;\n\t\t\telse if (s.status === \"dry-run\") acc.dryRun += 1;\n\t\t\treturn acc;\n\t\t},\n\t\t{ ok: 0, fail: 0, skip: 0, dryRun: 0 }\n\t);\n\n\tprint(\"\");\n\tconst summaryLine = ` ${summary.ok} ok, ${summary.fail} fail, ${summary.skip} skipped${\n\t\tdryRun ? `, ${summary.dryRun} would-do` : \"\"\n\t}`;\n\tprint(summary.fail > 0 ? style.fail(summaryLine.trim()) : style.success(summaryLine.trim()));\n\n\tconst skippedSteps = steps.filter((s) => s.status === \"skip\");\n\tif (skippedSteps.length > 0) {\n\t\tprint(\"\");\n\t\tprint(style.hint(\" Skipped:\"));\n\t\tfor (const s of skippedSteps) {\n\t\t\t/* v8 ignore next -- all skip steps set message; empty fallback is defensive */\n\t\t\tprint(style.hint(` · ${s.step}${s.message ? ` (${s.message})` : \"\"}`));\n\t\t}\n\t}\n\n\tif (steps.some((s) => s.reason === \"permissions\")) {\n\t\tprint(\"\");\n\t\tprint(style.warn(\"Some steps failed with 403 (insufficient token permissions).\"));\n\t\tprint(style.hint(\" Repo-scoped operations (rulesets, settings, workflows) require a\"));\n\t\tprint(style.hint(\" fine-grained PAT passed via --token or HOLOCRON_ADMIN_TOKEN:\"));\n\t\tprint(\"\");\n\t\tprint(style.hint(\" · Administration — read and write\"));\n\t\tprint(style.hint(\" · Code scanning alerts — read and write\"));\n\t\tprint(style.hint(\" · Contents — read and write\"));\n\t\tprint(style.hint(\" · Secret scanning alerts — read and write\"));\n\t\tprint(style.hint(\" · Workflows — read and write\"));\n\t\tprint(style.hint(\" · Metadata — read (added automatically)\"));\n\t\tprint(\"\");\n\t\tprint(style.hint(\" Org-scoped operations (teams, custom properties) require\"));\n\t\tprint(style.hint(\" HOLOCRON_ORG_TOKEN — a fine-grained PAT with resource owner set to the org:\"));\n\t\tprint(\"\");\n\t\tprint(style.hint(\" · Administration — read and write (repository permission)\"));\n\t\tprint(style.hint(\" · Members — read (organization permission)\"));\n\t\tprint(style.hint(\" · Organization custom properties — read and write (organization permission)\"));\n\t\tprint(style.hint(\" · Metadata — read (repository permission, auto-included)\"));\n\t\tprint(\"\");\n\t\tprint(style.hint(\" Create tokens at: https://github.com/settings/personal-access-tokens/new\"));\n\t\tprint(style.hint(\" Then re-run: holocron setup --token <your-admin-pat>\"));\n\t\tprint(style.hint(\" Store org token: HOLOCRON_ORG_TOKEN env var or keyring key github.org\"));\n\t}\n\n\treturn { steps, summary };\n}\n\n// ── skills installer ─────────────────────────────────────────────────\n// Canonical location: .agents/skills/<name>/\n// Agent symlinks: .<agent>/skills/<name> → relative path into .agents/\n// Pattern mirrors the `npx skills add` CLI (skills.sh) for multi-agent compat.\n\ninterface SkillLockEntry {\n\tsource: string;\n\tsourceType: \"github\";\n\tskillPath: string;\n\tcomputedHash?: string;\n}\n\ninterface SkillsLock {\n\tversion: number;\n\tskills: Record<string, SkillLockEntry>;\n}\n\n/**\n * Fetch a single SKILL.md from its upstream GitHub source.\n * Verifies the SHA-256 hash when `computedHash` is present in the lock entry.\n */\nasync function fetchExternalSkill(entry: SkillLockEntry): Promise<{ content: string; stale: boolean }> {\n\tif (entry.sourceType !== \"github\") {\n\t\tthrow new Error(`unsupported sourceType: ${entry.sourceType}`);\n\t}\n\tconst url = `https://raw.githubusercontent.com/${entry.source}/HEAD/${entry.skillPath}`;\n\tconst res = await fetch(url);\n\tif (!res.ok) throw new Error(`HTTP ${res.status} fetching ${url}`);\n\tconst content = await res.text();\n\t// A hash mismatch means the upstream file changed since the lock was recorded.\n\t// Install anyway and surface via \"stale:\" so the user knows to run\n\t// `holocron skills update` to refresh the lock.\n\tconst stale = !!entry.computedHash && createHash(\"sha256\").update(content).digest(\"hex\") !== entry.computedHash;\n\treturn { content, stale };\n}\n\nconst AGENTS_SKILLS_ROOT = \".agents/skills\";\n\n/** Relative path of the agent-specific symlink. undefined = unsupported agent. */\nconst AGENT_SYMLINK_PATHS: Partial<Record<string, (name: string) => string>> = {\n\tclaude: (name) => `.claude/skills/${name}`,\n};\n\nconst GITIGNORE_BLOCK_START = \"# managed by holocron setup — skills\";\n// Safety invariant: GITIGNORE_BLOCK_START must NOT be a substring of\n// GITIGNORE_BLOCK_END. The \"# end \" prefix currently guarantees this — if\n// either string is edited, verify the invariant still holds so that\n// indexOf(GITIGNORE_BLOCK_START) cannot match inside the end marker.\nconst GITIGNORE_BLOCK_END = \"# end managed by holocron setup — skills\";\n\nexport async function installSkills({\n\tagent,\n\tskills,\n\trepoRoot,\n}: {\n\tagent: string;\n\tskills: string[];\n\trepoRoot: string;\n}): Promise<string> {\n\tconst symlinkFn = AGENT_SYMLINK_PATHS[agent];\n\tif (!symlinkFn) {\n\t\treturn `agent \"${agent}\" has no known skill install path — skipping`;\n\t}\n\n\t// Locate @theholocron/skills relative to the consumer repo.\n\t// Uses ./package.json subpath — must be declared in the package exports map.\n\t// Auto-installs if not present rather than failing with a manual instruction.\n\tconst require = createRequire(pathToFileURL(join(repoRoot, \"package.json\")));\n\tlet skillsRoot: string;\n\ttry {\n\t\tskillsRoot = dirname(require.resolve(\"@theholocron/skills/package.json\"));\n\t} catch {\n\t\tconst result = spawnSync(\"pnpm\", [\"add\", \"-D\", \"@theholocron/skills\"], {\n\t\t\tcwd: repoRoot,\n\t\t\tstdio: \"inherit\",\n\t\t});\n\t\tif (result.status !== 0) {\n\t\t\tthrow new Error(\"failed to auto-install @theholocron/skills\");\n\t\t}\n\t\ttry {\n\t\t\tskillsRoot = dirname(require.resolve(\"@theholocron/skills/package.json\"));\n\t\t} catch {\n\t\t\tthrow new Error(\"failed to auto-install @theholocron/skills\");\n\t\t}\n\t}\n\n\t// Find which skills from the previous run are no longer wanted (prune stale).\n\tconst gitignorePath = join(repoRoot, \".gitignore\");\n\tconst existingContent = await readFile(gitignorePath, \"utf8\").catch(() => \"\");\n\tconst previouslyInstalled = parsePreviousSkills(existingContent, symlinkFn);\n\tconst currentSet = new Set(skills);\n\tconst stale = previouslyInstalled.filter((n) => !currentSet.has(n));\n\tfor (const name of stale) {\n\t\tawait rm(join(repoRoot, symlinkFn(name)), { force: true }).catch(() => undefined);\n\t\tawait rm(join(repoRoot, AGENTS_SKILLS_ROOT, name), { recursive: true, force: true }).catch(() => undefined);\n\t}\n\n\tconst installed: string[] = [];\n\tconst missing: string[] = [];\n\n\tfor (const name of skills) {\n\t\tconst srcDir = join(skillsRoot, \"src\", name);\n\n\t\ttry {\n\t\t\tawait stat(srcDir);\n\t\t} catch {\n\t\t\tmissing.push(name);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// 1. Copy recursively to .agents/skills/<name>/ (handles nested reference dirs)\n\t\tconst agentsDir = join(repoRoot, AGENTS_SKILLS_ROOT, name);\n\t\tawait copyDirRecursive(srcDir, agentsDir);\n\n\t\t// 2. Relative symlink at agent-specific path → .agents/skills/<name>\n\t\tconst symlinkPath = join(repoRoot, symlinkFn(name));\n\t\tawait mkdir(dirname(symlinkPath), { recursive: true });\n\t\ttry {\n\t\t\tawait unlink(symlinkPath);\n\t\t} catch {\n\t\t\t// didn't exist — that's fine\n\t\t}\n\t\t// Forward slashes in symlink target (posix-compatible on all platforms)\n\t\tawait symlink(relative(dirname(symlinkPath), agentsDir).replace(/\\\\/g, \"/\"), symlinkPath);\n\n\t\tinstalled.push(name);\n\t}\n\n\t// ── external skills: fetch from upstream sources in skills-lock.json ─────\n\tconst externalFailed: string[] = [];\n\tconst externalStale: string[] = [];\n\tif (missing.length > 0) {\n\t\tlet lock: SkillsLock | null = null;\n\t\ttry {\n\t\t\tlock = JSON.parse(await readFile(join(skillsRoot, \"skills-lock.json\"), \"utf8\")) as SkillsLock;\n\t\t} catch {\n\t\t\t// No lock file or parse error — all missing remain unknown.\n\t\t}\n\t\tif (lock?.skills) {\n\t\t\tfor (const name of [...missing]) {\n\t\t\t\tconst entry = lock.skills[name];\n\t\t\t\tif (!entry) continue;\n\t\t\t\ttry {\n\t\t\t\t\tconst { content, stale: isStale } = await fetchExternalSkill(entry);\n\t\t\t\t\tconst agentsDir = join(repoRoot, AGENTS_SKILLS_ROOT, name);\n\t\t\t\t\tawait mkdir(agentsDir, { recursive: true });\n\t\t\t\t\tawait writeFile(join(agentsDir, \"SKILL.md\"), content);\n\t\t\t\t\tconst symlinkPath = join(repoRoot, symlinkFn(name));\n\t\t\t\t\tawait mkdir(dirname(symlinkPath), { recursive: true });\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait unlink(symlinkPath);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// didn't exist — that's fine\n\t\t\t\t\t}\n\t\t\t\t\tawait symlink(relative(dirname(symlinkPath), agentsDir).replace(/\\\\/g, \"/\"), symlinkPath);\n\t\t\t\t\tmissing.splice(missing.indexOf(name), 1);\n\t\t\t\t\tinstalled.push(name);\n\t\t\t\t\tif (isStale) externalStale.push(name);\n\t\t\t\t} catch {\n\t\t\t\t\tmissing.splice(missing.indexOf(name), 1);\n\t\t\t\t\texternalFailed.push(name);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Include all installed + still-unknown + failed skills in the gitignore.\n\tif (installed.length > 0 || stale.length > 0 || missing.length > 0 || externalFailed.length > 0) {\n\t\tawait updateSkillsGitignore(\n\t\t\tgitignorePath,\n\t\t\texistingContent,\n\t\t\t[...installed, ...missing, ...externalFailed],\n\t\t\tsymlinkFn\n\t\t);\n\t}\n\n\tconst parts: string[] = [`installed ${installed.length}`];\n\tif (stale.length > 0) parts.push(`pruned: ${stale.join(\", \")}`);\n\tif (externalStale.length > 0)\n\t\tparts.push(`stale: ${externalStale.join(\", \")} (run \\`holocron skills update\\` to refresh)`);\n\tif (externalFailed.length > 0) parts.push(`fetch failed: ${externalFailed.join(\", \")}`);\n\tif (missing.length > 0) parts.push(`unknown: ${missing.join(\", \")}`);\n\treturn parts.join(\"; \");\n}\n\n/** Extract skill names from the previous gitignore block so stale dirs can be pruned. */\nfunction parsePreviousSkills(gitignoreContent: string, symlinkFn: (n: string) => string): string[] {\n\tif (!gitignoreContent.includes(GITIGNORE_BLOCK_START)) return [];\n\tconst startIdx = gitignoreContent.indexOf(GITIGNORE_BLOCK_START);\n\tconst endIdx = gitignoreContent.indexOf(GITIGNORE_BLOCK_END, startIdx);\n\tconst block = endIdx !== -1 ? gitignoreContent.slice(startIdx, endIdx) : gitignoreContent.slice(startIdx);\n\t// Derive the symlink prefix by calling symlinkFn with a placeholder and removing it\n\tconst placeholder = \"__placeholder__\";\n\tconst symlinkPrefix = `/${symlinkFn(placeholder)}`.replace(placeholder, \"\");\n\treturn block\n\t\t.split(\"\\n\")\n\t\t.filter((line) => line.startsWith(symlinkPrefix))\n\t\t.map((line) => line.slice(symlinkPrefix.length));\n}\n\nasync function copyDirRecursive(src: string, dest: string): Promise<void> {\n\tawait mkdir(dest, { recursive: true });\n\tconst entries = await readdir(src, { withFileTypes: true });\n\tfor (const entry of entries) {\n\t\tconst srcPath = join(src, entry.name);\n\t\tconst destPath = join(dest, entry.name);\n\t\tif (entry.isDirectory()) {\n\t\t\tawait copyDirRecursive(srcPath, destPath);\n\t\t} else {\n\t\t\tawait copyFile(srcPath, destPath);\n\t\t}\n\t}\n}\n\nasync function updateSkillsGitignore(\n\tgitignorePath: string,\n\texistingContent: string,\n\tskills: string[],\n\tsymlinkFn: (name: string) => string\n): Promise<void> {\n\t// Always use forward slashes in gitignore (posix paths regardless of OS)\n\tconst entries = [`/${AGENTS_SKILLS_ROOT}/`, ...skills.map((n) => `/${symlinkFn(n)}`)];\n\tconst block = [GITIGNORE_BLOCK_START, ...entries, GITIGNORE_BLOCK_END].join(\"\\n\");\n\n\tlet content: string;\n\tif (existingContent.includes(GITIGNORE_BLOCK_START)) {\n\t\tconst start = existingContent.indexOf(GITIGNORE_BLOCK_START);\n\t\tconst end = existingContent.indexOf(GITIGNORE_BLOCK_END, start);\n\t\t// Without an end marker we cannot tell where managed entries stop and user\n\t\t// content begins, so just close the new block with a newline and discard\n\t\t// the orphaned entries rather than risk corrupting the file.\n\t\tconst afterBlock = end !== -1 ? existingContent.slice(end + GITIGNORE_BLOCK_END.length) : \"\\n\";\n\t\tcontent = existingContent.slice(0, start) + block + afterBlock;\n\t} else {\n\t\tcontent = (existingContent.trimEnd() ? existingContent.trimEnd() + \"\\n\\n\" : \"\") + block + \"\\n\";\n\t}\n\n\tawait writeFile(gitignorePath, content, \"utf8\");\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nasync function runStep(\n\tcapability: string,\n\tstep: string,\n\tdryRun: boolean,\n\tbody: () => Promise<string | void>,\n\topts: { skipCodes?: number[] } = {}\n): Promise<SetupStepResult> {\n\tif (dryRun) {\n\t\treturn { capability, step, status: \"dry-run\" };\n\t}\n\ttry {\n\t\tconst note = await body();\n\t\tconst result: SetupStepResult = { capability, step, status: \"ok\" };\n\t\tif (typeof note === \"string\") result.message = note;\n\t\treturn result;\n\t} catch (err) {\n\t\tif (err instanceof ProviderApiError) {\n\t\t\tif (err.status !== undefined && opts.skipCodes?.includes(err.status)) {\n\t\t\t\treturn { capability, step, status: \"skip\", message: err.message };\n\t\t\t}\n\t\t\tif (err.status === 403) {\n\t\t\t\tconst reason = classify403(err);\n\t\t\t\t// Plan-restriction 403s mean the feature is unavailable on the current\n\t\t\t\t// plan — not a setup failure, just a capability gap. Report as skip.\n\t\t\t\treturn { capability, step, status: reason === \"plan\" ? \"skip\" : \"fail\", message: err.message, reason };\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tcapability,\n\t\t\tstep,\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t};\n\t}\n}\n\nfunction classify403(err: ProviderApiError): FailReason {\n\tconst detailText =\n\t\ttypeof err.details === \"string\"\n\t\t\t? err.details\n\t\t\t: typeof err.details === \"object\" && err.details !== null && \"message\" in err.details\n\t\t\t\t? String((err.details as { message?: unknown }).message)\n\t\t\t\t: \"\";\n\tconst text = `${err.message} ${detailText}`.toLowerCase();\n\tif (\n\t\ttext.includes(\"advanced security\") ||\n\t\ttext.includes(\"not enabled for this repository\") ||\n\t\ttext.includes(\"upgrade\") ||\n\t\ttext.includes(\"not available on\")\n\t) {\n\t\treturn \"plan\";\n\t}\n\treturn \"permissions\";\n}\n\nfunction formatStep(step: SetupStepResult): string {\n\tconst tag = step.reason === \"permissions\" ? \" [permissions]\" : step.reason === \"plan\" ? \" [plan restriction]\" : \"\";\n\tconst detail = step.message ? style.dim(` (${step.message})`) : \"\";\n\tconst label = `${step.step}${tag}${detail}`;\n\tif (step.status === \"ok\") return ` ${style.success(label)}`;\n\tif (step.status === \"fail\") return ` ${style.fail(label)}`;\n\tif (step.status === \"dry-run\") return ` ${style.dim(`… ${label}`)}`;\n\treturn ` ${style.dim(`· ${label}`)}`;\n}\n","/**\n * `holocron skills` — install, remove, and update agent skills from @theholocron/skills.\n *\n * Unlike `holocron setup`, this command is purely local (no GitHub token\n * required). It reads `agent` and `skills` from the config and installs\n * the listed skills into `.agents/skills/<name>/` with a symlink at the\n * agent-specific path (e.g. `.claude/skills/<name>` for Claude Code).\n *\n * `holocron skills remove [name]` and `holocron skills update [name]` delegate\n * to the corresponding `npx skills` subcommands from the upstream skills CLI.\n */\n\nimport { spawnSync } from \"node:child_process\";\n\nimport type { LoadedConfig } from \"../load-config.js\";\nimport type { RuntimeContext } from \"../loader.js\";\nimport { installSkills } from \"./setup.js\";\n\n// ── shared exec ──────────────────────────────────────────────────────────────\n\ntype ExecFn = (cmd: string, args: string[], opts: { cwd: string }) => { exitCode: number };\n\nconst defaultExec: ExecFn = (cmd, args, opts) => {\n\tconst result = spawnSync(cmd, args, { cwd: opts.cwd, stdio: \"inherit\" });\n\treturn { exitCode: result.status ?? -1 };\n};\n\n// ── install ──────────────────────────────────────────────────────────────────\n\nexport interface RunSkillsInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\tprint?: (line: string) => void;\n}\n\nexport async function runSkillsInstall(input: RunSkillsInput): Promise<void> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst config = input.loaded.resolved;\n\n\tif (!config.agent || !config.skills?.length) {\n\t\tprint(\"Nothing to install — set `agent` and `skills` in holocron.config.ts\");\n\t\treturn;\n\t}\n\n\tif (input.context.dryRun) {\n\t\tprint(`Would install ${config.skills.length} skill(s) for agent: ${config.agent}`);\n\t\tfor (const name of config.skills) {\n\t\t\tprint(` → would install: ${name}`);\n\t\t}\n\t\treturn;\n\t}\n\n\tprint(`Installing ${config.skills.length} skill(s) for agent: ${config.agent}`);\n\ttry {\n\t\tconst result = await installSkills({\n\t\t\tagent: config.agent,\n\t\t\tskills: config.skills,\n\t\t\trepoRoot: input.context.repoRoot,\n\t\t});\n\t\tprint(` → ${result}`);\n\t} catch (err) {\n\t\tprint(` ✗ ${err instanceof Error ? err.message : String(err)}`);\n\t}\n}\n\n// ── remove ───────────────────────────────────────────────────────────────────\n\nexport interface RunSkillsRemoveInput {\n\tcontext: RuntimeContext;\n\t/** Skill name(s) to remove. Omit to remove all installed skills. */\n\tnames?: string[];\n\texec?: ExecFn;\n}\n\nexport interface SkillsRemoveReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n}\n\nexport function runSkillsRemove(input: RunSkillsRemoveInput): SkillsRemoveReport {\n\tconst { dryRun, repoRoot } = input.context;\n\tconst exec = input.exec ?? defaultExec;\n\tconst args = [\"skills\", \"remove\", ...(input.names ?? [])];\n\n\tif (dryRun) {\n\t\tconsole.log(`Would run: npx ${args.join(\" \")}`);\n\t\treturn { status: \"dry-run\" };\n\t}\n\n\tconst { exitCode } = exec(\"npx\", args, { cwd: repoRoot });\n\treturn { status: exitCode === 0 ? \"ok\" : \"fail\" };\n}\n\n// ── update ───────────────────────────────────────────────────────────────────\n\nexport interface RunSkillsUpdateInput {\n\tcontext: RuntimeContext;\n\t/** When given, update only this skill. Omit to update all. */\n\tname?: string;\n\texec?: ExecFn;\n}\n\nexport interface SkillsUpdateReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n}\n\nexport function runSkillsUpdate(input: RunSkillsUpdateInput): SkillsUpdateReport {\n\tconst { dryRun, repoRoot } = input.context;\n\tconst exec = input.exec ?? defaultExec;\n\tconst args = [\"skills\", \"update\", ...(input.name ? [input.name] : [])];\n\n\tif (dryRun) {\n\t\tconsole.log(`Would run: npx ${args.join(\" \")}`);\n\t\treturn { status: \"dry-run\" };\n\t}\n\n\tconst { exitCode } = exec(\"npx\", args, { cwd: repoRoot });\n\treturn { status: exitCode === 0 ? \"ok\" : \"fail\" };\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { PackagesRegistry } from \"@theholocron/components-doc/markdown\";\nimport { generateReadme } from \"@theholocron/components-doc/markdown\";\nimport { getClients, getConfigs, getDocs, getPlugins, getSkills, getThemes, getUtils } from \"@theholocron/registry-doc\";\n\nimport type { LoadedConfig } from \"../load-config.js\";\nimport type { RuntimeContext } from \"../loader.js\";\nimport { style } from \"../ui/style.js\";\n\nconst MARKER_INSTALL_START = \"<!-- holocron:installation -->\";\nconst MARKER_INSTALL_END = \"<!-- /holocron:installation -->\";\n\nconst REGISTRY_MAP: Record<string, () => PackagesRegistry> = {\n\t\"@theholocron/clients\": getClients,\n\t\"@theholocron/configs\": getConfigs,\n\t\"@theholocron/docs\": getDocs,\n\t\"@theholocron/holocron\": getPlugins,\n\t\"@theholocron/skills\": getSkills,\n\t\"@theholocron/themes\": getThemes,\n\t\"@theholocron/utils\": getUtils,\n};\n\ninterface PackageJson {\n\tname?: string;\n\thomepage?: string;\n\tbin?: Record<string, string> | string;\n\tpeerDependencies?: Record<string, string>;\n\tscripts?: Record<string, string>;\n\tworkspaces?: string[];\n}\n\nexport interface RunSyncReadmeInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\tprint?: (line: string) => void;\n\treadFileFn?: (path: string, encoding: BufferEncoding) => Promise<string>;\n\twriteFileFn?: (path: string, content: string, encoding: BufferEncoding) => Promise<void>;\n}\n\nexport interface SyncReadmeReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n\tupdated: boolean;\n\tmessage?: string;\n}\n\nfunction generateInstallBlock(pkg: PackageJson): string {\n\tconst { name = \"\", bin, peerDependencies = {} } = pkg;\n\tconst isCli = Boolean(bin);\n\tconst isReact = Boolean(peerDependencies[\"react\"]);\n\tconst lines: string[] = [];\n\n\tlines.push(\"## Installation\", \"\");\n\n\tif (isCli) {\n\t\tlines.push(\"```bash\", `npm install --global ${name}`, \"```\");\n\t} else {\n\t\tlines.push(\"```bash\", `pnpm install ${name}`, \"```\");\n\t}\n\n\tlines.push(\"\", \"## Usage\", \"\");\n\n\tif (isCli) {\n\t\tconst commands =\n\t\t\ttypeof bin === \"string\" ? [name.split(\"/\").at(-1)!] : Object.keys(bin as Record<string, string>);\n\t\tlines.push(\"```bash\");\n\t\tfor (const cmd of commands) {\n\t\t\tlines.push(`${cmd} --help`);\n\t\t}\n\t\tlines.push(\"```\");\n\t} else if (isReact) {\n\t\tlines.push(\"```tsx\", `import { } from \"${name}\";`, \"\", \"function App() {\", ` return <></>;`, \"}\", \"```\");\n\t} else {\n\t\tlines.push(\"```typescript\", `import { } from \"${name}\";`, \"```\");\n\t}\n\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Replace content between `<!-- holocron:marker -->` / `<!-- /holocron:marker -->` tags.\n * Returns the updated README string, or the original if the marker pair is absent.\n */\nfunction replaceMarkerBlock(readme: string, marker: string, content: string): string {\n\tconst start = `<!-- holocron:${marker} -->`;\n\tconst end = `<!-- /holocron:${marker} -->`;\n\tconst lines = readme.split(\"\\n\");\n\tconst startIdx = lines.findIndex((l) => l.trim() === start);\n\tconst endIdx = lines.findIndex((l) => l.trim() === end);\n\tif (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return readme;\n\tlines.splice(startIdx + 1, endIdx - startIdx - 1, \"\", ...content.split(\"\\n\"), \"\");\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Apply all README updates in a single read-write cycle.\n * Returns true if the README was found (even if no changes were needed).\n */\nasync function updateReadme(\n\trepoRoot: string,\n\tinstallBlock: string,\n\tsections: Record<string, string>,\n\tdryRun: boolean,\n\treadFileFn: (path: string, encoding: BufferEncoding) => Promise<string>,\n\twriteFileFn: (path: string, content: string, encoding: BufferEncoding) => Promise<void>\n): Promise<boolean> {\n\tconst readmePath = join(repoRoot, \"README.md\");\n\tlet content: string;\n\ttry {\n\t\tcontent = await readFileFn(readmePath, \"utf8\");\n\t} catch {\n\t\treturn false;\n\t}\n\n\tlet updated = content;\n\n\t// Replace existing marker blocks for generated sections\n\tfor (const [marker, text] of Object.entries(sections)) {\n\t\tupdated = replaceMarkerBlock(updated, marker, text);\n\t}\n\n\t// Replace or insert installation block\n\tconst lines = updated.split(\"\\n\");\n\tconst startIdx = lines.findIndex((l) => l.trim() === MARKER_INSTALL_START);\n\tconst endIdx = lines.findIndex((l) => l.trim() === MARKER_INSTALL_END);\n\tconst blockLines = installBlock.split(\"\\n\");\n\n\tif (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {\n\t\tlines.splice(startIdx + 1, endIdx - startIdx - 1, \"\", ...blockLines, \"\");\n\t\tupdated = lines.join(\"\\n\");\n\t} else {\n\t\tconst descEnd = lines.findIndex((l) => l.trim() === \"<!-- /holocron:description -->\");\n\t\tconst insertAfter = descEnd !== -1 ? descEnd : lines.findIndex((l) => /^# /.test(l));\n\t\tif (insertAfter === -1) return false;\n\t\tlines.splice(insertAfter + 1, 0, \"\", MARKER_INSTALL_START, \"\", ...blockLines, \"\", MARKER_INSTALL_END);\n\t\tupdated = lines.join(\"\\n\");\n\t}\n\n\tif (!dryRun) {\n\t\tawait writeFileFn(readmePath, updated, \"utf8\");\n\t}\n\treturn true;\n}\n\nasync function updateIndexMdxDescription(\n\trepoRoot: string,\n\tdescription: string,\n\tdryRun: boolean,\n\treadFileFn: (path: string, encoding: BufferEncoding) => Promise<string>,\n\twriteFileFn: (path: string, content: string, encoding: BufferEncoding) => Promise<void>\n): Promise<void> {\n\tconst mdxPath = join(repoRoot, \"docs\", \"src\", \"content\", \"docs\", \"index.mdx\");\n\tlet content: string;\n\ttry {\n\t\tcontent = await readFileFn(mdxPath, \"utf8\");\n\t} catch {\n\t\treturn; // file doesn't exist — skip silently\n\t}\n\tconst updated = content.replace(/^(description:\\s*).*$/m, `$1${description}`);\n\tif (updated !== content && !dryRun) {\n\t\tawait writeFileFn(mdxPath, updated, \"utf8\");\n\t}\n}\n\nexport async function runSyncReadme(input: RunSyncReadmeInput): Promise<SyncReadmeReport> {\n\tconst { loaded, context, print = console.log, readFileFn = readFile, writeFileFn = writeFile } = input;\n\n\tconst { repoRoot, dryRun = false } = context;\n\n\tconst namespaces = loaded.resolved.env?.namespaces ?? [];\n\n\tprint(style.header(`Syncing README installation block${dryRun ? \" (dry-run)\" : \"\"}…`));\n\tif (namespaces.length > 0) {\n\t\tprint(style.hint(` namespaces: ${namespaces.join(\", \")}`));\n\t}\n\n\t// Read package.json\n\tlet pkg: PackageJson;\n\ttry {\n\t\tconst raw = await readFileFn(join(repoRoot, \"package.json\"), \"utf8\");\n\t\tpkg = JSON.parse(raw) as PackageJson;\n\t} catch {\n\t\treturn { status: \"fail\", updated: false, message: \"Could not read package.json\" };\n\t}\n\n\t// Assemble generated sections (4.3)\n\tconst description = loaded.resolved.description ?? \"\";\n\tconst homepage = loaded.resolved.homepage ?? pkg.homepage ?? \"\";\n\tconst scripts = pkg.scripts ?? {};\n\tconst packages = pkg.name ? REGISTRY_MAP[pkg.name]?.() : undefined;\n\n\tconst sections = generateReadme({ description, homepage, scripts, packages });\n\tconst markerSections: Record<string, string> = {\n\t\t...(sections.packages !== undefined && { packages: sections.packages }),\n\t\tdevelopment: sections.development,\n\t\treleases: sections.releases,\n\t};\n\n\t// Single read-write pass for all README changes\n\tconst installBlock = generateInstallBlock(pkg);\n\tconst updated = await updateReadme(repoRoot, installBlock, markerSections, dryRun, readFileFn, writeFileFn);\n\n\tif (!updated) {\n\t\tprint(style.warn(\"README.md not found or has no writable location for installation block\"));\n\t\treturn { status: \"fail\", updated: false, message: \"README.md update failed\" };\n\t}\n\n\t// Update docs/src/content/docs/index.mdx frontmatter description (4.4)\n\tif (description) {\n\t\tawait updateIndexMdxDescription(repoRoot, description, dryRun, readFileFn, writeFileFn);\n\t}\n\n\tprint(dryRun ? style.hint(\" would update README.md\") : style.success(\" updated README.md\"));\n\treturn { status: dryRun ? \"dry-run\" : \"ok\", updated };\n}\n","import { access, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AuthError } from \"../auth-resolver.js\";\nimport type { Source } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport type { SetupPrintLine, SetupReport, SetupStepResult } from \"./setup.js\";\nimport { CANONICAL_LABELS, STALE_LABELS } from \"./setup.js\";\nimport { runSyncReadme } from \"./sync-readme.js\";\n\nexport const SYNC_STEPS = [\n\t\"labels\",\n\t\"properties\",\n\t\"teams\",\n\t\"topics\",\n\t\"keywords\",\n\t\"description\",\n\t\"homepage\",\n\t\"readme\",\n] as const;\nexport type SyncStep = (typeof SYNC_STEPS)[number];\n\n// Steps that write to the local filesystem only — no provider token needed.\nconst LOCAL_STEPS = new Set<SyncStep>([\"keywords\", \"description\", \"homepage\", \"readme\"]);\n\nexport interface RunSyncInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\tsteps?: string[];\n\tloader?: PluginLoader;\n\tprint?: SetupPrintLine;\n}\n\nexport async function runSync(input: RunSyncInput): Promise<SetupReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\n\tconst config = input.loaded.resolved;\n\tconst dryRun = input.context.dryRun ?? false;\n\tconst requestedSteps = input.steps;\n\tconst steps: SetupStepResult[] = [];\n\n\t// Remote steps (labels, properties, topics) always need a provider token.\n\t// Local steps (keywords, description) write to disk and only optionally\n\t// push to GitHub. Load plugins eagerly when remote steps are requested;\n\t// for local-only runs, attempt a load for the optional GitHub sync but\n\t// swallow auth errors so the command works without a token.\n\tconst needsProvider = !requestedSteps || requestedSteps.some((s) => !LOCAL_STEPS.has(s as SyncStep));\n\tif (needsProvider) {\n\t\tawait loader.load();\n\t} else {\n\t\ttry {\n\t\t\tawait loader.load();\n\t\t} catch (err) {\n\t\t\t// Only swallow auth errors (missing token). Any other load failure\n\t\t\t// (bad plugin config, unresolvable package) is re-thrown so the\n\t\t\t// operator sees it rather than getting a silent GitHub-push miss.\n\t\t\tif (!(err instanceof AuthError)) throw err;\n\t\t}\n\t}\n\n\tprint(`Holocron sync — ${config.name}${dryRun ? \" (dry-run)\" : \"\"}`);\n\tprint(` config: ${input.loaded.filepath}`);\n\tprint(\"\");\n\n\tif (loader.has(\"source\")) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tprint(\" → source\");\n\n\t\tfor (const stepName of SYNC_STEPS) {\n\t\t\tif (requestedSteps !== undefined && !requestedSteps.includes(stepName)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Local steps are handled below, outside this block.\n\t\t\tif (LOCAL_STEPS.has(stepName)) continue;\n\n\t\t\tif (stepName === \"labels\") {\n\t\t\t\tif (source.syncLabels) {\n\t\t\t\t\tsteps.push(\n\t\t\t\t\t\tawait runSyncStep(\"source\", \"sync labels\", dryRun, () =>\n\t\t\t\t\t\t\tsource.syncLabels!(CANONICAL_LABELS, STALE_LABELS)\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t} else {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync labels\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"provider does not implement syncLabels\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (stepName === \"properties\") {\n\t\t\t\tif (source.syncProperties) {\n\t\t\t\t\tconst repo = config.repo;\n\t\t\t\t\tconst properties: Record<string, string> = {};\n\t\t\t\t\tconst effectivePreset = repo?.protection;\n\t\t\t\t\tif (effectivePreset && effectivePreset !== \"none\")\n\t\t\t\t\t\tproperties[\"branch_protection_level\"] = effectivePreset;\n\t\t\t\t\tconst isMonorepo = await access(join(input.context.repoRoot, \"pnpm-workspace.yaml\"))\n\t\t\t\t\t\t.then(() => true)\n\t\t\t\t\t\t.catch(() => false);\n\t\t\t\t\tproperties[\"monorepo\"] = String(isMonorepo);\n\t\t\t\t\tconst manual = repo?.properties ?? {};\n\t\t\t\t\tif (manual.lifecycle) properties[\"lifecycle\"] = manual.lifecycle;\n\t\t\t\t\tif (manual.open_source !== undefined) properties[\"open_source\"] = String(manual.open_source);\n\t\t\t\t\tif (manual.runtime_environment) properties[\"runtime_environment\"] = manual.runtime_environment;\n\t\t\t\t\tif (manual.uses_external_packages !== undefined)\n\t\t\t\t\t\tproperties[\"uses_external_packages\"] = String(manual.uses_external_packages);\n\n\t\t\t\t\tsteps.push(\n\t\t\t\t\t\tawait runSyncStep(\"source\", \"sync properties\", dryRun, () => source.syncProperties!(properties))\n\t\t\t\t\t);\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t} else {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync properties\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"provider does not implement syncProperties\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (stepName === \"teams\") {\n\t\t\t\tconst teams = config.repo?.teams ?? [];\n\t\t\t\tif (teams.length === 0) {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync teams\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"no teams configured\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t} else if (source.syncTeams) {\n\t\t\t\t\tsteps.push(await runSyncStep(\"source\", \"sync teams\", dryRun, () => source.syncTeams!(teams)));\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\n\t\t\t\t\tconst repoCoord = input.context.repo ?? config.repo?.name ?? \"\";\n\t\t\t\t\tconst org = repoCoord.includes(\"/\") ? repoCoord.split(\"/\")[0]! : \"\";\n\t\t\t\t\tconst writeableTeams = teams\n\t\t\t\t\t\t.map((t) => (typeof t === \"string\" ? { slug: t, permission: \"push\" as const } : t))\n\t\t\t\t\t\t.filter((t) => [\"push\", \"maintain\", \"admin\"].includes(t.permission));\n\t\t\t\t\tif (org && writeableTeams.length > 0) {\n\t\t\t\t\t\tsteps.push(\n\t\t\t\t\t\t\tawait runSyncStep(\"source\", \"write .github/CODEOWNERS\", dryRun, async () => {\n\t\t\t\t\t\t\t\tconst content = writeableTeams.map((t) => `* @${org}/${t.slug}`).join(\"\\n\") + \"\\n\";\n\t\t\t\t\t\t\t\tawait source.writeRepoFile(\".github/CODEOWNERS\", content);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync teams\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"provider does not implement syncTeams\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (stepName === \"topics\") {\n\t\t\t\tconst topics = config.repo?.topics ?? [];\n\t\t\t\tif (topics.length === 0) {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync topics\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"no topics configured\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t} else if (source.syncTopics) {\n\t\t\t\t\tsteps.push(await runSyncStep(\"source\", \"sync topics\", dryRun, () => source.syncTopics!(topics)));\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t} else {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync topics\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"provider does not implement syncTopics\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Report unknown step names\n\t\tif (requestedSteps) {\n\t\t\tfor (const name of requestedSteps) {\n\t\t\t\tif (!(SYNC_STEPS as ReadonlyArray<string>).includes(name)) {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: `sync ${name}`,\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: `unknown step \"${name}\"`,\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── local-only steps (no provider token required) ──────────────────\n\t// keywords, description, homepage, and readme write to local files and\n\t// optionally push to GitHub when source is loaded. They run outside\n\t// the `if (loader.has(\"source\"))` block so they work without a token.\n\n\tfor (const stepName of [\"keywords\", \"description\", \"homepage\", \"readme\"] as const) {\n\t\tif (requestedSteps !== undefined && !requestedSteps.includes(stepName)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (stepName === \"keywords\") {\n\t\t\tconst topics = config.repo?.topics ?? [];\n\t\t\tif (topics.length === 0) {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"local\",\n\t\t\t\t\tstep: \"sync keywords\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"no topics configured\",\n\t\t\t\t});\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t} else {\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runSyncStep(\"local\", \"sync keywords\", dryRun, async () => {\n\t\t\t\t\t\tconst wrote = await writePackageJsonField(input.context.repoRoot, \"keywords\", topics);\n\t\t\t\t\t\treturn wrote\n\t\t\t\t\t\t\t? `${topics.length} keywords written`\n\t\t\t\t\t\t\t: `${topics.length} topics (no package.json)`;\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t}\n\t\t}\n\n\t\tif (stepName === \"description\") {\n\t\t\tconst description = config.description;\n\t\t\tif (!description) {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"local\",\n\t\t\t\t\tstep: \"sync description\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"no description configured\",\n\t\t\t\t});\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t} else {\n\t\t\t\tconst source = loader.has(\"source\") ? (loader.get(\"source\") as Source) : null;\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runSyncStep(\"local\", \"sync description\", dryRun, async () => {\n\t\t\t\t\t\tconst pkgWrote = await writePackageJsonField(\n\t\t\t\t\t\t\tinput.context.repoRoot,\n\t\t\t\t\t\t\t\"description\",\n\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst readmeWrote = await updateReadmeDescription(input.context.repoRoot, description);\n\t\t\t\t\t\tif (source?.syncDescription) {\n\t\t\t\t\t\t\tawait source.syncDescription(description);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst parts: string[] = [];\n\t\t\t\t\t\tif (pkgWrote) parts.push(\"package.json\");\n\t\t\t\t\t\tif (readmeWrote) parts.push(\"README.md\");\n\t\t\t\t\t\tif (source?.syncDescription) parts.push(\"GitHub\");\n\t\t\t\t\t\treturn parts.length > 0 ? parts.join(\", \") + \" updated\" : \"description synced\";\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t}\n\t\t}\n\n\t\tif (stepName === \"homepage\") {\n\t\t\tconst homepage = config.homepage;\n\t\t\tif (!homepage) {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"local\",\n\t\t\t\t\tstep: \"sync homepage\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"no homepage configured\",\n\t\t\t\t});\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t} else {\n\t\t\t\tconst source = loader.has(\"source\") ? (loader.get(\"source\") as Source) : null;\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runSyncStep(\"local\", \"sync homepage\", dryRun, async () => {\n\t\t\t\t\t\tconst pkgWrote = await writePackageJsonField(input.context.repoRoot, \"homepage\", homepage);\n\t\t\t\t\t\tif (source?.syncHomepage) {\n\t\t\t\t\t\t\tawait source.syncHomepage(homepage);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst parts: string[] = [];\n\t\t\t\t\t\tif (pkgWrote) parts.push(\"package.json\");\n\t\t\t\t\t\tif (source?.syncHomepage) parts.push(\"GitHub\");\n\t\t\t\t\t\treturn parts.length > 0 ? parts.join(\", \") + \" updated\" : \"homepage synced\";\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t}\n\t\t}\n\n\t\tif (stepName === \"readme\") {\n\t\t\tconst report = await runSyncReadme({ loaded: input.loaded, context: input.context, print: () => {} });\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"local\",\n\t\t\t\tstep: \"sync readme\",\n\t\t\t\tstatus: report.status === \"ok\" ? \"ok\" : report.status === \"dry-run\" ? \"dry-run\" : \"skip\",\n\t\t\t\t...(report.message ? { message: report.message } : {}),\n\t\t\t});\n\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\tconst summary = steps.reduce(\n\t\t(acc, s) => {\n\t\t\tif (s.status === \"ok\") acc.ok += 1;\n\t\t\telse if (s.status === \"fail\") acc.fail += 1;\n\t\t\telse if (s.status === \"skip\") acc.skip += 1;\n\t\t\telse if (s.status === \"dry-run\") acc.dryRun += 1;\n\t\t\treturn acc;\n\t\t},\n\t\t{ ok: 0, fail: 0, skip: 0, dryRun: 0 }\n\t);\n\n\tprint(\"\");\n\tprint(\n\t\t` ${summary.ok} ok, ${summary.fail} fail, ${summary.skip} skipped${\n\t\t\tdryRun ? `, ${summary.dryRun} would-do` : \"\"\n\t\t}`\n\t);\n\n\treturn { steps, summary };\n}\n\nasync function runSyncStep(\n\tcapability: string,\n\tstep: string,\n\tdryRun: boolean,\n\tbody: () => Promise<string | void>\n): Promise<SetupStepResult> {\n\tif (dryRun) {\n\t\treturn { capability, step, status: \"dry-run\" };\n\t}\n\ttry {\n\t\tconst note = await body();\n\t\tconst result: SetupStepResult = { capability, step, status: \"ok\" };\n\t\tif (typeof note === \"string\") result.message = note;\n\t\treturn result;\n\t} catch (err) {\n\t\treturn {\n\t\t\tcapability,\n\t\t\tstep,\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t};\n\t}\n}\n\nfunction formatSyncStep(step: SetupStepResult): string {\n\tconst icon = step.status === \"ok\" ? \"✓\" : step.status === \"fail\" ? \"✗\" : step.status === \"dry-run\" ? \"…\" : \"·\";\n\tconst detail = step.message ? ` (${step.message})` : \"\";\n\treturn ` ${icon} ${step.step}${detail}`;\n}\n\nasync function writePackageJsonField(repoRoot: string, field: string, value: unknown): Promise<boolean> {\n\tconst pkgPath = join(repoRoot, \"package.json\");\n\tlet content: string;\n\ttry {\n\t\tcontent = await readFile(pkgPath, \"utf8\");\n\t} catch {\n\t\treturn false;\n\t}\n\tconst pkg = JSON.parse(content) as Record<string, unknown>;\n\tpkg[field] = value;\n\tawait writeFile(pkgPath, JSON.stringify(pkg, null, 2) + \"\\n\", \"utf8\");\n\treturn true;\n}\n\nconst README_DESC_START = \"<!-- holocron:description -->\";\nconst README_DESC_END = \"<!-- /holocron:description -->\";\n\nasync function updateReadmeDescription(repoRoot: string, description: string): Promise<boolean> {\n\tconst readmePath = join(repoRoot, \"README.md\");\n\tlet content: string;\n\ttry {\n\t\tcontent = await readFile(readmePath, \"utf8\");\n\t} catch {\n\t\treturn false;\n\t}\n\tconst lines = content.split(\"\\n\");\n\n\tconst startIdx = lines.findIndex((l) => l.trim() === README_DESC_START);\n\tconst endIdx = lines.findIndex((l) => l.trim() === README_DESC_END);\n\tif (startIdx !== -1) {\n\t\tif (endIdx === -1 || endIdx <= startIdx) return false;\n\t\tlines.splice(startIdx + 1, endIdx - startIdx - 1, description);\n\t\tawait writeFile(readmePath, lines.join(\"\\n\"), \"utf8\");\n\t\treturn true;\n\t}\n\n\tconst h1Index = lines.findIndex((l) => /^# /.test(l));\n\tif (h1Index === -1) return false;\n\n\tlines.splice(h1Index + 1, 0, \"\", README_DESC_START, description, README_DESC_END);\n\tawait writeFile(readmePath, lines.join(\"\\n\"), \"utf8\");\n\treturn true;\n}\n","name: Auto Commit\ndescription: >\n Commit and push any file changes using stefanzweifel/git-auto-commit-action.\n If a branch name is provided and differs from the current branch, a new branch\n is created automatically.\n\ninputs:\n token:\n description: >\n GitHub token with push access to the target branch. Used to authenticate\n the git remote so the commit can be pushed.\n required: true\n branch:\n description: >\n Branch to commit to. Leave empty to commit to the current branch (useful\n in PR contexts). Provide an explicit name (e.g. chore/auto-sync) to push\n to a separate branch.\n required: false\n default: \"\"\n commit-message:\n description: Commit message.\n required: true\n commit-options:\n description: >\n Additional options passed to git commit (e.g. --no-verify).\n required: false\n default: \"\"\n commit-user-name:\n description: Git user.name for the commit.\n required: false\n default: \"github-actions[bot]\"\n commit-user-email:\n description: Git user.email for the commit.\n required: false\n default: \"41898282+github-actions[bot]@users.noreply.github.com\"\n commit-author:\n description: >\n Git author string in \"Name <email>\" format.\n required: false\n default: \"github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>\"\n\noutputs:\n changes-detected:\n description: \"'true' if any files were committed, 'false' otherwise.\"\n value: ${{ steps.commit.outputs.changes_detected }}\n\nruns:\n using: composite\n steps:\n - name: Configure git remote with token\n shell: bash\n run: |\n REMOTE_URL=$(git remote get-url origin)\n AUTHED_URL=$(echo \"$REMOTE_URL\" | sed \"s|https://|https://x-access-token:${TOKEN}@|\")\n git remote set-url origin \"$AUTHED_URL\"\n env:\n TOKEN: ${{ inputs.token }}\n\n - name: Reset branch to current HEAD\n if: ${{ inputs.branch != '' }}\n shell: bash\n run: git checkout -B \"$BRANCH\"\n env:\n BRANCH: ${{ inputs.branch }}\n\n - uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7.2.0\n id: commit\n with:\n branch: ${{ inputs.branch }}\n commit_message: ${{ inputs.commit-message }}\n commit_options: ${{ inputs.commit-options }}\n commit_user_name: ${{ inputs.commit-user-name }}\n commit_user_email: ${{ inputs.commit-user-email }}\n commit_author: ${{ inputs.commit-author }}\n","name: Install dependencies\ndescription: Install project dependencies with pnpm frozen lockfile.\n\nruns:\n using: composite\n\n steps:\n - name: Install dependencies\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n shell: bash\n run: pnpm install --frozen-lockfile\n","name: Setup\ndescription: Prepare the environment and install project dependencies.\n\ninputs:\n node-version:\n description: Node.js version\n required: false\n default: \"22.x\"\n\nruns:\n using: composite\n\n steps:\n - uses: theholocron/.github/.github/actions/setup-node@main\n with:\n node-version: ${{ inputs.node-version }}\n\n - uses: theholocron/.github/.github/actions/install@main\n\n - name: Cache Turbo artifacts\n if: ${{ hashFiles('turbo.json') != '' }}\n uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0\n with:\n path: .turbo\n key: turbo-${{ runner.os }}-${{ github.sha }}\n restore-keys: |\n turbo-${{ runner.os }}-\n","name: Setup Node\ndescription: Install pnpm and Node.js with pnpm dependency caching.\n\ninputs:\n node-version:\n description: Node.js version\n required: false\n default: \"22.x\"\nruns:\n using: composite\n\n steps:\n - name: Setup pnpm\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4\n\n - name: Setup Node.js\n uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0\n with:\n node-version: ${{ hashFiles('.node-version') != '' && '' || inputs.node-version }}\n node-version-file: ${{ hashFiles('.node-version') != '' && '.node-version' || '' }}\n cache: ${{ hashFiles('pnpm-lock.yaml') != '' && 'pnpm' || '' }}\n # Do NOT add registry-url here. setup-node writes .npmrc with\n # _authToken=${NODE_AUTH_TOKEN} and sets NPM_CONFIG_USERCONFIG to it.\n # pnpm reads that file, fails env-var substitution when the token is\n # empty, and loses auth entirely. Without registry-url, pnpm 10.15+\n # handles Trusted Publishing via its own native OIDC exchange.\n\n - name: Add node_modules/.bin to PATH\n shell: bash\n run: echo \"$GITHUB_WORKSPACE/node_modules/.bin\" >> $GITHUB_PATH\n","name: Audit\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n build-script:\n description: Script to build and upload bundle stats to Codecov\n type: string\n required: false\n default: pnpm build\n run-knip:\n description: Run Knip to detect unused files, exports, and dependencies\n type: boolean\n required: false\n default: false\n run-performance:\n description: Run Lighthouse CI performance audit (requires a lighthouse config file)\n type: boolean\n required: false\n default: false\n lighthouse-config:\n description: >\n Path to the Lighthouse CI config file passed as --config to lhci autorun.\n Defaults to lighthouse.config.cjs (the org standard).\n type: string\n required: false\n default: lighthouse.config.cjs\n knip-script:\n description: Script that invokes Knip (must exit non-zero on findings)\n type: string\n required: false\n default: pnpm run audit\n secrets:\n CODECOV_TOKEN:\n required: false\n LHCI_GITHUB_APP_TOKEN:\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n bundle-size:\n name: Audit the bundle size\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: eval \"$BUILD_SCRIPT\"\n name: Build and upload bundle stats\n env:\n BUILD_SCRIPT: ${{ inputs.build-script }}\n CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}\n\n knip:\n name: Knip\n if: ${{ inputs.run-knip }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n persist-credentials: false\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: eval \"$KNIP_SCRIPT\"\n name: Run Knip\n env:\n KNIP_SCRIPT: ${{ inputs.knip-script }}\n\n performance:\n name: Audit the performance\n if: ${{ inputs.run-performance }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: npm install -g @lhci/cli@0.14.x\n name: Install Lighthouse CLI\n\n - run: lhci autorun --config=\"$LIGHTHOUSE_CONFIG\"\n name: Run Lighthouse CI\n env:\n LIGHTHOUSE_CONFIG: ${{ inputs.lighthouse-config }}\n LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}\n","name: Bookkeeping\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n configuration-path:\n description: Path to the labeler configuration file in the calling repo\n type: string\n required: false\n default: .github/labeler.yml\n\njobs:\n label:\n name: Apply Labels\n permissions:\n contents: read\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n sparse-checkout: ${{ inputs.configuration-path || '.github/labeler.yml' }}\n sparse-checkout-cone-mode: false\n\n - uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4\n if: ${{ github.event_name == 'pull_request' && hashFiles(inputs.configuration-path || '.github/labeler.yml') != '' }}\n # v3.4 bundles Node 20; allow it to run under Actions' current default.\n env:\n ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true\n with:\n # Fall back to default path when triggered directly (not via workflow_call)\n # because inputs.* defaults only apply on workflow_call events.\n configuration-path: ${{ inputs.configuration-path || '.github/labeler.yml' }}\n include-title: 1\n include-body: 0\n sync-labels: 1\n enable-versioned-regex: 0\n repo-token: ${{ github.token }}\n","name: Clean up Preview\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n cloudflare-project:\n description: >\n Cloudflare Pages project name. Falls back to the CLOUDFLARE_PAGES_PROJECT\n org variable when omitted.\n required: false\n type: string\n default: \"\"\n\njobs:\n cleanup:\n name: Clean up Preview\n runs-on: ubuntu-latest\n permissions:\n contents: read\n deployments: write\n pull-requests: write\n steps:\n - name: Delete Cloudflare Pages deployments for branch\n if: ${{ inputs.cloudflare-project != '' || vars.CLOUDFLARE_PAGES_PROJECT != '' }}\n env:\n CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}\n CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}\n PROJECT: ${{ inputs.cloudflare-project || vars.CLOUDFLARE_PAGES_PROJECT }}\n BRANCH: ${{ github.event.repository.name }}-pr-${{ github.event.pull_request.number }}\n GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n run: |\n DEPLOYMENTS=$(curl -s \\\n \"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/${PROJECT}/deployments\" \\\n -H \"Authorization: Bearer ${CLOUDFLARE_API_TOKEN}\" \\\n | jq -r --arg b \"$BRANCH\" \\\n '.result[] | select(.deployment_trigger.metadata.branch == $b) | .id')\n\n if [ -z \"$DEPLOYMENTS\" ]; then\n echo \"No deployments found for branch ${BRANCH} — nothing to clean up.\"\n exit 0\n fi\n\n for id in $DEPLOYMENTS; do\n echo \"Deleting CF Pages deployment: $id\"\n curl -s -X DELETE \\\n \"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/${PROJECT}/deployments/${id}?force=true\" \\\n -H \"Authorization: Bearer ${CLOUDFLARE_API_TOKEN}\" | jq -r 'if .success then \" ✓ deleted\" else \" ✗ \\(.errors[0].message)\" end'\n done\n\n # Mark the GitHub Deployment environment as inactive.\n ENV_NAME=\"${PROJECT} (Preview)\"\n gh api \"repos/${GITHUB_REPOSITORY}/deployments\" \\\n | jq -r \".[] | select(.environment == \\\"${ENV_NAME}\\\") | .id\" \\\n | while read -r deploy_id; do\n gh api \"repos/${GITHUB_REPOSITORY}/deployments/${deploy_id}/statuses\" \\\n --method POST --field state=inactive 2>/dev/null || true\n done\n","name: CodeQL\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n language:\n description: CodeQL language to analyze\n type: string\n required: false\n default: javascript-typescript\n\njobs:\n analyze:\n name: Analyze (${{ inputs.language }})\n permissions:\n actions: read\n contents: read\n security-events: write\n runs-on: ubuntu-latest\n timeout-minutes: 45\n # Do not cancel in-progress security scans.\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0\n name: Initialize CodeQL\n with:\n languages: ${{ inputs.language }}\n\n - uses: github/codeql-action/autobuild@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0\n name: Autobuild\n\n - uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0\n name: Analyze\n with:\n category: /language:${{ inputs.language }}\n","name: Dependencies\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n merge-token:\n description: >\n Optional privileged token for auto-merge. Falls back to GITHUB_TOKEN.\n Required when branch protection enforces required reviews — GITHUB_TOKEN\n cannot approve its own PRs.\n required: false\n\njobs:\n dependabot:\n name: Update the dependencies\n permissions:\n contents: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n if: github.event.pull_request.user.login == 'dependabot[bot]'\n steps:\n - uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0\n name: Fetch Dependabot metadata\n id: metadata\n\n - run: gh pr merge --auto --squash \"$PR_URL\"\n # --squash is intentional: repo protection sets allow_merge_commit: false,\n # so --merge would fail on any repo using the standard preset.\n name: Enable auto-merge for Dependabot PRs\n if: steps.metadata.outputs.update-type == 'version-update:semver-patch'\n env:\n PR_URL: ${{ github.event.pull_request.html_url }}\n GH_TOKEN: ${{ secrets.merge-token || github.token }}\n","name: Deploy\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n type:\n description: \"Type of deployment: docs or storybook\"\n required: true\n type: string\n name:\n description: Repo name prefix used to filter the docs site package (<name>-site); omit to run pnpm -C docs build\n required: false\n type: string\n default: \"\"\n storybook-projects:\n description: >\n JSON array of { \"name\"?, \"workingDir\", \"outputDir\"? } objects for storybook deploys.\n Each is built via `pnpm -C <workingDir> build:storybook`. If \"name\" is provided the\n output is placed under `sandbox/<name>/`; omit \"name\" for single-repo deploys and the\n output lands directly in `sandbox/`.\n type: string\n required: false\n default: \"[]\"\n build-script:\n description: pnpm script that builds the Storybook static output (single storybook, type:storybook only)\n type: string\n required: false\n default: build:storybook\n output-dir:\n description: Directory where Storybook writes its static output (single storybook, type:storybook only)\n type: string\n required: false\n default: storybook-static\n\njobs:\n deploy:\n name: Deploy\n runs-on: ubuntu-latest\n permissions:\n contents: read\n pages: write\n id-token: write\n environment:\n name: github-pages\n url: ${{ steps.deployment.outputs.page_url }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Build docs site\n if: ${{ inputs.type == 'docs' && inputs.name != '' }}\n env:\n SITE_NAME: ${{ inputs.name }}\n run: pnpm --filter @theholocron/\"$SITE_NAME\"-site build\n\n - name: Build docs site\n if: ${{ inputs.type == 'docs' && inputs.name == '' }}\n run: pnpm -C docs build\n\n - name: Build Storybook projects\n if: ${{ inputs.storybook-projects != '[]' }}\n env:\n PROJECTS: ${{ inputs.storybook-projects }}\n run: |\n echo \"$PROJECTS\" | jq -c '.[]' | while IFS= read -r project; do\n workingDir=$(echo \"$project\" | jq -r '.workingDir')\n pnpm -C \"$workingDir\" build:storybook\n done\n\n - name: Build Storybook\n if: ${{ inputs.type == 'storybook' && inputs.storybook-projects == '[]' }}\n env:\n BUILD_SCRIPT: ${{ inputs.build-script }}\n run: pnpm run \"$BUILD_SCRIPT\"\n\n - name: Assemble site\n env:\n DEPLOY_TYPE: ${{ inputs.type }}\n PROJECTS: ${{ inputs.storybook-projects }}\n STORYBOOK_OUTPUT_DIR: ${{ inputs.output-dir }}\n run: |\n mkdir -p _site\n if [ \"$DEPLOY_TYPE\" = \"docs\" ]; then\n cp -r docs/dist/. _site/\n fi\n if [ \"$PROJECTS\" != \"[]\" ]; then\n echo \"$PROJECTS\" | jq -c '.[]' | while IFS= read -r project; do\n name=$(echo \"$project\" | jq -r '.name // \"\"')\n workingDir=$(echo \"$project\" | jq -r '.workingDir')\n outputDir=$(echo \"$project\" | jq -r '.outputDir // \"storybook-static\"')\n if [ -n \"$name\" ]; then\n target=\"_site/sandbox/${name}\"\n else\n target=\"_site/sandbox\"\n fi\n mkdir -p \"$target\"\n cp -r \"${workingDir}/${outputDir}/.\" \"$target/\"\n done\n elif [ \"$DEPLOY_TYPE\" = \"storybook\" ]; then\n mkdir -p _site/sandbox\n cp -r \"${STORYBOOK_OUTPUT_DIR}/.\" _site/sandbox/\n fi\n\n - uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1\n name: Upload pages artifact\n with:\n path: _site\n\n - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5\n id: deployment\n name: Deploy to GitHub Pages\n","name: Deploy Preview\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n type:\n description: \"Type of deployment: docs or storybook\"\n required: true\n type: string\n name:\n description: Repo name prefix used to filter the docs site package (<name>-site); omit to run pnpm -C docs build\n required: false\n type: string\n default: \"\"\n storybook-projects:\n description: >\n JSON array of { \"name\"?, \"workingDir\", \"outputDir\"? } objects for storybook deploys.\n Each is built via `pnpm -C <workingDir> build:storybook`. If \"name\" is provided the\n output is placed under `sandbox/<name>/`; omit \"name\" for single-repo deploys and the\n output lands directly in `sandbox/`.\n type: string\n required: false\n default: \"[]\"\n build-script:\n description: pnpm script that builds the Storybook static output (single storybook, type:storybook only)\n type: string\n required: false\n default: build:storybook\n output-dir:\n description: Directory where Storybook writes its static output (single storybook, type:storybook only)\n type: string\n required: false\n default: storybook-static\n cloudflare-project:\n description: >\n Cloudflare Pages project name. Falls back to the CLOUDFLARE_PAGES_PROJECT\n org variable when omitted — set that variable once and all repos get previews\n without per-repo config.\n required: false\n type: string\n default: \"\"\n\njobs:\n deploy-preview:\n name: Deploy Preview\n runs-on: ubuntu-latest\n permissions:\n contents: read\n deployments: write\n pull-requests: write\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Build docs site\n if: ${{ inputs.type == 'docs' && inputs.name != '' }}\n env:\n SITE_NAME: ${{ inputs.name }}\n run: pnpm --filter @theholocron/\"$SITE_NAME\"-site build\n\n - name: Build docs site\n if: ${{ inputs.type == 'docs' && inputs.name == '' }}\n run: pnpm -C docs build\n\n - name: Build Storybook projects\n if: ${{ inputs.storybook-projects != '[]' }}\n env:\n PROJECTS: ${{ inputs.storybook-projects }}\n run: |\n echo \"$PROJECTS\" | jq -c '.[]' | while IFS= read -r project; do\n workingDir=$(echo \"$project\" | jq -r '.workingDir')\n pnpm -C \"$workingDir\" build:storybook\n done\n\n - name: Build Storybook\n if: ${{ inputs.type == 'storybook' && inputs.storybook-projects == '[]' }}\n env:\n BUILD_SCRIPT: ${{ inputs.build-script }}\n run: pnpm run \"$BUILD_SCRIPT\"\n\n - name: Assemble site\n env:\n DEPLOY_TYPE: ${{ inputs.type }}\n SITE_NAME: ${{ inputs.name }}\n PROJECTS: ${{ inputs.storybook-projects }}\n STORYBOOK_OUTPUT_DIR: ${{ inputs.output-dir }}\n run: |\n mkdir -p _site\n if [ \"$DEPLOY_TYPE\" = \"docs\" ]; then\n if [ -n \"$SITE_NAME\" ]; then\n # Site built with base: /<name>/ — nest under _site/<name>/ so asset\n # paths match (/name/_astro/... → served at /name/_astro/...).\n mkdir -p \"_site/${SITE_NAME}\"\n cp -r docs/dist/. \"_site/${SITE_NAME}/\"\n # Redirect root to the base path so the preview URL lands correctly.\n printf \"/ /%s/ 301\\n\" \"$SITE_NAME\" > _site/_redirects\n else\n cp -r docs/dist/. _site/\n fi\n fi\n if [ \"$PROJECTS\" != \"[]\" ]; then\n echo \"$PROJECTS\" | jq -c '.[]' | while IFS= read -r project; do\n name=$(echo \"$project\" | jq -r '.name // \"\"')\n workingDir=$(echo \"$project\" | jq -r '.workingDir')\n outputDir=$(echo \"$project\" | jq -r '.outputDir // \"storybook-static\"')\n if [ -n \"$name\" ]; then\n target=\"_site/sandbox/${name}\"\n else\n target=\"_site/sandbox\"\n fi\n mkdir -p \"$target\"\n cp -r \"${workingDir}/${outputDir}/.\" \"$target/\"\n done\n elif [ \"$DEPLOY_TYPE\" = \"storybook\" ]; then\n mkdir -p _site/sandbox\n cp -r \"${STORYBOOK_OUTPUT_DIR}/.\" _site/sandbox/\n fi\n\n - uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4.0.0\n id: deploy\n name: Deploy to Cloudflare Pages\n # Skip when neither the per-repo input nor the org variable is set.\n if: ${{ inputs.cloudflare-project != '' || vars.CLOUDFLARE_PAGES_PROJECT != '' }}\n with:\n apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}\n accountId: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}\n packageManager: npm\n command: >-\n pages deploy _site\n --project-name ${{ inputs.cloudflare-project || vars.CLOUDFLARE_PAGES_PROJECT }}\n --branch ${{ github.event.repository.name }}-pr-${{ github.event.pull_request.number }}\n --commit-dirty=true\n\n - name: Report preview URL\n if: ${{ steps.deploy.outputs.pages-deployment-alias-url != '' }}\n env:\n GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n ALIAS: ${{ steps.deploy.outputs.pages-deployment-alias-url }}\n SITE_NAME: ${{ inputs.name }}\n PROJECT: ${{ inputs.cloudflare-project || vars.CLOUDFLARE_PAGES_PROJECT }}\n run: |\n PREVIEW_URL=\"${ALIAS%/}${SITE_NAME:+/${SITE_NAME}}/\"\n # GITHUB_HEAD_REF is the PR branch name — links the deployment to this PR's sidebar widget.\n PAYLOAD=$(printf '{\"ref\":\"%s\",\"environment\":\"%s\",\"description\":\"Cloudflare Pages\",\"production_environment\":false,\"auto_merge\":false,\"required_contexts\":[]}' \\\n \"$GITHUB_HEAD_REF\" \"${PROJECT} (Preview)\")\n DEPLOY_ID=$(echo \"$PAYLOAD\" | gh api \"repos/${GITHUB_REPOSITORY}/deployments\" \\\n --method POST --input - | jq -r '.id')\n gh api \"repos/${GITHUB_REPOSITORY}/deployments/${DEPLOY_ID}/statuses\" \\\n --method POST --field state=success --field environment_url=\"${PREVIEW_URL}\"\n","name: Greetings\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n\njobs:\n greeting:\n name: Greet first-time contributors\n permissions:\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n # Group by the issue/PR number so duplicate events don't race each other.\n steps:\n - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0\n name: Greet on first contribution\n with:\n script: |\n // Only greet on the initial open — ignore synchronize, reopened, etc.\n if (context.payload.action !== 'opened') return;\n\n const actor = context.actor;\n const { owner, repo } = context.repo;\n\n // Payload inspection is more reliable than context.eventName for detecting\n // whether this is an issue vs. PR event — works regardless of how GitHub\n // propagates event names through workflow_call chains.\n const isIssue = !!context.payload.issue && !context.payload.pull_request;\n // listForRepo returns both issues and PRs (GitHub treats PRs as issues),\n // sorted newest-first. Filter by type to track first-issue and first-PR\n // independently, and avoid search-index eventual-consistency lag.\n const { data: recent } = await github.rest.issues.listForRepo({\n owner, repo,\n creator: actor,\n state: 'all',\n per_page: 100\n });\n\n const sameType = recent.filter(item =>\n isIssue ? !item.pull_request : !!item.pull_request\n );\n\n if (sameType.length !== 1) return;\n const body = isIssue\n ? `Hey @${actor}!\\n\\nWe really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we are a limited number of volunteers, so it is possible that this will not be addressed as swiftly.\\n\\nYour patience is much appreciated and we will get back to you as quickly as possible.`\n : `Hey @${actor}!\\n\\nWe really appreciate you taking the time to help out with this PR. The collaborators on this project attempt to help as many people as possible, but we are a limited number of volunteers, so it is possible that this will not be addressed as swiftly.\\n\\nYour patience is much appreciated and we will get back to you as quickly as possible.`;\n\n await github.rest.issues.createComment({\n owner,\n repo,\n issue_number: context.issue.number,\n body\n });\n","name: Lint\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n eslint-config:\n description: >\n Filename for the ESLint flat config used by super-linter for\n JavaScript, JSX, TSX, and TypeScript (ES) files. Defaults to\n eslint.config.ts (the org standard). Note: ESLint 9 requires\n --flag unstable_ts_config to load .ts configs; if super-linter\n cannot load it, override with eslint.config.mjs or eslint.config.js.\n type: string\n required: false\n default: eslint.config.ts\n prettier-config:\n description: >\n Filename for the Prettier config. Defaults to prettier.config.ts\n (the org standard). Prettier 3.x loads .ts configs natively.\n type: string\n required: false\n default: prettier.config.ts\n yaml-config:\n description: >\n Filename for the yamllint config. Defaults to yamllint.config.yml.\n type: string\n required: false\n default: yamllint.config.yml\n enable-auto-commit:\n description: >\n Auto-commit super-linter fixes as a verified commit via a GitHub App.\n Requires SUPER_LINTER_APP_ID and SUPER_LINTER_PRIVATE_KEY secrets.\n type: boolean\n required: false\n default: false\n secrets:\n SUPER_LINTER_APP_ID:\n required: false\n SUPER_LINTER_PRIVATE_KEY:\n required: false\n\njobs:\n super-lint:\n name: Lint entire codebase\n permissions:\n contents: write\n issues: write\n statuses: write\n runs-on: ubuntu-latest\n timeout-minutes: 30\n env:\n APP_ID_SET: ${{ secrets.SUPER_LINTER_APP_ID != '' }}\n steps:\n - name: Generate GitHub App token\n id: app-token\n # Runs before checkout so the token is used as the checkout credential,\n # which makes the subsequent push go through the App and produce a\n # Verified commit. Skipped when auto-commit is disabled or secrets unset.\n if: >\n inputs.enable-auto-commit == true &&\n github.event.pull_request != null &&\n github.event.pull_request.head.repo.full_name == github.repository &&\n github.ref_name != github.event.repository.default_branch &&\n env.APP_ID_SET == 'true'\n uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0\n with:\n app-id: ${{ secrets.SUPER_LINTER_APP_ID }}\n private-key: ${{ secrets.SUPER_LINTER_PRIVATE_KEY }}\n\n - name: Resolve App bot identity\n id: app-bot\n # GitHub marks commits as Verified when the author email matches the\n # App bot's noreply address (<numeric-id>+<slug>[bot]@users.noreply.github.com).\n # The numeric ID must be fetched via the API — it differs from the App ID.\n # app-slug is passed via env rather than interpolated into the script to\n # prevent code injection (CWE-78).\n if: steps.app-token.conclusion == 'success'\n run: |\n BOT_SLUG=\"${APP_SLUG}[bot]\"\n BOT_ID=$(gh api \"/users/${BOT_SLUG}\" --jq .id)\n echo \"name=${BOT_SLUG}\" >> \"$GITHUB_OUTPUT\"\n echo \"email=${BOT_ID}+${BOT_SLUG}@users.noreply.github.com\" >> \"$GITHUB_OUTPUT\"\n env:\n GH_TOKEN: ${{ steps.app-token.outputs.token }}\n APP_SLUG: ${{ steps.app-token.outputs.app-slug }}\n\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n # Use the App token when available so the push credential is the App\n # bot — GitHub marks those commits as Verified automatically.\n token: ${{ steps.app-token.outputs.token || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n\n - name: Detect project features\n # Writes VALIDATE_*/FIX_* to GITHUB_ENV only when the feature exists.\n # Also writes step outputs for values referenced in expression context\n # (GITHUB_ENV is not readable via steps.*.outputs — they need GITHUB_OUTPUT).\n # All values written are hardcoded 'true' — no user input in the script.\n # Config file paths (inputs.*) stay in GH Actions expression context in\n # the super-linter env: block below, never shell-evaluated (CWE-78).\n id: detect\n run: |\n has() { find . -not -path '*/node_modules/*' -name \"$1\" -print -quit 2>/dev/null | grep -q .; }\n\n if { has 'eslint.config.ts' || has 'eslint.config.mjs' || has 'eslint.config.js' || has '.eslintrc.json' || has '.eslintrc.yml'; }; then\n {\n echo \"VALIDATE_JAVASCRIPT_ES=true\"\n echo \"VALIDATE_TYPESCRIPT_ES=true\"\n } >> \"$GITHUB_ENV\"\n echo \"eslint=true\" >> \"$GITHUB_OUTPUT\"\n fi\n\n if { has '*.js' || has '*.jsx' || has '*.mjs' || has '*.cjs' || has '*.ts' || has '*.tsx'; }; then\n {\n echo \"VALIDATE_JAVASCRIPT_PRETTIER=true\"\n echo \"VALIDATE_JSX_PRETTIER=true\"\n echo \"VALIDATE_TYPESCRIPT_PRETTIER=true\"\n echo \"VALIDATE_TSX=true\"\n echo \"FIX_JAVASCRIPT_PRETTIER=true\"\n echo \"FIX_JSX_PRETTIER=true\"\n echo \"FIX_TYPESCRIPT_PRETTIER=true\"\n echo \"FIX_TSX=true\"\n } >> \"$GITHUB_ENV\"\n fi\n\n if { has '*.css' || has '*.scss' || has 'stylelint.config.ts' || has 'stylelint.config.mjs' || has 'stylelint.config.js'; }; then\n {\n echo \"VALIDATE_CSS=true\"\n echo \"STYLELINT_CONFIG_FILE=stylelint.config.ts\"\n } >> \"$GITHUB_ENV\"\n fi\n\n if { has '*.graphql' || has '*.gql'; }; then\n {\n echo \"VALIDATE_GRAPHQL_PRETTIER=true\"\n echo \"FIX_GRAPHQL_PRETTIER=true\"\n } >> \"$GITHUB_ENV\"\n fi\n\n if { has '*.html' || has '*.htm'; }; then\n {\n echo \"VALIDATE_HTML_PRETTIER=true\"\n echo \"FIX_HTML_PRETTIER=true\"\n } >> \"$GITHUB_ENV\"\n fi\n\n if { has '.env' || has '.env.example' || has '.env.local'; }; then\n {\n echo \"VALIDATE_ENV=true\"\n echo \"FIX_ENV=true\"\n } >> \"$GITHUB_ENV\"\n fi\n\n if { has 'Dockerfile' || has '*.Dockerfile'; }; then\n echo \"VALIDATE_DOCKERFILE=true\" >> \"$GITHUB_ENV\"\n fi\n\n - uses: super-linter/super-linter/slim@4ce20838b8ab83717e78138c5b3a1407148e0918 # v8.7.0\n name: Run Super Linter\n env:\n GITHUB_TOKEN: ${{ github.token }}\n DEFAULT_BRANCH: ${{ github.event.pull_request.base.ref || github.event.repository.default_branch }}\n ANNOTATE_ONLY: true\n DISABLE_COMMENTS: false\n IGNORE_GITIGNORED_FILES: true\n LINTER_RULES_PATH: /\n EDITORCONFIG_FILE_NAME: \".editorconfig-checker.json\"\n # Config file paths — inputs stay in expression context, never shell-evaluated.\n # When VALIDATE_JAVASCRIPT_ES is not set by detect, ESLint doesn't run so\n # the empty-string fallback (→ eslint.config.mjs in container) is safe.\n JAVASCRIPT_ES_CONFIG_FILE: ${{ steps.detect.outputs.eslint == 'true' && inputs.eslint-config || '' }}\n TYPESCRIPT_ES_CONFIG_FILE: ${{ steps.detect.outputs.eslint == 'true' && inputs.eslint-config || '' }}\n PRETTIER_CONFIG: ${{ inputs.prettier-config }}\n YAML_CONFIG_FILE: ${{ inputs.yaml-config }}\n # Always-on linters\n FIX_MARKDOWN_PRETTIER: true\n VALIDATE_EDITORCONFIG: true\n VALIDATE_GIT_COMMITLINT: true\n VALIDATE_GIT_MERGE_CONFLICT_MARKERS: true\n VALIDATE_GITHUB_ACTIONS: true\n VALIDATE_GITLEAKS: true\n VALIDATE_MARKDOWN_PRETTIER: true\n VALIDATE_YAML: true\n\n - uses: theholocron/.github/.github/actions/auto-commit@main\n name: Commit and push linting fixes\n if: >\n inputs.enable-auto-commit == true &&\n github.event.pull_request != null &&\n github.event.pull_request.head.repo.full_name == github.repository &&\n github.ref_name != github.event.repository.default_branch &&\n env.APP_ID_SET == 'true'\n with:\n token: ${{ steps.app-token.outputs.token }}\n branch: ${{ github.event.pull_request.head.ref || github.head_ref || github.ref }}\n commit-message: \"chore: fix linting issues\\n\\nSigned-off-by: ${{ steps.app-bot.outputs.name }} <${{ steps.app-bot.outputs.email }}>\"\n commit-options: \"--no-verify\"\n commit-user-name: ${{ steps.app-bot.outputs.name }}\n commit-user-email: ${{ steps.app-bot.outputs.email }}\n commit-author: \"${{ steps.app-bot.outputs.name }} <${{ steps.app-bot.outputs.email }}>\"\n","name: Post-release Sync\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n HOLOCRON_SYNC_TOKEN:\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for gh CLI calls. Used when\n HOLOCRON_SYNC_TOKEN is not set.\n required: false\n\njobs:\n broadcast:\n name: Broadcast readme sync\n runs-on: ubuntu-latest\n timeout-minutes: 5\n steps:\n - name: Trigger broadcast readme sync\n run: |\n gh workflow run sync-broadcast.yml \\\n --repo theholocron/.github \\\n --field \"steps=readme\"\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n","name: Release\n\n# Semantic-release with OIDC Trusted Publishing.\n# actions/setup-node writes a default NODE_AUTH_TOKEN=${{ github.token }}\n# which shadows OIDC auth. We explicitly clear it so npm falls through to\n# the Trusted Publisher OIDC exchange.\n# The calling repo must have a .releaserc.json that configures branches,\n# plugins, and any publish options. npm@11+ is installed to support OIDC.\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n run-build:\n description: Run `pnpm build` before releasing\n type: boolean\n required: false\n default: true\n sentry-project:\n description: >\n Sentry project slug for sourcemap upload and release creation after\n publishing. Omit to skip the Sentry release step entirely.\n type: string\n required: false\n default: \"\"\n secrets:\n HOLOCRON_RELEASE_TOKEN:\n description: >\n Fine-grained PAT (Contents + Issues + Pull requests: write) owned by\n an admin. Required when the default branch is protected by a ruleset —\n github.token cannot push through rulesets, but an admin PAT can.\n Takes priority over HOLOCRON_SYNC_TOKEN. Falls back to github.token.\n required: false\n HOLOCRON_SYNC_TOKEN:\n description: >\n Legacy alias for HOLOCRON_RELEASE_TOKEN — kept for backward compatibility.\n Prefer HOLOCRON_RELEASE_TOKEN for new repos.\n required: false\n HOLOCRON_READ_TOKEN:\n description: >\n Fine-grained PAT for read-only GitHub API calls (e.g. resolving git\n committer identity via `gh api user`). Falls back to github.token.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for `gh` CLI calls. Used when\n HOLOCRON_READ_TOKEN is not set.\n required: false\n SENTRY_AUTH_TOKEN:\n description: >\n Sentry auth token for sourcemap upload and release creation.\n Required when sentry-project is set. Use the org-level secret.\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n release:\n name: Semantic release\n permissions:\n contents: write\n id-token: write\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 30\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n # Do not cancel in-progress releases — a partial release is worse than a slow one.\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n persist-credentials: false\n # Use HOLOCRON_RELEASE_TOKEN when available — git push (tags, release commits)\n # uses the checkout credential, not GITHUB_TOKEN env var. The\n # built-in github.token cannot push through branch protection rulesets.\n token: ${{ secrets.HOLOCRON_RELEASE_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Configure git identity\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n git config --global user.name \"$GIT_NAME\"\n git config --global user.email \"$GIT_EMAIL\"\n git config --global format.signoff true\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - name: Upgrade npm for OIDC support\n run: npm install -g npm@11 sigstore\n # sigstore is required by libnpmpublish/provenance.js at module parse\n # time — before any config takes effect. Some npm 11.x builds stopped\n # bundling it; installing it globally into the same prefix ensures it\n # resolves regardless of npm version. (Discovered 2026-07-09.)\n\n - run: pnpm build\n name: Build\n if: ${{ inputs.run-build == true }}\n\n - run: npx semantic-release\n name: Release\n env:\n # Prefer HOLOCRON_RELEASE_TOKEN (fine-grained PAT, Contents+Issues+PRs write,\n # owned by an admin with ruleset bypass) so @semantic-release/git can\n # push the version-bump commit through branch protection. Falls back to\n # HOLOCRON_SYNC_TOKEN (legacy) then github.token for unprotected repos.\n GITHUB_TOKEN: ${{ secrets.HOLOCRON_RELEASE_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || github.token }}\n HUSKY: \"0\"\n NPM_CONFIG_PROVENANCE: true\n\n - name: Get release version\n id: release_version\n if: ${{ inputs.sentry-project != '' }}\n env:\n SENTRY_PROJECT: ${{ inputs.sentry-project }}\n run: |\n TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo \"\")\n if [ -n \"$TAG\" ]; then\n echo \"release=${SENTRY_PROJECT}@${TAG#v}\" >> \"$GITHUB_OUTPUT\"\n fi\n\n - name: Create Sentry release\n if: ${{ inputs.sentry-project != '' && steps.release_version.outputs.release != '' }}\n uses: getsentry/action-release@ff07929a6537bac57790c3451cf4d364aca38528 # v3\n env:\n SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}\n SENTRY_ORG: theholocron\n SENTRY_PROJECT: ${{ inputs.sentry-project }}\n with:\n environment: production\n version: ${{ steps.release_version.outputs.release }}\n sourcemaps: \"**/dist\"\n","name: Review\n\n# ReviewDog is the annotation layer — posts inline PR diff annotations.\n# Runs on pull_request only: inline annotations require PR context,\n# and branch protection ensures all changes go through PRs anyway.\n# super-linter (lint.yml) is the CI gate covering push + PR events.\n# Gitleaks and YAML are intentionally duplicated: super-linter gates\n# merges; ReviewDog surfaces exact line annotations in the PR diff.\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n\njobs:\n reviewdog:\n name: Review PRs\n runs-on: ubuntu-latest\n timeout-minutes: 20\n permissions:\n contents: read\n pull-requests: write\n\n steps:\n - name: Checkout repository\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n\n - name: Setup\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n uses: theholocron/.github/.github/actions/setup@main\n\n - name: Install ReviewDog\n uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1\n with:\n reviewdog_version: latest\n\n # Detect which tools are relevant for this repo, excluding node_modules.\n # hashFiles('**/*') recurses into node_modules/.pnpm and produces false\n # positives for repos that don't own those file types.\n # -print -quit stops find after the first match without a pipe, avoiding\n # the SIGPIPE/pipefail exit-141 that find|head-1 triggers under\n # GitHub Actions' default bash --noprofile --norc -e -o pipefail mode.\n - name: Detect project features\n id: detect\n shell: bash\n run: |\n has() { find . -not -path '*/node_modules/*' -name \"$1\" -print -quit 2>/dev/null | grep -q .; }\n has_ext() { find . -not -path '*/node_modules/*' -name \"$1\" -print -quit 2>/dev/null | grep -q .; }\n { { has 'eslint.config.js' || has 'eslint.config.mjs' || has 'eslint.config.cjs' || \\\n has 'eslint.config.ts' || has '.eslintrc' || has '.eslintrc.js' || \\\n has '.eslintrc.cjs' || has '.eslintrc.json' || has '.eslintrc.yaml' || \\\n has '.eslintrc.yml'; } && grep -qF '\"eslint\":' package.json 2>/dev/null; } && echo \"eslint=true\" >> \"$GITHUB_OUTPUT\" || echo \"eslint=false\" >> \"$GITHUB_OUTPUT\"\n { has 'tsconfig.json' && grep -qF '\"typescript\":' package.json 2>/dev/null; } && echo \"tsconfig=true\" >> \"$GITHUB_OUTPUT\" || echo \"tsconfig=false\" >> \"$GITHUB_OUTPUT\"\n has_ext '*.sh' && echo \"shell=true\" >> \"$GITHUB_OUTPUT\" || echo \"shell=false\" >> \"$GITHUB_OUTPUT\"\n has 'Dockerfile' || has_ext '*.Dockerfile' || has 'Containerfile' && \\\n echo \"docker=true\" >> \"$GITHUB_OUTPUT\" || echo \"docker=false\" >> \"$GITHUB_OUTPUT\"\n has_ext '.env*' && echo \"dotenv=true\" >> \"$GITHUB_OUTPUT\" || echo \"dotenv=false\" >> \"$GITHUB_OUTPUT\"\n has_ext '*.md' && echo \"markdown=true\" >> \"$GITHUB_OUTPUT\" || echo \"markdown=false\" >> \"$GITHUB_OUTPUT\"\n\n #\n # Always applicable\n #\n\n - name: Gitleaks (secrets)\n uses: reviewdog/action-gitleaks@2b7b5685e3e3eecddab5d30cfa04f18123031421 # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / gitleaks\"\n fail_level: error\n gitleaks_flags: --log-opts=${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}\n\n - name: YamlLint\n if: ${{ hashFiles('yamllint.config.yml') != '' }}\n uses: reviewdog/action-yamllint@b5f7217d8c815ae374d1d55840d5e569d82f01f0 # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / yamllint\"\n fail_level: error\n yamllint_flags: -c ${{ github.workspace }}/yamllint.config.yml ${{ github.workspace }}\n\n - name: ActionLint (GitHub Actions)\n if: ${{ hashFiles('.github/workflows/*.yml', '.github/workflows/*.yaml') != '' }}\n uses: reviewdog/action-actionlint@6fb7acc99f4a1008869fa8a0f09cfca740837d9d # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / actionlint\"\n fail_level: error\n\n #\n # TypeScript / JavaScript\n #\n\n - name: ESLint\n if: steps.detect.outputs.eslint == 'true'\n uses: reviewdog/action-eslint@556a3fdaf8b4201d4d74d406013386aa4f7dab96 # v1.34.0\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / eslint\"\n fail_level: error\n eslint_flags: .\n\n - name: TypeScript\n if: steps.detect.outputs.tsconfig == 'true'\n uses: EPMatt/reviewdog-action-tsc@63d923a3c5b4497671940b8874f58a404e2351b5 # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / tsc\"\n fail_level: error\n\n #\n # Shell\n #\n\n - name: ShellCheck\n if: steps.detect.outputs.shell == 'true'\n uses: reviewdog/action-shellcheck@4c07458293ac342d477251099501a718ae5ef86e # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / shellcheck\"\n fail_level: none\n\n #\n # Docker\n #\n\n - name: Hadolint\n if: steps.detect.outputs.docker == 'true'\n uses: reviewdog/action-hadolint@1b2cfa6ba72072ad35158d7ff3aa49bbdc03506d # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / hadolint\"\n fail_level: none\n\n #\n # Environment files\n #\n\n - name: dotenv-linter\n if: steps.detect.outputs.dotenv == 'true'\n uses: dotenv-linter/action-dotenv-linter@afde61cfda2ecffe7bea35837b6f20b956c88689 # v3.0.0\n with:\n reporter: github-code-suggestions\n\n #\n # Documentation\n #\n\n - name: Alex (inclusive language)\n if: steps.detect.outputs.markdown == 'true'\n uses: reviewdog/action-alex@347481655add010a2ae302df34b57c9bcfa0d6e4 # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / alex\"\n","name: Stale\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n days-before-stale:\n description: Days of inactivity before an issue is marked stale\n type: number\n required: false\n default: 30\n days-before-close:\n description: Days of inactivity after stale label before closing\n type: number\n required: false\n default: 5\n\njobs:\n stale:\n name: Mark stale issues and pull requests\n permissions:\n contents: write\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10.4.0\n name: Run Stale\n with:\n close-issue-message: >\n This issue was closed because it has been stalled for\n ${{ inputs.days-before-close }} days with no activity.\n days-before-close: ${{ inputs.days-before-close }}\n days-before-stale: ${{ inputs.days-before-stale }}\n exempt-all-pr-milestones: true\n stale-issue-label: wontfix\n stale-issue-message: >\n This issue is stale because it has been open ${{ inputs.days-before-stale }}\n days with no activity. Remove the stale label or comment, or this will be\n closed in ${{ inputs.days-before-close }} days.\n stale-pr-label: wontfix\n stale-pr-message: >\n This PR is stale because it has been open ${{ inputs.days-before-stale }}\n days with no activity. Remove the stale label or comment, or this will be\n closed in ${{ inputs.days-before-close }} days.\n","name: Sync\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n steps:\n description: >\n Sync steps to run (default: all). Valid values:\n labels, properties, teams, topics, keywords, description, homepage, readme.\n Pass a space-separated list to run a subset, e.g. \"readme\" or \"readme description\".\n type: string\n required: false\n secrets:\n HOLOCRON_ADMIN_TOKEN:\n description: Fine-grained PAT with admin scopes (labels, properties, teams).\n required: false\n HOLOCRON_DEPLOY_TOKEN:\n description: Fine-grained PAT for GitHub Pages configuration.\n required: false\n HOLOCRON_ISSUES_TOKEN:\n description: Fine-grained PAT for issue management.\n required: false\n HOLOCRON_ORG_TOKEN:\n description: Org-scoped fine-grained PAT for team sync and org properties.\n required: false\n HOLOCRON_READ_TOKEN:\n description: Fine-grained PAT for read-only GitHub API calls.\n required: false\n HOLOCRON_SYNC_TOKEN:\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for gh CLI calls. Used when\n HOLOCRON_SYNC_TOKEN is not set.\n required: false\n\njobs:\n sync:\n name: Sync repo from config\n runs-on: ubuntu-latest\n timeout-minutes: 10\n permissions:\n contents: write\n pull-requests: write\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Run holocron sync\n run: |\n if [ -n \"$STEPS\" ]; then\n # shellcheck disable=SC2086\n pnpm exec holocron sync --steps $STEPS\n else\n pnpm exec holocron sync\n fi\n env:\n HOLOCRON_ADMIN_TOKEN: ${{ secrets.HOLOCRON_ADMIN_TOKEN }}\n HOLOCRON_DEPLOY_TOKEN: ${{ secrets.HOLOCRON_DEPLOY_TOKEN }}\n HOLOCRON_ISSUES_TOKEN: ${{ secrets.HOLOCRON_ISSUES_TOKEN }}\n HOLOCRON_ORG_TOKEN: ${{ secrets.HOLOCRON_ORG_TOKEN }}\n HOLOCRON_READ_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n STEPS: ${{ inputs.steps }}\n\n - name: Format generated files\n run: pnpm exec prettier --write README.md docs/src/content/docs/index.mdx 2>/dev/null || true\n\n - uses: theholocron/.github/.github/actions/auto-commit@main\n id: auto-commit\n name: Commit sync changes\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n branch: chore/auto-sync\n commit-message: \"chore: sync from holocron.config\"\n commit-options: \"--no-verify\"\n\n - name: Open PR if changes were committed\n if: steps.auto-commit.outputs.changes-detected == 'true'\n run: |\n gh pr create \\\n --title \"chore: sync README and repo metadata\" \\\n --body \"Automated sync triggered by changes to config or package files. Merge to apply.\" \\\n --base main \\\n --head chore/auto-sync \\\n || echo \"PR already open — branch updated.\"\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n","name: Sync Broadcast\n\non: # yamllint disable-line rule:truthy\n workflow_dispatch:\n inputs:\n steps:\n description: >\n Sync steps to pass to each repo's sync.yml. Default is \"readme\"\n (only README marker blocks are updated).\n type: string\n required: false\n default: readme\n\npermissions:\n contents: read\n\njobs:\n broadcast:\n name: Broadcast sync to all repos\n runs-on: ubuntu-latest\n timeout-minutes: 15\n steps:\n - name: Dispatch sync to all repos with sync.yml\n run: |\n gh api /orgs/theholocron/repos --paginate --jq '.[].name' \\\n | while IFS= read -r repo; do\n gh api \"/repos/theholocron/$repo/contents/.github/workflows/sync.yml\" --silent 2>/dev/null || continue\n echo \"Dispatching sync to theholocron/$repo\"\n gh workflow run sync.yml \\\n --repo \"theholocron/$repo\" \\\n --field \"steps=$STEPS\"\n done\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n STEPS: ${{ inputs.steps }}\n","name: Sync GitHub Templates\n\n# Builds the holocron CLI from source and pushes updated workflow templates\n# and composite actions to downstream .github repos. Runs whenever the\n# template source files change on main or alpha.\n#\n# Secrets required:\n# HOLOCRON_SYNC_TOKEN — fine-grained PAT (resource owner: org) with:\n# Actions: Read and write (dispatch workflow runs via gh workflow run)\n# Contents: Read and write (git trees, blobs, refs)\n# Pull requests: Read and write (open sync PR)\n# Workflows: Read and write (write .github/workflows/*.yml)\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n primary-repo:\n description: >\n Primary .github repo — receives composite actions, reusable workflows,\n and thin-caller templates. Requires a PR (branch protection assumed).\n type: string\n required: false\n default: theholocron/.github\n secondary-repos:\n description: >\n Space-separated list of secondary repos (reusable workflows + thin\n callers only, no composite actions). Changes are delivered via pull\n request, same as the primary repo.\n type: string\n required: false\n default: \"\"\n sync-branch:\n description: Branch name used for the primary and secondary repo PRs\n type: string\n required: false\n default: chore/sync-templates\n secrets:\n HOLOCRON_SYNC_TOKEN:\n required: true\n HOLOCRON_READ_TOKEN:\n description: >\n Fine-grained PAT for read-only GitHub API calls (e.g. resolving git\n committer identity via `gh api user`). Falls back to HOLOCRON_SYNC_TOKEN.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for `gh` CLI calls. Used when neither\n HOLOCRON_READ_TOKEN nor HOLOCRON_SYNC_TOKEN is set.\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n sync:\n name: Sync templates\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm build\n name: Build CLI\n\n - name: Cache actionlint\n id: cache-actionlint\n uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0\n with:\n path: /tmp/actionlint\n key: actionlint-v1.7.7-linux-amd64\n\n - name: Download actionlint\n if: steps.cache-actionlint.outputs.cache-hit != 'true'\n run: |\n curl -fsSL https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_amd64.tar.gz \\\n | tar -xz -C /tmp actionlint\n\n - name: Validate generated workflows\n run: |\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --output-dir /tmp/sync-validate\n /tmp/actionlint /tmp/sync-validate/.github/workflows/*.yml\n env:\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n\n - name: Sync primary repo (PR)\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$PRIMARY_REPO\" \"$SYNC_BRANCH\" 2>/dev/null || true\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n\n - name: Sync secondary repos (PR)\n if: ${{ inputs.secondary-repos != '' }}\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n for repo in $SECONDARY_REPOS; do\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$repo\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$repo\" \"$SYNC_BRANCH\" 2>/dev/null || true\n done\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n SECONDARY_REPOS: ${{ inputs.secondary-repos }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n","name: Tag\n\n# Release Please — fully automated tag and GitHub Release from Conventional Commits.\n# No package.json or npm publishing required. Operates in \"simple\" mode by default:\n# analyzes commits since the last tag, maintains a rolling Release PR, and creates\n# a tag + GitHub Release when that PR is merged.\n#\n# The calling repo must have two files at the root:\n# release-please-config.json — declares packages and release-type\n# .release-please-manifest.json — tracks the current version\n\non: # yamllint disable-line rule:truthy\n # Self-trigger: when this workflow lives in theholocron/.github itself,\n # push to main runs Release Please for that repo's own releases.\n push:\n branches:\n - main\n workflow_call:\n inputs:\n release-type:\n description: Release Please release type (simple, node, python, etc.)\n type: string\n required: false\n default: simple\n config-file:\n description: Path to release-please-config.json\n type: string\n required: false\n default: release-please-config.json\n manifest-file:\n description: Path to .release-please-manifest.json\n type: string\n required: false\n default: .release-please-manifest.json\n\njobs:\n tag:\n name: Tag release\n permissions:\n contents: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: google-github-actions/release-please-action@e4dc86ba9405554aeba3c6bb2d169500e7d3b4ee # v4.1.1\n name: Run Release Please\n with:\n release-type: ${{ inputs.release-type }}\n config-file: ${{ inputs.config-file }}\n manifest-file: ${{ inputs.manifest-file }}\n","name: Test\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n run-unit:\n description: Run unit tests with coverage (disable for UI-only repos that use Storybook testing exclusively)\n type: boolean\n required: false\n default: true\n run-storybook:\n description: Run Storybook vitest interaction tests (requires .storybook/ setup)\n type: boolean\n required: false\n default: false\n run-interaction:\n description: Run Storybook interaction and accessibility tests with Playwright\n type: boolean\n required: false\n default: false\n run-chromatic:\n description: Publish Storybook to Chromatic for visual regression testing\n type: boolean\n required: false\n default: false\n chromatic-projects:\n description: >\n JSON array of Chromatic projects to build, one matrix job per entry.\n Each entry: { \"tokenName\": \"WEB\", \"workingDir\": \"apps/web\", \"buildScript\": \"build:storybook\" }.\n tokenName maps to secret CHROMATIC_PROJECT_TOKEN_<TOKENNAME>; use \"default\"\n (or omit for the legacy empty-string form) to use the bare CHROMATIC_PROJECT_TOKEN\n secret for single-project repos.\n buildScript defaults to \"build:storybook\" when omitted.\n Default runs a single job from the repo root using CHROMATIC_PROJECT_TOKEN.\n type: string\n required: false\n default: '[{\"tokenName\":\"default\",\"workingDir\":\".\",\"buildScript\":\"build:storybook\"}]'\n run-user-flow:\n description: Run Cypress E2E user-flow tests (requires cypress.config.*)\n type: boolean\n required: false\n default: false\n wait-on-url:\n description: URL to wait for before running Cypress tests (default is Vite dev server; override for non-Vite stacks e.g. http://localhost:3000 for Next.js)\n type: string\n required: false\n default: \"http://localhost:5173\"\n secrets:\n CHROMATIC_PROJECT_TOKEN:\n required: false\n CYPRESS_RECORD_KEY:\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n unit:\n name: Run tests and collect coverage\n if: ${{ inputs.run-unit }}\n permissions:\n contents: read\n id-token: write\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm test:coverage\n name: Run tests with coverage\n\n - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0\n name: Upload coverage to Codecov\n with:\n use_oidc: true\n\n - uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1\n name: Upload test results to Codecov\n if: ${{ !cancelled() }}\n with:\n use_oidc: true\n files: '**/test-report.junit.xml'\n\n storybook:\n name: Run Storybook interaction tests\n if: ${{ inputs.run-storybook }}\n permissions:\n contents: read\n id-token: write\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm exec playwright install chromium --with-deps\n name: Install Playwright\n\n - run: pnpm test:storybook\n name: Run Storybook tests\n\n - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0\n name: Upload coverage to Codecov\n with:\n use_oidc: true\n\n - uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1\n name: Upload test results to Codecov\n if: ${{ !cancelled() }}\n with:\n use_oidc: true\n files: '**/test-report.junit.xml'\n\n visual-and-composition:\n name: Test Visual and Composition (${{ matrix.project.tokenName }})\n if: ${{ inputs.run-chromatic }}\n strategy:\n fail-fast: false\n matrix:\n project: ${{ fromJSON(inputs.chromatic-projects) }}\n permissions:\n contents: read\n statuses: write\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - uses: chromaui/action@14cfaef73576e69f95f47f60058063f46ca38719 # v18\n name: Publish to Chromatic\n with:\n projectToken: ${{ (matrix.project.tokenName == 'default' || matrix.project.tokenName == '') && secrets.CHROMATIC_PROJECT_TOKEN || secrets[format('CHROMATIC_PROJECT_TOKEN_{0}', matrix.project.tokenName)] }}\n token: ${{ github.token }}\n buildScriptName: ${{ matrix.project.buildScript || 'build:storybook' }}\n workingDir: ${{ matrix.project.workingDir || '.' }}\n storybookBaseDir: ${{ matrix.project.storybookBaseDir || '' }}\n untraced: ${{ matrix.project.untraced || '' }}\n onlyStoryFiles: ${{ matrix.project.onlyStoryFiles || '' }}\n exitZeroOnChanges: ${{ matrix.project.exitZeroOnChanges || false }}\n\n interaction-and-accessibility:\n name: Test Interactions and Accessibility\n if: ${{ inputs.run-interaction }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm exec playwright install --with-deps\n name: Install Playwright\n\n - run: pnpm test:storybook\n name: Run interaction and accessibility tests\n\n user-flow:\n name: Test User Flow\n if: ${{ inputs.run-user-flow }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n strategy:\n fail-fast: false\n matrix:\n containers: [1, 2]\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm exec cypress install\n name: Install Cypress binary\n\n - uses: cypress-io/github-action@1052aa98bbbe4f55210f844878213c07d9c8c399 # v6.7.13\n name: Cypress run\n with:\n start: pnpm dev\n wait-on: ${{ inputs.wait-on-url }}\n record: true\n parallel: true\n env:\n CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}\n GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n","name: Typecheck\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n TURBO_TOKEN:\n required: false\n\njobs:\n typecheck:\n name: tsc --noEmit\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm typecheck\n name: Type check\n","/**\n * All reusable workflow and composite action content bundled as string\n * constants so the CLI can push them to theholocron/.github without\n * needing filesystem access at runtime.\n *\n * Content lives in standalone .yml files; the rawYml rollup plugin\n * inlines them as string exports at build time.\n */\n\nimport autoCommitAction from \"./actions/auto-commit.yml\";\nimport installAction from \"./actions/install.yml\";\nimport setupAction from \"./actions/setup.yml\";\nimport setupNodeAction from \"./actions/setup-node.yml\";\nimport auditWorkflow from \"./workflows/audit.yml\";\nimport bookkeepingWorkflow from \"./workflows/bookkeeping.yml\";\nimport cleanupPreviewWorkflow from \"./workflows/cleanup-preview.yml\";\nimport codeqlWorkflow from \"./workflows/codeql.yml\";\nimport dependenciesWorkflow from \"./workflows/dependencies.yml\";\nimport deployWorkflow from \"./workflows/deploy.yml\";\nimport deployPreviewWorkflow from \"./workflows/deploy-preview.yml\";\nimport greetingsWorkflow from \"./workflows/greetings.yml\";\nimport lintWorkflow from \"./workflows/lint.yml\";\nimport postReleaseWorkflow from \"./workflows/post-release.yml\";\nimport releaseWorkflow from \"./workflows/release.yml\";\nimport reviewWorkflow from \"./workflows/review.yml\";\nimport staleWorkflow from \"./workflows/stale.yml\";\nimport syncWorkflow from \"./workflows/sync.yml\";\nimport syncBroadcastWorkflow from \"./workflows/sync-broadcast.yml\";\nimport syncGithubWorkflow from \"./workflows/sync-github.yml\";\nimport tagWorkflow from \"./workflows/tag.yml\";\nimport testWorkflow from \"./workflows/test.yml\";\nimport typecheckWorkflow from \"./workflows/typecheck.yml\";\n\nexport const ACTIONS: Record<string, string> = {\n\t\"auto-commit/action\": autoCommitAction,\n\t\"install/action\": installAction,\n\t\"setup/action\": setupAction,\n\t\"setup-node/action\": setupNodeAction,\n};\n\nexport const REUSABLE_WORKFLOWS: Record<string, string> = {\n\taudit: auditWorkflow,\n\tbookkeeping: bookkeepingWorkflow,\n\tcodeql: codeqlWorkflow,\n\tdependencies: dependenciesWorkflow,\n\tdeploy: deployWorkflow,\n\t\"cleanup-preview\": cleanupPreviewWorkflow,\n\t\"deploy-preview\": deployPreviewWorkflow,\n\tgreetings: greetingsWorkflow,\n\tlint: lintWorkflow,\n\t\"post-release\": postReleaseWorkflow,\n\trelease: releaseWorkflow,\n\treview: reviewWorkflow,\n\tstale: staleWorkflow,\n\t\"sync-broadcast\": syncBroadcastWorkflow,\n\ttag: tagWorkflow,\n\t\"sync-github\": syncGithubWorkflow,\n\tsync: syncWorkflow,\n\ttest: testWorkflow,\n\ttypecheck: typecheckWorkflow,\n};\n\nexport const WORKFLOW_TEMPLATE_PROPERTIES: Record<string, string> = {\n\tbookkeeping: JSON.stringify(\n\t\t{\n\t\t\tname: \"Bookkeeping\",\n\t\t\tdescription: \"Label and track issues and pull requests.\",\n\t\t\ticonName: \"octicon tag\",\n\t\t},\n\t\tnull,\n\t\t2\n\t),\n};\n","import { createHash } from \"node:crypto\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nimport { createGitHubClient } from \"@theholocron/github-client\";\nimport { ProviderApiError } from \"@theholocron/http-client\";\n\nimport { ACTIONS, REUSABLE_WORKFLOWS, WORKFLOW_TEMPLATE_PROPERTIES } from \"../templates/index.js\";\nimport {\n\tderiveDeployPaths,\n\textractPreviewConfig,\n\tgenerateCombinedDeployContent,\n\tgenerateThinCallerContent,\n\tKNOWN_WORKFLOWS,\n\tnormalizeWorkflowWith,\n\ttype OrgContext,\n\tWORKFLOW_TEMPLATES,\n\tworkflowHeader,\n} from \"./setup-workflows.js\";\n\nconst DEFAULT_REPO = \"theholocron/.github\";\n\nexport type SyncGithubStatus = \"ok\" | \"fail\" | \"dry-run\";\n\nexport interface RunSyncGithubInput {\n\t/** GitHub personal access token with repo write access. */\n\ttoken: string;\n\t/** Target org/repo. Defaults to \"theholocron/.github\". */\n\trepo?: string;\n\t/**\n\t * Push files to this branch instead of the default branch.\n\t * If the branch doesn't exist it is created from the default branch HEAD.\n\t * Combine with `createPr: true` to open a PR after the push.\n\t */\n\tbranch?: string;\n\t/** After pushing to `branch`, open a PR to the default branch. No-op if `branch` is unset. */\n\tcreatePr?: boolean;\n\t/** Commit message for the sync commit. */\n\tmessage?: string;\n\tdryRun?: boolean;\n\t/**\n\t * Write generated files to this local directory instead of pushing to the GitHub API.\n\t * Useful for local validation (e.g. actionlint) before a real sync run.\n\t * When set, no API calls are made and token is not required.\n\t */\n\toutputDir?: string;\n\tprint?: (line: string) => void;\n\t/** Injectable for testing. */\n\tfetch?: typeof globalThis.fetch;\n}\n\nexport interface SyncGithubReport {\n\tstatus: SyncGithubStatus;\n\tcreated: number;\n\tupdated: number;\n\tunchanged: number;\n\t/** URL of the opened PR, when createPr is true and changes were made. */\n\tprUrl?: string;\n\tmessage?: string;\n}\n\ntype FileBatch = Array<{ path: string; content: string }>;\ntype WorkflowEntry = { name: string; with?: Record<string, unknown> };\n\n/**\n * Extracts the `workflows` array from a `holocron.config.ts` source string.\n * Handles both plain string entries and `{ name, with }` object entries.\n * Falls back to an empty array if the array cannot be found or parsed.\n */\nexport function parseWorkflowsFromTs(source: string): WorkflowEntry[] {\n\tconst keyMatch = source.match(/\\bworkflows\\s*:\\s*\\[/);\n\tif (!keyMatch) return [];\n\n\t// Walk forward to find the matching ]\n\tconst start = keyMatch.index! + keyMatch[0].length;\n\tlet depth = 1;\n\tlet i = start;\n\twhile (i < source.length && depth > 0) {\n\t\tif (source[i] === \"[\") depth++;\n\t\telse if (source[i] === \"]\") depth--;\n\t\ti++;\n\t}\n\tconst body = source.slice(start, i - 1);\n\n\t// Detect spread operators like ...workflows (from node() / react() presets).\n\t// When present, all known workflows are included as defaults so the sync\n\t// doesn't silently skip workflows that come from the preset.\n\tconst hasPresetSpread = /\\.\\.\\.[a-zA-Z_$][a-zA-Z0-9_$]*/.test(body);\n\n\tconst explicit: Array<{ pos: number; entry: WorkflowEntry }> = [];\n\tconst objSpans: Array<[number, number]> = [];\n\n\t// Pass 1: extract top-level { ... } objects using bracket counting so that\n\t// nested braces inside with: values (e.g. storybook: [{ name: \"app\" }])\n\t// are handled correctly. The previous regex approach stopped at the first }\n\t// inside a nested object, causing JSON.parse to fail and with: to be silently\n\t// dropped from the generated thin caller.\n\tlet j = 0;\n\twhile (j < body.length) {\n\t\tif (body[j] !== \"{\") {\n\t\t\tj++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst objStart = j;\n\t\tlet objDepth = 1;\n\t\tj++;\n\t\twhile (j < body.length && objDepth > 0) {\n\t\t\tif (body[j] === \"{\") objDepth++;\n\t\t\telse if (body[j] === \"}\") objDepth--;\n\t\t\tj++;\n\t\t}\n\t\tconst objContent = body.slice(objStart, j);\n\t\tobjSpans.push([objStart, j]);\n\n\t\tconst nameMatch = objContent.match(/\\bname\\s*:\\s*\"([^\"]+)\"/);\n\t\tif (!nameMatch) continue;\n\t\tconst name = nameMatch[1];\n\n\t\tlet withObj: Record<string, unknown> | undefined;\n\t\tconst withKeyMatch = objContent.match(/\\bwith\\s*:\\s*\\{/);\n\t\tif (withKeyMatch) {\n\t\t\tconst withOpen = withKeyMatch.index! + withKeyMatch[0].length - 1;\n\t\t\tlet withDepth = 1;\n\t\t\tlet k = withOpen + 1;\n\t\t\twhile (k < objContent.length && withDepth > 0) {\n\t\t\t\tif (objContent[k] === \"{\") withDepth++;\n\t\t\t\telse if (objContent[k] === \"}\") withDepth--;\n\t\t\t\tk++;\n\t\t\t}\n\t\t\tconst withStr = objContent.slice(withOpen, k);\n\t\t\ttry {\n\t\t\t\t// TS object literals differ from JSON in two ways:\n\t\t\t\t// 1. Unquoted keys: { docs: true } → { \"docs\": true }\n\t\t\t\t// 2. Trailing commas: { a: 1, } → { a: 1 }\n\t\t\t\t// Normalise both before parsing so nested objects like\n\t\t\t\t// run-chromatic: { projects: [...], } are handled correctly.\n\t\t\t\tconst jsonSafe = withStr\n\t\t\t\t\t.replace(/([{,]\\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*:/g, '$1\"$2\":')\n\t\t\t\t\t.replace(/,(\\s*[}\\]])/g, \"$1\");\n\t\t\t\twithObj = JSON.parse(jsonSafe) as Record<string, unknown>;\n\t\t\t} catch {\n\t\t\t\t/* ignore malformed with: value */\n\t\t\t}\n\t\t}\n\n\t\texplicit.push({ pos: objStart, entry: { name, ...(withObj && { with: withObj }) } });\n\t}\n\n\t// Pass 2: simple string entries — \"workflowname\" — skip chars inside object spans\n\tconst strRe = /\"([^\"]+)\"/g;\n\tlet m: RegExpExecArray | null;\n\twhile ((m = strRe.exec(body)) !== null) {\n\t\tif (!objSpans.some(([s, e]) => m!.index >= s && m!.index < e)) {\n\t\t\texplicit.push({ pos: m.index, entry: { name: m[1] } });\n\t\t}\n\t}\n\n\texplicit.sort((a, b) => a.pos - b.pos);\n\tconst explicitEntries = explicit.map(({ entry }) => entry);\n\n\tif (!hasPresetSpread) return explicitEntries;\n\n\t// Spread detected: seed with all known workflows, then let explicit entries\n\t// override (e.g. to carry their with: overrides).\n\tconst merged = new Map<string, WorkflowEntry>([...KNOWN_WORKFLOWS].map((name) => [name, { name }]));\n\tfor (const entry of explicitEntries) {\n\t\tmerged.set(entry.name, entry);\n\t}\n\treturn [...merged.values()];\n}\n\n/**\n * Extract org name and docs domain from a `holocron.config.ts` source string.\n * Used to resolve `preview: true` to `{ project: \"<org>-preview\", domain: \"preview.<docsDomain>\" }`.\n */\nexport function parseOrgContextFromTs(source: string): OrgContext {\n\tconst orgMatch = source.match(/\\borg\\s*:\\s*[\"']([^\"']+)[\"']/);\n\t// Match top-level `domain: \"...\"` — the org canonical domain from which preview\n\t// subdomains are derived (e.g. \"theholocron.dev\" → preview.theholocron.dev).\n\tconst domainMatch = source.match(/\\bdomain\\s*:\\s*[\"']([^\"']+)[\"']/);\n\t// Match `name: \"...\"` only before `workflows:` so workflow-entry names are excluded.\n\tconst beforeWorkflows = source.split(/\\bworkflows\\s*:/)[0]!;\n\tconst nameMatch = beforeWorkflows.match(/\\bname\\s*:\\s*[\"']([^\"']+)[\"']/);\n\treturn {\n\t\torg: orgMatch?.[1],\n\t\tdomain: domainMatch?.[1],\n\t\trepoName: nameMatch?.[1],\n\t};\n}\n\nfunction reusableHeader(source: string): string {\n\treturn [\n\t\t`# AUTO-GENERATED — do not edit in theholocron/.github directly.`,\n\t\t`# Source: theholocron/holocron · ${source}`,\n\t\t`# Synced: ${new Date().toISOString()}`,\n\t\t`# Tool: holocron sync-github`,\n\t\t`# Changes: edit source in theholocron/holocron and push to alpha or main.`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\nfunction buildBatch(\n\trepo: string,\n\tallowedWorkflows?: Set<string>,\n\twithOverrides?: Map<string, Record<string, unknown>>,\n\torgContext?: OrgContext\n): FileBatch {\n\tconst files: FileBatch = [];\n\tconst isPrimaryGithubRepo = repo === DEFAULT_REPO;\n\n\tif (isPrimaryGithubRepo) {\n\t\tfor (const [name, content] of Object.entries(ACTIONS)) {\n\t\t\tfiles.push({\n\t\t\t\tpath: `.github/actions/${name}.yml`,\n\t\t\t\tcontent: reusableHeader(`packages/cli/src/templates/index.ts`) + content,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (isPrimaryGithubRepo) {\n\t\tfor (const [name, content] of Object.entries(REUSABLE_WORKFLOWS)) {\n\t\t\tfiles.push({\n\t\t\t\tpath: `.github/workflows/${name}.yml`,\n\t\t\t\tcontent: reusableHeader(`packages/cli/src/templates/index.ts`) + content,\n\t\t\t});\n\t\t}\n\n\t\tfor (const [name, content] of Object.entries(WORKFLOW_TEMPLATES)) {\n\t\t\tfiles.push({\n\t\t\t\tpath: `workflow-templates/${name}.yml`,\n\t\t\t\tcontent: workflowHeader(undefined, true) + content,\n\t\t\t});\n\t\t\tconst props = WORKFLOW_TEMPLATE_PROPERTIES[name];\n\t\t\tif (props) {\n\t\t\t\tfiles.push({\n\t\t\t\t\tpath: `workflow-templates/${name}.properties.json`,\n\t\t\t\t\tcontent: props,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor (const name of Object.keys(REUSABLE_WORKFLOWS)) {\n\t\t\t// deploy-preview is a reusable that lives in .github, not a user-configurable\n\t\t\t// thin caller — skip it in the secondary-repo loop.\n\t\t\tif (name === \"deploy-preview\") continue;\n\t\t\tif (allowedWorkflows && !allowedWorkflows.has(name)) continue;\n\t\t\tconst rawWith = withOverrides?.get(name);\n\t\t\tconst normalizedWith = rawWith ? normalizeWorkflowWith(rawWith, orgContext?.repoName) : undefined;\n\t\t\tconst additionalPaths = name === \"deploy\" && rawWith ? deriveDeployPaths(rawWith) : undefined;\n\n\t\t\t// deploy + preview: → combined thin caller; preview: true derives\n\t\t\t// project + domain from the repo's org/docs config.\n\t\t\tif (name === \"deploy\" && rawWith) {\n\t\t\t\tconst previewCfg = extractPreviewConfig(rawWith, orgContext);\n\t\t\t\tif (previewCfg) {\n\t\t\t\t\tfiles.push({\n\t\t\t\t\t\tpath: `.github/workflows/deploy.yml`,\n\t\t\t\t\t\tcontent:\n\t\t\t\t\t\t\tworkflowHeader() +\n\t\t\t\t\t\t\tgenerateCombinedDeployContent(normalizedWith!, additionalPaths!, previewCfg),\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst content = generateThinCallerContent(name, normalizedWith, additionalPaths);\n\t\t\tif (!content) continue;\n\t\t\tfiles.push({\n\t\t\t\tpath: `.github/workflows/${name}.yml`,\n\t\t\t\tcontent: workflowHeader() + content,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn files;\n}\n\n/** Git blob SHA: sha1(\"blob {len}\\0{content}\") — used to detect unchanged files. */\nexport function gitBlobSha(content: string): string {\n\tconst buf = Buffer.from(content, \"utf8\");\n\treturn createHash(\"sha1\").update(`blob ${buf.length}\\0`).update(buf).digest(\"hex\");\n}\n\nexport async function runSyncGithub(input: RunSyncGithubInput): Promise<SyncGithubReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst repo = input.repo ?? DEFAULT_REPO;\n\tconst { token, dryRun = false, branch, createPr = false } = input;\n\tconst message = input.message ?? `chore: sync from theholocron/holocron`;\n\n\tconst client = createGitHubClient({ token, fetch: input.fetch });\n\n\tprint(`holocron sync-github${dryRun ? \" (dry-run)\" : \"\"}`);\n\tprint(` repo: ${repo}`);\n\tif (branch) print(` branch: ${branch}`);\n\tprint(\"\");\n\n\t// ── output-dir: write all files to disk without any API calls ───────────\n\tif (input.outputDir) {\n\t\tconst batch = buildBatch(repo);\n\t\tfor (const file of batch) {\n\t\t\tconst dest = join(input.outputDir, file.path);\n\t\t\tmkdirSync(dirname(dest), { recursive: true });\n\t\t\twriteFileSync(dest, file.content, \"utf8\");\n\t\t}\n\t\tprint(` ${batch.length} files written to ${input.outputDir}`);\n\t\treturn { status: \"ok\", created: batch.length, updated: 0, unchanged: 0 };\n\t}\n\n\t// ── 1. Resolve target branch ─────────────────────────────────────────────\n\tlet targetBranch = branch;\n\tlet defaultBranch: string | undefined;\n\tif (!targetBranch || createPr) {\n\t\ttry {\n\t\t\tconst repoData = await client.repos.getRepo(repo);\n\t\t\tdefaultBranch = repoData.default_branch;\n\t\t\tif (!targetBranch) targetBranch = defaultBranch;\n\t\t} catch {\n\t\t\tconst msg = \"failed to fetch repo metadata\";\n\t\t\tprint(` ✗ ${msg}`);\n\t\t\treturn { status: \"fail\", created: 0, updated: 0, unchanged: 0, message: msg };\n\t\t}\n\t}\n\n\t// ── 2. Get HEAD commit → base tree ───────────────────────────────────────\n\tconst baseBranch = createPr && defaultBranch ? defaultBranch : targetBranch!;\n\tlet headSha: string;\n\tlet baseTreeSha: string;\n\tlet existingBlobs: Map<string, string>;\n\ttry {\n\t\tconst ref = await client.git.getRef(repo, baseBranch);\n\t\theadSha = ref.object.sha;\n\t\tconst commit = await client.git.getCommit(repo, headSha);\n\t\tbaseTreeSha = commit.tree.sha;\n\t\tconst treeData = await client.git.getTree(repo, baseTreeSha, true);\n\t\texistingBlobs = new Map(treeData.tree.filter((i) => i.type === \"blob\").map((i) => [i.path, i.sha]));\n\t} catch (err) {\n\t\tconst msg = err instanceof Error ? err.message : `Branch ${baseBranch} not found`;\n\t\tprint(` ✗ ${msg}`);\n\t\treturn { status: \"fail\", created: 0, updated: 0, unchanged: 0, message: msg };\n\t}\n\n\t// ── 3. Fetch workflow allowlist + per-workflow overrides from target repo ─\n\tlet allowedWorkflows: Set<string> | undefined;\n\tlet withOverrides: Map<string, Record<string, unknown>> | undefined;\n\tlet orgContext: OrgContext | undefined;\n\tif (repo !== DEFAULT_REPO) {\n\t\ttry {\n\t\t\tlet entries: WorkflowEntry[] = [];\n\n\t\t\ttry {\n\t\t\t\tconst data = await client.git.getContents(repo, \"holocron.config.json\");\n\t\t\t\tconst raw = JSON.parse(Buffer.from(data.content.replace(/\\n/g, \"\"), \"base64\").toString(\"utf8\")) as {\n\t\t\t\t\tworkflows?: Array<string | WorkflowEntry>;\n\t\t\t\t};\n\t\t\t\tentries = (raw?.workflows ?? []).map((w) => (typeof w === \"string\" ? { name: w } : w));\n\t\t\t} catch (err) {\n\t\t\t\tif (!(err instanceof ProviderApiError) || err.status !== 404) throw err;\n\t\t\t\t// Fall back to .ts config\n\t\t\t\ttry {\n\t\t\t\t\tconst data = await client.git.getContents(repo, \"holocron.config.ts\");\n\t\t\t\t\tconst source = Buffer.from(data.content.replace(/\\n/g, \"\"), \"base64\").toString(\"utf8\");\n\t\t\t\t\tentries = parseWorkflowsFromTs(source);\n\t\t\t\t\torgContext = parseOrgContextFromTs(source);\n\t\t\t\t} catch {\n\t\t\t\t\t// No config — sync all workflows with no overrides\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (entries.length > 0) {\n\t\t\t\tallowedWorkflows = new Set(entries.map((e) => e.name));\n\t\t\t\tconst overrideEntries = entries.filter((e) => e.with != null).map((e) => [e.name, e.with!] as const);\n\t\t\t\tif (overrideEntries.length > 0) withOverrides = new Map(overrideEntries);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Parse error — sync all workflows with no overrides\n\t\t}\n\t}\n\n\t// ── 4. Build file batch ──────────────────────────────────────────────────\n\tconst batch = buildBatch(repo, allowedWorkflows, withOverrides, orgContext);\n\n\t// ── 5. Detect changes ────────────────────────────────────────────────────\n\tlet created = 0;\n\tlet updated = 0;\n\tlet unchanged = 0;\n\tconst changedFiles: Array<{ path: string; content: string }> = [];\n\n\tfor (const file of batch) {\n\t\tconst localSha = gitBlobSha(file.content);\n\t\tconst existingSha = existingBlobs.get(file.path);\n\n\t\tif (existingSha === localSha) {\n\t\t\tprint(` · unchanged ${file.path}`);\n\t\t\tunchanged++;\n\t\t} else if (existingSha) {\n\t\t\tprint(` ${dryRun ? \"~\" : \"✓\"} updated ${file.path}`);\n\t\t\tupdated++;\n\t\t\tif (!dryRun) changedFiles.push(file);\n\t\t} else {\n\t\t\tprint(` ${dryRun ? \"~\" : \"✓\"} created ${file.path}`);\n\t\t\tcreated++;\n\t\t\tif (!dryRun) changedFiles.push(file);\n\t\t}\n\t}\n\n\tprint(\"\");\n\tprint(` ${created} created, ${updated} updated, ${unchanged} unchanged`);\n\n\tif (dryRun || changedFiles.length === 0) {\n\t\treturn { status: dryRun ? \"dry-run\" : \"ok\", created, updated, unchanged };\n\t}\n\n\t// ── 6. Create blobs for changed files ────────────────────────────────────\n\tconst treeEntries: Array<{ path: string; mode: string; type: string; sha: string }> = [];\n\tfor (const file of changedFiles) {\n\t\ttry {\n\t\t\tconst blob = await client.git.createBlob(repo, file.content);\n\t\t\ttreeEntries.push({ path: file.path, mode: \"100644\", type: \"blob\", sha: blob.sha });\n\t\t} catch (err) {\n\t\t\tconst msg = `failed to create blob for ${file.path}: ${err instanceof Error ? err.message : String(err)}`;\n\t\t\tprint(` ✗ ${msg}`);\n\t\t\treturn { status: \"fail\", created, updated, unchanged, message: msg };\n\t\t}\n\t}\n\n\t// ── 7. Create tree ───────────────────────────────────────────────────────\n\tlet newTreeSha: string;\n\ttry {\n\t\tconst newTree = await client.git.createTree(repo, treeEntries, baseTreeSha);\n\t\tnewTreeSha = newTree.sha;\n\t} catch (err) {\n\t\tconst msg = `failed to create tree: ${err instanceof Error ? err.message : String(err)}`;\n\t\tprint(` ✗ ${msg}`);\n\t\treturn { status: \"fail\", created, updated, unchanged, message: msg };\n\t}\n\n\t// ── 8. Create commit ─────────────────────────────────────────────────────\n\tlet newCommitSha: string;\n\ttry {\n\t\tconst newCommit = await client.git.createCommit(repo, message, newTreeSha, [headSha]);\n\t\tnewCommitSha = newCommit.sha;\n\t} catch (err) {\n\t\tconst msg = `failed to create commit: ${err instanceof Error ? err.message : String(err)}`;\n\t\tprint(` ✗ ${msg}`);\n\t\treturn { status: \"fail\", created, updated, unchanged, message: msg };\n\t}\n\n\t// ── 9. Update (or create) branch ref ────────────────────────────────────\n\ttry {\n\t\tif (createPr && branch) {\n\t\t\ttry {\n\t\t\t\tawait client.git.createRef(repo, `refs/heads/${branch}`, newCommitSha);\n\t\t\t} catch (err) {\n\t\t\t\tif (!(err instanceof ProviderApiError) || err.status !== 422) throw err;\n\t\t\t\t// Branch already exists from a previous partial run — force-update it.\n\t\t\t\tawait client.git.updateRef(repo, `heads/${branch}`, newCommitSha, true);\n\t\t\t}\n\t\t} else {\n\t\t\tawait client.git.updateRef(repo, `heads/${targetBranch!}`, newCommitSha);\n\t\t}\n\t} catch (err) {\n\t\tconst msg = `failed to update ref: ${err instanceof Error ? err.message : String(err)}`;\n\t\tprint(` ✗ ${msg}`);\n\t\treturn { status: \"fail\", created, updated, unchanged, message: msg };\n\t}\n\n\t// ── 10. Open PR if requested ─────────────────────────────────────────────\n\tlet prUrl: string | undefined;\n\tif (branch && createPr && !dryRun) {\n\t\ttry {\n\t\t\tconst pr = await client.git.createPull(repo, {\n\t\t\t\ttitle: message.split(\"\\n\")[0]!,\n\t\t\t\thead: branch,\n\t\t\t\tbase: \"main\",\n\t\t\t\tbody: \"Auto-generated by `holocron sync-github`. Review and merge to apply template updates.\",\n\t\t\t});\n\t\t\tprUrl = pr.html_url;\n\t\t\tprint(` → PR opened: ${prUrl}`);\n\t\t} catch (err) {\n\t\t\tconst alreadyExists =\n\t\t\t\terr instanceof ProviderApiError && err.status === 422 && String(err.details).includes(\"already exists\");\n\t\t\tif (alreadyExists) {\n\t\t\t\tprint(` → PR already open for ${branch} — branch updated, ready to merge`);\n\t\t\t} else {\n\t\t\t\tprint(` ⚠ PR creation failed: ${err instanceof Error ? err.message : String(err)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { status: \"ok\", created, updated, unchanged, prUrl };\n}\n","import { readdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\n\n// Directories to skip when walking the repo tree\nconst SKIP_DIRS = new Set([\"node_modules\", \".git\", \"dist\", \"coverage\", \"build\", \".turbo\", \".next\", \"out\"]);\n\n// ── per-file-type patch functions ─────────────────────────────────────────────\n// Each returns the new file content, or null if nothing in that file changed.\n\nfunction patchPackageJson(content: string, from: number, to: number): string | null {\n\tlet pkg: Record<string, unknown>;\n\ttry {\n\t\tpkg = JSON.parse(content) as Record<string, unknown>;\n\t} catch {\n\t\treturn null;\n\t}\n\n\tlet changed = false;\n\n\tconst engines = pkg.engines as Record<string, string> | undefined;\n\tif (engines?.node && /^>=\\d+(?:\\.0\\.0)?$/.test(engines.node)) {\n\t\tconst major = parseInt(engines.node.match(/\\d+/)![0]!, 10);\n\t\tif (major === from) {\n\t\t\tengines.node = `>=${to}.0.0`;\n\t\t\tchanged = true;\n\t\t}\n\t}\n\n\tfor (const field of [\"devDependencies\", \"dependencies\"] as const) {\n\t\tconst deps = pkg[field] as Record<string, string> | undefined;\n\t\tif (!deps?.[\"@types/node\"]) continue;\n\t\t// Only update exact semver ranges; leave catalog: pins alone\n\t\tif (deps[\"@types/node\"] === `^${from}.0.0`) {\n\t\t\tdeps[\"@types/node\"] = `^${to}.0.0`;\n\t\t\tchanged = true;\n\t\t}\n\t}\n\n\treturn changed ? JSON.stringify(pkg, null, 2) + \"\\n\" : null;\n}\n\nfunction patchYaml(content: string, from: number, to: number): string | null {\n\t// node-version: 20 / node-version: '20' / node-version: \"20\"\n\tconst updated = content.replace(/node-version:\\s+['\"]?(\\d+)['\"]?/g, (match, ver) =>\n\t\tver === String(from) ? match.replace(String(from), String(to)) : match\n\t);\n\treturn updated !== content ? updated : null;\n}\n\nfunction patchPinFile(content: string, from: number, to: number): string | null {\n\t// .nvmrc / .node-version — \"20\" or \"20.x.y\" on the first line\n\tconst trimmed = content.trim();\n\tif (trimmed === String(from) || trimmed.startsWith(`${from}.`)) {\n\t\treturn `${to}\\n`;\n\t}\n\treturn null;\n}\n\nfunction patchDockerfile(content: string, from: number, to: number): string | null {\n\t// FROM node:20 / FROM node:20-alpine / FROM node:20.11.0\n\tconst updated = content.replace(/^(FROM\\s+node:)(\\d+)/gm, (match, prefix, ver) =>\n\t\tver === String(from) ? `${prefix}${to}` : match\n\t);\n\treturn updated !== content ? updated : null;\n}\n\nfunction patchToolVersions(content: string, from: number, to: number): string | null {\n\t// nodejs 20 / nodejs 20.11.0\n\tconst updated = content.replace(/^(nodejs\\s+)(\\d+)/gm, (match, prefix, ver) =>\n\t\tver === String(from) ? `${prefix}${to}` : match\n\t);\n\treturn updated !== content ? updated : null;\n}\n\ninterface Pattern {\n\tmatches: (filename: string) => boolean;\n\tpatch: (content: string, from: number, to: number) => string | null;\n}\n\nconst PATTERNS: Pattern[] = [\n\t{ matches: (n) => n === \"package.json\", patch: patchPackageJson },\n\t{ matches: (n) => n.endsWith(\".yml\") || n.endsWith(\".yaml\"), patch: patchYaml },\n\t{ matches: (n) => n === \".nvmrc\" || n === \".node-version\", patch: patchPinFile },\n\t{ matches: (n) => n === \"Dockerfile\" || n.startsWith(\"Dockerfile.\"), patch: patchDockerfile },\n\t{ matches: (n) => n === \".tool-versions\", patch: patchToolVersions },\n];\n\n// ── auto-detect current major from the repo ───────────────────────────────────\n\nfunction detectFrom(cwd: string, _readFile: (p: string) => string): number | null {\n\tfor (const name of [\".nvmrc\", \".node-version\"]) {\n\t\ttry {\n\t\t\tconst major = parseInt(_readFile(join(cwd, name)).trim(), 10);\n\t\t\tif (!isNaN(major)) return major;\n\t\t} catch {\n\t\t\t/* absent */\n\t\t}\n\t}\n\ttry {\n\t\tconst pkg = JSON.parse(_readFile(join(cwd, \"package.json\"))) as Record<string, unknown>;\n\t\tconst node = (pkg.engines as Record<string, string> | undefined)?.node;\n\t\tif (node) {\n\t\t\tconst m = node.match(/(\\d+)/);\n\t\t\tif (m) return parseInt(m[1]!, 10);\n\t\t}\n\t} catch {\n\t\t/* absent */\n\t}\n\treturn null;\n}\n\n// ── default file walker ───────────────────────────────────────────────────────\n\nfunction defaultWalkFiles(dir: string): string[] {\n\tconst results: string[] = [];\n\n\tfunction walk(current: string): void {\n\t\tlet entries: string[];\n\t\ttry {\n\t\t\tentries = readdirSync(current);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (SKIP_DIRS.has(entry)) continue;\n\t\t\tconst abs = join(current, entry);\n\t\t\ttry {\n\t\t\t\tif (statSync(abs).isDirectory()) walk(abs);\n\t\t\t\telse results.push(abs);\n\t\t\t} catch {\n\t\t\t\t/* skip unreadable */\n\t\t\t}\n\t\t}\n\t}\n\n\twalk(dir);\n\treturn results;\n}\n\n// ── public API ────────────────────────────────────────────────────────────────\n\nexport interface RunUpgradeNodeInput {\n\t/** Target Node.js major version (e.g., 22). */\n\tto: number;\n\t/** Source major version. Auto-detected from .nvmrc / engines.node when omitted. */\n\tfrom?: number;\n\t/** Working directory (repo root). Defaults to process.cwd(). */\n\tcwd?: string;\n\t/** Print what would change without writing anything. */\n\tdryRun?: boolean;\n\t/**\n\t * Extra file paths (relative to cwd) to scan in addition to the normal\n\t * walk. Use for non-conventional locations not covered by the pattern\n\t * registry (e.g., custom Dockerfiles, .tool-versions in a subdirectory).\n\t * Sourced from `upgrade.node.extra` in holocron.config.json.\n\t */\n\textra?: string[];\n\tprint?: (line: string) => void;\n\t/** Injectable for testing. */\n\treadFile?: (path: string) => string;\n\twriteFile?: (path: string, content: string) => void;\n\twalkFiles?: (dir: string) => string[];\n}\n\nexport type UpgradeNodeStatus = \"ok\" | \"fail\" | \"dry-run\";\n\nexport interface UpgradeNodeReport {\n\tstatus: UpgradeNodeStatus;\n\tupdated: readonly string[];\n\tmessage?: string;\n}\n\nexport async function runUpgradeNode(input: RunUpgradeNodeInput): Promise<UpgradeNodeReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst cwd = input.cwd ?? process.cwd();\n\tconst { to, dryRun = false, extra = [] } = input;\n\tconst _readFile = input.readFile ?? ((p: string) => readFileSync(p, \"utf8\"));\n\tconst _writeFile = input.writeFile ?? ((p: string, c: string) => writeFileSync(p, c));\n\tconst _walkFiles = input.walkFiles ?? defaultWalkFiles;\n\n\tconst from = input.from ?? detectFrom(cwd, _readFile);\n\tif (from === null) {\n\t\treturn {\n\t\t\tstatus: \"fail\",\n\t\t\tupdated: [],\n\t\t\tmessage: \"could not detect current Node version — pass --from <major>\",\n\t\t};\n\t}\n\n\tif (from === to) {\n\t\tprint(`Already at Node.js ${to} — nothing to do.`);\n\t\treturn { status: \"ok\", updated: [] };\n\t}\n\n\tprint(`Upgrading Node.js ${from} → ${to}${dryRun ? \" (dry-run)\" : \"\"}…`);\n\n\tconst updated: string[] = [];\n\tconst scanned = [..._walkFiles(cwd), ...extra.map((p) => join(cwd, p))];\n\n\tfor (const abs of scanned) {\n\t\tconst name = basename(abs);\n\t\tconst pattern = PATTERNS.find((p) => p.matches(name));\n\t\tif (!pattern) continue;\n\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = _readFile(abs);\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst patched = pattern.patch(content, from, to);\n\t\tif (patched === null) continue;\n\n\t\tconst rel = abs.startsWith(cwd + \"/\") ? abs.slice(cwd.length + 1) : abs;\n\t\tif (!dryRun) _writeFile(abs, patched);\n\t\tprint(` ${dryRun ? \"~\" : \"✓\"} ${rel}`);\n\t\tupdated.push(rel);\n\t}\n\n\tif (updated.length === 0) {\n\t\tprint(` · no files contained Node.js ${from} pins`);\n\t}\n\n\treturn { status: dryRun ? \"dry-run\" : \"ok\", updated };\n}\n","/**\n * `holocron.config.{json,js,ts}` file loader.\n *\n * Search order: json → js → ts. JSON is parsed directly; JS is loaded\n * via native dynamic import; TS is loaded via `tsImport` from tsx (a\n * runtime dep) so operators can write typed configs with `defineConfig`\n * without needing a separate build step.\n *\n * All three forms are validated through the same `resolveConfig` path.\n * Implements the lookup-order contract from issue #75 / #81.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport { basename, dirname, join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nimport type { HolocronConfig, ResolvedHolocronConfig } from \"./config.js\";\nimport { ConfigError, resolveConfig } from \"./config.js\";\n\nconst CANDIDATE_FILENAMES = [\"holocron.config.json\", \"holocron.config.js\", \"holocron.config.ts\"] as const;\n\nexport class ConfigFileError extends Error {\n\toverride name = \"ConfigFileError\";\n}\n\nexport interface LoadedConfig {\n\tresolved: ResolvedHolocronConfig;\n\t/** Absolute path to the file the config was read from. */\n\tfilepath: string;\n}\n\n/**\n * Read + parse + resolve `holocron.config.*` from the given directory.\n * Search order: json → js → ts. Throws `ConfigFileError` if nothing\n * found, or `ConfigError` if the config is malformed / invalid.\n */\nexport async function loadConfig(cwd: string): Promise<LoadedConfig> {\n\tfor (const filename of CANDIDATE_FILENAMES) {\n\t\tconst fullPath = join(cwd, filename);\n\t\tif (await fileExists(fullPath)) {\n\t\t\tif (filename.endsWith(\".json\")) {\n\t\t\t\treturn { resolved: await loadJson(fullPath), filepath: fullPath };\n\t\t\t}\n\t\t\tif (filename.endsWith(\".ts\")) {\n\t\t\t\treturn { resolved: await loadTs(fullPath), filepath: fullPath };\n\t\t\t}\n\t\t\treturn { resolved: await loadJs(fullPath), filepath: fullPath };\n\t\t}\n\t}\n\tthrow new ConfigFileError(\n\t\t`no holocron.config.{json,js,ts} found in ${cwd}. Create one — see the README for the schema.`\n\t);\n}\n\nasync function loadJson(filepath: string): Promise<ResolvedHolocronConfig> {\n\tconst raw = await readFile(filepath, \"utf8\");\n\tlet parsed: HolocronConfig;\n\ttry {\n\t\tparsed = JSON.parse(raw) as HolocronConfig;\n\t} catch (err) {\n\t\tthrow new ConfigError(`${filepath} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);\n\t}\n\treturn resolveConfig(await deriveDefaults(dirname(filepath), parsed));\n}\n\nasync function loadJs(filepath: string): Promise<ResolvedHolocronConfig> {\n\tconst mod = await import(pathToFileURL(filepath).href);\n\treturn resolveConfig(await deriveDefaults(dirname(filepath), extractRaw(filepath, mod)));\n}\n\nasync function loadTs(filepath: string): Promise<ResolvedHolocronConfig> {\n\tconst { tsImport } = await import(\"tsx/esm/api\");\n\tconst mod = await tsImport(pathToFileURL(filepath).href, import.meta.url);\n\treturn resolveConfig(await deriveDefaults(dirname(filepath), extractRaw(filepath, mod)));\n}\n\nfunction extractRaw(filepath: string, mod: unknown): HolocronConfig {\n\tconst outer = (mod as { default?: unknown }).default;\n\t// tsx CJS-transforms `export default x` into `exports.default = x`, which\n\t// dynamic import wraps as { default: { __esModule: true, default: x } }.\n\t// Unwrap the extra layer when present so both ESM and CJS outputs work.\n\tconst raw =\n\t\t(outer as { __esModule?: boolean })?.__esModule === true ? (outer as { default?: unknown }).default : outer;\n\tif (raw === undefined || raw === null) {\n\t\tthrow new ConfigFileError(`${filepath} must have a default export (use \\`export default defineConfig({…})\\`)`);\n\t}\n\treturn raw as HolocronConfig;\n}\n\nasync function deriveDefaults(configDir: string, raw: HolocronConfig): Promise<HolocronConfig> {\n\tconst result = { ...raw };\n\tif (!result.name) {\n\t\tresult.name = (await readPackageJsonName(configDir)) ?? basename(configDir);\n\t}\n\tif (result.repo && !result.repo.name) {\n\t\tconst repoName = await readGitRemote(configDir);\n\t\tif (repoName) result.repo = { ...result.repo, name: repoName };\n\t}\n\treturn result;\n}\n\nasync function readPackageJsonName(dir: string): Promise<string | undefined> {\n\ttry {\n\t\tconst content = await readFile(join(dir, \"package.json\"), \"utf8\");\n\t\tconst pkg = JSON.parse(content) as { name?: string };\n\t\treturn typeof pkg.name === \"string\" ? pkg.name.replace(/^@[^/]+\\//, \"\") : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nasync function readGitRemote(dir: string): Promise<string | undefined> {\n\ttry {\n\t\tconst { stdout } = await execFileAsync(\"git\", [\"remote\", \"get-url\", \"origin\"], { cwd: dir });\n\t\treturn parseGitRemoteUrl(stdout.trim());\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction parseGitRemoteUrl(url: string): string | undefined {\n\tconst httpsMatch = url.match(/github\\.com\\/([^/]+\\/[^/]+?)(?:\\.git)?$/);\n\tif (httpsMatch) return httpsMatch[1]!;\n\tconst sshMatch = url.match(/github\\.com:([^/]+\\/[^/]+?)(?:\\.git)?$/);\n\tif (sshMatch) return sshMatch[1]!;\n\treturn undefined;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tconst s = await stat(path);\n\t\treturn s.isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n","import type { ErrorEvent, EventHint } from \"@sentry/node\";\nimport * as Sentry from \"@sentry/node\";\n\n// Paste your DSN from Sentry → Settings → Client Keys once the project is created.\n// Empty string = telemetry silently disabled — safe to ship before the project exists.\nconst DSN: string = \"https://95cbb72ad5636c94e119a5405ee8f55f@o4508238154104832.ingest.us.sentry.io/4511810950791168\";\n\nfunction isEnabled(): boolean {\n\treturn !process.env.NO_HOLOCRON_TELEMETRY && DSN !== \"\";\n}\n\nexport function init(version: string): void {\n\tif (!isEnabled()) return;\n\tSentry.init({\n\t\tdsn: DSN,\n\t\trelease: `holocron@${version}`,\n\t\tenvironment: process.env.CI ? \"ci\" : \"local\",\n\t\ttracesSampleRate: 1.0,\n\t\tbeforeSend: scrubError,\n\t});\n\tSentry.startSession();\n\tSentry.setTag(\"os\", process.platform);\n\tSentry.setTag(\"node\", process.version);\n\tSentry.setTag(\"ci\", String(Boolean(process.env.CI)));\n}\n\nexport function startCommand(name: string): (ok: boolean) => void {\n\tif (!isEnabled()) return () => {};\n\tSentry.setTag(\"command\", name);\n\tconst span = Sentry.startInactiveSpan({ name, op: \"holocron.command\", forceTransaction: true });\n\treturn (ok: boolean) => {\n\t\tspan.setStatus({ code: ok ? 1 : 2 });\n\t\tspan.end();\n\t};\n}\n\nexport function captureException(err: unknown): void {\n\tif (!isEnabled()) return;\n\tSentry.captureException(err);\n}\n\nexport function endSession(): void {\n\tif (!isEnabled()) return;\n\tSentry.endSession();\n}\n\nexport async function flush(): Promise<void> {\n\tif (!isEnabled()) return;\n\tawait Sentry.close(2_000);\n}\n\n// Scrub known token shapes from any string in the Sentry event payload.\nconst TOKEN_RE = /\\b(ghp_|ghs_|glpat-|xoxb-|xoxp-|npm_|sk-|[A-Z][A-Z0-9_]{2,}_TOKEN[=\\s])[^\\s\"]*/g;\n\nfunction redact(raw: string): string {\n\treturn raw.replace(TOKEN_RE, \"[REDACTED]\");\n}\n\nfunction scrubError(event: ErrorEvent, _hint: EventHint): ErrorEvent {\n\treturn JSON.parse(redact(JSON.stringify(event))) as ErrorEvent;\n}\n","export class TokenParseError extends Error {\n\toverride name = \"TokenParseError\";\n}\n\nexport interface ParsedTokenArgs {\n\t/** Set when a bare (unkeyed) --token value was passed. Used as fallback for all plugins. */\n\tcliToken?: string;\n\t/** Set when one or more vendor=value pairs were passed. */\n\tcliTokens?: Record<string, string>;\n}\n\n/**\n * Converts raw --token CLI values into a typed result.\n *\n * Bare form: --token ghp_xxx → { cliToken: \"ghp_xxx\" }\n * Keyed form: --token github=ghp_xxx → { cliTokens: { github: \"ghp_xxx\" } }\n * Mixed: --token github=ghp_xxx --token v_yyy\n * → { cliToken: \"v_yyy\", cliTokens: { github: \"ghp_xxx\" } }\n *\n * Values may contain \"=\" (e.g. base64 strings) — only the first \"=\" is treated as a separator.\n */\nexport function parseTokenArgs(tokens: string[]): ParsedTokenArgs {\n\tif (tokens.length === 0) return {};\n\n\tconst cliTokens: Record<string, string> = {};\n\tconst bare: string[] = [];\n\n\tfor (const raw of tokens) {\n\t\tconst eqIdx = raw.indexOf(\"=\");\n\n\t\tif (eqIdx === -1) {\n\t\t\tbare.push(raw);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst vendor = raw.slice(0, eqIdx);\n\t\tconst value = raw.slice(eqIdx + 1);\n\n\t\tif (vendor.trim() === \"\") {\n\t\t\tthrow new TokenParseError(`invalid --token value \"${raw}\": vendor name must not be empty`);\n\t\t}\n\t\tif (/\\s/.test(vendor)) {\n\t\t\tthrow new TokenParseError(`invalid --token value \"${raw}\": vendor name must not contain whitespace`);\n\t\t}\n\t\tif (value === \"\") {\n\t\t\tthrow new TokenParseError(`invalid --token value \"${raw}\": token value must not be empty`);\n\t\t}\n\n\t\tcliTokens[vendor] = value;\n\t}\n\n\tif (bare.length > 1) {\n\t\tthrow new TokenParseError(\n\t\t\t`only one bare --token value is allowed; got ${bare.length.toString()} — use vendor=value form for multiple tokens`\n\t\t);\n\t}\n\n\tconst result: ParsedTokenArgs = {};\n\tif (bare.length === 1) result.cliToken = bare[0];\n\tif (Object.keys(cliTokens).length > 0) result.cliTokens = cliTokens;\n\treturn result;\n}\n","import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport chalk from \"chalk\";\n\nconst PACKAGE_NAME = \"@theholocron/cli\";\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000;\nconst FETCH_TIMEOUT_MS = 3000;\n\ninterface CacheEntry {\n\tlatestVersion: string;\n\tcheckedAt: number;\n}\n\nfunction getCacheDir(): string {\n\treturn process.env[\"HOLOCRON_CACHE_DIR\"] ?? join(homedir(), \".cache\", \"holocron\");\n}\n\nfunction getCachePath(): string {\n\treturn join(getCacheDir(), \"update-check.json\");\n}\n\nfunction readCache(): CacheEntry | null {\n\ttry {\n\t\treturn JSON.parse(readFileSync(getCachePath(), \"utf8\")) as CacheEntry;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction writeCache(entry: CacheEntry): void {\n\ttry {\n\t\tmkdirSync(getCacheDir(), { recursive: true });\n\t\twriteFileSync(getCachePath(), JSON.stringify(entry));\n\t} catch {\n\t\t// silently ignore — update check is best-effort\n\t}\n}\n\nasync function fetchLatestVersion(channel: string): Promise<string | null> {\n\ttry {\n\t\tconst res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}`, {\n\t\t\tsignal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n\t\t});\n\t\tif (!res.ok) return null;\n\t\tconst data = (await res.json()) as { \"dist-tags\": Record<string, string> };\n\t\treturn data[\"dist-tags\"][channel] ?? data[\"dist-tags\"][\"latest\"] ?? null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction getChannel(version: string): string {\n\tconst match = /^[^-]+-([a-zA-Z]+)/.exec(version);\n\treturn match?.[1] ?? \"latest\";\n}\n\nexport function isUpdateAvailable(current: string, latest: string): boolean {\n\tconst normalize = (v: string) => v.replace(/^v/, \"\");\n\tconst c = normalize(current);\n\tconst l = normalize(latest);\n\tif (c === l) return false;\n\n\tconst splitPre = (v: string): [string, string] => {\n\t\tconst idx = v.indexOf(\"-\");\n\t\treturn idx === -1 ? [v, \"\"] : [v.slice(0, idx), v.slice(idx + 1)];\n\t};\n\n\tconst [cRelease, cPre] = splitPre(c);\n\tconst [lRelease, lPre] = splitPre(l);\n\n\tconst parseRelease = (r: string) => r.split(\".\").map(Number);\n\tconst cParts = parseRelease(cRelease);\n\tconst lParts = parseRelease(lRelease);\n\n\tfor (let i = 0; i < Math.max(cParts.length, lParts.length); i++) {\n\t\tconst cv = cParts[i] ?? 0;\n\t\tconst lv = lParts[i] ?? 0;\n\t\tif (lv > cv) return true;\n\t\tif (lv < cv) return false;\n\t}\n\n\t// Release parts equal — compare prerelease\n\tif (!lPre && cPre) return true; // stable > prerelease\n\tif (lPre && !cPre) return false; // prerelease < stable\n\n\t// Both prerelease — compare segment by segment\n\tconst cPreParts = cPre.split(\".\");\n\tconst lPreParts = lPre.split(\".\");\n\tfor (let i = 0; i < Math.max(cPreParts.length, lPreParts.length); i++) {\n\t\tconst cv = cPreParts[i] ?? \"\";\n\t\tconst lv = lPreParts[i] ?? \"\";\n\t\tconst cvNum = Number(cv);\n\t\tconst lvNum = Number(lv);\n\t\tif (!isNaN(cvNum) && !isNaN(lvNum)) {\n\t\t\tif (lvNum > cvNum) return true;\n\t\t\tif (lvNum < cvNum) return false;\n\t\t} else {\n\t\t\tif (lv > cv) return true;\n\t\t\tif (lv < cv) return false;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nfunction formatNotice(current: string, latest: string): string {\n\tconst installCmd = `npm install -g ${PACKAGE_NAME}`;\n\t// Measure raw strings before applying chalk so we avoid control-char regexes.\n\tconst raw1 = `Update available: ${current} → ${latest}`;\n\tconst raw2 = `Run ${installCmd} to update`;\n\tconst width = Math.max(raw1.length, raw2.length) + 4;\n\tconst bar = chalk.yellow(\"─\".repeat(width));\n\tconst border = chalk.yellow(\"│\");\n\tconst pad = (raw: string, styled: string) => `${border} ${styled}${\" \".repeat(width - 2 - raw.length)} ${border}`;\n\treturn [\n\t\t\"\",\n\t\tchalk.yellow(`╭${bar}╮`),\n\t\tpad(raw1, `Update available: ${chalk.dim(current)} → ${chalk.green(latest)}`),\n\t\tpad(raw2, `Run ${chalk.cyan(installCmd)} to update`),\n\t\tchalk.yellow(`╰${bar}╯`),\n\t\t\"\",\n\t].join(\"\\n\");\n}\n\nexport async function checkForUpdates(currentVersion: string): Promise<(() => void) | null> {\n\tif (process.env[\"CI\"] || process.env[\"NO_UPDATE_NOTIFIER\"]) return null;\n\n\tconst channel = getChannel(currentVersion);\n\tconst cache = readCache();\n\tconst now = Date.now();\n\n\tlet latestVersion: string | null = null;\n\n\tif (cache && now - cache.checkedAt < CACHE_TTL_MS) {\n\t\tlatestVersion = cache.latestVersion;\n\t} else {\n\t\tlatestVersion = await fetchLatestVersion(channel);\n\t\tif (latestVersion) writeCache({ latestVersion, checkedAt: now });\n\t}\n\n\tif (!latestVersion || !isUpdateAvailable(currentVersion, latestVersion)) return null;\n\n\treturn () => {\n\t\tprocess.stderr.write(formatNotice(currentVersion, latestVersion as string) + \"\\n\");\n\t};\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { input, select } from \"@inquirer/prompts\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\n\nimport { AuthError, createFeatureResolver } from \"./auth-resolver.js\";\nimport { CARDINALITY } from \"./capabilities/index.js\";\nimport { runAuthCheck, runAuthList, runAuthSet, runAuthUnset } from \"./commands/auth.js\";\nimport { runClone } from \"./commands/clone.js\";\nimport { runDeploy } from \"./commands/deploy.js\";\nimport { runDoctor } from \"./commands/doctor.js\";\nimport { NewError, parseTopics, runNew, validateRepoName } from \"./commands/new.js\";\nimport { runNpmBumpVersions } from \"./commands/npm-bump-versions.js\";\nimport { runNpmPublishInitial } from \"./commands/npm-publish-initial.js\";\nimport { PluginCreateError, resolvePluginCreateInputs, runPluginCreate } from \"./commands/plugin-create/index.js\";\nimport { runSecretSet } from \"./commands/secret-set.js\";\nimport { runSecretsSync } from \"./commands/secrets-sync.js\";\nimport { runSetup } from \"./commands/setup.js\";\nimport { runSkillsInstall, runSkillsRemove, runSkillsUpdate } from \"./commands/skills.js\";\nimport { runSync } from \"./commands/sync.js\";\nimport { runSyncGithub } from \"./commands/sync-github.js\";\nimport { runSyncReadme } from \"./commands/sync-readme.js\";\nimport { runUpgradeNode } from \"./commands/upgrade-node.js\";\nimport { loadConfig } from \"./load-config.js\";\nimport { captureException, endSession, flush, init, startCommand } from \"./telemetry.js\";\nimport { type ParsedTokenArgs, parseTokenArgs, TokenParseError } from \"./token-args.js\";\nimport { checkForUpdates } from \"./update-notifier.js\";\n\nconst resolveCloneToken = createFeatureResolver({ envName: \"HOLOCRON_READ_TOKEN\", keyringKey: \"github.read\" });\nconst resolveSyncToken = createFeatureResolver({ envName: \"HOLOCRON_SYNC_TOKEN\", keyringKey: \"github.sync\" });\n\nconst { version: CLI_VERSION } = JSON.parse(readFileSync(new URL(\"../package.json\", import.meta.url), \"utf-8\")) as {\n\tversion: string;\n};\n\n/**\n * Resolves the active org in priority order:\n * 1. `--org` CLI flag\n * 2. `HOLOCRON_ORG` env var\n * 3. `org` from `holocron.config.ts`\n */\nfunction resolveOrg(argv: { org?: string }, config: { org?: string }): string | undefined {\n\treturn argv.org ?? process.env[\"HOLOCRON_ORG\"] ?? config.org;\n}\n\n/** Parses --token values and returns the context spread, or null on parse error (exits with code 1). */\nfunction tokenContext(rawTokens: string[] | undefined): ParsedTokenArgs | null {\n\tif (!rawTokens?.length) return {};\n\ttry {\n\t\treturn parseTokenArgs(rawTokens);\n\t} catch (err) {\n\t\tif (err instanceof TokenParseError) {\n\t\t\tconsole.error(`--token: ${err.message}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn null;\n\t\t}\n\t\tthrow err;\n\t}\n}\n\ninit(CLI_VERSION);\nconst updateCheckPromise = checkForUpdates(CLI_VERSION);\n\nlet finishCommand: (ok: boolean) => void = () => {};\n\ntry {\n\tawait yargs(hideBin(process.argv))\n\t\t.middleware((argv) => {\n\t\t\tconst name = (argv._ as string[]).slice(0, 2).join(\" \") || \"unknown\";\n\t\t\tfinishCommand = startCommand(name);\n\t\t})\n\t\t.scriptName(\"\")\n\t\t.usage(\"holocron <command> [options]\")\n\t\t// ── global options (apply to every subcommand) ──────────────────────\n\t\t.option(\"dry-run\", {\n\t\t\ttype: \"boolean\",\n\t\t\tdefault: false,\n\t\t\tdescribe:\n\t\t\t\t\"Print what would be mutated without calling capability mutators. \" +\n\t\t\t\t\"Commands branch on this; read-only commands ignore it.\",\n\t\t})\n\t\t.option(\"token\", {\n\t\t\ttype: \"string\",\n\t\t\tarray: true,\n\t\t\tdescribe:\n\t\t\t\t\"Vendor token override for plugins. \" +\n\t\t\t\t\"Bare form: --token <value> (fallback for all plugins, single-plugin commands). \" +\n\t\t\t\t\"Keyed form: --token vendor=value (targets a specific provider; repeat for each). \" +\n\t\t\t\t\"Example: --token github=ghp_xxx --token vercel=v_yyy\",\n\t\t})\n\t\t.option(\"org\", {\n\t\t\ttype: \"string\",\n\t\t\tdescribe:\n\t\t\t\t\"Active org name for namespaced keyring lookup. \" +\n\t\t\t\t\"Overrides HOLOCRON_ORG env var and the `org` field in holocron.config.ts. \" +\n\t\t\t\t\"Example: --org theholocron\",\n\t\t})\n\t\t.option(\"cwd\", {\n\t\t\ttype: \"string\",\n\t\t\tdefault: process.cwd(),\n\t\t\tdescribe: \"Directory to search for holocron.config.json\",\n\t\t})\n\t\t// ── commands ────────────────────────────────────────────────────────\n\t\t.command(\n\t\t\t\"version\",\n\t\t\t\"Print the CLI version\",\n\t\t\t() => {},\n\t\t\t() => {\n\t\t\t\tconsole.log(`holocron ${CLI_VERSION}`);\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"clone\",\n\t\t\t\"Clone all repos in a GitHub org as siblings under a single directory\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.option(\"org\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"GitHub org to clone (e.g., theholocron)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"dir\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Parent directory to clone into (default: ~/Code/<org>)\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tlet token: string;\n\t\t\t\ttry {\n\t\t\t\t\ttoken = resolveCloneToken({ cliToken: tokens.cliTokens?.[\"github\"] ?? tokens.cliToken });\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`clone: ${err instanceof AuthError ? err.message : String(err)}`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst report = await runClone({\n\t\t\t\t\torg: argv.org,\n\t\t\t\t\ttoken,\n\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t...(argv.dir ? { dir: argv.dir } : {}),\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"doctor\",\n\t\t\t\"Load the config and run a smoke check against every provider\",\n\t\t\t(y) =>\n\t\t\t\ty.option(\"repo\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescribe: 'Repo coords (\"owner/name\"). Defaults to plugin-specific resolution.',\n\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runDoctor({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...(argv.repo ? { repo: argv.repo } : {}),\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (report.summary.fail > 0) {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"setup\",\n\t\t\t\"Apply infra setup actions across every configured capability\",\n\t\t\t(y) =>\n\t\t\t\ty.option(\"repo\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescribe: 'Repo coords (\"owner/name\"). Defaults to plugin-specific resolution.',\n\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runSetup({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...(argv.repo ? { repo: argv.repo } : {}),\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (report.summary.fail > 0) {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"skills\",\n\t\t\t\"Manage agent skills from the @theholocron/skills registry\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"install\",\n\t\t\t\t\t\t\"Copy skills from @theholocron/skills into .agents/ with agent symlinks\",\n\t\t\t\t\t\t() => {},\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\t\t\t\tawait runSkillsInstall({ loaded, context: { repoRoot: argv.cwd, dryRun: argv.dryRun } });\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"remove [names..]\",\n\t\t\t\t\t\t\"Remove installed skills via npx skills remove\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy.positional(\"names\", {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\tarray: true,\n\t\t\t\t\t\t\t\tdescribe: \"Skill name(s) to remove (omit to remove all installed skills)\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t(argv) => {\n\t\t\t\t\t\t\tconst report = runSkillsRemove({\n\t\t\t\t\t\t\t\tcontext: { repoRoot: argv.cwd, dryRun: argv.dryRun },\n\t\t\t\t\t\t\t\t...(argv.names?.length ? { names: argv.names as string[] } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"update [name]\",\n\t\t\t\t\t\t\"Update installed skills to their latest upstream versions via npx skills update\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy.positional(\"name\", {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\tdescribe: \"Skill name to update (omit to update all installed skills)\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t(argv) => {\n\t\t\t\t\t\t\tconst report = runSkillsUpdate({\n\t\t\t\t\t\t\t\tcontext: { repoRoot: argv.cwd, dryRun: argv.dryRun },\n\t\t\t\t\t\t\t\t...(argv.name ? { name: argv.name as string } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.demandCommand(1, \"Run `holocron skills --help` to see available skills subcommands.\"),\n\t\t\t() => {}\n\t\t)\n\t\t.command(\n\t\t\t\"secret set <name> [value]\",\n\t\t\t\"Set a single secret via the configured `secrets` capability\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"name\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Secret name (e.g., NPM_TOKEN)\",\n\t\t\t\t\t})\n\t\t\t\t\t.positional(\"value\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Secret value (positional). If omitted, sources from --from-stdin, --from-env, or env var matching <name>.\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"from-stdin\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescribe: \"Read the secret value from stdin\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"from-env\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Read the secret value from the named env var (otherwise: env var matching <name>)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"scope\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdefault: \"repo\",\n\t\t\t\t\t\tdescribe: 'Scope: \"repo\" (default), \"env=<name>\", or \"org=<name>\"',\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst scopeArg = argv.scope as string;\n\t\t\t\tconst scope = parseScope(scopeArg);\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runSecretSet({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t\tname: argv.name as string,\n\t\t\t\t\t...(argv.value ? { value: argv.value as string } : {}),\n\t\t\t\t\t...(argv.fromStdin ? { fromStdin: true } : {}),\n\t\t\t\t\t...(argv.fromEnv ? { fromEnv: argv.fromEnv as string } : {}),\n\t\t\t\t\tscope,\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"secrets sync <environmentId>\",\n\t\t\t\"Read a vault environment + fan KEY=VALUEs out to secrets + deployment env vars\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"environmentId\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Vault environment id to read (1P Environment id, etc.)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"project-id\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Deployment project id (e.g., Vercel prj_*). Required when deployment is loaded.\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"target\", {\n\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\tdefault: [\"production\", \"preview\"] as Array<\"development\" | \"preview\" | \"production\">,\n\t\t\t\t\t\tdescribe: \"Deployment targets to sync to. Defaults to production + preview.\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runSecretsSync({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t\tenvironmentId: argv.environmentId as string,\n\t\t\t\t\t...(argv.projectId ? { projectId: argv.projectId } : {}),\n\t\t\t\t\ttargets: argv.target as Array<\"development\" | \"preview\" | \"production\">,\n\t\t\t\t});\n\t\t\t\tif (report.summary.fail > 0) {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"deploy <branch>\",\n\t\t\t\"Trigger a deployment via the configured `deployment` capability\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"branch\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Git branch to deploy\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"project-id\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Deployment project id (e.g., Vercel prj_*)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"target\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tchoices: [\"production\", \"staging\"] as const,\n\t\t\t\t\t\tdescribe: \"Named environment to deploy into. Omit for a branch preview.\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runDeploy({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t\tprojectId: argv.projectId as string,\n\t\t\t\t\tbranch: argv.branch as string,\n\t\t\t\t\t...(argv.target ? { target: argv.target as \"production\" | \"staging\" } : {}),\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"npm\",\n\t\t\t\"npm-related monorepo utilities\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"bump-versions <new-version>\",\n\t\t\t\t\t\t\"Bump all non-private package versions in lockstep (semantic-release prepareCmd)\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy.positional(\"new-version\", {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\t\t\tdescribe: \"Version to set (e.g., 4.2.0 or 2.0.0-alpha.1)\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\tconst report = await runNpmBumpVersions({\n\t\t\t\t\t\t\t\tversion: argv.newVersion as string,\n\t\t\t\t\t\t\t\tcwd: argv.cwd,\n\t\t\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"publish-initial\",\n\t\t\t\t\t\t\"One-shot bootstrap publish for trusted-publishing-eligible packages\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy\n\t\t\t\t\t\t\t\t.option(\"tag\", {\n\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\tdefault: \"alpha\",\n\t\t\t\t\t\t\t\t\tdescribe: \"npm distribution tag (defaults to alpha)\",\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.option(\"otp\", {\n\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\t\t\t\"One-time password from your authenticator (required if npm needs 2FA for writes)\",\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\tconst report = await runNpmPublishInitial({\n\t\t\t\t\t\t\t\tcwd: argv.cwd,\n\t\t\t\t\t\t\t\ttag: argv.tag,\n\t\t\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t\t\t...(argv.otp ? { otp: argv.otp as string } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.demandCommand(1, \"Run `holocron npm --help` to see available npm subcommands.\"),\n\t\t\t() => {}\n\t\t)\n\t\t.command(\n\t\t\t\"sync [steps..]\",\n\t\t\t\"Sync state from config to the provider and local files (labels, properties, topics, keywords, description, homepage, readme)\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"steps\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tarray: true,\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Steps to run: labels, properties, topics, keywords, description, homepage, readme (default: all)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"repo\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: 'Repo coords (\"owner/name\"). Defaults to plugin-specific resolution.',\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runSync({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...(argv.repo ? { repo: argv.repo } : {}),\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t\t...(argv.steps && argv.steps.length > 0 ? { steps: argv.steps as string[] } : {}),\n\t\t\t\t});\n\t\t\t\tif (report.summary.fail > 0) {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"sync-github\",\n\t\t\t\"Sync workflow templates and composite actions to theholocron/.github via the GitHub API\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.option(\"repo\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdefault: \"theholocron/.github\",\n\t\t\t\t\t\tdescribe: \"Target org/repo (default: theholocron/.github)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"branch\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Push to this branch instead of the default branch (enables PR-based workflow for protected repos)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"pr\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescribe: \"Open a PR after pushing to --branch (no-op without --branch)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"message\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Commit message (default: chore: sync from theholocron/holocron)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"output-dir\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Write generated files to this local directory instead of pushing (for validation)\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst outputDir = argv[\"output-dir\"] as string | undefined;\n\t\t\t\tconst parsed = tokenContext(argv.token);\n\t\t\t\tif (!parsed) return;\n\t\t\t\tlet token: string;\n\t\t\t\tif (outputDir) {\n\t\t\t\t\ttoken = \"no-token-needed\";\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\ttoken = resolveSyncToken({ cliToken: parsed.cliTokens?.[\"github\"] ?? parsed.cliToken });\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(`sync-github: ${err instanceof AuthError ? err.message : String(err)}`);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst report = await runSyncGithub({\n\t\t\t\t\ttoken,\n\t\t\t\t\trepo: argv.repo,\n\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t...(argv.branch ? { branch: argv.branch } : {}),\n\t\t\t\t\t...(argv.pr ? { createPr: true } : {}),\n\t\t\t\t\t...(argv.message ? { message: argv.message } : {}),\n\t\t\t\t\t...(outputDir ? { outputDir } : {}),\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"sync-readme\",\n\t\t\t\"Sync the Installation + Usage block in README.md from package.json\",\n\t\t\t(y) =>\n\t\t\t\ty.option(\"dry-run\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdescribe: \"Print what would change without writing\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runSyncReadme({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: { repoRoot: argv.cwd, dryRun: argv.dryRun },\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"config show\",\n\t\t\t\"Print the resolved holocron config\",\n\t\t\t() => {},\n\t\t\tasync (argv) => {\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconsole.log(JSON.stringify(loaded.resolved, null, 2));\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"new [type] [name]\",\n\t\t\t\"Scaffold a new repo from a GitHub template (e.g. cli, react, nextjs, node, monorepo, base)\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"type\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Template type — maps to theholocron/<type>-template \" +\n\t\t\t\t\t\t\t\"(e.g. cli, react, nextjs, node, monorepo, base)\",\n\t\t\t\t\t})\n\t\t\t\t\t.positional(\"name\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"New repo name (kebab-case, e.g. my-tool)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"description\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Short description — replaces <description> placeholders in the template\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"homepage\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Homepage URL — replaces <homepage> placeholders and appears in holocron.config.ts\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"vault\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Vault provider: none, doppler, 1password, infisical\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"deployment\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Deployment provider: none, vercel\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"agent\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"AI agent: claude, none\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"runtime-environment\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Runtime environment: node, browser, universal, none\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"topics\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Comma-separated repo topics (e.g. typescript,nodejs)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"protection\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Branch protection level: strict, balanced, minimal\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"open-source\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdescribe: \"Whether the repo is open source (default: true)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"uses-external-packages\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdescribe: \"Whether the repo calls external APIs or services (default: true)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"skills\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Comma-separated agent skill names (e.g. git-safety,pr-workflow)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"is-template\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdescribe: \"Mark the new repo as a GitHub template repository\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"org\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdefault: \"theholocron\",\n\t\t\t\t\t\tdescribe: \"GitHub org that owns the template and will own the new repo\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"verify\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdefault: true,\n\t\t\t\t\t\tdescribe: \"Run pnpm install + holocron setup after bootstrapping (--no-verify skips)\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\t\tif (!tokens) return;\n\t\t\t\t\tconst adminToken = tokens.cliTokens?.[\"github\"] ?? tokens.cliToken;\n\n\t\t\t\t\tlet type = argv.type as string | undefined;\n\t\t\t\t\tlet name = argv.name as string | undefined;\n\t\t\t\t\tlet description = argv.description as string | undefined;\n\t\t\t\t\tlet homepage = argv.homepage as string | undefined;\n\t\t\t\t\tlet vaultProvider = argv.vault as string | undefined;\n\t\t\t\t\tlet vaultProject: string | undefined;\n\t\t\t\t\tlet vaultConfig: string | undefined;\n\t\t\t\t\tlet deploymentProvider = argv.deployment as string | undefined;\n\t\t\t\t\tlet agent = argv.agent as string | undefined;\n\t\t\t\t\tlet runtimeEnvironment = argv.runtimeEnvironment as string | undefined;\n\t\t\t\t\tlet topics: string[] = parseTopics(argv.topics as string | undefined);\n\t\t\t\t\tlet protection = argv.protection as string | undefined;\n\t\t\t\t\tlet openSource = argv.openSource as boolean | undefined;\n\t\t\t\t\tlet usesExternalPackages = argv.usesExternalPackages as boolean | undefined;\n\t\t\t\t\tlet skills: string[] = parseTopics(argv.skills as string | undefined);\n\t\t\t\t\tconst isTemplate = argv.isTemplate as boolean | undefined;\n\n\t\t\t\t\t// Interactive wizard — skip any field already supplied as a CLI arg\n\t\t\t\t\tif (!type) {\n\t\t\t\t\t\ttype = await select({\n\t\t\t\t\t\t\tmessage: \"Template type:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"node — Node.js library or tool\", value: \"node\" },\n\t\t\t\t\t\t\t\t{ name: \"cli — CLI application (inquirer, chalk, yargs)\", value: \"cli\" },\n\t\t\t\t\t\t\t\t{ name: \"monorepo — Turbo monorepo\", value: \"monorepo\" },\n\t\t\t\t\t\t\t\t{ name: \"react — React component library\", value: \"react\" },\n\t\t\t\t\t\t\t\t{ name: \"nextjs — Next.js application\", value: \"nextjs\" },\n\t\t\t\t\t\t\t\t{ name: \"base — Minimal repo (no package.json)\", value: \"base\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!name) {\n\t\t\t\t\t\tname = await input({\n\t\t\t\t\t\t\tmessage: \"Repo name (kebab-case):\",\n\t\t\t\t\t\t\tvalidate: validateRepoName,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tname = name.trim();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (description === undefined) {\n\t\t\t\t\t\tdescription = await input({ message: \"Short description:\" });\n\t\t\t\t\t}\n\n\t\t\t\t\tif (homepage === undefined) {\n\t\t\t\t\t\tconst raw = await input({ message: \"Homepage URL (optional, Enter to skip):\" });\n\t\t\t\t\t\thomepage = raw.trim() || undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!runtimeEnvironment) {\n\t\t\t\t\t\truntimeEnvironment = await select({\n\t\t\t\t\t\t\tmessage: \"Runtime environment:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"node — Node.js process\", value: \"node\" },\n\t\t\t\t\t\t\t\t{ name: \"browser — Browser only\", value: \"browser\" },\n\t\t\t\t\t\t\t\t{ name: \"universal — Node.js + browser\", value: \"universal\" },\n\t\t\t\t\t\t\t\t{ name: \"none — No runtime (docs, config, etc.)\", value: \"none\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdefault: type === \"base\" ? \"none\" : \"node\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!vaultProvider) {\n\t\t\t\t\t\tvaultProvider = await select({\n\t\t\t\t\t\t\tmessage: \"Vault provider:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"None\", value: \"none\" },\n\t\t\t\t\t\t\t\t{ name: \"Doppler\", value: \"doppler\" },\n\t\t\t\t\t\t\t\t{ name: \"1Password\", value: \"1password\" },\n\t\t\t\t\t\t\t\t{ name: \"Infisical\", value: \"infisical\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (vaultProvider === \"doppler\") {\n\t\t\t\t\t\tvaultProject = await input({ message: \"Doppler project name:\", default: name });\n\t\t\t\t\t\tvaultConfig = await input({ message: \"Doppler config:\", default: \"dev\" });\n\t\t\t\t\t} else if (vaultProvider === \"1password\" || vaultProvider === \"infisical\") {\n\t\t\t\t\t\tvaultProject = await input({\n\t\t\t\t\t\t\tmessage: `${vaultProvider === \"1password\" ? \"1Password vault\" : \"Infisical project\"} name:`,\n\t\t\t\t\t\t\tdefault: name,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!deploymentProvider) {\n\t\t\t\t\t\tdeploymentProvider = await select({\n\t\t\t\t\t\t\tmessage: \"Deployment provider:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"None\", value: \"none\" },\n\t\t\t\t\t\t\t\t{ name: \"Vercel\", value: \"vercel\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!agent) {\n\t\t\t\t\t\tagent = await select({\n\t\t\t\t\t\t\tmessage: \"AI agent:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"Claude\", value: \"claude\" },\n\t\t\t\t\t\t\t\t{ name: \"None\", value: \"none\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (topics.length === 0) {\n\t\t\t\t\t\tconst raw = await input({ message: \"Topics (comma-separated, optional):\" });\n\t\t\t\t\t\ttopics = parseTopics(raw);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!protection) {\n\t\t\t\t\t\tprotection = await select({\n\t\t\t\t\t\t\tmessage: \"Branch protection:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"strict — required reviews + passing checks\", value: \"strict\" },\n\t\t\t\t\t\t\t\t{ name: \"balanced — required reviews, flexible checks\", value: \"balanced\" },\n\t\t\t\t\t\t\t\t{ name: \"minimal — branch protection only\", value: \"minimal\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (openSource === undefined) {\n\t\t\t\t\t\tconst ans = await select({\n\t\t\t\t\t\t\tmessage: \"Open source?\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"Yes\", value: \"yes\" },\n\t\t\t\t\t\t\t\t{ name: \"No\", value: \"no\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t\topenSource = ans === \"yes\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif (usesExternalPackages === undefined) {\n\t\t\t\t\t\tconst ans = await select({\n\t\t\t\t\t\t\tmessage: \"Uses external APIs or services?\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"Yes\", value: \"yes\" },\n\t\t\t\t\t\t\t\t{ name: \"No\", value: \"no\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t\tusesExternalPackages = ans === \"yes\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif (skills.length === 0) {\n\t\t\t\t\t\tconst raw = await input({ message: \"Agent skills (comma-separated, optional):\" });\n\t\t\t\t\t\tskills = parseTopics(raw);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!type) {\n\t\t\t\t\t\tconsole.error(\"new: template type is required\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!name) {\n\t\t\t\t\t\tconsole.error(\"new: repo name is required\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst report = await runNew({\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: description || undefined,\n\t\t\t\t\t\thomepage,\n\t\t\t\t\t\tvaultProvider: (vaultProvider as \"doppler\" | \"1password\" | \"infisical\" | \"none\") ?? \"none\",\n\t\t\t\t\t\tvaultProject,\n\t\t\t\t\t\tvaultConfig,\n\t\t\t\t\t\tdeploymentProvider: (deploymentProvider as \"vercel\" | \"none\") ?? \"none\",\n\t\t\t\t\t\tagent: (agent as \"claude\" | \"none\") ?? \"claude\",\n\t\t\t\t\t\truntimeEnvironment: (runtimeEnvironment as \"node\" | \"browser\" | \"universal\" | \"none\") ?? \"node\",\n\t\t\t\t\t\tprotection: protection ?? \"strict\",\n\t\t\t\t\t\topenSource: openSource ?? true,\n\t\t\t\t\t\tusesExternalPackages: usesExternalPackages ?? true,\n\t\t\t\t\t\ttopics,\n\t\t\t\t\t\tskills,\n\t\t\t\t\t\tisTemplate,\n\t\t\t\t\t\torg: argv.org,\n\t\t\t\t\t\ttoken: adminToken,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\tnoVerify: !argv.verify,\n\t\t\t\t\t\tcwd: argv.cwd,\n\t\t\t\t\t});\n\t\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof NewError) {\n\t\t\t\t\t\tconsole.error(`new: ${err.message}`);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"plugin create <slug> <vendor>\",\n\t\t\t\"Scaffold a new @theholocron/holocron-plugin-<slug> package\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"slug\", { type: \"string\", demandOption: true, describe: \"Package slug (kebab-case)\" })\n\t\t\t\t\t.positional(\"vendor\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Vendor display name (PascalCase)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"capability\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Capability key: source|ci|secrets|environments|issues|deployment|storage|auth|vault|dns|tooling|notifications|analytics|observability\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"token-env\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Holocron env var name (defaults to HOLOCRON_<VENDOR>_TOKEN)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"vendor-env\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Vendor-native env var name\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"base-url\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"REST base URL\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"verify\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdefault: true,\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Run post-scaffold pnpm install + typecheck + lint + test (default true; --no-verify skips)\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst vendor = argv.vendor as string;\n\t\t\t\t\tconst { capability, vendorEnv, baseUrl } = await resolvePluginCreateInputs(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcapability: argv.capability as string | undefined,\n\t\t\t\t\t\t\tvendorEnv: argv.vendorEnv as string | undefined,\n\t\t\t\t\t\t\tbaseUrl: argv.baseUrl as string | undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tselectCapability: () =>\n\t\t\t\t\t\t\t\tselect({\n\t\t\t\t\t\t\t\t\tmessage: \"Capability:\",\n\t\t\t\t\t\t\t\t\tchoices: Object.keys(CARDINALITY).map((k) => ({ name: k, value: k })),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tinputVendorEnv: () =>\n\t\t\t\t\t\t\t\tinput({\n\t\t\t\t\t\t\t\t\tmessage: `Vendor-native env var for the ${vendor} token (e.g. MYVENDOR_API_KEY):`,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tinputBaseUrl: () =>\n\t\t\t\t\t\t\t\tinput({\n\t\t\t\t\t\t\t\t\tmessage: `REST base URL for the ${vendor} API (e.g. https://api.myvendor.com):`,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\t\tconst report = runPluginCreate({\n\t\t\t\t\t\tslug: argv.slug as string,\n\t\t\t\t\t\tvendorName: vendor,\n\t\t\t\t\t\tcapability,\n\t\t\t\t\t\tvendorEnv,\n\t\t\t\t\t\tbaseUrl,\n\t\t\t\t\t\t...(argv.tokenEnv ? { tokenEnv: argv.tokenEnv as string } : {}),\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t// Yargs: `--no-verify` flips `argv.verify` to false. We pass\n\t\t\t\t\t\t// the inverse to preserve the internal `noVerify` naming.\n\t\t\t\t\t\tnoVerify: !argv.verify,\n\t\t\t\t\t\tcwd: argv.cwd,\n\t\t\t\t\t});\n\t\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof PluginCreateError) {\n\t\t\t\t\t\tconsole.error(`plugin create: ${err.message}`);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"upgrade\",\n\t\t\t\"Upgrade toolchain version pins across the repo\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"node <to>\",\n\t\t\t\t\t\t\"Scan the repo and update every Node.js version pin to a new major\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy\n\t\t\t\t\t\t\t\t.positional(\"to\", {\n\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\t\t\t\tdescribe: \"Target Node.js major version (e.g., 22)\",\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.option(\"from\", {\n\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\t\t\t\"Current major version to replace. Auto-detected from .nvmrc / engines.node when omitted.\",\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\t// Read upgrade.node.extra from holocron.config.json if present.\n\t\t\t\t\t\t\t// We read the raw file directly rather than through loadConfig because\n\t\t\t\t\t\t\t// the upgrade config is not part of the plugin schema.\n\t\t\t\t\t\t\tlet extra: string[] = [];\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst raw = readFileSync(join(argv.cwd, \"holocron.config.json\"), \"utf8\");\n\t\t\t\t\t\t\t\tconst cfg = JSON.parse(raw) as Record<string, unknown>;\n\t\t\t\t\t\t\t\tconst upgradeNode = (cfg.upgrade as Record<string, unknown> | undefined)?.node as\n\t\t\t\t\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\t\t\tif (Array.isArray(upgradeNode?.extra)) {\n\t\t\t\t\t\t\t\t\textra = upgradeNode.extra as string[];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t/* no config or no upgrade section — fine */\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst report = await runUpgradeNode({\n\t\t\t\t\t\t\t\tto: argv.to as number,\n\t\t\t\t\t\t\t\t...(argv.from != null ? { from: argv.from as number } : {}),\n\t\t\t\t\t\t\t\tcwd: argv.cwd,\n\t\t\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t\t\textra,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\t\t\t\tif (report.message) console.error(`upgrade node: ${report.message}`);\n\t\t\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.demandCommand(1, \"Run `holocron upgrade --help` to see available upgrade subcommands.\"),\n\t\t\t() => {}\n\t\t)\n\t\t.command(\n\t\t\t\"auth <subcommand>\",\n\t\t\t\"Manage bootstrap credentials in the OS keyring\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"set <provider> [value]\",\n\t\t\t\t\t\t\"Verify + store a bootstrap token for a provider\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy\n\t\t\t\t\t\t\t\t.positional(\"provider\", { type: \"string\", demandOption: true })\n\t\t\t\t\t\t\t\t.positional(\"value\", { type: \"string\" }),\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\tconst result = await runAuthSet({\n\t\t\t\t\t\t\t\tprovider: argv.provider as string,\n\t\t\t\t\t\t\t\t...(argv.value ? { positional: argv.value as string } : {}),\n\t\t\t\t\t\t\t\t...(argv.org ? { org: argv.org as string } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (result.status === \"fail\") process.exitCode = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"unset <provider>\",\n\t\t\t\t\t\t\"Remove a stored bootstrap token\",\n\t\t\t\t\t\t(yy) => yy.positional(\"provider\", { type: \"string\", demandOption: true }),\n\t\t\t\t\t\t(argv) => {\n\t\t\t\t\t\t\trunAuthUnset({ provider: argv.provider as string });\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"check <provider>\",\n\t\t\t\t\t\t\"Re-verify a stored bootstrap token\",\n\t\t\t\t\t\t(yy) => yy.positional(\"provider\", { type: \"string\", demandOption: true }),\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\tconst result = await runAuthCheck({\n\t\t\t\t\t\t\t\tprovider: argv.provider as string,\n\t\t\t\t\t\t\t\t...(argv.org ? { org: argv.org as string } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (result.status === \"fail\") process.exitCode = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"list\",\n\t\t\t\t\t\t\"List every provider with a stored bootstrap token\",\n\t\t\t\t\t\t() => {},\n\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\tawait runAuthList();\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.demandCommand(1, \"Run `holocron auth --help` to see available auth subcommands.\"),\n\t\t\t() => {}\n\t\t)\n\t\t.demandCommand(1, \"Run `holocron --help` to see available commands.\")\n\t\t.strict()\n\t\t.help()\n\t\t.parse();\n} catch (err) {\n\tcaptureException(err);\n\tif (!process.exitCode) process.exitCode = 1;\n}\n\nfinishCommand(!process.exitCode);\nendSession();\nconst notify = await updateCheckPromise;\nnotify?.();\nawait flush();\n\n/**\n * Parse `--scope` strings: `repo` | `env=NAME` | `org=NAME`.\n */\nfunction parseScope(\n\ts: string\n): { kind: \"repo\" } | { kind: \"environment\"; name: string } | { kind: \"organization\"; name: string } {\n\tif (s === \"repo\") return { kind: \"repo\" };\n\tif (s.startsWith(\"env=\")) return { kind: \"environment\", name: s.slice(\"env=\".length) };\n\tif (s.startsWith(\"org=\")) return { kind: \"organization\", name: s.slice(\"org=\".length) };\n\tthrow new Error(`invalid --scope \"${s}\" — expected \"repo\", \"env=<name>\", or \"org=<name>\"`);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":["getKeyringToken","defaultImporter","SKIP_DIRS","defaultWalkFiles","preflight","defaultExec","defaultExec","printNextSteps","deriveDefaults","render","render","render","render","render","render","render","render","render","render","render","render","render","render","render","render","render","renderPackageJson","renderTsconfigJson","renderVitestConfig","renderEslintConfig","renderTsdownConfig","renderReadme","renderAuth","renderRest","renderVerifyToken","renderPluginIndex","renderCapability","renderHelpers","renderAuthTest","renderRestTest","renderVerifyTokenTest","renderCapabilityTest","renderIndexTest","renderValidateScript","deriveDefaults","defaultExec","lintYml","testYml","typecheckYml","codeqlYml","reviewYml","postReleaseYml","releaseYml","staleYml","syncYml","greetingsYml","dependenciesYml","bookkeepingYml","auditYml","deployYml","ProviderApiError","DEPENDABOT_CONFIG","autoCommitAction","installAction","setupAction","setupNodeAction","auditWorkflow","bookkeepingWorkflow","codeqlWorkflow","dependenciesWorkflow","deployWorkflow","cleanupPreviewWorkflow","deployPreviewWorkflow","greetingsWorkflow","lintWorkflow","postReleaseWorkflow","releaseWorkflow","reviewWorkflow","staleWorkflow","syncBroadcastWorkflow","tagWorkflow","syncGithubWorkflow","syncWorkflow","testWorkflow","typecheckWorkflow"],"sources":["../src/env.ts","../src/keyring.ts","../src/auth-resolver.ts","../src/capabilities/index.ts","../src/config.ts","../src/ui/progress.ts","../src/ui/style.ts","../src/commands/auth.ts","../src/loader.ts","../src/commands/cleanup-preview.ts","../src/commands/clone.ts","../src/commands/deploy.ts","../src/commands/doctor.ts","../src/commands/new.ts","../src/commands/npm-bump-versions.ts","../src/commands/npm-publish-initial.ts","../src/commands/plugin-create/template-inputs.ts","../src/commands/plugin-create/templates/auth.ts","../src/commands/plugin-create/templates/auth-test.ts","../src/commands/plugin-create/templates/capability.ts","../src/commands/plugin-create/templates/capability-test.ts","../src/commands/plugin-create/templates/eslint-config.ts","../src/commands/plugin-create/templates/helpers.ts","../src/commands/plugin-create/templates/index-test.ts","../src/commands/plugin-create/templates/package-json.ts","../src/commands/plugin-create/templates/plugin-index.ts","../src/commands/plugin-create/templates/readme.ts","../src/commands/plugin-create/templates/rest.ts","../src/commands/plugin-create/templates/rest-test.ts","../src/commands/plugin-create/templates/tsconfig-json.ts","../src/commands/plugin-create/templates/tsdown-config.ts","../src/commands/plugin-create/templates/validate-script.ts","../src/commands/plugin-create/templates/verify-token.ts","../src/commands/plugin-create/templates/verify-token-test.ts","../src/commands/plugin-create/templates/vitest-config.ts","../src/commands/plugin-create/index.ts","../src/commands/secret-set.ts","../src/commands/secrets-sync.ts","../src/commands/dependabot.yml","../src/commands/workflows/audit.yml","../src/commands/workflows/bookkeeping.yml","../src/commands/workflows/codeql.yml","../src/commands/workflows/dependencies.yml","../src/commands/workflows/deploy.yml","../src/commands/workflows/greetings.yml","../src/commands/workflows/lint.yml","../src/commands/workflows/post-release.yml","../src/commands/workflows/release.yml","../src/commands/workflows/review.yml","../src/commands/workflows/stale.yml","../src/commands/workflows/sync.yml","../src/commands/workflows/test.yml","../src/commands/workflows/typecheck.yml","../src/commands/setup-workflows.ts","../src/commands/setup.ts","../src/commands/skills.ts","../src/commands/sync-readme.ts","../src/commands/sync.ts","../src/templates/actions/auto-commit.yml","../src/templates/actions/install.yml","../src/templates/actions/setup.yml","../src/templates/actions/setup-node.yml","../src/templates/workflows/audit.yml","../src/templates/workflows/bookkeeping.yml","../src/templates/workflows/cleanup-preview.yml","../src/templates/workflows/codeql.yml","../src/templates/workflows/dependencies.yml","../src/templates/workflows/deploy.yml","../src/templates/workflows/deploy-preview.yml","../src/templates/workflows/greetings.yml","../src/templates/workflows/lint.yml","../src/templates/workflows/post-release.yml","../src/templates/workflows/release.yml","../src/templates/workflows/review.yml","../src/templates/workflows/stale.yml","../src/templates/workflows/sync.yml","../src/templates/workflows/sync-broadcast.yml","../src/templates/workflows/sync-github.yml","../src/templates/workflows/tag.yml","../src/templates/workflows/test.yml","../src/templates/workflows/typecheck.yml","../src/templates/index.ts","../src/commands/sync-github.ts","../src/commands/upgrade-node.ts","../src/load-config.ts","../src/telemetry.ts","../src/token-args.ts","../src/update-notifier.ts","../src/cli.ts"],"sourcesContent":["export interface EnvLookup {\n\tget(key: string): string | undefined;\n\tfirst(...keys: string[]): string | undefined;\n}\n\nexport function createEnvLookup(source: NodeJS.ProcessEnv = process.env): EnvLookup {\n\treturn {\n\t\tget(key: string): string | undefined {\n\t\t\treturn source[key] || undefined;\n\t\t},\n\t\tfirst(...keys: string[]): string | undefined {\n\t\t\tfor (const key of keys) {\n\t\t\t\tconst val = source[key];\n\t\t\t\tif (val) return val;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n","/**\n * Keyring-backed bootstrap credential store.\n *\n * Every holocron plugin's bootstrap token (the one it needs before it\n * can talk to its vendor's API) can be stored in the OS keyring under\n * a single reverse-DNS service scope. Managed via `holocron auth`\n * subcommands; consulted at position 4 in every plugin's auth\n * precedence chain (after --token / HOLOCRON_<X>_TOKEN / <native>_TOKEN).\n *\n * See `.notes/tech-auth-bootstrap.spec.md` for the design rationale.\n *\n * Failure model: keyring access is best-effort. Platforms without a\n * supported credential store (some Linux CI images, sandboxed\n * environments) will throw from the underlying library. Every export\n * here catches and returns a null/empty result rather than propagating\n * — the plugin's precedence chain then falls through to\n * env-var-only paths, which is exactly how CI is meant to work.\n */\n\nimport { Entry, findCredentials } from \"@napi-rs/keyring\";\n\nconst SERVICE = \"com.theholocron.cli\";\n\n/**\n * Store or overwrite a bootstrap token for a provider. Returns true on\n * success, false when the underlying keyring is unsupported or errored.\n */\nexport function setToken(provider: string, token: string): boolean {\n\ttry {\n\t\tnew Entry(SERVICE, provider).setPassword(token);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Read the bootstrap token for a provider. Returns `null` for both\n * \"not stored\" and \"keyring unavailable\" — callers can treat them the\n * same way (fall through to env-var precedence).\n */\nexport function getToken(provider: string): string | null {\n\ttry {\n\t\treturn new Entry(SERVICE, provider).getPassword();\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Delete a stored token. Returns true when a token was removed, false\n * when there was nothing to delete or the keyring is unavailable.\n * Distinguishing the two cases isn't worth the surface area — the\n * command output makes the situation clear either way.\n */\nexport function deleteToken(provider: string): boolean {\n\ttry {\n\t\treturn new Entry(SERVICE, provider).deletePassword();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * List provider slugs with a stored token in this service scope.\n * Uses the library's `findCredentials(service)` — supported on all\n * platforms the underlying credential store supports.\n */\nexport function listStoredProviders(): string[] {\n\ttry {\n\t\treturn findCredentials(SERVICE).map((c) => c.account);\n\t} catch {\n\t\treturn [];\n\t}\n}\n","// Re-exported from @theholocron/http — the canonical home for HTTP primitives.\n// createResolveToken is wrapped here to inject the keyring backend so plugins\n// don't need to pass it explicitly.\nimport {\n\tAuthError,\n\tcreateResolveToken as _createResolveToken,\n\ttype ResolveTokenConfig as _ResolveTokenConfig,\n\ttype ResolveTokenInput,\n} from \"@theholocron/http-client\";\n\nimport { createEnvLookup } from \"./env.js\";\nimport { getToken as getKeyringToken } from \"./keyring.js\";\n\nexport { AuthError, type ResolveTokenInput };\n\nexport type ResolveTokenConfig = Omit<_ResolveTokenConfig, \"getKeyringToken\">;\n\n/** Wraps `createResolveToken` from `@theholocron/http` and injects the\n * system keyring so plugins stay at a one-liner call site. */\nexport function createResolveToken(config: ResolveTokenConfig): (input?: ResolveTokenInput) => string {\n\treturn _createResolveToken({ ...config, getKeyringToken });\n}\n\nexport interface FeatureResolverConfig {\n\t/** Env var name for this feature, e.g. `\"HOLOCRON_ISSUES_TOKEN\"`. */\n\tenvName: string;\n\t/** Keyring account key, e.g. `\"github.issues\"`. */\n\tkeyringKey: string;\n}\n\n/**\n * Build a strict, single-feature token resolver.\n *\n * Resolution chain: `--token flag → envName env var → keyring(keyringKey)`.\n * No broad-token fallback — if the feature-specific token is absent the\n * operation fails with a message naming the exact env var to set.\n */\nexport function createFeatureResolver(config: FeatureResolverConfig): (input?: ResolveTokenInput) => string {\n\treturn function resolveFeatureToken(input: ResolveTokenInput = {}): string {\n\t\tconst env = createEnvLookup(input.env);\n\t\tconst keyring = input.keyring ?? getKeyringToken;\n\t\tconst token = input.cliToken || env.get(config.envName) || keyring(config.keyringKey);\n\t\tif (!token) {\n\t\t\tthrow new AuthError(\n\t\t\t\t`no GitHub token found for this operation. Pass --token <PAT>, ` +\n\t\t\t\t\t`set ${config.envName}, or run: holocron auth set ${config.keyringKey} <PAT>`\n\t\t\t);\n\t\t}\n\t\treturn token;\n\t};\n}\n","/**\n * Capability interfaces — the contracts that providers implement.\n *\n * Each capability has a stable key (`'source'`, `'ci'`, …) and a\n * cardinality (`'single'` = one provider; `'many'` = several active\n * at once). The cardinality is part of the type contract via\n * `CardinalityFor<K>` so config resolution + command code can branch\n * statically.\n *\n * See `.notes/tech-architecture.spec.md` for the design narrative\n * (status: proposed, issue: #74).\n */\n\nexport type CapabilityKey =\n\t| \"source\"\n\t| \"ci\"\n\t| \"secrets\"\n\t| \"environments\"\n\t| \"issues\"\n\t| \"deployment\"\n\t| \"storage\"\n\t| \"auth\"\n\t| \"vault\"\n\t| \"dns\"\n\t| \"tooling\"\n\t| \"notifications\"\n\t| \"analytics\"\n\t| \"observability\";\n\nexport type Cardinality = \"single\" | \"many\";\n\nexport const CARDINALITY = {\n\tsource: \"single\",\n\tci: \"single\",\n\tsecrets: \"single\",\n\tenvironments: \"single\",\n\tissues: \"single\",\n\tdeployment: \"single\",\n\tstorage: \"single\",\n\tauth: \"single\",\n\tvault: \"single\",\n\tdns: \"single\",\n\ttooling: \"many\",\n\tnotifications: \"many\",\n\tanalytics: \"many\",\n\tobservability: \"many\",\n} as const satisfies Record<CapabilityKey, Cardinality>;\n\n/**\n * No capabilities are strictly required — repos without secrets (e.g. org\n * community health repos) legitimately omit vault. Plugins validate their\n * own requirements at call time.\n */\nexport const REQUIRED_CAPABILITIES: readonly CapabilityKey[] = [] as const;\n\n// ───────────────────────────────────────────────────────────────────────\n// Common shapes\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface ProviderIdentity {\n\treadonly key: CapabilityKey;\n\treadonly providerName: string;\n}\n\nexport { ProviderApiError } from \"@theholocron/http-client\";\n\n// ───────────────────────────────────────────────────────────────────────\n// source — repos, branches, PRs, rulesets, settings, workflow files\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface Ruleset {\n\tid: number;\n\tname: string;\n\tenforcement: \"active\" | \"evaluate\" | \"disabled\";\n\ttarget?: string;\n}\n\nexport interface RepoSettings {\n\tallow_squash_merge?: boolean;\n\tallow_merge_commit?: boolean;\n\tallow_rebase_merge?: boolean;\n\tallow_auto_merge?: boolean;\n\t/** Always suggest updating PR branches when the base branch has new commits. */\n\tallow_update_branch?: boolean;\n\tdelete_branch_on_merge?: boolean;\n\tdefault_branch?: string;\n\thas_issues?: boolean;\n\thas_discussions?: boolean;\n\thas_projects?: boolean;\n\thas_wiki?: boolean;\n}\n\nexport interface RepoRef {\n\towner: string;\n\tname: string;\n\tdefaultBranch: string;\n}\n\nexport interface LabelDef {\n\treadonly name: string;\n\treadonly color: string;\n\treadonly description: string;\n}\n\nexport type TeamPermission = \"pull\" | \"triage\" | \"push\" | \"maintain\" | \"admin\";\n\n/** Shorthand `\"slug\"` defaults to `push` permission. */\nexport type TeamEntry = string | { slug: string; permission: TeamPermission };\n\nexport interface Source extends ProviderIdentity {\n\treadonly key: \"source\";\n\n\t/** Auth sanity-check. Throws ProviderApiError on auth failure. */\n\twhoami(): Promise<{ login: string }>;\n\n\tgetRepo(): Promise<RepoRef>;\n\n\t// Rulesets / branch protection\n\tlistRulesets(): Promise<Ruleset[]>;\n\tcreateRuleset(payload: Record<string, unknown>): Promise<Ruleset>;\n\tupdateRuleset(id: number, payload: Record<string, unknown>): Promise<Ruleset>;\n\n\t// Repo settings\n\tupdateRepoSettings(settings: RepoSettings): Promise<void>;\n\n\t/**\n\t * Classic branch protection — fallback for private repos on free plans\n\t * where the Rulesets API (requires Team+) returns 403.\n\t */\n\tprotectBranch(branch: string, payload: Record<string, unknown>): Promise<void>;\n\n\t// Security toggles (idempotent; flip-or-noop)\n\tenableVulnerabilityAlerts(): Promise<void>;\n\tenableAutomatedSecurityFixes(): Promise<void>;\n\tenableSecretScanning(): Promise<void>;\n\tenablePrivateVulnerabilityReporting(): Promise<void>;\n\t/**\n\t * Enables the dependency graph and automatic dependency snapshot\n\t * submission. Also enables secret-scanning validity checks and\n\t * non-provider pattern detection — these require GitHub Advanced\n\t * Security at the org level; the call is accepted but may be a no-op\n\t * until that is configured.\n\t */\n\tenableDependencyGraph(): Promise<void>;\n\n\t/**\n\t * Enables CodeQL default setup with the extended query suite and\n\t * `threat_model: all` (scans both remote and local exploit paths).\n\t * Triggers a new analysis run; returns the run id.\n\t */\n\tenableCodeScanning(): Promise<string>;\n\n\t/**\n\t * Disables CodeQL default setup. Required when the repo uses an advanced\n\t * CodeQL workflow instead — GitHub rejects SARIF from advanced workflows\n\t * while default setup is active.\n\t */\n\tdisableDefaultCodeScanning(): Promise<void>;\n\n\t// Workflow files — local YAML files in `.github/workflows/` (or\n\t// equivalent). These are conceptually repo content; providers may\n\t// throw `NotImplementedError` if the underlying VCS has no notion\n\t// of declarative CI files.\n\tlistWorkflowFiles(): Promise<string[]>;\n\treadWorkflowFile(name: string): Promise<string | null>;\n\twriteWorkflowFile(name: string, contents: string): Promise<void>;\n\tremoveWorkflowFile(name: string): Promise<void>;\n\n\t/**\n\t * Write an arbitrary file relative to the repo root. Used for\n\t * provisioning config files that live outside `.github/workflows/`\n\t * (e.g. `.github/dependabot.yml`).\n\t */\n\twriteRepoFile(path: string, contents: string): Promise<void>;\n\n\t/**\n\t * Idempotently sync repo labels to a canonical set. Creates missing\n\t * labels, patches color/description drift, deletes stale labels.\n\t * Optional — providers that have no label concept omit this.\n\t */\n\tsyncLabels?(canonical: ReadonlyArray<LabelDef>, stale: ReadonlyArray<string>): Promise<string>;\n\n\t/**\n\t * Set org-level custom property values on the repo.\n\t * Optional — providers that don't support custom properties omit this.\n\t */\n\tsyncProperties?(values: Record<string, string>): Promise<string>;\n\n\t/**\n\t * Replace the repo's topic set with the supplied list.\n\t * Optional — providers that don't support topics omit this.\n\t */\n\tsyncTopics?(topics: string[]): Promise<string>;\n\n\t/**\n\t * Sync GitHub team repository access. String shorthand defaults to `push`.\n\t * Optional — providers without a team concept omit this.\n\t */\n\tsyncTeams?(teams: TeamEntry[]): Promise<string>;\n\n\t/**\n\t * Set the repository description.\n\t * Optional — providers that don't support setting descriptions omit this.\n\t */\n\tsyncDescription?(description: string): Promise<string>;\n\n\t/**\n\t * Set the repository homepage URL (the \"Website\" field on the repo landing page).\n\t * Optional — providers that don't support setting a homepage omit this.\n\t */\n\tsyncHomepage?(homepage: string): Promise<string>;\n\n\t/**\n\t * Fetch a pull request by number. The `repo` override lets callers look up\n\t * a PR in a different repo than the one the plugin is scoped to — useful\n\t * when the cleanup command targets another repo's PR (e.g. docs PR from\n\t * the holocron repo context).\n\t * Optional — providers without a PR concept omit this.\n\t */\n\tgetPullRequest?(number: number, repo?: string): Promise<PullRequest>;\n\n\t/**\n\t * Enable or update GitHub Pages for the repository.\n\t * Idempotent: POST to create, PUT to update existing settings.\n\t * Requires HOLOCRON_DEPLOY_TOKEN (pages:write + repo scope) — passed\n\t * explicitly because it is a different PAT from the main admin token.\n\t * Optional — providers without a Pages concept omit this.\n\t */\n\tconfigurePages?(config: PagesConfig, token: string): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Pages\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface PagesConfig {\n\t/** GitHub Pages build source. */\n\tbuild: \"workflow\" | \"branch\";\n\t/**\n\t * Custom domain / CNAME (e.g. \"docs.theholocron.dev\").\n\t * When set and `homepage` is absent in holocron.config, setup derives\n\t * homepage as `https://{domain}/`.\n\t */\n\tdomain?: string;\n\t/** Enforce HTTPS. Only effective once the custom domain is DNS-verified. */\n\thttps?: boolean;\n}\n\nexport interface PullRequest {\n\tnumber: number;\n\ttitle: string;\n\t/** \"open\" | \"closed\" — GitHub marks merged PRs as \"closed\". */\n\tstate: \"open\" | \"closed\";\n\t/** True when the PR was merged (as opposed to closed without merging). */\n\tmerged: boolean;\n\t/** The head branch name (e.g. \"fix/my-change\"). */\n\tbranch: string;\n\turl: string;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// ci — workflow runs (history + status only)\n// ───────────────────────────────────────────────────────────────────────\n\nexport type CiRunStatus = \"queued\" | \"in_progress\" | \"completed\" | \"cancelled\" | \"failure\" | \"success\" | \"skipped\";\n\nexport interface CiRun {\n\tid: string | number;\n\tworkflowName: string;\n\tbranch: string;\n\tsha: string;\n\tstatus: CiRunStatus;\n\turl: string;\n\tstartedAt: string;\n\tcompletedAt?: string;\n}\n\nexport interface CiRunFilter {\n\tbranch?: string;\n\tstatus?: CiRunStatus;\n\tlimit?: number;\n}\n\nexport interface Ci extends ProviderIdentity {\n\treadonly key: \"ci\";\n\tlistRuns(filter?: CiRunFilter): Promise<CiRun[]>;\n\tgetRun(id: string | number): Promise<CiRun>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// secrets — CI/platform secrets sync destination (multi-scope)\n// ───────────────────────────────────────────────────────────────────────\n\nexport type SecretScope =\n\t| { kind: \"repo\" }\n\t| { kind: \"environment\"; name: string }\n\t| { kind: \"organization\"; name: string };\n\nexport interface Secrets extends ProviderIdentity {\n\treadonly key: \"secrets\";\n\n\t/** List secret NAMES (not values) at the given scope. */\n\tlistSecrets(scope: SecretScope): Promise<string[]>;\n\n\t/** Idempotent upsert. Adapter handles encryption. */\n\tsetSecret(scope: SecretScope, name: string, value: string): Promise<void>;\n\n\tdeleteSecret(scope: SecretScope, name: string): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// environments — named deployment environments\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface EnvironmentReviewer {\n\ttype: \"User\" | \"Team\";\n\t/** Numeric id — GitHub's reviewer API silently ignores login strings. */\n\tid: number;\n}\n\nexport interface Environment {\n\tname: string;\n\treviewers?: EnvironmentReviewer[];\n\twaitTimer?: number;\n\tpreventSelfReview?: boolean;\n}\n\nexport interface Environments extends ProviderIdentity {\n\treadonly key: \"environments\";\n\tlistEnvironments(): Promise<Environment[]>;\n\tupsertEnvironment(env: Environment): Promise<void>;\n\tdeleteEnvironment(name: string): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// issues — tracker\n// ───────────────────────────────────────────────────────────────────────\n\nexport type LifecycleSlot = \"inProgress\" | \"inReview\" | \"done\";\n\nexport type StatusCategory = \"open\" | \"in-progress\" | \"in-review\" | \"done\" | \"other\";\n\nexport interface TrackerUser {\n\tid: string;\n\tdisplayName: string;\n\temailAddress?: string;\n}\n\nexport interface Issue {\n\t/** Human-readable key — \"#42\" for GitHub, \"RANDO-42\" for Jira. */\n\tkey: string;\n\t/** Internal opaque id. */\n\tid: string;\n\tsummary: string;\n\tbody?: string;\n\tstatus: string;\n\tstatusCategory: StatusCategory;\n\tassignee: TrackerUser | null;\n\tupdated: string;\n\turl?: string;\n}\n\nexport interface IssueSearchFilter {\n\t/** Restrict to issues assigned to a specific id, or 'currentUser'. */\n\tassignee?: string | \"currentUser\";\n\t/** Exclude issues in the `done` category. */\n\topenOnly?: boolean;\n\t/** Max number of issues to return. Adapters apply a sensible default. */\n\tlimit?: number;\n}\n\nexport interface LifecycleResult {\n\t/** False when no API write happened (already at target state). */\n\ttransitioned: boolean;\n\t/** Status name the issue is in after this call. */\n\tstatus: string;\n\t/** Adapter-specific note (e.g., \"label set\" / \"closed (completed)\"). */\n\tvia?: string;\n}\n\nexport interface TrackerDoctorReport {\n\t/** \"Authenticated as ...\" subject for the spinner. */\n\tauthedAs: string;\n\t/** Free-form \"Project: RANDO\" / \"Repo: rando-id/rando\" identifier. */\n\tprojectLabel: string;\n\t/** Status values the adapter exposes. */\n\tstatuses: Array<{ name: string; category: StatusCategory }>;\n\t/**\n\t * Per-lifecycle-slot readiness check. `resolved` indicates whether\n\t * the configured value actually maps to something the tracker\n\t * recognizes; the `note` is the rendered explanation.\n\t */\n\tlifecycle: Array<{\n\t\tslot: LifecycleSlot;\n\t\tvalue: string | null;\n\t\tresolved: boolean;\n\t\tnote: string;\n\t}>;\n}\n\nexport interface Issues extends ProviderIdentity {\n\treadonly key: \"issues\";\n\n\t/** Currently-authenticated user. */\n\tgetMyself(): Promise<TrackerUser>;\n\n\tsearch(filter: IssueSearchFilter): Promise<Issue[]>;\n\tget(key: string): Promise<Issue>;\n\n\tcreate(input: {\n\t\tsummary: string;\n\t\tbody?: string;\n\t\tlabels?: string[];\n\t\t/** Numeric id or exact title (case-insensitive). */\n\t\tmilestone?: string;\n\t}): Promise<{ key: string }>;\n\n\t/** Idempotent — `transitioned: false` if the issue is already at the target. */\n\ttransition(key: string, slot: LifecycleSlot): Promise<LifecycleResult>;\n\n\tcomment(key: string, body: string): Promise<void>;\n\n\tdoctor(): Promise<TrackerDoctorReport>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// deployment — preview/prod deploy targets\n// ───────────────────────────────────────────────────────────────────────\n\n/** Env-var scope on the deploy platform. */\nexport type DeploymentTarget = \"development\" | \"preview\" | \"production\";\n\n/**\n * Named deployment trigger target — `undefined` means a branch\n * preview (no named environment).\n */\nexport type DeploymentTrigger = \"production\" | \"staging\";\n\nexport interface DeploymentProject {\n\tid: string;\n\tname: string;\n\tframework?: string;\n\t/** True when the project is linked to a Git provider. */\n\tgitLinked?: boolean;\n\trootDirectory?: string | null;\n}\n\nexport interface DeploymentProjectSettings {\n\tpreviewDeploymentsDisabled?: boolean;\n\t/** Vercel-specific: whether the GitHub integration creates deployments\n\t * for every push (false → only on-demand triggers). */\n\tgitProviderCreateDeployments?: boolean;\n}\n\nexport interface DeploymentRecord {\n\tid: string;\n\turl: string;\n\t/** Branch this deployment was made from (null if not git-sourced). */\n\tbranch: string | null;\n\t/** Named environment if one was targeted; undefined for branch previews. */\n\ttarget?: DeploymentTrigger;\n\tstatus: \"queued\" | \"building\" | \"ready\" | \"error\" | \"cancelled\";\n\tcreatedAt?: string;\n}\n\nexport interface Deployment extends ProviderIdentity {\n\treadonly key: \"deployment\";\n\n\tlistProjects(): Promise<DeploymentProject[]>;\n\t/** Create if missing, otherwise return existing. Idempotent. */\n\tensureProject(input: {\n\t\tname: string;\n\t\tframework?: string;\n\t\t/** \"owner/repo\" — passed when linking to a Git provider. */\n\t\trepo?: string;\n\t\trootDirectory?: string;\n\t}): Promise<DeploymentProject>;\n\n\tupdateProjectSettings(projectId: string, settings: DeploymentProjectSettings): Promise<DeploymentProject>;\n\n\t// Env vars on the deploy platform (Vercel-style: per-target).\n\tlistEnvVars(projectId: string, target: DeploymentTarget): Promise<string[]>;\n\tsetEnvVar(projectId: string, target: DeploymentTarget, name: string, value: string): Promise<void>;\n\n\t/**\n\t * Kick off a deployment of the given branch. Omit `target` for a\n\t * branch preview; pass `'production'` / `'staging'` to deploy into\n\t * a named environment.\n\t */\n\ttriggerDeployment(input: {\n\t\tprojectId: string;\n\t\tbranch: string;\n\t\ttarget?: DeploymentTrigger;\n\t}): Promise<DeploymentRecord>;\n\n\tgetDeployment(deploymentId: string): Promise<DeploymentRecord>;\n\n\t/**\n\t * List preview deployments for a specific branch alias (e.g. \"repo-pr-42\").\n\t * Optional — providers that don't support listing by branch omit this.\n\t */\n\tlistPreviewDeployments?(projectId: string, branch: string): Promise<DeploymentRecord[]>;\n\n\t/**\n\t * Delete specific preview deployments by id. Returns the count deleted.\n\t * Optional — providers that don't support deletion omit this.\n\t */\n\tdeletePreviewDeployments?(projectId: string, deploymentIds: string[]): Promise<number>;\n\n\t/**\n\t * Add a custom domain (or wildcard) to the project. Idempotent — no-op\n\t * when the domain is already present. Optional: providers without a custom\n\t * domain API omit this (e.g. Vercel manages domains separately).\n\t */\n\tensureCustomDomain?(projectId: string, hostname: string): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// storage — DB / object / file store\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface StorageBranch {\n\tid: string;\n\tname: string;\n\t/** Parent branch id; null for the root/main branch. */\n\tparentId: string | null;\n\tcreatedAt: string;\n}\n\nexport interface ConnectionStringOptions {\n\t/** Use the pooled (PgBouncer) URL when available. Defaults to false. */\n\tpooled?: boolean;\n}\n\nexport interface Storage extends ProviderIdentity {\n\treadonly key: \"storage\";\n\n\t/**\n\t * Connection string for the given scope. Scope is provider-specific:\n\t *\n\t * - branch-based providers (Neon, PlanetScale): scope = branch\n\t * name or id\n\t * - flat providers (single Postgres instance): scope is ignored\n\t *\n\t * Callers (or the orchestrator) decide how a deploy target maps to\n\t * a scope; the storage plugin doesn't own that mapping.\n\t */\n\tgetConnectionString(scope: string, options?: ConnectionStringOptions): Promise<string>;\n\n\t// Branch operations (optional — flat providers can omit).\n\tlistBranches?(): Promise<StorageBranch[]>;\n\tcreateBranch?(input: { name: string; from?: string }): Promise<StorageBranch>;\n\tdestroyBranch?(branch: string): Promise<void>;\n\t/** Restore one branch to match another (e.g., reset preview → main). */\n\tresetBranch?(input: { branch: string; from: string }): Promise<void>;\n\n\t/**\n\t * Provider-specific feature toggle. For Postgres providers this is\n\t * `CREATE EXTENSION IF NOT EXISTS ...` per branch.\n\t */\n\tenableExtension?(input: { branch: string; extension: string }): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// auth — identity provider\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface AuthDescription {\n\tprovider: string;\n\t/** Env-var names the app needs at runtime (CLERK_PUBLISHABLE_KEY, etc.). */\n\tenvKeys: string[];\n}\n\nexport interface AuthIdentity {\n\tprovider: string;\n\t/** Provider-specific health signal (user count, role, account name, etc.). */\n\tdetails?: Record<string, unknown>;\n}\n\nexport interface AuthUser {\n\tid: string;\n\temail: string;\n}\n\nexport interface CreateAuthUserInput {\n\temail: string;\n\tpassword: string;\n\tfirstName?: string;\n\tlastName?: string;\n}\n\nexport interface WebhookDashboardInfo {\n\turl: string;\n}\n\nexport interface Auth extends ProviderIdentity {\n\treadonly key: \"auth\";\n\n\t/** Env-var keys the runtime app needs. */\n\tdescribe(): Promise<AuthDescription>;\n\n\t/** Reachability probe — proves the configured key works. */\n\twhoami(): Promise<AuthIdentity>;\n\n\t// Optional capabilities — providers implement what they support.\n\n\t/** Idempotent webhook backend provisioning (Clerk: Svix app). */\n\tensureWebhookApp?(): Promise<{ alreadyExists: boolean }>;\n\n\t/** Deep-link to the provider's webhook config dashboard. */\n\tgetWebhookDashboardUrl?(): Promise<WebhookDashboardInfo>;\n\n\t/** Seed a user (test fixtures, admin bootstrap). */\n\tcreateUser?(input: CreateAuthUserInput): Promise<AuthUser>;\n\n\t/** Wire the auth provider's webhook into the project's repo. */\n\tsyncWebhook?(input: { repo: string; secretRef: string }): Promise<void>;\n}\n\n// ── Normalized webhook events (cross-provider sync) ──────────────────\n//\n// Plugins implementing `auth` may also expose a `parseWebhook` utility\n// (NOT a capability method — exported alongside the plugin's\n// createPlugin) that translates the vendor's webhook payload into one\n// of these normalized event shapes. Your app's webhook handler then\n// reads the normalized event and is vendor-agnostic:\n//\n// import { parseWebhook } from '@theholocron/holocron-plugin-clerk'\n// import type { AuthEvent } from '@theholocron/cli'\n//\n// app.post('/webhooks/clerk', async (req) => {\n// const event: AuthEvent = await parseWebhook({\n// body: req.body,\n// headers: req.headers,\n// signingSecret: process.env.CLERK_WEBHOOK_SECRET!,\n// })\n// await db.users.upsert(event.user)\n// })\n//\n// Swap clerk for another auth plugin → change one import line; the\n// handler logic stays the same.\n\nexport type AuthEventType = \"user.created\" | \"user.updated\" | \"user.deleted\";\n\nexport interface NormalizedAuthUser {\n\tid: string;\n\temail: string;\n\tfirstName?: string | null;\n\tlastName?: string | null;\n\t/** Provider-native fields preserved verbatim for consumers that need them. */\n\traw?: Record<string, unknown>;\n}\n\nexport interface AuthEvent {\n\ttype: AuthEventType;\n\tuser: NormalizedAuthUser;\n\t/** ISO timestamp of when the event occurred. */\n\toccurredAt: string;\n}\n\nexport interface ParseWebhookInput {\n\t/** Raw request body (string or Buffer). */\n\tbody: string | Buffer;\n\t/** Incoming HTTP headers — needed for signature verification. */\n\theaders: Record<string, string | string[] | undefined>;\n\t/** The signing secret the auth provider issued for this webhook endpoint. */\n\tsigningSecret: string;\n}\n\nexport class WebhookVerificationError extends Error {\n\toverride name = \"WebhookVerificationError\";\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// vault — REQUIRED source-of-truth for secrets\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface EnsureResult {\n\t/** True when the resource already existed (idempotent no-op). */\n\talreadyExists: boolean;\n}\n\nexport interface Vault extends ProviderIdentity {\n\treadonly key: \"vault\";\n\n\t/**\n\t * Read a secret by reference. The reference format is\n\t * provider-specific (1P: \"op://Vault/Item/field\"; HashiCorp Vault:\n\t * \"kv/path#field\"; etc.). Adapters validate the reference shape.\n\t */\n\tread(reference: string): Promise<string>;\n\n\t/** Write or update a secret. */\n\twrite(reference: string, value: string): Promise<void>;\n\n\t/** List secret keys available to the project. */\n\tlist(): Promise<string[]>;\n\n\t/**\n\t * Optional environment notion within the vault (e.g., 1P\n\t * Environments — named KEY=VALUE bundles). Adapters without\n\t * environments return [].\n\t */\n\tenvironments?(): Promise<string[]>;\n\n\t/**\n\t * Optional bulk read of an environment's KEY=VALUE pairs. Powers\n\t * the `holocron secrets sync` flow where the orchestrator pulls a\n\t * whole environment from the vault then fans the values out to\n\t * destinations (CI secrets, deployment env vars, local .env).\n\t */\n\treadEnvironment?(environmentId: string): Promise<Record<string, string>>;\n\n\t/**\n\t * Optional — create the top-level project container in the vault\n\t * if it does not exist. Idempotent: `alreadyExists: true` when the\n\t * project was already there. Providers whose data model has no\n\t * project notion (or that gate this behind a paid tier) omit this.\n\t */\n\tensureProject?(name: string): Promise<EnsureResult>;\n\n\t/**\n\t * Optional — create a named environment/config inside a project\n\t * (e.g., Doppler config `dev` / `stg` / `prd`). Idempotent.\n\t * Providers whose data model has a single flat namespace omit this.\n\t */\n\tensureEnvironment?(project: string, name: string): Promise<EnsureResult>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// dns — DNS record management\n// ───────────────────────────────────────────────────────────────────────\n\nexport type DnsRecordType = \"A\" | \"AAAA\" | \"CNAME\" | \"TXT\" | \"MX\" | \"NS\" | \"SRV\" | \"CAA\";\n\nexport interface DnsRecord {\n\tid?: string;\n\ttype: DnsRecordType;\n\tname: string;\n\tcontent: string;\n\tttl?: number;\n\tpriority?: number;\n}\n\nexport interface Dns extends ProviderIdentity {\n\treadonly key: \"dns\";\n\tlistRecords(domain: string): Promise<DnsRecord[]>;\n\tupsertRecord(domain: string, record: DnsRecord): Promise<DnsRecord>;\n\tdeleteRecord(domain: string, id: string): Promise<void>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Multi-provider capabilities — many can be active at once\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface ToolingDoctorReport {\n\tok: boolean;\n\tmessage: string;\n}\n\nexport interface Tooling extends ProviderIdentity {\n\treadonly key: \"tooling\";\n\n\t/** Sync the tool's authoritative state from the repo. */\n\tsync(): Promise<void>;\n\n\tdoctor(): Promise<ToolingDoctorReport>;\n}\n\nexport interface Notifications extends ProviderIdentity {\n\treadonly key: \"notifications\";\n\n\t/**\n\t * Send a message. `channel` is provider-specific (Slack channel id,\n\t * Discord webhook url-name, etc.); adapters resolve from config.\n\t */\n\tsend(channel: string, message: string): Promise<void>;\n}\n\nexport interface Analytics extends ProviderIdentity {\n\treadonly key: \"analytics\";\n\t/** Returns the env var names the app reads at runtime for this provider. */\n\tdescribe(): Promise<{ provider: string; envKeys: string[] }>;\n\twhoami?(): Promise<{ org: string }>;\n\tensureProject?(name: string): Promise<{ token: string; alreadyExists: boolean }>;\n}\n\nexport interface Observability extends ProviderIdentity {\n\treadonly key: \"observability\";\n\t/** Returns the env var names the app reads at runtime for this provider. */\n\tdescribe(): Promise<{ provider: string; envKeys: string[] }>;\n\twhoami?(): Promise<{ org: string }>;\n\tensureProject?(input: { name: string; platform?: string }): Promise<{ dsn: string; alreadyExists: boolean }>;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Capability map (key → implementation type) + cardinality helpers\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface CapabilityImpls {\n\tsource: Source;\n\tci: Ci;\n\tsecrets: Secrets;\n\tenvironments: Environments;\n\tissues: Issues;\n\tdeployment: Deployment;\n\tstorage: Storage;\n\tauth: Auth;\n\tvault: Vault;\n\tdns: Dns;\n\ttooling: Tooling;\n\tnotifications: Notifications;\n\tanalytics: Analytics;\n\tobservability: Observability;\n}\n\nexport type CardinalityFor<K extends CapabilityKey> = (typeof CARDINALITY)[K];\n\n/** Resolved runtime shape: single → one impl; many → array. */\nexport type ResolvedCapability<K extends CapabilityKey> =\n\tCardinalityFor<K> extends \"many\" ? CapabilityImpls[K][] : CapabilityImpls[K];\n\nexport function isMulti<K extends CapabilityKey>(key: K): CardinalityFor<K> extends \"many\" ? true : false {\n\treturn (CARDINALITY[key] === \"many\") as CardinalityFor<K> extends \"many\" ? true : false;\n}\n","/**\n * `holocron.config.json` schema, parser, and provider resolution.\n *\n * ESLint-style entry forms:\n *\n * \"source\": \"github\" ← single, short\n * \"deployment\": [\"vercel\", { team: \"rando\" }] ← single, with options\n * \"notifications\": [\"slack\", \"discord\"] ← multi, short\n * \"notifications\": [\n * [\"slack\", { channel: \"#ops\" }],\n * [\"discord\", { webhook: \"env:HOOK\" }]\n * ] ← multi, with options\n *\n * Discriminator: an array entry is a `[provider, options]` tuple when\n * the length is 2 AND element[1] is a non-array, non-null object.\n * Otherwise it's a multi-provider list (string[] or tuple[]).\n *\n * Validation rules:\n * - `vault` is REQUIRED (every project has secrets somewhere)\n * - Entries for `'many'` capabilities are normalized to an array of\n * normalized tuples; entries for `'single'` capabilities are\n * normalized to one tuple\n * - Tokens / secret values never appear in config — providers read\n * them from env (or pull from `vault` at runtime)\n */\n\nimport {\n\ttype CapabilityKey,\n\tCARDINALITY,\n\ttype PagesConfig,\n\tREQUIRED_CAPABILITIES,\n\ttype TeamEntry,\n\ttype TeamPermission,\n} from \"./capabilities/index.js\";\n\n// ───────────────────────────────────────────────────────────────────────\n// Raw config (what users write in holocron.config.json)\n// ───────────────────────────────────────────────────────────────────────\n\nexport type ProviderOptions = Record<string, unknown>;\n\n/**\n * The shape a capability config package's default export must satisfy.\n * Config packages let teams share a pre-bundled provider + options across\n * repos (Level 1 of the shareable-configs story, issue #75).\n *\n * @example\n * // @acme/holocron-vault/index.ts\n * import type { CapabilityConfigPackage } from '@theholocron/cli'\n * export default {\n * provider: '1password',\n * options: { vault: 'acme-app' },\n * } satisfies CapabilityConfigPackage\n */\nexport interface CapabilityConfigPackage {\n\tprovider: string;\n\toptions?: ProviderOptions;\n}\n\nexport type SingleEntry = string | [provider: string, options: ProviderOptions];\n\nexport type MultiEntry = Array<string | [provider: string, options: ProviderOptions]>;\n\nexport type RawProviderEntry = SingleEntry | MultiEntry;\n\nexport type RawProvidersConfig = Partial<Record<CapabilityKey, RawProviderEntry>>;\n\nexport type RepoProtection = \"balanced\" | \"strict\" | \"none\";\n\nexport type { PagesConfig, TeamEntry, TeamPermission };\n\n/**\n * Raw `docs` config as written by the user. `build` is optional so the\n * field can be declared without committing to a build type yet; setup\n * will error if `docs` is present but `build` is absent.\n */\nexport interface DocsConfig {\n\t/**\n\t * GitHub Pages build source.\n\t * \"workflow\" → GitHub Actions (PUT { build_type: \"workflow\" })\n\t * \"branch\" → classic gh-pages branch (PUT { build_type: \"legacy\", source: { branch: \"gh-pages\", path: \"/\" } })\n\t * When absent, Pages is not managed by `holocron setup`.\n\t */\n\tbuild?: \"workflow\" | \"branch\";\n\t/**\n\t * Custom domain / CNAME (e.g. \"docs.theholocron.dev\").\n\t * When set and `homepage` is not explicitly provided, setup derives\n\t * `homepage` as `https://{domain}/` for package.json and the repo website field.\n\t */\n\tdomain?: string;\n\t/** Enforce HTTPS. Only effective once the custom domain is DNS-verified. */\n\thttps?: boolean;\n}\n\nexport interface RepoProperties {\n\tlifecycle?: \"active\" | \"experimental\" | \"deprecated\";\n\topen_source?: boolean;\n\truntime_environment?: \"node\" | \"browser\" | \"universal\" | \"none\";\n\tuses_external_packages?: boolean;\n}\n\nexport interface RepoConfig {\n\t/** \"owner/name\" — the GitHub repository coordinate. Derived from the git remote when absent. */\n\tname?: string;\n\t/**\n\t * Branch protection preset applied by `holocron setup`. When omitted,\n\t * no protection is applied and no `branch_protection_level` property is set.\n\t */\n\tprotection?: RepoProtection;\n\t/** CI check context names required on the default branch (only used when `protection` is \"strict\"). */\n\trequiredChecks?: string[];\n\t/**\n\t * GitHub teams granted repository access. Synced by `holocron setup`, which\n\t * also writes `.github/CODEOWNERS` for teams with write-or-higher permission.\n\t * String shorthand defaults to `push` (Write).\n\t */\n\tteams?: TeamEntry[];\n\t/** GitHub topics set on the repository. */\n\ttopics?: string[];\n\t/** GitHub custom properties synced to the org dashboard. */\n\tproperties?: RepoProperties;\n}\n\nexport interface AppConfig {\n\tname: string;\n\tpath: string;\n\tkind?: string;\n}\n\nexport interface DoctorConfig {\n\tchecks?: string[];\n}\n\nexport interface EnvConfig {\n\t/**\n\t * Namespace prefixes used by this project's env vars.\n\t * Listed from least- to most-specific (cascade model — last wins).\n\t * Tooling reads this to generate `.env.example`, validate required\n\t * vars, and produce documentation. Runtime code passes the same\n\t * value to `createEnvParser({ namespaces })` from `@theholocron/env-utils`.\n\t *\n\t * @example\n\t * // Project-only prefix\n\t * namespaces: [\"CLI_TEMPLATE\"]\n\t *\n\t * // Org-wide defaults + project-specific overrides\n\t * namespaces: [\"HOLOCRON\", \"MY_CLI\"]\n\t */\n\tnamespaces?: string[];\n}\n\n/**\n * A single Chromatic project entry in a monorepo `run-chromatic` config.\n * Each entry produces one matrix job in CI, publishing to a separate Chromatic project.\n *\n * The `tokenName` maps to a repository secret named `CHROMATIC_PROJECT_TOKEN_<TOKENNAME>`.\n * Additional fields correspond to chromaui/action inputs and are passed through directly.\n *\n * @see https://www.chromatic.com/docs/monorepos/\n */\nexport interface ChromaticProjectConfig {\n\t/**\n\t * Secret suffix. The CI job reads `CHROMATIC_PROJECT_TOKEN_<tokenName>`.\n\t * Must be uppercase (e.g. `\"WEB\"`, `\"UI\"`).\n\t */\n\ttokenName: string;\n\t/**\n\t * Path to run the Chromatic build from, relative to the repo root.\n\t * Typically the package directory (e.g. `\"apps/web\"`, `\"packages/ui\"`).\n\t */\n\tworkingDir: string;\n\t/**\n\t * Script name to build Storybook. Defaults to `\"build:storybook\"`.\n\t * Must accept `--output-dir` pass-through (use `turbo run … --` at root).\n\t */\n\tbuildScript?: string;\n\t/**\n\t * Path to the Storybook folder relative to `workingDir`, for TurboSnap.\n\t * Tells Chromatic where to find `.storybook/` when the Storybook config\n\t * is in a subdirectory. Corresponds to `--storybook-base-dir`.\n\t */\n\tstorybookBaseDir?: string;\n\t/**\n\t * Glob patterns of files/dirs that should NOT trigger a TurboSnap bailout\n\t * when changed. Useful for ignoring non-UI changes in a monorepo\n\t * (e.g. `\"./packages/!(ui)/**\"` to focus TurboSnap on the UI package).\n\t * Corresponds to `--untraced`. Accepts a single glob string or array.\n\t */\n\tuntraced?: string | string[];\n\t/**\n\t * Glob patterns matching story files to snapshot. When set, only matching\n\t * stories are captured. Corresponds to `--only-story-files`.\n\t * Cannot be combined with `onlyStoryNames`.\n\t */\n\tonlyStoryFiles?: string;\n\t/**\n\t * Exit with code 0 even when visual changes are detected.\n\t * Useful during initial setup before baselines are approved.\n\t * Corresponds to `--exit-zero-on-changes`.\n\t */\n\texitZeroOnChanges?: boolean;\n}\n\n/**\n * A single Storybook app in a deploy workflow config.\n * `name` becomes the sandbox sub-path (`_site/sandbox/<name>/`).\n * `path` is the working directory relative to the repo root; defaults to `\".\"` (repo root) when omitted.\n */\nexport interface StorybookDeployProject {\n\tname?: string;\n\tpath?: string;\n}\n\n/**\n * Typed `with:` inputs for reusable workflows.\n *\n * `run-chromatic` accepts either a plain boolean (single-project) or a\n * `ChromaticProjectConfig[]` object (multi-project monorepo).\n *\n * `docs` / `storybook` are high-level deploy shorthand that `holocron setup`\n * translates to `type` / `storybook-projects` before writing the thin caller.\n * They also drive automatic `paths:` derivation so you never need to write\n * `paths:` manually for deploy entries.\n */\nexport type WorkflowWithConfig = Record<string, unknown> & {\n\t\"run-chromatic\"?: boolean | { projects: ChromaticProjectConfig[] };\n\t/**\n\t * Docs deployment shorthand. `true` uses the org-standard `docs/` directory;\n\t * `{ path: \"custom\" }` uses a custom directory. Both derive a `paths:` entry automatically.\n\t */\n\tdocs?: true | { path: string };\n\t/** Storybook apps to deploy alongside docs. Each entry's `path` is appended to `paths:`. */\n\tstorybook?: StorybookDeployProject[];\n};\n\nexport interface HolocronConfig {\n\t/** Project name. Derived from package.json when absent. */\n\tname?: string;\n\tdescription?: string;\n\t/** Project homepage URL. Synced to package.json#homepage and the GitHub repo's website field by `holocron sync`. */\n\thomepage?: string;\n\t/**\n\t * Active org name for namespaced keyring lookup. When set, token resolution\n\t * tries `<service>.<org>` before the unnamespaced `<service>` fallback, so\n\t * a single machine can hold credentials for multiple GitHub orgs without\n\t * collision. Overridden by `--org` CLI flag or `HOLOCRON_ORG` env var.\n\t */\n\torg?: string;\n\t/**\n\t * Org canonical domain (e.g. `\"theholocron.dev\"`). Subdomains are derived\n\t * from this — `preview: true` on a deploy workflow resolves the preview base\n\t * domain as `preview.<domain>`, giving URLs like `<repo>-pr-<n>.<domain>`.\n\t */\n\tdomain?: string;\n\t/**\n\t * Repository identity and metadata. When set, `PluginLoader` injects\n\t * `repo.name` into every plugin's `RuntimeContext.repo` so plugins that\n\t * need a repo (github, etc.) don't require `--repo` on every invocation.\n\t * `--repo` on the command line still overrides.\n\t */\n\trepo?: RepoConfig;\n\t/**\n\t * CI workflow names to install as thin wrappers during `holocron setup`.\n\t * Each name maps to a reusable workflow in `theholocron/.github`.\n\t * Use the object form to pass `with:` inputs to the reusable workflow.\n\t *\n\t * Supported values: \"lint\" | \"test\" | \"typecheck\" | \"codeql\" | \"review\" |\n\t * \"release\" | \"tag\" | \"stale\" | \"greetings\" | \"dependencies\" | \"bookkeeping\" | \"audit\" |\n\t * \"deploy\"\n\t *\n\t * `holocron setup` writes `.github/workflows/<name>.yml` for each entry,\n\t * calling the corresponding reusable workflow in `theholocron/.github`.\n\t * Files are overwritten on each run — they are generated artifacts.\n\t *\n\t * ### deploy workflow\n\t * Use `docs` and/or `storybook` in `with:` — setup derives `paths:` automatically.\n\t * `docs: true` uses the org-standard `docs/` directory; `docs: { path: \"custom\" }` overrides it.\n\t *\n\t * ```ts\n\t * // Docs only (standard layout)\n\t * { name: \"deploy\", with: { docs: true } }\n\t *\n\t * // Docs + monorepo storybooks\n\t * {\n\t * name: \"deploy\",\n\t * with: {\n\t * docs: true,\n\t * storybook: [\n\t * { name: \"web\", path: \"apps/web\" },\n\t * { name: \"ui\", path: \"packages/ui\" },\n\t * ],\n\t * },\n\t * }\n\t *\n\t * // Non-standard docs location\n\t * { name: \"deploy\", with: { docs: { path: \"packages/site\" } } }\n\t * ```\n\t *\n\t * ### run-chromatic\n\t * For a single-project repo, use `\"run-chromatic\": true` with a\n\t * `CHROMATIC_PROJECT_TOKEN` repository secret.\n\t *\n\t * For monorepos with multiple Storybooks, use the object form:\n\t * ```ts\n\t * \"run-chromatic\": {\n\t * projects: [\n\t * { tokenName: \"WEB\", workingDir: \"apps/web\" },\n\t * { tokenName: \"UI\", workingDir: \"packages/ui\" },\n\t * ]\n\t * }\n\t * ```\n\t * Each `tokenName` maps to a repository secret named\n\t * `CHROMATIC_PROJECT_TOKEN_<TOKENNAME>`. `holocron setup` expands this\n\t * to the flat `run-chromatic: true` + `chromatic-projects: <json>` inputs\n\t * that the reusable workflow accepts.\n\t *\n\t * @example\n\t * [\"lint\", { \"name\": \"release\", \"with\": { \"run-build\": false } }]\n\t * { \"name\": \"deploy\", \"with\": { \"docs\": true } }\n\t */\n\tworkflows?: Array<string | { name: string; with?: WorkflowWithConfig; paths?: string[] }>;\n\tproviders: RawProvidersConfig;\n\tapps?: AppConfig[];\n\tdoctor?: DoctorConfig;\n\t/**\n\t * Agent runtime that determines where skills are installed by `holocron setup`.\n\t * Skills are installed to `.agents/skills/<name>/` (canonical) with a\n\t * relative symlink at the agent-specific path:\n\t * - `\"claude\"` → `.claude/skills/<name>` → `../../.agents/skills/<name>`\n\t * - `\"codex\"` | `\"gemini\"` → logged as unsupported; skipped gracefully.\n\t */\n\tagent?: \"claude\" | \"codex\" | \"gemini\";\n\t/**\n\t * Skill names from `@theholocron/skills` to install during `holocron setup`.\n\t * Installed paths are gitignored and managed by setup — do not commit them.\n\t *\n\t * @example\n\t * [\"git-safety\", \"pr-workflow\", \"commit-standards\"]\n\t */\n\tskills?: string[];\n\t/**\n\t * GitHub Pages configuration. When present, `holocron setup` calls the\n\t * Pages API using `HOLOCRON_DEPLOY_TOKEN` (requires `pages:write` + `repo` scope).\n\t * When absent, Pages is left as-is.\n\t *\n\t * @example\n\t * { build: \"workflow\", domain: \"docs.theholocron.dev\", https: true }\n\t */\n\tdocs?: DocsConfig;\n\t/**\n\t * Environment variable namespace configuration.\n\t * Declares the prefix(es) this project uses for its env vars so that\n\t * tooling can generate `.env.example`, validate required vars, and\n\t * produce accurate documentation without hard-coding prefix strings.\n\t *\n\t * @example\n\t * { namespaces: [\"HOLOCRON\", \"MY_CLI\"] }\n\t */\n\tenv?: EnvConfig;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Resolved config (what the runtime sees after parsing)\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface ResolvedTuple {\n\tprovider: string;\n\t/** Resolved package name (`@theholocron/holocron-plugin-<provider>` for short refs). */\n\tpackageName: string;\n\toptions: ProviderOptions;\n}\n\nexport type ResolvedProviderEntry =\n\t| { cardinality: \"single\"; tuple: ResolvedTuple }\n\t| { cardinality: \"many\"; tuples: ResolvedTuple[] };\n\nexport type ResolvedProvidersConfig = Partial<Record<CapabilityKey, ResolvedProviderEntry>>;\n\nexport interface ResolvedHolocronConfig {\n\tname: string;\n\tdescription?: string;\n\thomepage?: string;\n\torg?: string;\n\tdomain?: string;\n\trepo?: RepoConfig;\n\tworkflows?: Array<string | { name: string; with?: WorkflowWithConfig; paths?: string[] }>;\n\tproviders: ResolvedProvidersConfig;\n\tapps: AppConfig[];\n\tdoctor: DoctorConfig;\n\tagent?: \"claude\" | \"codex\" | \"gemini\";\n\tskills?: string[];\n\t/** Resolved Pages config. `build` is guaranteed present when this field exists. */\n\tdocs?: PagesConfig;\n\tenv?: EnvConfig;\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Errors\n// ───────────────────────────────────────────────────────────────────────\n\nexport class ConfigError extends Error {\n\toverride name = \"ConfigError\";\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Helpers\n// ───────────────────────────────────────────────────────────────────────\n\nconst PLUGIN_PREFIX = \"@theholocron/holocron-plugin-\";\nconst COMMUNITY_PREFIX = \"holocron-plugin-\";\n\n/**\n * Resolve `\"github\"` → `\"@theholocron/holocron-plugin-github\"`.\n * Fully-qualified names (scoped or not) are honored verbatim, which\n * is how third-party plugins published outside the org work.\n */\nexport function resolvePluginPackage(provider: string): string {\n\tif (!provider) throw new ConfigError(\"provider name is empty\");\n\tif (provider.startsWith(\"@\")) return provider;\n\tif (provider.startsWith(COMMUNITY_PREFIX)) return provider;\n\tif (provider.includes(\"/\")) return provider;\n\treturn PLUGIN_PREFIX + provider;\n}\n\n/** A bare `[provider, options]` tuple, with both elements present? */\nfunction isOptionsTuple(value: unknown): value is [string, ProviderOptions] {\n\tif (!Array.isArray(value)) return false;\n\tif (value.length !== 2) return false;\n\tif (typeof value[0] !== \"string\") return false;\n\tconst opt = value[1];\n\treturn typeof opt === \"object\" && opt !== null && !Array.isArray(opt);\n}\n\nfunction normalizeEntry(entry: string | [string, ProviderOptions]): ResolvedTuple {\n\tif (typeof entry === \"string\") {\n\t\treturn { provider: entry, packageName: resolvePluginPackage(entry), options: {} };\n\t}\n\tconst [provider, options] = entry;\n\treturn { provider, packageName: resolvePluginPackage(provider), options };\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Parse / resolve\n// ───────────────────────────────────────────────────────────────────────\n\nexport function resolveEntry(key: CapabilityKey, raw: RawProviderEntry): ResolvedProviderEntry {\n\tconst cardinality = CARDINALITY[key];\n\n\t// Single short form: \"github\"\n\tif (typeof raw === \"string\") {\n\t\tif (cardinality === \"many\") {\n\t\t\tthrow new ConfigError(`\\`${key}\\` accepts multiple providers; wrap a single one in an array: [\"${raw}\"]`);\n\t\t}\n\t\treturn { cardinality: \"single\", tuple: normalizeEntry(raw) };\n\t}\n\n\tif (!Array.isArray(raw)) {\n\t\tthrow new ConfigError(`\\`${key}\\` entry must be a string or array, got ${typeof raw}`);\n\t}\n\n\t// Single options tuple: [\"vercel\", { team: \"rando\" }]\n\tif (isOptionsTuple(raw)) {\n\t\tif (cardinality === \"many\") {\n\t\t\t// Same shape, but cardinality forces multi — promote to one-element list\n\t\t\treturn { cardinality: \"many\", tuples: [normalizeEntry(raw)] };\n\t\t}\n\t\treturn { cardinality: \"single\", tuple: normalizeEntry(raw) };\n\t}\n\n\t// Multi list — array of strings, tuples, or a mix\n\tif (cardinality === \"single\") {\n\t\tthrow new ConfigError(\n\t\t\t`\\`${key}\\` accepts exactly one provider; got a multi-provider list with ${raw.length} entries`\n\t\t);\n\t}\n\n\tconst tuples = raw.map((entry, idx) => {\n\t\tif (typeof entry === \"string\") return normalizeEntry(entry);\n\t\tif (isOptionsTuple(entry)) return normalizeEntry(entry);\n\t\tthrow new ConfigError(`\\`${key}[${idx}]\\` must be a provider string or [provider, options] tuple`);\n\t});\n\n\treturn { cardinality: \"many\", tuples };\n}\n\nexport function resolveConfig(raw: HolocronConfig): ResolvedHolocronConfig {\n\tif (!raw.name) {\n\t\tthrow new ConfigError(\"`name` is required\");\n\t}\n\tif (!raw.providers || typeof raw.providers !== \"object\") {\n\t\tthrow new ConfigError(\"`providers` block is required\");\n\t}\n\n\tconst providers: ResolvedProvidersConfig = {};\n\tfor (const [key, entry] of Object.entries(raw.providers)) {\n\t\tif (entry === undefined) continue;\n\t\tproviders[key as CapabilityKey] = resolveEntry(key as CapabilityKey, entry as RawProviderEntry);\n\t}\n\n\tfor (const required of REQUIRED_CAPABILITIES) {\n\t\tif (!providers[required]) {\n\t\t\tthrow new ConfigError(`required capability \\`${required}\\` is missing from providers`);\n\t\t}\n\t}\n\n\t// Validate docs and narrow build to required\n\tlet docs: PagesConfig | undefined;\n\tif (raw.docs !== undefined) {\n\t\tif (!raw.docs.build) {\n\t\t\tthrow new ConfigError(\"`docs.build` is required when `docs` is set\");\n\t\t}\n\t\tdocs = raw.docs as PagesConfig;\n\t}\n\n\t// Derive homepage from docs.domain when not explicitly set\n\tconst homepage = raw.homepage ?? (docs?.domain ? `https://${docs.domain}/` : undefined);\n\n\treturn {\n\t\tname: raw.name,\n\t\tdescription: raw.description,\n\t\thomepage,\n\t\torg: raw.org,\n\t\tdomain: raw.domain,\n\t\trepo: raw.repo,\n\t\tworkflows: raw.workflows,\n\t\tproviders,\n\t\tapps: raw.apps ?? [],\n\t\tdoctor: raw.doctor ?? {},\n\t\tagent: raw.agent,\n\t\tskills: raw.skills,\n\t\tdocs,\n\t\tenv: raw.env,\n\t};\n}\n","import ora from \"ora\";\n\n/**\n * Runs `fn`, showing an ora spinner for its duration in TTY environments.\n * In non-TTY environments (CI, pipes, tests) the spinner is skipped entirely.\n */\nexport async function withSpinner<T>(label: string, fn: () => Promise<T>): Promise<T> {\n\tif (!process.stdout.isTTY) {\n\t\treturn fn();\n\t}\n\tconst spinner = ora(label).start();\n\ttry {\n\t\tconst result = await fn();\n\t\tspinner.succeed();\n\t\treturn result;\n\t} catch (err) {\n\t\tspinner.fail();\n\t\tthrow err;\n\t}\n}\n","import chalk from \"chalk\";\n\nexport const style = {\n\tsuccess: (msg: string) => `${chalk.green(\"✓\")} ${msg}`,\n\twarn: (msg: string) => `${chalk.yellow(\"⚠\")} ${msg}`,\n\tfail: (msg: string) => `${chalk.red(\"✗\")} ${msg}`,\n\tstep: (msg: string) => `${chalk.cyan(\"→\")} ${msg}`,\n\thint: (msg: string) => chalk.dim(msg),\n\tdim: (msg: string) => chalk.dim(msg),\n\theader: (msg: string) => chalk.bold(msg),\n};\n","/**\n * `holocron auth <subcommand>` — manage bootstrap credentials in the\n * OS keyring.\n *\n * Subcommands:\n * auth set <provider> [token] verify + store\n * auth unset <provider> remove\n * auth check <provider> re-verify a stored token\n * auth list every provider with a stored entry\n *\n * See `.notes/tech-auth-bootstrap.spec.md`.\n *\n * Verification lives in each plugin as a top-level `verifyToken(token)`\n * export. The auth command dynamically imports\n * `@theholocron/holocron-plugin-<provider>` and calls it. Plugins that\n * don't export `verifyToken` can still store — with a warning — because\n * \"no verify path\" shouldn't block credential storage.\n */\n\nimport { resolvePluginPackage } from \"../config.js\";\nimport { deleteToken, getToken, listStoredProviders, setToken } from \"../keyring.js\";\nimport { withSpinner } from \"../ui/progress.js\";\nimport { style } from \"../ui/style.js\";\n\n// ── Plugin-level export shapes (mirrored on every plugin) ────────────\n\nexport interface VerifyTokenSuccess {\n\tok: true;\n\t/** \"workplace: acme\" / \"user: cnewton@x\" — surfaced in success output. */\n\tsubject: string;\n}\n\nexport interface VerifyTokenFailure {\n\tok: false;\n\t/** Reason the token was rejected. Surfaces to the operator. */\n\tmessage: string;\n}\n\nexport type VerifyTokenResult = VerifyTokenSuccess | VerifyTokenFailure;\n\ninterface AuthPluginModule {\n\tverifyToken?: (token: string) => Promise<VerifyTokenResult>;\n\t/** One-line hint printed when no token was supplied. */\n\tAUTH_HINT?: string;\n}\n\nexport type AuthImporter = (packageName: string) => Promise<AuthPluginModule>;\n\nconst defaultImporter: AuthImporter = async (pkg) => (await import(pkg)) as AuthPluginModule;\n\n// ── Common types ─────────────────────────────────────────────────────\n\nexport type AuthPrint = (line: string) => void;\n\nexport interface AuthCommandStatus {\n\tstatus: \"ok\" | \"fail\" | \"skip\";\n\tmessage?: string;\n}\n\n// ── Token resolution ─────────────────────────────────────────────────\n\n/**\n * Resolve a token from (positional → HOLOCRON_<X> → vendor-native env).\n * Keyring is NOT consulted here — `auth set` writes TO the keyring, so\n * pulling FROM it would just re-store the same value.\n */\nexport function resolveAuthSetToken(input: {\n\tprovider: string;\n\tpositional?: string;\n\tenv?: NodeJS.ProcessEnv;\n}): string | null {\n\tconst env = input.env ?? process.env;\n\tconst upper = input.provider.toUpperCase();\n\tconst holocronKey = `HOLOCRON_${upper}_TOKEN`;\n\treturn input.positional || env[holocronKey] || env[upper + \"_TOKEN\"] || null;\n}\n\n// ── Subcommands ──────────────────────────────────────────────────────\n\nexport interface RunAuthSetInput {\n\tprovider: string;\n\tpositional?: string;\n\tenv?: NodeJS.ProcessEnv;\n\timporter?: AuthImporter;\n\tprint?: AuthPrint;\n\t/** When set, stores the token under `<provider>.<org>` in the keyring. */\n\torg?: string;\n}\n\nexport async function runAuthSet(input: RunAuthSetInput): Promise<AuthCommandStatus> {\n\tconst print = input.print ?? ((l: string) => console.log(l));\n\tconst importer = input.importer ?? defaultImporter;\n\tconst { provider } = input;\n\tconst keyringKey = input.org ? `${provider}.${input.org}` : provider;\n\n\tconst token = resolveAuthSetToken({ provider, positional: input.positional, env: input.env });\n\n\t// Feature sub-keys (e.g. \"github.read\") are stored directly — there is no\n\t// per-feature plugin package to load for verification.\n\tconst isFeatureKey = provider.includes(\".\");\n\tconst packageName = isFeatureKey ? null : resolvePluginPackage(provider);\n\n\tif (!token) {\n\t\tprint(style.fail(`no token supplied for \\`${keyringKey}\\`.`));\n\t\tprint(style.hint(` pass as positional arg: holocron auth set ${provider} <token>`));\n\t\tif (!isFeatureKey) {\n\t\t\tprint(\n\t\t\t\tstyle.hint(` or via env: HOLOCRON_${provider.toUpperCase()}_TOKEN / ${provider.toUpperCase()}_TOKEN`)\n\t\t\t);\n\t\t\tconst hint = await tryLoadHint(importer, packageName!);\n\t\t\tif (hint) {\n\t\t\t\tprint(style.hint(` hint: ${hint}`));\n\t\t\t}\n\t\t}\n\t\treturn { status: \"fail\", message: \"no token supplied\" };\n\t}\n\n\t// Verify via the plugin if it exports verifyToken (skipped for feature sub-keys).\n\tlet subject: string | undefined;\n\tif (!isFeatureKey && packageName) {\n\t\ttry {\n\t\t\tconst module = await importer(packageName);\n\t\t\tif (typeof module.verifyToken === \"function\") {\n\t\t\t\tconst verified = await module.verifyToken(token);\n\t\t\t\tif (!verified.ok) {\n\t\t\t\t\tprint(style.fail(`token rejected by ${provider}: ${verified.message}`));\n\t\t\t\t\tif (module.AUTH_HINT) print(style.hint(` hint: ${module.AUTH_HINT}`));\n\t\t\t\t\treturn { status: \"fail\", message: verified.message };\n\t\t\t\t}\n\t\t\t\tsubject = verified.subject;\n\t\t\t} else {\n\t\t\t\tprint(style.warn(`${provider} plugin has no verifyToken; storing without verification`));\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\tprint(style.warn(`cannot verify token — failed to load ${packageName}: ${msg}`));\n\t\t\tprint(\n\t\t\t\tstyle.hint(` storing token anyway; run 'holocron auth check ${provider}' once the plugin is installed`)\n\t\t\t);\n\t\t}\n\t}\n\n\tconst stored = setToken(keyringKey, token);\n\tif (!stored) {\n\t\tprint(style.fail(`keyring unavailable — token not stored. Use env vars instead.`));\n\t\treturn { status: \"fail\", message: \"keyring unavailable\" };\n\t}\n\n\tprint(style.success(`stored ${keyringKey} token${subject ? ` (${subject})` : \"\"}`));\n\treturn { status: \"ok\", ...(subject ? { message: subject } : {}) };\n}\n\nexport interface RunAuthUnsetInput {\n\tprovider: string;\n\tprint?: AuthPrint;\n}\n\nexport function runAuthUnset(input: RunAuthUnsetInput): AuthCommandStatus {\n\tconst print = input.print ?? ((l: string) => console.log(l));\n\tconst removed = deleteToken(input.provider);\n\tif (removed) {\n\t\tprint(style.success(`removed ${input.provider} token`));\n\t\treturn { status: \"ok\" };\n\t}\n\tprint(style.dim(`no stored token for ${input.provider}`));\n\treturn { status: \"skip\", message: \"nothing to remove\" };\n}\n\nexport interface RunAuthCheckInput {\n\tprovider: string;\n\timporter?: AuthImporter;\n\tprint?: AuthPrint;\n\t/** Set to false to suppress the ora spinner (e.g. when called from runAuthList). */\n\tshowSpinner?: boolean;\n\t/** When set, checks the token stored under `<provider>.<org>` in the keyring. */\n\torg?: string;\n}\n\nexport async function runAuthCheck(input: RunAuthCheckInput): Promise<AuthCommandStatus> {\n\tconst print = input.print ?? ((l: string) => console.log(l));\n\tconst importer = input.importer ?? defaultImporter;\n\tconst { provider } = input;\n\tconst keyringKey = input.org ? `${provider}.${input.org}` : provider;\n\n\tconst token = getToken(keyringKey);\n\tif (!token) {\n\t\tprint(style.dim(`no stored token for ${keyringKey}`));\n\t\treturn { status: \"skip\", message: \"no stored token\" };\n\t}\n\n\t// Feature sub-keys have no plugin to verify against — report stored only.\n\tif (provider.includes(\".\")) {\n\t\tprint(style.success(`${keyringKey}: token stored (feature key — no plugin verification)`));\n\t\treturn { status: \"ok\", message: \"stored\" };\n\t}\n\n\tconst packageName = resolvePluginPackage(provider);\n\ttry {\n\t\tconst module = await importer(packageName);\n\t\tif (typeof module.verifyToken !== \"function\") {\n\t\t\tprint(style.warn(`${keyringKey}: token stored (plugin has no verifyToken; can't confirm validity)`));\n\t\t\treturn { status: \"ok\", message: \"stored, unverified\" };\n\t\t}\n\t\tconst verify = () => module.verifyToken!(token);\n\t\tconst verified =\n\t\t\tinput.showSpinner !== false ? await withSpinner(`Verifying ${keyringKey} token…`, verify) : await verify();\n\t\tif (verified.ok) {\n\t\t\tprint(style.success(`${keyringKey}: ok — ${verified.subject}`));\n\t\t\treturn { status: \"ok\", message: verified.subject };\n\t\t}\n\t\tprint(style.fail(`${keyringKey}: rejected — ${verified.message}`));\n\t\tif (module.AUTH_HINT) print(style.hint(` hint: ${module.AUTH_HINT}`));\n\t\treturn { status: \"fail\", message: verified.message };\n\t} catch (err) {\n\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\tprint(style.fail(`${keyringKey}: cannot verify — ${msg}`));\n\t\treturn { status: \"fail\", message: msg };\n\t}\n}\n\nexport interface RunAuthListInput {\n\timporter?: AuthImporter;\n\tprint?: AuthPrint;\n}\n\nexport async function runAuthList(input: RunAuthListInput = {}): Promise<AuthCommandStatus> {\n\tconst print = input.print ?? ((l: string) => console.log(l));\n\tconst importer = input.importer ?? defaultImporter;\n\tconst providers = listStoredProviders();\n\n\tif (providers.length === 0) {\n\t\tprint(style.dim(\"no stored tokens.\"));\n\t\tprint(style.hint(\"run: holocron auth set <provider> <token>\"));\n\t\treturn { status: \"ok\", message: \"none\" };\n\t}\n\n\tfor (const provider of providers.sort()) {\n\t\tconst check = await runAuthCheck({ provider, importer, print: () => {}, showSpinner: false });\n\t\tconst label = `${provider}${check.message ? ` — ${check.message}` : \"\"}`;\n\t\tif (check.status === \"ok\") print(` ${style.success(label)}`);\n\t\telse if (check.status === \"fail\") print(` ${style.fail(label)}`);\n\t\telse print(` ${style.dim(`· ${label}`)}`);\n\t}\n\treturn { status: \"ok\" };\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nasync function tryLoadHint(importer: AuthImporter, packageName: string): Promise<string | null> {\n\ttry {\n\t\tconst module = await importer(packageName);\n\t\treturn module.AUTH_HINT ?? null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n","/**\n * `PluginLoader` — loads provider plugins per the resolved config and\n * builds a typed capability registry the runtime can query.\n *\n * Flow:\n * 1. Walk `config.providers[*]` from `resolveConfig()`\n * 2. For each entry, dynamic-import the resolved package name\n * (`@theholocron/holocron-plugin-<provider>` by default)\n * 3. Call the package's exported `createPlugin(options)` to get a\n * plugin object whose `capabilities` map holds factories\n * 4. Invoke the matching capability factory and stash the impl in\n * the registry — single-cardinality entries hold one impl,\n * many-cardinality entries hold an array\n *\n * A package may instead export a capability config (see\n * `CapabilityConfigPackage` in config.ts). The loader detects the shape\n * at import time and re-resolves to the underlying plugin, merging the\n * preset options with any per-project overrides from the config file\n * (project options win, mirroring ESLint's `extends` precedence).\n *\n * Loader keeps NO knowledge of vendor tokens. Each plugin reads its\n * own env vars (`HOLOCRON_ADMIN_TOKEN`, `HOLOCRON_VERCEL_TOKEN`, etc.)\n * inside its `createPlugin`. That keeps the loader vendor-agnostic\n * and the auth story per-plugin explicit.\n *\n * `importer` is injectable so tests don't need real network or\n * sibling packages installed.\n */\n\nimport type { CapabilityKey, CardinalityFor, ResolvedCapability } from \"./capabilities/index.js\";\nimport { CARDINALITY } from \"./capabilities/index.js\";\nimport type { CapabilityConfigPackage, ResolvedHolocronConfig, ResolvedTuple } from \"./config.js\";\nimport { resolvePluginPackage } from \"./config.js\";\n\n/**\n * Per-invocation context every plugin receives, on top of its own\n * config-time options. Kept intentionally narrow.\n */\nexport interface RuntimeContext {\n\t/** \"owner/name\" — the repo this invocation is operating on. */\n\trepo?: string;\n\t/** Absolute path to the working repo root. */\n\trepoRoot: string;\n\t/**\n\t * When true, commands print what they WOULD mutate instead of\n\t * actually calling capability mutators. Set by the global\n\t * `--dry-run` flag. Capabilities themselves are unaware — the check\n\t * lives at the command layer.\n\t */\n\tdryRun?: boolean;\n\t/**\n\t * Token passed via bare `--token <value>`. Used as fallback for all\n\t * plugins when no matching entry exists in `cliTokens`.\n\t */\n\tcliToken?: string;\n\t/**\n\t * Per-provider tokens from `--token vendor=value` pairs. The loader\n\t * routes each entry to the matching plugin (by `tuple.provider`) as\n\t * its `cliToken`, falling back to `cliToken` for unmatched providers.\n\t * Plugins never receive this map — they always see a single `cliToken`.\n\t */\n\tcliTokens?: Record<string, string>;\n\t/**\n\t * Active org name for namespaced keyring lookup. Resolved from\n\t * `--org` flag → `HOLOCRON_ORG` env var → `org` in config, then\n\t * injected here so plugins receive it via their options\n\t * (which extend `ResolveTokenInput`) without any per-plugin change.\n\t */\n\torg?: string;\n}\n\n/**\n * The shape every plugin's default-or-named export must satisfy:\n * `createPlugin(opts)` returns an object with capability factories.\n */\nexport interface LoadedPlugin {\n\tname: string;\n\tcapabilities: Partial<{\n\t\t[K in CapabilityKey]: () => unknown;\n\t}>;\n}\n\nexport interface PluginModule {\n\tcreatePlugin: (opts: Record<string, unknown>) => LoadedPlugin;\n}\n\n/** Returns `unknown` — the loader type-narrows inside `loadOne`. */\nexport type PluginImporter = (packageName: string) => Promise<unknown>;\n\nexport class LoaderError extends Error {\n\toverride name = \"LoaderError\";\n}\n\nexport class PluginLoader {\n\tprivate readonly registry = new Map<CapabilityKey, unknown>();\n\n\tconstructor(\n\t\tprivate readonly config: ResolvedHolocronConfig,\n\t\tprivate readonly context: RuntimeContext,\n\t\tprivate readonly importer: PluginImporter = defaultImporter\n\t) {}\n\n\t/** Imports every configured plugin and builds the capability registry. */\n\tasync load(): Promise<void> {\n\t\tconst entries = Object.entries(this.config.providers) as Array<\n\t\t\t[CapabilityKey, ResolvedHolocronConfig[\"providers\"][CapabilityKey]]\n\t\t>;\n\n\t\tfor (const [key, entry] of entries) {\n\t\t\tif (!entry) continue;\n\t\t\tif (entry.cardinality === \"single\") {\n\t\t\t\tthis.registry.set(key, await this.loadOne(key, entry.tuple));\n\t\t\t} else {\n\t\t\t\tconst impls = [];\n\t\t\t\tfor (const tuple of entry.tuples) {\n\t\t\t\t\timpls.push(await this.loadOne(key, tuple));\n\t\t\t\t}\n\t\t\t\tthis.registry.set(key, impls);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Type-safe lookup. Single-cardinality keys return one impl;\n\t * many-cardinality keys return an array. `ResolvedCapability<K>`\n\t * encodes the split via the `CARDINALITY` map.\n\t */\n\tget<K extends CapabilityKey>(key: K): ResolvedCapability<K> {\n\t\tconst impl = this.registry.get(key);\n\t\tif (impl === undefined) {\n\t\t\tthrow new LoaderError(`capability \\`${key}\\` is not loaded — is it declared in holocron.config.json?`);\n\t\t}\n\t\treturn impl as ResolvedCapability<K>;\n\t}\n\n\t/** Whether a capability has been loaded. */\n\thas<K extends CapabilityKey>(key: K): boolean {\n\t\treturn this.registry.has(key);\n\t}\n\n\t/** All capability keys currently loaded. Useful for the doctor command. */\n\tloadedKeys(): CapabilityKey[] {\n\t\treturn Array.from(this.registry.keys());\n\t}\n\n\t/** Internal — invoke a plugin's capability factory and return the impl. */\n\tprivate async loadOne(key: CapabilityKey, tuple: ResolvedTuple): Promise<unknown> {\n\t\tconst mod = await this.importer(tuple.packageName).catch((err: unknown) => {\n\t\t\tthrow new LoaderError(\n\t\t\t\t`failed to import \\`${tuple.packageName}\\` for capability \\`${key}\\`: ${\n\t\t\t\t\terr instanceof Error ? err.message : String(err)\n\t\t\t\t}`\n\t\t\t);\n\t\t});\n\n\t\t// Plugin package: exports createPlugin(opts) → { capabilities }\n\t\tif (isPluginModule(mod)) {\n\t\t\t// Resolve the effective token for this specific plugin.\n\t\t\t// cliTokens[provider] wins over the bare cliToken fallback.\n\t\t\tconst effectiveToken = this.context.cliTokens?.[tuple.provider] ?? this.context.cliToken;\n\n\t\t\t// Precedence (later wins): project-level defaults from config →\n\t\t\t// runtime context (CLI flags: --repo, --token) → per-plugin\n\t\t\t// resolved token → tuple options (per-plugin overrides in config).\n\t\t\t// cliTokens is explicitly cleared so the map never reaches plugins.\n\t\t\tconst plugin = mod.createPlugin({\n\t\t\t\t...this.projectDefaults(),\n\t\t\t\t...this.context,\n\t\t\t\t...(effectiveToken !== undefined ? { cliToken: effectiveToken } : {}),\n\t\t\t\tcliTokens: undefined,\n\t\t\t\t...tuple.options,\n\t\t\t});\n\t\t\tconst factory = plugin.capabilities[key];\n\t\t\tif (typeof factory !== \"function\") {\n\t\t\t\tthrow new LoaderError(`\\`${tuple.packageName}\\` does not implement the \\`${key}\\` capability`);\n\t\t\t}\n\t\t\treturn factory();\n\t\t}\n\n\t\t// Capability config package: default export is { provider, options? }.\n\t\t// Re-resolve to the underlying plugin; preset options are the base,\n\t\t// per-project tuple options override them (ESLint extends precedence).\n\t\tif (isCapabilityConfigModule(mod)) {\n\t\t\tconst cap = (mod as { default: CapabilityConfigPackage }).default;\n\t\t\treturn this.loadOne(key, {\n\t\t\t\tprovider: cap.provider,\n\t\t\t\tpackageName: resolvePluginPackage(cap.provider),\n\t\t\t\toptions: { ...cap.options, ...tuple.options },\n\t\t\t});\n\t\t}\n\n\t\tthrow new LoaderError(\n\t\t\t`\\`${tuple.packageName}\\` does not export \\`createPlugin(options)\\` or a capability config ({ provider, options? })`\n\t\t);\n\t}\n\n\t/**\n\t * Project-level defaults that get merged into every plugin's options\n\t * unless overridden by the CLI context or per-plugin tuple options.\n\t * See `.notes/tech-setup-and-config.spec.md` §Design.\n\t */\n\tprivate projectDefaults(): Partial<RuntimeContext> {\n\t\tconst defaults: Partial<RuntimeContext> = {};\n\t\tif (this.config.repo?.name) defaults.repo = this.config.repo.name;\n\t\treturn defaults;\n\t}\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\n/** Default importer — native dynamic import. */\nconst defaultImporter: PluginImporter = async (pkg) => {\n\treturn import(pkg);\n};\n\nfunction isPluginModule(mod: unknown): mod is PluginModule {\n\treturn typeof (mod as PluginModule).createPlugin === \"function\";\n}\n\nfunction isCapabilityConfigModule(mod: unknown): mod is { default: CapabilityConfigPackage } {\n\tconst def = (mod as { default?: unknown }).default;\n\treturn typeof (def as CapabilityConfigPackage)?.provider === \"string\";\n}\n\n/** Convenience re-export so callers can compute counts without importing CARDINALITY directly. */\nexport function cardinalityOf<K extends CapabilityKey>(key: K): CardinalityFor<K> {\n\treturn CARDINALITY[key];\n}\n","import { checkbox } from \"@inquirer/prompts\";\n\nimport type { Deployment, DeploymentRecord, PullRequest, Source } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport { style } from \"../ui/style.js\";\n\nexport interface RunCleanupPreviewInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** PR number to look up on the source provider. */\n\tprNumber: number;\n\t/**\n\t * \"owner/name\" override — when provided, the PR is looked up in this repo\n\t * instead of the one the source plugin is scoped to.\n\t */\n\trepo?: string;\n\t/** Cloudflare Pages project name (e.g. \"theholocron-preview\"). */\n\tproject: string;\n\tloader?: PluginLoader;\n\tprint?: (line: string) => void;\n}\n\nexport interface CleanupPreviewReport {\n\tpr: PullRequest;\n\t/** Branch alias used to query Cloudflare (e.g. \"holocron-pr-42\"). */\n\tbranch: string;\n\tfound: number;\n\tdeleted: number;\n\tstatus: \"ok\" | \"none\" | \"aborted\" | \"fail\";\n\tmessage?: string;\n}\n\nfunction prStateLabel(pr: PullRequest): string {\n\tif (pr.merged) return style.success(\"merged\");\n\tif (pr.state === \"closed\") return style.dim(\"closed (not merged)\");\n\treturn style.warn(\"open\");\n}\n\nexport async function runCleanupPreview(input: RunCleanupPreviewInput): Promise<CleanupPreviewReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\t// c8 ignore next -- real PluginLoader construction is integration-level; unit tests always supply loader\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait loader.load();\n\n\t// ── 1. Look up the PR ───────────────────────────────────────────────\n\tif (!loader.has(\"source\")) {\n\t\tthrow new Error(\"source capability is not configured — add a source provider to holocron.config.json\");\n\t}\n\tconst source = loader.get(\"source\") as Source;\n\tif (!source.getPullRequest) {\n\t\tthrow new Error(`${source.providerName} source provider does not support getPullRequest`);\n\t}\n\n\tlet pr: PullRequest;\n\ttry {\n\t\tpr = await source.getPullRequest(input.prNumber, input.repo);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to fetch PR #${input.prNumber}: ${message}`, { cause: err });\n\t}\n\n\t// Derive the Cloudflare branch alias from the repo name and PR number.\n\t// Matches the convention the deploy-preview workflow uses:\n\t// --branch ${{ github.event.repository.name }}-pr-${{ github.event.pull_request.number }}\n\tconst repoName = (input.repo ?? input.loaded.resolved.repo?.name ?? \"\").split(\"/\").pop()!;\n\tconst branch = `${repoName}-pr-${pr.number}`;\n\n\tprint(\"\");\n\tprint(`${style.header(`PR #${pr.number}`)} — ${pr.title}`);\n\tprint(` Status : ${prStateLabel(pr)} | Branch : ${style.dim(pr.branch)}`);\n\tprint(` URL : ${style.dim(pr.url)}`);\n\tprint(` CF alias : ${style.dim(branch)}`);\n\tprint(\"\");\n\n\t// ── 2. List deployments ─────────────────────────────────────────────\n\tif (!loader.has(\"deployment\")) {\n\t\tthrow new Error(\"deployment capability is not configured — add a deployment provider to holocron.config.json\");\n\t}\n\tconst deploy = loader.get(\"deployment\") as Deployment;\n\tif (!deploy.listPreviewDeployments || !deploy.deletePreviewDeployments) {\n\t\tthrow new Error(`${deploy.providerName} deployment provider does not support preview cleanup`);\n\t}\n\n\tlet deployments: DeploymentRecord[];\n\ttry {\n\t\tdeployments = await deploy.listPreviewDeployments(input.project, branch);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to list deployments: ${message}`, { cause: err });\n\t}\n\n\tif (deployments.length === 0) {\n\t\tprint(style.dim(`No deployments found for branch ${branch}.`));\n\t\treturn { pr, branch, found: 0, deleted: 0, status: \"none\" };\n\t}\n\n\tprint(`Found ${deployments.length} deployment${deployments.length === 1 ? \"\" : \"s\"} for ${style.dim(branch)}:`);\n\tprint(\"\");\n\n\tif (pr.state === \"open\") {\n\t\tprint(\n\t\t\tstyle.warn(\n\t\t\t\t`PR #${pr.number} is still open. Deleting its preview deployments will break the live preview link.`\n\t\t\t)\n\t\t);\n\t\tprint(style.warn(\"Nothing is pre-selected — check the deployments you want to remove.\"));\n\t\tprint(\"\");\n\t}\n\n\t// ── 3. Interactive selection ────────────────────────────────────────\n\tconst choices = deployments.map((d) => {\n\t\tconst label = d.id.includes(\":\") ? d.id.split(\":\").pop()! : d.id;\n\t\tconst date = d.createdAt ? style.dim(d.createdAt.slice(0, 10)) : \"\";\n\t\treturn {\n\t\t\tname: `${label} ${date} ${style.dim(d.url)}`,\n\t\t\tvalue: d.id,\n\t\t\tchecked: pr.state !== \"open\",\n\t\t};\n\t});\n\n\tlet selected: string[];\n\ttry {\n\t\tselected = await checkbox({\n\t\t\tmessage: \"Select deployments to delete (space to toggle, a to select all, enter to confirm):\",\n\t\t\tchoices,\n\t\t});\n\t} catch {\n\t\t// Ctrl-C\n\t\tprint(style.dim(\"Aborted.\"));\n\t\treturn { pr, branch, found: deployments.length, deleted: 0, status: \"aborted\" };\n\t}\n\n\tif (selected.length === 0) {\n\t\tprint(style.dim(\"Nothing selected — no deployments deleted.\"));\n\t\treturn { pr, branch, found: deployments.length, deleted: 0, status: \"aborted\" };\n\t}\n\n\t// ── 4. Delete ───────────────────────────────────────────────────────\n\tprint(\"\");\n\ttry {\n\t\tconst count = await deploy.deletePreviewDeployments(input.project, selected);\n\t\tprint(style.success(`Deleted ${count} deployment${count === 1 ? \"\" : \"s\"}.`));\n\t\treturn { pr, branch, found: deployments.length, deleted: count, status: \"ok\" };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tprint(style.fail(message));\n\t\treturn { pr, branch, found: deployments.length, deleted: 0, status: \"fail\", message };\n\t}\n}\n","import { spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nimport { style } from \"../ui/style.js\";\n\nfunction encodeTokenForGitHttpAuth(token: string): string {\n\tconst trimmed = token.trim();\n\tif (!trimmed) throw new Error(\"empty token\");\n\t// eslint-disable-next-line no-control-regex\n\tif (/[\\u0000-\\u001F\\u007F\\s]/.test(trimmed)) {\n\t\tthrow new Error(\"token contains whitespace or control characters\");\n\t}\n\treturn encodeURIComponent(trimmed);\n}\n\ninterface GitHubRepo {\n\tname: string;\n\tfull_name: string;\n\tclone_url: string;\n\tarchived: boolean;\n}\n\ntype ExecFn = (cmd: string, args: string[], opts: { cwd: string }) => { status: number | null };\n\nexport interface RunCloneInput {\n\torg: string;\n\t/** Parent directory to clone into. Defaults to ~/Code/<org>. */\n\tdir?: string;\n\ttoken: string;\n\tdryRun?: boolean;\n\tfetch?: typeof globalThis.fetch;\n\texec?: ExecFn;\n\tprint?: (line: string) => void;\n}\n\nexport interface CloneReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n\tcloned: number;\n\tskipped: number;\n\tfailed: number;\n\tmessage?: string;\n}\n\nasync function listOrgRepos(org: string, token: string, fetchFn: typeof globalThis.fetch): Promise<GitHubRepo[]> {\n\tconst repos: GitHubRepo[] = [];\n\tlet url: string | null = `https://api.github.com/orgs/${org}/repos?per_page=100&type=all`;\n\n\twhile (url) {\n\t\tconst res = await fetchFn(url, {\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\tAccept: \"application/vnd.github+json\",\n\t\t\t\t\"X-GitHub-Api-Version\": \"2022-11-28\",\n\t\t\t},\n\t\t});\n\n\t\tif (!res.ok) {\n\t\t\tthrow new Error(`GitHub API ${res.status}: ${res.statusText} — check that the token has org:read scope`);\n\t\t}\n\n\t\trepos.push(...((await res.json()) as GitHubRepo[]));\n\n\t\tconst link = res.headers.get(\"link\");\n\t\tconst next = link?.match(/<([^>]+)>;\\s*rel=\"next\"/);\n\t\turl = next ? next[1] : null;\n\t}\n\n\treturn repos;\n}\n\nexport async function runClone(input: RunCloneInput): Promise<CloneReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst fetchFn = input.fetch ?? globalThis.fetch;\n\tconst dryRun = input.dryRun ?? false;\n\tconst targetDir = resolve(input.dir ?? join(homedir(), \"Code\", input.org));\n\tconst exec: ExecFn =\n\t\tinput.exec ??\n\t\t((cmd, args, opts) => {\n\t\t\tconst r = spawnSync(cmd, args, { cwd: opts.cwd, stdio: \"inherit\" });\n\t\t\treturn { status: r.status };\n\t\t});\n\n\tprint(style.header(`Holocron clone — org=${input.org} → ${targetDir}${dryRun ? \" (dry-run)\" : \"\"}`));\n\n\tif (!existsSync(targetDir)) {\n\t\tif (dryRun) {\n\t\t\tprint(style.dim(` would create ${targetDir}`));\n\t\t} else {\n\t\t\tmkdirSync(targetDir, { recursive: true });\n\t\t}\n\t}\n\n\tlet repos: GitHubRepo[];\n\ttry {\n\t\trepos = await listOrgRepos(input.org, input.token, fetchFn);\n\t} catch (err) {\n\t\treturn {\n\t\t\tstatus: \"fail\",\n\t\t\tcloned: 0,\n\t\t\tskipped: 0,\n\t\t\tfailed: 0,\n\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t};\n\t}\n\n\tlet cloned = 0;\n\tlet skipped = 0;\n\tlet failed = 0;\n\n\tfor (const repo of repos) {\n\t\t// Strip leading dot so hidden repos (e.g. .github) are visible in Finder.\n\t\tconst dirName = repo.name.startsWith(\".\") ? repo.name.slice(1) : repo.name;\n\t\tconst dest = join(targetDir, dirName);\n\n\t\tif (existsSync(dest)) {\n\t\t\tprint(style.dim(` skip ${repo.full_name}`));\n\t\t\tskipped++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (dryRun) {\n\t\t\tprint(style.dim(` would clone ${repo.full_name} → ${dest}`));\n\t\t\tcloned++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tprint(style.step(` clone ${repo.full_name}`));\n\t\tconst { clone_url } = repo;\n\t\tif (!clone_url.startsWith(\"https://github.com/\")) {\n\t\t\tprint(style.fail(` failed ${repo.full_name} — unexpected clone URL: ${clone_url}`));\n\t\t\tfailed++;\n\t\t\tcontinue;\n\t\t}\n\t\tlet encodedToken: string;\n\t\ttry {\n\t\t\tencodedToken = encodeTokenForGitHttpAuth(input.token);\n\t\t} catch (err) {\n\t\t\tprint(\n\t\t\t\tstyle.fail(\n\t\t\t\t\t` failed ${repo.full_name} — invalid token format: ${err instanceof Error ? err.message : String(err)}`\n\t\t\t\t)\n\t\t\t);\n\t\t\tfailed++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst authedUrl = `https://x-access-token:${encodedToken}@github.com/${clone_url.slice(\"https://github.com/\".length)}`;\n\t\tconst result = exec(\"git\", [\"clone\", \"--\", authedUrl, dest], { cwd: targetDir });\n\n\t\tif (result.status !== 0) {\n\t\t\tprint(style.fail(` failed ${repo.full_name}`));\n\t\t\tfailed++;\n\t\t} else {\n\t\t\tprint(style.success(` cloned ${repo.name}`));\n\t\t\tcloned++;\n\t\t}\n\t}\n\n\tconst summary = `${cloned} cloned, ${skipped} skipped, ${failed} failed`;\n\tprint(\n\t\tdryRun\n\t\t\t? style.dim(`\\n dry-run: ${summary}`)\n\t\t\t: failed > 0\n\t\t\t\t? style.fail(`\\n ${summary}`)\n\t\t\t\t: style.success(`\\n ${summary}`)\n\t);\n\n\treturn {\n\t\tstatus: dryRun ? \"dry-run\" : failed > 0 ? \"fail\" : \"ok\",\n\t\tcloned,\n\t\tskipped,\n\t\tfailed,\n\t};\n}\n","/**\n * `holocron deploy` — trigger a deployment via the configured\n * `deployment` capability.\n *\n * Errors clearly when `deployment` isn't loaded (no provider declared\n * in `holocron.config.json`). Returns the resulting deployment record\n * so callers can print the URL + status.\n *\n * Dry-run skips the actual triggerDeployment call but still verifies\n * the deployment capability is present, so operators can sanity-check\n * the wiring without spinning up a build.\n */\n\nimport type { Deployment, DeploymentRecord, DeploymentTrigger } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport { withSpinner } from \"../ui/progress.js\";\nimport { style } from \"../ui/style.js\";\n\nexport type DeployPrintLine = (line: string) => void;\n\nexport interface RunDeployInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** Vendor project id (e.g., Vercel prj_*). Required. */\n\tprojectId: string;\n\t/** Git branch to deploy. */\n\tbranch: string;\n\t/** Named target — `undefined` means branch preview. */\n\ttarget?: DeploymentTrigger;\n\tloader?: PluginLoader;\n\tprint?: DeployPrintLine;\n}\n\nexport interface DeployReport {\n\t/** Null in dry-run mode (no actual deployment was triggered). */\n\tdeployment: DeploymentRecord | null;\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n\tmessage?: string;\n}\n\nexport async function runDeploy(input: RunDeployInput): Promise<DeployReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait loader.load();\n\n\tconst dryRun = input.context.dryRun ?? false;\n\n\tprint(\n\t\tstyle.header(\n\t\t\t`Holocron deploy — branch=${input.branch}${\n\t\t\t\tinput.target ? `, target=${input.target}` : \" (preview)\"\n\t\t\t}${dryRun ? \" (dry-run)\" : \"\"}`\n\t\t)\n\t);\n\n\tif (!loader.has(\"deployment\")) {\n\t\tthrow new Error(\n\t\t\t\"deployment capability is not configured — add a `deployment` provider to holocron.config.json\"\n\t\t);\n\t}\n\tconst deploy = loader.get(\"deployment\") as Deployment;\n\n\tif (dryRun) {\n\t\tconst message = `would: ${deploy.providerName}.triggerDeployment(projectId=${input.projectId}, branch=${input.branch}${\n\t\t\tinput.target ? `, target=${input.target}` : \"\"\n\t\t})`;\n\t\tprint(` ${style.dim(`… ${message}`)}`);\n\t\treturn { deployment: null, status: \"dry-run\", message };\n\t}\n\n\ttry {\n\t\tconst record = await withSpinner(`Deploying ${input.branch}${input.target ? ` → ${input.target}` : \"\"}…`, () =>\n\t\t\tdeploy.triggerDeployment({\n\t\t\t\tprojectId: input.projectId,\n\t\t\t\tbranch: input.branch,\n\t\t\t\t...(input.target ? { target: input.target } : {}),\n\t\t\t})\n\t\t);\n\t\tprint(` ${style.success(`${record.status} — ${record.url}`)}`);\n\t\treturn { deployment: record, status: \"ok\" };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tprint(` ${style.fail(message)}`);\n\t\treturn { deployment: null, status: \"fail\", message };\n\t}\n}\n","/**\n * `holocron doctor` — load the config, instantiate every capability,\n * print a per-capability readiness report.\n *\n * Each capability gets a smoke check appropriate to its surface:\n * source → `whoami()`\n * issues → `doctor()` (rich report)\n * secrets → `listSecrets({ kind: 'repo' })`\n * ci → `listRuns({ limit: 1 })`\n * others → just \"loaded\" (no smoke endpoint defined yet)\n *\n * Output is plain text via a passed-in `print` function so tests can\n * capture lines without ANSI / spinner noise.\n */\n\nimport type { Auth, Ci, Issues, Secrets, Source, Vault } from \"../capabilities/index.js\";\nimport { CARDINALITY } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport { withSpinner } from \"../ui/progress.js\";\nimport { style } from \"../ui/style.js\";\n\nexport type DoctorPrintLine = (line: string) => void;\n\nexport type DoctorStatus = \"ok\" | \"fail\" | \"skip\";\n\nexport interface DoctorRow {\n\tcapability: string;\n\tprovider: string;\n\tstatus: DoctorStatus;\n\tmessage: string;\n}\n\nexport interface DoctorReport {\n\trows: DoctorRow[];\n\tsummary: { ok: number; fail: number; skip: number };\n}\n\nexport interface RunDoctorInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** Lets tests inject mock plugins; defaults to native dynamic import. */\n\tloader?: PluginLoader;\n\tprint?: DoctorPrintLine;\n}\n\nexport async function runDoctor(input: RunDoctorInput): Promise<DoctorReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait withSpinner(\"Loading plugins…\", () => loader.load());\n\n\tconst rows: DoctorRow[] = [];\n\tconst config = input.loaded.resolved;\n\n\tprint(style.header(`Holocron doctor — ${config.name}`));\n\tprint(style.dim(` config: ${input.loaded.filepath}`));\n\tprint(\"\");\n\n\tfor (const key of loader.loadedKeys()) {\n\t\tconst cardinality = CARDINALITY[key];\n\t\tconst entry = config.providers[key];\n\t\tconst providers =\n\t\t\tentry?.cardinality === \"many\"\n\t\t\t\t? entry.tuples.map((t) => t.provider)\n\t\t\t\t: entry?.cardinality === \"single\"\n\t\t\t\t\t? [entry.tuple.provider]\n\t\t\t\t\t: [];\n\n\t\tif (cardinality === \"many\") {\n\t\t\tconst impls = loader.get(key) as unknown as unknown[];\n\t\t\timpls.forEach((_impl, idx) => {\n\t\t\t\trows.push({\n\t\t\t\t\tcapability: key,\n\t\t\t\t\tprovider: providers[idx] ?? \"?\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"loaded (no smoke check defined for this capability)\",\n\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\tconst impl = loader.get(key) as unknown;\n\t\t\tconst row = await smokeCheck(key, providers[0] ?? \"?\", impl);\n\t\t\trows.push(row);\n\t\t}\n\t}\n\n\t// Render rows\n\tfor (const row of rows) {\n\t\tconst label = `${pad(row.capability, 14)} via ${pad(row.provider, 14)} ${row.message}`;\n\t\tif (row.status === \"ok\") print(` ${style.success(label)}`);\n\t\telse if (row.status === \"fail\") print(` ${style.fail(label)}`);\n\t\telse print(` ${style.dim(`· ${label}`)}`);\n\t}\n\n\tconst summary = rows.reduce(\n\t\t(acc, r) => {\n\t\t\tacc[r.status] += 1;\n\t\t\treturn acc;\n\t\t},\n\t\t{ ok: 0, fail: 0, skip: 0 }\n\t);\n\n\tconst summaryLine = `${summary.ok} ok, ${summary.fail} fail, ${summary.skip} skipped`;\n\tprint(\"\");\n\tprint(summary.fail > 0 ? style.fail(summaryLine) : style.success(summaryLine));\n\n\treturn { rows, summary };\n}\n\n// ── smoke checks ────────────────────────────────────────────────────\n\nasync function smokeCheck(key: string, provider: string, impl: unknown): Promise<DoctorRow> {\n\ttry {\n\t\tswitch (key) {\n\t\t\tcase \"source\": {\n\t\t\t\tconst result = await (impl as Source).whoami();\n\t\t\t\treturn mk(key, provider, \"ok\", `whoami: ${result.login}`);\n\t\t\t}\n\t\t\tcase \"issues\": {\n\t\t\t\tconst report = await (impl as Issues).doctor();\n\t\t\t\treturn mk(\n\t\t\t\t\tkey,\n\t\t\t\t\tprovider,\n\t\t\t\t\t\"ok\",\n\t\t\t\t\t`${report.authedAs} / ${report.projectLabel} (${countResolvedLifecycle(report)})`\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase \"secrets\": {\n\t\t\t\tconst names = await (impl as Secrets).listSecrets({ kind: \"repo\" });\n\t\t\t\treturn mk(key, provider, \"ok\", `repo secrets: ${names.length} configured`);\n\t\t\t}\n\t\t\tcase \"ci\": {\n\t\t\t\tconst runs = await (impl as Ci).listRuns({ limit: 1 });\n\t\t\t\treturn mk(\n\t\t\t\t\tkey,\n\t\t\t\t\tprovider,\n\t\t\t\t\t\"ok\",\n\t\t\t\t\truns.length === 0 ? \"no recent runs\" : `most recent: ${runs[0]!.workflowName} (${runs[0]!.status})`\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase \"vault\": {\n\t\t\t\tconst keys = await (impl as Vault).list();\n\t\t\t\treturn mk(key, provider, \"ok\", `${keys.length} keys available`);\n\t\t\t}\n\t\t\tcase \"auth\": {\n\t\t\t\tconst desc = await (impl as Auth).describe();\n\t\t\t\treturn mk(key, provider, \"ok\", `provider: ${desc.provider}; env keys: ${desc.envKeys.join(\", \")}`);\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn mk(key, provider, \"skip\", \"loaded (no smoke check defined for this capability)\");\n\t\t}\n\t} catch (err) {\n\t\treturn mk(key, provider, \"fail\", err instanceof Error ? err.message : String(err));\n\t}\n}\n\nfunction countResolvedLifecycle(report: Awaited<ReturnType<Issues[\"doctor\"]>>): string {\n\tconst resolved = report.lifecycle.filter((l) => l.resolved).length;\n\treturn `${resolved}/${report.lifecycle.length} lifecycle slots ready`;\n}\n\nfunction mk(capability: string, provider: string, status: DoctorStatus, message: string): DoctorRow {\n\treturn { capability, provider, status, message };\n}\n\nfunction pad(s: string, width: number): string {\n\treturn s.length >= width ? s : s + \" \".repeat(width - s.length);\n}\n","/**\n * `holocron new <type> <name>` — create a GitHub repo from a template and\n * bootstrap it by replacing all template-slug casing variants with the new\n * project name, then generate a `holocron.config.ts` from the answers given\n * during the interactive wizard.\n *\n * Flow:\n * 1. Preflight — verify `gh` CLI is available.\n * 2. Resolve type, name, description, homepage, vault/deployment/agent options.\n * 3. `gh repo create <org>/<name> --template <org>/<type>-template --private --clone`\n * → clones to `<cwd>/<name>/`\n * 4. Detect template slug from cloned package.json.\n * 5. Replace all casing variants of the slug across every text file.\n * 6. Replace `<description>` and `<homepage>` placeholders.\n * 7. Generate and write `holocron.config.ts` based on wizard answers.\n * 8. Commit the patched files (-s for DCO).\n * 9. Unless --no-verify: `pnpm install` in the new repo.\n * 10. Print next steps.\n */\n\nimport { execFileSync, spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\n// ── Public API ────────────────────────────────────────────────────────\n\nexport type VaultProvider = \"doppler\" | \"1password\" | \"infisical\" | \"none\";\nexport type DeploymentProvider = \"vercel\" | \"none\";\nexport type AgentChoice = \"claude\" | \"none\";\nexport type RuntimeEnvironment = \"node\" | \"browser\" | \"universal\" | \"none\";\n\nexport interface RunNewInput {\n\ttype: string;\n\tname: string;\n\tdescription?: string;\n\thomepage?: string;\n\tvaultProvider?: VaultProvider;\n\tvaultProject?: string;\n\tvaultConfig?: string;\n\tdeploymentProvider?: DeploymentProvider;\n\tagent?: AgentChoice;\n\truntimeEnvironment?: RuntimeEnvironment;\n\tprotection?: string;\n\topenSource?: boolean;\n\tusesExternalPackages?: boolean;\n\ttopics?: string[];\n\tskills?: string[];\n\t/** Mark the new repo as a GitHub template repository. */\n\tisTemplate?: boolean;\n\t/** GitHub org that owns both the template and the new repo. Default: \"theholocron\". */\n\torg?: string;\n\t/** GitHub admin token forwarded to `holocron setup` during verify. */\n\ttoken?: string;\n\tdryRun?: boolean;\n\tnoVerify?: boolean;\n\t/** Parent directory where the repo will be cloned. Default: process.cwd(). */\n\tcwd?: string;\n\tprint?: (line: string) => void;\n\t/** Injectable subprocess runner for testing. */\n\texec?: (cmd: string, args: string[], opts: { cwd: string; stdio: \"inherit\"; env?: Record<string, string> }) => void;\n\t/** Injectable file writer for testing. */\n\twriteFile?: (filepath: string, content: string) => void;\n\t/** Injectable file reader for testing (returns utf-8 string). */\n\treadFile?: (filepath: string) => string;\n\t/** Injectable directory walker for testing (returns absolute paths). */\n\twalkFiles?: (dir: string) => string[];\n}\n\nexport interface NewReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n\trepoDir?: string;\n\tfilesPatched?: string[];\n\tmessage?: string;\n}\n\nexport class NewError extends Error {\n\toverride name = \"NewError\";\n}\n\n// ── Case derivation ───────────────────────────────────────────────────\n\nfunction cap(word: string): string {\n\treturn word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();\n}\n\n/**\n * Derive all common casing variants of a kebab-case slug (e.g.\n * \"cli-template\") and map each to the corresponding form of a\n * kebab-case name (e.g. \"my-tool\").\n *\n * Returns search→replacement pairs, deduplicating single-word slugs\n * that would otherwise produce identical entries.\n */\nexport function deriveVariants(slug: string, name: string): Array<[string, string]> {\n\tconst sw = slug.split(\"-\");\n\tconst nw = name.split(\"-\");\n\n\tconst pairs: Array<[string, string]> = [\n\t\t[slug, name],\n\t\t[sw.join(\"_\"), nw.join(\"_\")],\n\t\t[sw.join(\"_\").toUpperCase(), nw.join(\"_\").toUpperCase()],\n\t\t[sw.map(cap).join(\"\"), nw.map(cap).join(\"\")],\n\t\t[sw[0]!.toLowerCase() + sw.slice(1).map(cap).join(\"\"), nw[0]!.toLowerCase() + nw.slice(1).map(cap).join(\"\")],\n\t\t[sw.map(cap).join(\" \"), nw.map(cap).join(\" \")],\n\t];\n\n\tconst seen = new Set<string>();\n\treturn pairs.filter(([s]) => {\n\t\tif (seen.has(s)) return false;\n\t\tseen.add(s);\n\t\treturn true;\n\t});\n}\n\n// ── Input helpers ─────────────────────────────────────────────────────\n\n/** Validate a repo name: must be lowercase kebab-case. Returns `true` on success or an error string. */\nexport function validateRepoName(v: string): true | string {\n\treturn /^[a-z][a-z0-9-]*$/.test(v.trim()) ? true : \"Must be lowercase kebab-case (e.g. my-tool)\";\n}\n\n/** Parse a comma-separated topics string into a trimmed, non-empty array. */\nexport function parseTopics(raw: string | undefined): string[] {\n\treturn raw\n\t\t? String(raw)\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((t) => t.trim())\n\t\t\t\t.filter(Boolean)\n\t\t: [];\n}\n\n// ── Config generation ─────────────────────────────────────────────────\n\nexport interface HolocronConfigOptions {\n\tname: string;\n\ttype: string;\n\torg?: string;\n\tdescription?: string;\n\thomepage?: string;\n\tvaultProvider?: VaultProvider;\n\tvaultProject?: string;\n\tvaultConfig?: string;\n\tdeploymentProvider?: DeploymentProvider;\n\tagent?: AgentChoice;\n\truntimeEnvironment?: RuntimeEnvironment;\n\tprotection?: string;\n\topenSource?: boolean;\n\tusesExternalPackages?: boolean;\n\ttopics?: string[];\n\tskills?: string[];\n}\n\n/**\n * Generate the content of `holocron.config.ts` for a newly-scaffolded repo.\n * Uses the `node()` preset from `@theholocron/holocron-config` as the baseline\n * and layers in the provider/agent choices made during the wizard.\n */\nexport function generateHolocronConfig(opts: HolocronConfigOptions): string {\n\tconst lines: string[] = [\n\t\t`import { defineConfig } from \"@theholocron/cli\";`,\n\t\t`import { node } from \"@theholocron/holocron-config\";`,\n\t\t``,\n\t\t`const { repo, workflows, providers } = node();`,\n\t\t`export default defineConfig({`,\n\t];\n\n\tif (opts.description) lines.push(`\\tdescription: ${JSON.stringify(opts.description)},`);\n\tif (opts.homepage) lines.push(`\\thomepage: ${JSON.stringify(opts.homepage)},`);\n\n\tconst topics = opts.topics?.length ? opts.topics : [];\n\tconst hasRuntimeOverride = opts.runtimeEnvironment != null && opts.runtimeEnvironment !== \"node\";\n\tconst hasFullRepo = opts.org != null;\n\n\tif (hasFullRepo) {\n\t\t// Full explicit repo block when org is known (always the case from the CLI).\n\t\tconst repoName = `${opts.org}/${opts.name}`;\n\t\tlines.push(`\\trepo: {`);\n\t\tlines.push(`\\t\\tname: ${JSON.stringify(repoName)},`);\n\t\tlines.push(`\\t\\tteams: [{ slug: \"gatekeepers\", permission: \"maintain\" }],`);\n\t\tlines.push(`\\t\\ttopics: ${JSON.stringify(topics)},`);\n\t\tlines.push(`\\t\\t...repo,`);\n\t\tif (opts.protection && opts.protection !== \"strict\") {\n\t\t\tlines.push(`\\t\\tprotection: ${JSON.stringify(opts.protection)},`);\n\t\t}\n\t\tconst propParts: string[] = [];\n\t\tif (hasRuntimeOverride) propParts.push(`runtime_environment: ${JSON.stringify(opts.runtimeEnvironment)}`);\n\t\tif (opts.openSource === false) propParts.push(`open_source: false`);\n\t\tif (opts.usesExternalPackages === false) propParts.push(`uses_external_packages: false`);\n\t\tif (propParts.length > 0) {\n\t\t\tlines.push(`\\t\\tproperties: { ...repo.properties, ${propParts.join(\", \")} },`);\n\t\t}\n\t\tlines.push(`\\t},`);\n\t} else if (topics.length > 0 || hasRuntimeOverride) {\n\t\tlines.push(`\\trepo: {`);\n\t\tif (topics.length > 0) lines.push(`\\t\\ttopics: ${JSON.stringify(topics)},`);\n\t\tlines.push(`\\t\\t...repo,`);\n\t\tif (hasRuntimeOverride) {\n\t\t\tlines.push(\n\t\t\t\t`\\t\\tproperties: { ...repo.properties, runtime_environment: ${JSON.stringify(opts.runtimeEnvironment)} },`\n\t\t\t);\n\t\t}\n\t\tlines.push(`\\t},`);\n\t} else {\n\t\tlines.push(`\\trepo,`);\n\t}\n\n\tlines.push(`\\tworkflows,`);\n\n\tconst hasVault = opts.vaultProvider && opts.vaultProvider !== \"none\";\n\tconst hasDeployment = opts.deploymentProvider && opts.deploymentProvider !== \"none\";\n\n\tif (hasVault || hasDeployment) {\n\t\tlines.push(`\\tproviders: {`);\n\t\tlines.push(`\\t\\t...providers,`);\n\t\tif (opts.vaultProvider === \"doppler\") {\n\t\t\tconst proj = JSON.stringify(opts.vaultProject ?? opts.name);\n\t\t\tconst cfg = JSON.stringify(opts.vaultConfig ?? \"dev\");\n\t\t\tlines.push(`\\t\\tvault: [\"doppler\", { project: ${proj}, config: ${cfg} }],`);\n\t\t} else if (opts.vaultProvider === \"1password\") {\n\t\t\tconst vault = JSON.stringify(opts.vaultProject ?? opts.name);\n\t\t\tlines.push(`\\t\\tvault: [\"1password\", { vault: ${vault} }],`);\n\t\t} else if (opts.vaultProvider === \"infisical\") {\n\t\t\tconst proj = JSON.stringify(opts.vaultProject ?? opts.name);\n\t\t\tlines.push(`\\t\\tvault: [\"infisical\", { project: ${proj} }],`);\n\t\t}\n\t\tif (opts.deploymentProvider === \"vercel\") {\n\t\t\tlines.push(`\\t\\tdeployment: \"vercel\",`);\n\t\t}\n\t\tlines.push(`\\t},`);\n\t} else {\n\t\tlines.push(`\\tproviders,`);\n\t}\n\n\tif (opts.agent && opts.agent !== \"none\") {\n\t\tlines.push(`\\tagent: ${JSON.stringify(opts.agent)},`);\n\t}\n\n\tif (opts.skills?.length) {\n\t\tlines.push(`\\tskills: ${JSON.stringify(opts.skills)},`);\n\t}\n\n\tlines.push(`});`);\n\tlines.push(``);\n\n\treturn lines.join(\"\\n\");\n}\n\n// ── File discovery ────────────────────────────────────────────────────\n\nconst SKIP_DIRS = new Set([\".git\", \"node_modules\", \"dist\", \".turbo\"]);\n\nfunction defaultWalkFiles(dir: string): string[] {\n\tconst results: string[] = [];\n\tfor (const entry of readdirSync(dir)) {\n\t\tif (SKIP_DIRS.has(entry)) continue;\n\t\tconst full = path.join(dir, entry);\n\t\tconst stat = statSync(full);\n\t\tif (stat.isDirectory()) results.push(...defaultWalkFiles(full));\n\t\telse if (stat.isFile()) results.push(full);\n\t}\n\treturn results;\n}\n\nfunction isBinary(content: string): boolean {\n\tfor (let i = 0; i < Math.min(content.length, 8000); i++) {\n\t\tif (content.charCodeAt(i) === 0) return true;\n\t}\n\treturn false;\n}\n\n// ── Patching ──────────────────────────────────────────────────────────\n\nfunction patchFiles(\n\tdir: string,\n\tvariants: Array<[string, string]>,\n\tdescription: string | undefined,\n\thomepage: string | undefined,\n\truntimeEnvironment: string | undefined,\n\tprint: (line: string) => void,\n\treadFn: (p: string) => string,\n\twriteFn: (p: string, c: string) => void,\n\twalkFn: (d: string) => string[]\n): string[] {\n\tconst patched: string[] = [];\n\tfor (const filepath of walkFn(dir)) {\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = readFn(filepath);\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tif (isBinary(content)) continue;\n\n\t\tconst original = content;\n\t\tfor (const [search, replacement] of variants) {\n\t\t\tcontent = content.split(search).join(replacement);\n\t\t}\n\t\tif (description !== undefined) {\n\t\t\tcontent = content.split(\"<description>\").join(description);\n\t\t\t// Also replace the content of <!-- holocron:description --> blocks so\n\t\t\t// the README description marker is updated even when the template has\n\t\t\t// real prose rather than a bare <description> placeholder.\n\t\t\tcontent = content.replace(\n\t\t\t\t/(<!-- holocron:description -->)[\\s\\S]*?(<!-- \\/holocron:description -->)/g,\n\t\t\t\t`$1\\n${description}\\n$2`\n\t\t\t);\n\t\t}\n\t\tif (homepage !== undefined) {\n\t\t\tcontent = content.split(\"<homepage>\").join(homepage);\n\t\t}\n\t\tif (runtimeEnvironment !== undefined) {\n\t\t\tcontent = content.split(\"<runtime_environment>\").join(runtimeEnvironment);\n\t\t}\n\t\t// Strip template-only blocks — sections relevant only to the template\n\t\t// repo itself (e.g. \"Getting Started\" scaffolding instructions) that\n\t\t// should not appear in projects generated from the template.\n\t\tcontent = content.replace(\n\t\t\t/\\n?<!-- holocron:template-only -->[\\s\\S]*?<!-- \\/holocron:template-only -->\\n?/g,\n\t\t\t\"\"\n\t\t);\n\n\t\tif (content !== original) {\n\t\t\twriteFn(filepath, content);\n\t\t\tprint(` ✓ ${path.relative(dir, filepath)}`);\n\t\t\tpatched.push(filepath);\n\t\t}\n\t}\n\treturn patched;\n}\n\n// ── Preflight ─────────────────────────────────────────────────────────\n\nfunction preflight(): void {\n\tconst result = spawnSync(\"gh\", [\"--version\"], { encoding: \"utf8\" });\n\tif (result.error != null || result.status !== 0) {\n\t\tthrow new NewError(\"`gh` CLI is not installed or not on PATH. Install it from https://cli.github.com\");\n\t}\n}\n\n// ── Defaults ──────────────────────────────────────────────────────────\n\nfunction defaultExec(\n\tcmd: string,\n\targs: string[],\n\topts: { cwd: string; stdio: \"inherit\"; env?: Record<string, string> }\n): void {\n\texecFileSync(cmd, args, {\n\t\tcwd: opts.cwd,\n\t\tstdio: opts.stdio,\n\t\t...(opts.env && Object.keys(opts.env).length > 0 ? { env: { ...process.env, ...opts.env } } : {}),\n\t});\n}\n\nfunction keychainLookup(key: string): string | undefined {\n\tconst result = spawnSync(\"security\", [\"find-generic-password\", \"-s\", \"com.theholocron.cli\", \"-a\", key, \"-w\"], {\n\t\tencoding: \"utf8\",\n\t});\n\treturn result.status === 0 ? result.stdout?.trim() || undefined : undefined;\n}\n\nfunction defaultReadFile(filepath: string): string {\n\treturn readFileSync(filepath, \"utf-8\");\n}\n\nfunction defaultWriteFile(filepath: string, content: string): void {\n\tmkdirSync(path.dirname(filepath), { recursive: true });\n\twriteFileSync(filepath, content, \"utf-8\");\n}\n\n// ── Orchestrator ──────────────────────────────────────────────────────\n\nexport async function runNew(input: RunNewInput): Promise<NewReport> {\n\tconst cwd = input.cwd ?? process.cwd();\n\tconst org = input.org ?? \"theholocron\";\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst execFn = input.exec ?? defaultExec;\n\tconst readFn = input.readFile ?? defaultReadFile;\n\tconst writeFn = input.writeFile ?? defaultWriteFile;\n\tconst walkFn = input.walkFiles ?? defaultWalkFiles;\n\n\tpreflight();\n\n\tconst templateRepo = `${org}/${input.type}-template`;\n\tconst newRepo = `${org}/${input.name}`;\n\tconst repoDir = path.join(cwd, input.name);\n\n\tif (input.dryRun) {\n\t\tprint(` Would create ${newRepo} from template ${templateRepo}`);\n\t\tprint(` Would clone to ${repoDir}`);\n\t\tprint(` Would patch all casing variants of \"${input.type}-template\" → \"${input.name}\"`);\n\t\tif (input.description) print(` Would replace <description> → \"${input.description}\"`);\n\t\tif (input.homepage) print(` Would replace <homepage> → \"${input.homepage}\"`);\n\t\tif (input.runtimeEnvironment) print(` Would replace <runtime_environment> → \"${input.runtimeEnvironment}\"`);\n\t\tprint(` Would generate holocron.config.ts`);\n\t\treturn { status: \"dry-run\" };\n\t}\n\n\tif (existsSync(repoDir)) {\n\t\tthrow new NewError(`\\`${repoDir}\\` already exists — delete it or pick a different name.`);\n\t}\n\n\tprint(` Creating ${newRepo} from template ${templateRepo}…`);\n\tconst visibility = input.openSource ? \"--public\" : \"--private\";\n\ttry {\n\t\texecFn(\"gh\", [\"repo\", \"create\", newRepo, `--template=${templateRepo}`, visibility, \"--clone\"], {\n\t\t\tcwd,\n\t\t\tstdio: \"inherit\",\n\t\t});\n\t} catch (err) {\n\t\tthrow new NewError(`gh repo create failed: ${err instanceof Error ? err.message : String(err)}`);\n\t}\n\n\tif (input.isTemplate) {\n\t\ttry {\n\t\t\texecFn(\"gh\", [\"repo\", \"edit\", newRepo, \"--template=true\"], { cwd, stdio: \"inherit\" });\n\t\t} catch {\n\t\t\t// non-fatal — template flag can be set manually in repo settings\n\t\t}\n\t}\n\n\t// gh repo create --template does not reliably honor --public/--private on all\n\t// plan/org combinations, so set visibility explicitly after creation.\n\ttry {\n\t\texecFn(\"gh\", [\"repo\", \"edit\", newRepo, `--visibility=${input.openSource ? \"public\" : \"private\"}`], {\n\t\t\tcwd,\n\t\t\tstdio: \"inherit\",\n\t\t});\n\t} catch {\n\t\t// non-fatal — visibility can be changed manually in repo settings\n\t}\n\n\t// Detect template slug from cloned package.json\n\tlet templateSlug = `${input.type}-template`;\n\tconst pkgJsonPath = path.join(repoDir, \"package.json\");\n\tif (existsSync(pkgJsonPath)) {\n\t\ttry {\n\t\t\tconst pkg = JSON.parse(readFn(pkgJsonPath)) as { name?: string };\n\t\t\tif (typeof pkg.name === \"string\") {\n\t\t\t\ttemplateSlug = pkg.name.split(\"/\").at(-1) || templateSlug;\n\t\t\t}\n\t\t} catch {\n\t\t\t// fall back to derived slug\n\t\t}\n\t}\n\n\tprint(` Detected template slug: ${templateSlug}`);\n\tprint(` Patching files…`);\n\n\tconst variants = deriveVariants(templateSlug, input.name);\n\t// Prepend the full org/slug pair so GitHub URLs and scoped package names\n\t// use the correct org. Must come before the slug-only pairs so it takes\n\t// priority — e.g. \"@theholocron/node-template\" becomes \"@<org>/<name>\"\n\t// rather than \"@theholocron/<name>\".\n\tvariants.unshift([`theholocron/${templateSlug}`, `${org}/${input.name}`]);\n\tconst filesPatched = patchFiles(\n\t\trepoDir,\n\t\tvariants,\n\t\tinput.description,\n\t\tinput.homepage,\n\t\tinput.runtimeEnvironment,\n\t\tprint,\n\t\treadFn,\n\t\twriteFn,\n\t\twalkFn\n\t);\n\n\tprint(` ${filesPatched.length} file${filesPatched.length === 1 ? \"\" : \"s\"} patched`);\n\n\t// Always overwrite description and homepage in package.json directly,\n\t// regardless of whether the template used placeholders or real values.\n\tif (input.description !== undefined || input.homepage !== undefined) {\n\t\ttry {\n\t\t\tconst pkg = JSON.parse(readFn(pkgJsonPath)) as Record<string, unknown>;\n\t\t\tif (input.description !== undefined) pkg[\"description\"] = input.description;\n\t\t\tif (input.homepage !== undefined) pkg[\"homepage\"] = input.homepage;\n\t\t\twriteFn(pkgJsonPath, JSON.stringify(pkg, null, 2) + \"\\n\");\n\t\t\tprint(` ✓ package.json (description/homepage)`);\n\t\t} catch {\n\t\t\t// non-fatal — placeholder replacement already covered it\n\t\t}\n\t}\n\n\t// Update the root tsconfig.json \"display\" field by parsing the JSON directly\n\t// rather than relying on a <display_name> placeholder. Templates can use their\n\t// real human-readable display name; we always overwrite it with the title-case\n\t// of the new repo name on scaffolding.\n\tconst displayName = input.name.split(\"-\").map(cap).join(\" \");\n\tconst rootTsconfigPath = path.join(repoDir, \"tsconfig.json\");\n\ttry {\n\t\tconst tsconfig = JSON.parse(readFn(rootTsconfigPath)) as Record<string, unknown>;\n\t\tif (typeof tsconfig[\"display\"] === \"string\") {\n\t\t\ttsconfig[\"display\"] = displayName;\n\t\t\twriteFn(rootTsconfigPath, JSON.stringify(tsconfig, null, 2) + \"\\n\");\n\t\t\tprint(` ✓ tsconfig.json (display)`);\n\t\t}\n\t} catch {\n\t\t// non-fatal — no tsconfig or no display field\n\t}\n\n\t// Generate and write holocron.config.ts\n\tconst configContent = generateHolocronConfig({\n\t\tname: input.name,\n\t\ttype: input.type,\n\t\torg,\n\t\tdescription: input.description,\n\t\thomepage: input.homepage,\n\t\tvaultProvider: input.vaultProvider,\n\t\tvaultProject: input.vaultProject,\n\t\tvaultConfig: input.vaultConfig,\n\t\tdeploymentProvider: input.deploymentProvider,\n\t\tagent: input.agent,\n\t\truntimeEnvironment: input.runtimeEnvironment,\n\t\tprotection: input.protection,\n\t\topenSource: input.openSource,\n\t\tusesExternalPackages: input.usesExternalPackages,\n\t\ttopics: input.topics,\n\t\tskills: input.skills,\n\t});\n\tconst configPath = path.join(repoDir, \"holocron.config.ts\");\n\twriteFn(configPath, configContent);\n\tprint(` Generated holocron.config.ts`);\n\n\texecFn(\"git\", [\"add\", \"-A\"], { cwd: repoDir, stdio: \"inherit\" });\n\texecFn(\"git\", [\"commit\", \"-s\", \"-m\", `chore: bootstrap from ${templateSlug}`], {\n\t\tcwd: repoDir,\n\t\tstdio: \"inherit\",\n\t});\n\n\tif (!input.noVerify) {\n\t\tprint(\"\");\n\t\tprint(\" Installing dependencies…\");\n\t\ttry {\n\t\t\texecFn(\"pnpm\", [\"install\"], { cwd: repoDir, stdio: \"inherit\" });\n\t\t} catch (err) {\n\t\t\tprint(` ✗ pnpm install failed — ${err instanceof Error ? err.message : String(err)}`);\n\t\t\treturn {\n\t\t\t\tstatus: \"fail\",\n\t\t\t\trepoDir,\n\t\t\t\tfilesPatched,\n\t\t\t\tmessage: \"pnpm install failed; inspect output above\",\n\t\t\t};\n\t\t}\n\n\t\tprint(\"\");\n\t\tprint(\" Running holocron setup…\");\n\t\ttry {\n\t\t\tconst setupArgs: string[] = [\"setup\"];\n\t\t\tconst setupEnv: Record<string, string> = {};\n\n\t\t\t// Admin token: drives rulesets, repo settings, workflows, Pages.\n\t\t\t// Prefer the value forwarded via --token; fall back to keychain.\n\t\t\tconst adminToken = input.token ?? keychainLookup(\"github.admin\");\n\t\t\tif (adminToken) setupArgs.push(\"--token\", adminToken);\n\n\t\t\t// Org token: drives team assignments and custom properties.\n\t\t\t// Skip keychain if already in env (subprocess inherits it anyway).\n\t\t\tif (!process.env[\"HOLOCRON_ORG_TOKEN\"]) {\n\t\t\t\tconst orgToken = keychainLookup(\"github.org\");\n\t\t\t\tif (orgToken) setupEnv[\"HOLOCRON_ORG_TOKEN\"] = orgToken;\n\t\t\t}\n\n\t\t\t// Deploy token: drives GitHub Pages configuration.\n\t\t\tif (!process.env[\"HOLOCRON_DEPLOY_TOKEN\"]) {\n\t\t\t\tconst deployToken = keychainLookup(\"github.deploy\");\n\t\t\t\tif (deployToken) setupEnv[\"HOLOCRON_DEPLOY_TOKEN\"] = deployToken;\n\t\t\t}\n\n\t\t\texecFn(\"holocron\", setupArgs, { cwd: repoDir, stdio: \"inherit\", env: setupEnv });\n\t\t} catch {\n\t\t\tprint(\" ✗ holocron setup failed — run it manually after checking your config\");\n\t\t}\n\t}\n\n\tprint(\"\");\n\tprint(` Scaffolded ${newRepo} (${filesPatched.length} file${filesPatched.length === 1 ? \"\" : \"s\"} patched).`);\n\tprint(\"\");\n\tprint(\" Next:\");\n\tprint(` 1. cd ${repoDir}`);\n\tif (input.noVerify) {\n\t\tprint(` 2. pnpm install`);\n\t\tprint(` 3. holocron setup # wire up secrets, teams, labels, etc.`);\n\t\tprint(` 4. git push -u origin HEAD`);\n\t} else {\n\t\tprint(` 2. git push -u origin HEAD`);\n\t}\n\n\treturn { status: \"ok\", repoDir, filesPatched };\n}\n","import { readdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface RunNpmBumpVersionsInput {\n\t/** Next version string (e.g., \"4.2.0\" or \"2.0.0-alpha.1\"). */\n\tversion: string;\n\t/** Working directory (monorepo root). Defaults to process.cwd(). */\n\tcwd?: string;\n\t/** Print what would change without writing anything. */\n\tdryRun?: boolean;\n\tprint?: (line: string) => void;\n\t/** Injectable for testing. */\n\treadFile?: (path: string) => string;\n\twriteFile?: (path: string, content: string) => void;\n\tlistDir?: (path: string) => string[];\n\tisDir?: (path: string) => boolean;\n}\n\nexport type BumpVersionsStatus = \"ok\" | \"fail\" | \"dry-run\";\n\nexport interface NpmBumpVersionsReport {\n\tstatus: BumpVersionsStatus;\n\tbumped: readonly string[];\n\tskipped: readonly string[];\n\tmessage?: string;\n}\n\nexport async function runNpmBumpVersions(input: RunNpmBumpVersionsInput): Promise<NpmBumpVersionsReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst cwd = input.cwd ?? process.cwd();\n\tconst { version, dryRun = false } = input;\n\tconst readFile = input.readFile ?? ((p: string) => readFileSync(p, \"utf8\"));\n\tconst writeFile = input.writeFile ?? ((p: string, c: string) => writeFileSync(p, c));\n\tconst listDir = input.listDir ?? ((p: string) => readdirSync(p) as string[]);\n\tconst isDir = input.isDir ?? ((p: string) => statSync(p).isDirectory());\n\n\tconst bumped: string[] = [];\n\tconst skipped: string[] = [];\n\n\tprint(`Bumping monorepo to ${version}${dryRun ? \" (dry-run)\" : \"\"}…`);\n\n\tfunction bumpFile(absPath: string, label: string): void {\n\t\tlet pkg: Record<string, unknown>;\n\t\ttry {\n\t\t\tpkg = JSON.parse(readFile(absPath)) as Record<string, unknown>;\n\t\t} catch {\n\t\t\tprint(` ✗ could not parse ${label}`);\n\t\t\treturn;\n\t\t}\n\t\tconst old = pkg.version as string;\n\t\tif (!dryRun) {\n\t\t\tpkg.version = version;\n\t\t\twriteFile(absPath, JSON.stringify(pkg, null, 2) + \"\\n\");\n\t\t}\n\t\tprint(` ${dryRun ? \"~\" : \"✓\"} ${label}: ${old} → ${version}`);\n\t\tbumped.push(label);\n\t}\n\n\t// Root is always bumped — private means \"don't publish\", not \"don't version\".\n\tbumpFile(join(cwd, \"package.json\"), \"root\");\n\n\tconst packagesDir = join(cwd, \"packages\");\n\tlet entries: string[];\n\ttry {\n\t\tentries = listDir(packagesDir);\n\t} catch {\n\t\t// No packages/ dir — single-package repo; root bump is sufficient.\n\t\treturn { status: dryRun ? \"dry-run\" : \"ok\", bumped, skipped };\n\t}\n\n\tfor (const entry of entries) {\n\t\tconst pkgDir = join(packagesDir, entry);\n\t\ttry {\n\t\t\tif (!isDir(pkgDir)) continue;\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tconst pkgFile = join(pkgDir, \"package.json\");\n\t\tlet pkg: Record<string, unknown>;\n\t\ttry {\n\t\t\tpkg = JSON.parse(readFile(pkgFile)) as Record<string, unknown>;\n\t\t} catch {\n\t\t\tprint(` ! skipping packages/${entry}: no package.json or malformed JSON`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (pkg.private) {\n\t\t\tprint(` · skipping private package packages/${entry}`);\n\t\t\tskipped.push(`packages/${entry}`);\n\t\t\tcontinue;\n\t\t}\n\t\tbumpFile(pkgFile, `packages/${entry}`);\n\t}\n\n\treturn { status: dryRun ? \"dry-run\" : \"ok\", bumped, skipped };\n}\n","/**\n * `holocron npm publish-initial` — bottles up the chicken-and-egg\n * bootstrap that every new npm-published holocron monorepo hits.\n *\n * npm requires a package to exist before Trusted Publishing can be\n * configured on it. So the first publish has to happen outside the\n * OIDC flow — using either a browser-auth session (`npm login\n * --auth-type=web`) or an ephemeral automation token. This command\n * runs the publish step + tells you exactly what to do next.\n *\n * Workflow:\n *\n * $ npm login --auth-type=web # one-time, browser-based\n * $ pnpm install --frozen-lockfile\n * $ pnpm build\n * $ pnpm exec tsx packages/cli/src/cli.ts npm publish-initial\n *\n * The command itself only handles the publish step + the post-publish\n * Trusted Publisher setup reminder. `pnpm install` + `pnpm build`\n * stay outside the command (no pnpm-inside-pnpm).\n *\n * If `NPM_TOKEN` is detected in env, the command prints a final\n * \"revoke this token at <url>\" reminder — same pattern as `rando vc\n * setup` for the ephemeral GH admin PAT.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type PublishInitialPrint = (line: string) => void;\n\nexport type PublishExecResult = {\n\texitCode: number;\n\tstdout: string;\n\tstderr: string;\n};\n\nexport interface RunNpmPublishInitialInput {\n\t/** Working directory (the monorepo root). Defaults to process.cwd(). */\n\tcwd?: string;\n\t/** Distribution tag for the publish. Defaults to `'alpha'`. */\n\ttag?: string;\n\t/** Skip the actual publish; print what would happen. */\n\tdryRun?: boolean;\n\t/**\n\t * One-time password (TOTP) from your authenticator app. Required if\n\t * your npm account has \"Require 2FA for read and write\" enabled.\n\t * Reused across all 7 sequential publishes — they fire within a few\n\t * seconds, comfortably inside the TOTP window.\n\t */\n\totp?: string;\n\tprint?: PublishInitialPrint;\n\t/**\n\t * Injectable command runner. Defaults to `spawnSync` with\n\t * `stdio: ['inherit', 'pipe', 'pipe']` so interactive prompts\n\t * (e.g., npm OTP) still work.\n\t *\n\t * Returns exit code + captured stdout/stderr.\n\t */\n\texec?: (cmd: string, args: string[], opts: { cwd: string }) => Promise<PublishExecResult>;\n\t/** Env vars; passed in for testability. Defaults to process.env. */\n\tenv?: NodeJS.ProcessEnv;\n\t/**\n\t * Override the list of package names shown in the Trusted Publisher\n\t * next-steps output. Auto-discovered from packages/*\\/package.json\n\t * when omitted.\n\t */\n\tpackages?: readonly string[];\n\t/**\n\t * Override the repo name shown in the Trusted Publisher next-steps\n\t * output. Auto-detected from `git remote get-url origin` when omitted.\n\t */\n\trepoName?: string;\n}\n\nexport type PublishInitialStatus = \"ok\" | \"fail\" | \"dry-run\";\n\nexport interface NpmPublishInitialReport {\n\tstatus: PublishInitialStatus;\n\tmessage?: string;\n\t/** Packages that the publish step targeted. */\n\tpackageNames: readonly string[];\n}\n\nexport async function runNpmPublishInitial(input: RunNpmPublishInitialInput = {}): Promise<NpmPublishInitialReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst cwd = input.cwd ?? process.cwd();\n\tconst tag = input.tag ?? \"alpha\";\n\tconst dryRun = input.dryRun ?? false;\n\tconst otp = input.otp;\n\tconst env = input.env ?? process.env;\n\tconst exec = input.exec ?? defaultExec;\n\n\t// Build the publish args once — shared between dry-run preview and\n\t// the real call so what we print is exactly what we'd run.\n\tconst publishArgs = [\n\t\t\"-r\",\n\t\t\"--filter=./packages/*\",\n\t\t\"publish\",\n\t\t\"--access\",\n\t\t\"public\",\n\t\t\"--no-git-checks\",\n\t\t\"--tag\",\n\t\ttag,\n\t\t...(otp ? [\"--otp\", otp] : []),\n\t];\n\n\tprint(`Holocron npm publish-initial${dryRun ? \" (dry-run)\" : \"\"}`);\n\tprint(` cwd: ${cwd}`);\n\tprint(` tag: ${tag}`);\n\tif (otp) print(` otp: <${otp.length} chars>`);\n\tprint(\"\");\n\n\t// ── 1. Verify npm auth ──────────────────────────────────────────────\n\tprint(\" → verifying npm auth (`npm whoami`)…\");\n\tconst whoami = await exec(\"npm\", [\"whoami\"], { cwd });\n\tif (whoami.exitCode !== 0) {\n\t\tconst message =\n\t\t\t\"npm is not authenticated. Run `npm login --auth-type=web` (browser flow, no token stored) or `npm login`, then re-run this command.\";\n\t\tprint(` ✗ ${message}`);\n\t\tconst packageNames = input.packages ?? discoverPublicPackages(cwd);\n\t\treturn { status: \"fail\", message, packageNames };\n\t}\n\tconst whoamiName = whoami.stdout.trim() || \"<unknown>\";\n\tprint(` ✓ authed as ${whoamiName}`);\n\n\t// ── 2. Resolve dynamic values needed for next-steps ─────────────────\n\tconst packageNames = input.packages ?? discoverPublicPackages(cwd);\n\tconst repoName = input.repoName ?? (await resolveRepoName(cwd, exec));\n\n\t// ── 3. Publish ──────────────────────────────────────────────────────\n\tif (dryRun) {\n\t\tprint(\"\");\n\t\tprint(\" … (dry-run) skipping actual publish\");\n\t\tprint(` would run: pnpm ${publishArgs.join(\" \")}`);\n\t\tprintNextSteps(print, env, packageNames, repoName);\n\t\treturn { status: \"dry-run\", message: \"dry-run — no publish executed\", packageNames };\n\t}\n\n\tprint(\"\");\n\tprint(\" → publishing all public @theholocron/* packages…\");\n\tconst publish = await exec(\"pnpm\", publishArgs, { cwd });\n\tif (publish.exitCode !== 0) {\n\t\tconst message = `publish failed (exit ${publish.exitCode}): ${publish.stderr.trim() || publish.stdout.trim() || \"no output\"}`;\n\t\tprint(` ✗ ${message}`);\n\t\t// Detect EOTP and surface the --otp hint right at the failure.\n\t\tif (publish.stdout.includes(\"EOTP\") || publish.stderr.includes(\"EOTP\")) {\n\t\t\tprint(\"\");\n\t\t\tprint(\" → hint: your npm account requires 2FA for writes. Re-run with `--otp <code>`:\");\n\t\t\tprint(` pnpm exec tsx packages/cli/src/cli.ts npm publish-initial --otp <6-digit-code>`);\n\t\t}\n\t\treturn { status: \"fail\", message, packageNames };\n\t}\n\tprint(\" ✓ publish complete\");\n\n\t// ── 4. Next-step reminders ──────────────────────────────────────────\n\tprintNextSteps(print, env, packageNames, repoName);\n\treturn { status: \"ok\", packageNames };\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nfunction discoverPublicPackages(cwd: string): readonly string[] {\n\tconst packagesDir = join(cwd, \"packages\");\n\tif (!existsSync(packagesDir)) return [];\n\treturn readdirSync(packagesDir, { withFileTypes: true })\n\t\t.filter((e) => e.isDirectory())\n\t\t.flatMap((e) => {\n\t\t\tconst pkgPath = join(packagesDir, e.name, \"package.json\");\n\t\t\tif (!existsSync(pkgPath)) return [];\n\t\t\ttry {\n\t\t\t\tconst pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as {\n\t\t\t\t\tname?: string;\n\t\t\t\t\tprivate?: boolean;\n\t\t\t\t};\n\t\t\t\treturn !pkg.private && pkg.name ? [pkg.name] : [];\n\t\t\t} catch {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t});\n}\n\nasync function resolveRepoName(cwd: string, exec: NonNullable<RunNpmPublishInitialInput[\"exec\"]>): Promise<string> {\n\tconst result = await exec(\"git\", [\"remote\", \"get-url\", \"origin\"], { cwd });\n\tif (result.exitCode !== 0) return \"unknown\";\n\t// Matches both HTTPS (https://github.com/org/repo.git) and\n\t// SSH (git@github.com:org/repo.git) remote URL formats.\n\tconst match = /[/:]([^/:]+?)(?:\\.git)?$/.exec(result.stdout.trim());\n\treturn match?.[1] ?? \"unknown\";\n}\n\nfunction printNextSteps(\n\tprint: PublishInitialPrint,\n\tenv: NodeJS.ProcessEnv,\n\tpackageNames: readonly string[],\n\trepoName: string\n): void {\n\tprint(\"\");\n\tprint(\" → next: configure Trusted Publisher for each package on npm:\");\n\tfor (const name of packageNames) {\n\t\tprint(` https://www.npmjs.com/package/${name}/access`);\n\t}\n\tprint(` Publisher: GitHub Actions Org: theholocron Repo: ${repoName} Workflow: release.yml`);\n\n\tif (env.NPM_TOKEN) {\n\t\tprint(\"\");\n\t\tprint(\" → cleanup: $NPM_TOKEN was used. Revoke it now (no API for self-revoke; UI-only):\");\n\t\tprint(\" https://www.npmjs.com/settings/~/tokens\");\n\t}\n}\n\nconst defaultExec: NonNullable<RunNpmPublishInitialInput[\"exec\"]> = async (cmd, args, opts) => {\n\tconst result = spawnSync(cmd, args, {\n\t\tcwd: opts.cwd,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"inherit\", \"pipe\", \"pipe\"],\n\t});\n\treturn {\n\t\texitCode: result.status ?? -1,\n\t\tstdout: result.stdout ?? \"\",\n\t\tstderr: result.stderr ?? \"\",\n\t};\n};\n","/**\n * Shared input record for every template module.\n *\n * Every template exports `(inputs: TemplateInputs) => string` and reads\n * from this record. Keeping the surface small + typechecked lets the\n * templates stay dumb string builders while the command layer handles\n * normalization + defaulting from user input.\n */\n\nimport type { CapabilityKey } from \"../../capabilities/index.js\";\n\nexport interface TemplateInputs {\n\t/** Package slug — e.g., \"clerk\". Lowercase, kebab-case. */\n\tslug: string;\n\t/** Vendor display name — e.g., \"Clerk\". PascalCase. */\n\tvendorName: string;\n\t/** Vendor slug UPPERCASED — e.g., \"CLERK\". Used for env var names + class prefixes. */\n\tvendorUpper: string;\n\t/** Capability the plugin implements — one of the 14 known keys. */\n\tcapability: CapabilityKey;\n\t/** Capability implementation class name — e.g., \"ClerkAuth\". PascalCase. */\n\tcapabilityClass: string;\n\t/** Holocron-namespaced env var — defaults to `HOLOCRON_<VENDOR_UPPER>_TOKEN`. */\n\ttokenEnv: string;\n\t/** Vendor-native env var — e.g., \"CLERK_SECRET_KEY\". */\n\tvendorEnv: string;\n\t/** REST base URL — e.g., \"https://api.clerk.com/v1\". */\n\tbaseUrl: string;\n\t/** Transport. Only \"rest\" is supported in Phase 1 (spec: #77). */\n\ttransport: \"rest\";\n}\n\n/** Derive the standard defaults from a slug + vendor name. */\nexport function deriveDefaults(input: {\n\tslug: string;\n\tvendorName: string;\n\tcapability: CapabilityKey;\n}): Pick<TemplateInputs, \"vendorUpper\" | \"capabilityClass\" | \"tokenEnv\" | \"transport\"> {\n\tconst vendorUpper = input.slug.toUpperCase().replace(/-/g, \"_\");\n\tconst capability = input.capability;\n\tconst capabilityClass = `${input.vendorName}${capability.charAt(0).toUpperCase() + capability.slice(1)}`;\n\treturn {\n\t\tvendorUpper,\n\t\tcapabilityClass,\n\t\ttokenEnv: `HOLOCRON_${vendorUpper}_TOKEN`,\n\t\ttransport: \"rest\",\n\t};\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `import { AuthError, createResolveToken, type ResolveTokenInput } from \"@theholocron/cli\";\n\nexport { AuthError };\nexport type { ResolveTokenInput };\n\nexport const resolveToken = createResolveToken({\n\\tenvName: \"${inputs.tokenEnv}\",\n\\tvendorEnvName: \"${inputs.vendorEnv}\",\n\\tkeyringService: \"${inputs.slug}\",\n\\terrorMessage:\n\\t\\t\"no ${inputs.vendorName} token found. Pass --token <TOKEN>, set ${inputs.tokenEnv} / ${inputs.vendorEnv}, \" +\n\\t\\t\"or run: holocron auth set ${inputs.slug} <TOKEN>\",\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `import { describe, expect, it } from \"vitest\";\n\nimport { AuthError, resolveToken } from \"../auth.js\";\n\nconst noKeyring = () => null;\n\ndescribe(\"resolveToken\", () => {\n\tit(\"prefers --token over env vars + keyring\", () => {\n\t\texpect(\n\t\t\tresolveToken({\n\t\t\t\tcliToken: \"flag\",\n\t\t\t\tenv: { ${inputs.tokenEnv}: \"hlc\", ${inputs.vendorEnv}: \"vendor\" },\n\t\t\t\tkeyring: () => \"kr\",\n\t\t\t})\n\t\t).toBe(\"flag\");\n\t});\n\n\tit(\"prefers ${inputs.tokenEnv} over ${inputs.vendorEnv}\", () => {\n\t\texpect(\n\t\t\tresolveToken({\n\t\t\t\tenv: { ${inputs.tokenEnv}: \"hlc\", ${inputs.vendorEnv}: \"vendor\" },\n\t\t\t\tkeyring: noKeyring,\n\t\t\t})\n\t\t).toBe(\"hlc\");\n\t});\n\n\tit(\"falls back to ${inputs.vendorEnv} when ${inputs.tokenEnv} is unset\", () => {\n\t\texpect(resolveToken({ env: { ${inputs.vendorEnv}: \"vendor\" }, keyring: noKeyring })).toBe(\"vendor\");\n\t});\n\n\tit(\"falls back to keyring when env vars are unset\", () => {\n\t\texpect(resolveToken({ env: {}, keyring: (p) => (p === \"${inputs.slug}\" ? \"kr\" : null) })).toBe(\"kr\");\n\t});\n\n\tit(\"throws AuthError with a helpful message when nothing is set\", () => {\n\t\ttry {\n\t\t\tresolveToken({ env: {}, keyring: noKeyring });\n\t\t\tthrow new Error(\"should have thrown\");\n\t\t} catch (err) {\n\t\t\texpect(err).toBeInstanceOf(AuthError);\n\t\t\texpect((err as Error).message).toMatch(/${inputs.tokenEnv}/);\n\t\t\texpect((err as Error).message).toMatch(/holocron auth set ${inputs.slug}/);\n\t\t}\n\t});\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst clientClass = `${inputs.vendorName}RestClient`;\n\tconst capabilityInterface = inputs.capability.charAt(0).toUpperCase() + inputs.capability.slice(1);\n\treturn `/**\n * \\`${inputs.capability}\\` capability for ${inputs.vendorName}.\n *\n * Methods are STUBS — implement them against ${inputs.vendorName}'s\n * REST API per the \\`${capabilityInterface}\\` interface contract in\n * \\`@theholocron/cli\\`.\n *\n * TODO once you've stubbed the interface methods, restore the type\n * import + \\`implements\\` clause:\n * import type { ${capabilityInterface} } from \"@theholocron/cli\";\n * export class ${inputs.capabilityClass} implements ${capabilityInterface} { ... }\n */\n\nimport type { ${clientClass} } from \"../rest.js\";\n\nexport class ${inputs.capabilityClass} {\n\treadonly key = \"${inputs.capability}\" as const;\n\treadonly providerName = \"${inputs.slug}\";\n\n\tconstructor(private readonly rest: ${clientClass}) {}\n\n\t// TODO: implement the ${capabilityInterface} interface methods\n\t// (see \\`packages/cli/src/capabilities/index.ts\\`). Each method\n\t// should hit a specific ${inputs.vendorName} REST endpoint via\n\t// \\`this.rest.request(...)\\`. Once methods are stubbed, add\n\t// \\`implements ${capabilityInterface}\\` to the class declaration\n\t// above and remove the \\`as unknown as\\` cast in src/index.ts.\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst clientClass = `${inputs.vendorName}RestClient`;\n\treturn `import { describe, it } from \"vitest\";\n\nimport { ${inputs.capabilityClass} } from \"../capabilities/${inputs.capability}.js\";\nimport { ${clientClass} } from \"../rest.js\";\nimport { stubFetch } from \"./helpers.js\";\n\n// Stub client used by the constructor smoke test. Real capability\n// tests replace this with per-method stubs once implementations land.\nfunction makeCapability() {\n\tconst stub = stubFetch([]);\n\tconst rest = new ${clientClass}({ token: \"t\", fetch: stub.fetch });\n\treturn new ${inputs.capabilityClass}(rest);\n}\n\ndescribe(\"${inputs.capabilityClass}\", () => {\n\tit(\"constructs with a REST client\", () => {\n\t\tmakeCapability();\n\t});\n\n\t// TODO: implement one test per ${inputs.capability} capability method\n\t// as you fill in the class stubs. See other plugins for reference\n\t// patterns:\n\t// - REST behaviors (URL / method / body / query) via \\`stub.calls\\`\n\t// - Error paths via \\`stubFetch([{ status: 4xx, body: {...} }])\\`\n\t// - Idempotency (409 handling for ensure* methods, if applicable)\n\tit.todo(\"implement per-method tests\");\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(_inputs: TemplateInputs): string {\n\treturn `import root from \"../../eslint.config.js\";\n\nexport default [\n\t...root,\n\t{\n\t\tignores: [\"dist/**\", \"coverage/**\"],\n\t},\n];\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(_inputs: TemplateInputs): string {\n\treturn `import { vi, type Mock } from \"vitest\";\n\nexport interface FetchCall {\n\turl: string;\n\tmethod: string;\n\theaders: Record<string, string>;\n\tbody: unknown;\n}\n\nexport interface FetchStub {\n\tfetch: typeof fetch;\n\tcalls: FetchCall[];\n\tmock: Mock;\n}\n\nexport function stubFetch(responses: Array<{ status?: number; body?: unknown; text?: string }>): FetchStub {\n\tconst calls: FetchCall[] = [];\n\tlet i = 0;\n\tconst mock = vi.fn(async (input: string | URL, init?: RequestInit) => {\n\t\tconst url = typeof input === \"string\" ? input : input.toString();\n\t\tconst body = typeof init?.body === \"string\" ? safeJsonParse(init.body) : (init?.body ?? null);\n\t\tcalls.push({\n\t\t\turl,\n\t\t\tmethod: (init?.method ?? \"GET\").toUpperCase(),\n\t\t\theaders: (init?.headers as Record<string, string>) ?? {},\n\t\t\tbody,\n\t\t});\n\t\tconst next = responses[i++] ?? { status: 200, body: {} };\n\t\tconst status = next.status ?? 200;\n\t\tif (status === 204 || status === 205 || status === 304) {\n\t\t\treturn new Response(null, { status });\n\t\t}\n\t\tconst text = next.text ?? (typeof next.body === \"string\" ? next.body : JSON.stringify(next.body ?? {}));\n\t\treturn new Response(text, { status });\n\t});\n\treturn { fetch: mock as unknown as typeof fetch, calls, mock };\n}\n\nfunction safeJsonParse(s: string): unknown {\n\ttry {\n\t\treturn JSON.parse(s);\n\t} catch {\n\t\treturn s;\n\t}\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `import { describe, expect, it } from \"vitest\";\n\nimport { AUTH_HINT, createPlugin } from \"../index.js\";\nimport { stubFetch } from \"./helpers.js\";\n\ndescribe(\"createPlugin\", () => {\n\tit(\"wires the ${inputs.capability} capability against the given fetch + token\", () => {\n\t\tconst stub = stubFetch([]);\n\t\tconst plugin = createPlugin({\n\t\t\tcliToken: \"test-token\",\n\t\t\tfetch: stub.fetch,\n\t\t});\n\t\texpect(plugin.name).toBe(\"@theholocron/holocron-plugin-${inputs.slug}\");\n\t\texpect(typeof plugin.capabilities.${inputs.capability}).toBe(\"function\");\n\t});\n});\n\ndescribe(\"AUTH_HINT\", () => {\n\tit(\"mentions the holocron auth set command\", () => {\n\t\texpect(AUTH_HINT).toMatch(/holocron auth set ${inputs.slug}/);\n\t});\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `{\n \"name\": \"@theholocron/holocron-plugin-${inputs.slug}\",\n \"version\": \"2.0.0-alpha.1\",\n \"description\": \"Holocron plugin for ${inputs.vendorName}. Implements the ${inputs.capability} capability against ${inputs.vendorName}'s REST API, plus exports verifyToken + AUTH_HINT for \\`holocron auth\\`.\",\n \"homepage\": \"https://github.com/theholocron/holocron/tree/main/packages/holocron-plugin-${inputs.slug}#readme\",\n \"bugs\": \"https://github.com/theholocron/holocron/issues\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/theholocron/holocron.git\",\n \"directory\": \"packages/holocron-plugin-${inputs.slug}\"\n },\n \"license\": \"MIT\",\n \"author\": \"Newton Koumantzelis\",\n \"type\": \"module\",\n \"main\": \"./src/index.ts\",\n \"exports\": {\n \".\": \"./src/index.ts\"\n },\n \"scripts\": {\n \"build\": \"tsdown\",\n \"lint\": \"eslint .\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"validate\": \"tsx scripts/validate.mjs\"\n },\n \"peerDependencies\": {\n \"@theholocron/cli\": \"workspace:*\"\n },\n \"devDependencies\": {\n \"@theholocron/cli\": \"workspace:*\",\n \"@theholocron/tsconfig\": \"catalog:\",\n \"@tsconfig/node-lts\": \"catalog:\",\n \"@vitest/coverage-v8\": \"catalog:\",\n \"eslint\": \"catalog:\",\n \"globals\": \"catalog:\",\n \"typescript\": \"catalog:\",\n \"vitest\": \"catalog:\",\n \"tsdown\": \"catalog:\",\n \"tsx\": \"catalog:\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"main\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.mts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.mts\",\n \"import\": \"./dist/index.mjs\",\n \"default\": \"./dist/index.mjs\"\n }\n }\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ]\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst clientClass = `${inputs.vendorName}RestClient`;\n\t// Camel-case capability name is used as the factory function name.\n\tconst capabilityInterface = inputs.capability.charAt(0).toUpperCase() + inputs.capability.slice(1);\n\treturn `/**\n * \\`@theholocron/holocron-plugin-${inputs.slug}\\` — entrypoint.\n *\n * Implements the \\`${inputs.capability}\\` capability against ${inputs.vendorName}'s\n * REST API. Also exports \\`verifyToken\\` + \\`AUTH_HINT\\` for\n * \\`holocron auth\\`. See README for auth + config docs.\n *\n * TODO: once you fill in the ${inputs.capabilityClass} methods and add\n * \\`implements ${capabilityInterface}\\` to the class, add the type import:\n * import type { ${capabilityInterface} } from \"@theholocron/cli\";\n * and set \\`: ${capabilityInterface}\\` as the factory return type below.\n */\n\nimport { resolveToken, type ResolveTokenInput } from \"./auth.js\";\nimport { ${inputs.capabilityClass} } from \"./capabilities/${inputs.capability}.js\";\nimport { ${clientClass} } from \"./rest.js\";\n\nexport interface ${inputs.vendorName}PluginOptions extends ResolveTokenInput {\n\t/** Override base URL for tests. */\n\tbaseUrl?: string;\n\t/** Override \\`fetch\\` for tests. */\n\tfetch?: typeof fetch;\n}\n\nexport interface PluginContext {\n\toptions: ${inputs.vendorName}PluginOptions;\n\trest: ${clientClass};\n}\n\nexport function createContext(options: ${inputs.vendorName}PluginOptions): PluginContext {\n\tconst token = resolveToken(options);\n\tconst restOpts: ConstructorParameters<typeof ${clientClass}>[0] = { token };\n\tif (options.baseUrl !== undefined) restOpts.baseUrl = options.baseUrl;\n\tif (options.fetch !== undefined) restOpts.fetch = options.fetch;\n\treturn {\n\t\toptions,\n\t\trest: new ${clientClass}(restOpts),\n\t};\n}\n\nexport function ${inputs.capability}(ctx: PluginContext) {\n\t// Return type inferred at scaffold time — the class doesn't yet\n\t// \\`implements ${capabilityInterface}\\`. Add the type import + the\n\t// \\`: ${capabilityInterface}\\` annotation once methods are stubbed.\n\treturn new ${inputs.capabilityClass}(ctx.rest);\n}\n\nexport function createPlugin(options: ${inputs.vendorName}PluginOptions) {\n\tconst ctx = createContext(options);\n\treturn {\n\t\tname: \"@theholocron/holocron-plugin-${inputs.slug}\",\n\t\tcapabilities: {\n\t\t\t${inputs.capability}: () => ${inputs.capability}(ctx),\n\t\t},\n\t};\n}\n\n/**\n * One-line hint printed by \\`holocron auth set ${inputs.slug}\\` when no\n * token is supplied or the supplied token is rejected. Edit this to\n * point operators at the specific ${inputs.vendorName} docs path for\n * generating a token.\n */\nexport const AUTH_HINT =\n\t\"generate a ${inputs.vendorName} API token, then run: holocron auth set ${inputs.slug} <TOKEN>\";\n\n// ── Public re-exports ────────────────────────────────────────────────\n\nexport * from \"./auth.js\";\nexport { ${clientClass} } from \"./rest.js\";\nexport { ${inputs.capabilityClass} } from \"./capabilities/${inputs.capability}.js\";\nexport { verifyToken } from \"./verify-token.js\";\nexport type { VerifyTokenResult, VerifyTokenSuccess, VerifyTokenFailure } from \"./verify-token.js\";\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `<!-- editorconfig-checker-disable-file -->\n\n# \\`@theholocron/holocron-plugin-${inputs.slug}\\`\n\n${inputs.vendorName} plugin for [Holocron](../cli). Implements the\n\\`${inputs.capability}\\` capability against [${inputs.vendorName}'s REST API](${inputs.baseUrl}),\nplus exports \\`verifyToken\\` + \\`AUTH_HINT\\` for use by \\`holocron auth\\`.\n\n## Install\n\n\\`\\`\\`bash\npnpm add -D @theholocron/holocron-plugin-${inputs.slug}@alpha\n\\`\\`\\`\n\n## Auth\n\nToken resolution order (matches the standard 4-step precedence set by\n\\`.notes/tech-auth-bootstrap.spec.md\\`):\n\n1. \\`--token <TOKEN>\\` flag on the holocron invocation\n2. \\`${inputs.tokenEnv}\\` env var (preferred — explicit intent)\n3. \\`${inputs.vendorEnv}\\` env var (${inputs.vendorName}-native)\n4. **Keyring** — \\`com.theholocron.cli\\` service, account \\`${inputs.slug}\\`\n5. \\`AuthError\\` naming all four options + the bootstrap hint\n\n## Setup\n\n\\`\\`\\`bash\n# Generate a ${inputs.vendorName} API token (see vendor docs), then:\nholocron auth set ${inputs.slug} <TOKEN>\nholocron auth check ${inputs.slug} # verify\n\\`\\`\\`\n\n## Config\n\n\\`\\`\\`jsonc\n{\n\t\"providers\": {\n\t\t\"${inputs.capability}\": \"${inputs.slug}\",\n\t},\n}\n\\`\\`\\`\n\nPlugin options extend \\`ResolveTokenInput\\` — add whatever ${inputs.vendorName}-\nspecific options you need here (project id, workspace slug, etc.) via\nthe tuple form:\n\n\\`\\`\\`jsonc\n{\n\t\"providers\": {\n\t\t\"${inputs.capability}\": [\"${inputs.slug}\", { \"baseUrl\": \"${inputs.baseUrl}\" }],\n\t},\n}\n\\`\\`\\`\n\n## What's implemented\n\nTODO: fill in as capability methods land.\n\n## Status\n\n**\\`v2.0.0-alpha.1\\`** — scaffolded via \\`holocron plugin create\\`.\nNot yet published; capability methods are stubs.\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst factoryName = `create${inputs.vendorName}RestClient`;\n\treturn `import { createRestClient, type RequestOptions, type RestClient } from \"@theholocron/cli\";\n\nexport type { RequestOptions, RestClient };\n\nexport function ${factoryName}(opts: {\n\\ttoken: string;\n\\tbaseUrl?: string;\n\\tfetch?: typeof fetch;\n}): RestClient {\n\\treturn createRestClient({\n\\t\\tbaseUrl: opts.baseUrl ?? \"${inputs.baseUrl}\",\n\\t\\ttoken: opts.token,\n\\t\\tvendor: \"${inputs.vendorName}\",\n\\t\\tfetch: opts.fetch,\n\\t});\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst factoryName = `create${inputs.vendorName}RestClient`;\n\treturn `import { ProviderApiError } from \"@theholocron/cli\";\nimport { describe, expect, it } from \"vitest\";\n\nimport { ${factoryName} } from \"../rest.js\";\nimport { stubFetch } from \"./helpers.js\";\n\ndescribe(\"${factoryName}\", () => {\n\\tit(\"sends bearer + accept headers and returns the parsed body\", async () => {\n\\t\\tconst stub = stubFetch([{ status: 200, body: { ok: true } }]);\n\\t\\tconst client = ${factoryName}({ token: \"t\", fetch: stub.fetch });\n\\t\\tconst res = await client.request<{ ok: boolean }>(\"/me\");\n\\t\\texpect(res.ok).toBe(true);\n\\t\\texpect(stub.calls[0]?.headers[\"authorization\"]).toBe(\"Bearer t\");\n\\t\\texpect(stub.calls[0]?.headers[\"accept\"]).toBe(\"application/json\");\n\\t});\n\n\\tit(\"serializes body as JSON and sets content-type when present\", async () => {\n\\t\\tconst stub = stubFetch([{ status: 200, body: {} }]);\n\\t\\tconst client = ${factoryName}({ token: \"t\", fetch: stub.fetch });\n\\t\\tawait client.request<unknown>(\"/resource\", { method: \"POST\", body: { name: \"demo\" } });\n\\t\\texpect(stub.calls[0]?.method).toBe(\"POST\");\n\\t\\texpect(stub.calls[0]?.headers[\"content-type\"]).toBe(\"application/json\");\n\\t\\texpect(stub.calls[0]?.body).toEqual({ name: \"demo\" });\n\\t});\n\n\\tit(\"returns undefined on 204\", async () => {\n\\t\\tconst stub = stubFetch([{ status: 204 }]);\n\\t\\tconst client = ${factoryName}({ token: \"t\", fetch: stub.fetch });\n\\t\\texpect(await client.request<unknown>(\"/whatever\")).toBeUndefined();\n\\t});\n\n\\tit(\"throws ProviderApiError with the HTTP status on non-2xx\", async () => {\n\\t\\tconst stub = stubFetch([{ status: 401, body: { messages: [\"invalid\"] } }]);\n\\t\\tconst client = ${factoryName}({ token: \"bad\", fetch: stub.fetch });\n\\t\\tconst err = await client.request<unknown>(\"/me\").catch((e: unknown) => e);\n\\t\\texpect(err).toBeInstanceOf(ProviderApiError);\n\\t\\texpect((err as ProviderApiError).status).toBe(401);\n\\t});\n\n\\tit(\"wraps transport-level failures with status 0\", async () => {\n\\t\\tconst throwing: typeof fetch = async () => { throw new TypeError(\"fetch failed\"); };\n\\t\\tconst client = ${factoryName}({ token: \"t\", fetch: throwing });\n\\t\\tconst err = await client.request<unknown>(\"/me\").catch((e: unknown) => e);\n\\t\\texpect(err).toBeInstanceOf(ProviderApiError);\n\\t\\texpect((err as ProviderApiError).status).toBe(0);\n\\t});\n\n\\tit(\"trims trailing slashes from the base URL\", () => {\n\\t\\tconst client = ${factoryName}({ token: \"t\", baseUrl: \"${inputs.baseUrl}//\" });\n\\t\\texpect(client.baseUrl).toBe(\"${inputs.baseUrl}\");\n\\t});\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\treturn `{\n \"display\": \"Holocron Plugin: ${inputs.vendorName}\",\n \"extends\": \"@tsconfig/node-lts/tsconfig.json\",\n \"compilerOptions\": {\n \"baseUrl\": \"./\",\n \"outDir\": \"./dist\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n },\n \"include\": [\"src/**/*.ts\"],\n \"exclude\": [\"node_modules\", \"dist\"]\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(_inputs: TemplateInputs): string {\n\treturn `import { defineConfig } from \"tsdown\";\n\nexport default defineConfig({\n\tentry: [\"src/index.ts\"],\n\tformat: \"esm\",\n\tdts: true,\n\tclean: true,\n\tdeps: { neverBundle: [/^@theholocron\\\\//] },\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\n/**\n * Scaffolds `scripts/validate.mjs` — a smoke-test the operator runs\n * against a live vendor account to verify the plugin's REST endpoints,\n * auth, and response parsing all work in reality (the unit tests only\n * exercise stubbed HTTP responses). READ-ONLY BY DESIGN.\n *\n * Convention: every plugin ships this script + a matching `validate`\n * entry in `package.json`'s scripts block, so operators run\n * `pnpm --filter @theholocron/holocron-plugin-<slug> validate`.\n * Capability-specific args (project id, workspace, etc.) come from\n * positional command-line arguments; the plugin author fills in the\n * exact shape per their vendor.\n *\n * Includes a `hintFor(message)` helper the operator customizes with\n * vendor-specific \"here's the likely fix\" guidance for common error\n * shapes (401 / 403 / 404 / network / 5xx). Points users at docs and\n * setup steps rather than leaving them staring at a raw stack trace.\n */\nexport function render(inputs: TemplateInputs): string {\n\treturn `#!/usr/bin/env node\n/**\n * Read-only smoke test for @theholocron/holocron-plugin-${inputs.slug} against\n * a live ${inputs.vendorName} account.\n *\n * READ-ONLY BY DESIGN. Never calls write(), or bootstrap methods\n * (\\`ensureProject\\`, \\`ensureEnvironment\\`, etc.). Any ERROR line means\n * the plugin needs adjusting — the \\`hintFor\\` helper below points at\n * the most likely fix per error shape.\n *\n * Auth: reads the ${inputs.vendorName} token from holocron's keyring —\n * you must have run \\`pnpm holocron auth set ${inputs.slug} <TOKEN>\\` first.\n *\n * Usage:\n * pnpm --filter @theholocron/holocron-plugin-${inputs.slug} validate <arg1> [arg2] ...\n *\n * TODO: replace the positional args below with whatever your\n * capability's methods need (e.g., project id, environment slug,\n * secret name). Adapt the test steps to your capability's method\n * surface. Model on \\`packages/holocron-plugin-infisical/scripts/validate.mjs\\`.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars -- filled in by operator\nimport { AuthError, createPlugin, resolveToken, verifyToken } from \"../src/index.ts\";\n\nconst args = process.argv.slice(2);\n\nif (args.length === 0) {\n\tconsole.error(\"usage: pnpm --filter @theholocron/holocron-plugin-${inputs.slug} validate <args>\");\n\tprocess.exit(2);\n}\n\n// Use the plugin's own auth resolution so the validate script honors\n// the same 4-step precedence as the plugin's runtime:\n// --token → ${inputs.tokenEnv} → ${inputs.vendorEnv} → keyring\n// (--token isn't available here since this is a bare Node script;\n// the other three all work.)\nlet token;\ntry {\n\ttoken = resolveToken();\n} catch (err) {\n\tif (err instanceof AuthError) {\n\t\tconsole.error(err.message);\n\t\tconsole.error(\" see: packages/holocron-plugin-${inputs.slug}/README.md#setup\");\n\t\tprocess.exit(2);\n\t}\n\tthrow err;\n}\n\nconsole.log(\"Validating @theholocron/holocron-plugin-${inputs.slug} (READ-ONLY)\");\nconsole.log(\"\");\n\n// ── 1. verifyToken ─────────────────────────────────────────────────\nconsole.log(\"[1/N] verifyToken\");\nconst verifyResult = await verifyToken(token);\nconsole.log(\\` \\${verifyResult.ok ? \"✓\" : \"✗\"} \\${JSON.stringify(verifyResult)}\\`);\nif (!verifyResult.ok) {\n\tconst hint = hintFor(verifyResult.message);\n\tif (hint) console.log(\\` hint: \\${hint}\\`);\n}\nconsole.log(\"\");\n\n// ── 2..N. capability method calls ──────────────────────────────────\n// TODO: implement one \\`runStep\\`-wrapped call per meaningful read-side\n// capability method. Model on the infisical validate.mjs. Never call\n// write / ensure* / other mutating paths.\n//\n// Example:\n// console.log(\"[2/N] vault.list()\");\n// await runStep(async () => {\n// const keys = await vault.list();\n// console.log(\\` ✓ \\${keys.length} secrets\\`);\n// });\n\nconsole.log(\"Done. Fill in capability method calls above before shipping.\");\n\n// ── helpers ────────────────────────────────────────────────────────\n\n/** Wrap a capability call, print ERROR + hint on failure. */\nasync function runStep(body) {\n\ttry {\n\t\tawait body();\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tconsole.log(\\` ✗ ERROR: \\${message}\\`);\n\t\tconst hint = hintFor(message);\n\t\tif (hint) console.log(\\` hint: \\${hint}\\`);\n\t}\n}\n\n/**\n * Point the operator at the most likely fix based on the error shape.\n * Generic defaults below — CUSTOMIZE per your vendor's docs URLs and\n * common permission/config gotchas.\n */\nfunction hintFor(message) {\n\tif (/→ 401/.test(message)) {\n\t\treturn \"token invalid — regenerate per ${inputs.vendorName}'s docs (see README §Setup)\";\n\t}\n\tif (/→ 403/.test(message)) {\n\t\treturn \"token authenticates but lacks scope — check the token/identity has permissions on the resource\";\n\t}\n\tif (/→ 404/.test(message)) {\n\t\treturn \"endpoint or resource not found — verify your positional args match a real resource\";\n\t}\n\tif (/fetch failed|status: 0|network/i.test(message)) {\n\t\treturn \"network error — check the base URL (${inputs.baseUrl}) and connectivity\";\n\t}\n\tif (/→ 5\\\\d\\\\d/.test(message)) {\n\t\treturn \"server error — vendor-side. Retry, and check the vendor's status page if persistent\";\n\t}\n\treturn null;\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(inputs: TemplateInputs): string {\n\tconst clientClass = `${inputs.vendorName}RestClient`;\n\treturn `/**\n * \\`verifyToken\\` — plugin-level export used by \\`holocron auth set\\` +\n * \\`holocron auth check\\`. Hits a lightweight whoami-style endpoint\n * and translates the response into the normalized \\`VerifyTokenResult\\`\n * shape.\n *\n * Kept as a standalone function (not a capability method) so the auth\n * command can call it without initializing the full plugin — plugin\n * construction requires an already-resolved token, which is exactly\n * what we don't have yet at bootstrap time.\n *\n * TODO: replace \\`/me\\` with the ${inputs.vendorName} equivalent of a\n * \"check my token\" endpoint. Common shapes: \\`/user\\`, \\`/whoami\\`,\n * \\`/me\\`, \\`/account\\`.\n */\n\nimport { ${clientClass} } from \"./rest.js\";\n\nexport interface VerifyTokenSuccess {\n\tok: true;\n\tsubject: string;\n}\n\nexport interface VerifyTokenFailure {\n\tok: false;\n\tmessage: string;\n}\n\nexport type VerifyTokenResult = VerifyTokenSuccess | VerifyTokenFailure;\n\ninterface MeResponse {\n\t/** Adjust to whatever ${inputs.vendorName}'s whoami endpoint returns. */\n\tname?: string;\n\temail?: string;\n\tid?: string;\n}\n\nexport interface VerifyTokenOptions {\n\tbaseUrl?: string;\n\tfetch?: typeof fetch;\n}\n\nexport async function verifyToken(token: string, opts: VerifyTokenOptions = {}): Promise<VerifyTokenResult> {\n\tconst restOpts: ConstructorParameters<typeof ${clientClass}>[0] = { token };\n\tif (opts.baseUrl !== undefined) restOpts.baseUrl = opts.baseUrl;\n\tif (opts.fetch !== undefined) restOpts.fetch = opts.fetch;\n\tconst rest = new ${clientClass}(restOpts);\n\ttry {\n\t\tconst me = await rest.request<MeResponse>(\"/me\");\n\t\t// Optional chaining because \\`me\\` is \\`undefined\\` on 204 / empty body.\n\t\tconst subject = me?.email ?? me?.name ?? me?.id ?? \"unknown\";\n\t\treturn { ok: true, subject: \\`user @ \\${subject}\\` };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\treturn { ok: false, message };\n\t}\n}\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(_inputs: TemplateInputs): string {\n\treturn `import { describe, expect, it } from \"vitest\";\n\nimport { verifyToken } from \"../verify-token.js\";\nimport { stubFetch } from \"./helpers.js\";\n\ndescribe(\"verifyToken\", () => {\n\tit(\"returns ok with a subject when /me returns 200\", async () => {\n\t\tconst stub = stubFetch([{ status: 200, body: { email: \"user@example.com\" } }]);\n\t\tconst result = await verifyToken(\"token\", { fetch: stub.fetch });\n\t\texpect(result.ok).toBe(true);\n\t\tif (result.ok) {\n\t\t\texpect(result.subject).toMatch(/user@example.com/);\n\t\t}\n\t});\n\n\tit(\"returns ok:false with the error message on 401\", async () => {\n\t\tconst stub = stubFetch([{ status: 401, body: { messages: [\"Invalid token\"] } }]);\n\t\tconst result = await verifyToken(\"bad\", { fetch: stub.fetch });\n\t\texpect(result.ok).toBe(false);\n\t\tif (!result.ok) {\n\t\t\texpect(result.message).toMatch(/→ 401/);\n\t\t}\n\t});\n\n\tit(\"returns ok:false when the network layer throws\", async () => {\n\t\tconst throwing: typeof fetch = async () => {\n\t\t\tthrow new TypeError(\"network down\");\n\t\t};\n\t\tconst result = await verifyToken(\"t\", { fetch: throwing });\n\t\texpect(result.ok).toBe(false);\n\t\tif (!result.ok) {\n\t\t\texpect(result.message).toMatch(/network down/);\n\t\t}\n\t});\n});\n`;\n}\n","import type { TemplateInputs } from \"../template-inputs.js\";\n\nexport function render(_inputs: TemplateInputs): string {\n\treturn `import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n\ttest: {\n\t\tenvironment: \"node\",\n\t\tglobals: false,\n\t\tcoverage: {\n\t\t\tprovider: \"v8\",\n\t\t\treporter: [\"text\", \"html\", \"json-summary\"],\n\t\t\tinclude: [\"src/**/*.ts\"],\n\t\t\texclude: [\"src/**/__tests__/**\", \"src/**/*.test.ts\", \"src/index.ts\"],\n\t\t\tthresholds: { lines: 0, functions: 0, branches: 0, statements: 0 },\n\t\t},\n\t},\n});\n`;\n}\n","/**\n * `holocron plugin create <slug> <vendor>` — scaffold a new plugin\n * package matching the proven template.\n *\n * Design: see `.notes/tool-plugin-create.spec.md`.\n *\n * Flow:\n * 1. Preflight — verify CWD is a workspace root (pnpm-workspace.yaml\n * + packages/ dir present).\n * 2. Slug collision — packages/holocron-plugin-<slug>/ must not exist.\n * 3. Capability sanity — must be one of the 14 known keys; warn for\n * many-cardinality caps.\n * 4. Generate — for each template, write to\n * packages/holocron-plugin-<slug>/<path>.\n * 5. Verify (unless --no-verify) — runs pnpm install +\n * pnpm --filter <pkg> typecheck lint test.\n * 6. Print next steps.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { CapabilityKey } from \"../../capabilities/index.js\";\nimport { CARDINALITY } from \"../../capabilities/index.js\";\nimport { deriveDefaults, type TemplateInputs } from \"./template-inputs.js\";\nimport { render as renderAuth } from \"./templates/auth.js\";\nimport { render as renderAuthTest } from \"./templates/auth-test.js\";\nimport { render as renderCapability } from \"./templates/capability.js\";\nimport { render as renderCapabilityTest } from \"./templates/capability-test.js\";\nimport { render as renderEslintConfig } from \"./templates/eslint-config.js\";\nimport { render as renderHelpers } from \"./templates/helpers.js\";\nimport { render as renderIndexTest } from \"./templates/index-test.js\";\nimport { render as renderPackageJson } from \"./templates/package-json.js\";\nimport { render as renderPluginIndex } from \"./templates/plugin-index.js\";\nimport { render as renderReadme } from \"./templates/readme.js\";\nimport { render as renderRest } from \"./templates/rest.js\";\nimport { render as renderRestTest } from \"./templates/rest-test.js\";\nimport { render as renderTsconfigJson } from \"./templates/tsconfig-json.js\";\nimport { render as renderTsdownConfig } from \"./templates/tsdown-config.js\";\nimport { render as renderValidateScript } from \"./templates/validate-script.js\";\nimport { render as renderVerifyToken } from \"./templates/verify-token.js\";\nimport { render as renderVerifyTokenTest } from \"./templates/verify-token-test.js\";\nimport { render as renderVitestConfig } from \"./templates/vitest-config.js\";\n\n// ── Public API ──────────────────────────────────────────────────────\n\n// ── Wizard resolver ───────────────────────────────────────────────────\n\nexport interface PluginCreateWizardArgs {\n\tcapability?: string;\n\tvendorEnv?: string;\n\tbaseUrl?: string;\n}\n\nexport interface PluginCreateWizardPrompts {\n\tselectCapability: () => Promise<string>;\n\tinputVendorEnv: () => Promise<string>;\n\tinputBaseUrl: () => Promise<string>;\n}\n\n/**\n * Resolve `capability`, `vendorEnv`, and `baseUrl` from argv or by calling\n * the supplied prompt functions for any that are absent. Extracted from\n * `cli.ts` so the resolution logic is unit-testable.\n */\nexport async function resolvePluginCreateInputs(\n\targs: PluginCreateWizardArgs,\n\tprompts: PluginCreateWizardPrompts\n): Promise<{ capability: CapabilityKey; vendorEnv: string; baseUrl: string }> {\n\tconst capability = (args.capability ?? (await prompts.selectCapability())) as CapabilityKey;\n\tconst vendorEnv = args.vendorEnv ?? (await prompts.inputVendorEnv());\n\tconst baseUrl = args.baseUrl ?? (await prompts.inputBaseUrl());\n\treturn { capability, vendorEnv, baseUrl };\n}\n\n// ── Run input / report ────────────────────────────────────────────────\n\nexport interface RunPluginCreateInput {\n\t/** Package slug, e.g., \"clerk\". Kebab-case. */\n\tslug: string;\n\t/** Vendor display name, e.g., \"Clerk\". PascalCase. */\n\tvendorName: string;\n\t/** Capability the plugin implements — one of the 14 known keys. */\n\tcapability: CapabilityKey;\n\t/** Vendor-native env var, e.g., \"CLERK_SECRET_KEY\". */\n\tvendorEnv: string;\n\t/** REST base URL, e.g., \"https://api.clerk.com/v1\". */\n\tbaseUrl: string;\n\t/** Optional token env override. Defaults to `HOLOCRON_<VENDOR>_TOKEN`. */\n\ttokenEnv?: string;\n\t/** Print steps without writing files. */\n\tdryRun?: boolean;\n\t/** Skip the post-scaffold pnpm install/typecheck/lint/test. */\n\tnoVerify?: boolean;\n\t/** Working directory (workspace root). Defaults to `process.cwd()`. */\n\tcwd?: string;\n\t/** Injection point for tests / dry-run wiring. Defaults to fs write. */\n\twriteFile?: (filepath: string, content: string) => void;\n\t/** Print fn — captures orchestrator output. Defaults to console.log. */\n\tprint?: (line: string) => void;\n\t/** Injectable subprocess runner for testing. Defaults to execFileSync. */\n\texec?: (cmd: string, args: string[], opts: { cwd: string; stdio: \"inherit\" }) => void;\n}\n\nexport interface PluginCreateReport {\n\tstatus: \"ok\" | \"fail\";\n\tpackagePath: string;\n\tfilesWritten: string[];\n\tmessage?: string;\n}\n\nexport class PluginCreateError extends Error {\n\toverride name = \"PluginCreateError\";\n}\n\n// ── Templates registry ──────────────────────────────────────────────\n\ninterface TemplateEntry {\n\t/** Path relative to the plugin package root. */\n\tpath: string;\n\trender: (inputs: TemplateInputs) => string;\n}\n\nconst TEMPLATES: TemplateEntry[] = [\n\t// Config (5)\n\t{ path: \"package.json\", render: renderPackageJson },\n\t{ path: \"tsconfig.json\", render: renderTsconfigJson },\n\t{ path: \"vitest.config.ts\", render: renderVitestConfig },\n\t{ path: \"eslint.config.js\", render: renderEslintConfig },\n\t{ path: \"tsdown.config.ts\", render: renderTsdownConfig },\n\t// Docs (1)\n\t{ path: \"README.md\", render: renderReadme },\n\t// Source (5) — capability path uses the dynamic capability slug.\n\t{ path: \"src/auth.ts\", render: renderAuth },\n\t{ path: \"src/rest.ts\", render: renderRest },\n\t{ path: \"src/verify-token.ts\", render: renderVerifyToken },\n\t{ path: \"src/index.ts\", render: renderPluginIndex },\n\t{ path: \"src/capabilities/{{capability}}.ts\", render: renderCapability },\n\t// Tests (6)\n\t{ path: \"src/__tests__/helpers.ts\", render: renderHelpers },\n\t{ path: \"src/__tests__/auth.test.ts\", render: renderAuthTest },\n\t{ path: \"src/__tests__/rest.test.ts\", render: renderRestTest },\n\t{ path: \"src/__tests__/verify-token.test.ts\", render: renderVerifyTokenTest },\n\t{ path: \"src/__tests__/{{capability}}.test.ts\", render: renderCapabilityTest },\n\t{ path: \"src/__tests__/index.test.ts\", render: renderIndexTest },\n\t// Live-account validation script (1) — read-only smoke test.\n\t{ path: \"scripts/validate.mjs\", render: renderValidateScript },\n];\n\n/** Replace `{{capability}}` in a template path with the actual capability key. */\nfunction resolvePath(template: string, inputs: TemplateInputs): string {\n\treturn template.replace(/\\{\\{capability\\}\\}/g, inputs.capability);\n}\n\n// ── Orchestrator ────────────────────────────────────────────────────\n\nexport function runPluginCreate(input: RunPluginCreateInput): PluginCreateReport {\n\tconst cwd = input.cwd ?? process.cwd();\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst write = input.writeFile ?? defaultWrite;\n\n\tpreflight(cwd);\n\tvalidateSlug(input.slug);\n\tvalidateVendorName(input.vendorName);\n\n\tconst packageDir = path.join(cwd, \"packages\", `holocron-plugin-${input.slug}`);\n\tif (existsSync(packageDir)) {\n\t\tthrow new PluginCreateError(`\\`${packageDir}\\` already exists — edit in place or pick a different slug.`);\n\t}\n\n\tvalidateCapability(input.capability, print);\n\n\tconst derived = deriveDefaults({\n\t\tslug: input.slug,\n\t\tvendorName: input.vendorName,\n\t\tcapability: input.capability,\n\t});\n\tconst inputs: TemplateInputs = {\n\t\tslug: input.slug,\n\t\tvendorName: input.vendorName,\n\t\tvendorUpper: derived.vendorUpper,\n\t\tcapability: input.capability,\n\t\tcapabilityClass: derived.capabilityClass,\n\t\ttokenEnv: input.tokenEnv ?? derived.tokenEnv,\n\t\tvendorEnv: input.vendorEnv,\n\t\t// Normalize: strip trailing slashes so the embedded value in the\n\t\t// generated rest-test.ts matches what the client trims at runtime.\n\t\tbaseUrl: trimTrailingSlashes(input.baseUrl),\n\t\ttransport: derived.transport,\n\t};\n\n\tconst filesWritten: string[] = [];\n\tprint(`Scaffolding @theholocron/holocron-plugin-${inputs.slug}${input.dryRun ? \" (dry-run)\" : \"\"}`);\n\tprint(` → ${packageDir}`);\n\tfor (const template of TEMPLATES) {\n\t\tconst resolvedPath = resolvePath(template.path, inputs);\n\t\tconst filepath = path.join(packageDir, resolvedPath);\n\t\tconst content = template.render(inputs);\n\t\tif (input.dryRun) {\n\t\t\tprint(` … would write ${resolvedPath} (${content.length} bytes)`);\n\t\t} else {\n\t\t\twrite(filepath, content);\n\t\t\tprint(` ✓ ${resolvedPath}`);\n\t\t}\n\t\tfilesWritten.push(resolvedPath);\n\t}\n\n\tif (!input.dryRun && !input.noVerify) {\n\t\tconst execFn = input.exec ?? defaultExec;\n\t\tconst pkg = `@theholocron/holocron-plugin-${inputs.slug}`;\n\t\tprint(\"\");\n\t\tprint(\" Verifying scaffold…\");\n\t\ttry {\n\t\t\texecFn(\"pnpm\", [\"install\", \"--frozen-lockfile=false\"], { cwd, stdio: \"inherit\" });\n\t\t\texecFn(\"pnpm\", [\"--filter\", pkg, \"typecheck\"], { cwd, stdio: \"inherit\" });\n\t\t\texecFn(\"pnpm\", [\"--filter\", pkg, \"lint\"], { cwd, stdio: \"inherit\" });\n\t\t\texecFn(\"pnpm\", [\"--filter\", pkg, \"test\"], { cwd, stdio: \"inherit\" });\n\t\t\tprint(\" ✓ scaffold verified\");\n\t\t} catch (err) {\n\t\t\tprint(` ✗ verify failed — ${err instanceof Error ? err.message : String(err)}`);\n\t\t\treturn {\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tpackagePath: packageDir,\n\t\t\t\tfilesWritten,\n\t\t\t\tmessage: \"post-scaffold verify failed; inspect output above\",\n\t\t\t};\n\t\t}\n\t}\n\n\tif (!input.dryRun) {\n\t\tprintNextSteps(print, inputs);\n\t}\n\n\treturn { status: \"ok\", packagePath: packageDir, filesWritten };\n}\n\n// ── Internals ───────────────────────────────────────────────────────\n\nfunction preflight(cwd: string): void {\n\tif (!existsSync(path.join(cwd, \"pnpm-workspace.yaml\"))) {\n\t\tthrow new PluginCreateError(\n\t\t\t`\\`pnpm-workspace.yaml\\` not found in \\`${cwd}\\`. Run \\`holocron plugin create\\` from the monorepo root.`\n\t\t);\n\t}\n\tif (!existsSync(path.join(cwd, \"packages\"))) {\n\t\tthrow new PluginCreateError(`\\`packages/\\` directory not found in \\`${cwd}\\`.`);\n\t}\n}\n\n/**\n * npm-package-name conventions: kebab-case, starts with lowercase\n * letter. Rejecting numeric-prefixed slugs also sidesteps the\n * `env.HOLOCRON_1FOO_TOKEN` invalid-identifier trap in the auth\n * template.\n */\nconst SLUG_RE = /^[a-z][a-z0-9-]*$/;\n\nfunction validateSlug(slug: string): void {\n\tif (!SLUG_RE.test(slug)) {\n\t\tthrow new PluginCreateError(\n\t\t\t`invalid slug \"${slug}\" — must be kebab-case: lowercase letter followed by lowercase letters, digits, or hyphens. ` +\n\t\t\t\t`Examples: \"clerk\", \"cloud-flare\", \"doppler\".`\n\t\t);\n\t}\n}\n\n/** PascalCase — starts with uppercase, alphanumeric only. */\nconst VENDOR_NAME_RE = /^[A-Z][a-zA-Z0-9]*$/;\n\nfunction validateVendorName(name: string): void {\n\tif (!VENDOR_NAME_RE.test(name)) {\n\t\tthrow new PluginCreateError(\n\t\t\t`invalid vendor name \"${name}\" — must be PascalCase: starts with uppercase, alphanumeric only. ` +\n\t\t\t\t`Examples: \"Clerk\", \"CloudFlare\", \"Doppler\".`\n\t\t);\n\t}\n}\n\n/**\n * Trim trailing slashes with a plain loop (no regex — matches the\n * rest.ts template's own trimming to stay ReDoS-safe under CodeQL).\n */\nfunction trimTrailingSlashes(url: string): string {\n\tlet out = url;\n\twhile (out.endsWith(\"/\")) out = out.slice(0, -1);\n\treturn out;\n}\n\nfunction validateCapability(capability: CapabilityKey, print: (line: string) => void): void {\n\tif (!(capability in CARDINALITY)) {\n\t\tthrow new PluginCreateError(\n\t\t\t`\\`${capability}\\` is not a known capability. See \\`packages/cli/src/capabilities/index.ts\\`.`\n\t\t);\n\t}\n\tif (CARDINALITY[capability] === \"many\") {\n\t\tprint(\n\t\t\t` ! ${capability} is a many-cardinality capability — multiple providers can be active at once. ` +\n\t\t\t\t\"Confirm your config wiring accordingly.\"\n\t\t);\n\t}\n}\n\nfunction defaultWrite(filepath: string, content: string): void {\n\tmkdirSync(path.dirname(filepath), { recursive: true });\n\twriteFileSync(filepath, content, \"utf8\");\n}\n\nfunction defaultExec(cmd: string, args: string[], opts: { cwd: string; stdio: \"inherit\" }): void {\n\texecFileSync(cmd, args, { cwd: opts.cwd, stdio: opts.stdio });\n}\n\nfunction printNextSteps(print: (line: string) => void, inputs: TemplateInputs): void {\n\tprint(\"\");\n\tprint(` Scaffolded @theholocron/holocron-plugin-${inputs.slug} (18 files).`);\n\tprint(\"\");\n\tprint(\" Next:\");\n\tprint(\n\t\t` 1. pnpm install # picks up the workspace package`\n\t);\n\tprint(` 2. pnpm --filter @theholocron/holocron-plugin-${inputs.slug} typecheck # green`);\n\tprint(` 3. pnpm --filter @theholocron/holocron-plugin-${inputs.slug} lint # green`);\n\tprint(\n\t\t` 4. pnpm --filter @theholocron/holocron-plugin-${inputs.slug} test # green (stubs pass, real tests are it.todo)`\n\t);\n\tprint(` 5. Implement ${inputs.capabilityClass} methods in src/capabilities/${inputs.capability}.ts`);\n\tprint(` 6. Replace it.todo(...) with real tests in src/__tests__/${inputs.capability}.test.ts`);\n\tprint(\" 7. Commit + push when capability is functionally complete.\");\n}\n","/**\n * `holocron secret set` — one-shot single-secret push.\n *\n * Complements `holocron secrets sync` (bulk vault → destinations) for\n * ad-hoc scenarios:\n * - Bootstrap secrets (e.g., NPM_TOKEN on theholocron/holocron itself\n * before the rest of the setup exists)\n * - One-off rotations that don't warrant a vault sync\n * - Setting secrets the vault doesn't track\n *\n * Value source resolution (in priority order):\n * 1. Positional `value` argument\n * 2. `--from-stdin` reads from stdin\n * 3. `--from-env <NAME>` reads from the named env var\n * 4. Implicit: env var matching the secret name (e.g., `NPM_TOKEN`)\n *\n * Errors clearly when no value can be sourced.\n */\n\nimport type { Secrets, SecretScope } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\n\nexport type SecretSetPrint = (line: string) => void;\n\nexport interface RunSecretSetInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** Secret name (e.g., `NPM_TOKEN`). */\n\tname: string;\n\t/** Secret value. If absent, resolves via stdin / env. */\n\tvalue?: string;\n\t/** Read from stdin instead of positional or env var. */\n\tfromStdin?: boolean;\n\t/** Read from a specific env var rather than implicit-by-name. */\n\tfromEnv?: string;\n\t/** Defaults to `{ kind: 'repo' }`. */\n\tscope?: SecretScope;\n\tloader?: PluginLoader;\n\tprint?: SecretSetPrint;\n\t/** Lets tests inject a stdin reader. Defaults to reading process.stdin. */\n\treadStdin?: () => Promise<string>;\n}\n\nexport interface SecretSetReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n\tname: string;\n\tscope: SecretScope;\n\tmessage?: string;\n}\n\nexport async function runSecretSet(input: RunSecretSetInput): Promise<SecretSetReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait loader.load();\n\n\tconst dryRun = input.context.dryRun ?? false;\n\tconst scope: SecretScope = input.scope ?? { kind: \"repo\" };\n\n\tif (!loader.has(\"secrets\")) {\n\t\tthrow new Error(\"`secrets` capability is not configured — add a `secrets` provider to holocron.config.json\");\n\t}\n\n\t// Resolve the value to push, surfacing a clear error when none can be sourced.\n\tconst value = await resolveValue(input);\n\tif (!value) {\n\t\tthrow new Error(\n\t\t\t`no value for secret \\`${input.name}\\` — pass it positionally, via --from-stdin, --from-env <NAME>, or set $${input.name} in the environment`\n\t\t);\n\t}\n\n\tprint(`Holocron secret set — ${input.name} (${describeScope(scope)})${dryRun ? \" (dry-run)\" : \"\"}`);\n\n\tif (dryRun) {\n\t\tconst message = `would: secrets.setSecret(${describeScope(scope)}, ${input.name}, <${value.length} chars>)`;\n\t\tprint(` … ${message}`);\n\t\treturn { status: \"dry-run\", name: input.name, scope, message };\n\t}\n\n\ttry {\n\t\tconst secrets = loader.get(\"secrets\") as Secrets;\n\t\tawait secrets.setSecret(scope, input.name, value);\n\t\tprint(` ✓ set ${input.name} via ${secrets.providerName}`);\n\t\treturn { status: \"ok\", name: input.name, scope };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tprint(` ✗ ${message}`);\n\t\treturn { status: \"fail\", name: input.name, scope, message };\n\t}\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nasync function resolveValue(input: RunSecretSetInput): Promise<string | undefined> {\n\tif (input.value) return input.value;\n\tif (input.fromStdin) {\n\t\tconst reader = input.readStdin ?? defaultReadStdin;\n\t\tconst text = await reader();\n\t\treturn text.replace(/\\r?\\n$/, \"\"); // trim trailing newline\n\t}\n\tconst env = process.env;\n\tif (input.fromEnv) {\n\t\treturn env[input.fromEnv];\n\t}\n\t// Implicit: env var with the same name as the secret.\n\treturn env[input.name];\n}\n\nasync function defaultReadStdin(): Promise<string> {\n\tconst chunks: Buffer[] = [];\n\treturn new Promise<string>((resolve, reject) => {\n\t\tprocess.stdin.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n\t\tprocess.stdin.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf8\")));\n\t\tprocess.stdin.on(\"error\", reject);\n\t});\n}\n\nfunction describeScope(scope: SecretScope): string {\n\tif (scope.kind === \"repo\") return \"scope=repo\";\n\tif (scope.kind === \"environment\") return `scope=environment:${scope.name}`;\n\treturn `scope=organization:${scope.name}`;\n}\n","/**\n * `holocron secrets sync` — vault → destinations.\n *\n * Reads a named environment from the configured `vault` (1P\n * Environment / similar) as KEY=VALUE pairs, then fans those values\n * out to the configured destinations:\n *\n * - `secrets` capability (e.g., GH Actions secrets) — repo-scope\n * - `deployment` capability (e.g., Vercel env vars) — per-target\n * - local `.env` file (optional, planned for v5.1 — currently skipped\n * with a soft \"not yet\" note)\n *\n * Per-secret routing rules:\n *\n * - All keys go to `secrets` (CI needs them)\n * - All keys go to `deployment` for each target the caller asks for\n * (defaults: production + preview)\n *\n * The vault MUST implement `readEnvironment(envId)` (optional method).\n * If it doesn't, the command errors with a hint to populate the keys\n * individually via `holocron secret set` (also planned for v5.1).\n */\n\nimport type { Deployment, DeploymentTarget, Secrets, Vault } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport { withSpinner } from \"../ui/progress.js\";\nimport { style } from \"../ui/style.js\";\n\nexport type SyncPrintLine = (line: string) => void;\n\nexport type SyncRowStatus = \"ok\" | \"fail\" | \"dry-run\" | \"skip\";\n\nexport interface SyncRow {\n\tdestination: string;\n\t/** e.g., `target=production` for deployment, `scope=repo` for secrets. */\n\tscope: string;\n\tkey: string;\n\tstatus: SyncRowStatus;\n\tmessage?: string;\n}\n\nexport interface SyncReport {\n\trows: SyncRow[];\n\tsummary: { ok: number; fail: number; skip: number; dryRun: number };\n}\n\nexport interface RunSecretsSyncInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** Vault environment id to read. */\n\tenvironmentId: string;\n\t/** Deployment targets to sync to. Defaults to ['production', 'preview']. */\n\ttargets?: DeploymentTarget[];\n\t/** Vercel project id (or equivalent). Required if `deployment` is loaded. */\n\tprojectId?: string;\n\tloader?: PluginLoader;\n\tprint?: SyncPrintLine;\n}\n\nexport async function runSecretsSync(input: RunSecretsSyncInput): Promise<SyncReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait withSpinner(\"Loading plugins…\", () => loader.load());\n\n\tconst dryRun = input.context.dryRun ?? false;\n\tconst targets = input.targets ?? ([\"production\", \"preview\"] as DeploymentTarget[]);\n\n\tprint(style.header(`Holocron secrets sync — environment ${input.environmentId}${dryRun ? \" (dry-run)\" : \"\"}`));\n\tprint(style.dim(` vault: ${vaultProviderName(loader)}`));\n\tprint(\"\");\n\n\t// ── Read the vault ─────────────────────────────────────────────────\n\tconst vault = loader.get(\"vault\") as Vault;\n\tif (!vault.readEnvironment) {\n\t\tthrow new Error(\n\t\t\t`vault provider (${vault.providerName}) does not implement readEnvironment — sync needs bulk env reads`\n\t\t);\n\t}\n\tconst envVars = await withSpinner(`Reading vault environment ${input.environmentId}…`, () =>\n\t\tvault.readEnvironment!(input.environmentId)\n\t);\n\tconst keys = Object.keys(envVars).sort();\n\tprint(style.step(`read ${keys.length} keys from vault`));\n\tprint(\"\");\n\n\tconst rows: SyncRow[] = [];\n\n\t// ── Push to `secrets` (CI/Actions secrets) ─────────────────────────\n\tif (loader.has(\"secrets\")) {\n\t\tconst secrets = loader.get(\"secrets\") as Secrets;\n\t\tprint(style.step(\"secrets (repo scope)\"));\n\t\tfor (const key of keys) {\n\t\t\trows.push(\n\t\t\t\tawait runRow(`secrets:${secrets.providerName}`, \"scope=repo\", key, dryRun, async () => {\n\t\t\t\t\tawait secrets.setSecret({ kind: \"repo\" }, key, envVars[key]!);\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatRow(rows[rows.length - 1]!));\n\t\t}\n\t}\n\n\t// ── Push to `deployment` (Vercel env vars) ─────────────────────────\n\tif (loader.has(\"deployment\")) {\n\t\tconst deploy = loader.get(\"deployment\") as Deployment;\n\t\tif (!input.projectId) {\n\t\t\tprint(style.step(\"deployment\"));\n\t\t\tconst row: SyncRow = {\n\t\t\t\tdestination: `deployment:${deploy.providerName}`,\n\t\t\t\tscope: \"no projectId\",\n\t\t\t\tkey: \"(all)\",\n\t\t\t\tstatus: \"skip\",\n\t\t\t\tmessage: \"projectId required for deployment env-var sync (pass --project-id)\",\n\t\t\t};\n\t\t\trows.push(row);\n\t\t\tprint(formatRow(row));\n\t\t} else {\n\t\t\tfor (const target of targets) {\n\t\t\t\tprint(style.step(`deployment (target=${target})`));\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\trows.push(\n\t\t\t\t\t\tawait runRow(`deployment:${deploy.providerName}`, `target=${target}`, key, dryRun, async () => {\n\t\t\t\t\t\t\tawait deploy.setEnvVar(input.projectId!, target, key, envVars[key]!);\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tprint(formatRow(rows[rows.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tconst summary = rows.reduce(\n\t\t(acc, r) => {\n\t\t\tif (r.status === \"ok\") acc.ok += 1;\n\t\t\telse if (r.status === \"fail\") acc.fail += 1;\n\t\t\telse if (r.status === \"skip\") acc.skip += 1;\n\t\t\telse if (r.status === \"dry-run\") acc.dryRun += 1;\n\t\t\treturn acc;\n\t\t},\n\t\t{ ok: 0, fail: 0, skip: 0, dryRun: 0 }\n\t);\n\n\tprint(\"\");\n\tconst summaryLine = `${summary.ok} ok, ${summary.fail} fail, ${summary.skip} skipped${\n\t\tdryRun ? `, ${summary.dryRun} would-do` : \"\"\n\t}`;\n\tprint(summary.fail > 0 ? style.fail(summaryLine) : style.success(summaryLine));\n\n\treturn { rows, summary };\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nasync function runRow(\n\tdestination: string,\n\tscope: string,\n\tkey: string,\n\tdryRun: boolean,\n\tbody: () => Promise<void>\n): Promise<SyncRow> {\n\tif (dryRun) {\n\t\treturn { destination, scope, key, status: \"dry-run\" };\n\t}\n\ttry {\n\t\tawait body();\n\t\treturn { destination, scope, key, status: \"ok\" };\n\t} catch (err) {\n\t\treturn {\n\t\t\tdestination,\n\t\t\tscope,\n\t\t\tkey,\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t};\n\t}\n}\n\nfunction formatRow(row: SyncRow): string {\n\tconst detail = row.message ? style.dim(` (${row.message})`) : \"\";\n\tconst label = `${row.key}${detail}`;\n\tif (row.status === \"ok\") return ` ${style.success(label)}`;\n\tif (row.status === \"fail\") return ` ${style.fail(label)}`;\n\tif (row.status === \"dry-run\") return ` ${style.dim(`… ${label}`)}`;\n\treturn ` ${style.dim(`· ${label}`)}`;\n}\n\nfunction vaultProviderName(loader: PluginLoader): string {\n\tif (!loader.has(\"vault\")) return \"<missing>\";\n\treturn (loader.get(\"vault\") as Vault).providerName;\n}\n","version: 2\nupdates:\n - package-ecosystem: npm\n directory: /\n schedule:\n interval: weekly\n commit-message:\n prefix: \"chore(deps)\"\n prefix-development: \"chore(deps-dev)\"\n groups:\n security-patches:\n applies-to: security-updates\n patterns:\n - \"*\"\n all-dependencies:\n update-types:\n - minor\n - patch\n\n - package-ecosystem: github-actions\n directory: /\n schedule:\n interval: weekly\n commit-message:\n prefix: \"chore(deps)\"\n groups:\n all-actions:\n patterns:\n - \"*\"\n","name: Audit\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\npermissions:\n contents: read\n\njobs:\n audit:\n uses: theholocron/.github/.github/workflows/audit.yml@main\n secrets: inherit\n","name: Bookkeeping\n\non: # yamllint disable-line rule:truthy\n pull_request:\n types:\n - opened\n - edited\n\npermissions:\n contents: read\n issues: write\n pull-requests: write\n\njobs:\n bookkeeping:\n uses: theholocron/.github/.github/workflows/bookkeeping.yml@main\n secrets: inherit\n","name: CodeQL\n\non: # yamllint disable-line rule:truthy\n push:\n branches:\n - main\n pull_request:\n branches:\n - main\n schedule:\n - cron: \"0 0 * * 1\"\n\npermissions:\n actions: read\n contents: read\n security-events: write\n\njobs:\n codeql:\n uses: theholocron/.github/.github/workflows/codeql.yml@main\n secrets: inherit\n","name: Dependencies\n\non: # yamllint disable-line rule:truthy\n pull_request:\n\npermissions:\n contents: write\n pull-requests: write\n\njobs:\n dependencies:\n uses: theholocron/.github/.github/workflows/dependencies.yml@main\n secrets: inherit\n","name: Deploy\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main]\n workflow_dispatch:\n\nconcurrency:\n group: pages\n cancel-in-progress: false\n\npermissions:\n contents: read\n pages: write\n id-token: write\n\njobs:\n deploy:\n name: Deploy\n uses: theholocron/.github/.github/workflows/deploy.yml@main\n secrets: inherit\n","name: Greetings\n\non: # yamllint disable-line rule:truthy\n pull_request:\n issues:\n\npermissions:\n issues: write\n pull-requests: write\n\njobs:\n greetings:\n uses: theholocron/.github/.github/workflows/greetings.yml@main\n secrets: inherit\n","name: Lint\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\nconcurrency:\n group: lint-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: write\n issues: write\n statuses: write\n\njobs:\n lint:\n name: Lint\n uses: theholocron/.github/.github/workflows/lint.yml@main\n secrets: inherit\n with:\n enable-auto-commit: true\n","name: Post-release Sync\n\non: # yamllint disable-line rule:truthy\n release:\n types: [published]\n\npermissions:\n contents: read\n\njobs:\n broadcast:\n name: Post-release Sync\n uses: theholocron/.github/.github/workflows/post-release.yml@main\n secrets: inherit\n","name: Release\n\non: # yamllint disable-line rule:truthy\n push:\n branches:\n - main\n - alpha\n workflow_dispatch:\n\npermissions:\n contents: write\n id-token: write\n issues: write\n pull-requests: write\n\nconcurrency:\n group: ${{ github.workflow }}-${{ github.ref }}\n cancel-in-progress: false\n\njobs:\n release:\n uses: theholocron/.github/.github/workflows/release.yml@main\n secrets: inherit\n","name: Review\n\non: # yamllint disable-line rule:truthy\n pull_request:\n\nconcurrency:\n group: review-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n checks: write\n pull-requests: write\n\njobs:\n review:\n name: Review\n uses: theholocron/.github/.github/workflows/review.yml@main\n secrets: inherit\n","name: Stale\n\non: # yamllint disable-line rule:truthy\n schedule:\n - cron: \"30 1 * * *\"\n\npermissions:\n contents: write\n issues: write\n pull-requests: write\n\njobs:\n stale:\n uses: theholocron/.github/.github/workflows/stale.yml@main\n secrets: inherit\n","name: Sync\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main]\n paths:\n - holocron.config.ts\n - package.json\n - pnpm-workspace.yaml\n workflow_dispatch:\n inputs:\n steps:\n description: \"Sync steps to run (default: all)\"\n type: string\n required: false\n\nconcurrency:\n group: sync-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: write\n pull-requests: write\n\njobs:\n sync:\n name: Sync\n uses: theholocron/.github/.github/workflows/sync.yml@main\n with:\n steps: ${{ inputs.steps }}\n secrets: inherit\n","name: Test\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\nconcurrency:\n group: test-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n id-token: write\n statuses: write\n\njobs:\n test:\n name: Test\n uses: theholocron/.github/.github/workflows/test.yml@main\n with:\n run-unit: true\n secrets: inherit\n","name: Typecheck\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\nconcurrency:\n group: typecheck-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n\njobs:\n typecheck:\n name: Typecheck\n uses: theholocron/.github/.github/workflows/typecheck.yml@main\n secrets: inherit\n","/**\n * Thin workflow wrapper templates for `holocron setup`.\n *\n * Each entry is a complete `.github/workflows/<name>.yml` that delegates\n * to the corresponding reusable `ci-<name>.yml` in `theholocron/.github`.\n * Files are overwritten on each setup run — they are generated artifacts.\n */\n\nexport { default as DEPENDABOT_CONFIG } from \"./dependabot.yml\";\n\nimport auditYml from \"./workflows/audit.yml\";\nimport bookkeepingYml from \"./workflows/bookkeeping.yml\";\nimport codeqlYml from \"./workflows/codeql.yml\";\nimport dependenciesYml from \"./workflows/dependencies.yml\";\nimport deployYml from \"./workflows/deploy.yml\";\nimport greetingsYml from \"./workflows/greetings.yml\";\nimport lintYml from \"./workflows/lint.yml\";\nimport postReleaseYml from \"./workflows/post-release.yml\";\nimport releaseYml from \"./workflows/release.yml\";\nimport reviewYml from \"./workflows/review.yml\";\nimport staleYml from \"./workflows/stale.yml\";\nimport syncYml from \"./workflows/sync.yml\";\nimport testYml from \"./workflows/test.yml\";\nimport typecheckYml from \"./workflows/typecheck.yml\";\n\n/**\n * Header prepended to every auto-generated workflow thin caller.\n *\n * Used by both `holocron setup` (initial creation) and `holocron sync-github`\n * (subsequent updates) so the header is always identical regardless of which\n * command last wrote the file.\n *\n * @param source - path within theholocron/holocron that owns the template\n * @param forPrimary - true only when writing to theholocron/.github itself\n */\nexport function workflowHeader(source = \"packages/cli/src/commands/setup-workflows.ts\", forPrimary = false): string {\n\tconst doNotEdit = forPrimary\n\t\t? `# AUTO-GENERATED — do not edit in theholocron/.github directly.`\n\t\t: `# AUTO-GENERATED — do not edit directly.`;\n\treturn [\n\t\tdoNotEdit,\n\t\t`# Source: theholocron/holocron · ${source}`,\n\t\t`# Tool: holocron sync-github`,\n\t\t`# Changes: edit source in theholocron/holocron and push to alpha or main.`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\nexport function scaffoldHeader(source = \"packages/cli/src/commands/setup.ts\"): string {\n\treturn [\n\t\t`# Scaffolded by holocron setup — edit this file freely.`,\n\t\t`# Source: theholocron/holocron · ${source}`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\nexport const WORKFLOW_TEMPLATES: Record<string, string> = {\n\tlint: lintYml,\n\ttest: testYml,\n\ttypecheck: typecheckYml,\n\tcodeql: codeqlYml,\n\treview: reviewYml,\n\t\"post-release\": postReleaseYml,\n\trelease: releaseYml,\n\tstale: staleYml,\n\tsync: syncYml,\n\tgreetings: greetingsYml,\n\tdependencies: dependenciesYml,\n\tbookkeeping: bookkeepingYml,\n\taudit: auditYml,\n\tdeploy: deployYml,\n};\n\nexport const KNOWN_WORKFLOWS = new Set(Object.keys(WORKFLOW_TEMPLATES));\n\n/**\n * GitHub check context name each CI workflow produces on a PR.\n *\n * The format is \"{caller-workflow-name} / {reusable-job-name}\". The caller\n * job's own `name:` field does NOT appear in the external check name — only\n * the calling workflow's top-level `name:` and the inner reusable-workflow\n * job name matter. Only workflows that gate merges are listed here.\n */\nexport const WORKFLOW_CHECK_CONTEXTS: Partial<Record<string, string>> = {\n\tlint: \"Lint / Lint entire codebase\",\n\ttest: \"Test / Run tests and collect coverage\",\n\ttypecheck: \"Typecheck / tsc --noEmit\",\n};\n\n/**\n * Generate the thin caller content for a workflow, optionally injecting or\n * merging `with:` overrides into the jobs block.\n *\n * Two strategies are used depending on the template:\n * - Templates that already have a `with:` block (e.g. lint):\n * the override entries are merged in, replacing existing keys and appending\n * new ones.\n * - Templates that end with ` secrets: inherit`: a new `with:` block is\n * injected immediately before `secrets: inherit`.\n * If neither pattern matches the template, a warning is emitted and the\n * base template is returned unchanged.\n */\nexport function generateThinCallerContent(\n\tname: string,\n\twithOverrides?: Record<string, unknown>,\n\tadditionalPaths?: string[]\n): string {\n\tconst base = WORKFLOW_TEMPLATES[name];\n\tif (!base) return \"\";\n\n\t// YAML treats bare [ and { as sequence/mapping nodes; single-quote them so\n\t// values like JSON arrays are kept as strings.\n\tconst yamlScalar = (v: unknown): string => {\n\t\tif (v === true) return \"true\";\n\t\tif (v === false) return \"false\";\n\t\tconst s = String(v);\n\t\treturn s.startsWith(\"[\") || s.startsWith(\"{\") ? `'${s}'` : s;\n\t};\n\tconst fmt = (k: string, v: unknown) => ` ${k}: ${yamlScalar(v)}`;\n\n\tlet result = base;\n\n\t// Append extra push.paths entries after an existing paths: block (deduplicating), or\n\t// insert a fresh paths: block after `branches: [main]` when the template has none.\n\tif (additionalPaths && additionalPaths.length > 0) {\n\t\tconst pathsBlockRe = /( {4}paths:\\n)((?:[ ]{6}- [^\\n]+\\n)+)/;\n\t\tif (pathsBlockRe.test(result)) {\n\t\t\tresult = result.replace(pathsBlockRe, (_, header, existing) => {\n\t\t\t\tconst existingPaths = new Set([...existing.matchAll(/- (.+)/g)].map((m) => m[1]));\n\t\t\t\tconst newEntries = additionalPaths\n\t\t\t\t\t.filter((p) => !existingPaths.has(p))\n\t\t\t\t\t.map((p) => ` - ${p}\\n`)\n\t\t\t\t\t.join(\"\");\n\t\t\t\treturn header + existing + newEntries;\n\t\t\t});\n\t\t} else {\n\t\t\tconst pathsBlock = ` paths:\\n${additionalPaths.map((p) => ` - ${p}\\n`).join(\"\")}`;\n\t\t\tresult = result.replace(/( {4}branches: \\[main\\]\\n)/, `$1${pathsBlock}`);\n\t\t}\n\t}\n\n\tif (!withOverrides || Object.keys(withOverrides).length === 0) return result;\n\n\t// If the template already has a with: block, merge overrides into it.\n\t// Existing keys are replaced; new keys are appended.\n\tconst withBlockRe = /( {4}with:\\n)((?:[ ]{6}[^\\n]+\\n)*)/;\n\tconst existingMatch = result.match(withBlockRe);\n\tif (existingMatch) {\n\t\tconst existingEntries = new Map(\n\t\t\texistingMatch[2]\n\t\t\t\t.split(\"\\n\")\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.map((line) => {\n\t\t\t\t\tconst m = line.match(/^ {6}([^:]+):\\s*(.*)/);\n\t\t\t\t\treturn m ? ([m[1].trim(), m[2].trim()] as [string, string]) : null;\n\t\t\t\t})\n\t\t\t\t.filter((e): e is [string, string] => e !== null)\n\t\t);\n\t\tfor (const [k, v] of Object.entries(withOverrides)) {\n\t\t\texistingEntries.set(k, yamlScalar(v));\n\t\t}\n\t\tconst merged = [...existingEntries.entries()].map(([k, v]) => ` ${k}: ${v}`).join(\"\\n\");\n\t\treturn result.replace(withBlockRe, ` with:\\n${merged}\\n`);\n\t}\n\n\t// No existing with: block — inject before ` secrets: inherit` at end.\n\tconst withBlock = Object.entries(withOverrides)\n\t\t.map(([k, v]) => fmt(k, v))\n\t\t.join(\"\\n\");\n\tconst injected = result.replace(/ {4}secrets: inherit\\n$/, ` with:\\n${withBlock}\\n secrets: inherit\\n`);\n\tif (injected === result) {\n\t\tconsole.warn(`[generateThinCallerContent] could not inject with: overrides into \"${name}\" template`);\n\t}\n\treturn injected;\n}\n\nexport interface PreviewConfig {\n\t/** Cloudflare Pages project name shared across all repos for previews. */\n\tproject: string;\n\t/**\n\t * Base domain for preview URLs (e.g. `\"preview.theholocron.dev\"`).\n\t * When set, `holocron setup` automatically provisions:\n\t * - Cloudflare Pages custom domain `*.<domain>` on the project\n\t * - DNS wildcard CNAME `*.<domain>` → `<project>.pages.dev`\n\t *\n\t * Preview URLs resolve as `<repo>-pr-<n>.<domain>`.\n\t */\n\tdomain?: string;\n}\n\n/** Org-level context used to derive preview defaults from `preview: true`. */\nexport interface OrgContext {\n\t/** GitHub org name — becomes the prefix of the default project: `<org>-preview`. */\n\torg?: string;\n\t/** Org canonical domain — becomes `preview.<domain>` for the default preview domain. */\n\tdomain?: string;\n\t/** Project name — injected as the `name` input to the deploy reusable when `docs: true`. */\n\trepoName?: string;\n}\n\n/**\n * Extract the Cloudflare Pages preview config from a deploy workflow's `with:` object.\n *\n * Accepts three forms:\n * - `preview: true` — derive both project and domain from org context\n * - `preview: { project: \"...\" }` — explicit project; domain derived from context if omitted\n * - `preview: { project: \"...\", domain: \"...\" }` — fully explicit\n *\n * Returns null when `preview:` is absent, false, or can't be resolved.\n */\nexport function extractPreviewConfig(raw: Record<string, unknown>, ctx: OrgContext = {}): PreviewConfig | null {\n\tconst preview = raw[\"preview\"];\n\tif (!preview) return null;\n\n\t// preview: true — derive both values from org context\n\tif (preview === true) {\n\t\tconst project = ctx.org ? `${ctx.org}-preview` : null;\n\t\tconst domain = ctx.domain ? `preview.${ctx.domain}` : undefined;\n\t\tif (!project) return null;\n\t\treturn { project, ...(domain ? { domain } : {}) };\n\t}\n\n\tif (typeof preview !== \"object\") return null;\n\tconst p = preview as Record<string, unknown>;\n\n\tconst project =\n\t\ttypeof p[\"project\"] === \"string\" && p[\"project\"] ? p[\"project\"] : ctx.org ? `${ctx.org}-preview` : null;\n\tif (!project) return null;\n\n\tconst domain =\n\t\ttypeof p[\"domain\"] === \"string\" && p[\"domain\"] ? p[\"domain\"] : ctx.domain ? `preview.${ctx.domain}` : undefined;\n\n\treturn { project, ...(domain ? { domain } : {}) };\n}\n\n/**\n * Generate the full thin-caller YAML for a `deploy.yml` that handles both\n * production (push to main → GitHub Pages) and preview (pull_request →\n * Cloudflare Pages) in a single file.\n *\n * Both jobs receive the same docs/storybook `with:` inputs. If the per-repo\n * config supplies `cloudflare-project` it is forwarded; otherwise the reusable\n * falls back to the `CLOUDFLARE_PAGES_PROJECT` org variable — set that once and\n * all repos with a `deploy` workflow get previews without per-repo config.\n */\nexport function generateCombinedDeployContent(\n\tdeployWith: Record<string, unknown>,\n\tpaths: string[],\n\tpreview: Pick<PreviewConfig, \"project\">\n): string {\n\tconst yamlScalar = (v: unknown): string => {\n\t\tif (v === true) return \"true\";\n\t\tif (v === false) return \"false\";\n\t\tconst s = String(v);\n\t\treturn s.startsWith(\"[\") || s.startsWith(\"{\") ? `'${s}'` : s;\n\t};\n\tconst withLines = (entries: Record<string, unknown>) =>\n\t\tObject.entries(entries)\n\t\t\t.map(([k, v]) => ` ${k}: ${yamlScalar(v)}`)\n\t\t\t.join(\"\\n\");\n\n\tconst pathsBlock = paths.length > 0 ? ` paths:\\n${paths.map((p) => ` - ${p}\\n`).join(\"\")}` : \"\";\n\n\tconst previewWith = { ...deployWith, \"cloudflare-project\": preview.project };\n\n\tconst deployWithBlock = Object.keys(deployWith).length > 0 ? ` with:\\n${withLines(deployWith)}\\n` : \"\";\n\t// previewWith always has at least cloudflare-project, so the block is never empty.\n\tconst previewWithBlock = ` with:\\n${withLines(previewWith)}\\n`;\n\n\tconst cleanupWithBlock = ` with:\\n cloudflare-project: ${preview.project}`;\n\n\treturn [\n\t\t`name: Deploy`,\n\t\t``,\n\t\t`on: # yamllint disable-line rule:truthy`,\n\t\t` push:`,\n\t\t` branches: [main]`,\n\t\t...(pathsBlock ? [`${pathsBlock}`] : []),\n\t\t` pull_request:`,\n\t\t` branches: [main]`,\n\t\t` types: [opened, synchronize, reopened, closed]`,\n\t\t...(pathsBlock ? [`${pathsBlock}`] : []),\n\t\t` workflow_dispatch:`,\n\t\t``,\n\t\t`concurrency:`,\n\t\t` group: $\\{{ github.event_name == 'pull_request' && format('deploy-preview-{0}', github.event.pull_request.number) || 'pages' }}`,\n\t\t` cancel-in-progress: $\\{{ github.event_name == 'pull_request' && github.event.action != 'closed' }}`,\n\t\t``,\n\t\t`permissions:`,\n\t\t` contents: read`,\n\t\t` deployments: write`,\n\t\t` pages: write`,\n\t\t` id-token: write`,\n\t\t` pull-requests: write`,\n\t\t``,\n\t\t`jobs:`,\n\t\t` deploy:`,\n\t\t` name: Deploy`,\n\t\t` if: \\${{ github.event_name != 'pull_request' }}`,\n\t\t` uses: theholocron/.github/.github/workflows/deploy.yml@main`,\n\t\t...(deployWithBlock ? [deployWithBlock.trimEnd()] : []),\n\t\t` secrets: inherit`,\n\t\t``,\n\t\t` preview:`,\n\t\t` name: Deploy Preview`,\n\t\t` if: \\${{ github.event_name == 'pull_request' && github.event.action != 'closed' }}`,\n\t\t` uses: theholocron/.github/.github/workflows/deploy-preview.yml@main`,\n\t\tpreviewWithBlock.trimEnd(),\n\t\t` secrets: inherit`,\n\t\t``,\n\t\t` cleanup:`,\n\t\t` name: Clean up Preview`,\n\t\t` if: \\${{ github.event_name == 'pull_request' && github.event.action == 'closed' }}`,\n\t\t` uses: theholocron/.github/.github/workflows/cleanup-preview.yml@main`,\n\t\tcleanupWithBlock,\n\t\t` secrets: inherit`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\n/**\n * Expand structured with-values to flat GitHub Actions inputs before\n * generating the thin caller. Handles:\n * - deploy shorthand: docs/storybook → type + storybook-projects\n * - preview: stripped (handled separately via extractPreviewConfig)\n * - run-chromatic object → run-chromatic: true + chromatic-projects\n * - plain arrays → JSON-stringified for YAML scalar quoting\n *\n * Used by both `holocron setup` and `sync-workflow-templates`.\n */\nexport function normalizeWorkflowWith(raw: Record<string, unknown>, repoName?: string): Record<string, unknown> {\n\tconst result = { ...raw };\n\tdelete result[\"preview\"];\n\n\tconst hasDocs = raw[\"docs\"] === true || (raw[\"docs\"] !== null && typeof raw[\"docs\"] === \"object\");\n\tconst storybookProjects = raw[\"storybook\"];\n\tif (hasDocs) {\n\t\tresult[\"type\"] = \"docs\";\n\t\tdelete result[\"docs\"];\n\t\t// Derive the `name` input (selects @theholocron/<name>-site) from caller context\n\t\t// when not already set explicitly in the config.\n\t\tif (!result[\"name\"] && repoName) result[\"name\"] = repoName;\n\t}\n\tif (Array.isArray(storybookProjects)) {\n\t\tif (!hasDocs) result[\"type\"] = \"storybook\";\n\t\tresult[\"storybook-projects\"] = JSON.stringify(\n\t\t\t(storybookProjects as Array<{ name: string; path?: string }>).map(({ name, path = \".\" }) => ({\n\t\t\t\tname,\n\t\t\t\tworkingDir: path,\n\t\t\t}))\n\t\t);\n\t\tdelete result[\"storybook\"];\n\t}\n\n\tconst runChromatic = raw[\"run-chromatic\"];\n\tif (runChromatic !== null && typeof runChromatic === \"object\" && \"projects\" in runChromatic) {\n\t\tresult[\"run-chromatic\"] = true;\n\t\tconst projects = (runChromatic as { projects: Record<string, unknown>[] }).projects.map((p) => ({\n\t\t\t...p,\n\t\t\t...(Array.isArray(p.untraced) ? { untraced: (p.untraced as string[]).join(\"\\n\") } : {}),\n\t\t}));\n\t\tresult[\"chromatic-projects\"] = JSON.stringify(projects);\n\t}\n\tfor (const [k, v] of Object.entries(result)) {\n\t\tif (Array.isArray(v)) result[k] = JSON.stringify(v);\n\t}\n\treturn result;\n}\n\n/**\n * Derive on.push.paths entries from the deploy with: shorthand.\n * Used by both `holocron setup` and `sync-workflow-templates`.\n */\nexport function deriveDeployPaths(raw: Record<string, unknown>): string[] {\n\tconst paths: string[] = [];\n\tconst docs = raw[\"docs\"];\n\tif (docs === true) {\n\t\tpaths.push(\"docs/**\");\n\t\tpaths.push(\"astro.config.ts\");\n\t\tpaths.push(\"pnpm-workspace.yaml\");\n\t\tpaths.push(\"pnpm-lock.yaml\");\n\t} else if (docs !== null && typeof docs === \"object\" && \"path\" in docs) {\n\t\tconst p = (docs as { path: string }).path;\n\t\tif (p && p !== \".\") paths.push(`${p}/**`);\n\t}\n\tconst storybookProjects = raw[\"storybook\"];\n\tif (Array.isArray(storybookProjects)) {\n\t\tfor (const s of storybookProjects as Array<{ path?: string }>) {\n\t\t\tconst p = s.path || \".\";\n\t\t\tif (p === \".\") {\n\t\t\t\tpaths.push(\"src/**\");\n\t\t\t\tpaths.push(\".storybook/**\");\n\t\t\t} else {\n\t\t\t\tpaths.push(`${p}/**`);\n\t\t\t}\n\t\t}\n\t}\n\treturn paths;\n}\n","/**\n * `holocron setup` — orchestrates per-capability setup actions across\n * every plugin loaded from `holocron.config.json`.\n *\n * Per CLAUDE.md soft-skip: each step is wrapped in a try/catch and\n * failures don't abort subsequent capabilities. The summary at the end\n * reports counts so the operator can see what worked + what didn't.\n *\n * Per the Standards: when `ctx.dryRun` is true, mutating calls are\n * replaced with \"would\" log lines. Read-only probes (e.g.,\n * `vault.list`) still run so the operator sees real state.\n *\n * The orchestrator knows about specific capability methods by name\n * (e.g., `source.enableVulnerabilityAlerts`). This deliberate coupling\n * makes the \"what does setup do\" contract explicit and concrete —\n * decoupling via a per-capability `setupSteps()` method would be more\n * extensible but pushes the same knowledge into N plugins instead of\n * one central place.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { access, copyFile, mkdir, readdir, readFile, rm, stat, symlink, unlink, writeFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, relative } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { AuthError, createFeatureResolver } from \"../auth-resolver.js\";\nimport type {\n\tAuth,\n\tDeployment,\n\tDns,\n\tEnvironments,\n\tRepoSettings,\n\tSource,\n\tTooling,\n\tVault,\n} from \"../capabilities/index.js\";\nimport { ProviderApiError } from \"../capabilities/index.js\";\nimport { ConfigError } from \"../config.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport { withSpinner } from \"../ui/progress.js\";\nimport { style } from \"../ui/style.js\";\nimport {\n\tDEPENDABOT_CONFIG,\n\tderiveDeployPaths,\n\textractPreviewConfig,\n\tgenerateCombinedDeployContent,\n\tgenerateThinCallerContent,\n\tKNOWN_WORKFLOWS,\n\tnormalizeWorkflowWith,\n\tscaffoldHeader,\n\tWORKFLOW_CHECK_CONTEXTS,\n\tworkflowHeader,\n} from \"./setup-workflows.js\";\n\n// ── .editorconfig ────────────────────────────────────────────────────\n// Canonical editor settings shared across all theholocron repos.\n// Kept in sync via `holocron setup` so drift (e.g. missing yaml glob)\n// is corrected automatically.\nfunction editorconfigContent(): string {\n\treturn [\n\t\tworkflowHeader(\"packages/cli/src/commands/setup.ts\"),\n\t\t`root = true`,\n\t\t``,\n\t\t`[*]`,\n\t\t`end_of_line = lf`,\n\t\t`charset = utf-8`,\n\t\t`trim_trailing_whitespace = true`,\n\t\t`insert_final_newline = true`,\n\t\t`indent_style = tab`,\n\t\t`indent_size = 4`,\n\t\t``,\n\t\t`[.gitattributes]`,\n\t\t`indent_style = space`,\n\t\t`indent_size = 2`,\n\t\t``,\n\t\t`[*.{json,yml,yaml}]`,\n\t\t`indent_style = space`,\n\t\t`indent_size = 2`,\n\t\t``,\n\t\t`[*.{md,mdx}]`,\n\t\t`trim_trailing_whitespace = false`,\n\t\t``,\n\t\t`[.*{rc,ignore}]`,\n\t\t`indent_style = space`,\n\t\t`indent_size = 2`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\n// ── codecov.yml ──────────────────────────────────────────────────────\n// Generates the codecov.yml for a monorepo workspace. Each package under\n// packages/ becomes an individual_component entry so Codecov shows\n// per-package coverage in PR comments and the UI.\n//\n// When a codecov.yml already exists, only the individual_components block is\n// replaced — everything else (coverage thresholds, comments, etc.) is left\n// untouched. The name field uses the directory slug, not the npm package name,\n// so the org scope (@theholocron/) is never included.\n\nexport interface WorkspacePackage {\n\tslug: string;\n\tname: string;\n}\n\nconst INDIVIDUAL_COMPONENTS_MARKER = \" individual_components:\";\n\nfunction codecovComponentBlock(packages: WorkspacePackage[]): string {\n\tif (packages.length === 0) return \"\\n []\\n\";\n\treturn (\n\t\t\"\\n\" +\n\t\tpackages\n\t\t\t.flatMap(({ slug }) => [\n\t\t\t\t` - component_id: ${slug}`,\n\t\t\t\t` name: \"${slug}\"`,\n\t\t\t\t` paths:`,\n\t\t\t\t` - packages/${slug}/**`,\n\t\t\t\t``,\n\t\t\t])\n\t\t\t.join(\"\\n\")\n\t);\n}\n\nexport function mergeCodecovComponents(existing: string, packages: WorkspacePackage[]): string {\n\tconst idx = existing.indexOf(INDIVIDUAL_COMPONENTS_MARKER);\n\tif (idx === -1) return existing;\n\treturn existing.slice(0, idx + INDIVIDUAL_COMPONENTS_MARKER.length) + codecovComponentBlock(packages);\n}\n\nexport function codecovContent(packages: WorkspacePackage[]): string {\n\treturn (\n\t\t[\n\t\t\tscaffoldHeader(),\n\t\t\t`codecov:`,\n\t\t\t` require_ci_to_pass: true`,\n\t\t\t``,\n\t\t\t`coverage:`,\n\t\t\t` precision: 2`,\n\t\t\t` round: down`,\n\t\t\t` status:`,\n\t\t\t` project:`,\n\t\t\t` default:`,\n\t\t\t` target: auto`,\n\t\t\t` threshold: 2%`,\n\t\t\t` patch:`,\n\t\t\t` default:`,\n\t\t\t` target: 80%`,\n\t\t\t``,\n\t\t\t`comment:`,\n\t\t\t` layout: \"reach,diff,flags,components\"`,\n\t\t\t` behavior: default`,\n\t\t\t` require_changes: true`,\n\t\t\t``,\n\t\t\t`component_management:`,\n\t\t\t` default_rules:`,\n\t\t\t` statuses:`,\n\t\t\t` - type: patch`,\n\t\t\t` target: 80%`,\n\t\t\t` individual_components:`,\n\t\t].join(\"\\n\") + codecovComponentBlock(packages)\n\t);\n}\n\nasync function readWorkspacePackages(repoRoot: string): Promise<WorkspacePackage[]> {\n\tconst packagesDir = join(repoRoot, \"packages\");\n\tconst entries = await readdir(packagesDir, { withFileTypes: true }).catch(() => null);\n\tif (!entries) return [];\n\tconst packages: WorkspacePackage[] = [];\n\tfor (const entry of entries) {\n\t\tif (!entry.isDirectory()) continue;\n\t\ttry {\n\t\t\tconst raw = await readFile(join(packagesDir, entry.name, \"package.json\"), \"utf8\");\n\t\t\tconst pkg = JSON.parse(raw) as { name?: string };\n\t\t\tif (typeof pkg.name === \"string\") {\n\t\t\t\tpackages.push({ slug: entry.name, name: pkg.name });\n\t\t\t}\n\t\t} catch {\n\t\t\t// no package.json or invalid JSON — skip\n\t\t}\n\t}\n\treturn packages.sort((a, b) => a.slug.localeCompare(b.slug));\n}\n\n// ── .editorconfig-checker.json ───────────────────────────────────────\n// Canonical exclusions for editorconfig-checker. LICENSE files use a\n// non-standard format and must be excluded; public/ is generated output.\nconst EDITORCONFIG_CHECKER_CONFIG =\n\tJSON.stringify(\n\t\t{\n\t\t\tVersion: \"v3.7.0\",\n\t\t\tVerbose: false,\n\t\t\tFormat: \"\",\n\t\t\tDebug: false,\n\t\t\tIgnoreDefaults: false,\n\t\t\tSpacesAfterTabs: false,\n\t\t\tNoColor: false,\n\t\t\tExclude: [\"(^|.+/)LICENSE$\", \"^public/.*\", \"\\\\.md$\", \"\\\\.mdx$\"],\n\t\t\tAllowedContentTypes: [],\n\t\t\tPassedFiles: [],\n\t\t\tDisable: {\n\t\t\t\tEndOfLine: false,\n\t\t\t\tIndentation: false,\n\t\t\t\tInsertFinalNewline: false,\n\t\t\t\tTrimTrailingWhitespace: false,\n\t\t\t\tIndentSize: false,\n\t\t\t\tMaxLineLength: false,\n\t\t\t},\n\t\t},\n\t\tnull,\n\t\t2\n\t) + \"\\n\";\n\n// ── alex config ──────────────────────────────────────────────────────\n// Canonical allow-list for the alex prose linter. Shared across all\n// theholocron repos via `holocron setup` so the list only needs to be\n// updated here.\nconst ALEX_CONFIG =\n\tJSON.stringify({ allow: [\"dead\", \"failure\", \"failures\", \"hook\", \"hooks\", \"husky\", \"period\"] }, null, 2) + \"\\n\";\n\n// ── devmoji config ───────────────────────────────────────────────────\n// Delegates to @theholocron/devmoji-config so all repos share a single\n// source of truth for emoji mappings. Lives at the repo root so it is\n// picked up for every package in the monorepo.\n// Must be .cjs because devmoji uses require() and repos set \"type\":\"module\".\n// eslint-disable comment suppresses no-undef for module.exports / require\n// in ESLint flat configs that use recommended-module globals.\nfunction devmojiConfigContent(): string {\n\treturn [\n\t\t`/* eslint-disable */`,\n\t\t`// devmoji.config.cjs — generated by holocron setup, do not edit`,\n\t\t`// https://github.com/folke/devmoji`,\n\t\t`const { defineConfig } = require(\"@theholocron/devmoji-config\");`,\n\t\t`module.exports = defineConfig();`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\n// ── .husky/prepare-commit-msg hook ───────────────────────────────────\n// 1. Validates that git user.name and user.email are configured.\n// 2. Appends the DCO Signed-off-by trailer (required on every commit).\n// 3. Runs devmoji to add an emoji to the commit subject.\n// Note: --lint is intentionally omitted. prepare-commit-msg fires before\n// the editor opens, so --lint would reject the still-empty message on\n// interactive `git commit`. Validation is handled by commitlint in commit-msg.\nfunction prepareCommitMsgHookContent(): string {\n\treturn [\n\t\t`#!/bin/sh`,\n\t\t``,\n\t\t`NAME=$(git config user.name)`,\n\t\t`EMAIL=$(git config user.email)`,\n\t\t``,\n\t\t`if [ -z \"$NAME\" ]; then`,\n\t\t`\\techo \"empty git config user.name\"`,\n\t\t`\\texit 1`,\n\t\t`fi`,\n\t\t``,\n\t\t`if [ -z \"$EMAIL\" ]; then`,\n\t\t`\\techo \"empty git config user.email\"`,\n\t\t`\\texit 1`,\n\t\t`fi`,\n\t\t``,\n\t\t`git interpret-trailers --if-exists doNothing --trailer \\\\`,\n\t\t`\\t\"Signed-off-by: $NAME <$EMAIL>\" \\\\`,\n\t\t`\\t--in-place \"$1\"`,\n\t\t``,\n\t\t`npx devmoji -e`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\n// ── canonical label set ──────────────────────────────────────────────\n// Single source of truth for labels across all theholocron repos.\n// `syncLabels` (holocron-plugin-github) diffs against these and\n// creates/updates/deletes as needed.\nexport const CANONICAL_LABELS = [\n\t{ name: \"bug\", color: \"d73a4a\", description: \"Something isn't working\" },\n\t{ name: \"chore\", color: \"ededed\", description: \"Maintenance, no user-facing change\" },\n\t{ name: \"ci\", color: \"0075ca\", description: \"CI/CD pipeline changes\" },\n\t{ name: \"dependencies\", color: \"0366d6\", description: \"Dependency update\" },\n\t{ name: \"documentation\", color: \"0075ca\", description: \"Documentation only\" },\n\t{ name: \"duplicate\", color: \"cfd3d7\", description: \"Already reported\" },\n\t{ name: \"enhancement\", color: \"a2eeef\", description: \"New feature or request\" },\n\t{ name: \"good first issue\", color: \"7057ff\", description: \"Good for newcomers\" },\n\t{ name: \"help wanted\", color: \"008672\", description: \"Extra attention needed\" },\n\t{ name: \"invalid\", color: \"e4e669\", description: \"Doesn't seem right\" },\n\t{ name: \"performance\", color: \"fbca04\", description: \"Performance improvement\" },\n\t{ name: \"question\", color: \"d876e3\", description: \"Further information requested\" },\n\t{ name: \"refactor\", color: \"cfd3d7\", description: \"Code restructuring\" },\n\t{ name: \"released\", color: \"ededed\", description: \"Included in a release\" },\n\t{ name: \"test\", color: \"bfd4f2\", description: \"Test-related changes\" },\n\t{ name: \"triage\", color: \"e4e669\", description: \"Needs investigation\" },\n\t{ name: \"wontfix\", color: \"ffffff\", description: \"Won't be addressed\" },\n] as const;\n\nexport const STALE_LABELS = [\n\t\"github_actions\",\n\t\"javascript\",\n\t\"autorelease: pending\",\n\t\"autorelease: tagged\",\n\t\"released on @alpha\",\n];\n\n// ── labeler config template ──────────────────────────────────────────\n// Maps Conventional Commit title prefixes to standard GitHub label names.\n// Written when bookkeeping is in the workflows list; read by the\n// github/issue-labeler action inside the bookkeeping reusable workflow.\n// Only applied to pull requests (CC-style regexes don't suit free-form\n// issue titles; sync-labels would strip manually applied labels on issues).\nfunction labelerConfig(): string {\n\treturn [\n\t\tworkflowHeader(\"packages/cli/src/commands/setup.ts\"),\n\t\t`bug:`,\n\t\t` - '^fix'`,\n\t\t``,\n\t\t`chore:`,\n\t\t` - '^chore(?!\\\\(deps)'`,\n\t\t``,\n\t\t`ci:`,\n\t\t` - '^ci'`,\n\t\t``,\n\t\t`dependencies:`,\n\t\t` - '^chore\\\\(deps'`,\n\t\t``,\n\t\t`documentation:`,\n\t\t` - '^docs'`,\n\t\t``,\n\t\t`enhancement:`,\n\t\t` - '^feat'`,\n\t\t``,\n\t\t`performance:`,\n\t\t` - '^perf'`,\n\t\t``,\n\t\t`refactor:`,\n\t\t` - '^refactor'`,\n\t\t``,\n\t\t`test:`,\n\t\t` - '^test'`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\n// ── repo policy presets ───────────────────────────────────────────────\n\nconst RULESET_NAME = \"holocron-default-branch\";\n\nconst BALANCED_REPO_SETTINGS: RepoSettings = {\n\tallow_squash_merge: true,\n\tallow_merge_commit: false,\n\tallow_rebase_merge: false,\n\tallow_auto_merge: true,\n\tallow_update_branch: true,\n\tdelete_branch_on_merge: true,\n\thas_issues: true,\n\thas_discussions: true,\n\thas_projects: true,\n\thas_wiki: false,\n\t// web_commit_signoff_required is intentionally omitted: GitHub rejects this\n\t// field when the organization already enforces it at org level (422). Org-level\n\t// enforcement already covers every repo — no per-repo override is needed.\n};\n\nfunction buildClassicProtectionPayload(requiredChecks: string[] = []): Record<string, unknown> {\n\treturn {\n\t\trequired_status_checks: requiredChecks.length > 0 ? { strict: false, contexts: requiredChecks } : null,\n\t\tenforce_admins: false,\n\t\trequired_pull_request_reviews: {\n\t\t\trequired_approving_review_count: 0,\n\t\t\tdismiss_stale_reviews: false,\n\t\t\trequire_code_owner_reviews: false,\n\t\t},\n\t\trestrictions: null,\n\t\tallow_force_pushes: false,\n\t\tallow_deletions: false,\n\t};\n}\n\nfunction buildRulesetPayload(requiredChecks: string[] = []): Record<string, unknown> {\n\tconst rules: Record<string, unknown>[] = [\n\t\t{ type: \"deletion\" },\n\t\t{ type: \"non_fast_forward\" },\n\t\t{\n\t\t\ttype: \"pull_request\",\n\t\t\tparameters: {\n\t\t\t\trequired_approving_review_count: 0,\n\t\t\t\tdismiss_stale_reviews_on_push: false,\n\t\t\t\trequire_code_owner_review: false,\n\t\t\t\trequire_last_push_approval: false,\n\t\t\t\trequired_review_thread_resolution: true,\n\t\t\t},\n\t\t},\n\t];\n\tif (requiredChecks.length > 0) {\n\t\trules.push({\n\t\t\ttype: \"required_status_checks\",\n\t\t\tparameters: {\n\t\t\t\trequired_status_checks: requiredChecks.map((context) => ({ context })),\n\t\t\t\tstrict_required_status_checks_policy: false,\n\t\t\t},\n\t\t});\n\t}\n\treturn {\n\t\tname: RULESET_NAME,\n\t\ttarget: \"branch\",\n\t\tenforcement: \"active\",\n\t\t// Repository admins (role 4) can bypass — required for semantic-release\n\t\t// and other automation that pushes directly to the default branch.\n\t\tbypass_actors: [{ actor_id: 4, actor_type: \"RepositoryRole\", bypass_mode: \"always\" }],\n\t\tconditions: { ref_name: { include: [\"~DEFAULT_BRANCH\"], exclude: [] } },\n\t\trules,\n\t};\n}\n\n// ── branch protection helper ─────────────────────────────────────────────────\n// Tries the modern Rulesets API first, falls back to classic branch protection\n// if rulesets return 403 (requires GitHub Team+ on private repos), and gracefully\n// skips if both APIs are unavailable (GitHub Free on private repos).\n\nasync function upsertBranchProtection(\n\tsource: Source,\n\tdryRun: boolean,\n\trequiredChecks: string[]\n): Promise<SetupStepResult> {\n\tconst step = `upsert ruleset ${RULESET_NAME}`;\n\tif (dryRun) return { capability: \"source\", step, status: \"dry-run\" };\n\n\t// Attempt 1: modern rulesets\n\ttry {\n\t\tconst existing = await source.listRulesets();\n\t\tconst found = existing.find((r) => r.name === RULESET_NAME);\n\t\tif (found) {\n\t\t\tawait source.updateRuleset(found.id, buildRulesetPayload(requiredChecks));\n\t\t\treturn { capability: \"source\", step, status: \"ok\", message: \"updated\" };\n\t\t}\n\t\tawait source.createRuleset(buildRulesetPayload(requiredChecks));\n\t\treturn { capability: \"source\", step, status: \"ok\", message: \"created\" };\n\t} catch (err) {\n\t\tif (!(err instanceof ProviderApiError) || err.status !== 403) {\n\t\t\treturn {\n\t\t\t\tcapability: \"source\",\n\t\t\t\tstep,\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t};\n\t\t}\n\t}\n\n\t// Attempt 2: classic branch protection (free-plan fallback)\n\ttry {\n\t\tconst repo = await source.getRepo();\n\t\tawait source.protectBranch(repo.defaultBranch, buildClassicProtectionPayload(requiredChecks));\n\t\treturn { capability: \"source\", step, status: \"ok\", message: `classic protection on ${repo.defaultBranch}` };\n\t} catch (err) {\n\t\tif (err instanceof ProviderApiError && err.status === 403) {\n\t\t\treturn {\n\t\t\t\tcapability: \"source\",\n\t\t\t\tstep,\n\t\t\t\tstatus: \"skip\",\n\t\t\t\tmessage: \"branch protection unavailable on private repos without GitHub Pro/Team\",\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tcapability: \"source\",\n\t\t\tstep,\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t};\n\t}\n}\n\nexport type SetupPrintLine = (line: string) => void;\n\nexport type SetupStatus = \"ok\" | \"fail\" | \"skip\" | \"dry-run\";\n\n/** Why a step failed with HTTP 403. */\nexport type FailReason = \"permissions\" | \"plan\";\n\nexport interface SetupStepResult {\n\tcapability: string;\n\tstep: string;\n\tstatus: SetupStatus;\n\tmessage?: string;\n\t/** Set when status === \"fail\" and the error was a 403. */\n\treason?: FailReason;\n}\n\nexport interface SetupReport {\n\tsteps: SetupStepResult[];\n\tsummary: { ok: number; fail: number; skip: number; dryRun: number };\n}\n\nexport interface RunSetupInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\t/** Lets tests inject a pre-loaded loader; defaults to native dynamic import. */\n\tloader?: PluginLoader;\n\tprint?: SetupPrintLine;\n\t/** Injectable keyring backend. Tests pass `() => null` to skip real OS keychain lookups. */\n\tkeyring?: (key: string) => string | null;\n}\n\nexport async function runSetup(input: RunSetupInput): Promise<SetupReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\tawait withSpinner(\"Loading plugins…\", () => loader.load());\n\n\tconst config = input.loaded.resolved;\n\tconst dryRun = input.context.dryRun ?? false;\n\tconst steps: SetupStepResult[] = [];\n\tconst repo = config.repo;\n\tconst effectivePreset = repo?.protection;\n\n\tprint(style.header(`Holocron setup — ${config.name}${dryRun ? \" (dry-run)\" : \"\"}`));\n\tprint(style.dim(` config: ${input.loaded.filepath}`));\n\tprint(\"\");\n\n\t// ── source: security toggles + repo policy ──────────────────────────\n\tif (loader.has(\"source\")) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tprint(style.step(\"source\"));\n\t\t// Secret scanning on public repos is always on (422); private vuln\n\t\t// reporting doesn't exist on public repos (404). Treat both as skip so\n\t\t// a public-repo setup doesn't report spurious failures.\n\t\tconst SECURITY_SKIP_CODES: Partial<Record<string, number[]>> = {\n\t\t\tenableSecretScanning: [422],\n\t\t\tenablePrivateVulnerabilityReporting: [404],\n\t\t};\n\t\tfor (const method of [\n\t\t\t\"enableVulnerabilityAlerts\",\n\t\t\t\"enableAutomatedSecurityFixes\",\n\t\t\t\"enableSecretScanning\",\n\t\t\t\"enablePrivateVulnerabilityReporting\",\n\t\t\t\"enableDependencyGraph\",\n\t\t] as const) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\n\t\t\t\t\t\"source\",\n\t\t\t\t\tmethod,\n\t\t\t\t\tdryRun,\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\tawait source[method]();\n\t\t\t\t\t},\n\t\t\t\t\t{ skipCodes: SECURITY_SKIP_CODES[method] }\n\t\t\t\t)\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tconst usesAdvancedCodeQL = (config.workflows ?? [])\n\t\t\t.map((e) => (typeof e === \"string\" ? e : e.name))\n\t\t\t.includes(\"codeql\");\n\t\tsteps.push(\n\t\t\tawait runStep(\n\t\t\t\t\"source\",\n\t\t\t\tusesAdvancedCodeQL ? \"disableDefaultCodeScanning\" : \"enableCodeScanning\",\n\t\t\t\tdryRun,\n\t\t\t\tasync () => {\n\t\t\t\t\tif (usesAdvancedCodeQL) {\n\t\t\t\t\t\tawait source.disableDefaultCodeScanning();\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn await source.enableCodeScanning();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t)\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\n\t\tif (effectivePreset && effectivePreset !== \"none\") {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"source\", \"updateRepoSettings\", dryRun, async () => {\n\t\t\t\t\tawait source.updateRepoSettings(BALANCED_REPO_SETTINGS);\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\n\t\t\tconst configuredWorkflowNames = [\n\t\t\t\t...new Set((config.workflows ?? []).map((entry) => (typeof entry === \"string\" ? entry : entry.name))),\n\t\t\t];\n\t\t\tconst requiredChecks =\n\t\t\t\teffectivePreset === \"strict\"\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t\"DCO\",\n\t\t\t\t\t\t\t...configuredWorkflowNames.flatMap((name) => {\n\t\t\t\t\t\t\t\tconst ctx = WORKFLOW_CHECK_CONTEXTS[name];\n\t\t\t\t\t\t\t\treturn ctx ? [ctx] : [];\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(repo?.requiredChecks ?? []),\n\t\t\t\t\t\t]\n\t\t\t\t\t: [];\n\t\t\tsteps.push(await upsertBranchProtection(source, dryRun, requiredChecks));\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── source: workflow thin wrappers ──────────────────────────────────\n\t// normalizeWorkflowWith and deriveDeployPaths are imported from setup-workflows.ts\n\t// so they're shared with sync-github.ts.\n\n\tconst workflows = config.workflows;\n\tif (loader.has(\"source\") && workflows && workflows.length > 0) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tprint(style.step(\"workflows\"));\n\t\tfor (const entry of workflows) {\n\t\t\tconst name = typeof entry === \"string\" ? entry : entry.name;\n\t\t\tconst rawWith = typeof entry === \"object\" ? entry.with : undefined;\n\t\t\tconst withOverrides = rawWith ? normalizeWorkflowWith(rawWith, config.name) : undefined;\n\t\t\tconst explicitPaths = typeof entry === \"object\" ? entry.paths : undefined;\n\t\t\tconst additionalPaths =\n\t\t\t\texplicitPaths ??\n\t\t\t\t(name === \"deploy\" && rawWith ? deriveDeployPaths(rawWith as Record<string, unknown>) : undefined);\n\n\t\t\t// Enforce that the test workflow has at least one test type enabled.\n\t\t\t// This check lives here so it fails at setup time rather than silently\n\t\t\t// producing a CI job that never runs any tests.\n\t\t\tif (name === \"test\" && withOverrides) {\n\t\t\t\tconst runUnit = withOverrides[\"run-unit\"];\n\t\t\t\tconst runStorybook = withOverrides[\"run-storybook\"];\n\t\t\t\tconst unitDisabled = runUnit === false;\n\t\t\t\tconst storybookDisabled = runStorybook === false;\n\t\t\t\tconst neitherEnabled = unitDisabled && storybookDisabled;\n\t\t\t\tif (neitherEnabled) {\n\t\t\t\t\tthrow new ConfigError(\n\t\t\t\t\t\t'test workflow: at least one of \"run-unit\" or \"run-storybook\" must be true. ' +\n\t\t\t\t\t\t\t\"Library repos use run-unit: true; UI/Storybook repos use run-storybook: true.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!KNOWN_WORKFLOWS.has(name)) {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\tstep: `write workflow ${name}`,\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: `unknown workflow \"${name}\" — no template available`,\n\t\t\t\t});\n\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// deploy + preview: → combined thin caller (single file, two jobs).\n\t\t\t// preview: true derives project + domain from config.org / config.docs.\n\t\t\tif (name === \"deploy\" && rawWith) {\n\t\t\t\tconst previewCfg = extractPreviewConfig(rawWith as Record<string, unknown>, {\n\t\t\t\t\torg: config.org,\n\t\t\t\t\tdomain: config.domain,\n\t\t\t\t});\n\t\t\t\tif (previewCfg) {\n\t\t\t\t\tconst paths = additionalPaths!;\n\t\t\t\t\tsteps.push(\n\t\t\t\t\t\tawait runStep(\"source\", \"write workflow deploy (with preview)\", dryRun, async () => {\n\t\t\t\t\t\t\tawait source.writeWorkflowFile(\n\t\t\t\t\t\t\t\t\"deploy.yml\",\n\t\t\t\t\t\t\t\tworkflowHeader() + generateCombinedDeployContent(withOverrides!, paths, previewCfg)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"source\", `write workflow ${name}`, dryRun, async () => {\n\t\t\t\t\tawait source.writeWorkflowFile(\n\t\t\t\t\t\t`${name}.yml`,\n\t\t\t\t\t\tworkflowHeader() + generateThinCallerContent(name, withOverrides, additionalPaths)\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── source: labeler config ───────────────────────────────────────────\n\tif (\n\t\tloader.has(\"source\") &&\n\t\t(config.workflows ?? []).map((e) => (typeof e === \"string\" ? e : e.name)).includes(\"bookkeeping\")\n\t) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .github/labeler.yml\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\".github/labeler.yml\", labelerConfig());\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t}\n\n\t// ── source: dependabot config ────────────────────────────────────────\n\tif (loader.has(\"source\") && effectivePreset !== \"none\") {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .github/dependabot.yml\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\n\t\t\t\t\t\".github/dependabot.yml\",\n\t\t\t\t\tworkflowHeader(\"packages/cli/src/commands/setup.ts\") + DEPENDABOT_CONFIG\n\t\t\t\t);\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t}\n\n\t// ── source: alex config ───────────────────────────────────────────────\n\t// Always written — not gated on protection since all prose benefits from\n\t// a consistent allow-list. Update ALEX_CONFIG above to propagate changes.\n\tif (loader.has(\"source\")) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .alexrc.json\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\".alexrc.json\", ALEX_CONFIG);\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .editorconfig\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\".editorconfig\", editorconfigContent());\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .editorconfig-checker.json\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\".editorconfig-checker.json\", EDITORCONFIG_CHECKER_CONFIG);\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write devmoji.config.cjs\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\"devmoji.config.cjs\", devmojiConfigContent());\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\tsteps.push(\n\t\t\tawait runStep(\"source\", \"write .husky/prepare-commit-msg\", dryRun, async () => {\n\t\t\t\tawait source.writeRepoFile(\".husky/prepare-commit-msg\", prepareCommitMsgHookContent());\n\t\t\t})\n\t\t);\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t{\n\t\t\tconst configuredWorkflowNames = (config.workflows ?? []).map((e) => (typeof e === \"string\" ? e : e.name));\n\t\t\tconst hasTestWorkflow = configuredWorkflowNames.includes(\"test\");\n\t\t\tconst packages = await readWorkspacePackages(input.context.repoRoot);\n\t\t\tconst existing = await readFile(join(input.context.repoRoot, \"codecov.yml\"), \"utf8\").catch(() => null);\n\t\t\tif (!hasTestWorkflow && existing == null) {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\tstep: \"write codecov.yml\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"no test workflow configured\",\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runStep(\"source\", \"write codecov.yml\", dryRun, async () => {\n\t\t\t\t\t\tconst content =\n\t\t\t\t\t\t\texisting != null ? mergeCodecovComponents(existing, packages) : codecovContent(packages);\n\t\t\t\t\t\tawait source.writeRepoFile(\"codecov.yml\", content);\n\t\t\t\t\t\treturn packages.length > 0 ? `${packages.length} components` : \"no components\";\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (source.syncLabels) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"source\", \"sync labels\", dryRun, async () => {\n\t\t\t\t\treturn source.syncLabels!(CANONICAL_LABELS, STALE_LABELS);\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tconst properties: Record<string, string> = {};\n\n\t\tif (effectivePreset && effectivePreset !== \"none\") properties[\"branch_protection_level\"] = effectivePreset;\n\n\t\tconst isMonorepo = await access(join(input.context.repoRoot, \"pnpm-workspace.yaml\"))\n\t\t\t.then(() => true)\n\t\t\t.catch(() => false);\n\t\tproperties[\"monorepo\"] = String(isMonorepo);\n\n\t\tconst manual = repo?.properties ?? {};\n\t\tif (manual.lifecycle) properties[\"lifecycle\"] = manual.lifecycle;\n\t\tif (manual.open_source !== undefined) properties[\"open_source\"] = String(manual.open_source);\n\t\tif (manual.runtime_environment) properties[\"runtime_environment\"] = manual.runtime_environment;\n\t\tif (manual.uses_external_packages !== undefined)\n\t\t\tproperties[\"uses_external_packages\"] = String(manual.uses_external_packages);\n\n\t\tif (source.syncProperties) {\n\t\t\tsteps.push(await runStep(\"source\", \"sync properties\", dryRun, () => source.syncProperties!(properties)));\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tconst topics = repo?.topics ?? [];\n\t\tif (topics.length > 0 && source.syncTopics) {\n\t\t\tsteps.push(await runStep(\"source\", \"sync topics\", dryRun, () => source.syncTopics!(topics)));\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (config.description && source.syncDescription) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"source\", \"sync description\", dryRun, () => source.syncDescription!(config.description!))\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (config.homepage && source.syncHomepage) {\n\t\t\tsteps.push(await runStep(\"source\", \"sync homepage\", dryRun, () => source.syncHomepage!(config.homepage!)));\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tconst teams = repo?.teams ?? [];\n\t\tif (teams.length > 0) {\n\t\t\tif (source.syncTeams) {\n\t\t\t\t// 422 means the team is already assigned — desired state is in place,\n\t\t\t\t// so treat it as an idempotent success (skip) rather than a failure.\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runStep(\"source\", \"sync teams\", dryRun, () => source.syncTeams!(teams), { skipCodes: [422] })\n\t\t\t\t);\n\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\n\t\t\t\t// Only split on \"/\" so a bare repo name (no owner prefix) yields an\n\t\t\t\t// empty org and silently skips the CODEOWNERS write rather than\n\t\t\t\t// producing an invalid \"* @reponame/slug\" entry.\n\t\t\t\tconst repoCoord = input.context.repo ?? repo?.name ?? \"\";\n\t\t\t\tconst org = repoCoord.includes(\"/\") ? repoCoord.split(\"/\")[0]! : \"\";\n\t\t\t\tconst writeableTeams = teams\n\t\t\t\t\t.map((t) => (typeof t === \"string\" ? { slug: t, permission: \"push\" as const } : t))\n\t\t\t\t\t.filter((t) => [\"push\", \"maintain\", \"admin\"].includes(t.permission));\n\t\t\t\tif (org && writeableTeams.length > 0) {\n\t\t\t\t\tsteps.push(\n\t\t\t\t\t\tawait runStep(\"source\", \"write .github/CODEOWNERS\", dryRun, async () => {\n\t\t\t\t\t\t\tconst content = writeableTeams.map((t) => `* @${org}/${t.slug}`).join(\"\\n\") + \"\\n\";\n\t\t\t\t\t\t\tawait source.writeRepoFile(\".github/CODEOWNERS\", content);\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\tstep: \"sync teams\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"provider does not implement syncTeams\",\n\t\t\t\t});\n\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── environments ────────────────────────────────────────────────────\n\tif (loader.has(\"environments\")) {\n\t\tconst envs = loader.get(\"environments\") as Environments;\n\t\tprint(style.step(\"environments\"));\n\t\tfor (const envName of [\"staging\", \"production\"]) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"environments\", `upsert ${envName}`, dryRun, async () => {\n\t\t\t\t\tawait envs.upsertEnvironment({ name: envName });\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── docs: configure GitHub Pages ────────────────────────────────────\n\tif (loader.has(\"source\") && config.docs) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tconst resolveDeployToken = createFeatureResolver({\n\t\t\tenvName: \"HOLOCRON_DEPLOY_TOKEN\",\n\t\t\tkeyringKey: \"github.deploy\",\n\t\t});\n\t\tlet deployToken: string | undefined;\n\t\ttry {\n\t\t\tdeployToken = resolveDeployToken({ keyring: input.keyring });\n\t\t} catch (err) {\n\t\t\tif (!(err instanceof AuthError)) throw err;\n\t\t}\n\t\tprint(style.step(\"docs\"));\n\t\tif (!deployToken) {\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"source\",\n\t\t\t\tstep: \"configure GitHub Pages\",\n\t\t\t\tstatus: \"skip\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"no deploy token found — set HOLOCRON_DEPLOY_TOKEN or run: holocron auth set github.deploy <PAT>\",\n\t\t\t});\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t} else if (source.configurePages) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"source\", \"configure GitHub Pages\", dryRun, async () => {\n\t\t\t\t\tawait source.configurePages!(config.docs!, deployToken);\n\t\t\t\t\tconst parts: string[] = [config.docs!.build];\n\t\t\t\t\tif (config.docs!.domain) parts.push(`domain: ${config.docs!.domain}`);\n\t\t\t\t\tif (config.docs!.https) parts.push(\"https: enforced\");\n\t\t\t\t\treturn parts.join(\", \");\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── deployment: ensure project + preview infrastructure ─────────────\n\tif (loader.has(\"deployment\")) {\n\t\tconst deploy = loader.get(\"deployment\") as Deployment;\n\t\tprint(style.step(\"deployment\"));\n\n\t\t// Resolve preview config first so we know whether the deployment capability\n\t\t// is being used exclusively for preview infrastructure or for a direct deploy.\n\t\tconst deployEntry = (config.workflows ?? [])\n\t\t\t.map((e) => (typeof e === \"string\" ? { name: e } : e))\n\t\t\t.find((e) => e.name === \"deploy\");\n\t\tconst previewCfg = deployEntry?.with\n\t\t\t? extractPreviewConfig(deployEntry.with as Record<string, unknown>, {\n\t\t\t\t\torg: config.org,\n\t\t\t\t\tdomain: config.domain,\n\t\t\t\t})\n\t\t\t: null;\n\n\t\t// Only provision the main project when the repo is directly deploying to\n\t\t// Cloudflare Pages (no preview config). When preview: is set, the deployment\n\t\t// provider is used solely for preview infrastructure — creating a project\n\t\t// named after the repo would be an unwanted side-effect.\n\t\tif (!previewCfg) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"deployment\", `ensureProject ${config.name}`, dryRun, async () => {\n\t\t\t\t\tawait deploy.ensureProject({ name: config.name });\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (previewCfg) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"deployment\", `ensureProject ${previewCfg.project}`, dryRun, async () => {\n\t\t\t\t\tawait deploy.ensureProject({ name: previewCfg.project });\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (previewCfg?.domain && deploy.ensureCustomDomain) {\n\t\t\t// CF Pages accepts the apex domain, not a wildcard — branch deployments\n\t\t\t// then resolve automatically as <repo>-pr-<n>.<domain>.\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"deployment\", `ensureCustomDomain ${previewCfg.domain}`, dryRun, async () => {\n\t\t\t\t\tawait deploy.ensureCustomDomain!(previewCfg.project, previewCfg.domain!);\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\tif (previewCfg?.domain && loader.has(\"dns\")) {\n\t\t\tconst dns = loader.get(\"dns\") as Dns;\n\t\t\tconst wildcardDomain = `*.${previewCfg.domain}`;\n\t\t\t// Apex CNAME so preview.theholocron.dev itself resolves.\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"dns\", `upsertRecord ${previewCfg.domain}`, dryRun, async () => {\n\t\t\t\t\tawait dns.upsertRecord(previewCfg.domain!, {\n\t\t\t\t\t\ttype: \"CNAME\",\n\t\t\t\t\t\tname: previewCfg.domain!,\n\t\t\t\t\t\tcontent: `${previewCfg.project}.pages.dev`,\n\t\t\t\t\t\tttl: 1,\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t// Wildcard CNAME so <repo>-pr-<n>.preview.theholocron.dev resolves.\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"dns\", `upsertRecord ${wildcardDomain}`, dryRun, async () => {\n\t\t\t\t\tawait dns.upsertRecord(previewCfg.domain!, {\n\t\t\t\t\t\ttype: \"CNAME\",\n\t\t\t\t\t\tname: wildcardDomain,\n\t\t\t\t\t\tcontent: `${previewCfg.project}.pages.dev`,\n\t\t\t\t\t\tttl: 1,\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── auth: ensure webhook app (optional method) ──────────────────────\n\tif (loader.has(\"auth\")) {\n\t\tconst auth = loader.get(\"auth\") as Auth;\n\t\tprint(style.step(\"auth\"));\n\t\tif (auth.ensureWebhookApp) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"auth\", \"ensureWebhookApp\", dryRun, async () => {\n\t\t\t\t\tconst result = await auth.ensureWebhookApp!();\n\t\t\t\t\treturn `webhook ${result.alreadyExists ? \"exists\" : \"created\"}`;\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t} else {\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"auth\",\n\t\t\t\tstep: \"ensureWebhookApp\",\n\t\t\t\tstatus: \"skip\",\n\t\t\t\tmessage: \"provider does not implement ensureWebhookApp\",\n\t\t\t});\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── vault: bootstrap project + configs, then read-only probe ───────\n\tif (loader.has(\"vault\")) {\n\t\tconst vault = loader.get(\"vault\") as Vault;\n\t\tprint(style.step(\"vault\"));\n\n\t\t// ensureProject — providers that have a top-level container.\n\t\tif (vault.ensureProject) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"vault\", `ensureProject ${config.name}`, dryRun, async () => {\n\t\t\t\t\tconst result = await vault.ensureProject!(config.name);\n\t\t\t\t\treturn `project ${result.alreadyExists ? \"exists\" : \"created\"}`;\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\n\t\t// ensureEnvironment — providers with a project/config split\n\t\t// (Doppler configs, Infisical environments, etc.). Canonical\n\t\t// names; per-project overrides live in the plugin's options.\n\t\tif (vault.ensureEnvironment) {\n\t\t\tfor (const envName of [\"dev\", \"stg\", \"prd\"]) {\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runStep(\"vault\", `ensureEnvironment ${envName}`, dryRun, async () => {\n\t\t\t\t\t\tconst result = await vault.ensureEnvironment!(config.name, envName);\n\t\t\t\t\t\treturn `${envName} ${result.alreadyExists ? \"exists\" : \"created\"}`;\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t\t}\n\t\t}\n\n\t\t// Read-only reachability probe. Runs even under --dry-run.\n\t\ttry {\n\t\t\tconst keys = await vault.list();\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"vault\",\n\t\t\t\tstep: \"list\",\n\t\t\t\tstatus: \"ok\",\n\t\t\t\tmessage: `${keys.length} keys available`,\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"vault\",\n\t\t\t\tstep: \"list\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t});\n\t\t}\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t}\n\n\t// ── tooling: sync each (many cardinality) ───────────────────────────\n\tif (loader.has(\"tooling\")) {\n\t\tconst tools = loader.get(\"tooling\") as Tooling[];\n\t\tprint(style.step(\"tooling\"));\n\t\tfor (const tool of tools) {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"tooling\", `${tool.providerName}.sync`, dryRun, async () => {\n\t\t\t\t\tawait tool.sync();\n\t\t\t\t})\n\t\t\t);\n\t\t\tprint(formatStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\t// ── skills: install agent skills from registry ──────────────────────\n\t// Pure local fs operation — no source plugin required. Reads skill dirs\n\t// from the installed @theholocron/skills package and copies them to the\n\t// agent-specific location, then gitignores the installed paths.\n\tif (config.skills && config.skills.length > 0 && config.agent) {\n\t\tprint(style.step(\"skills\"));\n\t\tif (!(config.agent in AGENT_SYMLINK_PATHS)) {\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"skills\",\n\t\t\t\tstep: \"install skills\",\n\t\t\t\tstatus: \"skip\",\n\t\t\t\tmessage: `agent \"${config.agent}\" has no known skill install path`,\n\t\t\t});\n\t\t} else {\n\t\t\tsteps.push(\n\t\t\t\tawait runStep(\"skills\", \"install skills\", dryRun, async () => {\n\t\t\t\t\treturn await installSkills({\n\t\t\t\t\t\tagent: config.agent!,\n\t\t\t\t\t\tskills: config.skills!,\n\t\t\t\t\t\trepoRoot: input.context.repoRoot,\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\t\tprint(formatStep(steps[steps.length - 1]!));\n\t}\n\n\tconst summary = steps.reduce(\n\t\t(acc, s) => {\n\t\t\tif (s.status === \"ok\") acc.ok += 1;\n\t\t\telse if (s.status === \"fail\") acc.fail += 1;\n\t\t\telse if (s.status === \"skip\") acc.skip += 1;\n\t\t\telse if (s.status === \"dry-run\") acc.dryRun += 1;\n\t\t\treturn acc;\n\t\t},\n\t\t{ ok: 0, fail: 0, skip: 0, dryRun: 0 }\n\t);\n\n\tprint(\"\");\n\tconst summaryLine = ` ${summary.ok} ok, ${summary.fail} fail, ${summary.skip} skipped${\n\t\tdryRun ? `, ${summary.dryRun} would-do` : \"\"\n\t}`;\n\tprint(summary.fail > 0 ? style.fail(summaryLine.trim()) : style.success(summaryLine.trim()));\n\n\tconst skippedSteps = steps.filter((s) => s.status === \"skip\");\n\tif (skippedSteps.length > 0) {\n\t\tprint(\"\");\n\t\tprint(style.hint(\" Skipped:\"));\n\t\tfor (const s of skippedSteps) {\n\t\t\t/* v8 ignore next -- all skip steps set message; empty fallback is defensive */\n\t\t\tprint(style.hint(` · ${s.step}${s.message ? ` (${s.message})` : \"\"}`));\n\t\t}\n\t}\n\n\tif (steps.some((s) => s.reason === \"permissions\")) {\n\t\tprint(\"\");\n\t\tprint(style.warn(\"Some steps failed with 403 (insufficient token permissions).\"));\n\t\tprint(style.hint(\" Repo-scoped operations (rulesets, settings, workflows) require a\"));\n\t\tprint(style.hint(\" fine-grained PAT passed via --token or HOLOCRON_ADMIN_TOKEN:\"));\n\t\tprint(\"\");\n\t\tprint(style.hint(\" · Administration — read and write\"));\n\t\tprint(style.hint(\" · Code scanning alerts — read and write\"));\n\t\tprint(style.hint(\" · Contents — read and write\"));\n\t\tprint(style.hint(\" · Secret scanning alerts — read and write\"));\n\t\tprint(style.hint(\" · Workflows — read and write\"));\n\t\tprint(style.hint(\" · Metadata — read (added automatically)\"));\n\t\tprint(\"\");\n\t\tprint(style.hint(\" Org-scoped operations (teams, custom properties) require\"));\n\t\tprint(style.hint(\" HOLOCRON_ORG_TOKEN — a fine-grained PAT with resource owner set to the org:\"));\n\t\tprint(\"\");\n\t\tprint(style.hint(\" · Administration — read and write (repository permission)\"));\n\t\tprint(style.hint(\" · Members — read (organization permission)\"));\n\t\tprint(style.hint(\" · Organization custom properties — read and write (organization permission)\"));\n\t\tprint(style.hint(\" · Metadata — read (repository permission, auto-included)\"));\n\t\tprint(\"\");\n\t\tprint(style.hint(\" Create tokens at: https://github.com/settings/personal-access-tokens/new\"));\n\t\tprint(style.hint(\" Then re-run: holocron setup --token <your-admin-pat>\"));\n\t\tprint(style.hint(\" Store org token: HOLOCRON_ORG_TOKEN env var or keyring key github.org\"));\n\t}\n\n\treturn { steps, summary };\n}\n\n// ── skills installer ─────────────────────────────────────────────────\n// Canonical location: .agents/skills/<name>/\n// Agent symlinks: .<agent>/skills/<name> → relative path into .agents/\n// Pattern mirrors the `npx skills add` CLI (skills.sh) for multi-agent compat.\n\ninterface SkillLockEntry {\n\tsource: string;\n\tsourceType: \"github\";\n\tskillPath: string;\n\tcomputedHash?: string;\n}\n\ninterface SkillsLock {\n\tversion: number;\n\tskills: Record<string, SkillLockEntry>;\n}\n\n/**\n * Fetch a single SKILL.md from its upstream GitHub source.\n * Verifies the SHA-256 hash when `computedHash` is present in the lock entry.\n */\nasync function fetchExternalSkill(entry: SkillLockEntry): Promise<{ content: string; stale: boolean }> {\n\tif (entry.sourceType !== \"github\") {\n\t\tthrow new Error(`unsupported sourceType: ${entry.sourceType}`);\n\t}\n\tconst url = `https://raw.githubusercontent.com/${entry.source}/HEAD/${entry.skillPath}`;\n\tconst res = await fetch(url);\n\tif (!res.ok) throw new Error(`HTTP ${res.status} fetching ${url}`);\n\tconst content = await res.text();\n\t// A hash mismatch means the upstream file changed since the lock was recorded.\n\t// Install anyway and surface via \"stale:\" so the user knows to run\n\t// `holocron skills update` to refresh the lock.\n\tconst stale = !!entry.computedHash && createHash(\"sha256\").update(content).digest(\"hex\") !== entry.computedHash;\n\treturn { content, stale };\n}\n\nconst AGENTS_SKILLS_ROOT = \".agents/skills\";\n\n/** Relative path of the agent-specific symlink. undefined = unsupported agent. */\nconst AGENT_SYMLINK_PATHS: Partial<Record<string, (name: string) => string>> = {\n\tclaude: (name) => `.claude/skills/${name}`,\n};\n\nconst GITIGNORE_BLOCK_START = \"# managed by holocron setup — skills\";\n// Safety invariant: GITIGNORE_BLOCK_START must NOT be a substring of\n// GITIGNORE_BLOCK_END. The \"# end \" prefix currently guarantees this — if\n// either string is edited, verify the invariant still holds so that\n// indexOf(GITIGNORE_BLOCK_START) cannot match inside the end marker.\nconst GITIGNORE_BLOCK_END = \"# end managed by holocron setup — skills\";\n\nexport async function installSkills({\n\tagent,\n\tskills,\n\trepoRoot,\n}: {\n\tagent: string;\n\tskills: string[];\n\trepoRoot: string;\n}): Promise<string> {\n\tconst symlinkFn = AGENT_SYMLINK_PATHS[agent];\n\tif (!symlinkFn) {\n\t\treturn `agent \"${agent}\" has no known skill install path — skipping`;\n\t}\n\n\t// Locate @theholocron/skills relative to the consumer repo.\n\t// Uses ./package.json subpath — must be declared in the package exports map.\n\t// Auto-installs if not present rather than failing with a manual instruction.\n\tconst require = createRequire(pathToFileURL(join(repoRoot, \"package.json\")));\n\tlet skillsRoot: string;\n\ttry {\n\t\tskillsRoot = dirname(require.resolve(\"@theholocron/skills/package.json\"));\n\t} catch {\n\t\tconst result = spawnSync(\"pnpm\", [\"add\", \"-D\", \"@theholocron/skills\"], {\n\t\t\tcwd: repoRoot,\n\t\t\tstdio: \"inherit\",\n\t\t});\n\t\tif (result.status !== 0) {\n\t\t\tthrow new Error(\"failed to auto-install @theholocron/skills\");\n\t\t}\n\t\ttry {\n\t\t\tskillsRoot = dirname(require.resolve(\"@theholocron/skills/package.json\"));\n\t\t} catch {\n\t\t\tthrow new Error(\"failed to auto-install @theholocron/skills\");\n\t\t}\n\t}\n\n\t// Find which skills from the previous run are no longer wanted (prune stale).\n\tconst gitignorePath = join(repoRoot, \".gitignore\");\n\tconst existingContent = await readFile(gitignorePath, \"utf8\").catch(() => \"\");\n\tconst previouslyInstalled = parsePreviousSkills(existingContent, symlinkFn);\n\tconst currentSet = new Set(skills);\n\tconst stale = previouslyInstalled.filter((n) => !currentSet.has(n));\n\tfor (const name of stale) {\n\t\tawait rm(join(repoRoot, symlinkFn(name)), { force: true }).catch(() => undefined);\n\t\tawait rm(join(repoRoot, AGENTS_SKILLS_ROOT, name), { recursive: true, force: true }).catch(() => undefined);\n\t}\n\n\tconst installed: string[] = [];\n\tconst missing: string[] = [];\n\n\tfor (const name of skills) {\n\t\tconst srcDir = join(skillsRoot, \"src\", name);\n\n\t\ttry {\n\t\t\tawait stat(srcDir);\n\t\t} catch {\n\t\t\tmissing.push(name);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// 1. Copy recursively to .agents/skills/<name>/ (handles nested reference dirs)\n\t\tconst agentsDir = join(repoRoot, AGENTS_SKILLS_ROOT, name);\n\t\tawait copyDirRecursive(srcDir, agentsDir);\n\n\t\t// 2. Relative symlink at agent-specific path → .agents/skills/<name>\n\t\tconst symlinkPath = join(repoRoot, symlinkFn(name));\n\t\tawait mkdir(dirname(symlinkPath), { recursive: true });\n\t\ttry {\n\t\t\tawait unlink(symlinkPath);\n\t\t} catch {\n\t\t\t// didn't exist — that's fine\n\t\t}\n\t\t// Forward slashes in symlink target (posix-compatible on all platforms)\n\t\tawait symlink(relative(dirname(symlinkPath), agentsDir).replace(/\\\\/g, \"/\"), symlinkPath);\n\n\t\tinstalled.push(name);\n\t}\n\n\t// ── external skills: fetch from upstream sources in skills-lock.json ─────\n\tconst externalFailed: string[] = [];\n\tconst externalStale: string[] = [];\n\tif (missing.length > 0) {\n\t\tlet lock: SkillsLock | null = null;\n\t\ttry {\n\t\t\tlock = JSON.parse(await readFile(join(skillsRoot, \"skills-lock.json\"), \"utf8\")) as SkillsLock;\n\t\t} catch {\n\t\t\t// No lock file or parse error — all missing remain unknown.\n\t\t}\n\t\tif (lock?.skills) {\n\t\t\tfor (const name of [...missing]) {\n\t\t\t\tconst entry = lock.skills[name];\n\t\t\t\tif (!entry) continue;\n\t\t\t\ttry {\n\t\t\t\t\tconst { content, stale: isStale } = await fetchExternalSkill(entry);\n\t\t\t\t\tconst agentsDir = join(repoRoot, AGENTS_SKILLS_ROOT, name);\n\t\t\t\t\tawait mkdir(agentsDir, { recursive: true });\n\t\t\t\t\tawait writeFile(join(agentsDir, \"SKILL.md\"), content);\n\t\t\t\t\tconst symlinkPath = join(repoRoot, symlinkFn(name));\n\t\t\t\t\tawait mkdir(dirname(symlinkPath), { recursive: true });\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait unlink(symlinkPath);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// didn't exist — that's fine\n\t\t\t\t\t}\n\t\t\t\t\tawait symlink(relative(dirname(symlinkPath), agentsDir).replace(/\\\\/g, \"/\"), symlinkPath);\n\t\t\t\t\tmissing.splice(missing.indexOf(name), 1);\n\t\t\t\t\tinstalled.push(name);\n\t\t\t\t\tif (isStale) externalStale.push(name);\n\t\t\t\t} catch {\n\t\t\t\t\tmissing.splice(missing.indexOf(name), 1);\n\t\t\t\t\texternalFailed.push(name);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Include all installed + still-unknown + failed skills in the gitignore.\n\tif (installed.length > 0 || stale.length > 0 || missing.length > 0 || externalFailed.length > 0) {\n\t\tawait updateSkillsGitignore(\n\t\t\tgitignorePath,\n\t\t\texistingContent,\n\t\t\t[...installed, ...missing, ...externalFailed],\n\t\t\tsymlinkFn\n\t\t);\n\t}\n\n\tconst parts: string[] = [`installed ${installed.length}`];\n\tif (stale.length > 0) parts.push(`pruned: ${stale.join(\", \")}`);\n\tif (externalStale.length > 0)\n\t\tparts.push(`stale: ${externalStale.join(\", \")} (run \\`holocron skills update\\` to refresh)`);\n\tif (externalFailed.length > 0) parts.push(`fetch failed: ${externalFailed.join(\", \")}`);\n\tif (missing.length > 0) parts.push(`unknown: ${missing.join(\", \")}`);\n\treturn parts.join(\"; \");\n}\n\n/** Extract skill names from the previous gitignore block so stale dirs can be pruned. */\nfunction parsePreviousSkills(gitignoreContent: string, symlinkFn: (n: string) => string): string[] {\n\tif (!gitignoreContent.includes(GITIGNORE_BLOCK_START)) return [];\n\tconst startIdx = gitignoreContent.indexOf(GITIGNORE_BLOCK_START);\n\tconst endIdx = gitignoreContent.indexOf(GITIGNORE_BLOCK_END, startIdx);\n\tconst block = endIdx !== -1 ? gitignoreContent.slice(startIdx, endIdx) : gitignoreContent.slice(startIdx);\n\t// Derive the symlink prefix by calling symlinkFn with a placeholder and removing it\n\tconst placeholder = \"__placeholder__\";\n\tconst symlinkPrefix = `/${symlinkFn(placeholder)}`.replace(placeholder, \"\");\n\treturn block\n\t\t.split(\"\\n\")\n\t\t.filter((line) => line.startsWith(symlinkPrefix))\n\t\t.map((line) => line.slice(symlinkPrefix.length));\n}\n\nasync function copyDirRecursive(src: string, dest: string): Promise<void> {\n\tawait mkdir(dest, { recursive: true });\n\tconst entries = await readdir(src, { withFileTypes: true });\n\tfor (const entry of entries) {\n\t\tconst srcPath = join(src, entry.name);\n\t\tconst destPath = join(dest, entry.name);\n\t\tif (entry.isDirectory()) {\n\t\t\tawait copyDirRecursive(srcPath, destPath);\n\t\t} else {\n\t\t\tawait copyFile(srcPath, destPath);\n\t\t}\n\t}\n}\n\nasync function updateSkillsGitignore(\n\tgitignorePath: string,\n\texistingContent: string,\n\tskills: string[],\n\tsymlinkFn: (name: string) => string\n): Promise<void> {\n\t// Always use forward slashes in gitignore (posix paths regardless of OS)\n\tconst entries = [`/${AGENTS_SKILLS_ROOT}/`, ...skills.map((n) => `/${symlinkFn(n)}`)];\n\tconst block = [GITIGNORE_BLOCK_START, ...entries, GITIGNORE_BLOCK_END].join(\"\\n\");\n\n\tlet content: string;\n\tif (existingContent.includes(GITIGNORE_BLOCK_START)) {\n\t\tconst start = existingContent.indexOf(GITIGNORE_BLOCK_START);\n\t\tconst end = existingContent.indexOf(GITIGNORE_BLOCK_END, start);\n\t\t// Without an end marker we cannot tell where managed entries stop and user\n\t\t// content begins, so just close the new block with a newline and discard\n\t\t// the orphaned entries rather than risk corrupting the file.\n\t\tconst afterBlock = end !== -1 ? existingContent.slice(end + GITIGNORE_BLOCK_END.length) : \"\\n\";\n\t\tcontent = existingContent.slice(0, start) + block + afterBlock;\n\t} else {\n\t\tcontent = (existingContent.trimEnd() ? existingContent.trimEnd() + \"\\n\\n\" : \"\") + block + \"\\n\";\n\t}\n\n\tawait writeFile(gitignorePath, content, \"utf8\");\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nasync function runStep(\n\tcapability: string,\n\tstep: string,\n\tdryRun: boolean,\n\tbody: () => Promise<string | void>,\n\topts: { skipCodes?: number[] } = {}\n): Promise<SetupStepResult> {\n\tif (dryRun) {\n\t\treturn { capability, step, status: \"dry-run\" };\n\t}\n\ttry {\n\t\tconst note = await body();\n\t\tconst result: SetupStepResult = { capability, step, status: \"ok\" };\n\t\tif (typeof note === \"string\") result.message = note;\n\t\treturn result;\n\t} catch (err) {\n\t\tif (err instanceof ProviderApiError) {\n\t\t\tif (err.status !== undefined && opts.skipCodes?.includes(err.status)) {\n\t\t\t\treturn { capability, step, status: \"skip\", message: err.message };\n\t\t\t}\n\t\t\tif (err.status === 403) {\n\t\t\t\tconst reason = classify403(err);\n\t\t\t\t// Plan-restriction 403s mean the feature is unavailable on the current\n\t\t\t\t// plan — not a setup failure, just a capability gap. Report as skip.\n\t\t\t\treturn { capability, step, status: reason === \"plan\" ? \"skip\" : \"fail\", message: err.message, reason };\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tcapability,\n\t\t\tstep,\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t};\n\t}\n}\n\nfunction classify403(err: ProviderApiError): FailReason {\n\tconst detailText =\n\t\ttypeof err.details === \"string\"\n\t\t\t? err.details\n\t\t\t: typeof err.details === \"object\" && err.details !== null && \"message\" in err.details\n\t\t\t\t? String((err.details as { message?: unknown }).message)\n\t\t\t\t: \"\";\n\tconst text = `${err.message} ${detailText}`.toLowerCase();\n\tif (\n\t\ttext.includes(\"advanced security\") ||\n\t\ttext.includes(\"not enabled for this repository\") ||\n\t\ttext.includes(\"upgrade\") ||\n\t\ttext.includes(\"not available on\")\n\t) {\n\t\treturn \"plan\";\n\t}\n\treturn \"permissions\";\n}\n\nfunction formatStep(step: SetupStepResult): string {\n\tconst tag = step.reason === \"permissions\" ? \" [permissions]\" : step.reason === \"plan\" ? \" [plan restriction]\" : \"\";\n\tconst detail = step.message ? style.dim(` (${step.message})`) : \"\";\n\tconst label = `${step.step}${tag}${detail}`;\n\tif (step.status === \"ok\") return ` ${style.success(label)}`;\n\tif (step.status === \"fail\") return ` ${style.fail(label)}`;\n\tif (step.status === \"dry-run\") return ` ${style.dim(`… ${label}`)}`;\n\treturn ` ${style.dim(`· ${label}`)}`;\n}\n","/**\n * `holocron skills` — install, remove, and update agent skills from @theholocron/skills.\n *\n * Unlike `holocron setup`, this command is purely local (no GitHub token\n * required). It reads `agent` and `skills` from the config and installs\n * the listed skills into `.agents/skills/<name>/` with a symlink at the\n * agent-specific path (e.g. `.claude/skills/<name>` for Claude Code).\n *\n * `holocron skills remove [name]` and `holocron skills update [name]` delegate\n * to the corresponding `npx skills` subcommands from the upstream skills CLI.\n */\n\nimport { spawnSync } from \"node:child_process\";\n\nimport type { LoadedConfig } from \"../load-config.js\";\nimport type { RuntimeContext } from \"../loader.js\";\nimport { installSkills } from \"./setup.js\";\n\n// ── shared exec ──────────────────────────────────────────────────────────────\n\ntype ExecFn = (cmd: string, args: string[], opts: { cwd: string }) => { exitCode: number };\n\nconst defaultExec: ExecFn = (cmd, args, opts) => {\n\tconst result = spawnSync(cmd, args, { cwd: opts.cwd, stdio: \"inherit\" });\n\treturn { exitCode: result.status ?? -1 };\n};\n\n// ── install ──────────────────────────────────────────────────────────────────\n\nexport interface RunSkillsInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\tprint?: (line: string) => void;\n}\n\nexport async function runSkillsInstall(input: RunSkillsInput): Promise<void> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst config = input.loaded.resolved;\n\n\tif (!config.agent || !config.skills?.length) {\n\t\tprint(\"Nothing to install — set `agent` and `skills` in holocron.config.ts\");\n\t\treturn;\n\t}\n\n\tif (input.context.dryRun) {\n\t\tprint(`Would install ${config.skills.length} skill(s) for agent: ${config.agent}`);\n\t\tfor (const name of config.skills) {\n\t\t\tprint(` → would install: ${name}`);\n\t\t}\n\t\treturn;\n\t}\n\n\tprint(`Installing ${config.skills.length} skill(s) for agent: ${config.agent}`);\n\ttry {\n\t\tconst result = await installSkills({\n\t\t\tagent: config.agent,\n\t\t\tskills: config.skills,\n\t\t\trepoRoot: input.context.repoRoot,\n\t\t});\n\t\tprint(` → ${result}`);\n\t} catch (err) {\n\t\tprint(` ✗ ${err instanceof Error ? err.message : String(err)}`);\n\t}\n}\n\n// ── remove ───────────────────────────────────────────────────────────────────\n\nexport interface RunSkillsRemoveInput {\n\tcontext: RuntimeContext;\n\t/** Skill name(s) to remove. Omit to remove all installed skills. */\n\tnames?: string[];\n\texec?: ExecFn;\n}\n\nexport interface SkillsRemoveReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n}\n\nexport function runSkillsRemove(input: RunSkillsRemoveInput): SkillsRemoveReport {\n\tconst { dryRun, repoRoot } = input.context;\n\tconst exec = input.exec ?? defaultExec;\n\tconst args = [\"skills\", \"remove\", ...(input.names ?? [])];\n\n\tif (dryRun) {\n\t\tconsole.log(`Would run: npx ${args.join(\" \")}`);\n\t\treturn { status: \"dry-run\" };\n\t}\n\n\tconst { exitCode } = exec(\"npx\", args, { cwd: repoRoot });\n\treturn { status: exitCode === 0 ? \"ok\" : \"fail\" };\n}\n\n// ── update ───────────────────────────────────────────────────────────────────\n\nexport interface RunSkillsUpdateInput {\n\tcontext: RuntimeContext;\n\t/** When given, update only this skill. Omit to update all. */\n\tname?: string;\n\texec?: ExecFn;\n}\n\nexport interface SkillsUpdateReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n}\n\nexport function runSkillsUpdate(input: RunSkillsUpdateInput): SkillsUpdateReport {\n\tconst { dryRun, repoRoot } = input.context;\n\tconst exec = input.exec ?? defaultExec;\n\tconst args = [\"skills\", \"update\", ...(input.name ? [input.name] : [])];\n\n\tif (dryRun) {\n\t\tconsole.log(`Would run: npx ${args.join(\" \")}`);\n\t\treturn { status: \"dry-run\" };\n\t}\n\n\tconst { exitCode } = exec(\"npx\", args, { cwd: repoRoot });\n\treturn { status: exitCode === 0 ? \"ok\" : \"fail\" };\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { PackagesRegistry } from \"@theholocron/components-doc/markdown\";\nimport { generateReadme } from \"@theholocron/components-doc/markdown\";\nimport { getClients, getConfigs, getDocs, getPlugins, getSkills, getThemes, getUtils } from \"@theholocron/registry-doc\";\n\nimport type { LoadedConfig } from \"../load-config.js\";\nimport type { RuntimeContext } from \"../loader.js\";\nimport { style } from \"../ui/style.js\";\n\nconst MARKER_INSTALL_START = \"<!-- holocron:installation -->\";\nconst MARKER_INSTALL_END = \"<!-- /holocron:installation -->\";\n\nconst REGISTRY_MAP: Record<string, () => PackagesRegistry> = {\n\t\"@theholocron/clients\": getClients,\n\t\"@theholocron/configs\": getConfigs,\n\t\"@theholocron/docs\": getDocs,\n\t\"@theholocron/holocron\": getPlugins,\n\t\"@theholocron/skills\": getSkills,\n\t\"@theholocron/themes\": getThemes,\n\t\"@theholocron/utils\": getUtils,\n};\n\ninterface PackageJson {\n\tname?: string;\n\thomepage?: string;\n\tbin?: Record<string, string> | string;\n\tpeerDependencies?: Record<string, string>;\n\tscripts?: Record<string, string>;\n\tworkspaces?: string[];\n}\n\nexport interface RunSyncReadmeInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\tprint?: (line: string) => void;\n\treadFileFn?: (path: string, encoding: BufferEncoding) => Promise<string>;\n\twriteFileFn?: (path: string, content: string, encoding: BufferEncoding) => Promise<void>;\n}\n\nexport interface SyncReadmeReport {\n\tstatus: \"ok\" | \"fail\" | \"dry-run\";\n\tupdated: boolean;\n\tmessage?: string;\n}\n\nfunction generateInstallBlock(pkg: PackageJson): string {\n\tconst { name = \"\", bin, peerDependencies = {} } = pkg;\n\tconst isCli = Boolean(bin);\n\tconst isReact = Boolean(peerDependencies[\"react\"]);\n\tconst lines: string[] = [];\n\n\tlines.push(\"## Installation\", \"\");\n\n\tif (isCli) {\n\t\tlines.push(\"```bash\", `npm install --global ${name}`, \"```\");\n\t} else {\n\t\tlines.push(\"```bash\", `pnpm install ${name}`, \"```\");\n\t}\n\n\tlines.push(\"\", \"## Usage\", \"\");\n\n\tif (isCli) {\n\t\tconst commands =\n\t\t\ttypeof bin === \"string\" ? [name.split(\"/\").at(-1)!] : Object.keys(bin as Record<string, string>);\n\t\tlines.push(\"```bash\");\n\t\tfor (const cmd of commands) {\n\t\t\tlines.push(`${cmd} --help`);\n\t\t}\n\t\tlines.push(\"```\");\n\t} else if (isReact) {\n\t\tlines.push(\"```tsx\", `import { } from \"${name}\";`, \"\", \"function App() {\", ` return <></>;`, \"}\", \"```\");\n\t} else {\n\t\tlines.push(\"```typescript\", `import { } from \"${name}\";`, \"```\");\n\t}\n\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Replace content between `<!-- holocron:marker -->` / `<!-- /holocron:marker -->` tags.\n * Returns the updated README string, or the original if the marker pair is absent.\n */\nfunction replaceMarkerBlock(readme: string, marker: string, content: string): string {\n\tconst start = `<!-- holocron:${marker} -->`;\n\tconst end = `<!-- /holocron:${marker} -->`;\n\tconst lines = readme.split(\"\\n\");\n\tconst startIdx = lines.findIndex((l) => l.trim() === start);\n\tconst endIdx = lines.findIndex((l) => l.trim() === end);\n\tif (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return readme;\n\tlines.splice(startIdx + 1, endIdx - startIdx - 1, \"\", ...content.split(\"\\n\"), \"\");\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Apply all README updates in a single read-write cycle.\n * Returns true if the README was found (even if no changes were needed).\n */\nasync function updateReadme(\n\trepoRoot: string,\n\tinstallBlock: string,\n\tsections: Record<string, string>,\n\tdryRun: boolean,\n\treadFileFn: (path: string, encoding: BufferEncoding) => Promise<string>,\n\twriteFileFn: (path: string, content: string, encoding: BufferEncoding) => Promise<void>\n): Promise<boolean> {\n\tconst readmePath = join(repoRoot, \"README.md\");\n\tlet content: string;\n\ttry {\n\t\tcontent = await readFileFn(readmePath, \"utf8\");\n\t} catch {\n\t\treturn false;\n\t}\n\n\tlet updated = content;\n\n\t// Replace existing marker blocks for generated sections\n\tfor (const [marker, text] of Object.entries(sections)) {\n\t\tupdated = replaceMarkerBlock(updated, marker, text);\n\t}\n\n\t// Replace or insert installation block\n\tconst lines = updated.split(\"\\n\");\n\tconst startIdx = lines.findIndex((l) => l.trim() === MARKER_INSTALL_START);\n\tconst endIdx = lines.findIndex((l) => l.trim() === MARKER_INSTALL_END);\n\tconst blockLines = installBlock.split(\"\\n\");\n\n\tif (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {\n\t\tlines.splice(startIdx + 1, endIdx - startIdx - 1, \"\", ...blockLines, \"\");\n\t\tupdated = lines.join(\"\\n\");\n\t} else {\n\t\tconst descEnd = lines.findIndex((l) => l.trim() === \"<!-- /holocron:description -->\");\n\t\tconst insertAfter = descEnd !== -1 ? descEnd : lines.findIndex((l) => /^# /.test(l));\n\t\tif (insertAfter === -1) return false;\n\t\tlines.splice(insertAfter + 1, 0, \"\", MARKER_INSTALL_START, \"\", ...blockLines, \"\", MARKER_INSTALL_END);\n\t\tupdated = lines.join(\"\\n\");\n\t}\n\n\tif (!dryRun) {\n\t\tawait writeFileFn(readmePath, updated, \"utf8\");\n\t}\n\treturn true;\n}\n\nasync function updateIndexMdxDescription(\n\trepoRoot: string,\n\tdescription: string,\n\tdryRun: boolean,\n\treadFileFn: (path: string, encoding: BufferEncoding) => Promise<string>,\n\twriteFileFn: (path: string, content: string, encoding: BufferEncoding) => Promise<void>\n): Promise<void> {\n\tconst mdxPath = join(repoRoot, \"docs\", \"src\", \"content\", \"docs\", \"index.mdx\");\n\tlet content: string;\n\ttry {\n\t\tcontent = await readFileFn(mdxPath, \"utf8\");\n\t} catch {\n\t\treturn; // file doesn't exist — skip silently\n\t}\n\tconst updated = content.replace(/^(description:\\s*).*$/m, `$1${description}`);\n\tif (updated !== content && !dryRun) {\n\t\tawait writeFileFn(mdxPath, updated, \"utf8\");\n\t}\n}\n\nexport async function runSyncReadme(input: RunSyncReadmeInput): Promise<SyncReadmeReport> {\n\tconst { loaded, context, print = console.log, readFileFn = readFile, writeFileFn = writeFile } = input;\n\n\tconst { repoRoot, dryRun = false } = context;\n\n\tconst namespaces = loaded.resolved.env?.namespaces ?? [];\n\n\tprint(style.header(`Syncing README installation block${dryRun ? \" (dry-run)\" : \"\"}…`));\n\tif (namespaces.length > 0) {\n\t\tprint(style.hint(` namespaces: ${namespaces.join(\", \")}`));\n\t}\n\n\t// Read package.json\n\tlet pkg: PackageJson;\n\ttry {\n\t\tconst raw = await readFileFn(join(repoRoot, \"package.json\"), \"utf8\");\n\t\tpkg = JSON.parse(raw) as PackageJson;\n\t} catch {\n\t\treturn { status: \"fail\", updated: false, message: \"Could not read package.json\" };\n\t}\n\n\t// Assemble generated sections (4.3)\n\tconst description = loaded.resolved.description ?? \"\";\n\tconst homepage = loaded.resolved.homepage ?? pkg.homepage ?? \"\";\n\tconst scripts = pkg.scripts ?? {};\n\tconst packages = pkg.name ? REGISTRY_MAP[pkg.name]?.() : undefined;\n\n\tconst sections = generateReadme({ description, homepage, scripts, packages });\n\tconst markerSections: Record<string, string> = {\n\t\t...(sections.packages !== undefined && { packages: sections.packages }),\n\t\tdevelopment: sections.development,\n\t\treleases: sections.releases,\n\t};\n\n\t// Single read-write pass for all README changes\n\tconst installBlock = generateInstallBlock(pkg);\n\tconst updated = await updateReadme(repoRoot, installBlock, markerSections, dryRun, readFileFn, writeFileFn);\n\n\tif (!updated) {\n\t\tprint(style.warn(\"README.md not found or has no writable location for installation block\"));\n\t\treturn { status: \"fail\", updated: false, message: \"README.md update failed\" };\n\t}\n\n\t// Update docs/src/content/docs/index.mdx frontmatter description (4.4)\n\tif (description) {\n\t\tawait updateIndexMdxDescription(repoRoot, description, dryRun, readFileFn, writeFileFn);\n\t}\n\n\tprint(dryRun ? style.hint(\" would update README.md\") : style.success(\" updated README.md\"));\n\treturn { status: dryRun ? \"dry-run\" : \"ok\", updated };\n}\n","import { access, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AuthError } from \"../auth-resolver.js\";\nimport type { Source } from \"../capabilities/index.js\";\nimport type { LoadedConfig } from \"../load-config.js\";\nimport { PluginLoader, type RuntimeContext } from \"../loader.js\";\nimport type { SetupPrintLine, SetupReport, SetupStepResult } from \"./setup.js\";\nimport { CANONICAL_LABELS, STALE_LABELS } from \"./setup.js\";\nimport { runSyncReadme } from \"./sync-readme.js\";\n\nexport const SYNC_STEPS = [\n\t\"labels\",\n\t\"properties\",\n\t\"teams\",\n\t\"topics\",\n\t\"keywords\",\n\t\"description\",\n\t\"homepage\",\n\t\"readme\",\n] as const;\nexport type SyncStep = (typeof SYNC_STEPS)[number];\n\n// Steps that write to the local filesystem only — no provider token needed.\nconst LOCAL_STEPS = new Set<SyncStep>([\"keywords\", \"description\", \"homepage\", \"readme\"]);\n\nexport interface RunSyncInput {\n\tloaded: LoadedConfig;\n\tcontext: RuntimeContext;\n\tsteps?: string[];\n\tloader?: PluginLoader;\n\tprint?: SetupPrintLine;\n}\n\nexport async function runSync(input: RunSyncInput): Promise<SetupReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);\n\n\tconst config = input.loaded.resolved;\n\tconst dryRun = input.context.dryRun ?? false;\n\tconst requestedSteps = input.steps;\n\tconst steps: SetupStepResult[] = [];\n\n\t// Remote steps (labels, properties, topics) always need a provider token.\n\t// Local steps (keywords, description) write to disk and only optionally\n\t// push to GitHub. Load plugins eagerly when remote steps are requested;\n\t// for local-only runs, attempt a load for the optional GitHub sync but\n\t// swallow auth errors so the command works without a token.\n\tconst needsProvider = !requestedSteps || requestedSteps.some((s) => !LOCAL_STEPS.has(s as SyncStep));\n\tif (needsProvider) {\n\t\tawait loader.load();\n\t} else {\n\t\ttry {\n\t\t\tawait loader.load();\n\t\t} catch (err) {\n\t\t\t// Only swallow auth errors (missing token). Any other load failure\n\t\t\t// (bad plugin config, unresolvable package) is re-thrown so the\n\t\t\t// operator sees it rather than getting a silent GitHub-push miss.\n\t\t\tif (!(err instanceof AuthError)) throw err;\n\t\t}\n\t}\n\n\tprint(`Holocron sync — ${config.name}${dryRun ? \" (dry-run)\" : \"\"}`);\n\tprint(` config: ${input.loaded.filepath}`);\n\tprint(\"\");\n\n\tif (loader.has(\"source\")) {\n\t\tconst source = loader.get(\"source\") as Source;\n\t\tprint(\" → source\");\n\n\t\tfor (const stepName of SYNC_STEPS) {\n\t\t\tif (requestedSteps !== undefined && !requestedSteps.includes(stepName)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Local steps are handled below, outside this block.\n\t\t\tif (LOCAL_STEPS.has(stepName)) continue;\n\n\t\t\tif (stepName === \"labels\") {\n\t\t\t\tif (source.syncLabels) {\n\t\t\t\t\tsteps.push(\n\t\t\t\t\t\tawait runSyncStep(\"source\", \"sync labels\", dryRun, () =>\n\t\t\t\t\t\t\tsource.syncLabels!(CANONICAL_LABELS, STALE_LABELS)\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t} else {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync labels\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"provider does not implement syncLabels\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (stepName === \"properties\") {\n\t\t\t\tif (source.syncProperties) {\n\t\t\t\t\tconst repo = config.repo;\n\t\t\t\t\tconst properties: Record<string, string> = {};\n\t\t\t\t\tconst effectivePreset = repo?.protection;\n\t\t\t\t\tif (effectivePreset && effectivePreset !== \"none\")\n\t\t\t\t\t\tproperties[\"branch_protection_level\"] = effectivePreset;\n\t\t\t\t\tconst isMonorepo = await access(join(input.context.repoRoot, \"pnpm-workspace.yaml\"))\n\t\t\t\t\t\t.then(() => true)\n\t\t\t\t\t\t.catch(() => false);\n\t\t\t\t\tproperties[\"monorepo\"] = String(isMonorepo);\n\t\t\t\t\tconst manual = repo?.properties ?? {};\n\t\t\t\t\tif (manual.lifecycle) properties[\"lifecycle\"] = manual.lifecycle;\n\t\t\t\t\tif (manual.open_source !== undefined) properties[\"open_source\"] = String(manual.open_source);\n\t\t\t\t\tif (manual.runtime_environment) properties[\"runtime_environment\"] = manual.runtime_environment;\n\t\t\t\t\tif (manual.uses_external_packages !== undefined)\n\t\t\t\t\t\tproperties[\"uses_external_packages\"] = String(manual.uses_external_packages);\n\n\t\t\t\t\tsteps.push(\n\t\t\t\t\t\tawait runSyncStep(\"source\", \"sync properties\", dryRun, () => source.syncProperties!(properties))\n\t\t\t\t\t);\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t} else {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync properties\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"provider does not implement syncProperties\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (stepName === \"teams\") {\n\t\t\t\tconst teams = config.repo?.teams ?? [];\n\t\t\t\tif (teams.length === 0) {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync teams\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"no teams configured\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t} else if (source.syncTeams) {\n\t\t\t\t\tsteps.push(await runSyncStep(\"source\", \"sync teams\", dryRun, () => source.syncTeams!(teams)));\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\n\t\t\t\t\tconst repoCoord = input.context.repo ?? config.repo?.name ?? \"\";\n\t\t\t\t\tconst org = repoCoord.includes(\"/\") ? repoCoord.split(\"/\")[0]! : \"\";\n\t\t\t\t\tconst writeableTeams = teams\n\t\t\t\t\t\t.map((t) => (typeof t === \"string\" ? { slug: t, permission: \"push\" as const } : t))\n\t\t\t\t\t\t.filter((t) => [\"push\", \"maintain\", \"admin\"].includes(t.permission));\n\t\t\t\t\tif (org && writeableTeams.length > 0) {\n\t\t\t\t\t\tsteps.push(\n\t\t\t\t\t\t\tawait runSyncStep(\"source\", \"write .github/CODEOWNERS\", dryRun, async () => {\n\t\t\t\t\t\t\t\tconst content = writeableTeams.map((t) => `* @${org}/${t.slug}`).join(\"\\n\") + \"\\n\";\n\t\t\t\t\t\t\t\tawait source.writeRepoFile(\".github/CODEOWNERS\", content);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync teams\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"provider does not implement syncTeams\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (stepName === \"topics\") {\n\t\t\t\tconst topics = config.repo?.topics ?? [];\n\t\t\t\tif (topics.length === 0) {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync topics\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"no topics configured\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t} else if (source.syncTopics) {\n\t\t\t\t\tsteps.push(await runSyncStep(\"source\", \"sync topics\", dryRun, () => source.syncTopics!(topics)));\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t} else {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: \"sync topics\",\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: \"provider does not implement syncTopics\",\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Report unknown step names\n\t\tif (requestedSteps) {\n\t\t\tfor (const name of requestedSteps) {\n\t\t\t\tif (!(SYNC_STEPS as ReadonlyArray<string>).includes(name)) {\n\t\t\t\t\tsteps.push({\n\t\t\t\t\t\tcapability: \"source\",\n\t\t\t\t\t\tstep: `sync ${name}`,\n\t\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\t\tmessage: `unknown step \"${name}\"`,\n\t\t\t\t\t});\n\t\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── local-only steps (no provider token required) ──────────────────\n\t// keywords, description, homepage, and readme write to local files and\n\t// optionally push to GitHub when source is loaded. They run outside\n\t// the `if (loader.has(\"source\"))` block so they work without a token.\n\n\tfor (const stepName of [\"keywords\", \"description\", \"homepage\", \"readme\"] as const) {\n\t\tif (requestedSteps !== undefined && !requestedSteps.includes(stepName)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (stepName === \"keywords\") {\n\t\t\tconst topics = config.repo?.topics ?? [];\n\t\t\tif (topics.length === 0) {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"local\",\n\t\t\t\t\tstep: \"sync keywords\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"no topics configured\",\n\t\t\t\t});\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t} else {\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runSyncStep(\"local\", \"sync keywords\", dryRun, async () => {\n\t\t\t\t\t\tconst wrote = await writePackageJsonField(input.context.repoRoot, \"keywords\", topics);\n\t\t\t\t\t\treturn wrote\n\t\t\t\t\t\t\t? `${topics.length} keywords written`\n\t\t\t\t\t\t\t: `${topics.length} topics (no package.json)`;\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t}\n\t\t}\n\n\t\tif (stepName === \"description\") {\n\t\t\tconst description = config.description;\n\t\t\tif (!description) {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"local\",\n\t\t\t\t\tstep: \"sync description\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"no description configured\",\n\t\t\t\t});\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t} else {\n\t\t\t\tconst source = loader.has(\"source\") ? (loader.get(\"source\") as Source) : null;\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runSyncStep(\"local\", \"sync description\", dryRun, async () => {\n\t\t\t\t\t\tconst pkgWrote = await writePackageJsonField(\n\t\t\t\t\t\t\tinput.context.repoRoot,\n\t\t\t\t\t\t\t\"description\",\n\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst readmeWrote = await updateReadmeDescription(input.context.repoRoot, description);\n\t\t\t\t\t\tif (source?.syncDescription) {\n\t\t\t\t\t\t\tawait source.syncDescription(description);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst parts: string[] = [];\n\t\t\t\t\t\tif (pkgWrote) parts.push(\"package.json\");\n\t\t\t\t\t\tif (readmeWrote) parts.push(\"README.md\");\n\t\t\t\t\t\tif (source?.syncDescription) parts.push(\"GitHub\");\n\t\t\t\t\t\treturn parts.length > 0 ? parts.join(\", \") + \" updated\" : \"description synced\";\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t}\n\t\t}\n\n\t\tif (stepName === \"homepage\") {\n\t\t\tconst homepage = config.homepage;\n\t\t\tif (!homepage) {\n\t\t\t\tsteps.push({\n\t\t\t\t\tcapability: \"local\",\n\t\t\t\t\tstep: \"sync homepage\",\n\t\t\t\t\tstatus: \"skip\",\n\t\t\t\t\tmessage: \"no homepage configured\",\n\t\t\t\t});\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t} else {\n\t\t\t\tconst source = loader.has(\"source\") ? (loader.get(\"source\") as Source) : null;\n\t\t\t\tsteps.push(\n\t\t\t\t\tawait runSyncStep(\"local\", \"sync homepage\", dryRun, async () => {\n\t\t\t\t\t\tconst pkgWrote = await writePackageJsonField(input.context.repoRoot, \"homepage\", homepage);\n\t\t\t\t\t\tif (source?.syncHomepage) {\n\t\t\t\t\t\t\tawait source.syncHomepage(homepage);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst parts: string[] = [];\n\t\t\t\t\t\tif (pkgWrote) parts.push(\"package.json\");\n\t\t\t\t\t\tif (source?.syncHomepage) parts.push(\"GitHub\");\n\t\t\t\t\t\treturn parts.length > 0 ? parts.join(\", \") + \" updated\" : \"homepage synced\";\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t\t}\n\t\t}\n\n\t\tif (stepName === \"readme\") {\n\t\t\tconst report = await runSyncReadme({ loaded: input.loaded, context: input.context, print: () => {} });\n\t\t\tsteps.push({\n\t\t\t\tcapability: \"local\",\n\t\t\t\tstep: \"sync readme\",\n\t\t\t\tstatus: report.status === \"ok\" ? \"ok\" : report.status === \"dry-run\" ? \"dry-run\" : \"skip\",\n\t\t\t\t...(report.message ? { message: report.message } : {}),\n\t\t\t});\n\t\t\tprint(formatSyncStep(steps[steps.length - 1]!));\n\t\t}\n\t}\n\n\tconst summary = steps.reduce(\n\t\t(acc, s) => {\n\t\t\tif (s.status === \"ok\") acc.ok += 1;\n\t\t\telse if (s.status === \"fail\") acc.fail += 1;\n\t\t\telse if (s.status === \"skip\") acc.skip += 1;\n\t\t\telse if (s.status === \"dry-run\") acc.dryRun += 1;\n\t\t\treturn acc;\n\t\t},\n\t\t{ ok: 0, fail: 0, skip: 0, dryRun: 0 }\n\t);\n\n\tprint(\"\");\n\tprint(\n\t\t` ${summary.ok} ok, ${summary.fail} fail, ${summary.skip} skipped${\n\t\t\tdryRun ? `, ${summary.dryRun} would-do` : \"\"\n\t\t}`\n\t);\n\n\treturn { steps, summary };\n}\n\nasync function runSyncStep(\n\tcapability: string,\n\tstep: string,\n\tdryRun: boolean,\n\tbody: () => Promise<string | void>\n): Promise<SetupStepResult> {\n\tif (dryRun) {\n\t\treturn { capability, step, status: \"dry-run\" };\n\t}\n\ttry {\n\t\tconst note = await body();\n\t\tconst result: SetupStepResult = { capability, step, status: \"ok\" };\n\t\tif (typeof note === \"string\") result.message = note;\n\t\treturn result;\n\t} catch (err) {\n\t\treturn {\n\t\t\tcapability,\n\t\t\tstep,\n\t\t\tstatus: \"fail\",\n\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t};\n\t}\n}\n\nfunction formatSyncStep(step: SetupStepResult): string {\n\tconst icon = step.status === \"ok\" ? \"✓\" : step.status === \"fail\" ? \"✗\" : step.status === \"dry-run\" ? \"…\" : \"·\";\n\tconst detail = step.message ? ` (${step.message})` : \"\";\n\treturn ` ${icon} ${step.step}${detail}`;\n}\n\nasync function writePackageJsonField(repoRoot: string, field: string, value: unknown): Promise<boolean> {\n\tconst pkgPath = join(repoRoot, \"package.json\");\n\tlet content: string;\n\ttry {\n\t\tcontent = await readFile(pkgPath, \"utf8\");\n\t} catch {\n\t\treturn false;\n\t}\n\tconst pkg = JSON.parse(content) as Record<string, unknown>;\n\tpkg[field] = value;\n\tawait writeFile(pkgPath, JSON.stringify(pkg, null, 2) + \"\\n\", \"utf8\");\n\treturn true;\n}\n\nconst README_DESC_START = \"<!-- holocron:description -->\";\nconst README_DESC_END = \"<!-- /holocron:description -->\";\n\nasync function updateReadmeDescription(repoRoot: string, description: string): Promise<boolean> {\n\tconst readmePath = join(repoRoot, \"README.md\");\n\tlet content: string;\n\ttry {\n\t\tcontent = await readFile(readmePath, \"utf8\");\n\t} catch {\n\t\treturn false;\n\t}\n\tconst lines = content.split(\"\\n\");\n\n\tconst startIdx = lines.findIndex((l) => l.trim() === README_DESC_START);\n\tconst endIdx = lines.findIndex((l) => l.trim() === README_DESC_END);\n\tif (startIdx !== -1) {\n\t\tif (endIdx === -1 || endIdx <= startIdx) return false;\n\t\tlines.splice(startIdx + 1, endIdx - startIdx - 1, description);\n\t\tawait writeFile(readmePath, lines.join(\"\\n\"), \"utf8\");\n\t\treturn true;\n\t}\n\n\tconst h1Index = lines.findIndex((l) => /^# /.test(l));\n\tif (h1Index === -1) return false;\n\n\tlines.splice(h1Index + 1, 0, \"\", README_DESC_START, description, README_DESC_END);\n\tawait writeFile(readmePath, lines.join(\"\\n\"), \"utf8\");\n\treturn true;\n}\n","name: Auto Commit\ndescription: >\n Commit and push any file changes using stefanzweifel/git-auto-commit-action.\n If a branch name is provided and differs from the current branch, a new branch\n is created automatically.\n\ninputs:\n token:\n description: >\n GitHub token with push access to the target branch. Used to authenticate\n the git remote so the commit can be pushed.\n required: true\n branch:\n description: >\n Branch to commit to. Leave empty to commit to the current branch (useful\n in PR contexts). Provide an explicit name (e.g. chore/auto-sync) to push\n to a separate branch.\n required: false\n default: \"\"\n commit-message:\n description: Commit message.\n required: true\n commit-options:\n description: >\n Additional options passed to git commit (e.g. --no-verify).\n required: false\n default: \"\"\n commit-user-name:\n description: Git user.name for the commit.\n required: false\n default: \"github-actions[bot]\"\n commit-user-email:\n description: Git user.email for the commit.\n required: false\n default: \"41898282+github-actions[bot]@users.noreply.github.com\"\n commit-author:\n description: >\n Git author string in \"Name <email>\" format.\n required: false\n default: \"github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>\"\n\noutputs:\n changes-detected:\n description: \"'true' if any files were committed, 'false' otherwise.\"\n value: ${{ steps.commit.outputs.changes_detected }}\n\nruns:\n using: composite\n steps:\n - name: Configure git remote with token\n shell: bash\n run: |\n REMOTE_URL=$(git remote get-url origin)\n AUTHED_URL=$(echo \"$REMOTE_URL\" | sed \"s|https://|https://x-access-token:${TOKEN}@|\")\n git remote set-url origin \"$AUTHED_URL\"\n env:\n TOKEN: ${{ inputs.token }}\n\n - name: Reset branch to current HEAD\n if: ${{ inputs.branch != '' }}\n shell: bash\n run: git checkout -B \"$BRANCH\"\n env:\n BRANCH: ${{ inputs.branch }}\n\n - uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7.2.0\n id: commit\n with:\n branch: ${{ inputs.branch }}\n commit_message: ${{ inputs.commit-message }}\n commit_options: ${{ inputs.commit-options }}\n commit_user_name: ${{ inputs.commit-user-name }}\n commit_user_email: ${{ inputs.commit-user-email }}\n commit_author: ${{ inputs.commit-author }}\n","name: Install dependencies\ndescription: Install project dependencies with pnpm frozen lockfile.\n\nruns:\n using: composite\n\n steps:\n - name: Install dependencies\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n shell: bash\n run: pnpm install --frozen-lockfile\n","name: Setup\ndescription: Prepare the environment and install project dependencies.\n\ninputs:\n node-version:\n description: Node.js version\n required: false\n default: \"22.x\"\n\nruns:\n using: composite\n\n steps:\n - uses: theholocron/.github/.github/actions/setup-node@main\n with:\n node-version: ${{ inputs.node-version }}\n\n - uses: theholocron/.github/.github/actions/install@main\n\n - name: Cache Turbo artifacts\n if: ${{ hashFiles('turbo.json') != '' }}\n uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0\n with:\n path: .turbo\n key: turbo-${{ runner.os }}-${{ github.sha }}\n restore-keys: |\n turbo-${{ runner.os }}-\n","name: Setup Node\ndescription: Install pnpm and Node.js with pnpm dependency caching.\n\ninputs:\n node-version:\n description: Node.js version\n required: false\n default: \"22.x\"\nruns:\n using: composite\n\n steps:\n - name: Setup pnpm\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4\n\n - name: Setup Node.js\n uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0\n with:\n node-version: ${{ hashFiles('.node-version') != '' && '' || inputs.node-version }}\n node-version-file: ${{ hashFiles('.node-version') != '' && '.node-version' || '' }}\n cache: ${{ hashFiles('pnpm-lock.yaml') != '' && 'pnpm' || '' }}\n # Do NOT add registry-url here. setup-node writes .npmrc with\n # _authToken=${NODE_AUTH_TOKEN} and sets NPM_CONFIG_USERCONFIG to it.\n # pnpm reads that file, fails env-var substitution when the token is\n # empty, and loses auth entirely. Without registry-url, pnpm 10.15+\n # handles Trusted Publishing via its own native OIDC exchange.\n\n - name: Add node_modules/.bin to PATH\n shell: bash\n run: echo \"$GITHUB_WORKSPACE/node_modules/.bin\" >> $GITHUB_PATH\n","name: Audit\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n build-script:\n description: Script to build and upload bundle stats to Codecov\n type: string\n required: false\n default: pnpm build\n run-knip:\n description: Run Knip to detect unused files, exports, and dependencies\n type: boolean\n required: false\n default: false\n run-performance:\n description: Run Lighthouse CI performance audit (requires a lighthouse config file)\n type: boolean\n required: false\n default: false\n lighthouse-config:\n description: >\n Path to the Lighthouse CI config file passed as --config to lhci autorun.\n Defaults to lighthouse.config.cjs (the org standard).\n type: string\n required: false\n default: lighthouse.config.cjs\n knip-script:\n description: Script that invokes Knip (must exit non-zero on findings)\n type: string\n required: false\n default: pnpm run audit\n secrets:\n CODECOV_TOKEN:\n required: false\n LHCI_GITHUB_APP_TOKEN:\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n bundle-size:\n name: Audit the bundle size\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: eval \"$BUILD_SCRIPT\"\n name: Build and upload bundle stats\n env:\n BUILD_SCRIPT: ${{ inputs.build-script }}\n CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}\n\n knip:\n name: Knip\n if: ${{ inputs.run-knip }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n persist-credentials: false\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: eval \"$KNIP_SCRIPT\"\n name: Run Knip\n env:\n KNIP_SCRIPT: ${{ inputs.knip-script }}\n\n performance:\n name: Audit the performance\n if: ${{ inputs.run-performance }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: npm install -g @lhci/cli@0.14.x\n name: Install Lighthouse CLI\n\n - run: lhci autorun --config=\"$LIGHTHOUSE_CONFIG\"\n name: Run Lighthouse CI\n env:\n LIGHTHOUSE_CONFIG: ${{ inputs.lighthouse-config }}\n LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}\n","name: Bookkeeping\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n configuration-path:\n description: Path to the labeler configuration file in the calling repo\n type: string\n required: false\n default: .github/labeler.yml\n\njobs:\n label:\n name: Apply Labels\n permissions:\n contents: read\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n sparse-checkout: ${{ inputs.configuration-path || '.github/labeler.yml' }}\n sparse-checkout-cone-mode: false\n\n - uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4\n if: ${{ github.event_name == 'pull_request' && hashFiles(inputs.configuration-path || '.github/labeler.yml') != '' }}\n # v3.4 bundles Node 20; allow it to run under Actions' current default.\n env:\n ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true\n with:\n # Fall back to default path when triggered directly (not via workflow_call)\n # because inputs.* defaults only apply on workflow_call events.\n configuration-path: ${{ inputs.configuration-path || '.github/labeler.yml' }}\n include-title: 1\n include-body: 0\n sync-labels: 1\n enable-versioned-regex: 0\n repo-token: ${{ github.token }}\n","name: Clean up Preview\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n cloudflare-project:\n description: >\n Cloudflare Pages project name. Falls back to the CLOUDFLARE_PAGES_PROJECT\n org variable when omitted.\n required: false\n type: string\n default: \"\"\n\njobs:\n cleanup:\n name: Clean up Preview\n runs-on: ubuntu-latest\n permissions:\n contents: read\n deployments: write\n pull-requests: write\n steps:\n - name: Delete Cloudflare Pages deployments for branch\n if: ${{ inputs.cloudflare-project != '' || vars.CLOUDFLARE_PAGES_PROJECT != '' }}\n env:\n CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}\n CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}\n PROJECT: ${{ inputs.cloudflare-project || vars.CLOUDFLARE_PAGES_PROJECT }}\n BRANCH: ${{ github.event.repository.name }}-pr-${{ github.event.pull_request.number }}\n GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n run: |\n DEPLOYMENTS=$(curl -s \\\n \"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/${PROJECT}/deployments\" \\\n -H \"Authorization: Bearer ${CLOUDFLARE_API_TOKEN}\" \\\n | jq -r --arg b \"$BRANCH\" \\\n '.result[] | select(.deployment_trigger.metadata.branch == $b) | .id')\n\n if [ -z \"$DEPLOYMENTS\" ]; then\n echo \"No deployments found for branch ${BRANCH} — nothing to clean up.\"\n exit 0\n fi\n\n for id in $DEPLOYMENTS; do\n echo \"Deleting CF Pages deployment: $id\"\n curl -s -X DELETE \\\n \"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/${PROJECT}/deployments/${id}?force=true\" \\\n -H \"Authorization: Bearer ${CLOUDFLARE_API_TOKEN}\" | jq -r 'if .success then \" ✓ deleted\" else \" ✗ \\(.errors[0].message)\" end'\n done\n\n # Mark the GitHub Deployment environment as inactive.\n ENV_NAME=\"${PROJECT} (Preview)\"\n gh api \"repos/${GITHUB_REPOSITORY}/deployments\" \\\n | jq -r \".[] | select(.environment == \\\"${ENV_NAME}\\\") | .id\" \\\n | while read -r deploy_id; do\n gh api \"repos/${GITHUB_REPOSITORY}/deployments/${deploy_id}/statuses\" \\\n --method POST --field state=inactive 2>/dev/null || true\n done\n","name: CodeQL\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n language:\n description: CodeQL language to analyze\n type: string\n required: false\n default: javascript-typescript\n\njobs:\n analyze:\n name: Analyze (${{ inputs.language }})\n permissions:\n actions: read\n contents: read\n security-events: write\n runs-on: ubuntu-latest\n timeout-minutes: 45\n # Do not cancel in-progress security scans.\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0\n name: Initialize CodeQL\n with:\n languages: ${{ inputs.language }}\n\n - uses: github/codeql-action/autobuild@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0\n name: Autobuild\n\n - uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0\n name: Analyze\n with:\n category: /language:${{ inputs.language }}\n","name: Dependencies\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n merge-token:\n description: >\n Optional privileged token for auto-merge. Falls back to GITHUB_TOKEN.\n Required when branch protection enforces required reviews — GITHUB_TOKEN\n cannot approve its own PRs.\n required: false\n\njobs:\n dependabot:\n name: Update the dependencies\n permissions:\n contents: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n if: github.event.pull_request.user.login == 'dependabot[bot]'\n steps:\n - uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0\n name: Fetch Dependabot metadata\n id: metadata\n\n - run: gh pr merge --auto --squash \"$PR_URL\"\n # --squash is intentional: repo protection sets allow_merge_commit: false,\n # so --merge would fail on any repo using the standard preset.\n name: Enable auto-merge for Dependabot PRs\n if: steps.metadata.outputs.update-type == 'version-update:semver-patch'\n env:\n PR_URL: ${{ github.event.pull_request.html_url }}\n GH_TOKEN: ${{ secrets.merge-token || github.token }}\n","name: Deploy\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n type:\n description: \"Type of deployment: docs or storybook\"\n required: true\n type: string\n name:\n description: Repo name prefix used to filter the docs site package (<name>-site); omit to run pnpm -C docs build\n required: false\n type: string\n default: \"\"\n storybook-projects:\n description: >\n JSON array of { \"name\"?, \"workingDir\", \"outputDir\"? } objects for storybook deploys.\n Each is built via `pnpm -C <workingDir> build:storybook`. If \"name\" is provided the\n output is placed under `sandbox/<name>/`; omit \"name\" for single-repo deploys and the\n output lands directly in `sandbox/`.\n type: string\n required: false\n default: \"[]\"\n build-script:\n description: pnpm script that builds the Storybook static output (single storybook, type:storybook only)\n type: string\n required: false\n default: build:storybook\n output-dir:\n description: Directory where Storybook writes its static output (single storybook, type:storybook only)\n type: string\n required: false\n default: storybook-static\n\njobs:\n deploy:\n name: Deploy\n runs-on: ubuntu-latest\n permissions:\n contents: read\n pages: write\n id-token: write\n environment:\n name: github-pages\n url: ${{ steps.deployment.outputs.page_url }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Build docs site\n if: ${{ inputs.type == 'docs' && inputs.name != '' }}\n env:\n SITE_NAME: ${{ inputs.name }}\n run: pnpm --filter @theholocron/\"$SITE_NAME\"-site build\n\n - name: Build docs site\n if: ${{ inputs.type == 'docs' && inputs.name == '' }}\n run: pnpm -C docs build\n\n - name: Build Storybook projects\n if: ${{ inputs.storybook-projects != '[]' }}\n env:\n PROJECTS: ${{ inputs.storybook-projects }}\n run: |\n echo \"$PROJECTS\" | jq -c '.[]' | while IFS= read -r project; do\n workingDir=$(echo \"$project\" | jq -r '.workingDir')\n pnpm -C \"$workingDir\" build:storybook\n done\n\n - name: Build Storybook\n if: ${{ inputs.type == 'storybook' && inputs.storybook-projects == '[]' }}\n env:\n BUILD_SCRIPT: ${{ inputs.build-script }}\n run: pnpm run \"$BUILD_SCRIPT\"\n\n - name: Assemble site\n env:\n DEPLOY_TYPE: ${{ inputs.type }}\n PROJECTS: ${{ inputs.storybook-projects }}\n STORYBOOK_OUTPUT_DIR: ${{ inputs.output-dir }}\n run: |\n mkdir -p _site\n if [ \"$DEPLOY_TYPE\" = \"docs\" ]; then\n cp -r docs/dist/. _site/\n fi\n if [ \"$PROJECTS\" != \"[]\" ]; then\n echo \"$PROJECTS\" | jq -c '.[]' | while IFS= read -r project; do\n name=$(echo \"$project\" | jq -r '.name // \"\"')\n workingDir=$(echo \"$project\" | jq -r '.workingDir')\n outputDir=$(echo \"$project\" | jq -r '.outputDir // \"storybook-static\"')\n if [ -n \"$name\" ]; then\n target=\"_site/sandbox/${name}\"\n else\n target=\"_site/sandbox\"\n fi\n mkdir -p \"$target\"\n cp -r \"${workingDir}/${outputDir}/.\" \"$target/\"\n done\n elif [ \"$DEPLOY_TYPE\" = \"storybook\" ]; then\n mkdir -p _site/sandbox\n cp -r \"${STORYBOOK_OUTPUT_DIR}/.\" _site/sandbox/\n fi\n\n - uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1\n name: Upload pages artifact\n with:\n path: _site\n\n - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5\n id: deployment\n name: Deploy to GitHub Pages\n","name: Deploy Preview\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n type:\n description: \"Type of deployment: docs or storybook\"\n required: true\n type: string\n name:\n description: Repo name prefix used to filter the docs site package (<name>-site); omit to run pnpm -C docs build\n required: false\n type: string\n default: \"\"\n storybook-projects:\n description: >\n JSON array of { \"name\"?, \"workingDir\", \"outputDir\"? } objects for storybook deploys.\n Each is built via `pnpm -C <workingDir> build:storybook`. If \"name\" is provided the\n output is placed under `sandbox/<name>/`; omit \"name\" for single-repo deploys and the\n output lands directly in `sandbox/`.\n type: string\n required: false\n default: \"[]\"\n build-script:\n description: pnpm script that builds the Storybook static output (single storybook, type:storybook only)\n type: string\n required: false\n default: build:storybook\n output-dir:\n description: Directory where Storybook writes its static output (single storybook, type:storybook only)\n type: string\n required: false\n default: storybook-static\n cloudflare-project:\n description: >\n Cloudflare Pages project name. Falls back to the CLOUDFLARE_PAGES_PROJECT\n org variable when omitted — set that variable once and all repos get previews\n without per-repo config.\n required: false\n type: string\n default: \"\"\n\njobs:\n deploy-preview:\n name: Deploy Preview\n runs-on: ubuntu-latest\n permissions:\n contents: read\n deployments: write\n pull-requests: write\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Build docs site\n if: ${{ inputs.type == 'docs' && inputs.name != '' }}\n env:\n SITE_NAME: ${{ inputs.name }}\n run: pnpm --filter @theholocron/\"$SITE_NAME\"-site build\n\n - name: Build docs site\n if: ${{ inputs.type == 'docs' && inputs.name == '' }}\n run: pnpm -C docs build\n\n - name: Build Storybook projects\n if: ${{ inputs.storybook-projects != '[]' }}\n env:\n PROJECTS: ${{ inputs.storybook-projects }}\n run: |\n echo \"$PROJECTS\" | jq -c '.[]' | while IFS= read -r project; do\n workingDir=$(echo \"$project\" | jq -r '.workingDir')\n pnpm -C \"$workingDir\" build:storybook\n done\n\n - name: Build Storybook\n if: ${{ inputs.type == 'storybook' && inputs.storybook-projects == '[]' }}\n env:\n BUILD_SCRIPT: ${{ inputs.build-script }}\n run: pnpm run \"$BUILD_SCRIPT\"\n\n - name: Assemble site\n env:\n DEPLOY_TYPE: ${{ inputs.type }}\n SITE_NAME: ${{ inputs.name }}\n PROJECTS: ${{ inputs.storybook-projects }}\n STORYBOOK_OUTPUT_DIR: ${{ inputs.output-dir }}\n run: |\n mkdir -p _site\n if [ \"$DEPLOY_TYPE\" = \"docs\" ]; then\n if [ -n \"$SITE_NAME\" ]; then\n # Site built with base: /<name>/ — nest under _site/<name>/ so asset\n # paths match (/name/_astro/... → served at /name/_astro/...).\n mkdir -p \"_site/${SITE_NAME}\"\n cp -r docs/dist/. \"_site/${SITE_NAME}/\"\n # Redirect root to the base path so the preview URL lands correctly.\n printf \"/ /%s/ 301\\n\" \"$SITE_NAME\" > _site/_redirects\n else\n cp -r docs/dist/. _site/\n fi\n fi\n if [ \"$PROJECTS\" != \"[]\" ]; then\n echo \"$PROJECTS\" | jq -c '.[]' | while IFS= read -r project; do\n name=$(echo \"$project\" | jq -r '.name // \"\"')\n workingDir=$(echo \"$project\" | jq -r '.workingDir')\n outputDir=$(echo \"$project\" | jq -r '.outputDir // \"storybook-static\"')\n if [ -n \"$name\" ]; then\n target=\"_site/sandbox/${name}\"\n else\n target=\"_site/sandbox\"\n fi\n mkdir -p \"$target\"\n cp -r \"${workingDir}/${outputDir}/.\" \"$target/\"\n done\n elif [ \"$DEPLOY_TYPE\" = \"storybook\" ]; then\n mkdir -p _site/sandbox\n cp -r \"${STORYBOOK_OUTPUT_DIR}/.\" _site/sandbox/\n fi\n\n - name: Install Wrangler\n # The action's install step runs npm/pnpm in the repo root; pnpm fails\n # because it rejects adding to a workspace root without -w, and npm fails\n # because package.json contains pnpm catalog: references it cannot parse.\n # Pre-installing from /tmp (no package.json) lets the action find wrangler\n # already on PATH and skip its own install entirely.\n working-directory: /tmp\n run: npm install -g wrangler@4\n\n - uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4.0.0\n id: deploy\n name: Deploy to Cloudflare Pages\n # Skip when neither the per-repo input nor the org variable is set.\n if: ${{ inputs.cloudflare-project != '' || vars.CLOUDFLARE_PAGES_PROJECT != '' }}\n with:\n apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}\n accountId: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}\n packageManager: npm\n command: >-\n pages deploy _site\n --project-name ${{ inputs.cloudflare-project || vars.CLOUDFLARE_PAGES_PROJECT }}\n --branch ${{ github.event.repository.name }}-pr-${{ github.event.pull_request.number }}\n --commit-dirty=true\n\n - name: Report preview URL\n if: ${{ steps.deploy.outputs.pages-deployment-alias-url != '' }}\n env:\n GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n ALIAS: ${{ steps.deploy.outputs.pages-deployment-alias-url }}\n SITE_NAME: ${{ inputs.name }}\n PROJECT: ${{ inputs.cloudflare-project || vars.CLOUDFLARE_PAGES_PROJECT }}\n run: |\n PREVIEW_URL=\"${ALIAS%/}${SITE_NAME:+/${SITE_NAME}}/\"\n # GITHUB_HEAD_REF is the PR branch name — links the deployment to this PR's sidebar widget.\n PAYLOAD=$(printf '{\"ref\":\"%s\",\"environment\":\"%s\",\"description\":\"Cloudflare Pages\",\"production_environment\":false,\"auto_merge\":false,\"required_contexts\":[]}' \\\n \"$GITHUB_HEAD_REF\" \"${PROJECT} (Preview)\")\n DEPLOY_ID=$(echo \"$PAYLOAD\" | gh api \"repos/${GITHUB_REPOSITORY}/deployments\" \\\n --method POST --input - | jq -r '.id')\n gh api \"repos/${GITHUB_REPOSITORY}/deployments/${DEPLOY_ID}/statuses\" \\\n --method POST --field state=success --field environment_url=\"${PREVIEW_URL}\"\n","name: Greetings\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n\njobs:\n greeting:\n name: Greet first-time contributors\n permissions:\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n # Group by the issue/PR number so duplicate events don't race each other.\n steps:\n - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0\n name: Greet on first contribution\n with:\n script: |\n // Only greet on the initial open — ignore synchronize, reopened, etc.\n if (context.payload.action !== 'opened') return;\n\n const actor = context.actor;\n const { owner, repo } = context.repo;\n\n // Payload inspection is more reliable than context.eventName for detecting\n // whether this is an issue vs. PR event — works regardless of how GitHub\n // propagates event names through workflow_call chains.\n const isIssue = !!context.payload.issue && !context.payload.pull_request;\n // listForRepo returns both issues and PRs (GitHub treats PRs as issues),\n // sorted newest-first. Filter by type to track first-issue and first-PR\n // independently, and avoid search-index eventual-consistency lag.\n const { data: recent } = await github.rest.issues.listForRepo({\n owner, repo,\n creator: actor,\n state: 'all',\n per_page: 100\n });\n\n const sameType = recent.filter(item =>\n isIssue ? !item.pull_request : !!item.pull_request\n );\n\n if (sameType.length !== 1) return;\n const body = isIssue\n ? `Hey @${actor}!\\n\\nWe really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we are a limited number of volunteers, so it is possible that this will not be addressed as swiftly.\\n\\nYour patience is much appreciated and we will get back to you as quickly as possible.`\n : `Hey @${actor}!\\n\\nWe really appreciate you taking the time to help out with this PR. The collaborators on this project attempt to help as many people as possible, but we are a limited number of volunteers, so it is possible that this will not be addressed as swiftly.\\n\\nYour patience is much appreciated and we will get back to you as quickly as possible.`;\n\n await github.rest.issues.createComment({\n owner,\n repo,\n issue_number: context.issue.number,\n body\n });\n","name: Lint\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n eslint-config:\n description: >\n Filename for the ESLint flat config used by super-linter for\n JavaScript, JSX, TSX, and TypeScript (ES) files. Defaults to\n eslint.config.ts (the org standard). Note: ESLint 9 requires\n --flag unstable_ts_config to load .ts configs; if super-linter\n cannot load it, override with eslint.config.mjs or eslint.config.js.\n type: string\n required: false\n default: eslint.config.ts\n prettier-config:\n description: >\n Filename for the Prettier config. Defaults to prettier.config.ts\n (the org standard). Prettier 3.x loads .ts configs natively.\n type: string\n required: false\n default: prettier.config.ts\n yaml-config:\n description: >\n Filename for the yamllint config. Defaults to yamllint.config.yml.\n type: string\n required: false\n default: yamllint.config.yml\n enable-auto-commit:\n description: >\n Auto-commit super-linter fixes as a verified commit via a GitHub App.\n Requires SUPER_LINTER_APP_ID and SUPER_LINTER_PRIVATE_KEY secrets.\n type: boolean\n required: false\n default: false\n secrets:\n SUPER_LINTER_APP_ID:\n required: false\n SUPER_LINTER_PRIVATE_KEY:\n required: false\n\njobs:\n super-lint:\n name: Lint entire codebase\n permissions:\n contents: write\n issues: write\n statuses: write\n runs-on: ubuntu-latest\n timeout-minutes: 30\n env:\n APP_ID_SET: ${{ secrets.SUPER_LINTER_APP_ID != '' }}\n steps:\n - name: Generate GitHub App token\n id: app-token\n # Runs before checkout so the token is used as the checkout credential,\n # which makes the subsequent push go through the App and produce a\n # Verified commit. Skipped when auto-commit is disabled or secrets unset.\n if: >\n inputs.enable-auto-commit == true &&\n github.event.pull_request != null &&\n github.event.pull_request.head.repo.full_name == github.repository &&\n github.ref_name != github.event.repository.default_branch &&\n env.APP_ID_SET == 'true'\n uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0\n with:\n app-id: ${{ secrets.SUPER_LINTER_APP_ID }}\n private-key: ${{ secrets.SUPER_LINTER_PRIVATE_KEY }}\n\n - name: Resolve App bot identity\n id: app-bot\n # GitHub marks commits as Verified when the author email matches the\n # App bot's noreply address (<numeric-id>+<slug>[bot]@users.noreply.github.com).\n # The numeric ID must be fetched via the API — it differs from the App ID.\n # app-slug is passed via env rather than interpolated into the script to\n # prevent code injection (CWE-78).\n if: steps.app-token.conclusion == 'success'\n run: |\n BOT_SLUG=\"${APP_SLUG}[bot]\"\n BOT_ID=$(gh api \"/users/${BOT_SLUG}\" --jq .id)\n echo \"name=${BOT_SLUG}\" >> \"$GITHUB_OUTPUT\"\n echo \"email=${BOT_ID}+${BOT_SLUG}@users.noreply.github.com\" >> \"$GITHUB_OUTPUT\"\n env:\n GH_TOKEN: ${{ steps.app-token.outputs.token }}\n APP_SLUG: ${{ steps.app-token.outputs.app-slug }}\n\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n # Use the App token when available so the push credential is the App\n # bot — GitHub marks those commits as Verified automatically.\n token: ${{ steps.app-token.outputs.token || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n\n - name: Detect project features\n # Writes VALIDATE_*/FIX_* to GITHUB_ENV only when the feature exists.\n # Also writes step outputs for values referenced in expression context\n # (GITHUB_ENV is not readable via steps.*.outputs — they need GITHUB_OUTPUT).\n # All values written are hardcoded 'true' — no user input in the script.\n # Config file paths (inputs.*) stay in GH Actions expression context in\n # the super-linter env: block below, never shell-evaluated (CWE-78).\n id: detect\n run: |\n has() { find . -not -path '*/node_modules/*' -name \"$1\" -print -quit 2>/dev/null | grep -q .; }\n\n if { has 'eslint.config.ts' || has 'eslint.config.mjs' || has 'eslint.config.js' || has '.eslintrc.json' || has '.eslintrc.yml'; }; then\n {\n echo \"VALIDATE_JAVASCRIPT_ES=true\"\n echo \"VALIDATE_TYPESCRIPT_ES=true\"\n } >> \"$GITHUB_ENV\"\n echo \"eslint=true\" >> \"$GITHUB_OUTPUT\"\n fi\n\n if { has '*.js' || has '*.jsx' || has '*.mjs' || has '*.cjs' || has '*.ts' || has '*.tsx'; }; then\n {\n echo \"VALIDATE_JAVASCRIPT_PRETTIER=true\"\n echo \"VALIDATE_JSX_PRETTIER=true\"\n echo \"VALIDATE_TYPESCRIPT_PRETTIER=true\"\n echo \"VALIDATE_TSX=true\"\n echo \"FIX_JAVASCRIPT_PRETTIER=true\"\n echo \"FIX_JSX_PRETTIER=true\"\n echo \"FIX_TYPESCRIPT_PRETTIER=true\"\n echo \"FIX_TSX=true\"\n } >> \"$GITHUB_ENV\"\n fi\n\n if { has '*.css' || has '*.scss' || has 'stylelint.config.ts' || has 'stylelint.config.mjs' || has 'stylelint.config.js'; }; then\n {\n echo \"VALIDATE_CSS=true\"\n echo \"STYLELINT_CONFIG_FILE=stylelint.config.ts\"\n } >> \"$GITHUB_ENV\"\n fi\n\n if { has '*.graphql' || has '*.gql'; }; then\n {\n echo \"VALIDATE_GRAPHQL_PRETTIER=true\"\n echo \"FIX_GRAPHQL_PRETTIER=true\"\n } >> \"$GITHUB_ENV\"\n fi\n\n if { has '*.html' || has '*.htm'; }; then\n {\n echo \"VALIDATE_HTML_PRETTIER=true\"\n echo \"FIX_HTML_PRETTIER=true\"\n } >> \"$GITHUB_ENV\"\n fi\n\n if { has '.env' || has '.env.example' || has '.env.local'; }; then\n {\n echo \"VALIDATE_ENV=true\"\n echo \"FIX_ENV=true\"\n } >> \"$GITHUB_ENV\"\n fi\n\n if { has 'Dockerfile' || has '*.Dockerfile'; }; then\n echo \"VALIDATE_DOCKERFILE=true\" >> \"$GITHUB_ENV\"\n fi\n\n - uses: super-linter/super-linter/slim@4ce20838b8ab83717e78138c5b3a1407148e0918 # v8.7.0\n name: Run Super Linter\n env:\n GITHUB_TOKEN: ${{ github.token }}\n DEFAULT_BRANCH: ${{ github.event.pull_request.base.ref || github.event.repository.default_branch }}\n ANNOTATE_ONLY: true\n DISABLE_COMMENTS: false\n IGNORE_GITIGNORED_FILES: true\n LINTER_RULES_PATH: /\n EDITORCONFIG_FILE_NAME: \".editorconfig-checker.json\"\n # Config file paths — inputs stay in expression context, never shell-evaluated.\n # When VALIDATE_JAVASCRIPT_ES is not set by detect, ESLint doesn't run so\n # the empty-string fallback (→ eslint.config.mjs in container) is safe.\n JAVASCRIPT_ES_CONFIG_FILE: ${{ steps.detect.outputs.eslint == 'true' && inputs.eslint-config || '' }}\n TYPESCRIPT_ES_CONFIG_FILE: ${{ steps.detect.outputs.eslint == 'true' && inputs.eslint-config || '' }}\n PRETTIER_CONFIG: ${{ inputs.prettier-config }}\n YAML_CONFIG_FILE: ${{ inputs.yaml-config }}\n # Always-on linters\n FIX_MARKDOWN_PRETTIER: true\n VALIDATE_EDITORCONFIG: true\n VALIDATE_GIT_COMMITLINT: true\n VALIDATE_GIT_MERGE_CONFLICT_MARKERS: true\n VALIDATE_GITHUB_ACTIONS: true\n VALIDATE_GITLEAKS: true\n VALIDATE_MARKDOWN_PRETTIER: true\n VALIDATE_YAML: true\n\n - uses: theholocron/.github/.github/actions/auto-commit@main\n name: Commit and push linting fixes\n if: >\n inputs.enable-auto-commit == true &&\n github.event.pull_request != null &&\n github.event.pull_request.head.repo.full_name == github.repository &&\n github.ref_name != github.event.repository.default_branch &&\n env.APP_ID_SET == 'true'\n with:\n token: ${{ steps.app-token.outputs.token }}\n branch: ${{ github.event.pull_request.head.ref || github.head_ref || github.ref }}\n commit-message: \"chore: fix linting issues\\n\\nSigned-off-by: ${{ steps.app-bot.outputs.name }} <${{ steps.app-bot.outputs.email }}>\"\n commit-options: \"--no-verify\"\n commit-user-name: ${{ steps.app-bot.outputs.name }}\n commit-user-email: ${{ steps.app-bot.outputs.email }}\n commit-author: \"${{ steps.app-bot.outputs.name }} <${{ steps.app-bot.outputs.email }}>\"\n","name: Post-release Sync\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n HOLOCRON_SYNC_TOKEN:\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for gh CLI calls. Used when\n HOLOCRON_SYNC_TOKEN is not set.\n required: false\n\njobs:\n broadcast:\n name: Broadcast readme sync\n runs-on: ubuntu-latest\n timeout-minutes: 5\n steps:\n - name: Trigger broadcast readme sync\n run: |\n gh workflow run sync-broadcast.yml \\\n --repo theholocron/.github \\\n --field \"steps=readme\"\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n","name: Release\n\n# Semantic-release with OIDC Trusted Publishing.\n# actions/setup-node writes a default NODE_AUTH_TOKEN=${{ github.token }}\n# which shadows OIDC auth. We explicitly clear it so npm falls through to\n# the Trusted Publisher OIDC exchange.\n# The calling repo must have a .releaserc.json that configures branches,\n# plugins, and any publish options. npm@11+ is installed to support OIDC.\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n run-build:\n description: Run `pnpm build` before releasing\n type: boolean\n required: false\n default: true\n sentry-project:\n description: >\n Sentry project slug for sourcemap upload and release creation after\n publishing. Omit to skip the Sentry release step entirely.\n type: string\n required: false\n default: \"\"\n secrets:\n HOLOCRON_RELEASE_TOKEN:\n description: >\n Fine-grained PAT (Contents + Issues + Pull requests: write) owned by\n an admin. Required when the default branch is protected by a ruleset —\n github.token cannot push through rulesets, but an admin PAT can.\n Takes priority over HOLOCRON_SYNC_TOKEN. Falls back to github.token.\n required: false\n HOLOCRON_SYNC_TOKEN:\n description: >\n Legacy alias for HOLOCRON_RELEASE_TOKEN — kept for backward compatibility.\n Prefer HOLOCRON_RELEASE_TOKEN for new repos.\n required: false\n HOLOCRON_READ_TOKEN:\n description: >\n Fine-grained PAT for read-only GitHub API calls (e.g. resolving git\n committer identity via `gh api user`). Falls back to github.token.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for `gh` CLI calls. Used when\n HOLOCRON_READ_TOKEN is not set.\n required: false\n SENTRY_AUTH_TOKEN:\n description: >\n Sentry auth token for sourcemap upload and release creation.\n Required when sentry-project is set. Use the org-level secret.\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n release:\n name: Semantic release\n permissions:\n contents: write\n id-token: write\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 30\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n # Do not cancel in-progress releases — a partial release is worse than a slow one.\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n persist-credentials: false\n # Use HOLOCRON_RELEASE_TOKEN when available — git push (tags, release commits)\n # uses the checkout credential, not GITHUB_TOKEN env var. The\n # built-in github.token cannot push through branch protection rulesets.\n token: ${{ secrets.HOLOCRON_RELEASE_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Configure git identity\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n git config --global user.name \"$GIT_NAME\"\n git config --global user.email \"$GIT_EMAIL\"\n git config --global format.signoff true\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - name: Upgrade npm for OIDC support\n run: npm install -g npm@11 sigstore\n # sigstore is required by libnpmpublish/provenance.js at module parse\n # time — before any config takes effect. Some npm 11.x builds stopped\n # bundling it; installing it globally into the same prefix ensures it\n # resolves regardless of npm version. (Discovered 2026-07-09.)\n\n - run: pnpm build\n name: Build\n if: ${{ inputs.run-build == true }}\n\n - run: npx semantic-release\n name: Release\n env:\n # Prefer HOLOCRON_RELEASE_TOKEN (fine-grained PAT, Contents+Issues+PRs write,\n # owned by an admin with ruleset bypass) so @semantic-release/git can\n # push the version-bump commit through branch protection. Falls back to\n # HOLOCRON_SYNC_TOKEN (legacy) then github.token for unprotected repos.\n GITHUB_TOKEN: ${{ secrets.HOLOCRON_RELEASE_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || github.token }}\n HUSKY: \"0\"\n NPM_CONFIG_PROVENANCE: true\n\n - name: Get release version\n id: release_version\n if: ${{ inputs.sentry-project != '' }}\n env:\n SENTRY_PROJECT: ${{ inputs.sentry-project }}\n run: |\n TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo \"\")\n if [ -n \"$TAG\" ]; then\n echo \"release=${SENTRY_PROJECT}@${TAG#v}\" >> \"$GITHUB_OUTPUT\"\n fi\n\n - name: Create Sentry release\n if: ${{ inputs.sentry-project != '' && steps.release_version.outputs.release != '' }}\n uses: getsentry/action-release@ff07929a6537bac57790c3451cf4d364aca38528 # v3\n env:\n SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}\n SENTRY_ORG: theholocron\n SENTRY_PROJECT: ${{ inputs.sentry-project }}\n with:\n environment: production\n version: ${{ steps.release_version.outputs.release }}\n sourcemaps: \"**/dist\"\n","name: Review\n\n# ReviewDog is the annotation layer — posts inline PR diff annotations.\n# Runs on pull_request only: inline annotations require PR context,\n# and branch protection ensures all changes go through PRs anyway.\n# super-linter (lint.yml) is the CI gate covering push + PR events.\n# Gitleaks and YAML are intentionally duplicated: super-linter gates\n# merges; ReviewDog surfaces exact line annotations in the PR diff.\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n\njobs:\n reviewdog:\n name: Review PRs\n runs-on: ubuntu-latest\n timeout-minutes: 20\n permissions:\n contents: read\n pull-requests: write\n\n steps:\n - name: Checkout repository\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n\n - name: Setup\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n uses: theholocron/.github/.github/actions/setup@main\n\n - name: Install ReviewDog\n uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1\n with:\n reviewdog_version: latest\n\n # Detect which tools are relevant for this repo, excluding node_modules.\n # hashFiles('**/*') recurses into node_modules/.pnpm and produces false\n # positives for repos that don't own those file types.\n # -print -quit stops find after the first match without a pipe, avoiding\n # the SIGPIPE/pipefail exit-141 that find|head-1 triggers under\n # GitHub Actions' default bash --noprofile --norc -e -o pipefail mode.\n - name: Detect project features\n id: detect\n shell: bash\n run: |\n has() { find . -not -path '*/node_modules/*' -name \"$1\" -print -quit 2>/dev/null | grep -q .; }\n has_ext() { find . -not -path '*/node_modules/*' -name \"$1\" -print -quit 2>/dev/null | grep -q .; }\n { { has 'eslint.config.js' || has 'eslint.config.mjs' || has 'eslint.config.cjs' || \\\n has 'eslint.config.ts' || has '.eslintrc' || has '.eslintrc.js' || \\\n has '.eslintrc.cjs' || has '.eslintrc.json' || has '.eslintrc.yaml' || \\\n has '.eslintrc.yml'; } && grep -qF '\"eslint\":' package.json 2>/dev/null; } && echo \"eslint=true\" >> \"$GITHUB_OUTPUT\" || echo \"eslint=false\" >> \"$GITHUB_OUTPUT\"\n { has 'tsconfig.json' && grep -qF '\"typescript\":' package.json 2>/dev/null; } && echo \"tsconfig=true\" >> \"$GITHUB_OUTPUT\" || echo \"tsconfig=false\" >> \"$GITHUB_OUTPUT\"\n has_ext '*.sh' && echo \"shell=true\" >> \"$GITHUB_OUTPUT\" || echo \"shell=false\" >> \"$GITHUB_OUTPUT\"\n has 'Dockerfile' || has_ext '*.Dockerfile' || has 'Containerfile' && \\\n echo \"docker=true\" >> \"$GITHUB_OUTPUT\" || echo \"docker=false\" >> \"$GITHUB_OUTPUT\"\n has_ext '.env*' && echo \"dotenv=true\" >> \"$GITHUB_OUTPUT\" || echo \"dotenv=false\" >> \"$GITHUB_OUTPUT\"\n has_ext '*.md' && echo \"markdown=true\" >> \"$GITHUB_OUTPUT\" || echo \"markdown=false\" >> \"$GITHUB_OUTPUT\"\n\n #\n # Always applicable\n #\n\n - name: Gitleaks (secrets)\n uses: reviewdog/action-gitleaks@2b7b5685e3e3eecddab5d30cfa04f18123031421 # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / gitleaks\"\n fail_level: error\n gitleaks_flags: --log-opts=${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}\n\n - name: YamlLint\n if: ${{ hashFiles('yamllint.config.yml') != '' }}\n uses: reviewdog/action-yamllint@b5f7217d8c815ae374d1d55840d5e569d82f01f0 # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / yamllint\"\n fail_level: error\n yamllint_flags: -c ${{ github.workspace }}/yamllint.config.yml ${{ github.workspace }}\n\n - name: ActionLint (GitHub Actions)\n if: ${{ hashFiles('.github/workflows/*.yml', '.github/workflows/*.yaml') != '' }}\n uses: reviewdog/action-actionlint@6fb7acc99f4a1008869fa8a0f09cfca740837d9d # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / actionlint\"\n fail_level: error\n\n #\n # TypeScript / JavaScript\n #\n\n - name: ESLint\n if: steps.detect.outputs.eslint == 'true'\n uses: reviewdog/action-eslint@556a3fdaf8b4201d4d74d406013386aa4f7dab96 # v1.34.0\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / eslint\"\n fail_level: error\n eslint_flags: .\n\n - name: TypeScript\n if: steps.detect.outputs.tsconfig == 'true'\n uses: EPMatt/reviewdog-action-tsc@63d923a3c5b4497671940b8874f58a404e2351b5 # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / tsc\"\n fail_level: error\n\n #\n # Shell\n #\n\n - name: ShellCheck\n if: steps.detect.outputs.shell == 'true'\n uses: reviewdog/action-shellcheck@4c07458293ac342d477251099501a718ae5ef86e # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / shellcheck\"\n fail_level: none\n\n #\n # Docker\n #\n\n - name: Hadolint\n if: steps.detect.outputs.docker == 'true'\n uses: reviewdog/action-hadolint@1b2cfa6ba72072ad35158d7ff3aa49bbdc03506d # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / hadolint\"\n fail_level: none\n\n #\n # Environment files\n #\n\n - name: dotenv-linter\n if: steps.detect.outputs.dotenv == 'true'\n uses: dotenv-linter/action-dotenv-linter@afde61cfda2ecffe7bea35837b6f20b956c88689 # v3.0.0\n with:\n reporter: github-code-suggestions\n\n #\n # Documentation\n #\n\n - name: Alex (inclusive language)\n if: steps.detect.outputs.markdown == 'true'\n uses: reviewdog/action-alex@347481655add010a2ae302df34b57c9bcfa0d6e4 # v1\n with:\n reporter: github-pr-annotations\n tool_name: \"Review / alex\"\n","name: Stale\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n days-before-stale:\n description: Days of inactivity before an issue is marked stale\n type: number\n required: false\n default: 30\n days-before-close:\n description: Days of inactivity after stale label before closing\n type: number\n required: false\n default: 5\n\njobs:\n stale:\n name: Mark stale issues and pull requests\n permissions:\n contents: write\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10.4.0\n name: Run Stale\n with:\n close-issue-message: >\n This issue was closed because it has been stalled for\n ${{ inputs.days-before-close }} days with no activity.\n days-before-close: ${{ inputs.days-before-close }}\n days-before-stale: ${{ inputs.days-before-stale }}\n exempt-all-pr-milestones: true\n stale-issue-label: wontfix\n stale-issue-message: >\n This issue is stale because it has been open ${{ inputs.days-before-stale }}\n days with no activity. Remove the stale label or comment, or this will be\n closed in ${{ inputs.days-before-close }} days.\n stale-pr-label: wontfix\n stale-pr-message: >\n This PR is stale because it has been open ${{ inputs.days-before-stale }}\n days with no activity. Remove the stale label or comment, or this will be\n closed in ${{ inputs.days-before-close }} days.\n","name: Sync\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n steps:\n description: >\n Sync steps to run (default: all). Valid values:\n labels, properties, teams, topics, keywords, description, homepage, readme.\n Pass a space-separated list to run a subset, e.g. \"readme\" or \"readme description\".\n type: string\n required: false\n secrets:\n HOLOCRON_ADMIN_TOKEN:\n description: Fine-grained PAT with admin scopes (labels, properties, teams).\n required: false\n HOLOCRON_DEPLOY_TOKEN:\n description: Fine-grained PAT for GitHub Pages configuration.\n required: false\n HOLOCRON_ISSUES_TOKEN:\n description: Fine-grained PAT for issue management.\n required: false\n HOLOCRON_ORG_TOKEN:\n description: Org-scoped fine-grained PAT for team sync and org properties.\n required: false\n HOLOCRON_READ_TOKEN:\n description: Fine-grained PAT for read-only GitHub API calls.\n required: false\n HOLOCRON_SYNC_TOKEN:\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for gh CLI calls. Used when\n HOLOCRON_SYNC_TOKEN is not set.\n required: false\n\njobs:\n sync:\n name: Sync repo from config\n runs-on: ubuntu-latest\n timeout-minutes: 10\n permissions:\n contents: write\n pull-requests: write\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Run holocron sync\n run: |\n if [ -n \"$STEPS\" ]; then\n # shellcheck disable=SC2086\n pnpm exec holocron sync --steps $STEPS\n else\n pnpm exec holocron sync\n fi\n env:\n HOLOCRON_ADMIN_TOKEN: ${{ secrets.HOLOCRON_ADMIN_TOKEN }}\n HOLOCRON_DEPLOY_TOKEN: ${{ secrets.HOLOCRON_DEPLOY_TOKEN }}\n HOLOCRON_ISSUES_TOKEN: ${{ secrets.HOLOCRON_ISSUES_TOKEN }}\n HOLOCRON_ORG_TOKEN: ${{ secrets.HOLOCRON_ORG_TOKEN }}\n HOLOCRON_READ_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n STEPS: ${{ inputs.steps }}\n\n - name: Format generated files\n run: pnpm exec prettier --write README.md docs/src/content/docs/index.mdx 2>/dev/null || true\n\n - uses: theholocron/.github/.github/actions/auto-commit@main\n id: auto-commit\n name: Commit sync changes\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n branch: chore/auto-sync\n commit-message: \"chore: sync from holocron.config\"\n commit-options: \"--no-verify\"\n\n - name: Open PR if changes were committed\n if: steps.auto-commit.outputs.changes-detected == 'true'\n run: |\n gh pr create \\\n --title \"chore: sync README and repo metadata\" \\\n --body \"Automated sync triggered by changes to config or package files. Merge to apply.\" \\\n --base main \\\n --head chore/auto-sync \\\n || echo \"PR already open — branch updated.\"\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n","name: Sync Broadcast\n\non: # yamllint disable-line rule:truthy\n workflow_dispatch:\n inputs:\n steps:\n description: >\n Sync steps to pass to each repo's sync.yml. Default is \"readme\"\n (only README marker blocks are updated).\n type: string\n required: false\n default: readme\n\npermissions:\n contents: read\n\njobs:\n broadcast:\n name: Broadcast sync to all repos\n runs-on: ubuntu-latest\n timeout-minutes: 15\n steps:\n - name: Dispatch sync to all repos with sync.yml\n run: |\n gh api /orgs/theholocron/repos --paginate --jq '.[].name' \\\n | while IFS= read -r repo; do\n gh api \"/repos/theholocron/$repo/contents/.github/workflows/sync.yml\" --silent 2>/dev/null || continue\n echo \"Dispatching sync to theholocron/$repo\"\n gh workflow run sync.yml \\\n --repo \"theholocron/$repo\" \\\n --field \"steps=$STEPS\"\n done\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n STEPS: ${{ inputs.steps }}\n","name: Sync GitHub Templates\n\n# Builds the holocron CLI from source and pushes updated workflow templates\n# and composite actions to downstream .github repos. Runs whenever the\n# template source files change on main or alpha.\n#\n# Secrets required:\n# HOLOCRON_SYNC_TOKEN — fine-grained PAT (resource owner: org) with:\n# Actions: Read and write (dispatch workflow runs via gh workflow run)\n# Contents: Read and write (git trees, blobs, refs)\n# Pull requests: Read and write (open sync PR)\n# Workflows: Read and write (write .github/workflows/*.yml)\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n primary-repo:\n description: >\n Primary .github repo — receives composite actions, reusable workflows,\n and thin-caller templates. Requires a PR (branch protection assumed).\n type: string\n required: false\n default: theholocron/.github\n secondary-repos:\n description: >\n Space-separated list of secondary repos (reusable workflows + thin\n callers only, no composite actions). Changes are delivered via pull\n request, same as the primary repo.\n type: string\n required: false\n default: \"\"\n sync-branch:\n description: Branch name used for the primary and secondary repo PRs\n type: string\n required: false\n default: chore/sync-templates\n secrets:\n HOLOCRON_SYNC_TOKEN:\n required: true\n HOLOCRON_READ_TOKEN:\n description: >\n Fine-grained PAT for read-only GitHub API calls (e.g. resolving git\n committer identity via `gh api user`). Falls back to HOLOCRON_SYNC_TOKEN.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for `gh` CLI calls. Used when neither\n HOLOCRON_READ_TOKEN nor HOLOCRON_SYNC_TOKEN is set.\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n sync:\n name: Sync templates\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm build\n name: Build CLI\n\n - name: Cache actionlint\n id: cache-actionlint\n uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0\n with:\n path: /tmp/actionlint\n key: actionlint-v1.7.7-linux-amd64\n\n - name: Download actionlint\n if: steps.cache-actionlint.outputs.cache-hit != 'true'\n run: |\n curl -fsSL https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_amd64.tar.gz \\\n | tar -xz -C /tmp actionlint\n\n - name: Validate generated workflows\n run: |\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --output-dir /tmp/sync-validate\n /tmp/actionlint /tmp/sync-validate/.github/workflows/*.yml\n env:\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n\n - name: Sync primary repo (PR)\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$PRIMARY_REPO\" \"$SYNC_BRANCH\" 2>/dev/null || true\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n\n - name: Sync secondary repos (PR)\n if: ${{ inputs.secondary-repos != '' }}\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n for repo in $SECONDARY_REPOS; do\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$repo\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$repo\" \"$SYNC_BRANCH\" 2>/dev/null || true\n done\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n SECONDARY_REPOS: ${{ inputs.secondary-repos }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n","name: Tag\n\n# Release Please — fully automated tag and GitHub Release from Conventional Commits.\n# No package.json or npm publishing required. Operates in \"simple\" mode by default:\n# analyzes commits since the last tag, maintains a rolling Release PR, and creates\n# a tag + GitHub Release when that PR is merged.\n#\n# The calling repo must have two files at the root:\n# release-please-config.json — declares packages and release-type\n# .release-please-manifest.json — tracks the current version\n\non: # yamllint disable-line rule:truthy\n # Self-trigger: when this workflow lives in theholocron/.github itself,\n # push to main runs Release Please for that repo's own releases.\n push:\n branches:\n - main\n workflow_call:\n inputs:\n release-type:\n description: Release Please release type (simple, node, python, etc.)\n type: string\n required: false\n default: simple\n config-file:\n description: Path to release-please-config.json\n type: string\n required: false\n default: release-please-config.json\n manifest-file:\n description: Path to .release-please-manifest.json\n type: string\n required: false\n default: .release-please-manifest.json\n\njobs:\n tag:\n name: Tag release\n permissions:\n contents: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: google-github-actions/release-please-action@e4dc86ba9405554aeba3c6bb2d169500e7d3b4ee # v4.1.1\n name: Run Release Please\n with:\n release-type: ${{ inputs.release-type }}\n config-file: ${{ inputs.config-file }}\n manifest-file: ${{ inputs.manifest-file }}\n","name: Test\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n run-unit:\n description: Run unit tests with coverage (disable for UI-only repos that use Storybook testing exclusively)\n type: boolean\n required: false\n default: true\n run-storybook:\n description: Run Storybook vitest interaction tests (requires .storybook/ setup)\n type: boolean\n required: false\n default: false\n run-interaction:\n description: Run Storybook interaction and accessibility tests with Playwright\n type: boolean\n required: false\n default: false\n run-chromatic:\n description: Publish Storybook to Chromatic for visual regression testing\n type: boolean\n required: false\n default: false\n chromatic-projects:\n description: >\n JSON array of Chromatic projects to build, one matrix job per entry.\n Each entry: { \"tokenName\": \"WEB\", \"workingDir\": \"apps/web\", \"buildScript\": \"build:storybook\" }.\n tokenName maps to secret CHROMATIC_PROJECT_TOKEN_<TOKENNAME>; use \"default\"\n (or omit for the legacy empty-string form) to use the bare CHROMATIC_PROJECT_TOKEN\n secret for single-project repos.\n buildScript defaults to \"build:storybook\" when omitted.\n Default runs a single job from the repo root using CHROMATIC_PROJECT_TOKEN.\n type: string\n required: false\n default: '[{\"tokenName\":\"default\",\"workingDir\":\".\",\"buildScript\":\"build:storybook\"}]'\n run-user-flow:\n description: Run Cypress E2E user-flow tests (requires cypress.config.*)\n type: boolean\n required: false\n default: false\n wait-on-url:\n description: URL to wait for before running Cypress tests (default is Vite dev server; override for non-Vite stacks e.g. http://localhost:3000 for Next.js)\n type: string\n required: false\n default: \"http://localhost:5173\"\n secrets:\n CHROMATIC_PROJECT_TOKEN:\n required: false\n CYPRESS_RECORD_KEY:\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n unit:\n name: Run tests and collect coverage\n if: ${{ inputs.run-unit }}\n permissions:\n contents: read\n id-token: write\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm test:coverage\n name: Run tests with coverage\n\n - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0\n name: Upload coverage to Codecov\n with:\n use_oidc: true\n\n - uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1\n name: Upload test results to Codecov\n if: ${{ !cancelled() }}\n with:\n use_oidc: true\n files: '**/test-report.junit.xml'\n\n storybook:\n name: Run Storybook interaction tests\n if: ${{ inputs.run-storybook }}\n permissions:\n contents: read\n id-token: write\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm exec playwright install chromium --with-deps\n name: Install Playwright\n\n - run: pnpm test:storybook\n name: Run Storybook tests\n\n - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0\n name: Upload coverage to Codecov\n with:\n use_oidc: true\n\n - uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1\n name: Upload test results to Codecov\n if: ${{ !cancelled() }}\n with:\n use_oidc: true\n files: '**/test-report.junit.xml'\n\n visual-and-composition:\n name: Test Visual and Composition (${{ matrix.project.tokenName }})\n if: ${{ inputs.run-chromatic }}\n strategy:\n fail-fast: false\n matrix:\n project: ${{ fromJSON(inputs.chromatic-projects) }}\n permissions:\n contents: read\n statuses: write\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - uses: chromaui/action@14cfaef73576e69f95f47f60058063f46ca38719 # v18\n name: Publish to Chromatic\n with:\n projectToken: ${{ (matrix.project.tokenName == 'default' || matrix.project.tokenName == '') && secrets.CHROMATIC_PROJECT_TOKEN || secrets[format('CHROMATIC_PROJECT_TOKEN_{0}', matrix.project.tokenName)] }}\n token: ${{ github.token }}\n buildScriptName: ${{ matrix.project.buildScript || 'build:storybook' }}\n workingDir: ${{ matrix.project.workingDir || '.' }}\n storybookBaseDir: ${{ matrix.project.storybookBaseDir || '' }}\n untraced: ${{ matrix.project.untraced || '' }}\n onlyStoryFiles: ${{ matrix.project.onlyStoryFiles || '' }}\n exitZeroOnChanges: ${{ matrix.project.exitZeroOnChanges || false }}\n\n interaction-and-accessibility:\n name: Test Interactions and Accessibility\n if: ${{ inputs.run-interaction }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm exec playwright install --with-deps\n name: Install Playwright\n\n - run: pnpm test:storybook\n name: Run interaction and accessibility tests\n\n user-flow:\n name: Test User Flow\n if: ${{ inputs.run-user-flow }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n strategy:\n fail-fast: false\n matrix:\n containers: [1, 2]\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm exec cypress install\n name: Install Cypress binary\n\n - uses: cypress-io/github-action@1052aa98bbbe4f55210f844878213c07d9c8c399 # v6.7.13\n name: Cypress run\n with:\n start: pnpm dev\n wait-on: ${{ inputs.wait-on-url }}\n record: true\n parallel: true\n env:\n CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}\n GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n","name: Typecheck\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n TURBO_TOKEN:\n required: false\n\njobs:\n typecheck:\n name: tsc --noEmit\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm typecheck\n name: Type check\n","/**\n * All reusable workflow and composite action content bundled as string\n * constants so the CLI can push them to theholocron/.github without\n * needing filesystem access at runtime.\n *\n * Content lives in standalone .yml files; the rawYml rollup plugin\n * inlines them as string exports at build time.\n */\n\nimport autoCommitAction from \"./actions/auto-commit.yml\";\nimport installAction from \"./actions/install.yml\";\nimport setupAction from \"./actions/setup.yml\";\nimport setupNodeAction from \"./actions/setup-node.yml\";\nimport auditWorkflow from \"./workflows/audit.yml\";\nimport bookkeepingWorkflow from \"./workflows/bookkeeping.yml\";\nimport cleanupPreviewWorkflow from \"./workflows/cleanup-preview.yml\";\nimport codeqlWorkflow from \"./workflows/codeql.yml\";\nimport dependenciesWorkflow from \"./workflows/dependencies.yml\";\nimport deployWorkflow from \"./workflows/deploy.yml\";\nimport deployPreviewWorkflow from \"./workflows/deploy-preview.yml\";\nimport greetingsWorkflow from \"./workflows/greetings.yml\";\nimport lintWorkflow from \"./workflows/lint.yml\";\nimport postReleaseWorkflow from \"./workflows/post-release.yml\";\nimport releaseWorkflow from \"./workflows/release.yml\";\nimport reviewWorkflow from \"./workflows/review.yml\";\nimport staleWorkflow from \"./workflows/stale.yml\";\nimport syncWorkflow from \"./workflows/sync.yml\";\nimport syncBroadcastWorkflow from \"./workflows/sync-broadcast.yml\";\nimport syncGithubWorkflow from \"./workflows/sync-github.yml\";\nimport tagWorkflow from \"./workflows/tag.yml\";\nimport testWorkflow from \"./workflows/test.yml\";\nimport typecheckWorkflow from \"./workflows/typecheck.yml\";\n\nexport const ACTIONS: Record<string, string> = {\n\t\"auto-commit/action\": autoCommitAction,\n\t\"install/action\": installAction,\n\t\"setup/action\": setupAction,\n\t\"setup-node/action\": setupNodeAction,\n};\n\nexport const REUSABLE_WORKFLOWS: Record<string, string> = {\n\taudit: auditWorkflow,\n\tbookkeeping: bookkeepingWorkflow,\n\tcodeql: codeqlWorkflow,\n\tdependencies: dependenciesWorkflow,\n\tdeploy: deployWorkflow,\n\t\"cleanup-preview\": cleanupPreviewWorkflow,\n\t\"deploy-preview\": deployPreviewWorkflow,\n\tgreetings: greetingsWorkflow,\n\tlint: lintWorkflow,\n\t\"post-release\": postReleaseWorkflow,\n\trelease: releaseWorkflow,\n\treview: reviewWorkflow,\n\tstale: staleWorkflow,\n\t\"sync-broadcast\": syncBroadcastWorkflow,\n\ttag: tagWorkflow,\n\t\"sync-github\": syncGithubWorkflow,\n\tsync: syncWorkflow,\n\ttest: testWorkflow,\n\ttypecheck: typecheckWorkflow,\n};\n\nexport const WORKFLOW_TEMPLATE_PROPERTIES: Record<string, string> = {\n\tbookkeeping: JSON.stringify(\n\t\t{\n\t\t\tname: \"Bookkeeping\",\n\t\t\tdescription: \"Label and track issues and pull requests.\",\n\t\t\ticonName: \"octicon tag\",\n\t\t},\n\t\tnull,\n\t\t2\n\t),\n};\n","import { createHash } from \"node:crypto\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nimport { createGitHubClient } from \"@theholocron/github-client\";\nimport { ProviderApiError } from \"@theholocron/http-client\";\n\nimport { ACTIONS, REUSABLE_WORKFLOWS, WORKFLOW_TEMPLATE_PROPERTIES } from \"../templates/index.js\";\nimport {\n\tderiveDeployPaths,\n\textractPreviewConfig,\n\tgenerateCombinedDeployContent,\n\tgenerateThinCallerContent,\n\tKNOWN_WORKFLOWS,\n\tnormalizeWorkflowWith,\n\ttype OrgContext,\n\tWORKFLOW_TEMPLATES,\n\tworkflowHeader,\n} from \"./setup-workflows.js\";\n\nconst DEFAULT_REPO = \"theholocron/.github\";\n\nexport type SyncGithubStatus = \"ok\" | \"fail\" | \"dry-run\";\n\nexport interface RunSyncGithubInput {\n\t/** GitHub personal access token with repo write access. */\n\ttoken: string;\n\t/** Target org/repo. Defaults to \"theholocron/.github\". */\n\trepo?: string;\n\t/**\n\t * Push files to this branch instead of the default branch.\n\t * If the branch doesn't exist it is created from the default branch HEAD.\n\t * Combine with `createPr: true` to open a PR after the push.\n\t */\n\tbranch?: string;\n\t/** After pushing to `branch`, open a PR to the default branch. No-op if `branch` is unset. */\n\tcreatePr?: boolean;\n\t/** Commit message for the sync commit. */\n\tmessage?: string;\n\tdryRun?: boolean;\n\t/**\n\t * Write generated files to this local directory instead of pushing to the GitHub API.\n\t * Useful for local validation (e.g. actionlint) before a real sync run.\n\t * When set, no API calls are made and token is not required.\n\t */\n\toutputDir?: string;\n\tprint?: (line: string) => void;\n\t/** Injectable for testing. */\n\tfetch?: typeof globalThis.fetch;\n}\n\nexport interface SyncGithubReport {\n\tstatus: SyncGithubStatus;\n\tcreated: number;\n\tupdated: number;\n\tunchanged: number;\n\t/** URL of the opened PR, when createPr is true and changes were made. */\n\tprUrl?: string;\n\tmessage?: string;\n}\n\ntype FileBatch = Array<{ path: string; content: string }>;\ntype WorkflowEntry = { name: string; with?: Record<string, unknown> };\n\n/**\n * Extracts the `workflows` array from a `holocron.config.ts` source string.\n * Handles both plain string entries and `{ name, with }` object entries.\n * Falls back to an empty array if the array cannot be found or parsed.\n */\nexport function parseWorkflowsFromTs(source: string): WorkflowEntry[] {\n\tconst keyMatch = source.match(/\\bworkflows\\s*:\\s*\\[/);\n\tif (!keyMatch) return [];\n\n\t// Walk forward to find the matching ]\n\tconst start = keyMatch.index! + keyMatch[0].length;\n\tlet depth = 1;\n\tlet i = start;\n\twhile (i < source.length && depth > 0) {\n\t\tif (source[i] === \"[\") depth++;\n\t\telse if (source[i] === \"]\") depth--;\n\t\ti++;\n\t}\n\tconst body = source.slice(start, i - 1);\n\n\t// Detect spread operators like ...workflows (from node() / react() presets).\n\t// When present, all known workflows are included as defaults so the sync\n\t// doesn't silently skip workflows that come from the preset.\n\tconst hasPresetSpread = /\\.\\.\\.[a-zA-Z_$][a-zA-Z0-9_$]*/.test(body);\n\n\tconst explicit: Array<{ pos: number; entry: WorkflowEntry }> = [];\n\tconst objSpans: Array<[number, number]> = [];\n\n\t// Pass 1: extract top-level { ... } objects using bracket counting so that\n\t// nested braces inside with: values (e.g. storybook: [{ name: \"app\" }])\n\t// are handled correctly. The previous regex approach stopped at the first }\n\t// inside a nested object, causing JSON.parse to fail and with: to be silently\n\t// dropped from the generated thin caller.\n\tlet j = 0;\n\twhile (j < body.length) {\n\t\tif (body[j] !== \"{\") {\n\t\t\tj++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst objStart = j;\n\t\tlet objDepth = 1;\n\t\tj++;\n\t\twhile (j < body.length && objDepth > 0) {\n\t\t\tif (body[j] === \"{\") objDepth++;\n\t\t\telse if (body[j] === \"}\") objDepth--;\n\t\t\tj++;\n\t\t}\n\t\tconst objContent = body.slice(objStart, j);\n\t\tobjSpans.push([objStart, j]);\n\n\t\tconst nameMatch = objContent.match(/\\bname\\s*:\\s*\"([^\"]+)\"/);\n\t\tif (!nameMatch) continue;\n\t\tconst name = nameMatch[1];\n\n\t\tlet withObj: Record<string, unknown> | undefined;\n\t\tconst withKeyMatch = objContent.match(/\\bwith\\s*:\\s*\\{/);\n\t\tif (withKeyMatch) {\n\t\t\tconst withOpen = withKeyMatch.index! + withKeyMatch[0].length - 1;\n\t\t\tlet withDepth = 1;\n\t\t\tlet k = withOpen + 1;\n\t\t\twhile (k < objContent.length && withDepth > 0) {\n\t\t\t\tif (objContent[k] === \"{\") withDepth++;\n\t\t\t\telse if (objContent[k] === \"}\") withDepth--;\n\t\t\t\tk++;\n\t\t\t}\n\t\t\tconst withStr = objContent.slice(withOpen, k);\n\t\t\ttry {\n\t\t\t\t// TS object literals differ from JSON in two ways:\n\t\t\t\t// 1. Unquoted keys: { docs: true } → { \"docs\": true }\n\t\t\t\t// 2. Trailing commas: { a: 1, } → { a: 1 }\n\t\t\t\t// Normalise both before parsing so nested objects like\n\t\t\t\t// run-chromatic: { projects: [...], } are handled correctly.\n\t\t\t\tconst jsonSafe = withStr\n\t\t\t\t\t.replace(/([{,]\\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*:/g, '$1\"$2\":')\n\t\t\t\t\t.replace(/,(\\s*[}\\]])/g, \"$1\");\n\t\t\t\twithObj = JSON.parse(jsonSafe) as Record<string, unknown>;\n\t\t\t} catch {\n\t\t\t\t/* ignore malformed with: value */\n\t\t\t}\n\t\t}\n\n\t\texplicit.push({ pos: objStart, entry: { name, ...(withObj && { with: withObj }) } });\n\t}\n\n\t// Pass 2: simple string entries — \"workflowname\" — skip chars inside object spans\n\tconst strRe = /\"([^\"]+)\"/g;\n\tlet m: RegExpExecArray | null;\n\twhile ((m = strRe.exec(body)) !== null) {\n\t\tif (!objSpans.some(([s, e]) => m!.index >= s && m!.index < e)) {\n\t\t\texplicit.push({ pos: m.index, entry: { name: m[1] } });\n\t\t}\n\t}\n\n\texplicit.sort((a, b) => a.pos - b.pos);\n\tconst explicitEntries = explicit.map(({ entry }) => entry);\n\n\tif (!hasPresetSpread) return explicitEntries;\n\n\t// Spread detected: seed with all known workflows, then let explicit entries\n\t// override (e.g. to carry their with: overrides).\n\tconst merged = new Map<string, WorkflowEntry>([...KNOWN_WORKFLOWS].map((name) => [name, { name }]));\n\tfor (const entry of explicitEntries) {\n\t\tmerged.set(entry.name, entry);\n\t}\n\treturn [...merged.values()];\n}\n\n/**\n * Extract org name and docs domain from a `holocron.config.ts` source string.\n * Used to resolve `preview: true` to `{ project: \"<org>-preview\", domain: \"preview.<docsDomain>\" }`.\n */\nexport function parseOrgContextFromTs(source: string): OrgContext {\n\tconst orgMatch = source.match(/\\borg\\s*:\\s*[\"']([^\"']+)[\"']/);\n\t// Match top-level `domain: \"...\"` — the org canonical domain from which preview\n\t// subdomains are derived (e.g. \"theholocron.dev\" → preview.theholocron.dev).\n\tconst domainMatch = source.match(/\\bdomain\\s*:\\s*[\"']([^\"']+)[\"']/);\n\t// Match `name: \"...\"` only before `workflows:` so workflow-entry names are excluded.\n\tconst beforeWorkflows = source.split(/\\bworkflows\\s*:/)[0]!;\n\tconst nameMatch = beforeWorkflows.match(/\\bname\\s*:\\s*[\"']([^\"']+)[\"']/);\n\treturn {\n\t\torg: orgMatch?.[1],\n\t\tdomain: domainMatch?.[1],\n\t\trepoName: nameMatch?.[1],\n\t};\n}\n\nfunction reusableHeader(source: string): string {\n\treturn [\n\t\t`# AUTO-GENERATED — do not edit in theholocron/.github directly.`,\n\t\t`# Source: theholocron/holocron · ${source}`,\n\t\t`# Synced: ${new Date().toISOString()}`,\n\t\t`# Tool: holocron sync-github`,\n\t\t`# Changes: edit source in theholocron/holocron and push to alpha or main.`,\n\t\t``,\n\t].join(\"\\n\");\n}\n\nfunction buildBatch(\n\trepo: string,\n\tallowedWorkflows?: Set<string>,\n\twithOverrides?: Map<string, Record<string, unknown>>,\n\torgContext?: OrgContext\n): FileBatch {\n\tconst files: FileBatch = [];\n\tconst isPrimaryGithubRepo = repo === DEFAULT_REPO;\n\n\tif (isPrimaryGithubRepo) {\n\t\tfor (const [name, content] of Object.entries(ACTIONS)) {\n\t\t\tfiles.push({\n\t\t\t\tpath: `.github/actions/${name}.yml`,\n\t\t\t\tcontent: reusableHeader(`packages/cli/src/templates/index.ts`) + content,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (isPrimaryGithubRepo) {\n\t\tfor (const [name, content] of Object.entries(REUSABLE_WORKFLOWS)) {\n\t\t\tfiles.push({\n\t\t\t\tpath: `.github/workflows/${name}.yml`,\n\t\t\t\tcontent: reusableHeader(`packages/cli/src/templates/index.ts`) + content,\n\t\t\t});\n\t\t}\n\n\t\tfor (const [name, content] of Object.entries(WORKFLOW_TEMPLATES)) {\n\t\t\tfiles.push({\n\t\t\t\tpath: `workflow-templates/${name}.yml`,\n\t\t\t\tcontent: workflowHeader(undefined, true) + content,\n\t\t\t});\n\t\t\tconst props = WORKFLOW_TEMPLATE_PROPERTIES[name];\n\t\t\tif (props) {\n\t\t\t\tfiles.push({\n\t\t\t\t\tpath: `workflow-templates/${name}.properties.json`,\n\t\t\t\t\tcontent: props,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor (const name of Object.keys(REUSABLE_WORKFLOWS)) {\n\t\t\t// deploy-preview is a reusable that lives in .github, not a user-configurable\n\t\t\t// thin caller — skip it in the secondary-repo loop.\n\t\t\tif (name === \"deploy-preview\") continue;\n\t\t\tif (allowedWorkflows && !allowedWorkflows.has(name)) continue;\n\t\t\tconst rawWith = withOverrides?.get(name);\n\t\t\tconst normalizedWith = rawWith ? normalizeWorkflowWith(rawWith, orgContext?.repoName) : undefined;\n\t\t\tconst additionalPaths = name === \"deploy\" && rawWith ? deriveDeployPaths(rawWith) : undefined;\n\n\t\t\t// deploy + preview: → combined thin caller; preview: true derives\n\t\t\t// project + domain from the repo's org/docs config.\n\t\t\tif (name === \"deploy\" && rawWith) {\n\t\t\t\tconst previewCfg = extractPreviewConfig(rawWith, orgContext);\n\t\t\t\tif (previewCfg) {\n\t\t\t\t\tfiles.push({\n\t\t\t\t\t\tpath: `.github/workflows/deploy.yml`,\n\t\t\t\t\t\tcontent:\n\t\t\t\t\t\t\tworkflowHeader() +\n\t\t\t\t\t\t\tgenerateCombinedDeployContent(normalizedWith!, additionalPaths!, previewCfg),\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst content = generateThinCallerContent(name, normalizedWith, additionalPaths);\n\t\t\tif (!content) continue;\n\t\t\tfiles.push({\n\t\t\t\tpath: `.github/workflows/${name}.yml`,\n\t\t\t\tcontent: workflowHeader() + content,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn files;\n}\n\n/** Git blob SHA: sha1(\"blob {len}\\0{content}\") — used to detect unchanged files. */\nexport function gitBlobSha(content: string): string {\n\tconst buf = Buffer.from(content, \"utf8\");\n\treturn createHash(\"sha1\").update(`blob ${buf.length}\\0`).update(buf).digest(\"hex\");\n}\n\nexport async function runSyncGithub(input: RunSyncGithubInput): Promise<SyncGithubReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst repo = input.repo ?? DEFAULT_REPO;\n\tconst { token, dryRun = false, branch, createPr = false } = input;\n\tconst message = input.message ?? `chore: sync from theholocron/holocron`;\n\n\tconst client = createGitHubClient({ token, fetch: input.fetch });\n\n\tprint(`holocron sync-github${dryRun ? \" (dry-run)\" : \"\"}`);\n\tprint(` repo: ${repo}`);\n\tif (branch) print(` branch: ${branch}`);\n\tprint(\"\");\n\n\t// ── output-dir: write all files to disk without any API calls ───────────\n\tif (input.outputDir) {\n\t\tconst batch = buildBatch(repo);\n\t\tfor (const file of batch) {\n\t\t\tconst dest = join(input.outputDir, file.path);\n\t\t\tmkdirSync(dirname(dest), { recursive: true });\n\t\t\twriteFileSync(dest, file.content, \"utf8\");\n\t\t}\n\t\tprint(` ${batch.length} files written to ${input.outputDir}`);\n\t\treturn { status: \"ok\", created: batch.length, updated: 0, unchanged: 0 };\n\t}\n\n\t// ── 1. Resolve target branch ─────────────────────────────────────────────\n\tlet targetBranch = branch;\n\tlet defaultBranch: string | undefined;\n\tif (!targetBranch || createPr) {\n\t\ttry {\n\t\t\tconst repoData = await client.repos.getRepo(repo);\n\t\t\tdefaultBranch = repoData.default_branch;\n\t\t\tif (!targetBranch) targetBranch = defaultBranch;\n\t\t} catch {\n\t\t\tconst msg = \"failed to fetch repo metadata\";\n\t\t\tprint(` ✗ ${msg}`);\n\t\t\treturn { status: \"fail\", created: 0, updated: 0, unchanged: 0, message: msg };\n\t\t}\n\t}\n\n\t// ── 2. Get HEAD commit → base tree ───────────────────────────────────────\n\tconst baseBranch = createPr && defaultBranch ? defaultBranch : targetBranch!;\n\tlet headSha: string;\n\tlet baseTreeSha: string;\n\tlet existingBlobs: Map<string, string>;\n\ttry {\n\t\tconst ref = await client.git.getRef(repo, baseBranch);\n\t\theadSha = ref.object.sha;\n\t\tconst commit = await client.git.getCommit(repo, headSha);\n\t\tbaseTreeSha = commit.tree.sha;\n\t\tconst treeData = await client.git.getTree(repo, baseTreeSha, true);\n\t\texistingBlobs = new Map(treeData.tree.filter((i) => i.type === \"blob\").map((i) => [i.path, i.sha]));\n\t} catch (err) {\n\t\tconst msg = err instanceof Error ? err.message : `Branch ${baseBranch} not found`;\n\t\tprint(` ✗ ${msg}`);\n\t\treturn { status: \"fail\", created: 0, updated: 0, unchanged: 0, message: msg };\n\t}\n\n\t// ── 3. Fetch workflow allowlist + per-workflow overrides from target repo ─\n\tlet allowedWorkflows: Set<string> | undefined;\n\tlet withOverrides: Map<string, Record<string, unknown>> | undefined;\n\tlet orgContext: OrgContext | undefined;\n\tif (repo !== DEFAULT_REPO) {\n\t\ttry {\n\t\t\tlet entries: WorkflowEntry[] = [];\n\n\t\t\ttry {\n\t\t\t\tconst data = await client.git.getContents(repo, \"holocron.config.json\");\n\t\t\t\tconst raw = JSON.parse(Buffer.from(data.content.replace(/\\n/g, \"\"), \"base64\").toString(\"utf8\")) as {\n\t\t\t\t\tworkflows?: Array<string | WorkflowEntry>;\n\t\t\t\t};\n\t\t\t\tentries = (raw?.workflows ?? []).map((w) => (typeof w === \"string\" ? { name: w } : w));\n\t\t\t} catch (err) {\n\t\t\t\tif (!(err instanceof ProviderApiError) || err.status !== 404) throw err;\n\t\t\t\t// Fall back to .ts config\n\t\t\t\ttry {\n\t\t\t\t\tconst data = await client.git.getContents(repo, \"holocron.config.ts\");\n\t\t\t\t\tconst source = Buffer.from(data.content.replace(/\\n/g, \"\"), \"base64\").toString(\"utf8\");\n\t\t\t\t\tentries = parseWorkflowsFromTs(source);\n\t\t\t\t\torgContext = parseOrgContextFromTs(source);\n\t\t\t\t} catch {\n\t\t\t\t\t// No config — sync all workflows with no overrides\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (entries.length > 0) {\n\t\t\t\tallowedWorkflows = new Set(entries.map((e) => e.name));\n\t\t\t\tconst overrideEntries = entries.filter((e) => e.with != null).map((e) => [e.name, e.with!] as const);\n\t\t\t\tif (overrideEntries.length > 0) withOverrides = new Map(overrideEntries);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Parse error — sync all workflows with no overrides\n\t\t}\n\t}\n\n\t// ── 4. Build file batch ──────────────────────────────────────────────────\n\tconst batch = buildBatch(repo, allowedWorkflows, withOverrides, orgContext);\n\n\t// ── 5. Detect changes ────────────────────────────────────────────────────\n\tlet created = 0;\n\tlet updated = 0;\n\tlet unchanged = 0;\n\tconst changedFiles: Array<{ path: string; content: string }> = [];\n\n\tfor (const file of batch) {\n\t\tconst localSha = gitBlobSha(file.content);\n\t\tconst existingSha = existingBlobs.get(file.path);\n\n\t\tif (existingSha === localSha) {\n\t\t\tprint(` · unchanged ${file.path}`);\n\t\t\tunchanged++;\n\t\t} else if (existingSha) {\n\t\t\tprint(` ${dryRun ? \"~\" : \"✓\"} updated ${file.path}`);\n\t\t\tupdated++;\n\t\t\tif (!dryRun) changedFiles.push(file);\n\t\t} else {\n\t\t\tprint(` ${dryRun ? \"~\" : \"✓\"} created ${file.path}`);\n\t\t\tcreated++;\n\t\t\tif (!dryRun) changedFiles.push(file);\n\t\t}\n\t}\n\n\tprint(\"\");\n\tprint(` ${created} created, ${updated} updated, ${unchanged} unchanged`);\n\n\tif (dryRun || changedFiles.length === 0) {\n\t\treturn { status: dryRun ? \"dry-run\" : \"ok\", created, updated, unchanged };\n\t}\n\n\t// ── 6. Create blobs for changed files ────────────────────────────────────\n\tconst treeEntries: Array<{ path: string; mode: string; type: string; sha: string }> = [];\n\tfor (const file of changedFiles) {\n\t\ttry {\n\t\t\tconst blob = await client.git.createBlob(repo, file.content);\n\t\t\ttreeEntries.push({ path: file.path, mode: \"100644\", type: \"blob\", sha: blob.sha });\n\t\t} catch (err) {\n\t\t\tconst msg = `failed to create blob for ${file.path}: ${err instanceof Error ? err.message : String(err)}`;\n\t\t\tprint(` ✗ ${msg}`);\n\t\t\treturn { status: \"fail\", created, updated, unchanged, message: msg };\n\t\t}\n\t}\n\n\t// ── 7. Create tree ───────────────────────────────────────────────────────\n\tlet newTreeSha: string;\n\ttry {\n\t\tconst newTree = await client.git.createTree(repo, treeEntries, baseTreeSha);\n\t\tnewTreeSha = newTree.sha;\n\t} catch (err) {\n\t\tconst msg = `failed to create tree: ${err instanceof Error ? err.message : String(err)}`;\n\t\tprint(` ✗ ${msg}`);\n\t\treturn { status: \"fail\", created, updated, unchanged, message: msg };\n\t}\n\n\t// ── 8. Create commit ─────────────────────────────────────────────────────\n\tlet newCommitSha: string;\n\ttry {\n\t\tconst newCommit = await client.git.createCommit(repo, message, newTreeSha, [headSha]);\n\t\tnewCommitSha = newCommit.sha;\n\t} catch (err) {\n\t\tconst msg = `failed to create commit: ${err instanceof Error ? err.message : String(err)}`;\n\t\tprint(` ✗ ${msg}`);\n\t\treturn { status: \"fail\", created, updated, unchanged, message: msg };\n\t}\n\n\t// ── 9. Update (or create) branch ref ────────────────────────────────────\n\ttry {\n\t\tif (createPr && branch) {\n\t\t\ttry {\n\t\t\t\tawait client.git.createRef(repo, `refs/heads/${branch}`, newCommitSha);\n\t\t\t} catch (err) {\n\t\t\t\tif (!(err instanceof ProviderApiError) || err.status !== 422) throw err;\n\t\t\t\t// Branch already exists from a previous partial run — force-update it.\n\t\t\t\tawait client.git.updateRef(repo, `heads/${branch}`, newCommitSha, true);\n\t\t\t}\n\t\t} else {\n\t\t\tawait client.git.updateRef(repo, `heads/${targetBranch!}`, newCommitSha);\n\t\t}\n\t} catch (err) {\n\t\tconst msg = `failed to update ref: ${err instanceof Error ? err.message : String(err)}`;\n\t\tprint(` ✗ ${msg}`);\n\t\treturn { status: \"fail\", created, updated, unchanged, message: msg };\n\t}\n\n\t// ── 10. Open PR if requested ─────────────────────────────────────────────\n\tlet prUrl: string | undefined;\n\tif (branch && createPr && !dryRun) {\n\t\ttry {\n\t\t\tconst pr = await client.git.createPull(repo, {\n\t\t\t\ttitle: message.split(\"\\n\")[0]!,\n\t\t\t\thead: branch,\n\t\t\t\tbase: \"main\",\n\t\t\t\tbody: \"Auto-generated by `holocron sync-github`. Review and merge to apply template updates.\",\n\t\t\t});\n\t\t\tprUrl = pr.html_url;\n\t\t\tprint(` → PR opened: ${prUrl}`);\n\t\t} catch (err) {\n\t\t\tconst alreadyExists =\n\t\t\t\terr instanceof ProviderApiError && err.status === 422 && String(err.details).includes(\"already exists\");\n\t\t\tif (alreadyExists) {\n\t\t\t\tprint(` → PR already open for ${branch} — branch updated, ready to merge`);\n\t\t\t} else {\n\t\t\t\tprint(` ⚠ PR creation failed: ${err instanceof Error ? err.message : String(err)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { status: \"ok\", created, updated, unchanged, prUrl };\n}\n","import { readdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\n\n// Directories to skip when walking the repo tree\nconst SKIP_DIRS = new Set([\"node_modules\", \".git\", \"dist\", \"coverage\", \"build\", \".turbo\", \".next\", \"out\"]);\n\n// ── per-file-type patch functions ─────────────────────────────────────────────\n// Each returns the new file content, or null if nothing in that file changed.\n\nfunction patchPackageJson(content: string, from: number, to: number): string | null {\n\tlet pkg: Record<string, unknown>;\n\ttry {\n\t\tpkg = JSON.parse(content) as Record<string, unknown>;\n\t} catch {\n\t\treturn null;\n\t}\n\n\tlet changed = false;\n\n\tconst engines = pkg.engines as Record<string, string> | undefined;\n\tif (engines?.node && /^>=\\d+(?:\\.0\\.0)?$/.test(engines.node)) {\n\t\tconst major = parseInt(engines.node.match(/\\d+/)![0]!, 10);\n\t\tif (major === from) {\n\t\t\tengines.node = `>=${to}.0.0`;\n\t\t\tchanged = true;\n\t\t}\n\t}\n\n\tfor (const field of [\"devDependencies\", \"dependencies\"] as const) {\n\t\tconst deps = pkg[field] as Record<string, string> | undefined;\n\t\tif (!deps?.[\"@types/node\"]) continue;\n\t\t// Only update exact semver ranges; leave catalog: pins alone\n\t\tif (deps[\"@types/node\"] === `^${from}.0.0`) {\n\t\t\tdeps[\"@types/node\"] = `^${to}.0.0`;\n\t\t\tchanged = true;\n\t\t}\n\t}\n\n\treturn changed ? JSON.stringify(pkg, null, 2) + \"\\n\" : null;\n}\n\nfunction patchYaml(content: string, from: number, to: number): string | null {\n\t// node-version: 20 / node-version: '20' / node-version: \"20\"\n\tconst updated = content.replace(/node-version:\\s+['\"]?(\\d+)['\"]?/g, (match, ver) =>\n\t\tver === String(from) ? match.replace(String(from), String(to)) : match\n\t);\n\treturn updated !== content ? updated : null;\n}\n\nfunction patchPinFile(content: string, from: number, to: number): string | null {\n\t// .nvmrc / .node-version — \"20\" or \"20.x.y\" on the first line\n\tconst trimmed = content.trim();\n\tif (trimmed === String(from) || trimmed.startsWith(`${from}.`)) {\n\t\treturn `${to}\\n`;\n\t}\n\treturn null;\n}\n\nfunction patchDockerfile(content: string, from: number, to: number): string | null {\n\t// FROM node:20 / FROM node:20-alpine / FROM node:20.11.0\n\tconst updated = content.replace(/^(FROM\\s+node:)(\\d+)/gm, (match, prefix, ver) =>\n\t\tver === String(from) ? `${prefix}${to}` : match\n\t);\n\treturn updated !== content ? updated : null;\n}\n\nfunction patchToolVersions(content: string, from: number, to: number): string | null {\n\t// nodejs 20 / nodejs 20.11.0\n\tconst updated = content.replace(/^(nodejs\\s+)(\\d+)/gm, (match, prefix, ver) =>\n\t\tver === String(from) ? `${prefix}${to}` : match\n\t);\n\treturn updated !== content ? updated : null;\n}\n\ninterface Pattern {\n\tmatches: (filename: string) => boolean;\n\tpatch: (content: string, from: number, to: number) => string | null;\n}\n\nconst PATTERNS: Pattern[] = [\n\t{ matches: (n) => n === \"package.json\", patch: patchPackageJson },\n\t{ matches: (n) => n.endsWith(\".yml\") || n.endsWith(\".yaml\"), patch: patchYaml },\n\t{ matches: (n) => n === \".nvmrc\" || n === \".node-version\", patch: patchPinFile },\n\t{ matches: (n) => n === \"Dockerfile\" || n.startsWith(\"Dockerfile.\"), patch: patchDockerfile },\n\t{ matches: (n) => n === \".tool-versions\", patch: patchToolVersions },\n];\n\n// ── auto-detect current major from the repo ───────────────────────────────────\n\nfunction detectFrom(cwd: string, _readFile: (p: string) => string): number | null {\n\tfor (const name of [\".nvmrc\", \".node-version\"]) {\n\t\ttry {\n\t\t\tconst major = parseInt(_readFile(join(cwd, name)).trim(), 10);\n\t\t\tif (!isNaN(major)) return major;\n\t\t} catch {\n\t\t\t/* absent */\n\t\t}\n\t}\n\ttry {\n\t\tconst pkg = JSON.parse(_readFile(join(cwd, \"package.json\"))) as Record<string, unknown>;\n\t\tconst node = (pkg.engines as Record<string, string> | undefined)?.node;\n\t\tif (node) {\n\t\t\tconst m = node.match(/(\\d+)/);\n\t\t\tif (m) return parseInt(m[1]!, 10);\n\t\t}\n\t} catch {\n\t\t/* absent */\n\t}\n\treturn null;\n}\n\n// ── default file walker ───────────────────────────────────────────────────────\n\nfunction defaultWalkFiles(dir: string): string[] {\n\tconst results: string[] = [];\n\n\tfunction walk(current: string): void {\n\t\tlet entries: string[];\n\t\ttry {\n\t\t\tentries = readdirSync(current);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (SKIP_DIRS.has(entry)) continue;\n\t\t\tconst abs = join(current, entry);\n\t\t\ttry {\n\t\t\t\tif (statSync(abs).isDirectory()) walk(abs);\n\t\t\t\telse results.push(abs);\n\t\t\t} catch {\n\t\t\t\t/* skip unreadable */\n\t\t\t}\n\t\t}\n\t}\n\n\twalk(dir);\n\treturn results;\n}\n\n// ── public API ────────────────────────────────────────────────────────────────\n\nexport interface RunUpgradeNodeInput {\n\t/** Target Node.js major version (e.g., 22). */\n\tto: number;\n\t/** Source major version. Auto-detected from .nvmrc / engines.node when omitted. */\n\tfrom?: number;\n\t/** Working directory (repo root). Defaults to process.cwd(). */\n\tcwd?: string;\n\t/** Print what would change without writing anything. */\n\tdryRun?: boolean;\n\t/**\n\t * Extra file paths (relative to cwd) to scan in addition to the normal\n\t * walk. Use for non-conventional locations not covered by the pattern\n\t * registry (e.g., custom Dockerfiles, .tool-versions in a subdirectory).\n\t * Sourced from `upgrade.node.extra` in holocron.config.json.\n\t */\n\textra?: string[];\n\tprint?: (line: string) => void;\n\t/** Injectable for testing. */\n\treadFile?: (path: string) => string;\n\twriteFile?: (path: string, content: string) => void;\n\twalkFiles?: (dir: string) => string[];\n}\n\nexport type UpgradeNodeStatus = \"ok\" | \"fail\" | \"dry-run\";\n\nexport interface UpgradeNodeReport {\n\tstatus: UpgradeNodeStatus;\n\tupdated: readonly string[];\n\tmessage?: string;\n}\n\nexport async function runUpgradeNode(input: RunUpgradeNodeInput): Promise<UpgradeNodeReport> {\n\tconst print = input.print ?? ((line: string) => console.log(line));\n\tconst cwd = input.cwd ?? process.cwd();\n\tconst { to, dryRun = false, extra = [] } = input;\n\tconst _readFile = input.readFile ?? ((p: string) => readFileSync(p, \"utf8\"));\n\tconst _writeFile = input.writeFile ?? ((p: string, c: string) => writeFileSync(p, c));\n\tconst _walkFiles = input.walkFiles ?? defaultWalkFiles;\n\n\tconst from = input.from ?? detectFrom(cwd, _readFile);\n\tif (from === null) {\n\t\treturn {\n\t\t\tstatus: \"fail\",\n\t\t\tupdated: [],\n\t\t\tmessage: \"could not detect current Node version — pass --from <major>\",\n\t\t};\n\t}\n\n\tif (from === to) {\n\t\tprint(`Already at Node.js ${to} — nothing to do.`);\n\t\treturn { status: \"ok\", updated: [] };\n\t}\n\n\tprint(`Upgrading Node.js ${from} → ${to}${dryRun ? \" (dry-run)\" : \"\"}…`);\n\n\tconst updated: string[] = [];\n\tconst scanned = [..._walkFiles(cwd), ...extra.map((p) => join(cwd, p))];\n\n\tfor (const abs of scanned) {\n\t\tconst name = basename(abs);\n\t\tconst pattern = PATTERNS.find((p) => p.matches(name));\n\t\tif (!pattern) continue;\n\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = _readFile(abs);\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst patched = pattern.patch(content, from, to);\n\t\tif (patched === null) continue;\n\n\t\tconst rel = abs.startsWith(cwd + \"/\") ? abs.slice(cwd.length + 1) : abs;\n\t\tif (!dryRun) _writeFile(abs, patched);\n\t\tprint(` ${dryRun ? \"~\" : \"✓\"} ${rel}`);\n\t\tupdated.push(rel);\n\t}\n\n\tif (updated.length === 0) {\n\t\tprint(` · no files contained Node.js ${from} pins`);\n\t}\n\n\treturn { status: dryRun ? \"dry-run\" : \"ok\", updated };\n}\n","/**\n * `holocron.config.{json,js,ts}` file loader.\n *\n * Search order: json → js → ts. JSON is parsed directly; JS is loaded\n * via native dynamic import; TS is loaded via `tsImport` from tsx (a\n * runtime dep) so operators can write typed configs with `defineConfig`\n * without needing a separate build step.\n *\n * All three forms are validated through the same `resolveConfig` path.\n * Implements the lookup-order contract from issue #75 / #81.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport { basename, dirname, join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nimport type { HolocronConfig, ResolvedHolocronConfig } from \"./config.js\";\nimport { ConfigError, resolveConfig } from \"./config.js\";\n\nconst CANDIDATE_FILENAMES = [\"holocron.config.json\", \"holocron.config.js\", \"holocron.config.ts\"] as const;\n\nexport class ConfigFileError extends Error {\n\toverride name = \"ConfigFileError\";\n}\n\nexport interface LoadedConfig {\n\tresolved: ResolvedHolocronConfig;\n\t/** Absolute path to the file the config was read from. */\n\tfilepath: string;\n}\n\n/**\n * Read + parse + resolve `holocron.config.*` from the given directory.\n * Search order: json → js → ts. Throws `ConfigFileError` if nothing\n * found, or `ConfigError` if the config is malformed / invalid.\n */\nexport async function loadConfig(cwd: string): Promise<LoadedConfig> {\n\tfor (const filename of CANDIDATE_FILENAMES) {\n\t\tconst fullPath = join(cwd, filename);\n\t\tif (await fileExists(fullPath)) {\n\t\t\tif (filename.endsWith(\".json\")) {\n\t\t\t\treturn { resolved: await loadJson(fullPath), filepath: fullPath };\n\t\t\t}\n\t\t\tif (filename.endsWith(\".ts\")) {\n\t\t\t\treturn { resolved: await loadTs(fullPath), filepath: fullPath };\n\t\t\t}\n\t\t\treturn { resolved: await loadJs(fullPath), filepath: fullPath };\n\t\t}\n\t}\n\tthrow new ConfigFileError(\n\t\t`no holocron.config.{json,js,ts} found in ${cwd}. Create one — see the README for the schema.`\n\t);\n}\n\nasync function loadJson(filepath: string): Promise<ResolvedHolocronConfig> {\n\tconst raw = await readFile(filepath, \"utf8\");\n\tlet parsed: HolocronConfig;\n\ttry {\n\t\tparsed = JSON.parse(raw) as HolocronConfig;\n\t} catch (err) {\n\t\tthrow new ConfigError(`${filepath} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);\n\t}\n\treturn resolveConfig(await deriveDefaults(dirname(filepath), parsed));\n}\n\nasync function loadJs(filepath: string): Promise<ResolvedHolocronConfig> {\n\tconst mod = await import(pathToFileURL(filepath).href);\n\treturn resolveConfig(await deriveDefaults(dirname(filepath), extractRaw(filepath, mod)));\n}\n\nasync function loadTs(filepath: string): Promise<ResolvedHolocronConfig> {\n\tconst { tsImport } = await import(\"tsx/esm/api\");\n\tconst mod = await tsImport(pathToFileURL(filepath).href, import.meta.url);\n\treturn resolveConfig(await deriveDefaults(dirname(filepath), extractRaw(filepath, mod)));\n}\n\nfunction extractRaw(filepath: string, mod: unknown): HolocronConfig {\n\tconst outer = (mod as { default?: unknown }).default;\n\t// tsx CJS-transforms `export default x` into `exports.default = x`, which\n\t// dynamic import wraps as { default: { __esModule: true, default: x } }.\n\t// Unwrap the extra layer when present so both ESM and CJS outputs work.\n\tconst raw =\n\t\t(outer as { __esModule?: boolean })?.__esModule === true ? (outer as { default?: unknown }).default : outer;\n\tif (raw === undefined || raw === null) {\n\t\tthrow new ConfigFileError(`${filepath} must have a default export (use \\`export default defineConfig({…})\\`)`);\n\t}\n\treturn raw as HolocronConfig;\n}\n\nasync function deriveDefaults(configDir: string, raw: HolocronConfig): Promise<HolocronConfig> {\n\tconst result = { ...raw };\n\tif (!result.name) {\n\t\tresult.name = (await readPackageJsonName(configDir)) ?? basename(configDir);\n\t}\n\tif (result.repo && !result.repo.name) {\n\t\tconst repoName = await readGitRemote(configDir);\n\t\tif (repoName) result.repo = { ...result.repo, name: repoName };\n\t}\n\treturn result;\n}\n\nasync function readPackageJsonName(dir: string): Promise<string | undefined> {\n\ttry {\n\t\tconst content = await readFile(join(dir, \"package.json\"), \"utf8\");\n\t\tconst pkg = JSON.parse(content) as { name?: string };\n\t\treturn typeof pkg.name === \"string\" ? pkg.name.replace(/^@[^/]+\\//, \"\") : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nasync function readGitRemote(dir: string): Promise<string | undefined> {\n\ttry {\n\t\tconst { stdout } = await execFileAsync(\"git\", [\"remote\", \"get-url\", \"origin\"], { cwd: dir });\n\t\treturn parseGitRemoteUrl(stdout.trim());\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction parseGitRemoteUrl(url: string): string | undefined {\n\tconst httpsMatch = url.match(/github\\.com\\/([^/]+\\/[^/]+?)(?:\\.git)?$/);\n\tif (httpsMatch) return httpsMatch[1]!;\n\tconst sshMatch = url.match(/github\\.com:([^/]+\\/[^/]+?)(?:\\.git)?$/);\n\tif (sshMatch) return sshMatch[1]!;\n\treturn undefined;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tconst s = await stat(path);\n\t\treturn s.isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n","import type { ErrorEvent, EventHint } from \"@sentry/node\";\nimport * as Sentry from \"@sentry/node\";\n\n// Paste your DSN from Sentry → Settings → Client Keys once the project is created.\n// Empty string = telemetry silently disabled — safe to ship before the project exists.\nconst DSN: string = \"https://95cbb72ad5636c94e119a5405ee8f55f@o4508238154104832.ingest.us.sentry.io/4511810950791168\";\n\nfunction isEnabled(): boolean {\n\treturn !process.env.NO_HOLOCRON_TELEMETRY && DSN !== \"\";\n}\n\nexport function init(version: string): void {\n\tif (!isEnabled()) return;\n\tSentry.init({\n\t\tdsn: DSN,\n\t\trelease: `holocron@${version}`,\n\t\tenvironment: process.env.CI ? \"ci\" : \"local\",\n\t\ttracesSampleRate: 1.0,\n\t\tbeforeSend: scrubError,\n\t});\n\tSentry.startSession();\n\tSentry.setTag(\"os\", process.platform);\n\tSentry.setTag(\"node\", process.version);\n\tSentry.setTag(\"ci\", String(Boolean(process.env.CI)));\n}\n\nexport function startCommand(name: string): (ok: boolean) => void {\n\tif (!isEnabled()) return () => {};\n\tSentry.setTag(\"command\", name);\n\tconst span = Sentry.startInactiveSpan({ name, op: \"holocron.command\", forceTransaction: true });\n\treturn (ok: boolean) => {\n\t\tspan.setStatus({ code: ok ? 1 : 2 });\n\t\tspan.end();\n\t};\n}\n\nexport function captureException(err: unknown): void {\n\tif (!isEnabled()) return;\n\tSentry.captureException(err);\n}\n\nexport function endSession(): void {\n\tif (!isEnabled()) return;\n\tSentry.endSession();\n}\n\nexport async function flush(): Promise<void> {\n\tif (!isEnabled()) return;\n\tawait Sentry.close(2_000);\n}\n\n// Scrub known token shapes from any string in the Sentry event payload.\nconst TOKEN_RE = /\\b(ghp_|ghs_|glpat-|xoxb-|xoxp-|npm_|sk-|[A-Z][A-Z0-9_]{2,}_TOKEN[=\\s])[^\\s\"]*/g;\n\nfunction redact(raw: string): string {\n\treturn raw.replace(TOKEN_RE, \"[REDACTED]\");\n}\n\nfunction scrubError(event: ErrorEvent, _hint: EventHint): ErrorEvent {\n\treturn JSON.parse(redact(JSON.stringify(event))) as ErrorEvent;\n}\n","export class TokenParseError extends Error {\n\toverride name = \"TokenParseError\";\n}\n\nexport interface ParsedTokenArgs {\n\t/** Set when a bare (unkeyed) --token value was passed. Used as fallback for all plugins. */\n\tcliToken?: string;\n\t/** Set when one or more vendor=value pairs were passed. */\n\tcliTokens?: Record<string, string>;\n}\n\n/**\n * Converts raw --token CLI values into a typed result.\n *\n * Bare form: --token ghp_xxx → { cliToken: \"ghp_xxx\" }\n * Keyed form: --token github=ghp_xxx → { cliTokens: { github: \"ghp_xxx\" } }\n * Mixed: --token github=ghp_xxx --token v_yyy\n * → { cliToken: \"v_yyy\", cliTokens: { github: \"ghp_xxx\" } }\n *\n * Values may contain \"=\" (e.g. base64 strings) — only the first \"=\" is treated as a separator.\n */\nexport function parseTokenArgs(tokens: string[]): ParsedTokenArgs {\n\tif (tokens.length === 0) return {};\n\n\tconst cliTokens: Record<string, string> = {};\n\tconst bare: string[] = [];\n\n\tfor (const raw of tokens) {\n\t\tconst eqIdx = raw.indexOf(\"=\");\n\n\t\tif (eqIdx === -1) {\n\t\t\tbare.push(raw);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst vendor = raw.slice(0, eqIdx);\n\t\tconst value = raw.slice(eqIdx + 1);\n\n\t\tif (vendor.trim() === \"\") {\n\t\t\tthrow new TokenParseError(`invalid --token value \"${raw}\": vendor name must not be empty`);\n\t\t}\n\t\tif (/\\s/.test(vendor)) {\n\t\t\tthrow new TokenParseError(`invalid --token value \"${raw}\": vendor name must not contain whitespace`);\n\t\t}\n\t\tif (value === \"\") {\n\t\t\tthrow new TokenParseError(`invalid --token value \"${raw}\": token value must not be empty`);\n\t\t}\n\n\t\tcliTokens[vendor] = value;\n\t}\n\n\tif (bare.length > 1) {\n\t\tthrow new TokenParseError(\n\t\t\t`only one bare --token value is allowed; got ${bare.length.toString()} — use vendor=value form for multiple tokens`\n\t\t);\n\t}\n\n\tconst result: ParsedTokenArgs = {};\n\tif (bare.length === 1) result.cliToken = bare[0];\n\tif (Object.keys(cliTokens).length > 0) result.cliTokens = cliTokens;\n\treturn result;\n}\n","import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport chalk from \"chalk\";\n\nconst PACKAGE_NAME = \"@theholocron/cli\";\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000;\nconst FETCH_TIMEOUT_MS = 3000;\n\ninterface CacheEntry {\n\tlatestVersion: string;\n\tcheckedAt: number;\n}\n\nfunction getCacheDir(): string {\n\treturn process.env[\"HOLOCRON_CACHE_DIR\"] ?? join(homedir(), \".cache\", \"holocron\");\n}\n\nfunction getCachePath(): string {\n\treturn join(getCacheDir(), \"update-check.json\");\n}\n\nfunction readCache(): CacheEntry | null {\n\ttry {\n\t\treturn JSON.parse(readFileSync(getCachePath(), \"utf8\")) as CacheEntry;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction writeCache(entry: CacheEntry): void {\n\ttry {\n\t\tmkdirSync(getCacheDir(), { recursive: true });\n\t\twriteFileSync(getCachePath(), JSON.stringify(entry));\n\t} catch {\n\t\t// silently ignore — update check is best-effort\n\t}\n}\n\nasync function fetchLatestVersion(channel: string): Promise<string | null> {\n\ttry {\n\t\tconst res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}`, {\n\t\t\tsignal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n\t\t});\n\t\tif (!res.ok) return null;\n\t\tconst data = (await res.json()) as { \"dist-tags\": Record<string, string> };\n\t\treturn data[\"dist-tags\"][channel] ?? data[\"dist-tags\"][\"latest\"] ?? null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction getChannel(version: string): string {\n\tconst match = /^[^-]+-([a-zA-Z]+)/.exec(version);\n\treturn match?.[1] ?? \"latest\";\n}\n\nexport function isUpdateAvailable(current: string, latest: string): boolean {\n\tconst normalize = (v: string) => v.replace(/^v/, \"\");\n\tconst c = normalize(current);\n\tconst l = normalize(latest);\n\tif (c === l) return false;\n\n\tconst splitPre = (v: string): [string, string] => {\n\t\tconst idx = v.indexOf(\"-\");\n\t\treturn idx === -1 ? [v, \"\"] : [v.slice(0, idx), v.slice(idx + 1)];\n\t};\n\n\tconst [cRelease, cPre] = splitPre(c);\n\tconst [lRelease, lPre] = splitPre(l);\n\n\tconst parseRelease = (r: string) => r.split(\".\").map(Number);\n\tconst cParts = parseRelease(cRelease);\n\tconst lParts = parseRelease(lRelease);\n\n\tfor (let i = 0; i < Math.max(cParts.length, lParts.length); i++) {\n\t\tconst cv = cParts[i] ?? 0;\n\t\tconst lv = lParts[i] ?? 0;\n\t\tif (lv > cv) return true;\n\t\tif (lv < cv) return false;\n\t}\n\n\t// Release parts equal — compare prerelease\n\tif (!lPre && cPre) return true; // stable > prerelease\n\tif (lPre && !cPre) return false; // prerelease < stable\n\n\t// Both prerelease — compare segment by segment\n\tconst cPreParts = cPre.split(\".\");\n\tconst lPreParts = lPre.split(\".\");\n\tfor (let i = 0; i < Math.max(cPreParts.length, lPreParts.length); i++) {\n\t\tconst cv = cPreParts[i] ?? \"\";\n\t\tconst lv = lPreParts[i] ?? \"\";\n\t\tconst cvNum = Number(cv);\n\t\tconst lvNum = Number(lv);\n\t\tif (!isNaN(cvNum) && !isNaN(lvNum)) {\n\t\t\tif (lvNum > cvNum) return true;\n\t\t\tif (lvNum < cvNum) return false;\n\t\t} else {\n\t\t\tif (lv > cv) return true;\n\t\t\tif (lv < cv) return false;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nfunction formatNotice(current: string, latest: string): string {\n\tconst installCmd = `npm install -g ${PACKAGE_NAME}`;\n\t// Measure raw strings before applying chalk so we avoid control-char regexes.\n\tconst raw1 = `Update available: ${current} → ${latest}`;\n\tconst raw2 = `Run ${installCmd} to update`;\n\tconst width = Math.max(raw1.length, raw2.length) + 4;\n\tconst bar = chalk.yellow(\"─\".repeat(width));\n\tconst border = chalk.yellow(\"│\");\n\tconst pad = (raw: string, styled: string) => `${border} ${styled}${\" \".repeat(width - 2 - raw.length)} ${border}`;\n\treturn [\n\t\t\"\",\n\t\tchalk.yellow(`╭${bar}╮`),\n\t\tpad(raw1, `Update available: ${chalk.dim(current)} → ${chalk.green(latest)}`),\n\t\tpad(raw2, `Run ${chalk.cyan(installCmd)} to update`),\n\t\tchalk.yellow(`╰${bar}╯`),\n\t\t\"\",\n\t].join(\"\\n\");\n}\n\nexport async function checkForUpdates(currentVersion: string): Promise<(() => void) | null> {\n\tif (process.env[\"CI\"] || process.env[\"NO_UPDATE_NOTIFIER\"]) return null;\n\n\tconst channel = getChannel(currentVersion);\n\tconst cache = readCache();\n\tconst now = Date.now();\n\n\tlet latestVersion: string | null = null;\n\n\tif (cache && now - cache.checkedAt < CACHE_TTL_MS) {\n\t\tlatestVersion = cache.latestVersion;\n\t} else {\n\t\tlatestVersion = await fetchLatestVersion(channel);\n\t\tif (latestVersion) writeCache({ latestVersion, checkedAt: now });\n\t}\n\n\tif (!latestVersion || !isUpdateAvailable(currentVersion, latestVersion)) return null;\n\n\treturn () => {\n\t\tprocess.stderr.write(formatNotice(currentVersion, latestVersion as string) + \"\\n\");\n\t};\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { input, select } from \"@inquirer/prompts\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\n\nimport { AuthError, createFeatureResolver } from \"./auth-resolver.js\";\nimport { CARDINALITY } from \"./capabilities/index.js\";\nimport { runAuthCheck, runAuthList, runAuthSet, runAuthUnset } from \"./commands/auth.js\";\nimport { runCleanupPreview } from \"./commands/cleanup-preview.js\";\nimport { runClone } from \"./commands/clone.js\";\nimport { runDeploy } from \"./commands/deploy.js\";\nimport { runDoctor } from \"./commands/doctor.js\";\nimport { NewError, parseTopics, runNew, validateRepoName } from \"./commands/new.js\";\nimport { runNpmBumpVersions } from \"./commands/npm-bump-versions.js\";\nimport { runNpmPublishInitial } from \"./commands/npm-publish-initial.js\";\nimport { PluginCreateError, resolvePluginCreateInputs, runPluginCreate } from \"./commands/plugin-create/index.js\";\nimport { runSecretSet } from \"./commands/secret-set.js\";\nimport { runSecretsSync } from \"./commands/secrets-sync.js\";\nimport { runSetup } from \"./commands/setup.js\";\nimport { runSkillsInstall, runSkillsRemove, runSkillsUpdate } from \"./commands/skills.js\";\nimport { runSync } from \"./commands/sync.js\";\nimport { runSyncGithub } from \"./commands/sync-github.js\";\nimport { runSyncReadme } from \"./commands/sync-readme.js\";\nimport { runUpgradeNode } from \"./commands/upgrade-node.js\";\nimport { loadConfig } from \"./load-config.js\";\nimport { captureException, endSession, flush, init, startCommand } from \"./telemetry.js\";\nimport { type ParsedTokenArgs, parseTokenArgs, TokenParseError } from \"./token-args.js\";\nimport { checkForUpdates } from \"./update-notifier.js\";\n\nconst resolveCloneToken = createFeatureResolver({ envName: \"HOLOCRON_READ_TOKEN\", keyringKey: \"github.read\" });\nconst resolveSyncToken = createFeatureResolver({ envName: \"HOLOCRON_SYNC_TOKEN\", keyringKey: \"github.sync\" });\n\nconst { version: CLI_VERSION } = JSON.parse(readFileSync(new URL(\"../package.json\", import.meta.url), \"utf-8\")) as {\n\tversion: string;\n};\n\n/**\n * Resolves the active org in priority order:\n * 1. `--org` CLI flag\n * 2. `HOLOCRON_ORG` env var\n * 3. `org` from `holocron.config.ts`\n */\nfunction resolveOrg(argv: { org?: string }, config: { org?: string }): string | undefined {\n\treturn argv.org ?? process.env[\"HOLOCRON_ORG\"] ?? config.org;\n}\n\n/** Parses --token values and returns the context spread, or null on parse error (exits with code 1). */\nfunction tokenContext(rawTokens: string[] | undefined): ParsedTokenArgs | null {\n\tif (!rawTokens?.length) return {};\n\ttry {\n\t\treturn parseTokenArgs(rawTokens);\n\t} catch (err) {\n\t\tif (err instanceof TokenParseError) {\n\t\t\tconsole.error(`--token: ${err.message}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn null;\n\t\t}\n\t\tthrow err;\n\t}\n}\n\ninit(CLI_VERSION);\nconst updateCheckPromise = checkForUpdates(CLI_VERSION);\n\nlet finishCommand: (ok: boolean) => void = () => {};\n\ntry {\n\tawait yargs(hideBin(process.argv))\n\t\t.middleware((argv) => {\n\t\t\tconst name = (argv._ as string[]).slice(0, 2).join(\" \") || \"unknown\";\n\t\t\tfinishCommand = startCommand(name);\n\t\t})\n\t\t.scriptName(\"\")\n\t\t.usage(\"holocron <command> [options]\")\n\t\t// ── global options (apply to every subcommand) ──────────────────────\n\t\t.option(\"dry-run\", {\n\t\t\ttype: \"boolean\",\n\t\t\tdefault: false,\n\t\t\tdescribe:\n\t\t\t\t\"Print what would be mutated without calling capability mutators. \" +\n\t\t\t\t\"Commands branch on this; read-only commands ignore it.\",\n\t\t})\n\t\t.option(\"token\", {\n\t\t\ttype: \"string\",\n\t\t\tarray: true,\n\t\t\tdescribe:\n\t\t\t\t\"Vendor token override for plugins. \" +\n\t\t\t\t\"Bare form: --token <value> (fallback for all plugins, single-plugin commands). \" +\n\t\t\t\t\"Keyed form: --token vendor=value (targets a specific provider; repeat for each). \" +\n\t\t\t\t\"Example: --token github=ghp_xxx --token vercel=v_yyy\",\n\t\t})\n\t\t.option(\"org\", {\n\t\t\ttype: \"string\",\n\t\t\tdescribe:\n\t\t\t\t\"Active org name for namespaced keyring lookup. \" +\n\t\t\t\t\"Overrides HOLOCRON_ORG env var and the `org` field in holocron.config.ts. \" +\n\t\t\t\t\"Example: --org theholocron\",\n\t\t})\n\t\t.option(\"cwd\", {\n\t\t\ttype: \"string\",\n\t\t\tdefault: process.cwd(),\n\t\t\tdescribe: \"Directory to search for holocron.config.json\",\n\t\t})\n\t\t// ── commands ────────────────────────────────────────────────────────\n\t\t.command(\n\t\t\t\"version\",\n\t\t\t\"Print the CLI version\",\n\t\t\t() => {},\n\t\t\t() => {\n\t\t\t\tconsole.log(`holocron ${CLI_VERSION}`);\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"clone\",\n\t\t\t\"Clone all repos in a GitHub org as siblings under a single directory\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.option(\"org\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"GitHub org to clone (e.g., theholocron)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"dir\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Parent directory to clone into (default: ~/Code/<org>)\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tlet token: string;\n\t\t\t\ttry {\n\t\t\t\t\ttoken = resolveCloneToken({ cliToken: tokens.cliTokens?.[\"github\"] ?? tokens.cliToken });\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`clone: ${err instanceof AuthError ? err.message : String(err)}`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst report = await runClone({\n\t\t\t\t\torg: argv.org,\n\t\t\t\t\ttoken,\n\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t...(argv.dir ? { dir: argv.dir } : {}),\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"doctor\",\n\t\t\t\"Load the config and run a smoke check against every provider\",\n\t\t\t(y) =>\n\t\t\t\ty.option(\"repo\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescribe: 'Repo coords (\"owner/name\"). Defaults to plugin-specific resolution.',\n\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runDoctor({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...(argv.repo ? { repo: argv.repo } : {}),\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (report.summary.fail > 0) {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"setup\",\n\t\t\t\"Apply infra setup actions across every configured capability\",\n\t\t\t(y) =>\n\t\t\t\ty.option(\"repo\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescribe: 'Repo coords (\"owner/name\"). Defaults to plugin-specific resolution.',\n\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runSetup({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...(argv.repo ? { repo: argv.repo } : {}),\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (report.summary.fail > 0) {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"skills\",\n\t\t\t\"Manage agent skills from the @theholocron/skills registry\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"install\",\n\t\t\t\t\t\t\"Copy skills from @theholocron/skills into .agents/ with agent symlinks\",\n\t\t\t\t\t\t() => {},\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\t\t\t\tawait runSkillsInstall({ loaded, context: { repoRoot: argv.cwd, dryRun: argv.dryRun } });\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"remove [names..]\",\n\t\t\t\t\t\t\"Remove installed skills via npx skills remove\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy.positional(\"names\", {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\tarray: true,\n\t\t\t\t\t\t\t\tdescribe: \"Skill name(s) to remove (omit to remove all installed skills)\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t(argv) => {\n\t\t\t\t\t\t\tconst report = runSkillsRemove({\n\t\t\t\t\t\t\t\tcontext: { repoRoot: argv.cwd, dryRun: argv.dryRun },\n\t\t\t\t\t\t\t\t...(argv.names?.length ? { names: argv.names as string[] } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"update [name]\",\n\t\t\t\t\t\t\"Update installed skills to their latest upstream versions via npx skills update\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy.positional(\"name\", {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\tdescribe: \"Skill name to update (omit to update all installed skills)\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t(argv) => {\n\t\t\t\t\t\t\tconst report = runSkillsUpdate({\n\t\t\t\t\t\t\t\tcontext: { repoRoot: argv.cwd, dryRun: argv.dryRun },\n\t\t\t\t\t\t\t\t...(argv.name ? { name: argv.name as string } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.demandCommand(1, \"Run `holocron skills --help` to see available skills subcommands.\"),\n\t\t\t() => {}\n\t\t)\n\t\t.command(\n\t\t\t\"secret set <name> [value]\",\n\t\t\t\"Set a single secret via the configured `secrets` capability\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"name\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Secret name (e.g., NPM_TOKEN)\",\n\t\t\t\t\t})\n\t\t\t\t\t.positional(\"value\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Secret value (positional). If omitted, sources from --from-stdin, --from-env, or env var matching <name>.\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"from-stdin\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescribe: \"Read the secret value from stdin\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"from-env\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Read the secret value from the named env var (otherwise: env var matching <name>)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"scope\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdefault: \"repo\",\n\t\t\t\t\t\tdescribe: 'Scope: \"repo\" (default), \"env=<name>\", or \"org=<name>\"',\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst scopeArg = argv.scope as string;\n\t\t\t\tconst scope = parseScope(scopeArg);\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runSecretSet({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t\tname: argv.name as string,\n\t\t\t\t\t...(argv.value ? { value: argv.value as string } : {}),\n\t\t\t\t\t...(argv.fromStdin ? { fromStdin: true } : {}),\n\t\t\t\t\t...(argv.fromEnv ? { fromEnv: argv.fromEnv as string } : {}),\n\t\t\t\t\tscope,\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"secrets sync <environmentId>\",\n\t\t\t\"Read a vault environment + fan KEY=VALUEs out to secrets + deployment env vars\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"environmentId\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Vault environment id to read (1P Environment id, etc.)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"project-id\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Deployment project id (e.g., Vercel prj_*). Required when deployment is loaded.\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"target\", {\n\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\tdefault: [\"production\", \"preview\"] as Array<\"development\" | \"preview\" | \"production\">,\n\t\t\t\t\t\tdescribe: \"Deployment targets to sync to. Defaults to production + preview.\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runSecretsSync({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t\tenvironmentId: argv.environmentId as string,\n\t\t\t\t\t...(argv.projectId ? { projectId: argv.projectId } : {}),\n\t\t\t\t\ttargets: argv.target as Array<\"development\" | \"preview\" | \"production\">,\n\t\t\t\t});\n\t\t\t\tif (report.summary.fail > 0) {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"deploy <branch>\",\n\t\t\t\"Trigger a deployment via the configured `deployment` capability\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"branch\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Git branch to deploy\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"project-id\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Deployment project id (e.g., Vercel prj_*)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"target\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tchoices: [\"production\", \"staging\"] as const,\n\t\t\t\t\t\tdescribe: \"Named environment to deploy into. Omit for a branch preview.\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runDeploy({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t\tprojectId: argv.projectId as string,\n\t\t\t\t\tbranch: argv.branch as string,\n\t\t\t\t\t...(argv.target ? { target: argv.target as \"production\" | \"staging\" } : {}),\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"cleanup-preview <pr>\",\n\t\t\t\"List and delete Cloudflare Pages preview deployments for a GitHub PR\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"pr\", {\n\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"PR number to clean up\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"project\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Cloudflare Pages project name (e.g. theholocron-preview)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"repo\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"GitHub repo as owner/name — defaults to the repo in holocron.config\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runCleanupPreview({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t\tprNumber: argv.pr as number,\n\t\t\t\t\tproject: argv.project as string,\n\t\t\t\t\t...(argv.repo ? { repo: argv.repo as string } : {}),\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"npm\",\n\t\t\t\"npm-related monorepo utilities\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"bump-versions <new-version>\",\n\t\t\t\t\t\t\"Bump all non-private package versions in lockstep (semantic-release prepareCmd)\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy.positional(\"new-version\", {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\t\t\tdescribe: \"Version to set (e.g., 4.2.0 or 2.0.0-alpha.1)\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\tconst report = await runNpmBumpVersions({\n\t\t\t\t\t\t\t\tversion: argv.newVersion as string,\n\t\t\t\t\t\t\t\tcwd: argv.cwd,\n\t\t\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"publish-initial\",\n\t\t\t\t\t\t\"One-shot bootstrap publish for trusted-publishing-eligible packages\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy\n\t\t\t\t\t\t\t\t.option(\"tag\", {\n\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\tdefault: \"alpha\",\n\t\t\t\t\t\t\t\t\tdescribe: \"npm distribution tag (defaults to alpha)\",\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.option(\"otp\", {\n\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\t\t\t\"One-time password from your authenticator (required if npm needs 2FA for writes)\",\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\tconst report = await runNpmPublishInitial({\n\t\t\t\t\t\t\t\tcwd: argv.cwd,\n\t\t\t\t\t\t\t\ttag: argv.tag,\n\t\t\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t\t\t...(argv.otp ? { otp: argv.otp as string } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.demandCommand(1, \"Run `holocron npm --help` to see available npm subcommands.\"),\n\t\t\t() => {}\n\t\t)\n\t\t.command(\n\t\t\t\"sync [steps..]\",\n\t\t\t\"Sync state from config to the provider and local files (labels, properties, topics, keywords, description, homepage, readme)\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"steps\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tarray: true,\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Steps to run: labels, properties, topics, keywords, description, homepage, readme (default: all)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"repo\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: 'Repo coords (\"owner/name\"). Defaults to plugin-specific resolution.',\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\tif (!tokens) return;\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runSync({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\trepoRoot: argv.cwd,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t...(argv.repo ? { repo: argv.repo } : {}),\n\t\t\t\t\t\t...tokens,\n\t\t\t\t\t\torg: resolveOrg(argv, loaded.resolved),\n\t\t\t\t\t},\n\t\t\t\t\t...(argv.steps && argv.steps.length > 0 ? { steps: argv.steps as string[] } : {}),\n\t\t\t\t});\n\t\t\t\tif (report.summary.fail > 0) {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"sync-github\",\n\t\t\t\"Sync workflow templates and composite actions to theholocron/.github via the GitHub API\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.option(\"repo\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdefault: \"theholocron/.github\",\n\t\t\t\t\t\tdescribe: \"Target org/repo (default: theholocron/.github)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"branch\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Push to this branch instead of the default branch (enables PR-based workflow for protected repos)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"pr\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescribe: \"Open a PR after pushing to --branch (no-op without --branch)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"message\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Commit message (default: chore: sync from theholocron/holocron)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"output-dir\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Write generated files to this local directory instead of pushing (for validation)\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst outputDir = argv[\"output-dir\"] as string | undefined;\n\t\t\t\tconst parsed = tokenContext(argv.token);\n\t\t\t\tif (!parsed) return;\n\t\t\t\tlet token: string;\n\t\t\t\tif (outputDir) {\n\t\t\t\t\ttoken = \"no-token-needed\";\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\ttoken = resolveSyncToken({ cliToken: parsed.cliTokens?.[\"github\"] ?? parsed.cliToken });\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(`sync-github: ${err instanceof AuthError ? err.message : String(err)}`);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst report = await runSyncGithub({\n\t\t\t\t\ttoken,\n\t\t\t\t\trepo: argv.repo,\n\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t...(argv.branch ? { branch: argv.branch } : {}),\n\t\t\t\t\t...(argv.pr ? { createPr: true } : {}),\n\t\t\t\t\t...(argv.message ? { message: argv.message } : {}),\n\t\t\t\t\t...(outputDir ? { outputDir } : {}),\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"sync-readme\",\n\t\t\t\"Sync the Installation + Usage block in README.md from package.json\",\n\t\t\t(y) =>\n\t\t\t\ty.option(\"dry-run\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdescribe: \"Print what would change without writing\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconst report = await runSyncReadme({\n\t\t\t\t\tloaded,\n\t\t\t\t\tcontext: { repoRoot: argv.cwd, dryRun: argv.dryRun },\n\t\t\t\t});\n\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"config show\",\n\t\t\t\"Print the resolved holocron config\",\n\t\t\t() => {},\n\t\t\tasync (argv) => {\n\t\t\t\tconst loaded = await loadConfig(argv.cwd);\n\t\t\t\tconsole.log(JSON.stringify(loaded.resolved, null, 2));\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"new [type] [name]\",\n\t\t\t\"Scaffold a new repo from a GitHub template (e.g. cli, react, nextjs, node, monorepo, base)\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"type\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Template type — maps to theholocron/<type>-template \" +\n\t\t\t\t\t\t\t\"(e.g. cli, react, nextjs, node, monorepo, base)\",\n\t\t\t\t\t})\n\t\t\t\t\t.positional(\"name\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"New repo name (kebab-case, e.g. my-tool)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"description\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Short description — replaces <description> placeholders in the template\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"homepage\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Homepage URL — replaces <homepage> placeholders and appears in holocron.config.ts\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"vault\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Vault provider: none, doppler, 1password, infisical\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"deployment\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Deployment provider: none, vercel\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"agent\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"AI agent: claude, none\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"runtime-environment\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Runtime environment: node, browser, universal, none\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"topics\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Comma-separated repo topics (e.g. typescript,nodejs)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"protection\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Branch protection level: strict, balanced, minimal\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"open-source\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdescribe: \"Whether the repo is open source (default: true)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"uses-external-packages\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdescribe: \"Whether the repo calls external APIs or services (default: true)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"skills\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Comma-separated agent skill names (e.g. git-safety,pr-workflow)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"is-template\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdescribe: \"Mark the new repo as a GitHub template repository\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"org\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdefault: \"theholocron\",\n\t\t\t\t\t\tdescribe: \"GitHub org that owns the template and will own the new repo\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"verify\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdefault: true,\n\t\t\t\t\t\tdescribe: \"Run pnpm install + holocron setup after bootstrapping (--no-verify skips)\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst tokens = tokenContext(argv.token);\n\t\t\t\t\tif (!tokens) return;\n\t\t\t\t\tconst adminToken = tokens.cliTokens?.[\"github\"] ?? tokens.cliToken;\n\n\t\t\t\t\tlet type = argv.type as string | undefined;\n\t\t\t\t\tlet name = argv.name as string | undefined;\n\t\t\t\t\tlet description = argv.description as string | undefined;\n\t\t\t\t\tlet homepage = argv.homepage as string | undefined;\n\t\t\t\t\tlet vaultProvider = argv.vault as string | undefined;\n\t\t\t\t\tlet vaultProject: string | undefined;\n\t\t\t\t\tlet vaultConfig: string | undefined;\n\t\t\t\t\tlet deploymentProvider = argv.deployment as string | undefined;\n\t\t\t\t\tlet agent = argv.agent as string | undefined;\n\t\t\t\t\tlet runtimeEnvironment = argv.runtimeEnvironment as string | undefined;\n\t\t\t\t\tlet topics: string[] = parseTopics(argv.topics as string | undefined);\n\t\t\t\t\tlet protection = argv.protection as string | undefined;\n\t\t\t\t\tlet openSource = argv.openSource as boolean | undefined;\n\t\t\t\t\tlet usesExternalPackages = argv.usesExternalPackages as boolean | undefined;\n\t\t\t\t\tlet skills: string[] = parseTopics(argv.skills as string | undefined);\n\t\t\t\t\tconst isTemplate = argv.isTemplate as boolean | undefined;\n\n\t\t\t\t\t// Interactive wizard — skip any field already supplied as a CLI arg\n\t\t\t\t\tif (!type) {\n\t\t\t\t\t\ttype = await select({\n\t\t\t\t\t\t\tmessage: \"Template type:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"node — Node.js library or tool\", value: \"node\" },\n\t\t\t\t\t\t\t\t{ name: \"cli — CLI application (inquirer, chalk, yargs)\", value: \"cli\" },\n\t\t\t\t\t\t\t\t{ name: \"monorepo — Turbo monorepo\", value: \"monorepo\" },\n\t\t\t\t\t\t\t\t{ name: \"react — React component library\", value: \"react\" },\n\t\t\t\t\t\t\t\t{ name: \"nextjs — Next.js application\", value: \"nextjs\" },\n\t\t\t\t\t\t\t\t{ name: \"base — Minimal repo (no package.json)\", value: \"base\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!name) {\n\t\t\t\t\t\tname = await input({\n\t\t\t\t\t\t\tmessage: \"Repo name (kebab-case):\",\n\t\t\t\t\t\t\tvalidate: validateRepoName,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tname = name.trim();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (description === undefined) {\n\t\t\t\t\t\tdescription = await input({ message: \"Short description:\" });\n\t\t\t\t\t}\n\n\t\t\t\t\tif (homepage === undefined) {\n\t\t\t\t\t\tconst raw = await input({ message: \"Homepage URL (optional, Enter to skip):\" });\n\t\t\t\t\t\thomepage = raw.trim() || undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!runtimeEnvironment) {\n\t\t\t\t\t\truntimeEnvironment = await select({\n\t\t\t\t\t\t\tmessage: \"Runtime environment:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"node — Node.js process\", value: \"node\" },\n\t\t\t\t\t\t\t\t{ name: \"browser — Browser only\", value: \"browser\" },\n\t\t\t\t\t\t\t\t{ name: \"universal — Node.js + browser\", value: \"universal\" },\n\t\t\t\t\t\t\t\t{ name: \"none — No runtime (docs, config, etc.)\", value: \"none\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdefault: type === \"base\" ? \"none\" : \"node\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!vaultProvider) {\n\t\t\t\t\t\tvaultProvider = await select({\n\t\t\t\t\t\t\tmessage: \"Vault provider:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"None\", value: \"none\" },\n\t\t\t\t\t\t\t\t{ name: \"Doppler\", value: \"doppler\" },\n\t\t\t\t\t\t\t\t{ name: \"1Password\", value: \"1password\" },\n\t\t\t\t\t\t\t\t{ name: \"Infisical\", value: \"infisical\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (vaultProvider === \"doppler\") {\n\t\t\t\t\t\tvaultProject = await input({ message: \"Doppler project name:\", default: name });\n\t\t\t\t\t\tvaultConfig = await input({ message: \"Doppler config:\", default: \"dev\" });\n\t\t\t\t\t} else if (vaultProvider === \"1password\" || vaultProvider === \"infisical\") {\n\t\t\t\t\t\tvaultProject = await input({\n\t\t\t\t\t\t\tmessage: `${vaultProvider === \"1password\" ? \"1Password vault\" : \"Infisical project\"} name:`,\n\t\t\t\t\t\t\tdefault: name,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!deploymentProvider) {\n\t\t\t\t\t\tdeploymentProvider = await select({\n\t\t\t\t\t\t\tmessage: \"Deployment provider:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"None\", value: \"none\" },\n\t\t\t\t\t\t\t\t{ name: \"Vercel\", value: \"vercel\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!agent) {\n\t\t\t\t\t\tagent = await select({\n\t\t\t\t\t\t\tmessage: \"AI agent:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"Claude\", value: \"claude\" },\n\t\t\t\t\t\t\t\t{ name: \"None\", value: \"none\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (topics.length === 0) {\n\t\t\t\t\t\tconst raw = await input({ message: \"Topics (comma-separated, optional):\" });\n\t\t\t\t\t\ttopics = parseTopics(raw);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!protection) {\n\t\t\t\t\t\tprotection = await select({\n\t\t\t\t\t\t\tmessage: \"Branch protection:\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"strict — required reviews + passing checks\", value: \"strict\" },\n\t\t\t\t\t\t\t\t{ name: \"balanced — required reviews, flexible checks\", value: \"balanced\" },\n\t\t\t\t\t\t\t\t{ name: \"minimal — branch protection only\", value: \"minimal\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (openSource === undefined) {\n\t\t\t\t\t\tconst ans = await select({\n\t\t\t\t\t\t\tmessage: \"Open source?\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"Yes\", value: \"yes\" },\n\t\t\t\t\t\t\t\t{ name: \"No\", value: \"no\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t\topenSource = ans === \"yes\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif (usesExternalPackages === undefined) {\n\t\t\t\t\t\tconst ans = await select({\n\t\t\t\t\t\t\tmessage: \"Uses external APIs or services?\",\n\t\t\t\t\t\t\tchoices: [\n\t\t\t\t\t\t\t\t{ name: \"Yes\", value: \"yes\" },\n\t\t\t\t\t\t\t\t{ name: \"No\", value: \"no\" },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t\tusesExternalPackages = ans === \"yes\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif (skills.length === 0) {\n\t\t\t\t\t\tconst raw = await input({ message: \"Agent skills (comma-separated, optional):\" });\n\t\t\t\t\t\tskills = parseTopics(raw);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!type) {\n\t\t\t\t\t\tconsole.error(\"new: template type is required\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!name) {\n\t\t\t\t\t\tconsole.error(\"new: repo name is required\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst report = await runNew({\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: description || undefined,\n\t\t\t\t\t\thomepage,\n\t\t\t\t\t\tvaultProvider: (vaultProvider as \"doppler\" | \"1password\" | \"infisical\" | \"none\") ?? \"none\",\n\t\t\t\t\t\tvaultProject,\n\t\t\t\t\t\tvaultConfig,\n\t\t\t\t\t\tdeploymentProvider: (deploymentProvider as \"vercel\" | \"none\") ?? \"none\",\n\t\t\t\t\t\tagent: (agent as \"claude\" | \"none\") ?? \"claude\",\n\t\t\t\t\t\truntimeEnvironment: (runtimeEnvironment as \"node\" | \"browser\" | \"universal\" | \"none\") ?? \"node\",\n\t\t\t\t\t\tprotection: protection ?? \"strict\",\n\t\t\t\t\t\topenSource: openSource ?? true,\n\t\t\t\t\t\tusesExternalPackages: usesExternalPackages ?? true,\n\t\t\t\t\t\ttopics,\n\t\t\t\t\t\tskills,\n\t\t\t\t\t\tisTemplate,\n\t\t\t\t\t\torg: argv.org,\n\t\t\t\t\t\ttoken: adminToken,\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\tnoVerify: !argv.verify,\n\t\t\t\t\t\tcwd: argv.cwd,\n\t\t\t\t\t});\n\t\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof NewError) {\n\t\t\t\t\t\tconsole.error(`new: ${err.message}`);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"plugin create <slug> <vendor>\",\n\t\t\t\"Scaffold a new @theholocron/holocron-plugin-<slug> package\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.positional(\"slug\", { type: \"string\", demandOption: true, describe: \"Package slug (kebab-case)\" })\n\t\t\t\t\t.positional(\"vendor\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\tdescribe: \"Vendor display name (PascalCase)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"capability\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Capability key: source|ci|secrets|environments|issues|deployment|storage|auth|vault|dns|tooling|notifications|analytics|observability\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"token-env\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Holocron env var name (defaults to HOLOCRON_<VENDOR>_TOKEN)\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"vendor-env\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"Vendor-native env var name\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"base-url\", {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tdescribe: \"REST base URL\",\n\t\t\t\t\t})\n\t\t\t\t\t.option(\"verify\", {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\tdefault: true,\n\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\"Run post-scaffold pnpm install + typecheck + lint + test (default true; --no-verify skips)\",\n\t\t\t\t\t}),\n\t\t\tasync (argv) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst vendor = argv.vendor as string;\n\t\t\t\t\tconst { capability, vendorEnv, baseUrl } = await resolvePluginCreateInputs(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcapability: argv.capability as string | undefined,\n\t\t\t\t\t\t\tvendorEnv: argv.vendorEnv as string | undefined,\n\t\t\t\t\t\t\tbaseUrl: argv.baseUrl as string | undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tselectCapability: () =>\n\t\t\t\t\t\t\t\tselect({\n\t\t\t\t\t\t\t\t\tmessage: \"Capability:\",\n\t\t\t\t\t\t\t\t\tchoices: Object.keys(CARDINALITY).map((k) => ({ name: k, value: k })),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tinputVendorEnv: () =>\n\t\t\t\t\t\t\t\tinput({\n\t\t\t\t\t\t\t\t\tmessage: `Vendor-native env var for the ${vendor} token (e.g. MYVENDOR_API_KEY):`,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tinputBaseUrl: () =>\n\t\t\t\t\t\t\t\tinput({\n\t\t\t\t\t\t\t\t\tmessage: `REST base URL for the ${vendor} API (e.g. https://api.myvendor.com):`,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\t\tconst report = runPluginCreate({\n\t\t\t\t\t\tslug: argv.slug as string,\n\t\t\t\t\t\tvendorName: vendor,\n\t\t\t\t\t\tcapability,\n\t\t\t\t\t\tvendorEnv,\n\t\t\t\t\t\tbaseUrl,\n\t\t\t\t\t\t...(argv.tokenEnv ? { tokenEnv: argv.tokenEnv as string } : {}),\n\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t// Yargs: `--no-verify` flips `argv.verify` to false. We pass\n\t\t\t\t\t\t// the inverse to preserve the internal `noVerify` naming.\n\t\t\t\t\t\tnoVerify: !argv.verify,\n\t\t\t\t\t\tcwd: argv.cwd,\n\t\t\t\t\t});\n\t\t\t\t\tif (report.status === \"fail\") process.exitCode = 1;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof PluginCreateError) {\n\t\t\t\t\t\tconsole.error(`plugin create: ${err.message}`);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.command(\n\t\t\t\"upgrade\",\n\t\t\t\"Upgrade toolchain version pins across the repo\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"node <to>\",\n\t\t\t\t\t\t\"Scan the repo and update every Node.js version pin to a new major\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy\n\t\t\t\t\t\t\t\t.positional(\"to\", {\n\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\tdemandOption: true,\n\t\t\t\t\t\t\t\t\tdescribe: \"Target Node.js major version (e.g., 22)\",\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.option(\"from\", {\n\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\tdescribe:\n\t\t\t\t\t\t\t\t\t\t\"Current major version to replace. Auto-detected from .nvmrc / engines.node when omitted.\",\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\t// Read upgrade.node.extra from holocron.config.json if present.\n\t\t\t\t\t\t\t// We read the raw file directly rather than through loadConfig because\n\t\t\t\t\t\t\t// the upgrade config is not part of the plugin schema.\n\t\t\t\t\t\t\tlet extra: string[] = [];\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst raw = readFileSync(join(argv.cwd, \"holocron.config.json\"), \"utf8\");\n\t\t\t\t\t\t\t\tconst cfg = JSON.parse(raw) as Record<string, unknown>;\n\t\t\t\t\t\t\t\tconst upgradeNode = (cfg.upgrade as Record<string, unknown> | undefined)?.node as\n\t\t\t\t\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\t\t\tif (Array.isArray(upgradeNode?.extra)) {\n\t\t\t\t\t\t\t\t\textra = upgradeNode.extra as string[];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t/* no config or no upgrade section — fine */\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst report = await runUpgradeNode({\n\t\t\t\t\t\t\t\tto: argv.to as number,\n\t\t\t\t\t\t\t\t...(argv.from != null ? { from: argv.from as number } : {}),\n\t\t\t\t\t\t\t\tcwd: argv.cwd,\n\t\t\t\t\t\t\t\tdryRun: argv.dryRun,\n\t\t\t\t\t\t\t\textra,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (report.status === \"fail\") {\n\t\t\t\t\t\t\t\tif (report.message) console.error(`upgrade node: ${report.message}`);\n\t\t\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.demandCommand(1, \"Run `holocron upgrade --help` to see available upgrade subcommands.\"),\n\t\t\t() => {}\n\t\t)\n\t\t.command(\n\t\t\t\"auth <subcommand>\",\n\t\t\t\"Manage bootstrap credentials in the OS keyring\",\n\t\t\t(y) =>\n\t\t\t\ty\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"set <provider> [value]\",\n\t\t\t\t\t\t\"Verify + store a bootstrap token for a provider\",\n\t\t\t\t\t\t(yy) =>\n\t\t\t\t\t\t\tyy\n\t\t\t\t\t\t\t\t.positional(\"provider\", { type: \"string\", demandOption: true })\n\t\t\t\t\t\t\t\t.positional(\"value\", { type: \"string\" }),\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\tconst result = await runAuthSet({\n\t\t\t\t\t\t\t\tprovider: argv.provider as string,\n\t\t\t\t\t\t\t\t...(argv.value ? { positional: argv.value as string } : {}),\n\t\t\t\t\t\t\t\t...(argv.org ? { org: argv.org as string } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (result.status === \"fail\") process.exitCode = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"unset <provider>\",\n\t\t\t\t\t\t\"Remove a stored bootstrap token\",\n\t\t\t\t\t\t(yy) => yy.positional(\"provider\", { type: \"string\", demandOption: true }),\n\t\t\t\t\t\t(argv) => {\n\t\t\t\t\t\t\trunAuthUnset({ provider: argv.provider as string });\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"check <provider>\",\n\t\t\t\t\t\t\"Re-verify a stored bootstrap token\",\n\t\t\t\t\t\t(yy) => yy.positional(\"provider\", { type: \"string\", demandOption: true }),\n\t\t\t\t\t\tasync (argv) => {\n\t\t\t\t\t\t\tconst result = await runAuthCheck({\n\t\t\t\t\t\t\t\tprovider: argv.provider as string,\n\t\t\t\t\t\t\t\t...(argv.org ? { org: argv.org as string } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (result.status === \"fail\") process.exitCode = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.command(\n\t\t\t\t\t\t\"list\",\n\t\t\t\t\t\t\"List every provider with a stored bootstrap token\",\n\t\t\t\t\t\t() => {},\n\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\tawait runAuthList();\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.demandCommand(1, \"Run `holocron auth --help` to see available auth subcommands.\"),\n\t\t\t() => {}\n\t\t)\n\t\t.demandCommand(1, \"Run `holocron --help` to see available commands.\")\n\t\t.strict()\n\t\t.help()\n\t\t.parse();\n} catch (err) {\n\tcaptureException(err);\n\tif (!process.exitCode) process.exitCode = 1;\n}\n\nfinishCommand(!process.exitCode);\nendSession();\nconst notify = await updateCheckPromise;\nnotify?.();\nawait flush();\n\n/**\n * Parse `--scope` strings: `repo` | `env=NAME` | `org=NAME`.\n */\nfunction parseScope(\n\ts: string\n): { kind: \"repo\" } | { kind: \"environment\"; name: string } | { kind: \"organization\"; name: string } {\n\tif (s === \"repo\") return { kind: \"repo\" };\n\tif (s.startsWith(\"env=\")) return { kind: \"environment\", name: s.slice(\"env=\".length) };\n\tif (s.startsWith(\"org=\")) return { kind: \"organization\", name: s.slice(\"org=\".length) };\n\tthrow new Error(`invalid --scope \"${s}\" — expected \"repo\", \"env=<name>\", or \"org=<name>\"`);\n}\n"],"mappings":"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"}
|