/** * Git commit and check-commit query handlers. * * Ported from get-shit-done/bin/lib/commands.cjs (cmdCommit, cmdCheckCommit) * and core.cjs (execGit). Provides commit creation with message sanitization * and pre-commit validation. * * @example * ```typescript * import { commit, checkCommit } from './commit.js'; * * await commit(['docs: update state', '.planning/STATE.md'], '/project'); * // { data: { committed: true, hash: 'abc1234', message: 'docs: update state', files: [...] } } * * await checkCommit([], '/project'); * // { data: { can_commit: true, reason: 'commit_docs_enabled', ... } } * ``` */ import type { QueryHandler } from './utils.js'; /** * Run a git command in the given working directory. * * Ported from core.cjs lines 531-542. * * @param cwd - Working directory for the git command * @param args - Git command arguments (e.g., ['commit', '-m', 'msg']) * @returns Object with exitCode, stdout, and stderr */ export declare function execGit(cwd: string, args: string[]): { exitCode: number; stdout: string; stderr: string; }; /** * Sanitize a commit message to prevent prompt injection. * * Ported from security.cjs sanitizeForPrompt. * Strips zero-width characters, null bytes, and neutralizes * known injection markers that could hijack agent context. * * @param text - Raw commit message * @returns Sanitized message safe for git commit */ export declare function sanitizeCommitMessage(text: string): string; /** * Parse phase identifiers from an array of file paths. * * Each path is matched INDIVIDUALLY against the phase-directory convention * `-` at the start of a path segment (e.g. `1-setup/file.md`). * Returns the set of all distinct phase IDs found across all paths. * * Empty input → empty Set (strategy will be skipped by the caller). * All paths from the same phase → Set of size 1. * Paths spanning multiple phases → Set of size > 1 (caller must reject). * * @param filePaths - File paths passed to the commit handler via --files * @returns Set of phase numeric identifiers (e.g. `{"1"}`, `{"1", "2"}`) */ export declare function parsePhasesFromFiles(filePaths: string[]): Set; /** * Validate a branch template string. * * A template is valid when it is a non-empty string. After substitution * the caller should separately check that no `{placeholder}` tokens remain. * * @param template - Template value from config (may be undefined/empty) * @returns `{ ok: true }` if the template is usable, or * `{ ok: false, reason: string, template: string | undefined }` */ export declare function validateBranchTemplate(template: string | undefined): { ok: true; } | { ok: false; reason: string; template: string | undefined; }; /** * Resolve the final branch name from a config template and two positional tokens. * * The naming is intentionally generic: `firstToken` and `secondToken` cover * both the phase strategy (`phase number` + `phase slug`) and the milestone * strategy (`milestone version` + `milestone slug`). The template placeholders * `{phase}` / `{milestone}` map to `firstToken`; `{slug}` maps to `secondToken`. * This avoids duplicating the substitution + unresolved-placeholder check in the * milestone strategy block (issue #1278, PR #1279). * * Returns `{ ok: false }` if the resolved name still contains unsubstituted * `{placeholder}` tokens (which would indicate a broken template). * * @param template - Raw template string (pre-validated) * @param firstToken - Primary substitution token (phase number or milestone version) * @param secondToken - Secondary substitution token (slug) — falls back to `"phase"` or `"milestone"` * @returns `{ ok: true; branch: string }` or `{ ok: false; reason: string; branch: string }` */ export declare function resolveStrategyBranchName(template: string, firstToken: string, secondToken: string): { ok: true; branch: string; } | { ok: false; reason: string; branch: string; }; /** * Result shape returned by ensureStrategyBranch. * * `ok: true` — branch was already correct or the switch succeeded. * `ok: false` — a hard failure occurred; the caller MUST NOT proceed with the commit. */ export type StrategyBranchResult = { ok: true; reason?: string; } | { ok: false; reason: string; branch?: string; err?: string; }; /** * Create or switch to the configured strategy branch before a commit. * * Port of the branching-strategy block in cmdCommit() at * get-shit-done/bin/lib/commands.cjs:285-320 (ported from CJS (issue #1278, * PR #1279); ported here to close the SDK gap — bug #3749). * * This version (post codex adversarial review) surfaces every skip * distinctly — no silent swallows. Callers receive a typed result and * MUST halt on `ok: false`. * * Does nothing (ok: true, with reason logged) when: * - branching_strategy is absent, "none", or unrecognised * - the current branch is already the target branch * - --files was empty and phase cannot be inferred * * Returns ok: false when: * - phase_branch_template is missing/invalid * - --files spans multiple phases (cross-phase commit guard) * - git checkout -b fails for reasons other than "branch already exists" * - git checkout fallback also fails * * @param projectDir - Project root directory * @param workstream - Optional workstream scope * @param filePaths - Explicit file paths being committed (used to infer phase) */ export declare function ensureStrategyBranch(projectDir: string, workstream: string | undefined, filePaths: string[]): Promise; /** * Stage files and create a git commit. * * Checks commit_docs config (unless --force), sanitizes message, * stages specified files (or all .planning/), and commits. * * By default, `--files ` runs `git add -- ` for each named file * before committing. This means any per-hunk staging set up via `git add -p` * is **overwritten** by a full re-stage of the file's working-tree content. * * Pass `--respect-staged` to skip the `git add` step entirely. The handler * will commit only what is already staged within the requested pathspec. If * nothing is staged within that scope, the handler returns * `{ committed: false, reason: 'nothing staged' }` without error. The #3061 * leak-prevention invariant still holds: the trailing `-- ` pathspec * on the commit ensures files staged outside `--files ` are excluded. * * @param args - args[0]=message, remaining=file paths or flags * (--force, --amend, --no-verify, --respect-staged) * @param projectDir - Project root directory * @returns QueryResult with commit result */ export declare const commit: QueryHandler; /** * Validate whether a commit can proceed. * * Checks commit_docs config and staged file state. * * @param _args - Unused * @param projectDir - Project root directory * @returns QueryResult with { can_commit, reason, commit_docs, staged_files } */ export declare const checkCommit: QueryHandler; export declare const commitToSubrepo: QueryHandler; //# sourceMappingURL=commit.d.ts.map