@cad0p/pi-steering 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +29 -0
  3. package/README.md +920 -0
  4. package/dist/__test-helpers__.d.ts +95 -0
  5. package/dist/__test-helpers__.d.ts.map +1 -0
  6. package/dist/__test-helpers__.js +174 -0
  7. package/dist/__test-helpers__.js.map +1 -0
  8. package/dist/bin/pi-steering.d.ts +9 -0
  9. package/dist/bin/pi-steering.d.ts.map +1 -0
  10. package/dist/bin/pi-steering.js +506 -0
  11. package/dist/bin/pi-steering.js.map +1 -0
  12. package/dist/compat.d.ts +50 -0
  13. package/dist/compat.d.ts.map +1 -0
  14. package/dist/compat.js +180 -0
  15. package/dist/compat.js.map +1 -0
  16. package/dist/defaults.d.ts +61 -0
  17. package/dist/defaults.d.ts.map +1 -0
  18. package/dist/defaults.js +106 -0
  19. package/dist/defaults.js.map +1 -0
  20. package/dist/define-config.d.ts +235 -0
  21. package/dist/define-config.d.ts.map +1 -0
  22. package/dist/define-config.js +118 -0
  23. package/dist/define-config.js.map +1 -0
  24. package/dist/define-predicate.d.ts +49 -0
  25. package/dist/define-predicate.d.ts.map +1 -0
  26. package/dist/define-predicate.js +35 -0
  27. package/dist/define-predicate.js.map +1 -0
  28. package/dist/evaluator-internals/context.d.ts +186 -0
  29. package/dist/evaluator-internals/context.d.ts.map +1 -0
  30. package/dist/evaluator-internals/context.js +219 -0
  31. package/dist/evaluator-internals/context.js.map +1 -0
  32. package/dist/evaluator-internals/override.d.ts +19 -0
  33. package/dist/evaluator-internals/override.d.ts.map +1 -0
  34. package/dist/evaluator-internals/override.js +79 -0
  35. package/dist/evaluator-internals/override.js.map +1 -0
  36. package/dist/evaluator-internals/predicates.d.ts +152 -0
  37. package/dist/evaluator-internals/predicates.d.ts.map +1 -0
  38. package/dist/evaluator-internals/predicates.js +849 -0
  39. package/dist/evaluator-internals/predicates.js.map +1 -0
  40. package/dist/evaluator-internals/speculative-synthesis.d.ts +102 -0
  41. package/dist/evaluator-internals/speculative-synthesis.d.ts.map +1 -0
  42. package/dist/evaluator-internals/speculative-synthesis.js +101 -0
  43. package/dist/evaluator-internals/speculative-synthesis.js.map +1 -0
  44. package/dist/evaluator.d.ts +101 -0
  45. package/dist/evaluator.d.ts.map +1 -0
  46. package/dist/evaluator.js +714 -0
  47. package/dist/evaluator.js.map +1 -0
  48. package/dist/helpers/walker-unknown-cwd-reason.d.ts +68 -0
  49. package/dist/helpers/walker-unknown-cwd-reason.d.ts.map +1 -0
  50. package/dist/helpers/walker-unknown-cwd-reason.js +73 -0
  51. package/dist/helpers/walker-unknown-cwd-reason.js.map +1 -0
  52. package/dist/index.d.ts +42 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +93 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/internal/drop-unused-observers.d.ts +43 -0
  57. package/dist/internal/drop-unused-observers.d.ts.map +1 -0
  58. package/dist/internal/drop-unused-observers.js +50 -0
  59. package/dist/internal/drop-unused-observers.js.map +1 -0
  60. package/dist/internal/finalize-plugin-state.d.ts +22 -0
  61. package/dist/internal/finalize-plugin-state.d.ts.map +1 -0
  62. package/dist/internal/finalize-plugin-state.js +14 -0
  63. package/dist/internal/finalize-plugin-state.js.map +1 -0
  64. package/dist/internal/merge-observers.d.ts +30 -0
  65. package/dist/internal/merge-observers.d.ts.map +1 -0
  66. package/dist/internal/merge-observers.js +27 -0
  67. package/dist/internal/merge-observers.js.map +1 -0
  68. package/dist/internal/pattern-utils.d.ts +33 -0
  69. package/dist/internal/pattern-utils.d.ts.map +1 -0
  70. package/dist/internal/pattern-utils.js +20 -0
  71. package/dist/internal/pattern-utils.js.map +1 -0
  72. package/dist/internal/ref-text.d.ts +11 -0
  73. package/dist/internal/ref-text.d.ts.map +1 -0
  74. package/dist/internal/ref-text.js +15 -0
  75. package/dist/internal/ref-text.js.map +1 -0
  76. package/dist/internal/session-runtime.d.ts +44 -0
  77. package/dist/internal/session-runtime.d.ts.map +1 -0
  78. package/dist/internal/session-runtime.js +143 -0
  79. package/dist/internal/session-runtime.js.map +1 -0
  80. package/dist/internal/watch-matcher.d.ts +56 -0
  81. package/dist/internal/watch-matcher.d.ts.map +1 -0
  82. package/dist/internal/watch-matcher.js +179 -0
  83. package/dist/internal/watch-matcher.js.map +1 -0
  84. package/dist/loader.d.ts +97 -0
  85. package/dist/loader.d.ts.map +1 -0
  86. package/dist/loader.js +527 -0
  87. package/dist/loader.js.map +1 -0
  88. package/dist/observer-dispatcher.d.ts +69 -0
  89. package/dist/observer-dispatcher.d.ts.map +1 -0
  90. package/dist/observer-dispatcher.js +184 -0
  91. package/dist/observer-dispatcher.js.map +1 -0
  92. package/dist/plugin-merger.d.ts +175 -0
  93. package/dist/plugin-merger.d.ts.map +1 -0
  94. package/dist/plugin-merger.js +450 -0
  95. package/dist/plugin-merger.js.map +1 -0
  96. package/dist/plugins/git/branch-tracker.d.ts +85 -0
  97. package/dist/plugins/git/branch-tracker.d.ts.map +1 -0
  98. package/dist/plugins/git/branch-tracker.js +181 -0
  99. package/dist/plugins/git/branch-tracker.js.map +1 -0
  100. package/dist/plugins/git/cwd-extensions.d.ts +10 -0
  101. package/dist/plugins/git/cwd-extensions.d.ts.map +1 -0
  102. package/dist/plugins/git/cwd-extensions.js +155 -0
  103. package/dist/plugins/git/cwd-extensions.js.map +1 -0
  104. package/dist/plugins/git/git-ops.d.ts +89 -0
  105. package/dist/plugins/git/git-ops.d.ts.map +1 -0
  106. package/dist/plugins/git/git-ops.js +107 -0
  107. package/dist/plugins/git/git-ops.js.map +1 -0
  108. package/dist/plugins/git/index.d.ts +225 -0
  109. package/dist/plugins/git/index.d.ts.map +1 -0
  110. package/dist/plugins/git/index.js +52 -0
  111. package/dist/plugins/git/index.js.map +1 -0
  112. package/dist/plugins/git/predicates.d.ts +312 -0
  113. package/dist/plugins/git/predicates.d.ts.map +1 -0
  114. package/dist/plugins/git/predicates.js +580 -0
  115. package/dist/plugins/git/predicates.js.map +1 -0
  116. package/dist/plugins/git/rules.d.ts +209 -0
  117. package/dist/plugins/git/rules.d.ts.map +1 -0
  118. package/dist/plugins/git/rules.js +267 -0
  119. package/dist/plugins/git/rules.js.map +1 -0
  120. package/dist/schema.d.ts +1799 -0
  121. package/dist/schema.d.ts.map +1 -0
  122. package/dist/schema.js +4 -0
  123. package/dist/schema.js.map +1 -0
  124. package/dist/testing/index.d.ts +621 -0
  125. package/dist/testing/index.d.ts.map +1 -0
  126. package/dist/testing/index.js +747 -0
  127. package/dist/testing/index.js.map +1 -0
  128. package/examples/README.md +83 -0
  129. package/examples/combined-git-discipline/README.md +52 -0
  130. package/examples/combined-git-discipline/node_modules/.bin/pi-steering +43 -0
  131. package/examples/combined-git-discipline/package.json +18 -0
  132. package/examples/combined-git-discipline/steering.json +27 -0
  133. package/examples/combined-git-discipline/steering.test.ts +42 -0
  134. package/examples/combined-git-discipline/steering.ts +64 -0
  135. package/examples/combined-git-discipline/tsconfig.json +7 -0
  136. package/examples/draft-prs-only/README.md +42 -0
  137. package/examples/draft-prs-only/node_modules/.bin/pi-steering +43 -0
  138. package/examples/draft-prs-only/package.json +18 -0
  139. package/examples/draft-prs-only/steering.json +12 -0
  140. package/examples/draft-prs-only/steering.test.ts +48 -0
  141. package/examples/draft-prs-only/steering.ts +36 -0
  142. package/examples/draft-prs-only/tsconfig.json +7 -0
  143. package/examples/dynamic-reason-runtime-cwd/README.md +148 -0
  144. package/examples/dynamic-reason-runtime-cwd/node_modules/.bin/pi-steering +43 -0
  145. package/examples/dynamic-reason-runtime-cwd/package.json +18 -0
  146. package/examples/dynamic-reason-runtime-cwd/steering.test.ts +130 -0
  147. package/examples/dynamic-reason-runtime-cwd/steering.ts +82 -0
  148. package/examples/dynamic-reason-runtime-cwd/tsconfig.json +7 -0
  149. package/examples/force-push-strict/README.md +75 -0
  150. package/examples/force-push-strict/node_modules/.bin/pi-steering +43 -0
  151. package/examples/force-push-strict/package.json +18 -0
  152. package/examples/force-push-strict/steering.json +12 -0
  153. package/examples/force-push-strict/steering.test.ts +51 -0
  154. package/examples/force-push-strict/steering.ts +54 -0
  155. package/examples/force-push-strict/tsconfig.json +7 -0
  156. package/examples/no-amend/README.md +52 -0
  157. package/examples/no-amend/node_modules/.bin/pi-steering +43 -0
  158. package/examples/no-amend/package.json +18 -0
  159. package/examples/no-amend/steering.cwd-scoped.json +12 -0
  160. package/examples/no-amend/steering.json +11 -0
  161. package/examples/no-amend/steering.test.ts +49 -0
  162. package/examples/no-amend/steering.ts +38 -0
  163. package/examples/no-amend/tsconfig.json +7 -0
  164. package/examples/work-item-plugin/README.md +103 -0
  165. package/examples/work-item-plugin/node_modules/.bin/pi-steering +43 -0
  166. package/examples/work-item-plugin/package.json +19 -0
  167. package/examples/work-item-plugin/src/index.test.ts +168 -0
  168. package/examples/work-item-plugin/src/index.ts +122 -0
  169. package/examples/work-item-plugin/src/observers/npm-test-tracker.test.ts +95 -0
  170. package/examples/work-item-plugin/src/observers/npm-test-tracker.ts +88 -0
  171. package/examples/work-item-plugin/src/observers/retest-required-tracker.test.ts +81 -0
  172. package/examples/work-item-plugin/src/observers/retest-required-tracker.ts +81 -0
  173. package/examples/work-item-plugin/src/predicates/work-item-format.test.ts +157 -0
  174. package/examples/work-item-plugin/src/predicates/work-item-format.ts +99 -0
  175. package/examples/work-item-plugin/src/rules/commit-description-check.test.ts +107 -0
  176. package/examples/work-item-plugin/src/rules/commit-description-check.ts +83 -0
  177. package/examples/work-item-plugin/src/rules/commit-requires-work-item.test.ts +79 -0
  178. package/examples/work-item-plugin/src/rules/commit-requires-work-item.ts +56 -0
  179. package/examples/work-item-plugin/src/rules/push-requires-tests.test.ts +245 -0
  180. package/examples/work-item-plugin/src/rules/push-requires-tests.ts +62 -0
  181. package/examples/work-item-plugin/tsconfig.json +8 -0
  182. package/package.json +88 -0
  183. package/skills/steering-authoring/SKILL.md +102 -0
  184. package/src/INVARIANTS.md +116 -0
  185. package/src/__test-helpers__.ts +243 -0
  186. package/src/bin/pi-steering.test.ts +920 -0
  187. package/src/bin/pi-steering.ts +584 -0
  188. package/src/compat.test.ts +431 -0
  189. package/src/compat.ts +282 -0
  190. package/src/defaults.test.ts +585 -0
  191. package/src/defaults.ts +148 -0
  192. package/src/define-config.test.ts +888 -0
  193. package/src/define-config.ts +375 -0
  194. package/src/define-predicate.test.ts +70 -0
  195. package/src/define-predicate.ts +57 -0
  196. package/src/evaluator-internals/context.ts +290 -0
  197. package/src/evaluator-internals/override.test.ts +99 -0
  198. package/src/evaluator-internals/override.ts +83 -0
  199. package/src/evaluator-internals/predicates.ts +1037 -0
  200. package/src/evaluator-internals/speculative-synthesis.test.ts +411 -0
  201. package/src/evaluator-internals/speculative-synthesis.ts +199 -0
  202. package/src/evaluator.test.ts +6296 -0
  203. package/src/evaluator.ts +1106 -0
  204. package/src/factory-time-load.test.ts +630 -0
  205. package/src/helpers/walker-unknown-cwd-reason.test.ts +73 -0
  206. package/src/helpers/walker-unknown-cwd-reason.ts +83 -0
  207. package/src/index.test.ts +836 -0
  208. package/src/index.ts +229 -0
  209. package/src/internal/drop-unused-observers.test.ts +141 -0
  210. package/src/internal/drop-unused-observers.ts +81 -0
  211. package/src/internal/finalize-plugin-state.ts +43 -0
  212. package/src/internal/merge-observers.ts +51 -0
  213. package/src/internal/pattern-utils.test.ts +52 -0
  214. package/src/internal/pattern-utils.ts +38 -0
  215. package/src/internal/ref-text.test.ts +54 -0
  216. package/src/internal/ref-text.ts +17 -0
  217. package/src/internal/session-runtime.test.ts +629 -0
  218. package/src/internal/session-runtime.ts +201 -0
  219. package/src/internal/watch-matcher.test.ts +326 -0
  220. package/src/internal/watch-matcher.ts +200 -0
  221. package/src/jsdoc-propagation.test.ts +277 -0
  222. package/src/loader.test.ts +1098 -0
  223. package/src/loader.ts +581 -0
  224. package/src/not-block-onunknown.test.ts +554 -0
  225. package/src/observer-dispatcher.test.ts +939 -0
  226. package/src/observer-dispatcher.ts +290 -0
  227. package/src/per-predicate-typing.test.ts +361 -0
  228. package/src/plugin-merger.test.ts +790 -0
  229. package/src/plugin-merger.ts +598 -0
  230. package/src/plugins/git/README.md +485 -0
  231. package/src/plugins/git/branch-tracker.test.ts +281 -0
  232. package/src/plugins/git/branch-tracker.ts +187 -0
  233. package/src/plugins/git/cwd-extensions.test.ts +230 -0
  234. package/src/plugins/git/cwd-extensions.ts +160 -0
  235. package/src/plugins/git/git-ops.test.ts +397 -0
  236. package/src/plugins/git/git-ops.ts +173 -0
  237. package/src/plugins/git/index.ts +253 -0
  238. package/src/plugins/git/integration.test.ts +705 -0
  239. package/src/plugins/git/predicates.test.ts +1401 -0
  240. package/src/plugins/git/predicates.ts +693 -0
  241. package/src/plugins/git/rules.test.ts +1001 -0
  242. package/src/plugins/git/rules.ts +307 -0
  243. package/src/schema.test.ts +259 -0
  244. package/src/schema.ts +1963 -0
  245. package/src/testing/index.test.ts +1696 -0
  246. package/src/testing/index.ts +1472 -0
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Git plugin for `@cad0p/pi-steering`.
3
+ *
4
+ * Subpath import: `pi-steering/plugins/git`.
5
+ *
6
+ * Registers (in the terms of `Plugin`):
7
+ *
8
+ * - `predicates` - `branch`, `upstream`, `commitsAhead`,
9
+ * `hasStagedChanges`, `isClean`, `remote`.
10
+ * See `./predicates.ts` for the arg
11
+ * shapes each handler accepts.
12
+ * - `rules` - `no-main-commit-github` (github-flavored,
13
+ * first-match-wins) + `no-main-commit`
14
+ * (generic fallback). Both overridable.
15
+ * Users disable via
16
+ * `disabledRules: ["no-main-commit"]` /
17
+ * `["no-main-commit-github"]` or opt out
18
+ * of the whole plugin with
19
+ * `disabledPlugins: ["git"]`.
20
+ * - `trackers.branch` - sequential `git checkout` / `git switch`
21
+ * branch tracker. See `./branch-tracker.ts`.
22
+ * - `trackerExtensions.cwd.git`
23
+ * - per-command `--git-dir=` / `--work-tree=`
24
+ * parser layered on the core cwd tracker.
25
+ * See `./cwd-extensions.ts`.
26
+ *
27
+ * Also re-exported as composable building blocks for downstream
28
+ * plugins (e.g. RDS-style multi-package `cr --all` scans that need
29
+ * to query git state per subpackage directory):
30
+ *
31
+ * - `getBranch(ctx, cwd?)` — current branch or `null`
32
+ * - `getUpstream(ctx, cwd?)` — upstream name or `null`
33
+ * - `getCommitsAhead(ctx, wrt?, cwd?)` — commit count or `null`
34
+ * - `getStagedChanges(ctx, cwd?)` — boolean or `null`
35
+ * - `getWorkingTreeClean(ctx, cwd?)` — boolean or `null`
36
+ * - `getRemoteUrl(ctx, cwd?)` — origin URL or `null`
37
+ * - `walkerString(value)` — walker-sentinel narrowing
38
+ * helper for plugin-author
39
+ * predicates
40
+ * - `NO_CHECKOUT_IN_CHAIN` — branch-tracker fall-through
41
+ * sentinel
42
+ * - `GIT_COMMIT_PATTERN` — shared `git commit` regex
43
+ * source used by both
44
+ * commit-on-main rules
45
+ * - `PROTECTED_BRANCH_PATTERN` — shared protected-branch
46
+ * regex (main / master /
47
+ * mainline / trunk) used by
48
+ * both commit-on-main rules
49
+ *
50
+ * See `./git-ops.ts` for the helper contract (all collapse failure
51
+ * modes to `null`; caller decides what to do with it).
52
+ *
53
+ * Opt-in since the v0.1.x monorepo split: `DEFAULT_PLUGINS` is empty,
54
+ * so this plugin is registered ONLY when the user declares it:
55
+ *
56
+ * ```ts
57
+ * import gitPlugin from "@cad0p/pi-steering/plugins/git";
58
+ * export default defineConfig({ plugins: [gitPlugin] });
59
+ * ```
60
+ *
61
+ * Declaring it explicitly also feeds its rule / predicate names into
62
+ * `defineConfig`'s type unions (typo-checking on `disabledRules` /
63
+ * `disabledPlugins`); relying on a default would silently widen the
64
+ * union and let typos through.
65
+ *
66
+ * Tests build configs via `loadHarness({ includeDefaults: false })`
67
+ * and pass the plugin explicitly.
68
+ *
69
+ * ## Note for plugin authors
70
+ *
71
+ * This is the canonical reference plugin. Third-party plugins are
72
+ * expected to mirror this layout - one file per concern (tracker /
73
+ * extension / predicates / rules), a terse default export assembling
74
+ * them. Copy-adapt liberally.
75
+ */
76
+ import type { Tracker } from "@cad0p/unbash-walker";
77
+ import type { Patterns, PredicateShape } from "../../schema.ts";
78
+ declare global {
79
+ /**
80
+ * gitPlugin's typed-predicate registry. Each entry declares the
81
+ * predicate's `bare` value type and (optionally) an explicit
82
+ * `spreadBase` (the spread's object form WITHOUT modifiers).
83
+ * Modifiers (currently `onUnknown:`) are added at use site via
84
+ * `& PredicateModifiers` (outer leaf) or at the not-block top
85
+ * level (inside `not:`).
86
+ *
87
+ * Note: `cwd` is intentionally NOT in this block. It's a built-in
88
+ * non-registry leaf on {@link BuiltInWhenLeaves} (see schema.ts) so
89
+ * authors can write `when: { cwd: /work/ }` against pi-steering core
90
+ * without needing gitPlugin's module augmentation in scope. The
91
+ * runtime handler that wires `when.cwd` to the walker still lives
92
+ * in pi-steering core; gitPlugin layers `git --git-dir=` /
93
+ * `--work-tree=` cwd extensions via {@link gitCwdExtensions} but
94
+ * does not own the predicate's registry shape.
95
+ *
96
+ * @see PredicateShape, DefaultSpreadBase, PredicateModifiers in
97
+ * `schema.ts` for the full registry contract.
98
+ */
99
+ interface PiSteeringPredicates {
100
+ /**
101
+ * `when.branch` — match the current git branch. Pattern leaf,
102
+ * tracker-aware (in-chain `git checkout X` resolves statically;
103
+ * dynamic `git checkout $VAR` surfaces the walker's
104
+ * `"unknown"` sentinel — the engine's `onUnknown:` policy
105
+ * then projects to a definite verdict).
106
+ */
107
+ branch: PredicateShape<Patterns>;
108
+ /**
109
+ * `when.upstream` — match the current branch's configured
110
+ * upstream (`git rev-parse --abbrev-ref @{upstream}`). Pattern
111
+ * leaf. Inlines a walker-unknown-cwd guard at the handler
112
+ * top — surfaces trinary `"unknown"` instead of querying the
113
+ * wrong repo when the walker can't statically resolve cwd.
114
+ */
115
+ upstream: PredicateShape<Patterns>;
116
+ /**
117
+ * `when.remote` — match the repo's `origin` remote URL
118
+ * (`git config --get remote.origin.url`). Pattern leaf. Same
119
+ * walker-unknown-cwd guard as `upstream:`.
120
+ */
121
+ remote: PredicateShape<Patterns>;
122
+ /**
123
+ * `when.isClean` — `true` when the working tree has no
124
+ * unstaged / untracked / staged changes (`git status
125
+ * --porcelain` is empty); `false` otherwise. Boolean leaf;
126
+ * spreadBase auto-detects to `{ value: boolean }`. Inlines
127
+ * the walker-unknown-cwd guard.
128
+ */
129
+ isClean: PredicateShape<boolean>;
130
+ /**
131
+ * `when.hasStagedChanges` — `true` when there are staged
132
+ * changes (`git diff --cached --quiet` exits non-zero);
133
+ * `false` otherwise. Boolean leaf. Inlines the walker-
134
+ * unknown-cwd guard.
135
+ */
136
+ hasStagedChanges: PredicateShape<boolean>;
137
+ /**
138
+ * `when.commitsAhead` — match when the count of commits ahead
139
+ * of `wrt:` (default `@{upstream}`) satisfies every supplied
140
+ * comparator. Bare shorthand `commitsAhead: N` is equivalent
141
+ * to `{ eq: N }`. Spread form supports:
142
+ * - `eq?: number` — exact equality (`count === eq`).
143
+ * - `gt?: number` — strict greater-than (`count > gt`).
144
+ * - `lt?: number` — strict less-than (`count < lt`).
145
+ * - `wrt?: string` — git revision to count against (default
146
+ * `"@{upstream}"`).
147
+ * At least one of `eq` / `gt` / `lt` MUST be specified;
148
+ * combined with AND.
149
+ *
150
+ * Mixed-bare predicate: explicit `SpreadBase` since auto-
151
+ * detection from `number` would give `{ value: number }`,
152
+ * which doesn't match the desired comparator-bag shape.
153
+ * Inlines the walker-unknown-cwd guard.
154
+ */
155
+ commitsAhead: PredicateShape<number, {
156
+ eq?: number;
157
+ gt?: number;
158
+ lt?: number;
159
+ wrt?: string;
160
+ }>;
161
+ }
162
+ }
163
+ /**
164
+ * The git plugin. Default export so `import gitPlugin from
165
+ * "pi-steering/plugins/git"` gives you the whole thing.
166
+ *
167
+ * `as const satisfies Plugin` (rather than `: Plugin`) preserves the
168
+ * literal `name: "git"` in the inferred type. That literal is the
169
+ * input to any future `AllPluginNames<P>`-style inference in
170
+ * `defineConfig`, which needs `name: "git"`, not `name: string`, to
171
+ * offer string-literal completion for e.g. `disabledPlugins`.
172
+ */
173
+ declare const gitPlugin: {
174
+ readonly name: "git";
175
+ readonly predicates: Record<string, import("../../schema.ts").AnyPredicateHandler>;
176
+ readonly rules: readonly [{
177
+ readonly name: "no-main-commit-github";
178
+ readonly tool: "bash";
179
+ readonly field: "command";
180
+ readonly pattern: "^git\\b(?:\\s+-{1,2}[A-Za-z]\\S*(?:\\s+\\S+)?)*\\s+commit\\b";
181
+ readonly when: {
182
+ readonly branch: RegExp;
183
+ readonly remote: {
184
+ readonly pattern: RegExp;
185
+ readonly onUnknown: "allow";
186
+ };
187
+ };
188
+ readonly reason: (ctx: import("../../schema.ts").PredicateContext) => string;
189
+ readonly noOverride: false;
190
+ }, {
191
+ readonly name: "no-main-commit";
192
+ readonly tool: "bash";
193
+ readonly field: "command";
194
+ readonly pattern: "^git\\b(?:\\s+-{1,2}[A-Za-z]\\S*(?:\\s+\\S+)?)*\\s+commit\\b";
195
+ readonly when: {
196
+ readonly branch: RegExp;
197
+ };
198
+ readonly reason: (ctx: import("../../schema.ts").PredicateContext) => string;
199
+ readonly noOverride: false;
200
+ }];
201
+ readonly trackers: {
202
+ readonly branch: Tracker<unknown>;
203
+ };
204
+ readonly trackerExtensions: {
205
+ readonly cwd: {
206
+ readonly git: readonly import("@cad0p/unbash-walker").Modifier<unknown>[];
207
+ };
208
+ };
209
+ };
210
+ /**
211
+ * Type-level regression sentinel: if the plugin literal ever loses
212
+ * the `name: "git"` narrowing (for example, someone reintroducing
213
+ * `: Plugin` annotation), the inferred type of `GIT_PLUGIN_NAME`
214
+ * widens to `string` and any downstream literal-name inference
215
+ * breaks. Keep this export in place to fail compilation loudly when
216
+ * that happens.
217
+ */
218
+ export declare const GIT_PLUGIN_NAME: "git";
219
+ export default gitPlugin;
220
+ export { branchTracker, NO_CHECKOUT_IN_CHAIN } from "./branch-tracker.ts";
221
+ export { gitCwdExtensions } from "./cwd-extensions.ts";
222
+ export { getBranch, getCommitsAhead, getRemoteUrl, getStagedChanges, getUpstream, getWorkingTreeClean, } from "./git-ops.ts";
223
+ export { branch, type CommitsAheadArgs, commitsAhead, hasStagedChanges, isClean, predicates, remote, upstream, type WalkerStringResult, walkerString, } from "./predicates.ts";
224
+ export { GIT_COMMIT_PATTERN, noMainCommit, noMainCommitGithub, PROTECTED_BRANCH_PATTERN, rules, } from "./rules.ts";
225
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/git/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,KAAK,EAEV,QAAQ,EAER,cAAc,EACf,MAAM,iBAAiB,CAAC;AAMzB,OAAO,CAAC,MAAM,CAAC;IACb;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAAU,oBAAoB;QAC5B;;;;;;WAMG;QACH,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;QAEjC;;;;;;WAMG;QACH,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;QAEnC;;;;WAIG;QACH,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;QAEjC;;;;;;WAMG;QACH,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;QAEjC;;;;;WAKG;QACH,gBAAgB,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;QAE1C;;;;;;;;;;;;;;;;;WAiBG;QACH,YAAY,EAAE,cAAc,CAC1B,MAAM,EACN;YAAE,EAAE,CAAC,EAAE,MAAM,CAAC;YAAC,EAAE,CAAC,EAAE,MAAM,CAAC;YAAC,EAAE,CAAC,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,MAAM,CAAA;SAAE,CACxD,CAAC;KACH;CACF;AAED;;;;;;;;;GASG;AACH,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBASyB,OAAO,CAAC,OAAO,CAAC;;;;;;;CAO7B,CAAC;AAE5B;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,KAAsB,CAAC;AAErD,eAAe,SAAS,CAAC;AAKzB,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EACL,SAAS,EACT,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,MAAM,EACN,KAAK,gBAAgB,EACrB,YAAY,EACZ,gBAAgB,EAChB,OAAO,EACP,UAAU,EACV,MAAM,EACN,QAAQ,EACR,KAAK,kBAAkB,EACvB,YAAY,GACb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,wBAAwB,EACxB,KAAK,GACN,MAAM,YAAY,CAAC"}
@@ -0,0 +1,52 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Part of pi-steering.
3
+ import { branchTracker } from "./branch-tracker.js";
4
+ import { gitCwdExtensions } from "./cwd-extensions.js";
5
+ import { predicates } from "./predicates.js";
6
+ import { rules } from "./rules.js";
7
+ /**
8
+ * The git plugin. Default export so `import gitPlugin from
9
+ * "pi-steering/plugins/git"` gives you the whole thing.
10
+ *
11
+ * `as const satisfies Plugin` (rather than `: Plugin`) preserves the
12
+ * literal `name: "git"` in the inferred type. That literal is the
13
+ * input to any future `AllPluginNames<P>`-style inference in
14
+ * `defineConfig`, which needs `name: "git"`, not `name: string`, to
15
+ * offer string-literal completion for e.g. `disabledPlugins`.
16
+ */
17
+ const gitPlugin = {
18
+ name: "git",
19
+ predicates,
20
+ rules,
21
+ trackers: {
22
+ // `Plugin.trackers` is typed `Record<string, Tracker<unknown>>`
23
+ // because the schema can't commit to a specific T per tracker.
24
+ // Cast is safe - the walker dispatches on `modifiers[basename]`
25
+ // and never narrows T at the tracker-registry layer.
26
+ branch: branchTracker,
27
+ },
28
+ trackerExtensions: {
29
+ cwd: {
30
+ git: gitCwdExtensions,
31
+ },
32
+ },
33
+ };
34
+ /**
35
+ * Type-level regression sentinel: if the plugin literal ever loses
36
+ * the `name: "git"` narrowing (for example, someone reintroducing
37
+ * `: Plugin` annotation), the inferred type of `GIT_PLUGIN_NAME`
38
+ * widens to `string` and any downstream literal-name inference
39
+ * breaks. Keep this export in place to fail compilation loudly when
40
+ * that happens.
41
+ */
42
+ export const GIT_PLUGIN_NAME = gitPlugin.name;
43
+ export default gitPlugin;
44
+ // Named re-exports for consumers that want to pick pieces (e.g. a
45
+ // test harness constructing a minimal config that uses only the
46
+ // `branch` predicate without the shipped rule).
47
+ export { branchTracker, NO_CHECKOUT_IN_CHAIN } from "./branch-tracker.js";
48
+ export { gitCwdExtensions } from "./cwd-extensions.js";
49
+ export { getBranch, getCommitsAhead, getRemoteUrl, getStagedChanges, getUpstream, getWorkingTreeClean, } from "./git-ops.js";
50
+ export { branch, commitsAhead, hasStagedChanges, isClean, predicates, remote, upstream, walkerString, } from "./predicates.js";
51
+ export { GIT_COMMIT_PATTERN, noMainCommit, noMainCommitGithub, PROTECTED_BRANCH_PATTERN, rules, } from "./rules.js";
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/git/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,uBAAuB;AAsFvB,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AA2FnC;;;;;;;;;GASG;AACH,MAAM,SAAS,GAAG;IAChB,IAAI,EAAE,KAAK;IACX,UAAU;IACV,KAAK;IACL,QAAQ,EAAE;QACR,gEAAgE;QAChE,+DAA+D;QAC/D,gEAAgE;QAChE,qDAAqD;QACrD,MAAM,EAAE,aAA4C;KACrD;IACD,iBAAiB,EAAE;QACjB,GAAG,EAAE;YACH,GAAG,EAAE,gBAAgB;SACtB;KACF;CACwB,CAAC;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAU,SAAS,CAAC,IAAI,CAAC;AAErD,eAAe,SAAS,CAAC;AAEzB,kEAAkE;AAClE,gEAAgE;AAChE,gDAAgD;AAChD,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EACL,SAAS,EACT,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,MAAM,EAEN,YAAY,EACZ,gBAAgB,EAChB,OAAO,EACP,UAAU,EACV,MAAM,EACN,QAAQ,EAER,YAAY,GACb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,wBAAwB,EACxB,KAAK,GACN,MAAM,YAAY,CAAC"}
@@ -0,0 +1,312 @@
1
+ import type { AnyPredicateHandler, PredicateContext, PredicateHandler } from "../../schema.ts";
2
+ /**
3
+ * Unwrap the boolean payload from a {@link PredicateShape}<boolean>
4
+ * argument. Accepts the bare form (`true` / `false`) and the
5
+ * spread form (`{ value: true, onUnknown? }` /
6
+ * `{ value: false, onUnknown? }`); the engine's `readLeafOnUnknown`
7
+ * reads any `onUnknown:` sibling and `projectVerdict` applies the
8
+ * policy to the handler's `"unknown"` returns. The handler itself
9
+ * treats `onUnknown:` as an opaque sibling field and only consumes
10
+ * `value:`.
11
+ *
12
+ * Returns `undefined` on malformed input — the caller decides what
13
+ * to do with that (typically `return false`, mirroring the existing
14
+ * pattern-unwrap fail-closed contract).
15
+ *
16
+ * Used by {@link isClean} and {@link hasStagedChanges}; both ship
17
+ * with `PredicateShape<boolean>` in the registry so the bare/spread
18
+ * shape is identical at the type level too.
19
+ *
20
+ * @internal
21
+ */
22
+ declare function unwrapBooleanLeafArg(args: unknown): boolean | undefined;
23
+ /**
24
+ * Test-internal export of {@link unwrapBooleanLeafArg}. Module-private
25
+ * by intent; the `@internal` JSDoc tag (TypeScript ecosystem-standard)
26
+ * flags "not part of the public surface" and the underscore prefix
27
+ * mirrors the convention so external consumers can grep-discover it
28
+ * too. Direct unit tests pin malformed-input branches that are hard
29
+ * to drive via the engine end-to-end.
30
+ *
31
+ * @internal
32
+ */
33
+ export declare const _unwrapBooleanLeafArg: typeof unwrapBooleanLeafArg;
34
+ /**
35
+ * Resolved outcome of reading a string tracker value from
36
+ * `ctx.walkerState[key]`. Callers MUST distinguish the three cases:
37
+ *
38
+ * - `value` - the tracker resolved the value statically for this
39
+ * command ref. Use it directly.
40
+ * - `unknown` - the tracker observed a write it couldn't resolve
41
+ * statically (e.g. `git checkout $VAR`). The walker
42
+ * deliberately surfaces this to signal "a change
43
+ * happened but I can't name the new value". Falling
44
+ * through to `exec` would return the PRE-write
45
+ * value and silently defeat the walker's static
46
+ * tracking - exactly the case it exists for.
47
+ * Callers must apply their `onUnknown` policy.
48
+ * - `missing` - no tracker modifier fired for this dimension in
49
+ * this ref's scope (the walker threaded the
50
+ * tracker's initial sentinel, or `walkerState` has
51
+ * no key for this tracker at all). `exec` fallback
52
+ * is correct here: the shell's current state is the
53
+ * value the predicate wants.
54
+ *
55
+ * The three-way split requires cooperation from the tracker: its
56
+ * `initial` value must be distinct from its `unknown` sentinel, so
57
+ * the predicate can tell "no modifier fired" apart from "modifier
58
+ * fired and couldn't resolve". `branchTracker` does this via
59
+ * {@link NO_CHECKOUT_IN_CHAIN}. A tracker that reuses `"unknown"`
60
+ * for both initial and unknown would collapse these two cases -
61
+ * preserved here as `missing` for backward compatibility (the
62
+ * predicate then behaves as it did pre-U1, shelling out on any
63
+ * unknown).
64
+ */
65
+ export type WalkerStringResult = {
66
+ kind: "value";
67
+ value: string;
68
+ } | {
69
+ kind: "unknown";
70
+ } | {
71
+ kind: "missing";
72
+ };
73
+ /**
74
+ * Resolve a string tracker value from `ctx.walkerState[key]` into a
75
+ * three-state discriminated result. See {@link WalkerStringResult}
76
+ * for why callers must not conflate `unknown` with `missing`.
77
+ *
78
+ * `initialSentinel` is the tracker's initial value (distinct from
79
+ * its `unknown` sentinel). When `walkerState[key]` equals this
80
+ * sentinel, the result is `missing` - no modifier fired for this
81
+ * dimension in this ref's scope.
82
+ */
83
+ export declare function walkerString(ctx: PredicateContext, key: string, initialSentinel: string): WalkerStringResult;
84
+ /**
85
+ * `when.branch` - match the current git branch.
86
+ *
87
+ * Accepted arg shapes:
88
+ *
89
+ * ```ts
90
+ * when: { branch: /^main$/ } // single Pattern
91
+ * when: { branch: "^feat-" } // single Pattern (string)
92
+ * when: { branch: [/^main$/, /^master$/, /^trunk$/] } // Pattern[] (any-of)
93
+ * when: { branch: { pattern: /^main$/, onUnknown: "allow" } } // object form
94
+ * when: { branch: { pattern: [/^main$/, /^master$/], onUnknown: "allow" } }
95
+ * ```
96
+ *
97
+ * Array semantics: OR-of-matches (rule fires when the resolved
98
+ * branch matches ANY of the listed patterns). Empty arrays are
99
+ * invalid (rule skips); arrays containing non-Pattern values are
100
+ * invalid (rule skips).
101
+ *
102
+ * Resolution order:
103
+ * 1. `ctx.walkerState.branch` - set by the branch tracker when the
104
+ * current bash chain contains `git checkout` / `git switch`.
105
+ * Three outcomes:
106
+ * - value resolved statically (e.g. `git checkout main`) ->
107
+ * match the pattern against it.
108
+ * - `"unknown"` sentinel (dynamic checkout like `git checkout
109
+ * $VAR`) -> apply `onUnknown` policy. Do NOT fall through
110
+ * to exec: a `git branch --show-current` call here would
111
+ * return the PRE-checkout branch (the walker exists to
112
+ * track exactly this kind of in-chain change statically).
113
+ * - missing (no checkout in chain) -> fall through to exec.
114
+ * 2. `git branch --show-current` in `ctx.cwd`. Empty stdout is
115
+ * treated as "no branch" (detached HEAD) - the predicate falls
116
+ * back to `onUnknown`.
117
+ *
118
+ * `onUnknown` default is `"block"` (fail-closed): if we can't
119
+ * determine the branch, the predicate reports "match" so
120
+ * branch-gated rules still fire.
121
+ */
122
+ export declare const branch: PredicateHandler;
123
+ /**
124
+ * `when.upstream` - match the current branch's configured upstream.
125
+ *
126
+ * Accepted arg shapes: same as {@link branch}.
127
+ *
128
+ * Resolves via `git rev-parse --abbrev-ref @{upstream}`. A branch
129
+ * without an upstream set returns a non-zero exit; the predicate then
130
+ * applies `onUnknown`.
131
+ *
132
+ * No tracker today - upstream configuration isn't changed by in-chain
133
+ * git commands at a rate that justifies modelling it (and `git push
134
+ * -u origin main` changes it but only AFTER the push succeeds, which
135
+ * is past the point where a pre-execution guard would act). The
136
+ * per-tool_call exec cache ensures multiple upstream-gated rules share
137
+ * one git call.
138
+ *
139
+ * Runtime-cwd guard: `getUpstream` shells out at `ctx.cwd`. When the
140
+ * walker surfaces `ctx.walkerState.cwd === "unknown"` (dynamic
141
+ * `cd "$VAR/pkg"` the walker couldn't resolve), the exec would run
142
+ * against the pi session cwd — the wrong repo — and a user who opted
143
+ * into `onUnknown: "allow"` would get a silent fail-OPEN. The handler
144
+ * inlines a {@link cwdIsWalkerUnknown} check at the top and surfaces
145
+ * trinary `"unknown"`; the engine's leaf-level (outer) or block-level
146
+ * (inside `not:`) `onUnknown:` policy then projects to the right
147
+ * boolean (default `"block"` = fail-CLOSED).
148
+ *
149
+ * @see walkerUnknownCwdReason — compose the agent-facing reason text
150
+ * for the walker-unknown-cwd fail-closed branch in your rule's
151
+ * ReasonFn.
152
+ */
153
+ export declare const upstream: PredicateHandler;
154
+ /**
155
+ * Argument shape for {@link commitsAhead}.
156
+ *
157
+ * ```ts
158
+ * when: { commitsAhead: { eq: 1 } } // exactly one ahead
159
+ * when: { commitsAhead: { gt: 0 } } // at least one
160
+ * when: { commitsAhead: { lt: 5 } } // fewer than five
161
+ * when: { commitsAhead: { gt: 0, lt: 5 } } // 1..4
162
+ * when: { commitsAhead: { wrt: "origin/main", eq: 1 } }
163
+ * ```
164
+ *
165
+ * At least one of `eq` / `gt` / `lt` MUST be specified. All provided
166
+ * comparisons must pass (AND). `wrt` is the git revision expression
167
+ * to count commits behind (`git rev-list --count WRT..HEAD`); it
168
+ * defaults to `@{upstream}`.
169
+ */
170
+ export interface CommitsAheadArgs {
171
+ /** Git revision to count commits ahead of. Defaults to `@{upstream}`. */
172
+ wrt?: string;
173
+ /** Exact equality: `count === eq`. */
174
+ eq?: number;
175
+ /** Strict greater-than: `count > gt`. */
176
+ gt?: number;
177
+ /** Strict less-than: `count < lt`. */
178
+ lt?: number;
179
+ }
180
+ /**
181
+ * `when.commitsAhead` - match when commits-ahead-of-WRT satisfy every
182
+ * supplied comparator.
183
+ *
184
+ * Returns `false` (rule doesn't fire) when:
185
+ * - the arg shape isn't an object with at least one of `eq` / `gt`
186
+ * / `lt`,
187
+ * - the `git rev-list` call fails,
188
+ * - the comparator chain doesn't match.
189
+ *
190
+ * No `onUnknown` here: commits-ahead is a numeric comparator, not a
191
+ * pattern match, and "I couldn't learn the answer" arguably shouldn't
192
+ * fire a rule that's gated on a specific count. Authors who want the
193
+ * fail-closed behavior can layer `{ upstream: "..." }` first in the
194
+ * same `when` (AND semantics via the ADR's plugin predicates) - that
195
+ * handles the "no upstream" case with explicit `onUnknown`.
196
+ *
197
+ * Runtime-cwd guard: `getCommitsAhead` shells out at `ctx.cwd`. When
198
+ * the walker surfaces `ctx.walkerState.cwd === "unknown"`, the exec
199
+ * would run against the pi session cwd — wrong repo — and the
200
+ * `count === null` failure path returns `false`, silently skipping
201
+ * the rule (fail-OPEN). The handler inlines a
202
+ * {@link cwdIsWalkerUnknown} check at the top and surfaces trinary
203
+ * `"unknown"`; the engine's `onUnknown:` policy then projects to the
204
+ * right boolean (default `"block"` = fail-CLOSED, matching the policy
205
+ * used by the other runtime-cwd predicates in this plugin).
206
+ *
207
+ * @see walkerUnknownCwdReason — compose the agent-facing reason text
208
+ * for the walker-unknown-cwd fail-closed branch in your rule's
209
+ * ReasonFn.
210
+ * @see PiSteeringPredicates.commitsAhead — the registry entry that
211
+ * declares the bare / spreadBase shape this handler dispatches
212
+ * on.
213
+ */
214
+ export declare const commitsAhead: PredicateHandler<number | CommitsAheadArgs>;
215
+ /**
216
+ * `when.hasStagedChanges` - match on the presence / absence of staged
217
+ * changes in the repo at `ctx.cwd`.
218
+ *
219
+ * - `when: { hasStagedChanges: true }` - fires when there ARE staged
220
+ * changes.
221
+ * - `when: { hasStagedChanges: false }` - fires when there are NOT.
222
+ *
223
+ * Uses `git diff --cached --quiet`: exit 0 = no staged changes, exit
224
+ * 1 = staged changes exist. On any other exit / spawn failure, we
225
+ * conservatively report `false` - the caller can AND this with an
226
+ * `upstream` check if fail-closed behavior is needed.
227
+ *
228
+ * Runtime-cwd guard: the underlying `git diff --cached` call runs
229
+ * at `ctx.cwd`. When the walker surfaces `ctx.walkerState.cwd ===
230
+ * "unknown"` (dynamic `cd "$VAR/pkg"` the walker couldn't resolve),
231
+ * `ctx.cwd` falls back to the pre-cd ambient cwd — the PI session
232
+ * cwd, not the intended subpackage. The handler inlines a
233
+ * {@link cwdIsWalkerUnknown} check at the top and surfaces trinary
234
+ * `"unknown"`; the engine's `onUnknown:` policy then projects to the
235
+ * right boolean (default `"block"` = fail-CLOSED).
236
+ *
237
+ * @see walkerUnknownCwdReason — compose the agent-facing reason text
238
+ * for the walker-unknown-cwd fail-closed branch in your rule's
239
+ * ReasonFn.
240
+ * @see PiSteeringPredicates.hasStagedChanges — the registry entry
241
+ * that declares the bare / spreadBase shape this handler
242
+ * dispatches on.
243
+ */
244
+ export declare const hasStagedChanges: PredicateHandler<boolean | {
245
+ value: boolean;
246
+ onUnknown?: "allow" | "block";
247
+ }>;
248
+ /**
249
+ * `when.isClean` - match on the working tree's cleanliness at
250
+ * `ctx.cwd`.
251
+ *
252
+ * - `when: { isClean: true }` - fires when the working tree is
253
+ * clean (no unstaged, no untracked, no staged changes).
254
+ * - `when: { isClean: false }` - fires when the working tree is
255
+ * dirty.
256
+ *
257
+ * Uses `git status --porcelain`: empty stdout = clean. Non-zero exit
258
+ * returns `false` (unknown); pair with an `upstream` check for
259
+ * fail-closed behavior.
260
+ *
261
+ * Runtime-cwd guard: same rationale as {@link hasStagedChanges} — the
262
+ * handler inlines a {@link cwdIsWalkerUnknown} check at the top and
263
+ * surfaces trinary `"unknown"` when the walker couldn't statically
264
+ * resolve the command's effective cwd, rather than silently running
265
+ * `git status` at the pi session cwd.
266
+ *
267
+ * @see walkerUnknownCwdReason — compose the agent-facing reason text
268
+ * for the walker-unknown-cwd fail-closed branch in your rule's
269
+ * ReasonFn.
270
+ * @see PiSteeringPredicates.isClean — the registry entry that
271
+ * declares the bare / spreadBase shape this handler dispatches
272
+ * on.
273
+ */
274
+ export declare const isClean: PredicateHandler<boolean | {
275
+ value: boolean;
276
+ onUnknown?: "allow" | "block";
277
+ }>;
278
+ /**
279
+ * `when.remote` - match the repo's `origin` remote URL.
280
+ *
281
+ * Accepted arg shapes: same as {@link branch}. Useful for rules that
282
+ * should only fire in specific repos ("never force-push to
283
+ * github.com/org/prod").
284
+ *
285
+ * Resolves via `git config --get remote.origin.url`. Non-zero exit
286
+ * (no origin configured) falls back to `onUnknown`.
287
+ *
288
+ * Runtime-cwd guard: the handler inlines a {@link cwdIsWalkerUnknown}
289
+ * check at the top and surfaces trinary `"unknown"` when the walker
290
+ * couldn't statically resolve the command's effective cwd — querying
291
+ * the wrong repo's remote would silently mis-route a repo-gated rule.
292
+ * Same rationale as {@link hasStagedChanges}.
293
+ *
294
+ * @see walkerUnknownCwdReason — compose the agent-facing reason text
295
+ * for the walker-unknown-cwd fail-closed branch in your rule's
296
+ * ReasonFn.
297
+ */
298
+ export declare const remote: PredicateHandler;
299
+ /**
300
+ * Bundle of predicate handlers the git plugin registers under
301
+ * `Plugin.predicates`. Keys become the `when.<key>` slots rule authors
302
+ * see.
303
+ *
304
+ * Typed as `Record<string, AnyPredicateHandler>` to match
305
+ * {@link Plugin.predicates} at the registry boundary — each handler's
306
+ * concrete argument shape is preserved in its individual declaration
307
+ * above, and consumers can import `commitsAhead`, `isClean`, etc.
308
+ * directly when they want the narrow type.
309
+ */
310
+ export declare const predicates: Record<string, AnyPredicateHandler>;
311
+ export {};
312
+ //# sourceMappingURL=predicates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicates.d.ts","sourceRoot":"","sources":["../../../src/plugins/git/predicates.ts"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EACV,mBAAmB,EAEnB,gBAAgB,EAChB,gBAAgB,EAGjB,MAAM,iBAAiB,CAAC;AAsHzB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,iBAAS,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAUhE;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,6BAAuB,CAAC;AAiC1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,MAAM,GACtB,kBAAkB,CAsBpB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,MAAM,EAAE,gBAoBpB,CAAC;AAMF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,QAAQ,EAAE,gBAQtB,CAAC;AAMF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,YAAY,EAAE,gBAAgB,CAAC,MAAM,GAAG,gBAAgB,CAiCpE,CAAC;AAMF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,gBAAgB,EAAE,gBAAgB,CAC7C,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;CAAE,CAc5D,CAAC;AAMF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,OAAO,EAAE,gBAAgB,CACpC,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;CAAE,CAc5D,CAAC;AAMF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,MAAM,EAAE,gBAQpB,CAAC;AAMF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAO1D,CAAC"}