Ancora.PolicyFiles (ancora v1.0.0)

Copy Markdown View Source

File-kind classification and the governance-file set for change/missing_decision.

Governance files

These paths count as governance. A change to any of them, with no .spec/decisions/ file added or changed in the same diff, is what change/missing_decision fires on:

  • .spec/specs/** — authored subject specs
  • .spec/config.yml — gate config
  • .spec/AGENTS.md — agent guidance
  • .spec/README.md — corpus README

.spec/decisions/** is the ADR set that satisfies the co-change rule (except README.md in that directory, which is documentation, not an ADR). Decision files themselves are not governance files: editing an ADR does not require a second ADR.

missing_decision?/1 is the boolean form of that rule over a list of repo-relative changed paths.

Summary

Functions

Classifies a repo-relative path into a file kind.

Returns the co-change rule that applies to a kind or path.

True when path is an ADR under .spec/decisions/ (not README.md).

True when path is in the governance-file set.

True when a governance file changed and no ADR in .spec/decisions/ was added or changed in the same path set. That is the change/missing_decision trigger.

Returns true when a path participates in co-change gating.

Types

co_change_rule()

@type co_change_rule() ::
  {:requires_subject_touch, severity()}
  | :test_only_allowed
  | :doc_only_allowed
  | :ignored
  | :unknown_escalates

kind()

@type kind() :: :lib | :test | :doc | :generated | :unknown

severity()

@type severity() :: :off | :info | :warning | :error

Functions

classify(path)

@spec classify(String.t()) :: kind()

Classifies a repo-relative path into a file kind.

co_change_rule(path)

@spec co_change_rule(kind() | String.t()) :: co_change_rule()

Returns the co-change rule that applies to a kind or path.

Branch-local docs/plans/ paths short-circuit to :ignored regardless of their :doc classification.

decision_file?(path)

@spec decision_file?(String.t()) :: boolean()

True when path is an ADR under .spec/decisions/ (not README.md).

governance?(path)

@spec governance?(String.t()) :: boolean()

True when path is in the governance-file set.

missing_decision?(changed_paths)

@spec missing_decision?([String.t()]) :: boolean()

True when a governance file changed and no ADR in .spec/decisions/ was added or changed in the same path set. That is the change/missing_decision trigger.

policy_target?(path)

@spec policy_target?(String.t()) :: boolean()

Returns true when a path participates in co-change gating.

Paths with rule :ignored (generated, or branch-local docs/plans/) are excluded. Paths with rule :unknown_escalates are also excluded from the gate itself; callers that want to surface unknowns can do so via a separate finding using co_change_rule/1 directly.