@mmnto/totem 1.102.0 → 1.103.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/artifacts/verdict.d.ts +70 -14
- package/dist/artifacts/verdict.d.ts.map +1 -1
- package/dist/artifacts/verdict.js +43 -3
- package/dist/artifacts/verdict.js.map +1 -1
- package/dist/artifacts/verdict.test.js +169 -1
- package/dist/artifacts/verdict.test.js.map +1 -1
- package/dist/autoclose/index.d.ts +12 -0
- package/dist/autoclose/index.d.ts.map +1 -0
- package/dist/autoclose/index.js +9 -0
- package/dist/autoclose/index.js.map +1 -0
- package/dist/autoclose/matcher.d.ts +115 -0
- package/dist/autoclose/matcher.d.ts.map +1 -0
- package/dist/autoclose/matcher.js +164 -0
- package/dist/autoclose/matcher.js.map +1 -0
- package/dist/autoclose/matcher.test.d.ts +2 -0
- package/dist/autoclose/matcher.test.d.ts.map +1 -0
- package/dist/autoclose/matcher.test.js +133 -0
- package/dist/autoclose/matcher.test.js.map +1 -0
- package/dist/autoclose/merge-config.d.ts +73 -0
- package/dist/autoclose/merge-config.d.ts.map +1 -0
- package/dist/autoclose/merge-config.js +81 -0
- package/dist/autoclose/merge-config.js.map +1 -0
- package/dist/autoclose/merge-config.test.d.ts +2 -0
- package/dist/autoclose/merge-config.test.d.ts.map +1 -0
- package/dist/autoclose/merge-config.test.js +108 -0
- package/dist/autoclose/merge-config.test.js.map +1 -0
- package/dist/autoclose/receipt.d.ts +160 -0
- package/dist/autoclose/receipt.d.ts.map +1 -0
- package/dist/autoclose/receipt.js +296 -0
- package/dist/autoclose/receipt.js.map +1 -0
- package/dist/autoclose/receipt.test.d.ts +2 -0
- package/dist/autoclose/receipt.test.d.ts.map +1 -0
- package/dist/autoclose/receipt.test.js +248 -0
- package/dist/autoclose/receipt.test.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { AUTO_CLOSE_KEYWORDS, AUTO_CLOSE_REGEX_SOURCE, autoCloseKeyForms, findAutoCloseRefs, } from './matcher.js';
|
|
3
|
+
/** Verbatim body of commit b8aa74a2 on main — the real #2471→#2466 specimen. */
|
|
4
|
+
const B8AA74A2_BODY = 'fix(review): deterministic skip paths no longer stamp the push gate (#2466) (#2471)\n' +
|
|
5
|
+
'\n' +
|
|
6
|
+
'Three deterministic skip paths (all-generated, all-non-code, filtered-empty) no longer ' +
|
|
7
|
+
'mint the reviewed-content stamp; they log a shared NON-REVIEW notice instead. Adds coverage ' +
|
|
8
|
+
'for the .gitattributes-marked .ts bypass and the filtered-empty path. ' +
|
|
9
|
+
'Does not close #2466 (live exit-0 half deferred to #2473).';
|
|
10
|
+
const refs = (t) => findAutoCloseRefs(t).map((m) => m.ref);
|
|
11
|
+
describe('AUTO_CLOSE_REGEX_SOURCE / findAutoCloseRefs', () => {
|
|
12
|
+
it('exports the nine GitHub close keywords', () => {
|
|
13
|
+
expect([...AUTO_CLOSE_KEYWORDS].sort()).toEqual([
|
|
14
|
+
'close',
|
|
15
|
+
'closed',
|
|
16
|
+
'closes',
|
|
17
|
+
'fix',
|
|
18
|
+
'fixed',
|
|
19
|
+
'fixes',
|
|
20
|
+
'resolve',
|
|
21
|
+
'resolved',
|
|
22
|
+
'resolves',
|
|
23
|
+
].sort());
|
|
24
|
+
});
|
|
25
|
+
it('compiles to a valid regex', () => {
|
|
26
|
+
expect(() => new RegExp(AUTO_CLOSE_REGEX_SOURCE, 'gi')).not.toThrow();
|
|
27
|
+
});
|
|
28
|
+
// ─── presence invariant: negated / emphasized / quoted all match ──────────
|
|
29
|
+
it('matches under NEGATION (the confirmed #2471 specimen)', () => {
|
|
30
|
+
expect(refs('Does not close #2466')).toEqual(['#2466']);
|
|
31
|
+
});
|
|
32
|
+
it('matches inside EMPHASIS', () => {
|
|
33
|
+
expect(refs('**Fixes #700**')).toEqual(['#700']);
|
|
34
|
+
});
|
|
35
|
+
it('matches inside a block QUOTE', () => {
|
|
36
|
+
expect(refs('> quoted: closes #12')).toEqual(['#12']);
|
|
37
|
+
});
|
|
38
|
+
it('matches a QUALIFIED cross-repo ref (still auto-closes)', () => {
|
|
39
|
+
expect(refs('This resolves mmnto-ai/totem#2466 upstream')).toEqual(['mmnto-ai/totem#2466']);
|
|
40
|
+
});
|
|
41
|
+
// ─── issue/PR URL form (kimi BLOCKING-1) ──────────────────────────────────
|
|
42
|
+
// GitHub's docs list only `#N` and `owner/repo#N` as closing syntaxes
|
|
43
|
+
// (docs.github.com/.../linking-a-pull-request-to-an-issue, verified: no URL
|
|
44
|
+
// form documented). The URL form is UNDOCUMENTED but EMPIRICALLY closes —
|
|
45
|
+
// isaacs/github#1731 (comment-permalink over-fire) + SAP/spartacus CONTRIBUTING
|
|
46
|
+
// (`Fixes https://github.com/SAP/spartacus/issues/<n>`). Matched
|
|
47
|
+
// presence-invariantly, normalized to the same `owner/repo#N` key.
|
|
48
|
+
it('matches the issue-URL form, normalized to owner/repo#N', () => {
|
|
49
|
+
expect(refs('Fixes https://github.com/mmnto-ai/totem/issues/2466')).toEqual([
|
|
50
|
+
'mmnto-ai/totem#2466',
|
|
51
|
+
]);
|
|
52
|
+
});
|
|
53
|
+
it('tolerates a trailing #issuecomment- permalink fragment on the URL', () => {
|
|
54
|
+
expect(refs('Fix https://github.com/o/r/issues/123#issuecomment-999')).toEqual(['o/r#123']);
|
|
55
|
+
});
|
|
56
|
+
it('matches the /pull/ URL form too', () => {
|
|
57
|
+
expect(refs('closes https://github.com/o/r/pull/45')).toEqual(['o/r#45']);
|
|
58
|
+
});
|
|
59
|
+
it('matches MULTIPLE refs including a colon separator', () => {
|
|
60
|
+
expect(refs('Fixes: #55 and also Resolved #56')).toEqual(['#55', '#56']);
|
|
61
|
+
});
|
|
62
|
+
it('matches every keyword inflection', () => {
|
|
63
|
+
for (const kw of AUTO_CLOSE_KEYWORDS) {
|
|
64
|
+
expect(refs(`${kw} #1`)).toEqual(['#1']);
|
|
65
|
+
expect(refs(`${kw.toUpperCase()} #2`)).toEqual(['#2']);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
it('preserves the keyword casing and records a match index', () => {
|
|
69
|
+
const [m] = findAutoCloseRefs('xx Closes #9');
|
|
70
|
+
expect(m?.keyword).toBe('Closes');
|
|
71
|
+
expect(m?.issue).toBe(9);
|
|
72
|
+
expect(m?.index).toBe(3);
|
|
73
|
+
});
|
|
74
|
+
// ─── non-matches ──────────────────────────────────────────────────────────
|
|
75
|
+
it('does NOT match subject-line parentheticals (no adjacent keyword)', () => {
|
|
76
|
+
expect(refs('fix(review): stamp the push gate (#2466) (#2471)')).toEqual([]);
|
|
77
|
+
});
|
|
78
|
+
it('does NOT match keyword substrings (prefix / affixes / fixup)', () => {
|
|
79
|
+
expect(refs('prefix #99, affixes #98, fixup #97')).toEqual([]);
|
|
80
|
+
});
|
|
81
|
+
it('does NOT match with no separator (closed#88 — GitHub declines it too)', () => {
|
|
82
|
+
expect(refs('closed#88')).toEqual([]);
|
|
83
|
+
});
|
|
84
|
+
it('does NOT match a bare ref with no keyword', () => {
|
|
85
|
+
expect(refs('See #247 above')).toEqual([]);
|
|
86
|
+
});
|
|
87
|
+
it('returns [] for empty / non-string input', () => {
|
|
88
|
+
expect(findAutoCloseRefs('')).toEqual([]);
|
|
89
|
+
expect(findAutoCloseRefs(undefined)).toEqual([]);
|
|
90
|
+
});
|
|
91
|
+
// ─── DELIBERATE pinned behavior (kimi Q1/Q2/NB-2/NB-3) ────────────────────
|
|
92
|
+
// These pin CURRENT behavior; the empirical GitHub questions are routed to the
|
|
93
|
+
// arming-phase sandbox matrix (spec §arming "open empirical questions").
|
|
94
|
+
it('DELIBERATE: emphasis/backtick wrapping ONLY the keyword => MISS', () => {
|
|
95
|
+
// `**`/backtick severs keyword→ref adjacency in the raw text.
|
|
96
|
+
expect(refs('**closes** #123')).toEqual([]);
|
|
97
|
+
expect(refs('`closes` #123')).toEqual([]);
|
|
98
|
+
});
|
|
99
|
+
it('DELIBERATE: the GH-123 autolink form => MISS (undocumented for closing)', () => {
|
|
100
|
+
expect(refs('fix GH-123')).toEqual([]);
|
|
101
|
+
});
|
|
102
|
+
it('DELIBERATE: a cross-paragraph span => MATCH (over-fires, invariant-consistent)', () => {
|
|
103
|
+
expect(refs('closes\n\n#123')).toEqual(['#123']);
|
|
104
|
+
});
|
|
105
|
+
it('DELIBERATE: a fenced code block => MATCH (over-fires; totem-context is the escape)', () => {
|
|
106
|
+
expect(refs('```\ncloses #123\n```')).toEqual(['#123']);
|
|
107
|
+
});
|
|
108
|
+
// ─── perf sanity (kimi NON-BLOCKING-1: the O(n²) is dead) ──────────────────
|
|
109
|
+
it('completes a pathological long-whitespace probe in well under 50ms', () => {
|
|
110
|
+
const probe = `fix${' '.repeat(65000)}x`; // keyword + ~64KB whitespace + non-ref
|
|
111
|
+
const t0 = performance.now();
|
|
112
|
+
findAutoCloseRefs(probe);
|
|
113
|
+
expect(performance.now() - t0).toBeLessThan(50);
|
|
114
|
+
});
|
|
115
|
+
// ─── the b8aa74a2 positive control ────────────────────────────────────────
|
|
116
|
+
it('finds exactly #2466 in the verbatim b8aa74a2 body (and NOT the parentheticals)', () => {
|
|
117
|
+
expect(refs(B8AA74A2_BODY)).toEqual(['#2466']);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe('autoCloseKeyForms', () => {
|
|
121
|
+
it('expands a bare ref to include the self-repo qualified form', () => {
|
|
122
|
+
expect(autoCloseKeyForms({ issue: 2466 }, 'mmnto-ai/totem').sort()).toEqual(['#2466', 'mmnto-ai/totem#2466'].sort());
|
|
123
|
+
});
|
|
124
|
+
it('expands a self-qualified ref to include the bare form', () => {
|
|
125
|
+
expect(autoCloseKeyForms({ qualifier: 'mmnto-ai/totem', issue: 2466 }, 'mmnto-ai/totem').sort()).toEqual(['#2466', 'mmnto-ai/totem#2466'].sort());
|
|
126
|
+
});
|
|
127
|
+
it('keeps a cross-repo qualified ref distinct from the bare form', () => {
|
|
128
|
+
expect(autoCloseKeyForms({ qualifier: 'mmnto-ai/other', issue: 5 }, 'mmnto-ai/totem')).toEqual([
|
|
129
|
+
'mmnto-ai/other#5',
|
|
130
|
+
]);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
//# sourceMappingURL=matcher.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.test.js","sourceRoot":"","sources":["../../src/autoclose/matcher.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAEtB,gFAAgF;AAChF,MAAM,aAAa,GACjB,uFAAuF;IACvF,IAAI;IACJ,yFAAyF;IACzF,8FAA8F;IAC9F,wEAAwE;IACxE,4DAA4D,CAAC;AAE/D,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAEnE,QAAQ,CAAC,6CAA6C,EAAE,GAAG,EAAE;IAC3D,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAC7C;YACE,OAAO;YACP,QAAQ;YACR,QAAQ;YACR,KAAK;YACL,OAAO;YACP,OAAO;YACP,SAAS;YACT,UAAU;YACV,UAAU;SACX,CAAC,IAAI,EAAE,CACT,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAE7E,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAC7E,sEAAsE;IACtE,4EAA4E;IAC5E,0EAA0E;IAC1E,gFAAgF;IAChF,iEAAiE;IACjE,mEAAmE;IAEnE,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC,CAAC,OAAO,CAAC;YAC1E,qBAAqB;SACtB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,MAAM,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,KAAK,MAAM,EAAE,IAAI,mBAAmB,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACzC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,cAAc,CAAC,CAAC;QAC9C,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAE7E,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,iBAAiB,CAAC,SAA8B,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAC7E,+EAA+E;IAC/E,yEAAyE;IAEzE,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,8DAA8D;QAC9D,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACxF,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oFAAoF,EAAE,GAAG,EAAE;QAC5F,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAE9E,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,uCAAuC;QACjF,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAC7B,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACzB,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAE7E,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACxF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,gBAAgB,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CACzE,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC,IAAI,EAAE,CACxC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CACJ,iBAAiB,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,gBAAgB,CAAC,CAAC,IAAI,EAAE,CACzF,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,CAAC,iBAAiB,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7F,kBAAkB;SACnB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo merge-config posture assertion for the auto-close enforcement seam
|
|
3
|
+
* (mmnto-ai/totem#1762, E-lever addendum — strategy-claude 2026-07-21T0235Z; the
|
|
4
|
+
* squash-only extension — codex supplement 2026-07-21T0356Z).
|
|
5
|
+
*
|
|
6
|
+
* The operator flipped all four governed repos to
|
|
7
|
+
* `squash_merge_commit_title: PR_TITLE` + `squash_merge_commit_message: BLANK`
|
|
8
|
+
* (executed 2026-07-21T02:30Z). BLANK stops GitHub composing a squash body from
|
|
9
|
+
* COMMIT_MESSAGES, so the server-composed close-keyword channel is gone; PR_TITLE
|
|
10
|
+
* makes the squash subject deterministically the PR title (a surface D1 already
|
|
11
|
+
* scans pre-merge).
|
|
12
|
+
*
|
|
13
|
+
* D1 also asserts SQUASH-ONLY (`allow_squash_merge` on, `allow_merge_commit` and
|
|
14
|
+
* `allow_rebase_merge` off). This is what LICENSES D2's single-HEAD, `(#N)`-subject
|
|
15
|
+
* assumption: a rebase merge pushes several commits (an earlier close-keyword
|
|
16
|
+
* commit would never be scanned when only the final SHA is read), and a regular
|
|
17
|
+
* merge commit need not carry the squash-subject form (breaking receipt
|
|
18
|
+
* correlation). Enabling squash-only is an OPERATOR settings action (routed
|
|
19
|
+
* separately, like the E lever); until flipped, D1 reds loudly by design.
|
|
20
|
+
*
|
|
21
|
+
* A repo setting is one careless settings-page click from silently reverting — so
|
|
22
|
+
* D1 ASSERTS the whole posture at workflow start and fails loud on drift (Tenet 4
|
|
23
|
+
* parity-test rule applied to repo config; a "keep it set" intention is not a
|
|
24
|
+
* coupling mechanism). Candidate standing row for the mmnto-ai/totem-strategy#482
|
|
25
|
+
* parity manifest.
|
|
26
|
+
*
|
|
27
|
+
* Pure evaluator — thin GraphQL glue lives in the D1 script. The source is
|
|
28
|
+
* GraphQL (`squashMergeAllowed` / `mergeCommitAllowed` / `rebaseMergeAllowed` /
|
|
29
|
+
* `squashMergeCommitTitle` / `squashMergeCommitMessage`), NOT the REST repos
|
|
30
|
+
* endpoint: REST omits the merge-policy fields for callers without admin
|
|
31
|
+
* visibility, and the Actions `GITHUB_TOKEN` is such a caller — discovered on
|
|
32
|
+
* D1's first live run, where a healthy posture read as all-absent. That failure
|
|
33
|
+
* class gets its own verdict (`unverifiable`) so a token-visibility problem is
|
|
34
|
+
* never misreported as settings drift.
|
|
35
|
+
*/
|
|
36
|
+
/** The required squash-merge posture (the E lever). */
|
|
37
|
+
export declare const REQUIRED_SQUASH_MERGE_TITLE = "PR_TITLE";
|
|
38
|
+
export declare const REQUIRED_SQUASH_MERGE_MESSAGE = "BLANK";
|
|
39
|
+
/** The repo-config fields the posture assertion reads (absent/null = not visible). */
|
|
40
|
+
export interface MergeConfigPosture {
|
|
41
|
+
squash_merge_commit_title?: string | null;
|
|
42
|
+
squash_merge_commit_message?: string | null;
|
|
43
|
+
allow_squash_merge?: boolean | null;
|
|
44
|
+
allow_merge_commit?: boolean | null;
|
|
45
|
+
allow_rebase_merge?: boolean | null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Verdict class: `drift` = a field is PRESENT and wrong (settings action needed);
|
|
49
|
+
* `unverifiable` = no field is wrong but at least one is absent from the config
|
|
50
|
+
* source (token-visibility failure — do NOT touch settings on this verdict).
|
|
51
|
+
*/
|
|
52
|
+
export type MergeConfigStatus = 'conforms' | 'drift' | 'unverifiable';
|
|
53
|
+
/** Verdict of {@link evaluateMergeConfigPosture}. */
|
|
54
|
+
export interface MergeConfigVerdict {
|
|
55
|
+
/** True iff every field is present AND matches the required posture. */
|
|
56
|
+
conforms: boolean;
|
|
57
|
+
status: MergeConfigStatus;
|
|
58
|
+
/** Human-readable descriptions of each present-and-wrong field. */
|
|
59
|
+
drift: string[];
|
|
60
|
+
/** Field names the config source did not carry (token-visibility class). */
|
|
61
|
+
absent: string[];
|
|
62
|
+
/** Precise operator-facing message for the job log. */
|
|
63
|
+
message: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Evaluate whether a repo's merge config matches the required posture: the
|
|
67
|
+
* E-lever squash-body shape (`PR_TITLE` + `BLANK`) AND squash-only (`allow_squash_
|
|
68
|
+
* merge` on, merge-commit and rebase off). Returns the drift set (one entry per
|
|
69
|
+
* off-posture field) and a precise message; the caller fails the check when
|
|
70
|
+
* `!conforms`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function evaluateMergeConfigPosture(config: MergeConfigPosture): MergeConfigVerdict;
|
|
73
|
+
//# sourceMappingURL=merge-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-config.d.ts","sourceRoot":"","sources":["../../src/autoclose/merge-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,uDAAuD;AACvD,eAAO,MAAM,2BAA2B,aAAa,CAAC;AACtD,eAAO,MAAM,6BAA6B,UAAU,CAAC;AAErD,sFAAsF;AACtF,MAAM,WAAW,kBAAkB;IACjC,yBAAyB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,2BAA2B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,kBAAkB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,kBAAkB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,kBAAkB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CACrC;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,OAAO,GAAG,cAAc,CAAC;AAEtE,qDAAqD;AACrD,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,mEAAmE;IACnE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,CAiDzF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo merge-config posture assertion for the auto-close enforcement seam
|
|
3
|
+
* (mmnto-ai/totem#1762, E-lever addendum — strategy-claude 2026-07-21T0235Z; the
|
|
4
|
+
* squash-only extension — codex supplement 2026-07-21T0356Z).
|
|
5
|
+
*
|
|
6
|
+
* The operator flipped all four governed repos to
|
|
7
|
+
* `squash_merge_commit_title: PR_TITLE` + `squash_merge_commit_message: BLANK`
|
|
8
|
+
* (executed 2026-07-21T02:30Z). BLANK stops GitHub composing a squash body from
|
|
9
|
+
* COMMIT_MESSAGES, so the server-composed close-keyword channel is gone; PR_TITLE
|
|
10
|
+
* makes the squash subject deterministically the PR title (a surface D1 already
|
|
11
|
+
* scans pre-merge).
|
|
12
|
+
*
|
|
13
|
+
* D1 also asserts SQUASH-ONLY (`allow_squash_merge` on, `allow_merge_commit` and
|
|
14
|
+
* `allow_rebase_merge` off). This is what LICENSES D2's single-HEAD, `(#N)`-subject
|
|
15
|
+
* assumption: a rebase merge pushes several commits (an earlier close-keyword
|
|
16
|
+
* commit would never be scanned when only the final SHA is read), and a regular
|
|
17
|
+
* merge commit need not carry the squash-subject form (breaking receipt
|
|
18
|
+
* correlation). Enabling squash-only is an OPERATOR settings action (routed
|
|
19
|
+
* separately, like the E lever); until flipped, D1 reds loudly by design.
|
|
20
|
+
*
|
|
21
|
+
* A repo setting is one careless settings-page click from silently reverting — so
|
|
22
|
+
* D1 ASSERTS the whole posture at workflow start and fails loud on drift (Tenet 4
|
|
23
|
+
* parity-test rule applied to repo config; a "keep it set" intention is not a
|
|
24
|
+
* coupling mechanism). Candidate standing row for the mmnto-ai/totem-strategy#482
|
|
25
|
+
* parity manifest.
|
|
26
|
+
*
|
|
27
|
+
* Pure evaluator — thin GraphQL glue lives in the D1 script. The source is
|
|
28
|
+
* GraphQL (`squashMergeAllowed` / `mergeCommitAllowed` / `rebaseMergeAllowed` /
|
|
29
|
+
* `squashMergeCommitTitle` / `squashMergeCommitMessage`), NOT the REST repos
|
|
30
|
+
* endpoint: REST omits the merge-policy fields for callers without admin
|
|
31
|
+
* visibility, and the Actions `GITHUB_TOKEN` is such a caller — discovered on
|
|
32
|
+
* D1's first live run, where a healthy posture read as all-absent. That failure
|
|
33
|
+
* class gets its own verdict (`unverifiable`) so a token-visibility problem is
|
|
34
|
+
* never misreported as settings drift.
|
|
35
|
+
*/
|
|
36
|
+
/** The required squash-merge posture (the E lever). */
|
|
37
|
+
export const REQUIRED_SQUASH_MERGE_TITLE = 'PR_TITLE';
|
|
38
|
+
export const REQUIRED_SQUASH_MERGE_MESSAGE = 'BLANK';
|
|
39
|
+
/**
|
|
40
|
+
* Evaluate whether a repo's merge config matches the required posture: the
|
|
41
|
+
* E-lever squash-body shape (`PR_TITLE` + `BLANK`) AND squash-only (`allow_squash_
|
|
42
|
+
* merge` on, merge-commit and rebase off). Returns the drift set (one entry per
|
|
43
|
+
* off-posture field) and a precise message; the caller fails the check when
|
|
44
|
+
* `!conforms`.
|
|
45
|
+
*/
|
|
46
|
+
export function evaluateMergeConfigPosture(config) {
|
|
47
|
+
const drift = [];
|
|
48
|
+
const absent = [];
|
|
49
|
+
const check = (name, value, required) => {
|
|
50
|
+
if (value === null || value === undefined) {
|
|
51
|
+
absent.push(name);
|
|
52
|
+
}
|
|
53
|
+
else if (value !== required) {
|
|
54
|
+
drift.push(`${name} is ${typeof value === 'string' ? `"${value}"` : String(value)}, expected ${typeof required === 'string' ? `"${required}"` : String(required)}`);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
check('squash_merge_commit_title', config.squash_merge_commit_title, REQUIRED_SQUASH_MERGE_TITLE);
|
|
58
|
+
check('squash_merge_commit_message', config.squash_merge_commit_message, REQUIRED_SQUASH_MERGE_MESSAGE);
|
|
59
|
+
// Squash-only: squash on, merge-commit + rebase off (codex supplement — this
|
|
60
|
+
// licenses D2's single-HEAD `(#N)`-subject assumption).
|
|
61
|
+
check('allow_squash_merge', config.allow_squash_merge, true);
|
|
62
|
+
check('allow_merge_commit', config.allow_merge_commit, false);
|
|
63
|
+
check('allow_rebase_merge', config.allow_rebase_merge, false);
|
|
64
|
+
const status = drift.length > 0 ? 'drift' : absent.length > 0 ? 'unverifiable' : 'conforms';
|
|
65
|
+
const message = status === 'conforms'
|
|
66
|
+
? `Merge-config posture conforms: E lever (${REQUIRED_SQUASH_MERGE_TITLE} + ${REQUIRED_SQUASH_MERGE_MESSAGE}) + squash-only.`
|
|
67
|
+
: status === 'drift'
|
|
68
|
+
? `Merge-config posture DRIFTED from the required E-lever + squash-only posture: ` +
|
|
69
|
+
`${drift.join('; ')}${absent.length > 0 ? ` (also not visible to this token: ${absent.join(', ')})` : ''}. ` +
|
|
70
|
+
'Re-set it in repo Settings > General > Pull Requests before ' +
|
|
71
|
+
'merging — a reverted posture re-opens the server-composed close-keyword channel or ' +
|
|
72
|
+
'defeats D2 single-HEAD receipt correlation. mmnto-ai/totem#1762.'
|
|
73
|
+
: `Merge-config posture UNVERIFIABLE — the config source did not carry: ${absent.join(', ')}. ` +
|
|
74
|
+
'This is a token-visibility failure, NOT settings drift — do not touch repo settings on this ' +
|
|
75
|
+
'message. The REST repos endpoint omits merge-policy fields for non-admin callers (the Actions ' +
|
|
76
|
+
'GITHUB_TOKEN is one); the D1 glue must read the posture via GraphQL (squashMergeAllowed / ' +
|
|
77
|
+
'mergeCommitAllowed / rebaseMergeAllowed / squashMergeCommitTitle / squashMergeCommitMessage), ' +
|
|
78
|
+
'which a plain read token can see. mmnto-ai/totem#1762.';
|
|
79
|
+
return { conforms: status === 'conforms', status, drift, absent, message };
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=merge-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-config.js","sourceRoot":"","sources":["../../src/autoclose/merge-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,uDAAuD;AACvD,MAAM,CAAC,MAAM,2BAA2B,GAAG,UAAU,CAAC;AACtD,MAAM,CAAC,MAAM,6BAA6B,GAAG,OAAO,CAAC;AA+BrD;;;;;;GAMG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAA0B;IACnE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,MAAM,KAAK,GAAG,CACZ,IAAY,EACZ,KAA0C,EAC1C,QAA0B,EACpB,EAAE;QACR,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CACR,GAAG,IAAI,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CACxJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,CAAC,2BAA2B,EAAE,MAAM,CAAC,yBAAyB,EAAE,2BAA2B,CAAC,CAAC;IAClG,KAAK,CACH,6BAA6B,EAC7B,MAAM,CAAC,2BAA2B,EAClC,6BAA6B,CAC9B,CAAC;IACF,6EAA6E;IAC7E,wDAAwD;IACxD,KAAK,CAAC,oBAAoB,EAAE,MAAM,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;IAC7D,KAAK,CAAC,oBAAoB,EAAE,MAAM,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;IAC9D,KAAK,CAAC,oBAAoB,EAAE,MAAM,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;IAE9D,MAAM,MAAM,GACV,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;IAC/E,MAAM,OAAO,GACX,MAAM,KAAK,UAAU;QACnB,CAAC,CAAC,2CAA2C,2BAA2B,MAAM,6BAA6B,kBAAkB;QAC7H,CAAC,CAAC,MAAM,KAAK,OAAO;YAClB,CAAC,CAAC,gFAAgF;gBAChF,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qCAAqC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI;gBAC5G,8DAA8D;gBAC9D,qFAAqF;gBACrF,kEAAkE;YACpE,CAAC,CAAC,wEAAwE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBAC7F,8FAA8F;gBAC9F,gGAAgG;gBAChG,4FAA4F;gBAC5F,gGAAgG;gBAChG,wDAAwD,CAAC;IAEjE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-config.test.d.ts","sourceRoot":"","sources":["../../src/autoclose/merge-config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { evaluateMergeConfigPosture } from './merge-config.js';
|
|
3
|
+
/** A fully-conforming posture: E lever (PR_TITLE + BLANK) + squash-only. */
|
|
4
|
+
const CONFORMING = {
|
|
5
|
+
squash_merge_commit_title: 'PR_TITLE',
|
|
6
|
+
squash_merge_commit_message: 'BLANK',
|
|
7
|
+
allow_squash_merge: true,
|
|
8
|
+
allow_merge_commit: false,
|
|
9
|
+
allow_rebase_merge: false,
|
|
10
|
+
};
|
|
11
|
+
describe('evaluateMergeConfigPosture (D1 posture assertion, #1762 E-lever + squash-only)', () => {
|
|
12
|
+
it('conforms when all five fields match the required posture', () => {
|
|
13
|
+
const v = evaluateMergeConfigPosture(CONFORMING);
|
|
14
|
+
expect(v.conforms).toBe(true);
|
|
15
|
+
expect(v.drift).toEqual([]);
|
|
16
|
+
expect(v.message).toMatch(/conforms/i);
|
|
17
|
+
});
|
|
18
|
+
it('flags title drift', () => {
|
|
19
|
+
const v = evaluateMergeConfigPosture({
|
|
20
|
+
...CONFORMING,
|
|
21
|
+
squash_merge_commit_title: 'COMMIT_OR_PR_TITLE',
|
|
22
|
+
});
|
|
23
|
+
expect(v.conforms).toBe(false);
|
|
24
|
+
expect(v.drift).toHaveLength(1);
|
|
25
|
+
expect(v.drift[0]).toMatch(/squash_merge_commit_title/);
|
|
26
|
+
expect(v.message).toMatch(/DRIFTED/);
|
|
27
|
+
});
|
|
28
|
+
it('flags message drift', () => {
|
|
29
|
+
const v = evaluateMergeConfigPosture({
|
|
30
|
+
...CONFORMING,
|
|
31
|
+
squash_merge_commit_message: 'COMMIT_MESSAGES',
|
|
32
|
+
});
|
|
33
|
+
expect(v.conforms).toBe(false);
|
|
34
|
+
expect(v.drift).toHaveLength(1);
|
|
35
|
+
expect(v.drift[0]).toMatch(/squash_merge_commit_message/);
|
|
36
|
+
});
|
|
37
|
+
it('flags allow_squash_merge drift (must be on)', () => {
|
|
38
|
+
const v = evaluateMergeConfigPosture({ ...CONFORMING, allow_squash_merge: false });
|
|
39
|
+
expect(v.conforms).toBe(false);
|
|
40
|
+
expect(v.drift[0]).toMatch(/allow_squash_merge/);
|
|
41
|
+
});
|
|
42
|
+
it('flags allow_merge_commit drift (must be off — codex supplement)', () => {
|
|
43
|
+
const v = evaluateMergeConfigPosture({ ...CONFORMING, allow_merge_commit: true });
|
|
44
|
+
expect(v.conforms).toBe(false);
|
|
45
|
+
expect(v.drift[0]).toMatch(/allow_merge_commit/);
|
|
46
|
+
});
|
|
47
|
+
it('flags allow_rebase_merge drift (must be off — codex supplement)', () => {
|
|
48
|
+
const v = evaluateMergeConfigPosture({ ...CONFORMING, allow_rebase_merge: true });
|
|
49
|
+
expect(v.conforms).toBe(false);
|
|
50
|
+
expect(v.drift[0]).toMatch(/allow_rebase_merge/);
|
|
51
|
+
});
|
|
52
|
+
it('flags EVERY axis when all five drift', () => {
|
|
53
|
+
const v = evaluateMergeConfigPosture({
|
|
54
|
+
squash_merge_commit_title: 'COMMIT_OR_PR_TITLE',
|
|
55
|
+
squash_merge_commit_message: 'COMMIT_MESSAGES',
|
|
56
|
+
allow_squash_merge: false,
|
|
57
|
+
allow_merge_commit: true,
|
|
58
|
+
allow_rebase_merge: true,
|
|
59
|
+
});
|
|
60
|
+
expect(v.conforms).toBe(false);
|
|
61
|
+
expect(v.drift).toHaveLength(5);
|
|
62
|
+
});
|
|
63
|
+
it('all fields absent → UNVERIFIABLE, never reported as drift (token-visibility class)', () => {
|
|
64
|
+
// D1's first live run: the Actions GITHUB_TOKEN cannot see REST merge-policy
|
|
65
|
+
// fields, so a HEALTHY posture read as all-absent and was misreported as
|
|
66
|
+
// drift. Absent must be its own verdict with its own remedy (fix the read
|
|
67
|
+
// source, not the settings).
|
|
68
|
+
const v = evaluateMergeConfigPosture({});
|
|
69
|
+
expect(v.conforms).toBe(false);
|
|
70
|
+
expect(v.status).toBe('unverifiable');
|
|
71
|
+
expect(v.drift).toEqual([]);
|
|
72
|
+
expect(v.absent).toHaveLength(5);
|
|
73
|
+
expect(v.message).toMatch(/UNVERIFIABLE/);
|
|
74
|
+
expect(v.message).toMatch(/token-visibility/);
|
|
75
|
+
expect(v.message).not.toMatch(/DRIFTED/);
|
|
76
|
+
});
|
|
77
|
+
it('null fields (GraphQL null) behave as absent, not as drift', () => {
|
|
78
|
+
const v = evaluateMergeConfigPosture({
|
|
79
|
+
...CONFORMING,
|
|
80
|
+
squash_merge_commit_title: null,
|
|
81
|
+
});
|
|
82
|
+
expect(v.status).toBe('unverifiable');
|
|
83
|
+
expect(v.absent).toEqual(['squash_merge_commit_title']);
|
|
84
|
+
});
|
|
85
|
+
it('a present-and-wrong field wins over absent fields: status=drift, absentees named', () => {
|
|
86
|
+
const v = evaluateMergeConfigPosture({
|
|
87
|
+
allow_merge_commit: true,
|
|
88
|
+
});
|
|
89
|
+
expect(v.status).toBe('drift');
|
|
90
|
+
expect(v.drift).toHaveLength(1);
|
|
91
|
+
expect(v.absent).toHaveLength(4);
|
|
92
|
+
expect(v.message).toMatch(/DRIFTED/);
|
|
93
|
+
expect(v.message).toMatch(/not visible to this token/);
|
|
94
|
+
});
|
|
95
|
+
it('the current live totem posture (all three methods on) drifts on the two off-axes', () => {
|
|
96
|
+
// codex supplement: live gh api reported allow_merge_commit=true,
|
|
97
|
+
// allow_rebase_merge=true, allow_squash_merge=true — so squash-only fails
|
|
98
|
+
// until the operator flips it (D1 reds loudly by design until then).
|
|
99
|
+
const v = evaluateMergeConfigPosture({
|
|
100
|
+
...CONFORMING,
|
|
101
|
+
allow_merge_commit: true,
|
|
102
|
+
allow_rebase_merge: true,
|
|
103
|
+
});
|
|
104
|
+
expect(v.conforms).toBe(false);
|
|
105
|
+
expect(v.drift).toHaveLength(2);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=merge-config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-config.test.js","sourceRoot":"","sources":["../../src/autoclose/merge-config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,0BAA0B,EAA2B,MAAM,mBAAmB,CAAC;AAExF,4EAA4E;AAC5E,MAAM,UAAU,GAAuB;IACrC,yBAAyB,EAAE,UAAU;IACrC,2BAA2B,EAAE,OAAO;IACpC,kBAAkB,EAAE,IAAI;IACxB,kBAAkB,EAAE,KAAK;IACzB,kBAAkB,EAAE,KAAK;CAC1B,CAAC;AAEF,QAAQ,CAAC,gFAAgF,EAAE,GAAG,EAAE;IAC9F,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,GAAG,0BAA0B,CAAC,UAAU,CAAC,CAAC;QACjD,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5B,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,GAAG,0BAA0B,CAAC;YACnC,GAAG,UAAU;YACb,yBAAyB,EAAE,oBAAoB;SAChD,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;QACxD,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,GAAG,0BAA0B,CAAC;YACnC,GAAG,UAAU;YACb,2BAA2B,EAAE,iBAAiB;SAC/C,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,GAAG,0BAA0B,CAAC,EAAE,GAAG,UAAU,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC;QACnF,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,CAAC,GAAG,0BAA0B,CAAC,EAAE,GAAG,UAAU,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,CAAC,GAAG,0BAA0B,CAAC,EAAE,GAAG,UAAU,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,GAAG,0BAA0B,CAAC;YACnC,yBAAyB,EAAE,oBAAoB;YAC/C,2BAA2B,EAAE,iBAAiB;YAC9C,kBAAkB,EAAE,KAAK;YACzB,kBAAkB,EAAE,IAAI;YACxB,kBAAkB,EAAE,IAAI;SACzB,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oFAAoF,EAAE,GAAG,EAAE;QAC5F,6EAA6E;QAC7E,yEAAyE;QACzE,0EAA0E;QAC1E,6BAA6B;QAC7B,MAAM,CAAC,GAAG,0BAA0B,CAAC,EAAE,CAAC,CAAC;QACzC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACtC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAC1C,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAC9C,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,CAAC,GAAG,0BAA0B,CAAC;YACnC,GAAG,UAAU;YACb,yBAAyB,EAAE,IAAI;SAChC,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACtC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,MAAM,CAAC,GAAG,0BAA0B,CAAC;YACnC,kBAAkB,EAAE,IAAI;SACzB,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,kEAAkE;QAClE,0EAA0E;QAC1E,qEAAqE;QACrE,MAAM,CAAC,GAAG,0BAA0B,CAAC;YACnC,GAAG,UAAU;YACb,kBAAkB,EAAE,IAAI;YACxB,kBAAkB,EAAE,IAAI;SACzB,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declared-intent receipt + reconciliation for the auto-close enforcement seam
|
|
3
|
+
* (mmnto-ai/totem#1762).
|
|
4
|
+
*
|
|
5
|
+
* D1 (PR-time required check) scans the PR corpus — title, description, and ALL
|
|
6
|
+
* branch commit messages (config-verified: the governed repos compose squash
|
|
7
|
+
* bodies from `COMMIT_MESSAGES`, so every branch commit is a squash-seed input)
|
|
8
|
+
* — for close-keyword-adjacent refs via {@link findAutoCloseRefs}, and fails on
|
|
9
|
+
* any ref that is not AUTHORIZED.
|
|
10
|
+
*
|
|
11
|
+
* AUTHORIZATION IS PROVENANCE-DISTINCT (codex #3 — the circularity fix). GitHub
|
|
12
|
+
* DERIVES `closingIssuesReferences` FROM the PR body's own close keywords, so a
|
|
13
|
+
* body keyword would self-whitelist against it. The ONLY authorizing channel is
|
|
14
|
+
* therefore the provenance-distinct `totem-close` marker (an HTML comment or a
|
|
15
|
+
* `Totem-Close:` trailer the author writes — see {@link parseDeclaredCloseIntent}).
|
|
16
|
+
* `closingIssuesReferences` is recorded on the receipt as OBSERVED GitHub state
|
|
17
|
+
* (informational), never as an authorization. Author workflow: declare every
|
|
18
|
+
* intended close with the marker.
|
|
19
|
+
*
|
|
20
|
+
* D2 (post-merge reconciliation, OBSERVATION MODE) compares the merged HEAD
|
|
21
|
+
* commit message against the receipt via {@link reconcile}. It alerts loud —
|
|
22
|
+
* never auto-reopens — until positive+negative controls arm enforcement (the
|
|
23
|
+
* Tenet 9 sense→enforce gate).
|
|
24
|
+
*
|
|
25
|
+
* Never scan issue/PR COMMENT bodies anywhere — comments never auto-close.
|
|
26
|
+
*/
|
|
27
|
+
export declare const AUTO_CLOSE_RECEIPT_SCHEMA_VERSION = 2;
|
|
28
|
+
/**
|
|
29
|
+
* A GitHub `closingIssuesReferences` node (from the PR GraphQL/REST API): the
|
|
30
|
+
* issue GitHub itself recognizes as a linked closing reference for the PR.
|
|
31
|
+
* OBSERVED state — informational only, NEVER authorizing (GitHub derives it from
|
|
32
|
+
* body keywords).
|
|
33
|
+
*/
|
|
34
|
+
export interface ClosingIssueRef {
|
|
35
|
+
number: number;
|
|
36
|
+
/** `owner/repo` the issue lives in, when cross-repo; omitted for same-repo. */
|
|
37
|
+
repoWithOwner?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The durable D1→D2 receipt. `declaredByMarker` is the AUTHORIZING set (marker
|
|
41
|
+
* provenance only); `closingIssuesReferences` is OBSERVED GitHub state recorded
|
|
42
|
+
* for the audit trail but not used to authorize. Persisted as a GitHub Actions
|
|
43
|
+
* artifact keyed to the PR (see the D1 workflow script).
|
|
44
|
+
*/
|
|
45
|
+
export interface AutoCloseReceipt {
|
|
46
|
+
schemaVersion: number;
|
|
47
|
+
/** `owner/repo` the PR targets. */
|
|
48
|
+
repo: string;
|
|
49
|
+
prNumber: number;
|
|
50
|
+
/** PR head SHA at D1 time (lets D2 correlate the artifact to the merge). */
|
|
51
|
+
headSha: string;
|
|
52
|
+
/**
|
|
53
|
+
* AUTHORIZING set: normalized keys declared via the provenance-distinct
|
|
54
|
+
* `totem-close` marker/trailer ONLY. reconcile authorizes against THIS set.
|
|
55
|
+
*/
|
|
56
|
+
declaredByMarker: string[];
|
|
57
|
+
/**
|
|
58
|
+
* INFORMATIONAL: GitHub's derived `closingIssuesReferences` (normalized keys).
|
|
59
|
+
* Recorded for the audit trail; NOT authorizing (breaks the self-whitelist
|
|
60
|
+
* circularity — codex #3).
|
|
61
|
+
*/
|
|
62
|
+
closingIssuesReferences: string[];
|
|
63
|
+
/** Normalized keys the D1 corpus scan found (audit only). */
|
|
64
|
+
corpusFindings: string[];
|
|
65
|
+
generatedAt: string;
|
|
66
|
+
note: string;
|
|
67
|
+
}
|
|
68
|
+
/** A structured-intent reference the author explicitly declared. */
|
|
69
|
+
export interface DeclaredIntentRef {
|
|
70
|
+
qualifier?: string;
|
|
71
|
+
issue: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Parse the structured-intent declarations out of `text`. Returns the refs the
|
|
75
|
+
* author explicitly whitelisted for closure. Does NOT interpret close keywords —
|
|
76
|
+
* a marker carries bare/qualified refs only.
|
|
77
|
+
*/
|
|
78
|
+
export declare function parseDeclaredCloseIntent(text: string): DeclaredIntentRef[];
|
|
79
|
+
/** The D1 corpus surfaces (never includes comment bodies). */
|
|
80
|
+
export interface PrCorpus {
|
|
81
|
+
title: string;
|
|
82
|
+
body: string;
|
|
83
|
+
commitMessages: string[];
|
|
84
|
+
closingIssuesReferences: ClosingIssueRef[];
|
|
85
|
+
repo: string;
|
|
86
|
+
}
|
|
87
|
+
/** Result of the D1 corpus scan. `ok` iff nothing unauthorized was found. */
|
|
88
|
+
export interface PrScanResult {
|
|
89
|
+
ok: boolean;
|
|
90
|
+
/** Normalized keys found across the corpus. */
|
|
91
|
+
findings: string[];
|
|
92
|
+
/** AUTHORIZING set (marker-declared only) — the receipt payload. */
|
|
93
|
+
declaredByMarker: string[];
|
|
94
|
+
/** INFORMATIONAL: GitHub's derived closingIssuesReferences (normalized keys). */
|
|
95
|
+
closingIssuesReferences: string[];
|
|
96
|
+
/** Findings not authorized by the marker set — these fail the check. */
|
|
97
|
+
undeclared: string[];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* D1: scan the PR corpus (title + body + every branch commit message) for
|
|
101
|
+
* close-keyword-adjacent refs and split them into authorized vs undeclared. A
|
|
102
|
+
* finding is authorized ONLY by the provenance-distinct `totem-close` marker —
|
|
103
|
+
* NOT by GitHub's `closingIssuesReferences` (which GitHub derives from the same
|
|
104
|
+
* body keywords, so it would self-whitelist; codex #3). Comment bodies are NEVER
|
|
105
|
+
* part of the corpus.
|
|
106
|
+
*/
|
|
107
|
+
export declare function scanPrCorpus(corpus: PrCorpus): PrScanResult;
|
|
108
|
+
/** Assemble the durable D1 receipt from a corpus scan. */
|
|
109
|
+
export declare function buildReceipt(corpus: Pick<PrCorpus, 'repo'>, prNumber: number, headSha: string, scan: PrScanResult, now?: Date): AutoCloseReceipt;
|
|
110
|
+
export type ReconcileStatus = 'clean' | 'anomaly' | 'missing-receipt' | 'ambiguous-receipt' | 'unexpected-body';
|
|
111
|
+
export interface ReconcileResult {
|
|
112
|
+
status: ReconcileStatus;
|
|
113
|
+
/** Normalized keys found in the merged commit message. */
|
|
114
|
+
findings: string[];
|
|
115
|
+
/** Findings not covered by the receipt's authorizing set (the anomaly set). */
|
|
116
|
+
undeclared: string[];
|
|
117
|
+
/**
|
|
118
|
+
* OBSERVATION MODE: the issues an armed enforcer WOULD reopen. Reported for the
|
|
119
|
+
* audit trail; D2 never acts on it (no auto-reopen until controls pass).
|
|
120
|
+
*/
|
|
121
|
+
reopenCandidates: string[];
|
|
122
|
+
/**
|
|
123
|
+
* Whether the merged commit carried a non-empty BODY after RFC-822 trailer
|
|
124
|
+
* lines are stripped (mmnto-ai/totem#1762 addendum + the 0330Z trailer-strip
|
|
125
|
+
* fold-in). Under the E lever (squash message = BLANK) the body should be
|
|
126
|
+
* empty; a non-empty non-trailer body is the posture signal (`unexpected-body`).
|
|
127
|
+
*/
|
|
128
|
+
bodyPresent: boolean;
|
|
129
|
+
/** Precise operator-facing message for the job log. */
|
|
130
|
+
message: string;
|
|
131
|
+
}
|
|
132
|
+
/** Options for {@link reconcile}. */
|
|
133
|
+
export interface ReconcileOptions {
|
|
134
|
+
/** `owner/repo` the merge landed on (enables same-repo key equivalence). */
|
|
135
|
+
repo?: string;
|
|
136
|
+
/** Expected PR number — a receipt for a different PR is ambiguous. */
|
|
137
|
+
expectedPrNumber?: number;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* D2: reconcile the merged HEAD commit message against the D1 receipt.
|
|
141
|
+
* OBSERVATION MODE — every non-clean outcome ALERTS (the caller decides exit
|
|
142
|
+
* code); NONE reopens.
|
|
143
|
+
*
|
|
144
|
+
* - `clean` — no close-keyword-adjacent ref, or every ref is
|
|
145
|
+
* authorized. Quiet path (empty / trailer-only body).
|
|
146
|
+
* - `anomaly` — a closure-capable message with ≥1 UNAUTHORIZED ref.
|
|
147
|
+
* The zero-allowed-set (`declaredByMarker: []`) + a
|
|
148
|
+
* closure-capable message is the #2471 specimen.
|
|
149
|
+
* - `missing-receipt` — a closure-capable message but NO receipt (PR merged
|
|
150
|
+
* before D1 existed, or the artifact expired /
|
|
151
|
+
* could not be downloaded). Alert, never guess.
|
|
152
|
+
* - `ambiguous-receipt`— a closure-capable message but the receipt is malformed
|
|
153
|
+
* or is for a different PR. Alert, never guess.
|
|
154
|
+
* - `unexpected-body` — a non-empty non-trailer body under BLANK with NO
|
|
155
|
+
* unauthorized ref: posture-drift / `--body`-override
|
|
156
|
+
* evidence (no closure harm). The caller surfaces it as
|
|
157
|
+
* a non-failing signal (interpretation call).
|
|
158
|
+
*/
|
|
159
|
+
export declare function reconcile(receipt: AutoCloseReceipt | null, mergedBody: string, opts?: ReconcileOptions): ReconcileResult;
|
|
160
|
+
//# sourceMappingURL=receipt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../../src/autoclose/receipt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAQH,eAAO,MAAM,iCAAiC,IAAI,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B;;;;OAIG;IACH,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,6DAA6D;IAC7D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,oEAAoE;AACpE,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAUD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAY1E;AAgCD,8DAA8D;AAC9D,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,uBAAuB,EAAE,eAAe,EAAE,CAAC;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,oEAAoE;IACpE,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,iFAAiF;IACjF,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,wEAAwE;IACxE,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAOD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,YAAY,CAsB3D;AAED,0DAA0D;AAC1D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,EAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,YAAY,EAClB,GAAG,GAAE,IAAiB,GACrB,gBAAgB,CAgBlB;AAED,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,SAAS,GACT,iBAAiB,GACjB,mBAAmB,GACnB,iBAAiB,CAAC;AAEtB,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,eAAe,CAAC;IACxB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;;;OAGG;IACH,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B;;;;;OAKG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAYD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,gBAAgB,GAAG,IAAI,EAChC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,gBAAqB,GAC1B,eAAe,CAwCjB"}
|