oct
Loading...
Searching...
No Matches
oct.git.oct_git Namespace Reference

Classes

class  FanoutGateOutcome

Functions

None git (click.Context ctx)
tuple[bool, list[str]] _quick_check_file (Path path, Path project_root)
str _badge (bool|None compliant)
bool _is_within_project (Path path, Path project_root_resolved)
 _maybe_load_workspace (Path root)
dict _build_workspace_view (*, workspace, list[Path] staged, list[Path] modified, list[Path] untracked, bool no_check)
list[Path] _get_untracked_files (Path root)
list[Path] _get_modified_unstaged (Path root)
tuple[int, int] _get_ahead_behind (Path root)
None git_status_cmd (click.Context ctx, bool json_mode, bool no_check, str|None scope)
int _git_check_fanout (click.Context ctx, *, workspace, str scope, str|None cli_profile, str fallback_profile, str|None branch, bool include_tests, bool fix, bool json_mode)
None git_check_cmd (click.Context ctx, bool staged_only, bool check_all, bool include_tests, bool fix, str|None profile, bool json_mode, bool sandbox)
list[str] _merge_ignore_file (Path path, tuple[str,...] entries, bool dry_run)
list[str] _create_gitattributes (Path root, bool dry_run)
bool _generate_github_workflow (Path root, bool dry_run)
None git_init_cmd (click.Context ctx, bool dry_run, bool github, bool no_hooks)
None git_commit_cmd (click.Context ctx, tuple[str,...] messages, bool force_commit, bool no_verify, str|None profile, bool json_mode, bool ignore_unstaged_mutation, tuple[str,...] extra_args)
None _emit_commit_json (ctx, *, int exit_code, str message, str|None branch, str profile, list[str]|None errors=None, list|None secrets=None)
None _populate_commit_audit (ctx, *, str|None branch, int exit_code, bool checks_passed, int staged_count, bool secrets=False, int lint_v=0, int format_v=0, list[str]|None tracked_mutations=None, list[dict]|None per_subproject_results=None)
dict[str, list[Path]] _group_files_by_subproject (list[Path] staged, workspace)
FanoutGateOutcome _run_fanout_gate (workspace, list[Path] files, *, str|None cli_profile, str|None branch, str fallback_profile, bool include_tests=False, bool apply_policy=True)
str _resolve_subproject_profile (subproject, dict|None sp_octrc, str|None cli_override, str|None branch)
 _merge_quality_gate_results (dict[str, "QualityGateResult"] per_sp)
list[dict] _build_per_subproject_audit (dict per_sp_results, dict per_sp_meta)
str _resolve_observe_method (dict|None octrc)
str _resolve_observe_mode (dict|None octrc, bool ignore_unstaged_mutation)
str|None _safe_relative (Path path, Path root)
list[str] _check_unstaged_mutation (Path root, dict[str, str] pre_snapshot, list[Path] staged, str stage_label, str method="hash")
None _emit_observer_block (ctx, *, list[str] mutations, str message, str|None branch, str profile, bool json_mode, int staged_count)
None _advisory_checks (Path root, list[Path] staged, str message, bool err=True)
None git_branch_cmd (click.Context ctx, str|None create_name, str|None switch_name, bool json_mode)
None _emit_branch_json (*, str operation="", str branch="", int exit_code=0, list[str]|None errors=None)
None _branch_audit (click.Context ctx, *, int exit_code, str branch="")
None _emit_add_json (*, str operation, list[str] paths_staged, list[dict] paths_skipped, dict|None post_check, int exit_code, list[str]|None errors=None)
None _add_audit (click.Context ctx, *, int exit_code, int staged_count=0)
dict|None _post_check_summary (Path root, dict|None octrc)
None git_add_cmd (click.Context ctx, tuple[str,...] paths, bool patch_mode, bool update_mode, bool all_mode, bool dry_run, bool json_mode)
None _print_post_check_advisory (dict|None post)
None _emit_ignore_json (*, str operation, list[str]|None patterns_added=None, list[str]|None patterns_removed=None, list[str]|None oct_managed=None, list[str]|None other=None, int exit_code=0, list[str]|None errors=None)
None _ignore_audit (click.Context ctx, *, int exit_code)
str _resolve_ignore_scope (str|None cli_scope, dict|None octrc)
tuple[Path|None, str|None] _resolve_ignore_target_dir (*, Path project_root, Path repo_root, str scope)
None _restore_audit (click.Context ctx, *, int exit_code)
None git_restore_cmd (click.Context ctx, tuple[str,...] paths, bool staged_mode, bool all_mode, bool skip_prompt, bool json_mode)
None git_ignore_cmd (click.Context ctx, tuple[str,...] patterns, str|None remove_pattern, bool list_mode, str|None scope, bool json_mode)
None git_commit_msg_cmd (click.Context ctx, Path message_file, bool json_mode)
None hooks_group (click.Context ctx)
None hooks_install_cmd (click.Context ctx, bool force)
None hooks_status_cmd (click.Context ctx)
None hooks_remove_cmd (click.Context ctx)
None git_changelog_cmd (click.Context ctx, str|None version, str|None since, bool dry_run, bool json_mode)
Path _require_git_repo (Path root)
list[tuple[str, int]] _check_large_staged_files (Path root, list[Path] staged, dict|None octrc)
bool _should_auto_branch (str|None branch, dict|None octrc)
str _deduplicate_branch_name (Path root, str name)
str|None _auto_branch_for_commit (Path root, str original_branch, str message, click.Context ctx, bool json_mode)

Variables

int _LARGE_FILE_THRESHOLD_BYTES = 10 * 1024 * 1024
tuple _FANOUT_FIX_REFUSAL
tuple _GITATTRIBUTES_DEFAULTS
str _GITHUB_WORKFLOW_TEMPLATE
str UNSCOPED_BUCKET = "__unscoped__"
 no_glob_expansion
str _ENHANCED_HOOKS_TEMPLATE
tuple _OCT_HOOK_IDS

Detailed Description

Purpose
-------
Click command definitions for the ``oct git`` command group (Phase 4B).
Contains only CLI glue - argument parsing, JSON rendering, exit-code
translation. All computational work is delegated to
:mod:`oct.git.quality_gate`, :mod:`oct.git.policy`, and
:mod:`oct.core.git`.

Responsibilities
----------------
- Define the ``git`` Click group mounted under the top-level ``cli``.
- Implement ``oct git status`` with ``--json`` and ``--no-check`` flags.
- Implement ``oct git check`` with ``--staged-only``, ``--all``,
  ``--include-tests``, ``--fix``, ``--profile``, ``--json`` flags.
- Render human-readable terminal output and machine-readable JSON.
- Populate ``ctx.obj["_audit_record"]`` for the ``@audited`` decorator.

Diagnostics
-----------
Domain: GIT
Levels:
    L2 - lifecycle: command start/end
    L3 - details: scope/profile resolution
    L4 - deep trace: per-file rendering decisions

Contracts
---------
- Each command is wrapped with ``@audited`` from :mod:`oct.git.audit`.
- Exit codes for ``oct git check`` follow blueprint §5.3:
  0=pass, 1=lint, 2=format, 3=lint+format, 4=tests, 5=secrets.
- ``oct git status`` always exits 0 (informational only).
- Plan 199: every octrc read in this module goes through
  :func:`oct.core.octrc.load_octrc_safe`, the same loader the lint,
  secrets and formatter passes use. It resolves ``.option_c/octrc.json``
  first and falls back to the legacy ``<root>/.octrc.json`` (FS-539), so
  a migrated project is never invisible to the git layer. Loading a
  second way here is what made a subproject's config unreadable on the
  commit path; do not reintroduce a local reader.
- The loader returns ``{}`` (never ``None``) when no config exists. Every
  consumer in this module guards with ``isinstance(octrc, dict)`` or
  ``(octrc or {})``, both of which treat ``{}`` exactly as they treated
  the old ``None``.

Dependencies
------------
- oct.core.diagnostics (_dbg structured logger)
- oct.core.octrc (the ONE octrc loader - see the contract above)
- oct.core.paths (project-relative path helper)
- oct.core.project_root (project root detection)
- oct.git.audit (AuditRecord, audited decorator)
- click (CLI framework)
- oct.git.policy (the .gitignore marker fences, the profile exit-code policy and the branch and ignore-pattern rules)
- oct.core.exclusions (lazy; GIT_IGNORE_DEFAULTS - the ignore patterns oct git init writes)
- oct.core.git (lazy; git_run, current_branch, get_repo_root and the other git primitives the commands use)
- oct.core.workspace (lazy; manifest discovery and subproject bucketing for the workspace fan-out)
- oct.git.changelog (lazy; collect_changelog_entries and format_changelog for oct git changelog)
- oct.git.commit_observer (lazy; unstaged-mutation snapshots taken around the git commit call)
- oct.git.conventional (lazy; commit message validation and diagnostics-impact analysis)
- oct.git.quality_gate (lazy; run_quality_gate and the secrets scan - the lint, format and secrets gate)
- oct.hooks.oct_hooks (lazy; install_hooks for oct git init)
- oct.linter.oct_lint (lazy; _lint_single_file - the quick header and docstring check for status)

Function Documentation

◆ _add_audit()

None oct.git.oct_git._add_audit ( click.Context ctx,
* ,
int exit_code,
int staged_count = 0 )
protected
Populate the audit record for ``oct git add``.

Definition at line 2572 of file oct_git.py.

Here is the caller graph for this function:

◆ _advisory_checks()

None oct.git.oct_git._advisory_checks ( Path root,
list[Path] staged,
str message,
bool err = True )
protected
Print advisory warnings for missing docs files.

Definition at line 2326 of file oct_git.py.

Here is the caller graph for this function:

◆ _auto_branch_for_commit()

str | None oct.git.oct_git._auto_branch_for_commit ( Path root,
str original_branch,
str message,
click.Context ctx,
bool json_mode )
protected
Create a feature branch from a commit message and switch to it.

Returns the new branch name on success, or ``None`` on failure
(after emitting errors and populating the audit record).

Definition at line 4071 of file oct_git.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _badge()

str oct.git.oct_git._badge ( bool | None compliant)
protected
Return ``[OK]``, ``[!!]``, or ``---`` for status rendering.

Definition at line 153 of file oct_git.py.

◆ _branch_audit()

None oct.git.oct_git._branch_audit ( click.Context ctx,
* ,
int exit_code,
str branch = "" )
protected
Populate the audit record for ``oct git branch``.

Definition at line 2531 of file oct_git.py.

Here is the caller graph for this function:

◆ _build_per_subproject_audit()

list[dict] oct.git.oct_git._build_per_subproject_audit ( dict per_sp_results,
dict per_sp_meta )
protected
Shape the per-subproject results dict for the audit record.

Definition at line 2160 of file oct_git.py.

Here is the caller graph for this function:

◆ _build_workspace_view()

dict oct.git.oct_git._build_workspace_view ( * ,
workspace,
list[Path] staged,
list[Path] modified,
list[Path] untracked,
bool no_check )
protected
Group files into per-subproject + workspace buckets for F1.2.

Returns a dict keyed by subproject name, plus ``"workspace"`` for
files matching ``workspace.workspace_files`` and
:data:`UNSCOPED_BUCKET` for everything else; each value is
``{"staged": [...], "modified": [...], "untracked": [...]}`` of
annotated entries.

Plan 213 / D-E: this view used to DROP files matching no subproject
and no ``workspace_files`` glob. That was the pre-208 silent-drop
shape surviving in the advisory view - incoherent with the commit
gate's partition invariant, and misleading in exactly the case that
matters, since a file the user cannot see in any section is the one
they are most likely to be surprised by at commit time. Unmatched
files now render in an ``__unscoped__`` section, under the same
workspace-root lens the gate uses for that bucket.

Definition at line 219 of file oct_git.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _check_large_staged_files()

list[tuple[str, int]] oct.git.oct_git._check_large_staged_files ( Path root,
list[Path] staged,
dict | None octrc )
protected
Check staged files for size exceeding the threshold.

Returns a list of ``(rel_path, size_bytes)`` for oversized files.
Threshold is configurable via ``octrc["git"]["large_file_threshold_mb"]``
(default: 10 MB).

Definition at line 3994 of file oct_git.py.

Here is the caller graph for this function:

◆ _check_unstaged_mutation()

list[str] oct.git.oct_git._check_unstaged_mutation ( Path root,
dict[str, str] pre_snapshot,
list[Path] staged,
str stage_label,
str method = "hash" )
protected
Re-snapshot and diff against *pre_snapshot*. Emit a stderr
warning for each mutated path. Returns the list of changed paths.

*method* is the detection method resolved once per commit (plan
242) and must match the one that produced *pre_snapshot*. Under
``"git"`` the post snapshot additionally hashes every path that
carried something other than the CLEAN sentinel in *pre_snapshot*,
so a file that was already dirty when the commit started is still
compared hash to hash - including when it was reverted to its
index content, which would otherwise leave git's dirty set and
read as unchanged.

Definition at line 2242 of file oct_git.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _create_gitattributes()

list[str] oct.git.oct_git._create_gitattributes ( Path root,
bool dry_run )
protected
Create or merge ``.gitattributes`` with Option C defaults.

Definition at line 1192 of file oct_git.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _deduplicate_branch_name()

str oct.git.oct_git._deduplicate_branch_name ( Path root,
str name )
protected
Return *name* if it does not exist, otherwise append ``-2``, ``-3``, etc.

Definition at line 4055 of file oct_git.py.

Here is the caller graph for this function:

◆ _emit_add_json()

None oct.git.oct_git._emit_add_json ( * ,
str operation,
list[str] paths_staged,
list[dict] paths_skipped,
dict | None post_check,
int exit_code,
list[str] | None errors = None )
protected
Emit JSON for ``oct git add`` to stdout.

Definition at line 2552 of file oct_git.py.

Here is the caller graph for this function:

◆ _emit_branch_json()

None oct.git.oct_git._emit_branch_json ( * ,
str operation = "",
str branch = "",
int exit_code = 0,
list[str] | None errors = None )
protected
Emit JSON for ``oct git branch`` to stdout.

Definition at line 2515 of file oct_git.py.

Here is the caller graph for this function:

◆ _emit_commit_json()

None oct.git.oct_git._emit_commit_json ( ctx,
* ,
int exit_code,
str message,
str | None branch,
str profile,
list[str] | None errors = None,
list | None secrets = None )
protected
Emit JSON output for the commit command.

Definition at line 1788 of file oct_git.py.

Here is the caller graph for this function:

◆ _emit_ignore_json()

None oct.git.oct_git._emit_ignore_json ( * ,
str operation,
list[str] | None patterns_added = None,
list[str] | None patterns_removed = None,
list[str] | None oct_managed = None,
list[str] | None other = None,
int exit_code = 0,
list[str] | None errors = None )
protected
Emit JSON for ``oct git ignore`` to stdout.

Definition at line 3054 of file oct_git.py.

Here is the caller graph for this function:

◆ _emit_observer_block()

None oct.git.oct_git._emit_observer_block ( ctx,
* ,
list[str] mutations,
str message,
str | None branch,
str profile,
bool json_mode,
int staged_count )
protected
Abort the commit with exit code 6 (B1.0 block mode).

Definition at line 2298 of file oct_git.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _generate_github_workflow()

bool oct.git.oct_git._generate_github_workflow ( Path root,
bool dry_run )
protected
Write ``.github/workflows/option-c.yml``. Returns True if created.

Definition at line 1198 of file oct_git.py.

Here is the caller graph for this function:

◆ _get_ahead_behind()

tuple[int, int] oct.git.oct_git._get_ahead_behind ( Path root)
protected
Return ``(ahead, behind)`` counts relative to upstream.

Returns ``(0, 0)`` if there is no upstream or if git fails.

Definition at line 399 of file oct_git.py.

Here is the caller graph for this function:

◆ _get_modified_unstaged()

list[Path] oct.git.oct_git._get_modified_unstaged ( Path root)
protected
Return tracked files with unstaged changes.

Definition at line 382 of file oct_git.py.

Here is the caller graph for this function:

◆ _get_untracked_files()

list[Path] oct.git.oct_git._get_untracked_files ( Path root)
protected
Return untracked files (not ignored) via ``git ls-files``.

Definition at line 365 of file oct_git.py.

Here is the caller graph for this function:

◆ _git_check_fanout()

int oct.git.oct_git._git_check_fanout ( click.Context ctx,
* ,
workspace,
str scope,
str | None cli_profile,
str fallback_profile,
str | None branch,
bool include_tests,
bool fix,
bool json_mode )
protected
Render ``oct git check`` in workspace fan-out mode (plan 213 / D-B).

Resolves the scope from ``workspace.root`` with the SAME helper the
commit gate uses (:func:`oct.git.quality_gate._resolve_scope`), gates
it through :func:`_run_fanout_gate`, renders one section per non-empty
bucket (mirroring ``oct git status``), and returns the worst-wins exit
code.

``--fix`` refuses loudly here (D-C). JSON output keeps the legacy
top-level shape, computed from the merged result, and ADDS a
``per_subproject`` array - the same precedent ``oct git status`` set
with ``workspace_view``.

Definition at line 729 of file oct_git.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _group_files_by_subproject()

dict[str, list[Path]] oct.git.oct_git._group_files_by_subproject ( list[Path] staged,
workspace )
protected
Group *staged* paths into per-subproject + workspace + unscoped buckets.

Files matched by a subproject's path go to that subproject's bucket; files
not under any subproject AND matching ``workspace.workspace_files`` go to
the ``"workspace"`` bucket; **every remaining file goes to the
:data:`UNSCOPED_BUCKET`** (plan 208).

The returned buckets PARTITION *staged* - the union of all bucket lists
equals the input set, with no duplicates. This is the invariant the commit
gate relies on so that no staged file is ever committed unscanned; the
caller asserts it and fails closed. Previously a file matching neither a
subproject nor ``workspace_files`` - or one that failed ``relative_to`` -
was silently discarded, and the commit fan-out then never scanned it.

Definition at line 1853 of file oct_git.py.

Here is the caller graph for this function:

◆ _ignore_audit()

None oct.git.oct_git._ignore_audit ( click.Context ctx,
* ,
int exit_code )
protected
Populate the audit record for ``oct git ignore``.

Definition at line 3081 of file oct_git.py.

Here is the caller graph for this function:

◆ _is_within_project()

bool oct.git.oct_git._is_within_project ( Path path,
Path project_root_resolved )
protected
Return ``True`` if *path* is inside the OCT project root.

Used by ``git_status_cmd`` to filter git results down to the
project scope in monorepo layouts where the git repo root is an
ancestor of the OCT project root.

Definition at line 160 of file oct_git.py.

Here is the caller graph for this function:

◆ _maybe_load_workspace()

oct.git.oct_git._maybe_load_workspace ( Path root)
protected
Probe for workspace mode and load the manifest if applicable.

F1.2 helper. Returns ``(workspace, in_workspace_mode)``:

- ``in_workspace_mode = True`` when *root* is itself the workspace
  root (the directory containing ``.option_c_workspace.json``).
  This activates per-subproject fan-out.
- ``in_workspace_mode = False`` when invocation came from inside a
  subproject (project-root discovery resolved to that subproject
  first), even if a workspace manifest exists higher up. This
  preserves backwards-compat byte-for-byte for single-project
  callers.

Returns ``(None, False)`` on any load failure; the caller falls
back to the legacy single-project rendering path.

Definition at line 174 of file oct_git.py.

Here is the caller graph for this function:

◆ _merge_ignore_file()

list[str] oct.git.oct_git._merge_ignore_file ( Path path,
tuple[str, ...] entries,
bool dry_run )
protected
Merge *entries* into an ignore/attributes file, appending only missing lines.

Returns the list of entries that were (or would be) added.

Definition at line 1143 of file oct_git.py.

Here is the caller graph for this function:

◆ _merge_quality_gate_results()

oct.git.oct_git._merge_quality_gate_results ( dict[str, "QualityGateResult"] per_sp)
protected
Aggregate per-subproject results into a single QualityGateResult.

Counters (lint, format, files_checked, test_failures) are summed.
Secrets findings are concatenated (preserves the
``(path, line, reason)`` tuples the G-D4 invariant uses to surface
every leak). per_file is concatenated. duration_ms is the max
(forward-compatible with parallel execution; v1 runs serially so
it's effectively the longest single bucket).

Definition at line 2119 of file oct_git.py.

Here is the caller graph for this function:

◆ _populate_commit_audit()

None oct.git.oct_git._populate_commit_audit ( ctx,
* ,
str | None branch,
int exit_code,
bool checks_passed,
int staged_count,
bool secrets = False,
int lint_v = 0,
int format_v = 0,
list[str] | None tracked_mutations = None,
list[dict] | None per_subproject_results = None )
protected
Populate the audit record for oct git commit.

Definition at line 1808 of file oct_git.py.

Here is the caller graph for this function:

◆ _post_check_summary()

dict | None oct.git.oct_git._post_check_summary ( Path root,
dict | None octrc )
protected
Run the staged-only quality gate and return a summary dict.

Honours ``git.add_post_check`` (default ``True``). Returns ``None``
when disabled.

Plan 285 (OCTGIT-06): at a workspace root the staged set is gated
through :func:`_run_fanout_gate` - the ONE fan-out implementation
``oct git check`` (plan 213 / D-B) and ``oct git commit`` (F1.3)
already share - so the advisory and the gate cannot report different
verdicts for the same staged set. They did before: this ran a single
:func:`~oct.git.quality_gate.run_quality_gate` rooted at the
invocation root, and at a workspace root that root has no octrc and
matches no subproject, so the profile collapsed to ``compact``, every
subproject-relative identity header failed the header rule against
the workspace-relative path, and the header fixer counted as the
format issue. A clean file therefore drew ``FAIL (lint=1 format=1)``
from ``add`` while ``check --staged-only`` reported ``0/0``.

In workspace mode the returned ``profile`` is the ``(bucket,
profile)`` list the fan-out actually used, so the JSON says which
profile gated which file, and ``unbucketed`` carries the fail-closed
signal: when it is non-empty NO gate ran and the verdict is 2, as it
is for the commit and check paths. Invocation from inside a
subproject, or in a non-workspace repo, is byte-identical to pre-285
- :func:`_maybe_load_workspace` returns ``(None, False)`` in both
cases - and so is the degenerate empty-staged-set case, which has no
buckets to name.

The advisory remains advisory: ``oct git add`` still exits 0 over a
FAIL verdict (the plan-208 contract). What changes is only whether
the verdict is true.

Definition at line 2588 of file oct_git.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _print_post_check_advisory()

None oct.git.oct_git._print_post_check_advisory ( dict | None post)
protected
Print a single-line summary of the post-stage quality gate result.

Plan 285: the three shapes and their precedence are unchanged, and in
single-project mode the bytes are unchanged too. In workspace mode
``post["profile"]`` is the ``(bucket, profile)`` list the fan-out used
rather than one profile name, and the line appends it in one short
parenthesis - ``Quality gate: PASS (oc_chat strict; workspace
compact)`` - so a verdict says where it looked and an operator can
see at a glance that their file was gated at its own profile.

A non-empty ``unbucketed`` replaces that parenthesis with the files
no bucket claimed: no gate ran over them, so the counts beside the
verdict describe nothing and the names are the only useful detail.

Definition at line 2993 of file oct_git.py.

Here is the caller graph for this function:

◆ _quick_check_file()

tuple[bool, list[str]] oct.git.oct_git._quick_check_file ( Path path,
Path project_root )
protected
Run a minimal lint check (header + docstring only) on a Python file.

Returns ``(compliant, issues_list)``. This is the "quick check" from
blueprint §5.2 - not the full gate, just enough for status badges.

Definition at line 109 of file oct_git.py.

Here is the caller graph for this function:

◆ _require_git_repo()

Path oct.git.oct_git._require_git_repo ( Path root)
protected
Return the git repo root, or exit with a clear UX message.

- Git not installed: *"Git is not installed. Git-related features
  are disabled."*
- Not a repo: *"Not a git repository. Run 'oct git init' to
  initialise."*

Definition at line 3967 of file oct_git.py.

Here is the caller graph for this function:

◆ _resolve_ignore_scope()

str oct.git.oct_git._resolve_ignore_scope ( str | None cli_scope,
dict | None octrc )
protected
Apply scope precedence: CLI > octrc > 'nearest'.

Mirrors the precedence used by ``oct git status --scope``.

Definition at line 3100 of file oct_git.py.

Here is the caller graph for this function:

◆ _resolve_ignore_target_dir()

tuple[Path | None, str | None] oct.git.oct_git._resolve_ignore_target_dir ( * ,
Path project_root,
Path repo_root,
str scope )
protected
Resolve the directory whose ``.gitignore`` should be edited.

Returns ``(target_dir, error_message)`` - exactly one is ``None``.

Scope semantics:

- ``workspace``: walk up from *project_root* to find a workspace
  manifest; the workspace root is the target. Errors when no
  manifest exists above CWD.
- ``project``: the *project_root* itself.
- ``nearest``: workspace root if *project_root* IS a workspace
  root (i.e. discovery resolved through the manifest fallback);
  otherwise *project_root* (a subproject or a single project).

Definition at line 3119 of file oct_git.py.

Here is the caller graph for this function:

◆ _resolve_observe_method()

str oct.git.oct_git._resolve_observe_method ( dict | None octrc)
protected
Return ``"git"`` / ``"hash"`` for the B1.0 observer (plan 242).

Read from ``.octrc.json -> git.observe_unstaged_mutation_method``.
An absent key resolves to ``"git"``, the git-native detection that
costs about 0.2 s per pass instead of the content walk's 6 to
188 s. ``"hash"`` selects the walk for a paranoid run.

Fails closed: any other value raises :class:`ValueError` naming the
key, and the caller refuses the commit with exit code 2 before a
snapshot is taken. A typo must never silently pick a method - in
either direction. Independent of the mode resolved by
:func:`_resolve_observe_mode`; the two keys do not interact.

Definition at line 2178 of file oct_git.py.

Here is the caller graph for this function:

◆ _resolve_observe_mode()

str oct.git.oct_git._resolve_observe_mode ( dict | None octrc,
bool ignore_unstaged_mutation )
protected
Return ``"off"`` / ``"warn"`` / ``"block"`` for the B1.0 observer.

Precedence (highest first): ``--ignore-unstaged-mutation`` flag
forces ``"warn"``; ``.octrc.json -> git.observe_unstaged_mutation``
sets the persistent default; final fallback is ``"warn"``.

Definition at line 2209 of file oct_git.py.

Here is the caller graph for this function:

◆ _resolve_subproject_profile()

str oct.git.oct_git._resolve_subproject_profile ( subproject,
dict | None sp_octrc,
str | None cli_override,
str | None branch )
protected
Resolve the lint profile for *subproject* under workspace fan-out.

Plan 197: this is now a thin adapter over the ONE resolver,
:func:`oct.git.policy.resolve_effective_profile`. Fan-out and
single-project resolution therefore cannot drift apart - the
property is pinned by
``tests/tests_git/test_profile_resolution_workspace.py``.

Precedence (highest first), unchanged in shape but now shared:

1. **Protected-branch override** - force ``"strict"``. Pre-197 this
   path only honoured an EXPLICIT ``git.protected_branches`` list,
   so a subproject without one was gated at its manifest profile
   even on ``master``; the shared resolver applies
   :data:`~oct.git.policy.DEFAULT_PROTECTED_BRANCHES`
   (``main``/``master``) as the fallback, matching what
   single-project mode has always done. Plan 209: an explicit
   ``protected_branches`` list only OPTS OUT of this override for a
   ``nested_git`` subproject (a foreign nested repo, e.g.
   ``oc_explorer``); every other subproject can only add to the
   default protected set, never remove ``main``/``master`` from it.
2. **CLI ``--profile``** - explicit user override.
3. **Manifest ``subproject.profile``** - workspace-declared
   per-subproject default.
4. **``sp_octrc.git.pre_commit_profile``** - newly honoured here;
   single-project mode has always read it.
5. **``sp_octrc.linter.profile``** - the subproject's own
   ``.octrc.json`` setting.
6. **``"compact"``** - final fallback
   (:data:`~oct.git.policy.DEFAULT_PROFILE`).

Definition at line 2067 of file oct_git.py.

Here is the caller graph for this function:

◆ _restore_audit()

None oct.git.oct_git._restore_audit ( click.Context ctx,
* ,
int exit_code )
protected
Populate the audit record for ``oct git restore``.

Definition at line 3169 of file oct_git.py.

Here is the caller graph for this function:

◆ _run_fanout_gate()

FanoutGateOutcome oct.git.oct_git._run_fanout_gate ( workspace,
list[Path] files,
* ,
str | None cli_profile,
str | None branch,
str fallback_profile,
bool include_tests = False,
bool apply_policy = True )
protected
Gate *files* per owning subproject under a workspace manifest.

Plan 213 / D-A: the ONE fan-out implementation. ``oct git commit``
(F1.3) and ``oct git check`` (plan 213 / D-B) both route through it, so
the two commands cannot report different verdicts for the same file set
- which is exactly what they did before, because ``check`` ran a single
``run_quality_gate`` pass rooted at the cwd-discovered project root. At
the workspace root that root has no octrc and matches no subproject, so
the profile collapsed to ``compact`` (or ``strict`` on a protected
branch) and ``workspace.workspace_profile`` was never consulted.

Each subproject's slice runs under its own root and its own resolved
profile (:func:`_resolve_subproject_profile`, the plan-197/209 shared
resolver). The ``workspace`` bucket (declared ``workspace_files``) and
the :data:`UNSCOPED_BUCKET` (plan 208 - everything else) both run at
*cli_profile* → ``workspace.workspace_profile`` → *fallback_profile*.

The G-D4 secrets-always-block invariant is preserved by construction:
the buckets partition *files*, every bucket is scanned, and the merged
result concatenates every bucket's findings. The partition is verified
rather than trusted - see :attr:`FanoutGateOutcome.unbucketed`.

Parameters
----------
workspace
    Loaded :class:`~oct.core.workspace.Workspace` manifest.
files
    The full file set to gate (staged, changed, or all).
cli_profile
    Explicit ``--profile`` override, or ``None``.
branch
    Current branch, for the protected-branch override.
fallback_profile
    Profile used for the workspace/unscoped buckets when neither
    *cli_profile* nor the manifest supplies one. Callers pass their
    own single-project resolution so behaviour is unchanged when a
    manifest omits ``workspace_profile``.
include_tests
    Forwarded per bucket. ``oct git commit`` never sets it.
apply_policy
    When False every bucket's policy verdict is skipped and
    ``gate_exit`` is 0 (``oct git commit --force``). Secrets findings
    still flow through ``result`` - force never suppresses them.

Definition at line 1927 of file oct_git.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _safe_relative()

str | None oct.git.oct_git._safe_relative ( Path path,
Path root )
protected
Return *path* relative to *root* as a forward-slash string, or
``None`` when *path* is outside *root*.

Definition at line 2231 of file oct_git.py.

Here is the caller graph for this function:

◆ _should_auto_branch()

bool oct.git.oct_git._should_auto_branch ( str | None branch,
dict | None octrc )
protected
Return True when auto-branching is enabled for *branch*.

Auto-branching activates when the branch is protected and the
``git.auto_branch_on_protected`` setting is not explicitly ``False``
(defaults to ``True``).

Definition at line 4035 of file oct_git.py.

Here is the caller graph for this function:

◆ git()

None oct.git.oct_git.git ( click.Context ctx)
Git integration with Option C compliance checks.

Definition at line 99 of file oct_git.py.

◆ git_add_cmd()

None oct.git.oct_git.git_add_cmd ( click.Context ctx,
tuple[str, ...] paths,
bool patch_mode,
bool update_mode,
bool all_mode,
bool dry_run,
bool json_mode )
Stage files for commit (whole-file or interactive hunk).

Definition at line 2747 of file oct_git.py.

Here is the call graph for this function:

◆ git_branch_cmd()

None oct.git.oct_git.git_branch_cmd ( click.Context ctx,
str | None create_name,
str | None switch_name,
bool json_mode )
Manage branches with Option C naming conventions.

Definition at line 2366 of file oct_git.py.

Here is the call graph for this function:

◆ git_changelog_cmd()

None oct.git.oct_git.git_changelog_cmd ( click.Context ctx,
str | None version,
str | None since,
bool dry_run,
bool json_mode )
Generate changelog from Conventional Commits history.

Definition at line 3892 of file oct_git.py.

Here is the call graph for this function:

◆ git_check_cmd()

None oct.git.oct_git.git_check_cmd ( click.Context ctx,
bool staged_only,
bool check_all,
bool include_tests,
bool fix,
str | None profile,
bool json_mode,
bool sandbox )
Run the unified quality gate: lint + format + secrets.

Definition at line 940 of file oct_git.py.

Here is the call graph for this function:

◆ git_commit_cmd()

None oct.git.oct_git.git_commit_cmd ( click.Context ctx,
tuple[str, ...] messages,
bool force_commit,
bool no_verify,
str | None profile,
bool json_mode,
bool ignore_unstaged_mutation,
tuple[str, ...] extra_args )
Commit staged changes with quality gate enforcement.

Definition at line 1362 of file oct_git.py.

Here is the call graph for this function:

◆ git_commit_msg_cmd()

None oct.git.oct_git.git_commit_msg_cmd ( click.Context ctx,
Path message_file,
bool json_mode )
Validate a Conventional Commit message file.

Intended as the entry for the ``commit-msg`` pre-commit-framework stage:
``pre-commit`` invokes ``oct git commit-msg <file>`` with the path to
``.git/COMMIT_EDITMSG``. Exits 0 on valid, 1 on invalid, 2 on I/O errors.

Definition at line 3610 of file oct_git.py.

◆ git_ignore_cmd()

None oct.git.oct_git.git_ignore_cmd ( click.Context ctx,
tuple[str, ...] patterns,
str | None remove_pattern,
bool list_mode,
str | None scope,
bool json_mode )
Manage .gitignore patterns within the OCT-managed block.

Definition at line 3386 of file oct_git.py.

Here is the call graph for this function:

◆ git_init_cmd()

None oct.git.oct_git.git_init_cmd ( click.Context ctx,
bool dry_run,
bool github,
bool no_hooks )
Initialise or enhance a git repo with Option C conventions.

Definition at line 1216 of file oct_git.py.

Here is the call graph for this function:

◆ git_restore_cmd()

None oct.git.oct_git.git_restore_cmd ( click.Context ctx,
tuple[str, ...] paths,
bool staged_mode,
bool all_mode,
bool skip_prompt,
bool json_mode )
Restore working-tree edits or unstage paths.

Without ``--staged``: discards unstaged working-tree edits in
*paths*, reverting them to the index (i.e. ``git restore <paths>``).

With ``--staged``: removes *paths* from the index without touching
the working tree (i.e. ``git restore --staged <paths>``).

With ``--all``: scope is every modified file inside the OCT
project root. ``--staged --all`` requires confirmation (irreversible
destruction of all staged content); pass ``--yes`` to skip.

Definition at line 3198 of file oct_git.py.

Here is the call graph for this function:

◆ git_status_cmd()

None oct.git.oct_git.git_status_cmd ( click.Context ctx,
bool json_mode,
bool no_check,
str | None scope )
Show git status with Option C compliance annotations.

Definition at line 438 of file oct_git.py.

Here is the call graph for this function:

◆ hooks_group()

None oct.git.oct_git.hooks_group ( click.Context ctx)
Manage Option C git hooks.

Definition at line 3727 of file oct_git.py.

◆ hooks_install_cmd()

None oct.git.oct_git.hooks_install_cmd ( click.Context ctx,
bool force )
Generate .pre-commit-config.yaml with all Option C hooks.

Definition at line 3736 of file oct_git.py.

◆ hooks_remove_cmd()

None oct.git.oct_git.hooks_remove_cmd ( click.Context ctx)
Remove Option C hooks from .pre-commit-config.yaml.

Definition at line 3803 of file oct_git.py.

◆ hooks_status_cmd()

None oct.git.oct_git.hooks_status_cmd ( click.Context ctx)
Show installed hook state.

Definition at line 3772 of file oct_git.py.

Variable Documentation

◆ _ENHANCED_HOOKS_TEMPLATE

str oct.git.oct_git._ENHANCED_HOOKS_TEMPLATE
protected

Definition at line 3675 of file oct_git.py.

◆ _FANOUT_FIX_REFUSAL

tuple oct.git.oct_git._FANOUT_FIX_REFUSAL
protected
Initial value:
1= (
2 "Refusing to run --fix across the workspace.\n"
3 "Fix mode is supported per subproject only. Run it from the "
4 "subproject you want to fix, for example:\n"
5 " cd {example}\n"
6 " oct git check --fix\n"
7 "Without --fix, this command checks the whole workspace."
8)

Definition at line 719 of file oct_git.py.

◆ _GITATTRIBUTES_DEFAULTS

tuple oct.git.oct_git._GITATTRIBUTES_DEFAULTS
protected
Initial value:
1= (
2 "*.py text eol=lf",
3 "*.pem binary",
4 "*.key binary",
5)

Definition at line 1109 of file oct_git.py.

◆ _GITHUB_WORKFLOW_TEMPLATE

str oct.git.oct_git._GITHUB_WORKFLOW_TEMPLATE
protected
Initial value:
1= """\
2name: Option C CI
3on: [push, pull_request]
4jobs:
5 check:
6 runs-on: ubuntu-latest
7 steps:
8 - uses: actions/checkout@v4
9 - uses: actions/setup-python@v5
10 with:
11 python-version: "3.12"
12 - run: pip install -e ./oct
13 - run: oct lint --json
14 - run: oct format --dry-run
15 - run: oct test
16"""

Definition at line 1116 of file oct_git.py.

◆ _LARGE_FILE_THRESHOLD_BYTES

int oct.git.oct_git._LARGE_FILE_THRESHOLD_BYTES = 10 * 1024 * 1024
protected

Definition at line 89 of file oct_git.py.

◆ _OCT_HOOK_IDS

tuple oct.git.oct_git._OCT_HOOK_IDS
protected
Initial value:
1= (
2 "oct-quality-gate",
3 "oct-secrets-check",
4 "oct-commit-msg",
5 "oct-pre-push",
6 # Legacy hook IDs from oct install-hooks (Phase 4C and earlier).
7 "oct-lint",
8 "oct-format-check",
9)

Definition at line 3714 of file oct_git.py.

◆ no_glob_expansion

oct.git.oct_git.no_glob_expansion

Definition at line 3595 of file oct_git.py.

◆ UNSCOPED_BUCKET

str oct.git.oct_git.UNSCOPED_BUCKET = "__unscoped__"

Definition at line 1850 of file oct_git.py.