@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,580 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Part of pi-steering.
3
+ /**
4
+ * Predicate handlers for the git plugin.
5
+ *
6
+ * Each handler is a `PredicateHandler<A>` where `A` is the
7
+ * plugin-author-facing argument shape the rule passes under the
8
+ * matching `when.<key>` slot. See each handler's JSDoc for the
9
+ * accepted shape and worked examples.
10
+ *
11
+ * Evaluation strategy:
12
+ *
13
+ * - `branch` - read `ctx.walkerState.branch` first (set by
14
+ * the branch tracker on in-chain checkouts).
15
+ * If the tracker resolved statically, use
16
+ * that value. If the tracker reports
17
+ * `"unknown"` (dynamic checkout like
18
+ * `git checkout $VAR` that the walker
19
+ * couldn't resolve), apply `onUnknown`
20
+ * policy without falling back to `exec` -
21
+ * a `git branch --show-current` call would
22
+ * return the PRE-checkout branch and
23
+ * silently defeat the walker. If no
24
+ * tracker state exists (no checkout in
25
+ * chain), shell out via `git branch
26
+ * --show-current`.
27
+ * - `upstream` - no tracker today; always shell out via
28
+ * `git rev-parse --abbrev-ref @{upstream}`.
29
+ * Inlines a {@link cwdIsWalkerUnknown} guard
30
+ * so walker-unknown cwd surfaces trinary
31
+ * `"unknown"` instead of shelling against
32
+ * the pi session cwd — the engine's
33
+ * `onUnknown:` policy then projects to a
34
+ * definite verdict (default `"block"` =
35
+ * fail-CLOSED).
36
+ * - `commitsAhead` - shell out via `git rev-list --count`.
37
+ * Inlines the same walker-unknown guard as
38
+ * `upstream`.
39
+ * - `hasStagedChanges` - shell out via `git diff --cached --quiet`.
40
+ * - `isClean` - shell out via `git status --porcelain`.
41
+ * - `remote` - shell out via `git config --get
42
+ * remote.origin.url`.
43
+ *
44
+ * `ctx.exec` is memoized per `(cmd, args, cwd)` within one tool_call
45
+ * (see the evaluator's `createExecCache`) so multiple rules reading
46
+ * the same git state don't re-fork git.
47
+ *
48
+ * `onUnknown` policy for string-valued predicates (`branch`,
49
+ * `upstream`, `remote`): fail-closed by default. When the underlying
50
+ * query fails (not a repo, no upstream configured, ...), the predicate
51
+ * reports "match" so the rule fires. Rule authors opt into the
52
+ * "allow-through" behavior explicitly by passing
53
+ * `{ pattern, onUnknown: "allow" }`.
54
+ */
55
+ import { isPattern } from "../../internal/pattern-utils.js";
56
+ import { NO_CHECKOUT_IN_CHAIN } from "./branch-tracker.js";
57
+ import { getCommitsAhead, getRemoteUrl, getStagedChanges, getUpstream, getWorkingTreeClean, } from "./git-ops.js";
58
+ // ---------------------------------------------------------------------------
59
+ // Walker-unknown cwd guard (inline trinary)
60
+ // ---------------------------------------------------------------------------
61
+ /**
62
+ * Inline trinary guard for runtime-cwd predicates: returns `true` when
63
+ * the walker couldn't statically resolve the command's effective cwd
64
+ * (the cwd-tracker `"unknown"` sentinel is on `ctx.walkerState.cwd`),
65
+ * which signals to the caller that the handler should bail with
66
+ * `"unknown"` instead of querying the wrong repo.
67
+ *
68
+ * Each runtime-cwd handler in this module starts with:
69
+ *
70
+ * ```ts
71
+ * if (cwdIsWalkerUnknown(ctx)) return "unknown";
72
+ * ```
73
+ *
74
+ * Surfacing walker-unknown as trinary `"unknown"` lets the engine
75
+ * apply the leaf-level (or block-level, inside `not:`) `onUnknown:`
76
+ * policy. Default `"block"` is fail-CLOSED (the rule fires); a user
77
+ * with `onUnknown: "allow"` opts into fail-OPEN handling.
78
+ * Self-documenting + composable.
79
+ */
80
+ function cwdIsWalkerUnknown(ctx) {
81
+ return ctx.walkerState?.cwd === "unknown";
82
+ }
83
+ // ---------------------------------------------------------------------------
84
+ // Shared helpers
85
+ // ---------------------------------------------------------------------------
86
+ /**
87
+ * Normalize the shorthand forms accepted by the pattern-valued
88
+ * predicates (`branch`, `upstream`, `remote`) into a canonical
89
+ * `{ patterns, onUnknown }` shape:
90
+ *
91
+ * - `Pattern` -> `{ patterns: [pattern], onUnknown: "block" }`
92
+ * - `Pattern[]` (non-empty, all-Pattern) -> `{ patterns, onUnknown: "block" }`
93
+ * - `{ pattern: Pattern, onUnknown? }` -> object used as-is,
94
+ * `pattern` re-wrapped
95
+ * into a single-element
96
+ * array; `onUnknown`
97
+ * defaults to `"block"`.
98
+ * - `{ pattern: Pattern[], onUnknown? }` -> array preserved,
99
+ * same `onUnknown`
100
+ * handling.
101
+ *
102
+ * Array semantics are OR-of-matches: the rule fires when the input
103
+ * matches ANY of the listed patterns. Array form requires at least
104
+ * one pattern (empty arrays are invalid).
105
+ *
106
+ * Returning `null` means the author supplied something that isn't a
107
+ * valid value for this predicate (e.g. a bare number, an empty array,
108
+ * or an array containing a non-Pattern value); handlers treat that as
109
+ * a non-match and don't throw - invalid config shouldn't crash the
110
+ * evaluator, but it also shouldn't silently fire.
111
+ */
112
+ function unwrapPatternArg(value) {
113
+ // Shorthand: single Pattern.
114
+ if (isPattern(value)) {
115
+ return { patterns: [value], onUnknown: "block" };
116
+ }
117
+ // Shorthand: Pattern[] (must be non-empty + all-Pattern).
118
+ if (Array.isArray(value) && value.every(isPattern)) {
119
+ if (value.length === 0)
120
+ return null;
121
+ return { patterns: value, onUnknown: "block" };
122
+ }
123
+ // Object form: { pattern: Pattern | Pattern[]; onUnknown? }.
124
+ if (value !== null &&
125
+ typeof value === "object" &&
126
+ "pattern" in value) {
127
+ const obj = value;
128
+ const onUnknown = obj.onUnknown === "allow" ? "allow" : "block";
129
+ if (isPattern(obj.pattern)) {
130
+ return { patterns: [obj.pattern], onUnknown };
131
+ }
132
+ if (Array.isArray(obj.pattern) && obj.pattern.every(isPattern)) {
133
+ if (obj.pattern.length === 0)
134
+ return null;
135
+ return { patterns: obj.pattern, onUnknown };
136
+ }
137
+ }
138
+ return null;
139
+ }
140
+ /** Test a Pattern against a concrete string. */
141
+ function matchPattern(pattern, target) {
142
+ if (pattern instanceof RegExp)
143
+ return pattern.test(target);
144
+ return new RegExp(pattern).test(target);
145
+ }
146
+ /**
147
+ * Apply the predicate's `onUnknown` policy to a shell failure or
148
+ * tracker-unknown case. "block" means the predicate reports "match"
149
+ * (rule fires); "allow" means the predicate reports "no match" (rule
150
+ * skips). Fail-closed default.
151
+ */
152
+ function unknownVerdict(onUnknown) {
153
+ return onUnknown === "block";
154
+ }
155
+ /**
156
+ * Unwrap the boolean payload from a {@link PredicateShape}<boolean>
157
+ * argument. Accepts the bare form (`true` / `false`) and the
158
+ * spread form (`{ value: true, onUnknown? }` /
159
+ * `{ value: false, onUnknown? }`); the engine's `readLeafOnUnknown`
160
+ * reads any `onUnknown:` sibling and `projectVerdict` applies the
161
+ * policy to the handler's `"unknown"` returns. The handler itself
162
+ * treats `onUnknown:` as an opaque sibling field and only consumes
163
+ * `value:`.
164
+ *
165
+ * Returns `undefined` on malformed input — the caller decides what
166
+ * to do with that (typically `return false`, mirroring the existing
167
+ * pattern-unwrap fail-closed contract).
168
+ *
169
+ * Used by {@link isClean} and {@link hasStagedChanges}; both ship
170
+ * with `PredicateShape<boolean>` in the registry so the bare/spread
171
+ * shape is identical at the type level too.
172
+ *
173
+ * @internal
174
+ */
175
+ function unwrapBooleanLeafArg(args) {
176
+ if (typeof args === "boolean")
177
+ return args;
178
+ if (args !== null &&
179
+ typeof args === "object" &&
180
+ typeof args.value === "boolean") {
181
+ return args.value;
182
+ }
183
+ return undefined;
184
+ }
185
+ /**
186
+ * Test-internal export of {@link unwrapBooleanLeafArg}. Module-private
187
+ * by intent; the `@internal` JSDoc tag (TypeScript ecosystem-standard)
188
+ * flags "not part of the public surface" and the underscore prefix
189
+ * mirrors the convention so external consumers can grep-discover it
190
+ * too. Direct unit tests pin malformed-input branches that are hard
191
+ * to drive via the engine end-to-end.
192
+ *
193
+ * @internal
194
+ */
195
+ export const _unwrapBooleanLeafArg = unwrapBooleanLeafArg;
196
+ /**
197
+ * Direct one-shot git exec used only by the `branch` predicate's
198
+ * tracker-missing fallback (the predicate's three-way tracker
199
+ * discrimination stays in predicate-land; see the `branch` JSDoc
200
+ * below AND `./git-ops.ts` file header "Branch caveat" for why
201
+ * `getBranch` is NOT called here).
202
+ * Other predicates delegate to helpers in `./git-ops.ts` and don't
203
+ * need this.
204
+ *
205
+ * Mirrors the failure-collapse contract of `tryGit` in git-ops:
206
+ * non-zero exit, spawn error, or thrown exception → `null`.
207
+ */
208
+ async function tryExec(ctx, cmd, args, cwd) {
209
+ try {
210
+ const res = await ctx.exec(cmd, [...args], cwd !== undefined ? { cwd } : undefined);
211
+ if (res.exitCode !== 0)
212
+ return null;
213
+ return res.stdout.trim();
214
+ }
215
+ catch {
216
+ return null;
217
+ }
218
+ }
219
+ /**
220
+ * Resolve a string tracker value from `ctx.walkerState[key]` into a
221
+ * three-state discriminated result. See {@link WalkerStringResult}
222
+ * for why callers must not conflate `unknown` with `missing`.
223
+ *
224
+ * `initialSentinel` is the tracker's initial value (distinct from
225
+ * its `unknown` sentinel). When `walkerState[key]` equals this
226
+ * sentinel, the result is `missing` - no modifier fired for this
227
+ * dimension in this ref's scope.
228
+ */
229
+ export function walkerString(ctx, key, initialSentinel) {
230
+ // Guard against a tracker that reuses `"unknown"` as its initial
231
+ // sentinel. Accepting such a value here would silently collapse the
232
+ // three-way discrimination back into the pre-U1 two-step: the
233
+ // `missing` branch would swallow genuine dynamic-checkout signals
234
+ // and the predicate would exec-fallback onto the PRE-checkout
235
+ // branch — exactly the bug U1 exists to prevent. The JSDoc on
236
+ // WalkerStringResult documents this; the assertion makes the
237
+ // contract un-foot-shootable for new tracker authors.
238
+ if (initialSentinel === "unknown") {
239
+ throw new Error(`[pi-steering/git] walkerString: tracker initialSentinel cannot be ` +
240
+ `"unknown" — it's reserved for the unresolvable-dynamic-value ` +
241
+ `signal. Use a distinct initial value (e.g. "" or a sentinel ` +
242
+ `like NO_CHECKOUT_IN_CHAIN). See WalkerStringResult JSDoc.`);
243
+ }
244
+ const v = ctx.walkerState?.[key];
245
+ if (typeof v !== "string")
246
+ return { kind: "missing" };
247
+ if (v === initialSentinel)
248
+ return { kind: "missing" };
249
+ if (v === "unknown")
250
+ return { kind: "unknown" };
251
+ return { kind: "value", value: v };
252
+ }
253
+ // ---------------------------------------------------------------------------
254
+ // branch
255
+ // ---------------------------------------------------------------------------
256
+ /**
257
+ * `when.branch` - match the current git branch.
258
+ *
259
+ * Accepted arg shapes:
260
+ *
261
+ * ```ts
262
+ * when: { branch: /^main$/ } // single Pattern
263
+ * when: { branch: "^feat-" } // single Pattern (string)
264
+ * when: { branch: [/^main$/, /^master$/, /^trunk$/] } // Pattern[] (any-of)
265
+ * when: { branch: { pattern: /^main$/, onUnknown: "allow" } } // object form
266
+ * when: { branch: { pattern: [/^main$/, /^master$/], onUnknown: "allow" } }
267
+ * ```
268
+ *
269
+ * Array semantics: OR-of-matches (rule fires when the resolved
270
+ * branch matches ANY of the listed patterns). Empty arrays are
271
+ * invalid (rule skips); arrays containing non-Pattern values are
272
+ * invalid (rule skips).
273
+ *
274
+ * Resolution order:
275
+ * 1. `ctx.walkerState.branch` - set by the branch tracker when the
276
+ * current bash chain contains `git checkout` / `git switch`.
277
+ * Three outcomes:
278
+ * - value resolved statically (e.g. `git checkout main`) ->
279
+ * match the pattern against it.
280
+ * - `"unknown"` sentinel (dynamic checkout like `git checkout
281
+ * $VAR`) -> apply `onUnknown` policy. Do NOT fall through
282
+ * to exec: a `git branch --show-current` call here would
283
+ * return the PRE-checkout branch (the walker exists to
284
+ * track exactly this kind of in-chain change statically).
285
+ * - missing (no checkout in chain) -> fall through to exec.
286
+ * 2. `git branch --show-current` in `ctx.cwd`. Empty stdout is
287
+ * treated as "no branch" (detached HEAD) - the predicate falls
288
+ * back to `onUnknown`.
289
+ *
290
+ * `onUnknown` default is `"block"` (fail-closed): if we can't
291
+ * determine the branch, the predicate reports "match" so
292
+ * branch-gated rules still fire.
293
+ */
294
+ export const branch = async (value, ctx) => {
295
+ const arg = unwrapPatternArg(value);
296
+ if (arg === null)
297
+ return false;
298
+ // 1. Walker state (tracker-resolved mid-command).
299
+ const fromWalker = walkerString(ctx, "branch", NO_CHECKOUT_IN_CHAIN);
300
+ if (fromWalker.kind === "value") {
301
+ return arg.patterns.some((p) => matchPattern(p, fromWalker.value));
302
+ }
303
+ if (fromWalker.kind === "unknown") {
304
+ // Dynamic in-chain checkout. Exec would return the PRE-checkout
305
+ // branch, which is the case the walker exists to catch. Apply
306
+ // the predicate's `onUnknown` policy instead of falling through.
307
+ return unknownVerdict(arg.onUnknown);
308
+ }
309
+ // 2. Shell out (tracker saw no in-chain checkout).
310
+ const out = await tryExec(ctx, "git", ["branch", "--show-current"], ctx.cwd);
311
+ if (out === null || out.length === 0)
312
+ return unknownVerdict(arg.onUnknown);
313
+ return arg.patterns.some((p) => matchPattern(p, out));
314
+ };
315
+ // ---------------------------------------------------------------------------
316
+ // upstream
317
+ // ---------------------------------------------------------------------------
318
+ /**
319
+ * `when.upstream` - match the current branch's configured upstream.
320
+ *
321
+ * Accepted arg shapes: same as {@link branch}.
322
+ *
323
+ * Resolves via `git rev-parse --abbrev-ref @{upstream}`. A branch
324
+ * without an upstream set returns a non-zero exit; the predicate then
325
+ * applies `onUnknown`.
326
+ *
327
+ * No tracker today - upstream configuration isn't changed by in-chain
328
+ * git commands at a rate that justifies modelling it (and `git push
329
+ * -u origin main` changes it but only AFTER the push succeeds, which
330
+ * is past the point where a pre-execution guard would act). The
331
+ * per-tool_call exec cache ensures multiple upstream-gated rules share
332
+ * one git call.
333
+ *
334
+ * Runtime-cwd guard: `getUpstream` shells out at `ctx.cwd`. When the
335
+ * walker surfaces `ctx.walkerState.cwd === "unknown"` (dynamic
336
+ * `cd "$VAR/pkg"` the walker couldn't resolve), the exec would run
337
+ * against the pi session cwd — the wrong repo — and a user who opted
338
+ * into `onUnknown: "allow"` would get a silent fail-OPEN. The handler
339
+ * inlines a {@link cwdIsWalkerUnknown} check at the top and surfaces
340
+ * trinary `"unknown"`; the engine's leaf-level (outer) or block-level
341
+ * (inside `not:`) `onUnknown:` policy then projects to the right
342
+ * boolean (default `"block"` = fail-CLOSED).
343
+ *
344
+ * @see walkerUnknownCwdReason — compose the agent-facing reason text
345
+ * for the walker-unknown-cwd fail-closed branch in your rule's
346
+ * ReasonFn.
347
+ */
348
+ export const upstream = async (value, ctx) => {
349
+ if (cwdIsWalkerUnknown(ctx))
350
+ return "unknown";
351
+ const arg = unwrapPatternArg(value);
352
+ if (arg === null)
353
+ return false;
354
+ const out = await getUpstream(ctx);
355
+ if (out === null)
356
+ return unknownVerdict(arg.onUnknown);
357
+ return arg.patterns.some((p) => matchPattern(p, out));
358
+ };
359
+ /**
360
+ * `when.commitsAhead` - match when commits-ahead-of-WRT satisfy every
361
+ * supplied comparator.
362
+ *
363
+ * Returns `false` (rule doesn't fire) when:
364
+ * - the arg shape isn't an object with at least one of `eq` / `gt`
365
+ * / `lt`,
366
+ * - the `git rev-list` call fails,
367
+ * - the comparator chain doesn't match.
368
+ *
369
+ * No `onUnknown` here: commits-ahead is a numeric comparator, not a
370
+ * pattern match, and "I couldn't learn the answer" arguably shouldn't
371
+ * fire a rule that's gated on a specific count. Authors who want the
372
+ * fail-closed behavior can layer `{ upstream: "..." }` first in the
373
+ * same `when` (AND semantics via the ADR's plugin predicates) - that
374
+ * handles the "no upstream" case with explicit `onUnknown`.
375
+ *
376
+ * Runtime-cwd guard: `getCommitsAhead` shells out at `ctx.cwd`. When
377
+ * the walker surfaces `ctx.walkerState.cwd === "unknown"`, the exec
378
+ * would run against the pi session cwd — wrong repo — and the
379
+ * `count === null` failure path returns `false`, silently skipping
380
+ * the rule (fail-OPEN). The handler inlines a
381
+ * {@link cwdIsWalkerUnknown} check at the top and surfaces trinary
382
+ * `"unknown"`; the engine's `onUnknown:` policy then projects to the
383
+ * right boolean (default `"block"` = fail-CLOSED, matching the policy
384
+ * used by the other runtime-cwd predicates in this plugin).
385
+ *
386
+ * @see walkerUnknownCwdReason — compose the agent-facing reason text
387
+ * for the walker-unknown-cwd fail-closed branch in your rule's
388
+ * ReasonFn.
389
+ * @see PiSteeringPredicates.commitsAhead — the registry entry that
390
+ * declares the bare / spreadBase shape this handler dispatches
391
+ * on.
392
+ */
393
+ export const commitsAhead = async (args, ctx) => {
394
+ if (cwdIsWalkerUnknown(ctx))
395
+ return "unknown";
396
+ // Schema advertises `PredicateShape<number, { eq?, gt?, lt?, wrt? }>`
397
+ // — bare-number `commitsAhead: N` is sugar for `{ eq: N }`.
398
+ let eq;
399
+ let gt;
400
+ let lt;
401
+ let wrt = "@{upstream}";
402
+ if (typeof args === "number") {
403
+ eq = args;
404
+ }
405
+ else if (args !== null && typeof args === "object") {
406
+ const shape = args;
407
+ eq = shape.eq;
408
+ gt = shape.gt;
409
+ lt = shape.lt;
410
+ wrt = shape.wrt ?? "@{upstream}";
411
+ }
412
+ else {
413
+ return false;
414
+ }
415
+ if (eq === undefined && gt === undefined && lt === undefined) {
416
+ return false;
417
+ }
418
+ const count = await getCommitsAhead(ctx, wrt);
419
+ if (count === null)
420
+ return false;
421
+ if (eq !== undefined && count !== eq)
422
+ return false;
423
+ if (gt !== undefined && !(count > gt))
424
+ return false;
425
+ if (lt !== undefined && !(count < lt))
426
+ return false;
427
+ return true;
428
+ };
429
+ // ---------------------------------------------------------------------------
430
+ // hasStagedChanges
431
+ // ---------------------------------------------------------------------------
432
+ /**
433
+ * `when.hasStagedChanges` - match on the presence / absence of staged
434
+ * changes in the repo at `ctx.cwd`.
435
+ *
436
+ * - `when: { hasStagedChanges: true }` - fires when there ARE staged
437
+ * changes.
438
+ * - `when: { hasStagedChanges: false }` - fires when there are NOT.
439
+ *
440
+ * Uses `git diff --cached --quiet`: exit 0 = no staged changes, exit
441
+ * 1 = staged changes exist. On any other exit / spawn failure, we
442
+ * conservatively report `false` - the caller can AND this with an
443
+ * `upstream` check if fail-closed behavior is needed.
444
+ *
445
+ * Runtime-cwd guard: the underlying `git diff --cached` call runs
446
+ * at `ctx.cwd`. When the walker surfaces `ctx.walkerState.cwd ===
447
+ * "unknown"` (dynamic `cd "$VAR/pkg"` the walker couldn't resolve),
448
+ * `ctx.cwd` falls back to the pre-cd ambient cwd — the PI session
449
+ * cwd, not the intended subpackage. The handler inlines a
450
+ * {@link cwdIsWalkerUnknown} check at the top and surfaces trinary
451
+ * `"unknown"`; the engine's `onUnknown:` policy then projects to the
452
+ * right boolean (default `"block"` = fail-CLOSED).
453
+ *
454
+ * @see walkerUnknownCwdReason — compose the agent-facing reason text
455
+ * for the walker-unknown-cwd fail-closed branch in your rule's
456
+ * ReasonFn.
457
+ * @see PiSteeringPredicates.hasStagedChanges — the registry entry
458
+ * that declares the bare / spreadBase shape this handler
459
+ * dispatches on.
460
+ */
461
+ export const hasStagedChanges = async (args, ctx) => {
462
+ if (cwdIsWalkerUnknown(ctx))
463
+ return "unknown";
464
+ // Schema's `PredicateShape<boolean>` auto-detects spreadBase to
465
+ // `{ value: boolean; onUnknown? }`; unwrap consumes `value:` only.
466
+ // Authors attach modifiers via `{ value: true, onUnknown: "allow" }`;
467
+ // the engine reads any `onUnknown:` sibling via readLeafOnUnknown
468
+ // and projects the handler's `"unknown"` returns under that policy
469
+ // (the handler itself treats `onUnknown:` as an opaque sibling field).
470
+ const expected = unwrapBooleanLeafArg(args);
471
+ if (expected === undefined)
472
+ return false;
473
+ const state = await getStagedChanges(ctx);
474
+ if (state === null)
475
+ return false; // unknown — don't fire
476
+ return expected === state;
477
+ };
478
+ // ---------------------------------------------------------------------------
479
+ // isClean
480
+ // ---------------------------------------------------------------------------
481
+ /**
482
+ * `when.isClean` - match on the working tree's cleanliness at
483
+ * `ctx.cwd`.
484
+ *
485
+ * - `when: { isClean: true }` - fires when the working tree is
486
+ * clean (no unstaged, no untracked, no staged changes).
487
+ * - `when: { isClean: false }` - fires when the working tree is
488
+ * dirty.
489
+ *
490
+ * Uses `git status --porcelain`: empty stdout = clean. Non-zero exit
491
+ * returns `false` (unknown); pair with an `upstream` check for
492
+ * fail-closed behavior.
493
+ *
494
+ * Runtime-cwd guard: same rationale as {@link hasStagedChanges} — the
495
+ * handler inlines a {@link cwdIsWalkerUnknown} check at the top and
496
+ * surfaces trinary `"unknown"` when the walker couldn't statically
497
+ * resolve the command's effective cwd, rather than silently running
498
+ * `git status` at the pi session cwd.
499
+ *
500
+ * @see walkerUnknownCwdReason — compose the agent-facing reason text
501
+ * for the walker-unknown-cwd fail-closed branch in your rule's
502
+ * ReasonFn.
503
+ * @see PiSteeringPredicates.isClean — the registry entry that
504
+ * declares the bare / spreadBase shape this handler dispatches
505
+ * on.
506
+ */
507
+ export const isClean = async (args, ctx) => {
508
+ if (cwdIsWalkerUnknown(ctx))
509
+ return "unknown";
510
+ // Schema's `PredicateShape<boolean>` auto-detects spreadBase to
511
+ // `{ value: boolean; onUnknown? }`; unwrap consumes `value:` only.
512
+ // Authors attach modifiers via `{ value: true, onUnknown: "allow" }`;
513
+ // the engine reads any `onUnknown:` sibling via readLeafOnUnknown
514
+ // and projects the handler's `"unknown"` returns under that policy
515
+ // (the handler itself treats `onUnknown:` as an opaque sibling field).
516
+ const expected = unwrapBooleanLeafArg(args);
517
+ if (expected === undefined)
518
+ return false;
519
+ const clean = await getWorkingTreeClean(ctx);
520
+ if (clean === null)
521
+ return false;
522
+ return expected === clean;
523
+ };
524
+ // ---------------------------------------------------------------------------
525
+ // remote
526
+ // ---------------------------------------------------------------------------
527
+ /**
528
+ * `when.remote` - match the repo's `origin` remote URL.
529
+ *
530
+ * Accepted arg shapes: same as {@link branch}. Useful for rules that
531
+ * should only fire in specific repos ("never force-push to
532
+ * github.com/org/prod").
533
+ *
534
+ * Resolves via `git config --get remote.origin.url`. Non-zero exit
535
+ * (no origin configured) falls back to `onUnknown`.
536
+ *
537
+ * Runtime-cwd guard: the handler inlines a {@link cwdIsWalkerUnknown}
538
+ * check at the top and surfaces trinary `"unknown"` when the walker
539
+ * couldn't statically resolve the command's effective cwd — querying
540
+ * the wrong repo's remote would silently mis-route a repo-gated rule.
541
+ * Same rationale as {@link hasStagedChanges}.
542
+ *
543
+ * @see walkerUnknownCwdReason — compose the agent-facing reason text
544
+ * for the walker-unknown-cwd fail-closed branch in your rule's
545
+ * ReasonFn.
546
+ */
547
+ export const remote = async (value, ctx) => {
548
+ if (cwdIsWalkerUnknown(ctx))
549
+ return "unknown";
550
+ const arg = unwrapPatternArg(value);
551
+ if (arg === null)
552
+ return false;
553
+ const out = await getRemoteUrl(ctx);
554
+ if (out === null)
555
+ return unknownVerdict(arg.onUnknown);
556
+ return arg.patterns.some((p) => matchPattern(p, out));
557
+ };
558
+ // ---------------------------------------------------------------------------
559
+ // Plugin-level export
560
+ // ---------------------------------------------------------------------------
561
+ /**
562
+ * Bundle of predicate handlers the git plugin registers under
563
+ * `Plugin.predicates`. Keys become the `when.<key>` slots rule authors
564
+ * see.
565
+ *
566
+ * Typed as `Record<string, AnyPredicateHandler>` to match
567
+ * {@link Plugin.predicates} at the registry boundary — each handler's
568
+ * concrete argument shape is preserved in its individual declaration
569
+ * above, and consumers can import `commitsAhead`, `isClean`, etc.
570
+ * directly when they want the narrow type.
571
+ */
572
+ export const predicates = {
573
+ branch,
574
+ upstream,
575
+ commitsAhead,
576
+ hasStagedChanges,
577
+ isClean,
578
+ remote,
579
+ };
580
+ //# sourceMappingURL=predicates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicates.js","sourceRoot":"","sources":["../../../src/plugins/git/predicates.ts"],"names":[],"mappings":"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"}