@mmnto/totem 2.2.1 → 2.4.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/dist/bot-identity.d.ts +99 -0
- package/dist/bot-identity.d.ts.map +1 -0
- package/dist/bot-identity.js +137 -0
- package/dist/bot-identity.js.map +1 -0
- package/dist/bot-identity.test.d.ts +2 -0
- package/dist/bot-identity.test.d.ts.map +1 -0
- package/dist/bot-identity.test.js +42 -0
- package/dist/bot-identity.test.js.map +1 -0
- package/dist/capability/review-catch.d.ts.map +1 -1
- package/dist/capability/review-catch.js +10 -6
- package/dist/capability/review-catch.js.map +1 -1
- package/dist/gate-engine.d.ts +8 -2
- package/dist/gate-engine.d.ts.map +1 -1
- package/dist/gate-engine.js +10 -2
- package/dist/gate-engine.js.map +1 -1
- package/dist/gate-engine.test.js +112 -1
- package/dist/gate-engine.test.js.map +1 -1
- package/dist/gate-types.d.ts +41 -1
- package/dist/gate-types.d.ts.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/merge-ready.d.ts +157 -0
- package/dist/merge-ready.d.ts.map +1 -0
- package/dist/merge-ready.js +1256 -0
- package/dist/merge-ready.js.map +1 -0
- package/dist/merge-ready.test.d.ts +2 -0
- package/dist/merge-ready.test.d.ts.map +1 -0
- package/dist/merge-ready.test.js +814 -0
- package/dist/merge-ready.test.js.map +1 -0
- package/dist/orchestration-resolver.d.ts +13 -7
- package/dist/orchestration-resolver.d.ts.map +1 -1
- package/dist/orchestration-resolver.js +60 -14
- package/dist/orchestration-resolver.js.map +1 -1
- package/dist/orchestration-resolver.test.js +277 -1
- package/dist/orchestration-resolver.test.js.map +1 -1
- package/dist/retrospect.d.ts +6 -6
- package/dist/selection-manifest.d.ts +2 -2
- package/dist/spine/corpus-dispositions.d.ts +30 -30
- package/dist/sys/git.d.ts +50 -0
- package/dist/sys/git.d.ts.map +1 -1
- package/dist/sys/git.js +101 -0
- package/dist/sys/git.js.map +1 -1
- package/dist/transport-shield.test.js +6 -2
- package/dist/transport-shield.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE definition of the review-bot identities the cohort reads
|
|
3
|
+
* (mmnto-ai/totem#2800, errata item 1).
|
|
4
|
+
*
|
|
5
|
+
* Before this module the same three logins were declared twice — a loose
|
|
6
|
+
* substring/shape match in `packages/cli/src/parsers/bot-review-parser.ts` and
|
|
7
|
+
* an exact-login actor map in `packages/core/src/capability/review-catch.ts` —
|
|
8
|
+
* so a login that drifted (or a fourth bot) had to be found in two places and
|
|
9
|
+
* a stale copy read as "no bot here", the silent direction. Every consumer now
|
|
10
|
+
* imports this module — those two, `packages/core/src/merge-ready.ts` (the
|
|
11
|
+
* gate's predicate reads) and `packages/cli/src/commands/resolve-threads.ts`
|
|
12
|
+
* (the human-reply test, which takes the App-suffix rule below) — and
|
|
13
|
+
* `bot-identity-parity.test.ts` scans all four: a list, a pattern or an
|
|
14
|
+
* escaped `\[bot\]` suffix declared in any of them fails the build.
|
|
15
|
+
*
|
|
16
|
+
* TWO SURFACES, TWO PATTERNS — the trap this module exists to hold:
|
|
17
|
+
* GitHub's REST author is `gemini-code-assist[bot]`, its GraphQL
|
|
18
|
+
* `author.login` for the SAME actor is `gemini-code-assist` (no `[bot]`
|
|
19
|
+
* suffix). Observed 2026-09-07 on mmnto-ai/totem#2834 (REST
|
|
20
|
+
* `repos/mmnto-ai/totem/pulls/2834/reviews` → `coderabbitai[bot]`,
|
|
21
|
+
* `gemini-code-assist[bot]`, `greptile-apps[bot]`) and on
|
|
22
|
+
* mmnto-ai/liquid-city#363 (GraphQL `reviewThreads.comments.author.login` →
|
|
23
|
+
* `gemini-code-assist`). So each identity carries BOTH:
|
|
24
|
+
* - `loginPattern` — the loose, substring-style read of a REST-shaped login
|
|
25
|
+
* (triage's surface: recognize every finding, `[bot]` suffix required for
|
|
26
|
+
* the shape-matched bots so a human `alice-greptile` is never a bot); and
|
|
27
|
+
* - `exactLogins` — the CLOSED list of logins actually OBSERVED, each in
|
|
28
|
+
* both spellings (with and without `[bot]`). It is a membership test, not a
|
|
29
|
+
* pattern: a wildcard variant arm (`greptile-<anything>`) admitted human
|
|
30
|
+
* accounts like `greptile-fan`, which would let a human comment gate a
|
|
31
|
+
* merge (mmnto-ai/totem#2800 fold F5). A new bot variant is added HERE, by
|
|
32
|
+
* observation, the same way the first ones were.
|
|
33
|
+
* A gate that reads GraphQL (merge-ready) uses `exactLogins`; triage keeps
|
|
34
|
+
* `loginPattern`.
|
|
35
|
+
*
|
|
36
|
+
* The GREPTILE login is fixed BY OBSERVATION, not by either stale copy: the
|
|
37
|
+
* runs above show `greptile-apps[bot]` on every totem PR greptile reviewed in
|
|
38
|
+
* the 2026-09 window (#2821, #2827, #2831, #2834). The loose `loginPattern`
|
|
39
|
+
* keeps its variant arm (a renamed app is still SURFACED to triage, and the
|
|
40
|
+
* required `[bot]` suffix keeps a human out); the anchored `exactLogins` list
|
|
41
|
+
* carries only what has been observed, so nothing a human could register
|
|
42
|
+
* satisfies the gate's read.
|
|
43
|
+
*/
|
|
44
|
+
/** Triage's compact tool id (the `BotTool` members that are bots). */
|
|
45
|
+
export type BotReviewerTool = 'coderabbit' | 'gca' | 'greptile' | 'ghcq';
|
|
46
|
+
export interface BotReviewerIdentity {
|
|
47
|
+
/** Triage's compact display id for this reviewer. */
|
|
48
|
+
tool: BotReviewerTool;
|
|
49
|
+
/**
|
|
50
|
+
* Loose recognition over a REST-shaped author login (`name[bot]`). Substring
|
|
51
|
+
* for the two bots whose login is stable; bot-login SHAPE (with the `[bot]`
|
|
52
|
+
* suffix required) for the two matched by shape.
|
|
53
|
+
*/
|
|
54
|
+
loginPattern: RegExp;
|
|
55
|
+
/**
|
|
56
|
+
* The closed list of logins observed for this reviewer, lowercase, in BOTH
|
|
57
|
+
* spellings: the REST one (`name[bot]`) and the GraphQL one (no suffix).
|
|
58
|
+
* Membership, never a pattern — see the module header.
|
|
59
|
+
*/
|
|
60
|
+
exactLogins: readonly string[];
|
|
61
|
+
/**
|
|
62
|
+
* The stable Layer-B actor id for hit-rate attribution
|
|
63
|
+
* (`capability/review-catch.ts`), when this reviewer has one. `ghcq` has
|
|
64
|
+
* none: it is not one of the three paid review bots the ledger attributes to,
|
|
65
|
+
* and minting one here would silently change `resolveActorId`.
|
|
66
|
+
*/
|
|
67
|
+
actorId?: string;
|
|
68
|
+
/**
|
|
69
|
+
* The EXACT lowercase logins that resolve to `actorId`. EXACT, not a prefix:
|
|
70
|
+
* a future variant like `greptile-enterprise[bot]` must not be silently
|
|
71
|
+
* collapsed into `greptile` and mixed into its hit-rate.
|
|
72
|
+
*/
|
|
73
|
+
actorLogins: readonly string[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The review bots, in triage's detection order (first match wins, so a login
|
|
77
|
+
* that could satisfy two patterns resolves the same way it did before this
|
|
78
|
+
* array existed).
|
|
79
|
+
*/
|
|
80
|
+
export declare const BOT_REVIEWER_IDENTITIES: readonly BotReviewerIdentity[];
|
|
81
|
+
/** Is this REST-shaped author login one of the known review bots? */
|
|
82
|
+
export declare function isBotReviewerLogin(author: string): boolean;
|
|
83
|
+
/** Triage's tool id for a REST-shaped author login, or null when it is not a known bot. */
|
|
84
|
+
export declare function detectBotReviewer(author: string): BotReviewerTool | null;
|
|
85
|
+
/**
|
|
86
|
+
* Is this a known review bot on a surface that spells the login WHOLE — the
|
|
87
|
+
* GraphQL `author.login`, where the `[bot]` suffix is absent? A CLOSED-list
|
|
88
|
+
* membership test: a login not on the observed list is not a bot, so no human
|
|
89
|
+
* account can satisfy it (mmnto-ai/totem#2800 fold F5).
|
|
90
|
+
*/
|
|
91
|
+
export declare function isBotReviewerLoginExact(author: string): boolean;
|
|
92
|
+
/** Does this login carry the GitHub App suffix (`name[bot]`), on whichever surface spelled it? */
|
|
93
|
+
export declare function hasBotAppLoginSuffix(login: string): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* The exact-login → Layer-B actor-id map, built from the identities that carry
|
|
96
|
+
* an `actorId`. Keys are lowercase EXACT logins (see `actorLogins`).
|
|
97
|
+
*/
|
|
98
|
+
export declare function botReviewerActorIds(): Readonly<Record<string, string>>;
|
|
99
|
+
//# sourceMappingURL=bot-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-identity.d.ts","sourceRoot":"","sources":["../src/bot-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,sEAAsE;AACtE,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC;AAEzE,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,IAAI,EAAE,eAAe,CAAC;IACtB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,mBAAmB,EAoChE,CAAC;AAEH,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,2FAA2F;AAC3F,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAI/D;AAeD,kGAAkG;AAClG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAStE"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE definition of the review-bot identities the cohort reads
|
|
3
|
+
* (mmnto-ai/totem#2800, errata item 1).
|
|
4
|
+
*
|
|
5
|
+
* Before this module the same three logins were declared twice — a loose
|
|
6
|
+
* substring/shape match in `packages/cli/src/parsers/bot-review-parser.ts` and
|
|
7
|
+
* an exact-login actor map in `packages/core/src/capability/review-catch.ts` —
|
|
8
|
+
* so a login that drifted (or a fourth bot) had to be found in two places and
|
|
9
|
+
* a stale copy read as "no bot here", the silent direction. Every consumer now
|
|
10
|
+
* imports this module — those two, `packages/core/src/merge-ready.ts` (the
|
|
11
|
+
* gate's predicate reads) and `packages/cli/src/commands/resolve-threads.ts`
|
|
12
|
+
* (the human-reply test, which takes the App-suffix rule below) — and
|
|
13
|
+
* `bot-identity-parity.test.ts` scans all four: a list, a pattern or an
|
|
14
|
+
* escaped `\[bot\]` suffix declared in any of them fails the build.
|
|
15
|
+
*
|
|
16
|
+
* TWO SURFACES, TWO PATTERNS — the trap this module exists to hold:
|
|
17
|
+
* GitHub's REST author is `gemini-code-assist[bot]`, its GraphQL
|
|
18
|
+
* `author.login` for the SAME actor is `gemini-code-assist` (no `[bot]`
|
|
19
|
+
* suffix). Observed 2026-09-07 on mmnto-ai/totem#2834 (REST
|
|
20
|
+
* `repos/mmnto-ai/totem/pulls/2834/reviews` → `coderabbitai[bot]`,
|
|
21
|
+
* `gemini-code-assist[bot]`, `greptile-apps[bot]`) and on
|
|
22
|
+
* mmnto-ai/liquid-city#363 (GraphQL `reviewThreads.comments.author.login` →
|
|
23
|
+
* `gemini-code-assist`). So each identity carries BOTH:
|
|
24
|
+
* - `loginPattern` — the loose, substring-style read of a REST-shaped login
|
|
25
|
+
* (triage's surface: recognize every finding, `[bot]` suffix required for
|
|
26
|
+
* the shape-matched bots so a human `alice-greptile` is never a bot); and
|
|
27
|
+
* - `exactLogins` — the CLOSED list of logins actually OBSERVED, each in
|
|
28
|
+
* both spellings (with and without `[bot]`). It is a membership test, not a
|
|
29
|
+
* pattern: a wildcard variant arm (`greptile-<anything>`) admitted human
|
|
30
|
+
* accounts like `greptile-fan`, which would let a human comment gate a
|
|
31
|
+
* merge (mmnto-ai/totem#2800 fold F5). A new bot variant is added HERE, by
|
|
32
|
+
* observation, the same way the first ones were.
|
|
33
|
+
* A gate that reads GraphQL (merge-ready) uses `exactLogins`; triage keeps
|
|
34
|
+
* `loginPattern`.
|
|
35
|
+
*
|
|
36
|
+
* The GREPTILE login is fixed BY OBSERVATION, not by either stale copy: the
|
|
37
|
+
* runs above show `greptile-apps[bot]` on every totem PR greptile reviewed in
|
|
38
|
+
* the 2026-09 window (#2821, #2827, #2831, #2834). The loose `loginPattern`
|
|
39
|
+
* keeps its variant arm (a renamed app is still SURFACED to triage, and the
|
|
40
|
+
* required `[bot]` suffix keeps a human out); the anchored `exactLogins` list
|
|
41
|
+
* carries only what has been observed, so nothing a human could register
|
|
42
|
+
* satisfies the gate's read.
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* The review bots, in triage's detection order (first match wins, so a login
|
|
46
|
+
* that could satisfy two patterns resolves the same way it did before this
|
|
47
|
+
* array existed).
|
|
48
|
+
*/
|
|
49
|
+
export const BOT_REVIEWER_IDENTITIES = Object.freeze([
|
|
50
|
+
{
|
|
51
|
+
tool: 'coderabbit',
|
|
52
|
+
loginPattern: /coderabbit/i,
|
|
53
|
+
exactLogins: ['coderabbitai', 'coderabbitai[bot]'],
|
|
54
|
+
actorId: 'coderabbit',
|
|
55
|
+
actorLogins: ['coderabbitai[bot]'],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
tool: 'gca',
|
|
59
|
+
loginPattern: /gemini-code-assist/i,
|
|
60
|
+
exactLogins: ['gemini-code-assist', 'gemini-code-assist[bot]'],
|
|
61
|
+
// The Layer-B actor id deliberately diverges from triage's compact `gca`:
|
|
62
|
+
// the ledger keys hit-rate on the full name.
|
|
63
|
+
actorId: 'gemini-code-assist',
|
|
64
|
+
actorLogins: ['gemini-code-assist[bot]'],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
tool: 'greptile',
|
|
68
|
+
// The reviewer's suggested trailing `\b` fails right after the closing `]`
|
|
69
|
+
// (a non-word char at end-of-string), so it is deliberately absent.
|
|
70
|
+
loginPattern: /\bgreptile(?:-[^[]+)?\[bot\]/i,
|
|
71
|
+
exactLogins: ['greptile-apps', 'greptile-apps[bot]'],
|
|
72
|
+
actorId: 'greptile',
|
|
73
|
+
// Observed 2026-09-07 on mmnto-ai/totem#2821, #2827, #2831 and #2834.
|
|
74
|
+
actorLogins: ['greptile-apps[bot]'],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
// GitHub's own `github-code-quality[bot]` (mmnto-ai/totem#2626): an
|
|
78
|
+
// inline-comment-only surface with no @-listener. Recognized by triage,
|
|
79
|
+
// deliberately WITHOUT an actorId (see `actorId` above).
|
|
80
|
+
tool: 'ghcq',
|
|
81
|
+
loginPattern: /\bgithub-code-quality(?:-[^[]+)?\[bot\]/i,
|
|
82
|
+
exactLogins: ['github-code-quality', 'github-code-quality[bot]'],
|
|
83
|
+
actorLogins: [],
|
|
84
|
+
},
|
|
85
|
+
]);
|
|
86
|
+
/** Is this REST-shaped author login one of the known review bots? */
|
|
87
|
+
export function isBotReviewerLogin(author) {
|
|
88
|
+
return BOT_REVIEWER_IDENTITIES.some((id) => id.loginPattern.test(author));
|
|
89
|
+
}
|
|
90
|
+
/** Triage's tool id for a REST-shaped author login, or null when it is not a known bot. */
|
|
91
|
+
export function detectBotReviewer(author) {
|
|
92
|
+
return BOT_REVIEWER_IDENTITIES.find((id) => id.loginPattern.test(author))?.tool ?? null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Is this a known review bot on a surface that spells the login WHOLE — the
|
|
96
|
+
* GraphQL `author.login`, where the `[bot]` suffix is absent? A CLOSED-list
|
|
97
|
+
* membership test: a login not on the observed list is not a bot, so no human
|
|
98
|
+
* account can satisfy it (mmnto-ai/totem#2800 fold F5).
|
|
99
|
+
*/
|
|
100
|
+
export function isBotReviewerLoginExact(author) {
|
|
101
|
+
const trimmed = author.trim().toLowerCase();
|
|
102
|
+
if (trimmed.length === 0)
|
|
103
|
+
return false;
|
|
104
|
+
return BOT_REVIEWER_IDENTITIES.some((id) => id.exactLogins.includes(trimmed));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The GitHub App login suffix, `name[bot]` — how REST spells every App's login
|
|
108
|
+
* (and how a GraphQL `author.login` never does; see the header). It is a third
|
|
109
|
+
* bot test beside the two list tests above: `resolve-threads` needs it so a
|
|
110
|
+
* `github-actions[bot]` or Copilot reply is never read as the human answer that
|
|
111
|
+
* resolves a thread. It lives HERE so the suffix has one home the parity
|
|
112
|
+
* sensor can hold every consumer to — that sensor's literal scan never saw the
|
|
113
|
+
* escaped spelling a regex source carries (`\[bot\]`), which is how the verb's
|
|
114
|
+
* own copy lived unscanned; the fold that moved it also gave the sensor that
|
|
115
|
+
* arm (mmnto-ai/totem#2841, the deferred fold; the pilot-install leg's F1).
|
|
116
|
+
*/
|
|
117
|
+
const BOT_APP_LOGIN_SUFFIX = /\[bot\]$/i;
|
|
118
|
+
/** Does this login carry the GitHub App suffix (`name[bot]`), on whichever surface spelled it? */
|
|
119
|
+
export function hasBotAppLoginSuffix(login) {
|
|
120
|
+
return BOT_APP_LOGIN_SUFFIX.test(login);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The exact-login → Layer-B actor-id map, built from the identities that carry
|
|
124
|
+
* an `actorId`. Keys are lowercase EXACT logins (see `actorLogins`).
|
|
125
|
+
*/
|
|
126
|
+
export function botReviewerActorIds() {
|
|
127
|
+
const map = {};
|
|
128
|
+
for (const id of BOT_REVIEWER_IDENTITIES) {
|
|
129
|
+
if (id.actorId === undefined)
|
|
130
|
+
continue;
|
|
131
|
+
for (const login of id.actorLogins) {
|
|
132
|
+
map[login.toLowerCase()] = id.actorId;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return map;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=bot-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-identity.js","sourceRoot":"","sources":["../src/bot-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAmCH;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAmC,MAAM,CAAC,MAAM,CAAC;IACnF;QACE,IAAI,EAAE,YAAY;QAClB,YAAY,EAAE,aAAa;QAC3B,WAAW,EAAE,CAAC,cAAc,EAAE,mBAAmB,CAAC;QAClD,OAAO,EAAE,YAAY;QACrB,WAAW,EAAE,CAAC,mBAAmB,CAAC;KACnC;IACD;QACE,IAAI,EAAE,KAAK;QACX,YAAY,EAAE,qBAAqB;QACnC,WAAW,EAAE,CAAC,oBAAoB,EAAE,yBAAyB,CAAC;QAC9D,0EAA0E;QAC1E,6CAA6C;QAC7C,OAAO,EAAE,oBAAoB;QAC7B,WAAW,EAAE,CAAC,yBAAyB,CAAC;KACzC;IACD;QACE,IAAI,EAAE,UAAU;QAChB,2EAA2E;QAC3E,oEAAoE;QACpE,YAAY,EAAE,+BAA+B;QAC7C,WAAW,EAAE,CAAC,eAAe,EAAE,oBAAoB,CAAC;QACpD,OAAO,EAAE,UAAU;QACnB,sEAAsE;QACtE,WAAW,EAAE,CAAC,oBAAoB,CAAC;KACpC;IACD;QACE,oEAAoE;QACpE,wEAAwE;QACxE,yDAAyD;QACzD,IAAI,EAAE,MAAM;QACZ,YAAY,EAAE,0CAA0C;QACxD,WAAW,EAAE,CAAC,qBAAqB,EAAE,0BAA0B,CAAC;QAChE,WAAW,EAAE,EAAE;KAChB;CACF,CAAC,CAAC;AAEH,qEAAqE;AACrE,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC;AAC1F,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,oBAAoB,GAAG,WAAW,CAAC;AAEzC,kGAAkG;AAClG,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,EAAE,IAAI,uBAAuB,EAAE,CAAC;QACzC,IAAI,EAAE,CAAC,OAAO,KAAK,SAAS;YAAE,SAAS;QACvC,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACnC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;QACxC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-identity.test.d.ts","sourceRoot":"","sources":["../src/bot-identity.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The identity module's own predicates, asserted where they live (the parity
|
|
3
|
+
* sensor in the CLI package scans the CONSUMERS; this file pins the PRODUCER).
|
|
4
|
+
* `hasBotAppLoginSuffix` entered with the mmnto-ai/totem#2841 fold and had no
|
|
5
|
+
* direct assertion in this package until the pilot-install leg named the gap.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, expect, it } from 'vitest';
|
|
8
|
+
import { BOT_REVIEWER_IDENTITIES, hasBotAppLoginSuffix, isBotReviewerLogin, isBotReviewerLoginExact, } from './bot-identity.js';
|
|
9
|
+
describe('hasBotAppLoginSuffix — the GitHub App login suffix', () => {
|
|
10
|
+
it('reads the REST spelling of any App login, review bot or not', () => {
|
|
11
|
+
expect(hasBotAppLoginSuffix('github-actions[bot]')).toBe(true);
|
|
12
|
+
expect(hasBotAppLoginSuffix('copilot-pull-request-reviewer[bot]')).toBe(true);
|
|
13
|
+
expect(hasBotAppLoginSuffix('coderabbitai[bot]')).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
it('is case-insensitive on the suffix, as GitHub renders it', () => {
|
|
16
|
+
expect(hasBotAppLoginSuffix('CodeRabbitAI[Bot]')).toBe(true);
|
|
17
|
+
expect(hasBotAppLoginSuffix('GREPTILE-APPS[BOT]')).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
it("never reads the GraphQL spelling (no suffix) as an App — that is the exact list's job", () => {
|
|
20
|
+
expect(hasBotAppLoginSuffix('greptile-apps')).toBe(false);
|
|
21
|
+
expect(hasBotAppLoginSuffix('gemini-code-assist')).toBe(false);
|
|
22
|
+
expect(hasBotAppLoginSuffix('')).toBe(false);
|
|
23
|
+
});
|
|
24
|
+
it('requires the suffix to END the login — a human login that merely contains it is not an App', () => {
|
|
25
|
+
expect(hasBotAppLoginSuffix('alice[bot]fan')).toBe(false);
|
|
26
|
+
expect(hasBotAppLoginSuffix('[bot]')).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
it('agrees with the two list tests on every observed identity', () => {
|
|
29
|
+
for (const id of BOT_REVIEWER_IDENTITIES) {
|
|
30
|
+
for (const login of id.exactLogins) {
|
|
31
|
+
// Every observed spelling is on the exact list by construction.
|
|
32
|
+
expect(isBotReviewerLoginExact(login)).toBe(true);
|
|
33
|
+
// The suffix test is exactly "ends with [bot]", whichever spelling the list carries…
|
|
34
|
+
expect(hasBotAppLoginSuffix(login)).toBe(login.toLowerCase().endsWith('[bot]'));
|
|
35
|
+
// …and every suffixed observed spelling also satisfies the loose REST pattern.
|
|
36
|
+
if (hasBotAppLoginSuffix(login))
|
|
37
|
+
expect(isBotReviewerLogin(login)).toBe(true);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=bot-identity.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-identity.test.js","sourceRoot":"","sources":["../src/bot-identity.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,QAAQ,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAClE,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,oBAAoB,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,MAAM,CAAC,oBAAoB,CAAC,oCAAoC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9E,MAAM,CAAC,oBAAoB,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,oBAAoB,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uFAAuF,EAAE,GAAG,EAAE;QAC/F,MAAM,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1D,MAAM,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/D,MAAM,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4FAA4F,EAAE,GAAG,EAAE;QACpG,MAAM,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1D,MAAM,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,KAAK,MAAM,EAAE,IAAI,uBAAuB,EAAE,CAAC;YACzC,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACnC,gEAAgE;gBAChE,MAAM,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClD,qFAAqF;gBACrF,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;gBAChF,+EAA+E;gBAC/E,IAAI,oBAAoB,CAAC,KAAK,CAAC;oBAAE,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChF,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-catch.d.ts","sourceRoot":"","sources":["../../src/capability/review-catch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"review-catch.d.ts","sourceRoot":"","sources":["../../src/capability/review-catch.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,oBAAoB,EAG1B,MAAM,aAAa,CAAC;AAErB,gFAAgF;AAChF,MAAM,WAAW,kBAAkB;IACjC,iGAAiG;IACjG,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC,4EAA4E;IAC5E,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AAYD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAWrD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,GAAG,qBAAqB,CA+C9F"}
|
|
@@ -8,14 +8,18 @@
|
|
|
8
8
|
// `bot-review-parser` disposition read is the CLI-side adapter, a follow-on); core stays
|
|
9
9
|
// network/LLM-free. No LLM-judge — the resolution is a deterministic disposition read
|
|
10
10
|
// (resolutionSource `disposition-thread`), so FM-b holds.
|
|
11
|
+
import { botReviewerActorIds } from '../bot-identity.js';
|
|
11
12
|
import { CapabilityClaimSchema, CapabilityResolutionSchema, deriveClaimId, } from './schema.js';
|
|
12
13
|
const REVIEW_CATCH_CLAIM_KIND = 'review-finding';
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The three active paid review bots → their stable actor-id, keyed by EXACT
|
|
16
|
+
* login. Derived from the ONE bot-identity definition in `../bot-identity.ts`
|
|
17
|
+
* (mmnto-ai/totem#2800): this module declares no list of its own, so a login
|
|
18
|
+
* that drifts is fixed in one place. `github-code-quality[bot]` is recognized
|
|
19
|
+
* there but carries no `actorId`, so it is deliberately absent from this map
|
|
20
|
+
* and still resolves to its own trimmed login below.
|
|
21
|
+
*/
|
|
22
|
+
const REVIEW_BOT_ACTOR_IDS = botReviewerActorIds();
|
|
19
23
|
/**
|
|
20
24
|
* Resolve a GitHub author login to a stable Layer-B actor-id, COUPLING to existing
|
|
21
25
|
* actors rather than minting a parallel scheme (#697 fold 5, corrected c.4755848293).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-catch.js","sourceRoot":"","sources":["../../src/capability/review-catch.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,uFAAuF;AACvF,oFAAoF;AACpF,uFAAuF;AACvF,oFAAoF;AACpF,oFAAoF;AACpF,yFAAyF;AACzF,sFAAsF;AACtF,0DAA0D;AAE1D,OAAO,EAEL,qBAAqB,EAErB,0BAA0B,EAC1B,aAAa,GACd,MAAM,aAAa,CAAC;AA2BrB,MAAM,uBAAuB,GAAG,gBAAgB,CAAC;AAOjD
|
|
1
|
+
{"version":3,"file":"review-catch.js","sourceRoot":"","sources":["../../src/capability/review-catch.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,uFAAuF;AACvF,oFAAoF;AACpF,uFAAuF;AACvF,oFAAoF;AACpF,oFAAoF;AACpF,yFAAyF;AACzF,sFAAsF;AACtF,0DAA0D;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAEL,qBAAqB,EAErB,0BAA0B,EAC1B,aAAa,GACd,MAAM,aAAa,CAAC;AA2BrB,MAAM,uBAAuB,GAAG,gBAAgB,CAAC;AAOjD;;;;;;;GAOG;AACH,MAAM,oBAAoB,GAAqC,mBAAmB,EAAE,CAAC;AAErF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,mFAAmF;QACnF,mDAAmD;QACnD,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;IACD,wFAAwF;IACxF,uFAAuF;IACvF,sFAAsF;IACtF,OAAO,oBAAoB,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,OAAO,CAAC;AAChE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,QAAuC;IACrE,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,WAAW,GAA2B,EAAE,CAAC;IAE/C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,qBAAqB,CAAC,CAAC,SAAS,EAAE,CAAC;QACrD,MAAM,WAAW,GAAG,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,aAAa,CAAC;YAC5B,WAAW;YACX,QAAQ,EAAE,cAAc;YACxB,SAAS,EAAE,uBAAuB;YAClC,aAAa,EAAE,CAAC,CAAC,KAAK;YACtB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,SAAS;SACV,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CACT,qBAAqB,CAAC,KAAK,CAAC;YAC1B,OAAO;YACP,WAAW;YACX,QAAQ,EAAE,cAAc;YACxB,SAAS,EAAE,uBAAuB;YAClC,UAAU,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE;YACpD,SAAS;YACT,UAAU,EAAE,CAAC,CAAC,UAAU;SACzB,CAAC,CACH,CAAC;QAEF,IAAI,CAAC,CAAC,WAAW,KAAK,UAAU,IAAI,CAAC,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;YACjE,WAAW,CAAC,IAAI,CACd,0BAA0B,CAAC,KAAK,CAAC;gBAC/B,YAAY,EAAE,UAAU,CAAC,CAAC,SAAS,EAAE;gBACrC,OAAO;gBACP,OAAO,EAAE,CAAC,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;gBAC3D,+EAA+E;gBAC/E,gBAAgB,EAAE,oBAAoB;gBACtC,+EAA+E;gBAC/E,yEAAyE;gBACzE,WAAW,EAAE,CAAC,CAAC,sBAAsB,EAAE,IAAI,EAAE,IAAI,SAAS;gBAC1D,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,UAAU;aACjD,CAAC,CACH,CAAC;QACJ,CAAC;QACD,sFAAsF;IACxF,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;AACjC,CAAC"}
|
package/dist/gate-engine.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GateMatcher, GateVerdict } from './gate-types.js';
|
|
1
|
+
import type { GateContext, GateMatcher, GateVerdict } from './gate-types.js';
|
|
2
2
|
export declare const FREEZE_CHECK_EVENT = "freeze-check";
|
|
3
3
|
/** The known gate event types — for error messages and host discovery. */
|
|
4
4
|
export declare function knownGateEvents(): string[];
|
|
@@ -16,6 +16,12 @@ export declare function gateMatcher(event: string): GateMatcher;
|
|
|
16
16
|
* Evaluate a gate. Pure with respect to state: reads deterministic sources,
|
|
17
17
|
* never mutates. Throws (fail-loud) on an unknown event or an unparseable
|
|
18
18
|
* source — it never default-allows.
|
|
19
|
+
*
|
|
20
|
+
* `context` (mmnto-ai/totem#2800) carries the per-evaluation seams a gate may
|
|
21
|
+
* read: the enforcement tier for ITS OWN unevaluable class, the injected `gh`
|
|
22
|
+
* runner, the environment, and the stderr sink. A gate that reads none of them
|
|
23
|
+
* — `freeze-check`, `transport-shield` — is unaffected by what it carries, so
|
|
24
|
+
* a tier can never soften them.
|
|
19
25
|
*/
|
|
20
|
-
export declare function evaluateGate(event: string, payload: unknown, totemDir: string): GateVerdict;
|
|
26
|
+
export declare function evaluateGate(event: string, payload: unknown, totemDir: string, context?: GateContext): GateVerdict;
|
|
21
27
|
//# sourceMappingURL=gate-engine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-engine.d.ts","sourceRoot":"","sources":["../src/gate-engine.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"gate-engine.d.ts","sourceRoot":"","sources":["../src/gate-engine.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,WAAW,EAGX,WAAW,EACX,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAIzB,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AA+EjD,0EAA0E;AAC1E,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED,8EAA8E;AAC9E,wBAAgB,UAAU,IAAI,aAAa,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC,CAEnF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAUtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,WAAW,GACpB,WAAW,CAUb"}
|
package/dist/gate-engine.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import { TotemError } from './errors.js';
|
|
3
3
|
import { FREEZE_FILE, readFreezeConfig } from './freeze.js';
|
|
4
|
+
import { MERGE_READY_EVENT, mergeReadyEvaluator } from './merge-ready.js';
|
|
4
5
|
import { TRANSPORT_SHIELD_EVENT, transportShieldEvaluator } from './transport-shield.js';
|
|
5
6
|
export const FREEZE_CHECK_EVENT = 'freeze-check';
|
|
6
7
|
/**
|
|
@@ -65,6 +66,7 @@ const freezeCheckEvaluator = (payload, totemDir) => {
|
|
|
65
66
|
const REGISTRY = new Map([
|
|
66
67
|
[FREEZE_CHECK_EVENT, { evaluator: freezeCheckEvaluator, matcher: 'Write|Edit' }],
|
|
67
68
|
[TRANSPORT_SHIELD_EVENT, { evaluator: transportShieldEvaluator, matcher: 'Bash|PowerShell' }],
|
|
69
|
+
[MERGE_READY_EVENT, { evaluator: mergeReadyEvaluator, matcher: 'Bash|PowerShell' }],
|
|
68
70
|
]);
|
|
69
71
|
/** The known gate event types — for error messages and host discovery. */
|
|
70
72
|
export function knownGateEvents() {
|
|
@@ -89,12 +91,18 @@ export function gateMatcher(event) {
|
|
|
89
91
|
* Evaluate a gate. Pure with respect to state: reads deterministic sources,
|
|
90
92
|
* never mutates. Throws (fail-loud) on an unknown event or an unparseable
|
|
91
93
|
* source — it never default-allows.
|
|
94
|
+
*
|
|
95
|
+
* `context` (mmnto-ai/totem#2800) carries the per-evaluation seams a gate may
|
|
96
|
+
* read: the enforcement tier for ITS OWN unevaluable class, the injected `gh`
|
|
97
|
+
* runner, the environment, and the stderr sink. A gate that reads none of them
|
|
98
|
+
* — `freeze-check`, `transport-shield` — is unaffected by what it carries, so
|
|
99
|
+
* a tier can never soften them.
|
|
92
100
|
*/
|
|
93
|
-
export function evaluateGate(event, payload, totemDir) {
|
|
101
|
+
export function evaluateGate(event, payload, totemDir, context) {
|
|
94
102
|
const def = REGISTRY.get(event);
|
|
95
103
|
if (!def) {
|
|
96
104
|
throw new TotemError('GATE_INVALID', `Unknown gate event "${event}". Known events: ${knownGateEvents().join(', ')}.`, 'Use one of the known --event values.');
|
|
97
105
|
}
|
|
98
|
-
return def.evaluator(payload, totemDir);
|
|
106
|
+
return def.evaluator(payload, totemDir, context);
|
|
99
107
|
}
|
|
100
108
|
//# sourceMappingURL=gate-engine.js.map
|
package/dist/gate-engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-engine.js","sourceRoot":"","sources":["../src/gate-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"gate-engine.js","sourceRoot":"","sources":["../src/gate-engine.ts"],"names":[],"mappings":"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"}
|
package/dist/gate-engine.test.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as os from 'node:os';
|
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
5
5
|
import { TotemConfigError } from './errors.js';
|
|
6
|
-
import { evaluateGate, knownGateEvents } from './gate-engine.js';
|
|
6
|
+
import { evaluateGate, gateMatcher, knownGateEvents } from './gate-engine.js';
|
|
7
7
|
let tmpRoot;
|
|
8
8
|
let totemDir;
|
|
9
9
|
function writeFreeze(content) {
|
|
@@ -105,4 +105,115 @@ describe('evaluateGate — dispatch', () => {
|
|
|
105
105
|
expect(knownGateEvents()).toContain('freeze-check');
|
|
106
106
|
});
|
|
107
107
|
});
|
|
108
|
+
// ─── merge-ready through the registry (mmnto-ai/totem#2800) ──────────────
|
|
109
|
+
//
|
|
110
|
+
// The evaluator's own predicate matrix lives in merge-ready.test.ts; what is
|
|
111
|
+
// locked HERE is what the registry owes: the event is dispatchable under its own
|
|
112
|
+
// matcher, the gh seam and the tier ride in on the context, and the ADR-109
|
|
113
|
+
// side-effect fixture extends to this event (a verdict that mutates on-disk
|
|
114
|
+
// state falsifies the ADR).
|
|
115
|
+
/** A runner that answers `gh --version` and then one canned, minimal PR page. */
|
|
116
|
+
function ghRunnerStub(mergeStateStatus) {
|
|
117
|
+
const pr = {
|
|
118
|
+
number: 4242,
|
|
119
|
+
isDraft: false,
|
|
120
|
+
mergeStateStatus,
|
|
121
|
+
headRefOid: 'a'.repeat(40),
|
|
122
|
+
headRefName: 'feat/x',
|
|
123
|
+
baseRefName: 'main',
|
|
124
|
+
commits: {
|
|
125
|
+
nodes: [
|
|
126
|
+
{
|
|
127
|
+
commit: {
|
|
128
|
+
oid: 'a'.repeat(40),
|
|
129
|
+
statusCheckRollup: {
|
|
130
|
+
state: 'SUCCESS',
|
|
131
|
+
contexts: {
|
|
132
|
+
totalCount: 1,
|
|
133
|
+
pageInfo: { hasNextPage: false, endCursor: null },
|
|
134
|
+
nodes: [
|
|
135
|
+
{
|
|
136
|
+
__typename: 'CheckRun',
|
|
137
|
+
name: 'CI',
|
|
138
|
+
status: 'COMPLETED',
|
|
139
|
+
conclusion: 'SUCCESS',
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
reviews: { pageInfo: { hasNextPage: false, endCursor: null }, nodes: [] },
|
|
149
|
+
reviewThreads: { pageInfo: { hasNextPage: false, endCursor: null }, nodes: [] },
|
|
150
|
+
};
|
|
151
|
+
return (args) => args[0] === '--version'
|
|
152
|
+
? { stdout: 'gh version 2.99.0 (2026-09-01)', exitCode: 0 }
|
|
153
|
+
: { stdout: JSON.stringify({ data: { repository: { pullRequest: pr } } }), exitCode: 0 };
|
|
154
|
+
}
|
|
155
|
+
const MERGE_READY_PAYLOAD = { repo: 'mmnto-ai/totem', pr: 4242 };
|
|
156
|
+
describe('evaluateGate — merge-ready', () => {
|
|
157
|
+
it('is a known gate under the Bash|PowerShell matcher', () => {
|
|
158
|
+
expect(knownGateEvents()).toContain('merge-ready');
|
|
159
|
+
expect(gateMatcher('merge-ready')).toBe('Bash|PowerShell');
|
|
160
|
+
});
|
|
161
|
+
it('dispatches with the injected gh runner and returns an ADR-109 verdict', () => {
|
|
162
|
+
const v = evaluateGate('merge-ready', MERGE_READY_PAYLOAD, totemDir, {
|
|
163
|
+
ghRunner: ghRunnerStub('CLEAN'),
|
|
164
|
+
env: {},
|
|
165
|
+
writeStderr: () => { },
|
|
166
|
+
});
|
|
167
|
+
expect(v.disposition).toBe('allow');
|
|
168
|
+
expect(v.reason).toMatch(/merge-ready floor/i);
|
|
169
|
+
expect(v.provenance.checkedAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
|
|
170
|
+
});
|
|
171
|
+
it('reads the tier from the context for its own UNEVALUABLE class only', () => {
|
|
172
|
+
const strict = evaluateGate('merge-ready', MERGE_READY_PAYLOAD, totemDir, {
|
|
173
|
+
ghRunner: ghRunnerStub('UNKNOWN'),
|
|
174
|
+
env: {},
|
|
175
|
+
writeStderr: () => { },
|
|
176
|
+
});
|
|
177
|
+
expect(strict.disposition).toBe('deny');
|
|
178
|
+
const pilot = evaluateGate('merge-ready', MERGE_READY_PAYLOAD, totemDir, {
|
|
179
|
+
tier: 'pilot',
|
|
180
|
+
ghRunner: ghRunnerStub('UNKNOWN'),
|
|
181
|
+
env: {},
|
|
182
|
+
writeStderr: () => { },
|
|
183
|
+
});
|
|
184
|
+
expect(pilot.disposition).toBe('warn');
|
|
185
|
+
});
|
|
186
|
+
it('leaves freeze-check failing closed at EVERY tier (the tier is per gate)', () => {
|
|
187
|
+
writeFreeze('{ not valid json');
|
|
188
|
+
expect(() => evaluateGate('freeze-check', { subsystem: 'rule-compilation' }, totemDir, {
|
|
189
|
+
tier: 'pilot',
|
|
190
|
+
})).toThrow(TotemConfigError);
|
|
191
|
+
writeFreeze(FROZEN);
|
|
192
|
+
const denied = evaluateGate('freeze-check', { subsystem: 'rule-compilation' }, totemDir, {
|
|
193
|
+
tier: 'pilot',
|
|
194
|
+
});
|
|
195
|
+
expect(denied.disposition).toBe('deny'); // never downgraded to `warn`
|
|
196
|
+
});
|
|
197
|
+
it('throws on a malformed payload — never default-allow', () => {
|
|
198
|
+
expect(() => evaluateGate('merge-ready', { repo: '', pr: null }, totemDir, {
|
|
199
|
+
ghRunner: ghRunnerStub('CLEAN'),
|
|
200
|
+
env: {},
|
|
201
|
+
writeStderr: () => { },
|
|
202
|
+
})).toThrow(/merge-ready payload is invalid/);
|
|
203
|
+
});
|
|
204
|
+
it('is side-effect-free — never writes or mutates state (ADR-109 fixture, extended)', () => {
|
|
205
|
+
writeFreeze(FROZEN);
|
|
206
|
+
const before = fs.readFileSync(path.join(totemDir, 'freeze.json'), 'utf-8');
|
|
207
|
+
const entriesBefore = fs.readdirSync(totemDir).sort();
|
|
208
|
+
const rootBefore = fs.readdirSync(tmpRoot).sort();
|
|
209
|
+
evaluateGate('merge-ready', MERGE_READY_PAYLOAD, totemDir, {
|
|
210
|
+
ghRunner: ghRunnerStub('CLEAN'),
|
|
211
|
+
env: {},
|
|
212
|
+
writeStderr: () => { },
|
|
213
|
+
});
|
|
214
|
+
expect(fs.readFileSync(path.join(totemDir, 'freeze.json'), 'utf-8')).toBe(before);
|
|
215
|
+
expect(fs.readdirSync(totemDir).sort()).toEqual(entriesBefore);
|
|
216
|
+
expect(fs.readdirSync(tmpRoot).sort()).toEqual(rootBefore); // no cache, no ledger, no stamp
|
|
217
|
+
});
|
|
218
|
+
});
|
|
108
219
|
//# sourceMappingURL=gate-engine.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-engine.test.js","sourceRoot":"","sources":["../src/gate-engine.test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAErE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"gate-engine.test.js","sourceRoot":"","sources":["../src/gate-engine.test.ts"],"names":[],"mappings":"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"}
|