@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.
- package/CHANGELOG.md +36 -0
- package/LICENSE +29 -0
- package/README.md +920 -0
- package/dist/__test-helpers__.d.ts +95 -0
- package/dist/__test-helpers__.d.ts.map +1 -0
- package/dist/__test-helpers__.js +174 -0
- package/dist/__test-helpers__.js.map +1 -0
- package/dist/bin/pi-steering.d.ts +9 -0
- package/dist/bin/pi-steering.d.ts.map +1 -0
- package/dist/bin/pi-steering.js +506 -0
- package/dist/bin/pi-steering.js.map +1 -0
- package/dist/compat.d.ts +50 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +180 -0
- package/dist/compat.js.map +1 -0
- package/dist/defaults.d.ts +61 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +106 -0
- package/dist/defaults.js.map +1 -0
- package/dist/define-config.d.ts +235 -0
- package/dist/define-config.d.ts.map +1 -0
- package/dist/define-config.js +118 -0
- package/dist/define-config.js.map +1 -0
- package/dist/define-predicate.d.ts +49 -0
- package/dist/define-predicate.d.ts.map +1 -0
- package/dist/define-predicate.js +35 -0
- package/dist/define-predicate.js.map +1 -0
- package/dist/evaluator-internals/context.d.ts +186 -0
- package/dist/evaluator-internals/context.d.ts.map +1 -0
- package/dist/evaluator-internals/context.js +219 -0
- package/dist/evaluator-internals/context.js.map +1 -0
- package/dist/evaluator-internals/override.d.ts +19 -0
- package/dist/evaluator-internals/override.d.ts.map +1 -0
- package/dist/evaluator-internals/override.js +79 -0
- package/dist/evaluator-internals/override.js.map +1 -0
- package/dist/evaluator-internals/predicates.d.ts +152 -0
- package/dist/evaluator-internals/predicates.d.ts.map +1 -0
- package/dist/evaluator-internals/predicates.js +849 -0
- package/dist/evaluator-internals/predicates.js.map +1 -0
- package/dist/evaluator-internals/speculative-synthesis.d.ts +102 -0
- package/dist/evaluator-internals/speculative-synthesis.d.ts.map +1 -0
- package/dist/evaluator-internals/speculative-synthesis.js +101 -0
- package/dist/evaluator-internals/speculative-synthesis.js.map +1 -0
- package/dist/evaluator.d.ts +101 -0
- package/dist/evaluator.d.ts.map +1 -0
- package/dist/evaluator.js +714 -0
- package/dist/evaluator.js.map +1 -0
- package/dist/helpers/walker-unknown-cwd-reason.d.ts +68 -0
- package/dist/helpers/walker-unknown-cwd-reason.d.ts.map +1 -0
- package/dist/helpers/walker-unknown-cwd-reason.js +73 -0
- package/dist/helpers/walker-unknown-cwd-reason.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/drop-unused-observers.d.ts +43 -0
- package/dist/internal/drop-unused-observers.d.ts.map +1 -0
- package/dist/internal/drop-unused-observers.js +50 -0
- package/dist/internal/drop-unused-observers.js.map +1 -0
- package/dist/internal/finalize-plugin-state.d.ts +22 -0
- package/dist/internal/finalize-plugin-state.d.ts.map +1 -0
- package/dist/internal/finalize-plugin-state.js +14 -0
- package/dist/internal/finalize-plugin-state.js.map +1 -0
- package/dist/internal/merge-observers.d.ts +30 -0
- package/dist/internal/merge-observers.d.ts.map +1 -0
- package/dist/internal/merge-observers.js +27 -0
- package/dist/internal/merge-observers.js.map +1 -0
- package/dist/internal/pattern-utils.d.ts +33 -0
- package/dist/internal/pattern-utils.d.ts.map +1 -0
- package/dist/internal/pattern-utils.js +20 -0
- package/dist/internal/pattern-utils.js.map +1 -0
- package/dist/internal/ref-text.d.ts +11 -0
- package/dist/internal/ref-text.d.ts.map +1 -0
- package/dist/internal/ref-text.js +15 -0
- package/dist/internal/ref-text.js.map +1 -0
- package/dist/internal/session-runtime.d.ts +44 -0
- package/dist/internal/session-runtime.d.ts.map +1 -0
- package/dist/internal/session-runtime.js +143 -0
- package/dist/internal/session-runtime.js.map +1 -0
- package/dist/internal/watch-matcher.d.ts +56 -0
- package/dist/internal/watch-matcher.d.ts.map +1 -0
- package/dist/internal/watch-matcher.js +179 -0
- package/dist/internal/watch-matcher.js.map +1 -0
- package/dist/loader.d.ts +97 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +527 -0
- package/dist/loader.js.map +1 -0
- package/dist/observer-dispatcher.d.ts +69 -0
- package/dist/observer-dispatcher.d.ts.map +1 -0
- package/dist/observer-dispatcher.js +184 -0
- package/dist/observer-dispatcher.js.map +1 -0
- package/dist/plugin-merger.d.ts +175 -0
- package/dist/plugin-merger.d.ts.map +1 -0
- package/dist/plugin-merger.js +450 -0
- package/dist/plugin-merger.js.map +1 -0
- package/dist/plugins/git/branch-tracker.d.ts +85 -0
- package/dist/plugins/git/branch-tracker.d.ts.map +1 -0
- package/dist/plugins/git/branch-tracker.js +181 -0
- package/dist/plugins/git/branch-tracker.js.map +1 -0
- package/dist/plugins/git/cwd-extensions.d.ts +10 -0
- package/dist/plugins/git/cwd-extensions.d.ts.map +1 -0
- package/dist/plugins/git/cwd-extensions.js +155 -0
- package/dist/plugins/git/cwd-extensions.js.map +1 -0
- package/dist/plugins/git/git-ops.d.ts +89 -0
- package/dist/plugins/git/git-ops.d.ts.map +1 -0
- package/dist/plugins/git/git-ops.js +107 -0
- package/dist/plugins/git/git-ops.js.map +1 -0
- package/dist/plugins/git/index.d.ts +225 -0
- package/dist/plugins/git/index.d.ts.map +1 -0
- package/dist/plugins/git/index.js +52 -0
- package/dist/plugins/git/index.js.map +1 -0
- package/dist/plugins/git/predicates.d.ts +312 -0
- package/dist/plugins/git/predicates.d.ts.map +1 -0
- package/dist/plugins/git/predicates.js +580 -0
- package/dist/plugins/git/predicates.js.map +1 -0
- package/dist/plugins/git/rules.d.ts +209 -0
- package/dist/plugins/git/rules.d.ts.map +1 -0
- package/dist/plugins/git/rules.js +267 -0
- package/dist/plugins/git/rules.js.map +1 -0
- package/dist/schema.d.ts +1799 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +4 -0
- package/dist/schema.js.map +1 -0
- package/dist/testing/index.d.ts +621 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +747 -0
- package/dist/testing/index.js.map +1 -0
- package/examples/README.md +83 -0
- package/examples/combined-git-discipline/README.md +52 -0
- package/examples/combined-git-discipline/node_modules/.bin/pi-steering +43 -0
- package/examples/combined-git-discipline/package.json +18 -0
- package/examples/combined-git-discipline/steering.json +27 -0
- package/examples/combined-git-discipline/steering.test.ts +42 -0
- package/examples/combined-git-discipline/steering.ts +64 -0
- package/examples/combined-git-discipline/tsconfig.json +7 -0
- package/examples/draft-prs-only/README.md +42 -0
- package/examples/draft-prs-only/node_modules/.bin/pi-steering +43 -0
- package/examples/draft-prs-only/package.json +18 -0
- package/examples/draft-prs-only/steering.json +12 -0
- package/examples/draft-prs-only/steering.test.ts +48 -0
- package/examples/draft-prs-only/steering.ts +36 -0
- package/examples/draft-prs-only/tsconfig.json +7 -0
- package/examples/dynamic-reason-runtime-cwd/README.md +148 -0
- package/examples/dynamic-reason-runtime-cwd/node_modules/.bin/pi-steering +43 -0
- package/examples/dynamic-reason-runtime-cwd/package.json +18 -0
- package/examples/dynamic-reason-runtime-cwd/steering.test.ts +130 -0
- package/examples/dynamic-reason-runtime-cwd/steering.ts +82 -0
- package/examples/dynamic-reason-runtime-cwd/tsconfig.json +7 -0
- package/examples/force-push-strict/README.md +75 -0
- package/examples/force-push-strict/node_modules/.bin/pi-steering +43 -0
- package/examples/force-push-strict/package.json +18 -0
- package/examples/force-push-strict/steering.json +12 -0
- package/examples/force-push-strict/steering.test.ts +51 -0
- package/examples/force-push-strict/steering.ts +54 -0
- package/examples/force-push-strict/tsconfig.json +7 -0
- package/examples/no-amend/README.md +52 -0
- package/examples/no-amend/node_modules/.bin/pi-steering +43 -0
- package/examples/no-amend/package.json +18 -0
- package/examples/no-amend/steering.cwd-scoped.json +12 -0
- package/examples/no-amend/steering.json +11 -0
- package/examples/no-amend/steering.test.ts +49 -0
- package/examples/no-amend/steering.ts +38 -0
- package/examples/no-amend/tsconfig.json +7 -0
- package/examples/work-item-plugin/README.md +103 -0
- package/examples/work-item-plugin/node_modules/.bin/pi-steering +43 -0
- package/examples/work-item-plugin/package.json +19 -0
- package/examples/work-item-plugin/src/index.test.ts +168 -0
- package/examples/work-item-plugin/src/index.ts +122 -0
- package/examples/work-item-plugin/src/observers/npm-test-tracker.test.ts +95 -0
- package/examples/work-item-plugin/src/observers/npm-test-tracker.ts +88 -0
- package/examples/work-item-plugin/src/observers/retest-required-tracker.test.ts +81 -0
- package/examples/work-item-plugin/src/observers/retest-required-tracker.ts +81 -0
- package/examples/work-item-plugin/src/predicates/work-item-format.test.ts +157 -0
- package/examples/work-item-plugin/src/predicates/work-item-format.ts +99 -0
- package/examples/work-item-plugin/src/rules/commit-description-check.test.ts +107 -0
- package/examples/work-item-plugin/src/rules/commit-description-check.ts +83 -0
- package/examples/work-item-plugin/src/rules/commit-requires-work-item.test.ts +79 -0
- package/examples/work-item-plugin/src/rules/commit-requires-work-item.ts +56 -0
- package/examples/work-item-plugin/src/rules/push-requires-tests.test.ts +245 -0
- package/examples/work-item-plugin/src/rules/push-requires-tests.ts +62 -0
- package/examples/work-item-plugin/tsconfig.json +8 -0
- package/package.json +88 -0
- package/skills/steering-authoring/SKILL.md +102 -0
- package/src/INVARIANTS.md +116 -0
- package/src/__test-helpers__.ts +243 -0
- package/src/bin/pi-steering.test.ts +920 -0
- package/src/bin/pi-steering.ts +584 -0
- package/src/compat.test.ts +431 -0
- package/src/compat.ts +282 -0
- package/src/defaults.test.ts +585 -0
- package/src/defaults.ts +148 -0
- package/src/define-config.test.ts +888 -0
- package/src/define-config.ts +375 -0
- package/src/define-predicate.test.ts +70 -0
- package/src/define-predicate.ts +57 -0
- package/src/evaluator-internals/context.ts +290 -0
- package/src/evaluator-internals/override.test.ts +99 -0
- package/src/evaluator-internals/override.ts +83 -0
- package/src/evaluator-internals/predicates.ts +1037 -0
- package/src/evaluator-internals/speculative-synthesis.test.ts +411 -0
- package/src/evaluator-internals/speculative-synthesis.ts +199 -0
- package/src/evaluator.test.ts +6296 -0
- package/src/evaluator.ts +1106 -0
- package/src/factory-time-load.test.ts +630 -0
- package/src/helpers/walker-unknown-cwd-reason.test.ts +73 -0
- package/src/helpers/walker-unknown-cwd-reason.ts +83 -0
- package/src/index.test.ts +836 -0
- package/src/index.ts +229 -0
- package/src/internal/drop-unused-observers.test.ts +141 -0
- package/src/internal/drop-unused-observers.ts +81 -0
- package/src/internal/finalize-plugin-state.ts +43 -0
- package/src/internal/merge-observers.ts +51 -0
- package/src/internal/pattern-utils.test.ts +52 -0
- package/src/internal/pattern-utils.ts +38 -0
- package/src/internal/ref-text.test.ts +54 -0
- package/src/internal/ref-text.ts +17 -0
- package/src/internal/session-runtime.test.ts +629 -0
- package/src/internal/session-runtime.ts +201 -0
- package/src/internal/watch-matcher.test.ts +326 -0
- package/src/internal/watch-matcher.ts +200 -0
- package/src/jsdoc-propagation.test.ts +277 -0
- package/src/loader.test.ts +1098 -0
- package/src/loader.ts +581 -0
- package/src/not-block-onunknown.test.ts +554 -0
- package/src/observer-dispatcher.test.ts +939 -0
- package/src/observer-dispatcher.ts +290 -0
- package/src/per-predicate-typing.test.ts +361 -0
- package/src/plugin-merger.test.ts +790 -0
- package/src/plugin-merger.ts +598 -0
- package/src/plugins/git/README.md +485 -0
- package/src/plugins/git/branch-tracker.test.ts +281 -0
- package/src/plugins/git/branch-tracker.ts +187 -0
- package/src/plugins/git/cwd-extensions.test.ts +230 -0
- package/src/plugins/git/cwd-extensions.ts +160 -0
- package/src/plugins/git/git-ops.test.ts +397 -0
- package/src/plugins/git/git-ops.ts +173 -0
- package/src/plugins/git/index.ts +253 -0
- package/src/plugins/git/integration.test.ts +705 -0
- package/src/plugins/git/predicates.test.ts +1401 -0
- package/src/plugins/git/predicates.ts +693 -0
- package/src/plugins/git/rules.test.ts +1001 -0
- package/src/plugins/git/rules.ts +307 -0
- package/src/schema.test.ts +259 -0
- package/src/schema.ts +1963 -0
- package/src/testing/index.test.ts +1696 -0
- 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"}
|