{"record":{"id":"04255e3497f74983","repo":"can1357/oh-my-pi","slug":"security-scans-require-a-git-repository-request","errorCode":null,"errorMessage":"Security scans require a Git repository: ${request.cwd}","messagePattern":"Security scans require a Git repository: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/security/preflight.ts","lineNumber":320,"sourceCode":"}\n\ninterface SecurityPlanMaterial {\n\trepositoryRoot: string;\n\ttarget: SecurityTarget;\n\tknowledgeBases: SecurityKnowledgeBaseRef[];\n\toutput: SecurityOutputPlan;\n\tmodel: SecurityModelRef;\n\taccount: SecurityAccountRef;\n\tconfigFingerprint: string;\n\tworkflowFingerprint: string;\n}\n\nasync function buildPlanMaterial(\n\trequest: SecurityPlanRequest,\n\tadapter: SecurityGitAdapter,\n): Promise<SecurityPlanMaterial> {\n\tconst repositoryRoot = await adapter.root(path.resolve(request.cwd), request.signal);\n\tif (!repositoryRoot) throw new Error(`Security scans require a Git repository: ${request.cwd}`);\n\tconst canonicalRoot = await fs.realpath(repositoryRoot);\n\tconst target = await normalizeTarget(canonicalRoot, request.target, adapter, request.signal);\n\tconst knowledgeBases = await normalizeKnowledgeBases(request.knowledgeBasePaths, canonicalRoot);\n\tconst output = await normalizeOutput(canonicalRoot, request.outputRoot, request.archiveExisting ?? false);\n\tconst model: SecurityModelRef = {\n\t\tprovider: request.model.provider,\n\t\tmodelId: request.model.modelId,\n\t};\n\tif (request.model.thinkingLevel !== undefined) model.thinkingLevel = request.model.thinkingLevel;\n\tconst account: SecurityAccountRef = {\n\t\tprovider: request.account.provider,\n\t\tcredentialId: request.account.credentialId,\n\t};\n\tif (request.account.accountId !== undefined) account.accountId = request.account.accountId;\n\tif (request.account.email !== undefined) account.email = request.account.email;\n\tif (request.account.organizationId !== undefined) account.organizationId = request.account.organizationId;\n\tif (request.account.organizationName !== undefined) account.organizationName = request.account.organizationName;\n\treturn {","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/security/preflight.ts#L302-L338","documentation":"buildPlanMaterial resolves the Git repository root for a security scan plan via the git adapter. If `adapter.root()` returns null (the resolved path is not inside a Git work tree), the function throws to refuse planning a scan outside version control. Security scans are anchored to a repo root so findings are repository-relative and reproducible.","triggerScenarios":"Calling material()/buildPlanMaterial() with a request.cwd that is outside any Git repository, inside a bare repo where root() cannot resolve a work tree, or in a directory whose .git was removed/corrupted.","commonSituations":"Running security scans on a downloaded source snapshot or extracted tarball, pointing the scan at a temp directory, initializing a project without `git init`, or .git being excluded when copying a project.","solutions":["Run `git init` (and an initial commit) in request.cwd or a parent directory so a work-tree root resolves","Pass a cwd that is inside an existing Git repository","Verify with `git -C <cwd> rev-parse --show-toplevel` that the root resolves before invoking the scan","If .git was lost during copy/extract, restore it or re-clone the project"],"exampleFix":"// before\nawait material({ cwd: \"/tmp/snapshot\", ... });\n// after\nconst $ = Bun.$; await $`git -C /tmp/snapshot rev-parse --show-toplevel`; // ensure repo first\nawait material({ cwd: \"/home/me/project\", ... });","handlingStrategy":"validation","validationCode":"const root = await $`git -C ${cwd} rev-parse --show-toplevel`.nothrow();\nif (root.exitCode !== 0) throw new Error(`cwd is not a git repo: ${cwd}`);","typeGuard":"null","tryCatchPattern":"try { await material(request); } catch (e) { if (String(e.message).includes(\"require a Git repository\")) { /* git init or fix cwd */ } else throw e; }","preventionTips":["Preflight with git rev-parse before scans","Never scan snapshots without .git"],"tags":["git","filesystem","validation"],"backgroundTag":"not-a-git-repository","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}