@cad0p/pi-steering-commit-format

Commit-message format validation predicates for pi-steering. Bundled formats: Conventional Commits 1.0.0 (Angular preset type allowlist), bracketed JIRA-style ticket references. Extensible via `commitFormatFactory`.

Packages

Package details

package

Install @cad0p/pi-steering-commit-format from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@cad0p/pi-steering-commit-format
Package
@cad0p/pi-steering-commit-format
Version
0.1.0
Published
Aug 10, 2026
Downloads
228/mo · 146/wk
Author
cad0p
License
MIT
Types
package
Size
75.6 KB
Dependencies
0 dependencies · 1 peer

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-steering-commit-format

Commit-message format validation predicates for pi-steering.

Bundled formats:

  • Conventional Commits 1.0.0 (Angular preset type allowlist)feat: , fix(scope): , refactor!: …, etc. The 11-token Angular preset (feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert); 1.0.0-conformant types outside that set (release:, merge:, …) are rejected.
  • Bracketed JIRA-style ticket references[ABC-123], [PROJ-1234], etc.

Extensible via commitFormatFactory — bring your own format checker and combine with the builtins.

What this package is

A sibling of @cad0p/pi-steering shipping the universal commit-message format checks as a plugin. Mirrors the pi-steering-flags precedent: opt-in functionality that doesn't belong in pi-steering core. External plugin authors get a clean import path; consumers that don't need commit-format validation don't pay the surface-area cost.

The package parses commit message strings — it does not walk bash ASTs. No unbash / unbash-walker dependency.

Quick start

// .pi/steering/index.ts
import { defineConfig } from "@cad0p/pi-steering";
import commitFormatPlugin from "pi-steering-commit-format";

export default defineConfig({
  plugins: [commitFormatPlugin],
  rules: [
    {
      name: "require-conventional-commit",
      tool: "bash",
      field: "command",
      pattern: /^git\s+commit\b/,
      when: { commitFormat: { require: ["conventional"] } },
      reason:
        "Commit messages must follow Conventional Commits 1.0.0 with the Angular preset's type allowlist (feat: ..., fix(scope): ..., etc.).",
    },
    {
      name: "require-jira-and-conventional",
      tool: "bash",
      field: "command",
      pattern: /^git\s+commit\b/,
      when: { commitFormat: { require: ["conventional", "jira"] } },
      reason:
        "Commit messages must follow Conventional Commits 1.0.0 with the Angular preset's type allowlist AND include a bracketed JIRA reference (e.g. [ABC-123]).",
    },
  ],
});

Predicate

when.commitFormat

Rule fires (commit BLOCKED) when the commit message fails any required format check.

commitFormat: {
  require: readonly FormatName[];   // AND across listed formats
}

The default plugin ships with two format checkers:

  • "conventional" — Conventional Commits 1.0.0 header check, restricted to the Angular preset's 11-token type allowlist (see the package overview above).
  • "jira" — at least one bracketed JIRA-style reference ([ABC-123]).

Empty require: [] is a no-op (nothing required → nothing fires).

The predicate inspects ctx.input.command, extracts the -m <msg> value via extractCommitMessage, and runs every required checker. Commands without a -m (e.g., bare git commit, which would open an editor) are NOT validated by this predicate — the editor flow needs a separate hook.

Combine with custom formats

Use commitFormatFactory to build your own predicate that AND-gates the builtins with a custom checker:

import {
  BUILTIN_FORMATS,
  commitFormatFactory,
} from "pi-steering-commit-format";
import type { Plugin, PredicateShape } from "@cad0p/pi-steering";

const myCommitFormat = commitFormatFactory({
  ...BUILTIN_FORMATS,
  custom: (msg) => /^\[CUSTOM\]/.test(msg),
});

// Register the predicate name on `PiSteeringPredicates` so consumers
// get the same compile-time autocomplete + JSDoc on hover the default
// `commitFormat` predicate provides. Without this `declare global`
// block, an unregistered predicate name is rejected at the type
// level inside a rule's `when:` slot.
declare global {
  interface PiSteeringPredicates {
    /** `when.myCommitFormat` — conventional + jira + custom. */
    myCommitFormat: PredicateShape<
      Parameters<typeof myCommitFormat>[0]
    >;
  }
}

export const myPlugin = {
  name: "my-org",
  predicates: { myCommitFormat },
} as const satisfies Plugin;

The factory's require: arg is type-narrowed to keyof F, so TypeScript flags typos at the rule's when: slot. Calling with an unknown format name via a JS / as any bypass fail-CLOSES (the predicate fires).

BUILTIN_FORMATS is the registry of available checkers, NOT a default-required set — callers always pick which formats to AND together via require:.

For reference patterns when registering a custom predicate name on PiSteeringPredicates, see:

  • @cad0p/pi-steering's gitPlugin in plugins/git/index.ts (multi-predicate registry block, mixed bare + spread shapes).
  • pi-steering-flags's src/index.ts (sibling external plugin's registry block).
  • This package's own src/plugin.ts (single-predicate spread-only registry block for commitFormat).

License

MIT