@byrde/cursor 0.1.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/api/init.ts","../src/domain/config.ts","../src/domain/asset-manifest.ts","../src/infrastructure/file-installer.ts","../src/domain/managed-state.ts","../src/infrastructure/agent-template.ts","../src/infrastructure/managed-state-store.ts","../src/infrastructure/install-output-validator.ts","../src/infrastructure/doc-template-installer.ts","../src/infrastructure/project-config-store.ts","../src/infrastructure/github-mcp-store.ts","../src/infrastructure/init-questionnaire.ts","../src/infrastructure/github-auth.ts"],"sourcesContent":["import { readFileSync, realpathSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command, CommanderError } from \"commander\";\nimport { runInit } from \"./api/init.js\";\nimport { runInitQuestionnaire } from \"./infrastructure/init-questionnaire.js\";\nimport { loadProjectConfig } from \"./infrastructure/project-config-store.js\";\n\nconst packageRoot = path.resolve(\n path.dirname(fileURLToPath(import.meta.url)),\n \"..\",\n);\n\nexport interface InitOptions {\n cwd: string;\n skipMcp: boolean;\n force: boolean;\n verbose: boolean;\n}\n\nfunction readPackageVersion(): string {\n const pkgPath = path.join(packageRoot, \"package.json\");\n const raw = readFileSync(pkgPath, \"utf8\");\n const pkg = JSON.parse(raw) as { version: string };\n return pkg.version;\n}\n\nconst packageVersion = readPackageVersion();\n\nexport interface CliDependencies {\n readonly runInit?: typeof runInit;\n readonly runInitQuestionnaire?: typeof runInitQuestionnaire;\n}\n\nexport function createProgram(deps: CliDependencies = {}): Command {\n const runInitCommand = deps.runInit ?? runInit;\n const runQuestionnaire = deps.runInitQuestionnaire ?? runInitQuestionnaire;\n const program = new Command();\n program\n .name(\"byrde-cursor\")\n .description(\"Byrde Cursor workflow CLI and assets\")\n .version(packageVersion);\n\n program\n .command(\"init\")\n .description(\"Interactively configure and install the workflow into the target project\")\n .option(\n \"--cwd <path>\",\n \"target working directory\",\n process.cwd(),\n )\n .option(\"--skip-mcp\", \"skip GitHub MCP setup\", false)\n .option(\"--force\", \"overwrite managed files when needed\", false)\n .option(\"--verbose\", \"print extra diagnostics\", false)\n .action(async (options: InitOptions) => {\n const questionnaire = await runQuestionnaire({\n cwd: options.cwd,\n existingConfig: loadProjectConfig(options.cwd),\n });\n await runInitCommand(\n {\n cwd: options.cwd,\n skipMcp: options.skipMcp,\n verbose: options.verbose,\n force: options.force,\n packageVersion,\n projectConfig: questionnaire.projectConfig,\n overwriteProjectConfig: questionnaire.shouldWriteProjectConfig,\n githubMcpToken: questionnaire.githubMcpToken,\n },\n packageRoot,\n );\n });\n\n return program;\n}\n\nfunction isExecutedAsCli(): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n try {\n const modulePath = realpathSync(fileURLToPath(import.meta.url));\n const argvPath = realpathSync(path.resolve(entry));\n return modulePath === argvPath;\n } catch {\n return false;\n }\n}\n\n/** Exported for tests; prints a short message and exits (no stack traces). */\nexport function reportCliFailure(err: unknown): never {\n if (err instanceof CommanderError) {\n const code = err.exitCode ?? 1;\n if (code !== 0) {\n console.error(err.message);\n }\n process.exit(code);\n } else if (err instanceof Error) {\n console.error(err.message);\n process.exit(1);\n } else {\n console.error(String(err));\n process.exit(1);\n }\n}\n\nif (isExecutedAsCli()) {\n void createProgram().parseAsync(process.argv).catch(reportCliFailure);\n}\n","import path from \"node:path\";\nimport {\n DEFAULT_PROJECT_CONFIG,\n normalizeProjectConfig,\n type ProjectConfig,\n} from \"../domain/config.js\";\nimport { DEFAULT_MANIFEST } from \"../domain/asset-manifest.js\";\nimport {\n installAssets,\n type InstallReconcileResult,\n} from \"../infrastructure/file-installer.js\";\nimport { validateInstalledPackageOutputs } from \"../infrastructure/install-output-validator.js\";\nimport { scaffoldTemplateDocs } from \"../infrastructure/doc-template-installer.js\";\nimport {\n ensureProjectConfig,\n saveProjectConfig,\n} from \"../infrastructure/project-config-store.js\";\nimport { writeGitHubMcpServer } from \"../infrastructure/github-mcp-store.js\";\n\nexport type { InstallReconcileResult };\n\nexport interface InitParams {\n cwd: string;\n skipMcp: boolean;\n verbose: boolean;\n force: boolean;\n packageVersion: string;\n projectConfig?: ProjectConfig;\n overwriteProjectConfig?: boolean;\n githubMcpToken?: string;\n}\n\nexport async function runInit(\n params: InitParams,\n packageRoot: string,\n): Promise<InstallReconcileResult> {\n const targetDir = path.join(params.cwd, \".cursor\");\n const projectConfig = normalizeProjectConfig(\n params.projectConfig ?? DEFAULT_PROJECT_CONFIG,\n );\n const result = installAssets(DEFAULT_MANIFEST, packageRoot, targetDir, {\n force: params.force,\n packageVersion: params.packageVersion,\n projectConfig,\n });\n const warnings = [...result.warnings];\n\n validateInstalledPackageOutputs(params.cwd, result.manifestOutcomes);\n const configResult = params.overwriteProjectConfig\n ? saveProjectConfig(params.cwd, projectConfig)\n : ensureProjectConfig(params.cwd, projectConfig);\n const docsResult = scaffoldTemplateDocs(packageRoot, params.cwd, projectConfig);\n const shouldConfigureGitHubMcp = projectConfig.backlog.provider === \"github-issues\";\n let mcpLabel: string | undefined;\n if (shouldConfigureGitHubMcp && !params.skipMcp) {\n const token = params.githubMcpToken;\n if (!token) {\n warnings.push(\n \"GitHub backlog selected, but no GitHub token was provided for Cursor MCP setup. Re-run `init` or edit `.cursor/mcp.json` manually.\",\n );\n } else {\n const mcpResult = writeGitHubMcpServer({\n cwd: params.cwd,\n serverName: projectConfig.backlog[\"github-issues\"]?.mcpServerName ?? \"github\",\n token,\n });\n mcpLabel = `${mcpResult.created ? \"GitHub MCP config created\" : \"GitHub MCP config updated\"}: ${mcpResult.path}`;\n }\n } else if (shouldConfigureGitHubMcp) {\n mcpLabel = \"Skipped GitHub MCP setup (--skip-mcp).\";\n } else {\n mcpLabel = \"No GitHub MCP setup needed for the selected backlog.\";\n }\n\n console.log(\"Project scaffolded.\");\n\n for (const w of warnings) {\n console.warn(w);\n }\n\n if (params.verbose) {\n const configLabel = params.overwriteProjectConfig\n ? (configResult.created ? \"Project config created\" : \"Project config updated\")\n : (configResult.created ? \"Project config created\" : \"Project config preserved\");\n\n console.log(`${configLabel}: ${configResult.path}`);\n console.log(\n `Docs scaffolded: ${docsResult.created.length} created, ${docsResult.skipped.length} preserved.`,\n );\n console.log(mcpLabel);\n if (configResult.created) {\n console.log(`config created: ${configResult.path}`);\n } else {\n console.log(`config preserved: ${configResult.path}`);\n }\n for (const created of docsResult.created) {\n console.log(`doc created: ${created}`);\n }\n for (const skipped of docsResult.skipped) {\n console.log(`doc preserved: ${skipped}`);\n }\n for (const o of result.manifestOutcomes) {\n const dest = `${o.target} -> ${o.absolutePath}`;\n if (o.kind === \"skipped\") {\n console.log(`skipped (${o.reason}): ${dest}`);\n } else {\n console.log(`${o.kind}: ${dest}`);\n }\n }\n for (const s of result.staleOutcomes) {\n if (s.kind === \"stale_removed\") {\n console.log(`stale removed: ${s.target} (${s.absolutePath})`);\n } else if (s.kind === \"stale_record_dropped\") {\n console.log(`stale record dropped (file missing): ${s.target}`);\n } else {\n console.log(\n `stale kept (${s.reason}): ${s.target} (${s.absolutePath})`,\n );\n }\n }\n }\n\n return {\n ...result,\n warnings,\n };\n}\n","export const PROJECT_CONFIG_FILENAME = \"workflow.json\";\n\nexport type BacklogProviderKind = \"file\" | \"github-issues\";\nexport type WorkflowDefaultMode = \"required\" | \"optional\";\n\n/** Subagent roles with configurable Cursor model ids (see `assets/agents/*.md`). */\nexport type WorkflowModelRole =\n | \"planner\"\n | \"architect\"\n | \"developer\"\n | \"tester\";\n\nexport interface WorkflowModels {\n readonly planner: string;\n readonly architect: string;\n readonly developer: string;\n readonly tester: string;\n}\n\n/**\n * GitHub backlog mode uses provider key `github-issues` (legacy name) and is\n * GitHub Project v2–first: issues are ordered by the Project **Priority** field,\n * workflow state by the Project **Status** field, and **milestones** represent epics.\n */\nexport interface GitHubIssuesBacklogConfig {\n readonly repository: string;\n /** GitHub Project (v2) number as shown on the repository Projects tab. */\n readonly projectNumber: number;\n /**\n * Organization or user login that owns the project. When omitted, tooling\n * assumes the repository owner (the segment before `/` in `repository`).\n */\n readonly projectOwner?: string;\n /** Project field name used for backlog ordering (default `Priority`). */\n readonly priorityField: string;\n /** Project field name used for workflow status (default `Status`). */\n readonly statusField: string;\n /**\n * Optional issue label filter (secondary to Project membership). Omit or leave\n * empty when everything is driven from the Project.\n */\n readonly label?: string;\n readonly mcpServerName: string;\n}\n\nexport interface ProjectConfig {\n readonly backlog: {\n readonly provider: BacklogProviderKind;\n readonly file?: {\n readonly path: string;\n };\n readonly \"github-issues\"?: GitHubIssuesBacklogConfig;\n };\n readonly workflow: {\n readonly defaults: {\n readonly architectReview: WorkflowDefaultMode;\n readonly testing: WorkflowDefaultMode;\n };\n readonly models: WorkflowModels;\n };\n}\n\n/** Defaults match pre-template agent frontmatter in `assets/agents/`. */\nexport function createDefaultWorkflowModels(): WorkflowModels {\n return {\n planner: \"gpt-5.4-high\",\n architect: \"gpt-5.4-high\",\n developer: \"composer-2-fast\",\n tester: \"composer-2-fast\",\n };\n}\n\nexport function createDefaultProjectConfig(): ProjectConfig {\n return {\n backlog: {\n provider: \"file\",\n file: {\n path: \"docs/backlog.md\",\n },\n },\n workflow: {\n defaults: {\n architectReview: \"required\",\n testing: \"required\",\n },\n models: createDefaultWorkflowModels(),\n },\n };\n}\n\nexport const DEFAULT_PROJECT_CONFIG = createDefaultProjectConfig();\n\nfunction isNonEmptyString(v: unknown): v is string {\n return typeof v === \"string\" && v.trim().length > 0;\n}\n\nfunction normalizeBacklog(\n raw: unknown,\n base: ProjectConfig[\"backlog\"],\n): ProjectConfig[\"backlog\"] {\n if (!raw || typeof raw !== \"object\") {\n return base;\n }\n const b = raw as Record<string, unknown>;\n const provider =\n b.provider === \"github-issues\" || b.provider === \"file\"\n ? b.provider\n : base.provider;\n\n if (provider === \"file\") {\n const fileRaw = b.file;\n const pathFrom =\n fileRaw && typeof fileRaw === \"object\" &&\n isNonEmptyString((fileRaw as Record<string, unknown>).path)\n ? String((fileRaw as Record<string, unknown>).path).trim()\n : base.file!.path;\n return { provider: \"file\", file: { path: pathFrom } };\n }\n\n const ghRaw = b[\"github-issues\"];\n const githubOptionalDefaults = {\n priorityField: \"Priority\",\n statusField: \"Status\",\n mcpServerName: \"github\",\n } as const;\n\n function parsePositiveInt(v: unknown): number | undefined {\n if (typeof v === \"number\" && Number.isFinite(v) && v > 0) {\n return Math.trunc(v);\n }\n if (isNonEmptyString(v)) {\n const n = Number.parseInt(String(v).trim(), 10);\n if (Number.isFinite(n) && n > 0) {\n return n;\n }\n }\n return undefined;\n }\n\n /**\n * GitHub mode requires an explicit repository and project number. Missing or\n * invalid nested config falls back to the default file backlog so we never\n * invent a plausible-looking `owner/repo` + `projectNumber: 1` target.\n */\n if (ghRaw && typeof ghRaw === \"object\") {\n const g = ghRaw as Record<string, unknown>;\n const repository = isNonEmptyString(g.repository)\n ? g.repository.trim()\n : undefined;\n const projectNumber = parsePositiveInt(g.projectNumber);\n\n if (repository !== undefined && projectNumber !== undefined) {\n const priorityField = isNonEmptyString(g.priorityField)\n ? g.priorityField.trim()\n : githubOptionalDefaults.priorityField;\n const statusField = isNonEmptyString(g.statusField)\n ? g.statusField.trim()\n : githubOptionalDefaults.statusField;\n const labelRaw = g.label;\n const label =\n isNonEmptyString(labelRaw) ? labelRaw.trim() : undefined;\n\n return {\n provider: \"github-issues\",\n \"github-issues\": {\n repository,\n projectNumber,\n projectOwner: isNonEmptyString(g.projectOwner)\n ? g.projectOwner.trim()\n : undefined,\n priorityField,\n statusField,\n ...(label !== undefined ? { label } : {}),\n mcpServerName: isNonEmptyString(g.mcpServerName)\n ? g.mcpServerName.trim()\n : githubOptionalDefaults.mcpServerName,\n },\n };\n }\n }\n\n return base;\n}\n\nfunction normalizeWorkflow(\n raw: unknown,\n base: ProjectConfig[\"workflow\"],\n): ProjectConfig[\"workflow\"] {\n const models = { ...base.models };\n let architectReview = base.defaults.architectReview;\n let testing = base.defaults.testing;\n\n if (raw && typeof raw === \"object\") {\n const w = raw as Record<string, unknown>;\n const d = w.defaults;\n if (d && typeof d === \"object\") {\n const def = d as Record<string, unknown>;\n if (def.architectReview === \"required\" || def.architectReview === \"optional\") {\n architectReview = def.architectReview;\n }\n if (def.testing === \"required\" || def.testing === \"optional\") {\n testing = def.testing;\n }\n }\n const m = w.models;\n if (m && typeof m === \"object\") {\n const mo = m as Record<string, unknown>;\n const pick = (key: keyof WorkflowModels): string => {\n const v = mo[key];\n return isNonEmptyString(v) ? v.trim() : base.models[key];\n };\n models.planner = pick(\"planner\");\n models.architect = pick(\"architect\");\n models.developer = pick(\"developer\");\n models.tester = pick(\"tester\");\n }\n }\n\n return {\n defaults: { architectReview, testing },\n models,\n };\n}\n\n/**\n * Merges parsed JSON with defaults so older configs without `workflow.models`\n * (or partial fields) remain valid.\n */\nexport function normalizeProjectConfig(raw: unknown): ProjectConfig {\n const base = createDefaultProjectConfig();\n if (!raw || typeof raw !== \"object\") {\n return base;\n }\n\n const o = raw as Record<string, unknown>;\n return {\n backlog: normalizeBacklog(o.backlog, base.backlog),\n workflow: normalizeWorkflow(o.workflow, base.workflow),\n };\n}\n","import type { WorkflowModelRole } from \"./config.js\";\n\nexport interface AssetEntry {\n readonly source: string;\n readonly target: string;\n /**\n * When set, `source` is a UTF-8 template with `{{MODEL}}`; install/sync\n * substitutes the value from `workflow.models.<role>`.\n */\n readonly renderAgent?: WorkflowModelRole;\n}\n\n/** Maps each shipped file under `assets/` to its path under `<cwd>/.cursor/`. */\nexport const DEFAULT_MANIFEST = [\n {\n source: \"assets/agents/architect.md\",\n target: \"agents/architect.md\",\n renderAgent: \"architect\",\n },\n {\n source: \"assets/agents/developer.md\",\n target: \"agents/developer.md\",\n renderAgent: \"developer\",\n },\n {\n source: \"assets/agents/planner.md\",\n target: \"agents/planner.md\",\n renderAgent: \"planner\",\n },\n {\n source: \"assets/agents/tester.md\",\n target: \"agents/tester.md\",\n renderAgent: \"tester\",\n },\n { source: \"assets/rules/global.mdc\", target: \"rules/global.mdc\" },\n { source: \"assets/rules/init.mdc\", target: \"rules/init.mdc\" },\n { source: \"assets/templates/backlog.md\", target: \"templates/backlog.md\" },\n { source: \"assets/templates/design.md\", target: \"templates/design.md\" },\n { source: \"assets/templates/overview.md\", target: \"templates/overview.md\" },\n {\n source: \"assets/templates/testability/README.md\",\n target: \"templates/testability/README.md\",\n },\n] as const satisfies readonly AssetEntry[];\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport path from \"node:path\";\nimport type { AssetEntry } from \"../domain/asset-manifest.js\";\nimport {\n createDefaultProjectConfig,\n normalizeProjectConfig,\n type ProjectConfig,\n} from \"../domain/config.js\";\nimport {\n hashFileContents,\n type ManagedFileRecord,\n type ManagedState,\n} from \"../domain/managed-state.js\";\nimport { renderAgentTemplate } from \"./agent-template.js\";\nimport {\n loadManagedState,\n saveManagedStateAtomic,\n} from \"./managed-state-store.js\";\n\nexport interface InstallOptions {\n readonly force: boolean;\n readonly packageVersion: string;\n /** Used to render agent templates (`{{MODEL}}`); defaults match shipped presets. */\n readonly projectConfig?: ProjectConfig;\n}\n\nfunction resolveManifestSourceBytes(\n entry: AssetEntry,\n packageRoot: string,\n projectConfig: ProjectConfig,\n): Buffer {\n const absSource = path.join(packageRoot, entry.source);\n const raw = readFileSync(absSource);\n if (!entry.renderAgent) {\n return raw;\n }\n const utf8 = raw.toString(\"utf8\");\n const model = projectConfig.workflow.models[entry.renderAgent];\n const rendered = renderAgentTemplate(utf8, model);\n return Buffer.from(rendered, \"utf8\");\n}\n\nexport type ManifestFileOutcome =\n | {\n kind: \"installed\";\n target: string;\n source: string;\n absolutePath: string;\n hash: string;\n }\n | {\n kind: \"updated\";\n target: string;\n source: string;\n absolutePath: string;\n hash: string;\n forced: boolean;\n }\n | {\n kind: \"adopted\";\n target: string;\n source: string;\n absolutePath: string;\n hash: string;\n }\n | {\n kind: \"recreated\";\n target: string;\n source: string;\n absolutePath: string;\n hash: string;\n }\n | {\n kind: \"skipped\";\n target: string;\n source: string;\n absolutePath: string;\n reason: \"tracked_hash_mismatch\" | \"untracked_bytes_mismatch\";\n forced: false;\n };\n\nexport type StaleOutcome =\n | { kind: \"stale_removed\"; target: string; absolutePath: string }\n | { kind: \"stale_record_dropped\"; target: string }\n | {\n kind: \"stale_kept_warn\";\n target: string;\n absolutePath: string;\n reason: \"content_mismatch\";\n };\n\nexport interface InstallReconcileResult {\n readonly manifestOutcomes: readonly ManifestFileOutcome[];\n readonly staleOutcomes: readonly StaleOutcome[];\n readonly warnings: readonly string[];\n}\n\nfunction nowRecord(\n hash: string,\n packageVersion: string,\n): ManagedFileRecord {\n return {\n hash,\n version: packageVersion,\n installedAt: new Date().toISOString(),\n };\n}\n\n/**\n * Reconciles manifest entries against disk and `.cursor/.managed.json`:\n * copies, adopts, skips conflicts, and cleans stale managed files.\n */\nexport function installAssets(\n manifest: readonly AssetEntry[],\n packageRoot: string,\n targetDir: string,\n options: InstallOptions,\n): InstallReconcileResult {\n const resolvedRoot = path.resolve(packageRoot);\n const resolvedTargetBase = path.resolve(targetDir);\n const projectConfig = normalizeProjectConfig(\n options.projectConfig ?? createDefaultProjectConfig(),\n );\n const initialState = loadManagedState(resolvedTargetBase);\n const workingFiles: Record<string, ManagedFileRecord> = {\n ...(initialState?.files ?? {}),\n };\n\n const manifestOutcomes: ManifestFileOutcome[] = [];\n const staleOutcomes: StaleOutcome[] = [];\n const warnings: string[] = [];\n\n const manifestTargets = new Set(manifest.map((e) => e.target));\n\n for (const entry of manifest) {\n const absSource = path.join(resolvedRoot, entry.source);\n const absTarget = path.join(resolvedTargetBase, entry.target);\n\n statSync(absSource);\n const sourceBytes = resolveManifestSourceBytes(\n entry,\n resolvedRoot,\n projectConfig,\n );\n const sourceHash = hashFileContents(sourceBytes);\n\n const record = workingFiles[entry.target];\n\n if (!existsSync(absTarget)) {\n mkdirSync(path.dirname(absTarget), { recursive: true });\n writeFileSync(absTarget, sourceBytes);\n const writtenHash = hashFileContents(readFileSync(absTarget));\n workingFiles[entry.target] = nowRecord(\n writtenHash,\n options.packageVersion,\n );\n\n if (record) {\n manifestOutcomes.push({\n kind: \"recreated\",\n target: entry.target,\n source: entry.source,\n absolutePath: absTarget,\n hash: writtenHash,\n });\n } else {\n manifestOutcomes.push({\n kind: \"installed\",\n target: entry.target,\n source: entry.source,\n absolutePath: absTarget,\n hash: writtenHash,\n });\n }\n continue;\n }\n\n const diskBytes = readFileSync(absTarget);\n const diskHash = hashFileContents(diskBytes);\n\n if (record) {\n if (diskHash === record.hash) {\n writeFileSync(absTarget, sourceBytes);\n const newHash = hashFileContents(readFileSync(absTarget));\n workingFiles[entry.target] = nowRecord(newHash, options.packageVersion);\n manifestOutcomes.push({\n kind: \"updated\",\n target: entry.target,\n source: entry.source,\n absolutePath: absTarget,\n hash: newHash,\n forced: false,\n });\n } else if (!options.force) {\n const msg = `Skipped managed file (modified on disk): ${entry.target}`;\n warnings.push(msg);\n if (entry.renderAgent) {\n const desiredHash = sourceHash;\n if (desiredHash !== record.hash) {\n warnings.push(\n `Model or template update not applied to ${entry.target} because the file was modified locally. ` +\n `Update the \\`model:\\` line yourself, or re-run init with --force to replace managed files.`,\n );\n }\n }\n manifestOutcomes.push({\n kind: \"skipped\",\n target: entry.target,\n source: entry.source,\n absolutePath: absTarget,\n reason: \"tracked_hash_mismatch\",\n forced: false,\n });\n } else {\n writeFileSync(absTarget, sourceBytes);\n const newHash = hashFileContents(readFileSync(absTarget));\n workingFiles[entry.target] = nowRecord(newHash, options.packageVersion);\n warnings.push(\n `Overwrote modified managed file (--force): ${entry.target}`,\n );\n manifestOutcomes.push({\n kind: \"updated\",\n target: entry.target,\n source: entry.source,\n absolutePath: absTarget,\n hash: newHash,\n forced: true,\n });\n }\n continue;\n }\n\n if (diskHash === sourceHash) {\n workingFiles[entry.target] = nowRecord(diskHash, options.packageVersion);\n manifestOutcomes.push({\n kind: \"adopted\",\n target: entry.target,\n source: entry.source,\n absolutePath: absTarget,\n hash: diskHash,\n });\n continue;\n }\n\n if (!options.force) {\n const msg = `Skipped untracked file (differs from package): ${entry.target}`;\n warnings.push(msg);\n manifestOutcomes.push({\n kind: \"skipped\",\n target: entry.target,\n source: entry.source,\n absolutePath: absTarget,\n reason: \"untracked_bytes_mismatch\",\n forced: false,\n });\n continue;\n }\n\n writeFileSync(absTarget, sourceBytes);\n const newHash = hashFileContents(readFileSync(absTarget));\n workingFiles[entry.target] = nowRecord(newHash, options.packageVersion);\n warnings.push(\n `Overwrote untracked file that differed from package (--force): ${entry.target}`,\n );\n manifestOutcomes.push({\n kind: \"updated\",\n target: entry.target,\n source: entry.source,\n absolutePath: absTarget,\n hash: newHash,\n forced: true,\n });\n }\n\n const initialKeys = Object.keys(initialState?.files ?? {});\n for (const target of initialKeys) {\n if (manifestTargets.has(target)) {\n continue;\n }\n\n const record = workingFiles[target];\n if (!record) {\n continue;\n }\n\n const absStale = path.join(resolvedTargetBase, target);\n\n if (!existsSync(absStale)) {\n delete workingFiles[target];\n staleOutcomes.push({ kind: \"stale_record_dropped\", target });\n continue;\n }\n\n const diskHash = hashFileContents(readFileSync(absStale));\n if (diskHash === record.hash) {\n unlinkSync(absStale);\n delete workingFiles[target];\n staleOutcomes.push({\n kind: \"stale_removed\",\n target,\n absolutePath: absStale,\n });\n } else {\n const msg = `Stale managed file not in manifest; keeping local changes: ${target}`;\n warnings.push(msg);\n staleOutcomes.push({\n kind: \"stale_kept_warn\",\n target,\n absolutePath: absStale,\n reason: \"content_mismatch\",\n });\n }\n }\n\n const finalState: ManagedState = {\n version: options.packageVersion,\n installedAt: new Date().toISOString(),\n files: workingFiles,\n };\n saveManagedStateAtomic(resolvedTargetBase, finalState);\n\n return {\n manifestOutcomes,\n staleOutcomes,\n warnings,\n };\n}\n","import { createHash } from \"node:crypto\";\n\n/** One tracked file under `.cursor/` as persisted in `.managed.json`. */\nexport interface ManagedFileRecord {\n /** Content hash, e.g. `sha256:hex…`. */\n readonly hash: string;\n /** Package version that last wrote this record. */\n readonly version: string;\n /** When this record was last written (ISO 8601). */\n readonly installedAt?: string;\n}\n\n/** Top-level managed state persisted at `.cursor/.managed.json`. */\nexport interface ManagedState {\n /** Package version from the last successful install run. */\n readonly version: string;\n readonly installedAt?: string;\n readonly files: Record<string, ManagedFileRecord>;\n}\n\nexport function hashFileContents(data: Buffer): string {\n const hex = createHash(\"sha256\").update(data).digest(\"hex\");\n return `sha256:${hex}`;\n}\n","/** Placeholder in shipped agent templates; replaced at init/sync time. */\nexport const AGENT_MODEL_PLACEHOLDER = \"{{MODEL}}\";\n\nexport function renderAgentTemplate(\n templateUtf8: string,\n model: string,\n): string {\n if (!templateUtf8.includes(AGENT_MODEL_PLACEHOLDER)) {\n throw new Error(\n `Agent template is missing ${AGENT_MODEL_PLACEHOLDER} placeholder`,\n );\n }\n return templateUtf8.replaceAll(AGENT_MODEL_PLACEHOLDER, model);\n}\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport path from \"node:path\";\nimport type { ManagedState } from \"../domain/managed-state.js\";\n\nexport const MANAGED_STATE_FILENAME = \".managed.json\";\n\nfunction managedStatePath(cursorDir: string): string {\n return path.join(cursorDir, MANAGED_STATE_FILENAME);\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseManagedState(raw: string): ManagedState {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw) as unknown;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(\n `Invalid managed state JSON in ${MANAGED_STATE_FILENAME}: ${msg}`,\n );\n }\n\n if (!isPlainRecord(parsed)) {\n throw new Error(\n `Invalid managed state: root must be a JSON object (${MANAGED_STATE_FILENAME})`,\n );\n }\n\n const version = parsed.version;\n if (typeof version !== \"string\" || version.length === 0) {\n throw new Error(\n `Invalid managed state: missing or invalid \"version\" string (${MANAGED_STATE_FILENAME})`,\n );\n }\n\n const filesRaw = parsed.files;\n if (!isPlainRecord(filesRaw)) {\n throw new Error(\n `Invalid managed state: \"files\" must be an object (${MANAGED_STATE_FILENAME})`,\n );\n }\n\n const files: Record<string, ManagedState[\"files\"][string]> = {};\n for (const [target, rec] of Object.entries(filesRaw)) {\n if (!isPlainRecord(rec)) {\n throw new Error(\n `Invalid managed state: files[\"${target}\"] must be an object (${MANAGED_STATE_FILENAME})`,\n );\n }\n const hash = rec.hash;\n const ver = rec.version;\n if (typeof hash !== \"string\" || hash.length === 0) {\n throw new Error(\n `Invalid managed state: files[\"${target}\"].hash must be a non-empty string (${MANAGED_STATE_FILENAME})`,\n );\n }\n if (typeof ver !== \"string\" || ver.length === 0) {\n throw new Error(\n `Invalid managed state: files[\"${target}\"].version must be a non-empty string (${MANAGED_STATE_FILENAME})`,\n );\n }\n const installedAt = rec.installedAt;\n files[target] = {\n hash,\n version: ver,\n ...(typeof installedAt === \"string\" ? { installedAt } : {}),\n };\n }\n\n const installedAt = parsed.installedAt;\n return {\n version,\n ...(typeof installedAt === \"string\" ? { installedAt } : {}),\n files,\n };\n}\n\n/**\n * Loads `.cursor/.managed.json`. Returns `null` if the file is absent.\n * Invalid or corrupt JSON fails fast with a clear error; no writes are performed.\n */\nexport function loadManagedState(cursorDir: string): ManagedState | null {\n const p = managedStatePath(cursorDir);\n if (!existsSync(p)) {\n return null;\n }\n const raw = readFileSync(p, \"utf8\");\n return parseManagedState(raw);\n}\n\n/**\n * Writes managed state atomically (temp file + rename) under `cursorDir`.\n */\nexport function saveManagedStateAtomic(\n cursorDir: string,\n state: ManagedState,\n): void {\n mkdirSync(cursorDir, { recursive: true });\n const finalPath = managedStatePath(cursorDir);\n const tmpPath = `${finalPath}.${process.pid}.tmp`;\n const payload = `${JSON.stringify(state, null, 2)}\\n`;\n try {\n writeFileSync(tmpPath, payload, \"utf8\");\n renameSync(tmpPath, finalPath);\n } catch (e) {\n try {\n if (existsSync(tmpPath)) unlinkSync(tmpPath);\n } catch {\n /* ignore */\n }\n throw e;\n }\n}\n","import { existsSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { ManifestFileOutcome } from \"./file-installer.js\";\n\nconst PACKAGE_OWNED_KINDS = new Set<\n ManifestFileOutcome[\"kind\"]\n>([\"installed\", \"updated\", \"adopted\", \"recreated\"]);\n\nfunction displayPath(cwd: string, absolutePath: string): string {\n const rel = path.relative(cwd, absolutePath);\n return rel.split(path.sep).join(\"/\");\n}\n\n/** Returns a human-readable failure reason, or `null` if the path is valid. */\nfunction failureReason(absolutePath: string): string | null {\n if (!existsSync(absolutePath)) {\n return \"missing\";\n }\n const st = statSync(absolutePath);\n if (!st.isFile()) {\n return \"not a regular file\";\n }\n if (st.size === 0) {\n return \"empty file\";\n }\n return null;\n}\n\n/**\n * Confirms every manifest outcome that should have produced a package-owned file\n * under `<cwd>/.cursor/` exists as a non-empty regular file.\n * Does not validate `skipped` outcomes (conflict handling).\n */\nexport function validateInstalledPackageOutputs(\n cwd: string,\n outcomes: readonly ManifestFileOutcome[],\n): void {\n const resolvedCwd = path.resolve(cwd);\n const failures: string[] = [];\n\n for (const o of outcomes) {\n if (!PACKAGE_OWNED_KINDS.has(o.kind)) {\n continue;\n }\n const reason = failureReason(o.absolutePath);\n if (reason !== null) {\n failures.push(`${displayPath(resolvedCwd, o.absolutePath)} (${reason})`);\n }\n }\n\n if (failures.length > 0) {\n const msg = `Post-install validation failed:\\n${failures.map((f) => ` - ${f}`).join(\"\\n\")}`;\n throw new Error(msg);\n }\n}\n","import { copyFileSync, existsSync, mkdirSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { ProjectConfig } from \"../domain/config.js\";\n\n/** Package `assets/templates/<source>` → `<cwd>/docs/<target>` (explicit list; no recursive copy). */\nexport const BASE_TEMPLATE_DOC_ENTRIES: ReadonlyArray<{\n source: string;\n target: string;\n}> = [\n { source: \"overview.md\", target: \"docs/overview.md\" },\n { source: \"design.md\", target: \"docs/design.md\" },\n { source: \"testability/README.md\", target: \"docs/testability/README.md\" },\n];\n\nexport interface TemplateDocsResult {\n readonly created: readonly string[];\n readonly skipped: readonly string[];\n}\n\nexport function scaffoldTemplateDocs(\n packageRoot: string,\n cwd: string,\n config?: ProjectConfig,\n): TemplateDocsResult {\n const created: string[] = [];\n const skipped: string[] = [];\n const entries = resolveTemplateEntries(config);\n\n mkdirSync(path.join(cwd, \"docs\"), { recursive: true });\n\n for (const entry of entries) {\n const source = path.join(packageRoot, \"assets\", \"templates\", entry.source);\n const target = path.join(cwd, entry.target);\n\n statSync(source);\n mkdirSync(path.dirname(target), { recursive: true });\n\n if (existsSync(target)) {\n skipped.push(target);\n continue;\n }\n\n copyFileSync(source, target);\n created.push(target);\n }\n\n return {\n created,\n skipped,\n };\n}\n\nfunction resolveTemplateEntries(\n config?: ProjectConfig,\n): ReadonlyArray<{ source: string; target: string }> {\n const entries = [...BASE_TEMPLATE_DOC_ENTRIES];\n\n if (!config || config.backlog.provider === \"file\") {\n entries.splice(2, 0, {\n source: \"backlog.md\",\n target: config?.backlog.file?.path ?? \"docs/backlog.md\",\n });\n }\n\n return entries;\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n DEFAULT_PROJECT_CONFIG,\n normalizeProjectConfig,\n PROJECT_CONFIG_FILENAME,\n type ProjectConfig,\n} from \"../domain/config.js\";\n\nconst LEGACY_PROJECT_CONFIG_FILENAME = \"byrde.json\";\n\nexport interface ProjectConfigWriteResult {\n readonly path: string;\n readonly created: boolean;\n}\n\nexport function projectConfigPath(cwd: string): string {\n return path.join(cwd, \".cursor\", PROJECT_CONFIG_FILENAME);\n}\n\nexport function loadProjectConfig(cwd: string): ProjectConfig | undefined {\n const configPath = projectConfigPath(cwd);\n const legacyPath = path.join(cwd, \".cursor\", LEGACY_PROJECT_CONFIG_FILENAME);\n\n if (existsSync(configPath)) {\n return normalizeProjectConfig(\n JSON.parse(readFileSync(configPath, \"utf8\")),\n );\n }\n\n if (existsSync(legacyPath)) {\n return normalizeProjectConfig(\n JSON.parse(readFileSync(legacyPath, \"utf8\")),\n );\n }\n\n return undefined;\n}\n\nexport function ensureProjectConfig(\n cwd: string,\n config: ProjectConfig = DEFAULT_PROJECT_CONFIG,\n): ProjectConfigWriteResult {\n const configPath = projectConfigPath(cwd);\n if (existsSync(configPath)) {\n return {\n path: configPath,\n created: false,\n };\n }\n\n mkdirSync(path.dirname(configPath), { recursive: true });\n const normalized = normalizeProjectConfig(config);\n writeFileSync(configPath, `${JSON.stringify(normalized, null, 2)}\\n`, \"utf8\");\n return {\n path: configPath,\n created: true,\n };\n}\n\nexport function saveProjectConfig(\n cwd: string,\n config: ProjectConfig = DEFAULT_PROJECT_CONFIG,\n): ProjectConfigWriteResult {\n const configPath = projectConfigPath(cwd);\n const created = !existsSync(configPath);\n mkdirSync(path.dirname(configPath), { recursive: true });\n const normalized = normalizeProjectConfig(config);\n writeFileSync(configPath, `${JSON.stringify(normalized, null, 2)}\\n`, \"utf8\");\n return {\n path: configPath,\n created,\n };\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nconst MANAGED_GITHUB_SERVER_PREFIX = \"cursor-workflow:\";\n\nexport interface McpServerEntry {\n readonly command: string;\n readonly args: readonly string[];\n readonly env?: Readonly<Record<string, string>>;\n}\n\nexport interface CursorMcpConfig {\n readonly mcpServers: Record<string, McpServerEntry>;\n}\n\nexport interface GitHubMcpWriteParams {\n readonly cwd: string;\n readonly serverName: string;\n readonly token: string;\n}\n\nexport interface GitHubMcpWriteResult {\n readonly path: string;\n readonly created: boolean;\n readonly serverKey: string;\n}\n\nfunction mcpConfigPath(cwd: string): string {\n return path.join(cwd, \".cursor\", \"mcp.json\");\n}\n\nfunction readExistingConfig(cwd: string): CursorMcpConfig {\n const filePath = mcpConfigPath(cwd);\n if (!existsSync(filePath)) {\n return { mcpServers: {} };\n }\n\n const raw = JSON.parse(readFileSync(filePath, \"utf8\")) as {\n mcpServers?: Record<string, McpServerEntry>;\n };\n return {\n mcpServers: raw.mcpServers ?? {},\n };\n}\n\nfunction managedServerKey(serverName: string): string {\n return `${MANAGED_GITHUB_SERVER_PREFIX}${serverName}`;\n}\n\nexport function writeGitHubMcpServer(\n params: GitHubMcpWriteParams,\n): GitHubMcpWriteResult {\n const filePath = mcpConfigPath(params.cwd);\n const created = !existsSync(filePath);\n const existing = readExistingConfig(params.cwd);\n const serverKey = managedServerKey(params.serverName);\n\n const nextServers: Record<string, McpServerEntry> = {};\n\n for (const [key, value] of Object.entries(existing.mcpServers)) {\n if (!key.startsWith(MANAGED_GITHUB_SERVER_PREFIX)) {\n nextServers[key] = value;\n }\n }\n\n nextServers[serverKey] = {\n command: \"npx\",\n args: [\"-y\", \"@modelcontextprotocol/server-github\"],\n env: {\n GITHUB_PERSONAL_ACCESS_TOKEN: params.token,\n },\n };\n\n mkdirSync(path.dirname(filePath), { recursive: true });\n writeFileSync(\n filePath,\n `${JSON.stringify({ mcpServers: nextServers }, null, 2)}\\n`,\n \"utf8\",\n );\n\n return {\n path: filePath,\n created,\n serverKey,\n };\n}\n","import type { Status } from \"@inquirer/core\";\nimport { confirm, input, password, select } from \"@inquirer/prompts\";\nimport { styleText } from \"node:util\";\nimport {\n createDefaultProjectConfig,\n normalizeProjectConfig,\n type BacklogProviderKind,\n type ProjectConfig,\n type WorkflowDefaultMode,\n type WorkflowModels,\n} from \"../domain/config.js\";\nimport {\n listGitHubAccounts,\n resolveGitHubTokenForAccount,\n type GitHubAccount,\n} from \"./github-auth.js\";\n\nconst BOLD = \"\\x1b[1m\";\nconst DIM = \"\\x1b[2m\";\nconst RESET = \"\\x1b[0m\";\n\nexport type ClientTarget = \"cursor\";\n\nexport interface QuestionnairePrompts {\n readonly select: typeof select;\n readonly input: typeof input;\n readonly confirm: typeof confirm;\n readonly password: typeof password;\n}\n\nexport interface InitQuestionnaireOptions {\n readonly cwd: string;\n readonly existingConfig?: ProjectConfig;\n}\n\nexport interface InitQuestionnaireResult {\n readonly projectConfig: ProjectConfig;\n readonly shouldWriteProjectConfig: boolean;\n readonly githubMcpToken?: string;\n}\n\nconst DEFAULT_PROMPTS: QuestionnairePrompts = {\n select,\n input,\n confirm,\n password,\n};\n\nexport async function runInitQuestionnaire(\n options: InitQuestionnaireOptions,\n prompts: QuestionnairePrompts = DEFAULT_PROMPTS,\n): Promise<InitQuestionnaireResult> {\n printBanner();\n\n const existingConfig = options.existingConfig;\n if (existingConfig) {\n const reconfigure = await prompts.confirm({\n message: \"Reconfigure workflow setup (.cursor/workflow.json)?\",\n default: false,\n });\n\n if (!reconfigure) {\n return {\n projectConfig: normalizeProjectConfig(existingConfig),\n shouldWriteProjectConfig: false,\n };\n }\n }\n\n const projectConfig = await promptProjectConfig(\n existingConfig ?? createDefaultProjectConfig(),\n prompts,\n );\n const githubMcpToken = projectConfig.backlog.provider === \"github-issues\"\n ? await promptGitHubMcpToken(prompts)\n : undefined;\n\n return {\n projectConfig,\n shouldWriteProjectConfig: true,\n githubMcpToken,\n };\n}\n\nasync function promptProjectConfig(\n defaults: ProjectConfig,\n prompts: QuestionnairePrompts,\n): Promise<ProjectConfig> {\n const provider = await prompts.select({\n message: \"Which backlog style should this project use?\",\n choices: [\n {\n name: \"Markdown file in the repository\",\n description: \"Track work in a markdown backlog file that the workflow updates directly.\",\n value: \"file\",\n },\n {\n name: \"GitHub Project (v2) + issues\",\n description:\n \"Track work in a GitHub Project (v2): milestones = epics, Project Priority orders work, Project Status maps to workflow state. Uses GitHub MCP instead of a local backlog file.\",\n value: \"github-issues\",\n },\n ],\n default: defaults.backlog.provider,\n }) as BacklogProviderKind;\n\n const backlog = await promptBacklogConfig(provider, defaults, prompts);\n const architectReview = await promptDefaultMode(\n \"Default architect review behavior?\",\n defaults.workflow.defaults.architectReview,\n prompts,\n {\n required: \"Require a second architect review by default\",\n optional: \"Let the orchestrator skip architect review by default when the task is clearly small and low-risk\",\n },\n );\n const testing = await promptDefaultMode(\n \"Default adversarial testing behavior?\",\n defaults.workflow.defaults.testing,\n prompts,\n {\n required: \"Require `/tester` by default\",\n optional: \"Let the orchestrator skip `/tester` by default when developer verification is sufficient\",\n },\n );\n\n const models = await promptWorkflowModels(defaults.workflow.models, prompts);\n\n return {\n backlog,\n workflow: {\n defaults: {\n architectReview,\n testing,\n },\n models,\n },\n };\n}\n\nasync function promptWorkflowModels(\n defaults: WorkflowModels,\n prompts: QuestionnairePrompts,\n): Promise<WorkflowModels> {\n const useRecommended = await prompts.confirm({\n message:\n \"Use recommended Cursor models for /planner, /architect, /developer, and /tester?\",\n default: true,\n });\n\n if (useRecommended) {\n return defaults;\n }\n\n const planner = (\n await prompts.input({\n message: \"Model id for /planner:\",\n default: defaults.planner,\n validate: (value) =>\n value.trim() ? true : \"Enter a model id (see Cursor docs).\",\n })\n ).trim();\n\n const architect = (\n await prompts.input({\n message: \"Model id for /architect:\",\n default: defaults.architect,\n validate: (value) =>\n value.trim() ? true : \"Enter a model id (see Cursor docs).\",\n })\n ).trim();\n\n const developer = (\n await prompts.input({\n message: \"Model id for /developer:\",\n default: defaults.developer,\n validate: (value) =>\n value.trim() ? true : \"Enter a model id (see Cursor docs).\",\n })\n ).trim();\n\n const tester = (\n await prompts.input({\n message: \"Model id for /tester:\",\n default: defaults.tester,\n validate: (value) =>\n value.trim() ? true : \"Enter a model id (see Cursor docs).\",\n })\n ).trim();\n\n return { planner, architect, developer, tester };\n}\n\nasync function promptBacklogConfig(\n provider: BacklogProviderKind,\n defaults: ProjectConfig,\n prompts: QuestionnairePrompts,\n): Promise<ProjectConfig[\"backlog\"]> {\n if (provider === \"github-issues\") {\n const githubDefaults = defaults.backlog[\"github-issues\"];\n const repository = (await prompts.input({\n message: \"GitHub repository for issues (owner/name):\",\n default: githubDefaults?.repository ?? \"\",\n validate: (value) =>\n value.trim().match(/^[^/\\s]+\\/[^/\\s]+$/)\n ? true\n : \"Use the form owner/name.\",\n })).trim();\n\n const projectNumberStr = await prompts.input({\n message: \"GitHub Project (v2) number:\",\n default: githubDefaults?.projectNumber != null\n ? String(githubDefaults.projectNumber)\n : \"\",\n validate: (value) => {\n const n = Number.parseInt(value.trim(), 10);\n return Number.isFinite(n) && n > 0\n ? true\n : \"Enter a positive Project number (from the Projects tab).\";\n },\n });\n const projectNumber = Number.parseInt(projectNumberStr.trim(), 10);\n\n const projectOwner = (await prompts.input({\n message:\n \"Project owner (org or user login; leave blank to use the repository owner):\",\n default: githubDefaults?.projectOwner ?? \"\",\n })).trim();\n\n const priorityField = (await prompts.input({\n message: \"Project field name for backlog ordering:\",\n default: githubDefaults?.priorityField ?? \"Priority\",\n validate: (value) =>\n value.trim() ? true : \"Field name is required.\",\n })).trim();\n\n const statusField = (await prompts.input({\n message: \"Project field name for workflow status:\",\n default: githubDefaults?.statusField ?? \"Status\",\n validate: (value) =>\n value.trim() ? true : \"Field name is required.\",\n })).trim();\n\n const labelRaw = (await prompts.input({\n message:\n \"Optional issue label filter (leave blank for none; secondary to Project items):\",\n default: githubDefaults?.label ?? \"\",\n })).trim();\n\n return {\n provider,\n \"github-issues\": {\n repository,\n projectNumber,\n ...(projectOwner.trim().length > 0\n ? { projectOwner: projectOwner.trim() }\n : {}),\n priorityField,\n statusField,\n ...(labelRaw.trim().length > 0 ? { label: labelRaw.trim() } : {}),\n mcpServerName: githubDefaults?.mcpServerName ?? \"github\",\n },\n };\n }\n\n const fileDefaults = defaults.backlog.file;\n const backlogPath = (await prompts.input({\n message: \"Backlog file path:\",\n default: fileDefaults?.path ?? \"docs/backlog.md\",\n validate: (value) => value.trim() ? true : \"Path is required.\",\n })).trim();\n\n return {\n provider,\n file: {\n path: backlogPath,\n },\n };\n}\n\ntype GitHubMcpAuthChoice =\n | { readonly kind: \"env\" }\n | { readonly kind: \"gh-account\"; readonly account: string }\n | { readonly kind: \"manual\" };\n\nconst GITHUB_MCP_AUTH_QUESTION =\n \"How should Cursor authenticate to GitHub for the MCP server?\";\n\nconst GITHUB_MCP_TOKEN_PROMPT =\n \"GitHub personal access token for the Cursor MCP server:\";\n\nfunction formatGitHubMcpContextBlock(): string {\n return (\n `${BOLD}GitHub MCP${RESET}\\n` +\n `${DIM}The GitHub MCP server needs a token so Cursor can reach your repository, Project (v2), and issues.${RESET}`\n );\n}\n\nfunction githubMcpAuthSelectMessage(): string {\n return `${formatGitHubMcpContextBlock()}\\n\\n${GITHUB_MCP_AUTH_QUESTION}`;\n}\n\nfunction githubMcpAuthSelectTheme() {\n return {\n style: {\n message: (text: string, status: Status) => {\n if (status === \"done\") {\n return styleText(\"bold\", GITHUB_MCP_AUTH_QUESTION);\n }\n return text;\n },\n },\n };\n}\n\nfunction githubMcpPasswordMessageNoGhAccounts(): string {\n return (\n `${formatGitHubMcpContextBlock()}\\n\\n` +\n `${DIM}No GitHub CLI accounts were found (install \\`gh\\` and run \\`gh auth login\\` to sign in).${RESET}\\n` +\n `${DIM}You can paste a fine-grained or classic PAT with repo scope for the MCP GitHub server.${RESET}\\n\\n` +\n `${GITHUB_MCP_TOKEN_PROMPT}`\n );\n}\n\nfunction githubMcpPasswordTheme() {\n return {\n style: {\n message: (text: string, status: Status) => {\n if (status === \"done\") {\n return styleText(\"bold\", GITHUB_MCP_TOKEN_PROMPT);\n }\n return text;\n },\n },\n };\n}\n\nfunction maskTokenHint(token: string): string {\n const t = token.trim();\n if (t.length <= 8) {\n return \"…\";\n }\n return `${t.slice(0, 4)}…${t.slice(-4)}`;\n}\n\nfunction formatAccountChoice(a: GitHubAccount): string {\n const active = a.active ? \" — active\" : \"\";\n return `${a.account} @ ${a.host}${active}`;\n}\n\nasync function promptGitHubMcpToken(\n prompts: QuestionnairePrompts,\n): Promise<string> {\n const envToken = process.env.GITHUB_PERSONAL_ACCESS_TOKEN?.trim();\n const accounts = await listGitHubAccounts();\n\n const choices: Array<{ name: string; value: GitHubMcpAuthChoice }> = [];\n\n if (envToken) {\n choices.push({\n name: `Use GITHUB_PERSONAL_ACCESS_TOKEN from the environment (${maskTokenHint(envToken)})`,\n value: { kind: \"env\" },\n });\n }\n\n for (const account of accounts) {\n choices.push({\n name: formatAccountChoice(account),\n value: { kind: \"gh-account\", account: account.account },\n });\n }\n\n choices.push({\n name: \"Enter a personal access token manually\",\n value: { kind: \"manual\" },\n });\n\n if (accounts.length === 0 && !envToken) {\n return (await prompts.password({\n message: githubMcpPasswordMessageNoGhAccounts(),\n theme: githubMcpPasswordTheme(),\n validate: (value) => value.trim() ? true : \"GitHub token is required.\",\n })).trim();\n }\n\n const selected = await prompts.select({\n message: githubMcpAuthSelectMessage(),\n choices,\n theme: githubMcpAuthSelectTheme(),\n }) as GitHubMcpAuthChoice;\n\n if (selected.kind === \"env\") {\n return envToken!;\n }\n\n if (selected.kind === \"manual\") {\n return (await prompts.password({\n message: GITHUB_MCP_TOKEN_PROMPT,\n validate: (value) => value.trim() ? true : \"GitHub token is required.\",\n })).trim();\n }\n\n const resolved = await resolveGitHubTokenForAccount(selected.account);\n if (resolved) {\n return resolved;\n }\n\n console.warn(\n `${BOLD}Could not read a token for that account via \\`gh auth token\\`.${RESET} ` +\n `${DIM}Sign in with \\`gh auth login\\` or enter a token below.${RESET}`,\n );\n return (await prompts.password({\n message: GITHUB_MCP_TOKEN_PROMPT,\n validate: (value) => value.trim() ? true : \"GitHub token is required.\",\n })).trim();\n}\n\nasync function promptDefaultMode(\n message: string,\n defaultValue: WorkflowDefaultMode,\n prompts: QuestionnairePrompts,\n labels: Record<WorkflowDefaultMode, string>,\n): Promise<WorkflowDefaultMode> {\n return prompts.select({\n message,\n choices: [\n { name: labels.required, value: \"required\" },\n { name: labels.optional, value: \"optional\" },\n ],\n default: defaultValue,\n }) as Promise<WorkflowDefaultMode>;\n}\n\nfunction printBanner(): void {\n console.log(`\n ${BOLD}@byrde/cursor${RESET}\n ${DIM}Install and configure the workflow so the project starts with the\n right backlog, review, testing, and GitHub tooling from day one.${RESET}\n`);\n}\n","import { execFile, execFileSync } from \"node:child_process\";\n\nexport interface GitHubAccount {\n readonly account: string;\n readonly host: string;\n readonly active: boolean;\n}\n\nfunction execFileResult(\n command: string,\n args: string[],\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n return new Promise((resolve) => {\n execFile(command, args, (error, stdout, stderr) => {\n const exitCode =\n error && typeof error === \"object\" && \"code\" in error\n ? (error.code as number)\n : error\n ? 1\n : 0;\n resolve({\n stdout: String(stdout ?? \"\"),\n stderr: String(stderr ?? \"\"),\n exitCode,\n });\n });\n });\n}\n\n/**\n * Parses `gh auth status` output into logged-in accounts (see agent-toolkit auth-checker).\n * Handles current `gh` output where each account block includes `- Active account: true|false`.\n */\nexport function parseGitHubAccounts(output: string): GitHubAccount[] {\n const accounts: GitHubAccount[] = [];\n const lines = output.split(\"\\n\");\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const accountMatch = line.match(/Logged in to (\\S+) account (\\S+)/);\n if (!accountMatch) {\n continue;\n }\n\n const host = accountMatch[1];\n const account = accountMatch[2];\n let active = line.includes(\"✓\");\n\n for (let j = i + 1; j < Math.min(i + 8, lines.length); j++) {\n const next = lines[j];\n if (/Logged in to \\S+ account \\S+/.test(next)) {\n break;\n }\n if (/Active account:\\s*true\\b/.test(next)) {\n active = true;\n break;\n }\n if (/Active account:\\s*false\\b/.test(next)) {\n active = false;\n break;\n }\n }\n\n accounts.push({ host, account, active });\n }\n\n return accounts;\n}\n\nexport async function listGitHubAccounts(): Promise<GitHubAccount[]> {\n let result: { stdout: string; stderr: string; exitCode: number };\n try {\n result = await execFileResult(\"gh\", [\"auth\", \"status\"]);\n } catch {\n return [];\n }\n\n if (result.exitCode !== 0) {\n return [];\n }\n\n const combined = `${result.stdout}\\n${result.stderr}`;\n return parseGitHubAccounts(combined);\n}\n\n/**\n * Resolves a token via `gh auth token`, optionally for a specific `--user` account.\n */\nexport async function resolveGitHubTokenForAccount(\n account?: string,\n): Promise<string | undefined> {\n const args = [\"auth\", \"token\"];\n if (account) {\n args.push(\"--user\", account);\n }\n\n try {\n const result = await execFileResult(\"gh\", args);\n const token = result.stdout.trim();\n if (result.exitCode !== 0 || !token) {\n return undefined;\n }\n return token;\n } catch {\n return undefined;\n }\n}\n\nexport function detectGitHubToken(): string | undefined {\n const envToken = process.env.GITHUB_PERSONAL_ACCESS_TOKEN?.trim();\n if (envToken) {\n return envToken;\n }\n\n try {\n const token = execFileSync(\"gh\", [\"auth\", \"token\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n return token || undefined;\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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","names":["readFileSync","path","path","existsSync","mkdirSync","readFileSync","unlinkSync","writeFileSync","path","installedAt","packageRoot","path","readFileSync","packageVersion","existsSync","mkdirSync","writeFileSync","newHash","unlinkSync","existsSync","statSync","path","existsSync","mkdirSync","statSync","path","packageRoot","existsSync","mkdirSync","readFileSync","writeFileSync","path","path","existsSync","readFileSync","mkdirSync","writeFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","path","packageRoot","path","path","readFileSync"]}
@@ -0,0 +1,155 @@
1
+ type BacklogProviderKind = "file" | "github-issues";
2
+ type WorkflowDefaultMode = "required" | "optional";
3
+ /** Subagent roles with configurable Cursor model ids (see `assets/agents/*.md`). */
4
+ type WorkflowModelRole = "planner" | "architect" | "developer" | "tester";
5
+ interface WorkflowModels {
6
+ readonly planner: string;
7
+ readonly architect: string;
8
+ readonly developer: string;
9
+ readonly tester: string;
10
+ }
11
+ /**
12
+ * GitHub backlog mode uses provider key `github-issues` (legacy name) and is
13
+ * GitHub Project v2–first: issues are ordered by the Project **Priority** field,
14
+ * workflow state by the Project **Status** field, and **milestones** represent epics.
15
+ */
16
+ interface GitHubIssuesBacklogConfig {
17
+ readonly repository: string;
18
+ /** GitHub Project (v2) number as shown on the repository Projects tab. */
19
+ readonly projectNumber: number;
20
+ /**
21
+ * Organization or user login that owns the project. When omitted, tooling
22
+ * assumes the repository owner (the segment before `/` in `repository`).
23
+ */
24
+ readonly projectOwner?: string;
25
+ /** Project field name used for backlog ordering (default `Priority`). */
26
+ readonly priorityField: string;
27
+ /** Project field name used for workflow status (default `Status`). */
28
+ readonly statusField: string;
29
+ /**
30
+ * Optional issue label filter (secondary to Project membership). Omit or leave
31
+ * empty when everything is driven from the Project.
32
+ */
33
+ readonly label?: string;
34
+ readonly mcpServerName: string;
35
+ }
36
+ interface ProjectConfig {
37
+ readonly backlog: {
38
+ readonly provider: BacklogProviderKind;
39
+ readonly file?: {
40
+ readonly path: string;
41
+ };
42
+ readonly "github-issues"?: GitHubIssuesBacklogConfig;
43
+ };
44
+ readonly workflow: {
45
+ readonly defaults: {
46
+ readonly architectReview: WorkflowDefaultMode;
47
+ readonly testing: WorkflowDefaultMode;
48
+ };
49
+ readonly models: WorkflowModels;
50
+ };
51
+ }
52
+ /** Defaults match pre-template agent frontmatter in `assets/agents/`. */
53
+ declare function createDefaultWorkflowModels(): WorkflowModels;
54
+ declare function createDefaultProjectConfig(): ProjectConfig;
55
+ declare const DEFAULT_PROJECT_CONFIG: ProjectConfig;
56
+ /**
57
+ * Merges parsed JSON with defaults so older configs without `workflow.models`
58
+ * (or partial fields) remain valid.
59
+ */
60
+ declare function normalizeProjectConfig(raw: unknown): ProjectConfig;
61
+
62
+ interface AssetEntry {
63
+ readonly source: string;
64
+ readonly target: string;
65
+ /**
66
+ * When set, `source` is a UTF-8 template with `{{MODEL}}`; install/sync
67
+ * substitutes the value from `workflow.models.<role>`.
68
+ */
69
+ readonly renderAgent?: WorkflowModelRole;
70
+ }
71
+ /** Maps each shipped file under `assets/` to its path under `<cwd>/.cursor/`. */
72
+ declare const DEFAULT_MANIFEST: readonly [{
73
+ readonly source: "assets/agents/architect.md";
74
+ readonly target: "agents/architect.md";
75
+ readonly renderAgent: "architect";
76
+ }, {
77
+ readonly source: "assets/agents/developer.md";
78
+ readonly target: "agents/developer.md";
79
+ readonly renderAgent: "developer";
80
+ }, {
81
+ readonly source: "assets/agents/planner.md";
82
+ readonly target: "agents/planner.md";
83
+ readonly renderAgent: "planner";
84
+ }, {
85
+ readonly source: "assets/agents/tester.md";
86
+ readonly target: "agents/tester.md";
87
+ readonly renderAgent: "tester";
88
+ }, {
89
+ readonly source: "assets/rules/global.mdc";
90
+ readonly target: "rules/global.mdc";
91
+ }, {
92
+ readonly source: "assets/rules/init.mdc";
93
+ readonly target: "rules/init.mdc";
94
+ }, {
95
+ readonly source: "assets/templates/backlog.md";
96
+ readonly target: "templates/backlog.md";
97
+ }, {
98
+ readonly source: "assets/templates/design.md";
99
+ readonly target: "templates/design.md";
100
+ }, {
101
+ readonly source: "assets/templates/overview.md";
102
+ readonly target: "templates/overview.md";
103
+ }, {
104
+ readonly source: "assets/templates/testability/README.md";
105
+ readonly target: "templates/testability/README.md";
106
+ }];
107
+
108
+ /** Canonical status values for markdown and GitHub-backed tasks. */
109
+ declare const TASK_STATUS_VALUES: readonly ["TODO", "In Progress", "Ready to Test", "Complete"];
110
+ type TaskStatus = (typeof TASK_STATUS_VALUES)[number];
111
+ /**
112
+ * Lower numbers sort first (1 = highest priority). File-backed backlogs without
113
+ * a Priority column assign {@link DEFAULT_TASK_PRIORITY} when reading.
114
+ */
115
+ type TaskPriority = number;
116
+ /** Default for rows missing a Priority cell (unprioritized / lowest). */
117
+ declare const DEFAULT_TASK_PRIORITY = 1000;
118
+ interface Task {
119
+ readonly id: string;
120
+ readonly epic: string;
121
+ readonly priority: TaskPriority;
122
+ readonly description: string;
123
+ readonly acceptanceCriteria: string;
124
+ readonly status: TaskStatus;
125
+ readonly prototype: string;
126
+ readonly notes: string;
127
+ }
128
+ interface TaskFilter {
129
+ readonly status?: TaskStatus;
130
+ readonly epic?: string;
131
+ }
132
+ type NewTask = Omit<Task, "id">;
133
+
134
+ interface BacklogProvider {
135
+ listTasks(filter?: TaskFilter): Promise<Task[]>;
136
+ getTask(id: string): Promise<Task | undefined>;
137
+ updateTaskStatus(id: string, status: TaskStatus): Promise<void>;
138
+ createTask(task: NewTask): Promise<Task>;
139
+ }
140
+
141
+ declare class FileBacklogProvider implements BacklogProvider {
142
+ private readonly backlogPath;
143
+ constructor(backlogPath: string);
144
+ listTasks(filter?: TaskFilter): Promise<Task[]>;
145
+ getTask(id: string): Promise<Task | undefined>;
146
+ updateTaskStatus(id: string, status: TaskStatus): Promise<void>;
147
+ createTask(task: NewTask): Promise<Task>;
148
+ private readDocument;
149
+ private writeDocument;
150
+ get path(): string;
151
+ }
152
+
153
+ declare const BYRDE_CURSOR_PACKAGE_NAME = "@byrde/cursor";
154
+
155
+ export { type AssetEntry, BYRDE_CURSOR_PACKAGE_NAME, type BacklogProvider, DEFAULT_MANIFEST, DEFAULT_PROJECT_CONFIG, DEFAULT_TASK_PRIORITY, FileBacklogProvider, type GitHubIssuesBacklogConfig, type NewTask, type ProjectConfig, TASK_STATUS_VALUES, type Task, type TaskFilter, type TaskPriority, type TaskStatus, type WorkflowModelRole, type WorkflowModels, createDefaultProjectConfig, createDefaultWorkflowModels, normalizeProjectConfig };