@bridge-ds/core 0.12.0 → 0.13.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/README.md +1 -1
- package/bridge.config.schema.json +5 -0
- package/dist/audit/index.js +3 -3
- package/dist/config.d.ts +5 -0
- package/dist/index.js +31 -28
- package/dist/node/index.js +3 -3
- package/dist/{prod-branch-BdMPKffE.js → prod-branch-6ftQWwdu.js} +41 -23
- package/dist/prod-branch-6ftQWwdu.js.map +1 -0
- package/dist/{report-DOnKUw8G.js → report-BeWNSjPk.js} +2 -2
- package/dist/{report-DOnKUw8G.js.map → report-BeWNSjPk.js.map} +1 -1
- package/dist/review-gate.d.ts +8 -1
- package/dist/rights.d.ts +20 -0
- package/dist/{suggestion-apply-DxXRGQrO.js → suggestion-apply-bH6-gZrE.js} +7 -6
- package/dist/suggestion-apply-bH6-gZrE.js.map +1 -0
- package/dist/suggestion-review.d.ts +4 -1
- package/package.json +1 -1
- package/dist/prod-branch-BdMPKffE.js.map +0 -1
- package/dist/suggestion-apply-DxXRGQrO.js.map +0 -1
package/dist/review-gate.d.ts
CHANGED
|
@@ -63,11 +63,18 @@ export interface ApprovalSummary {
|
|
|
63
63
|
design: boolean;
|
|
64
64
|
tech: boolean;
|
|
65
65
|
}
|
|
66
|
+
export interface ApprovalRules {
|
|
67
|
+
/**
|
|
68
|
+
* `governance.soloOwnerCanApproveBoth`: when the owners resolve to one person holding both roles, that person's
|
|
69
|
+
* approval counts for design and tech. Default false. The author still never approves their own change.
|
|
70
|
+
*/
|
|
71
|
+
soloOwnerCanApproveBoth?: boolean | undefined;
|
|
72
|
+
}
|
|
66
73
|
/** Latest decisive review per person (comments do not reset an approval), then owner coverage. */
|
|
67
74
|
export declare function summarizeApprovals(reviews: ReviewLike[], owners: {
|
|
68
75
|
design: string[];
|
|
69
76
|
tech: string[];
|
|
70
|
-
}, author?: string): ApprovalSummary;
|
|
77
|
+
}, author?: string, rules?: ApprovalRules): ApprovalSummary;
|
|
71
78
|
export type MissingApproval = 'design approval' | 'tech approval' | 'approval';
|
|
72
79
|
export interface MergeGate {
|
|
73
80
|
allowed: boolean;
|
package/dist/rights.d.ts
CHANGED
|
@@ -27,6 +27,26 @@ export declare function holdersOf(right: Right, owners: Owners, rights: Rights |
|
|
|
27
27
|
export declare function approverLists(owners: Owners, rights: Rights | null | undefined, teams?: TeamStates | null): Owners;
|
|
28
28
|
/** approverLists before team expansion: the entries as the config names them, for sentences. */
|
|
29
29
|
export declare function approverEntries(owners: Owners, rights: Rights | null | undefined): Owners;
|
|
30
|
+
/**
|
|
31
|
+
* The one person who holds both approver places, or null: the design and tech lists (after rights, teams expanded)
|
|
32
|
+
* name exactly one login between them, and it sits in both. A team, read or not, never counts as one person.
|
|
33
|
+
*/
|
|
34
|
+
export declare function soloApprover(owners: {
|
|
35
|
+
design: string[];
|
|
36
|
+
tech: string[];
|
|
37
|
+
}): string | null;
|
|
38
|
+
/**
|
|
39
|
+
* The only owner whose approval covers design and tech, or null when the rule is off or does not apply:
|
|
40
|
+
* `governance.soloOwnerCanApproveBoth` is true and the approver lists (after rights, teams expanded) name one person
|
|
41
|
+
* in both places. Studio Settings, the review screens, the MCP server and the CLI word it from this.
|
|
42
|
+
*/
|
|
43
|
+
export declare function soloOwnerOf(gov: {
|
|
44
|
+
owners: Owners;
|
|
45
|
+
rights?: Rights | null | undefined;
|
|
46
|
+
soloOwnerCanApproveBoth?: boolean | undefined;
|
|
47
|
+
}, teams?: TeamStates | null): string | null;
|
|
48
|
+
/** The rule in one sentence, for Settings, the CLI and the MCP server. `you`: the viewer is that owner. */
|
|
49
|
+
export declare function soloOwnerSentence(login: string, you?: boolean): string;
|
|
30
50
|
/** Who may ship, or null when nobody is singled out (no `rights`, or its groups list no logins): anyone with write access. */
|
|
31
51
|
export interface ShipPolicy {
|
|
32
52
|
/** Logins allowed to ship: people, and team members once read. A team not read keeps its "@org/slug" key. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cj as tokenBump, aQ as changeKind, L as LayeredTokenSet, aH as aliasOf, bZ as rgbaToDtcg, bn as hexToRgba, w as parseTokenFile, q as emptyTokenFile, s as serializeTokenFile, C as moveToken, r as removeToken, bq as inheritedTypeAt, u as upsertToken, H as readTokenAt, aW as comboKey, bY as renderedColor, b2 as contrastRatio, z as rgbaToHex, U as classifyRisk, W as RISK_LABELS, V as CONFIG_FILE, N as loadConfig, ak as ConfigError, _ as DEFAULT_TOKEN_PATHS, bl as globToRegExp, ae as slugify, Q as validateLayered, bI as parseJson, c1 as serializeJson, bN as plainEqual, ci as toPlain, bk as getEntry, bi as fromPlain, m as modeDisplayName, A as formatValue, X as previewLinks, a1 as readPreviewComment, aP as canShip, cq as whoCanShipSentence, cl as unreadableShipTeams, c4 as soloApprover, aL as approverLists, O as tokensPath, a6 as NEEDED_BY_LABEL, K as selectTokenFiles, R as parseContrastChecks } from "./prod-branch-6ftQWwdu.js";
|
|
2
2
|
function changesetBump(changes) {
|
|
3
3
|
return tokenBump(changes) ?? "patch";
|
|
4
4
|
}
|
|
@@ -2804,7 +2804,7 @@ function summarizeCi(runs, statuses = []) {
|
|
|
2804
2804
|
const state = total === 0 ? "none" : failed.length ? "fail" : pending.length ? "pending" : "pass";
|
|
2805
2805
|
return { state, total, passed, failed, pending };
|
|
2806
2806
|
}
|
|
2807
|
-
function summarizeApprovals(reviews, owners, author) {
|
|
2807
|
+
function summarizeApprovals(reviews, owners, author, rules = {}) {
|
|
2808
2808
|
const latest = /* @__PURE__ */ new Map();
|
|
2809
2809
|
const sorted = [...reviews].sort((a2, b) => String(a2.submitted_at ?? "").localeCompare(String(b.submitted_at ?? "")));
|
|
2810
2810
|
for (const r of sorted) {
|
|
@@ -2822,7 +2822,8 @@ function summarizeApprovals(reviews, owners, author) {
|
|
|
2822
2822
|
let tech;
|
|
2823
2823
|
if (d.length || t.length) {
|
|
2824
2824
|
design = d.length ? a.some((x) => d.includes(x)) : a.length > 0;
|
|
2825
|
-
const
|
|
2825
|
+
const solo = rules.soloOwnerCanApproveBoth ? soloApprover(owners) : null;
|
|
2826
|
+
const soloBoth = (x) => a.length === 1 && d.includes(x) && x !== solo;
|
|
2826
2827
|
tech = t.length ? a.some((x) => t.includes(x) && !soloBoth(x)) : a.length > 1;
|
|
2827
2828
|
} else {
|
|
2828
2829
|
design = a.length >= 1;
|
|
@@ -3088,7 +3089,7 @@ function summarizeSuggestionApprovals(comments, gov, opts) {
|
|
|
3088
3089
|
latestOld.delete(c.author);
|
|
3089
3090
|
reviews.push({ user: { login: c.author }, state: r.event === "approve" ? "APPROVED" : "CHANGES_REQUESTED", submitted_at: at });
|
|
3090
3091
|
});
|
|
3091
|
-
const summary = summarizeApprovals(reviews, lists, opts.author ?? void 0);
|
|
3092
|
+
const summary = summarizeApprovals(reviews, lists, opts.author ?? void 0, { soloOwnerCanApproveBoth: gov.soloOwnerCanApproveBoth });
|
|
3092
3093
|
const stale = [...latestOld.keys()].filter((l) => !summary.approvers.includes(l) && !summary.changesRequested.includes(l));
|
|
3093
3094
|
return { ...summary, stale, ignored: [...ignored].filter((l) => !summary.approvers.includes(l)) };
|
|
3094
3095
|
}
|
|
@@ -4425,7 +4426,7 @@ async function planSuggestionApply(input) {
|
|
|
4425
4426
|
for (const p of new Set(targets)) if (await ws.isSymlink(p)) links.push(`"${p}" is a symbolic link (or inside one): Bridge never writes through links.`);
|
|
4426
4427
|
if (links.length) return out("refused", "Not applied: the suggestion writes through a symbolic link.", { problems: links });
|
|
4427
4428
|
}
|
|
4428
|
-
const governance = input.governance ?? { owners: config.governance.owners, rights: config.governance.rights ?? null };
|
|
4429
|
+
const governance = input.governance ?? { owners: config.governance.owners, rights: config.governance.rights ?? null, soloOwnerCanApproveBoth: config.governance.soloOwnerCanApproveBoth };
|
|
4429
4430
|
const approvals = summarizeSuggestionApprovals(input.comments, governance, { payloadSha: parsed.sha, author: input.author });
|
|
4430
4431
|
const review = suggestionReviewState(payload.tier.tier, approvals);
|
|
4431
4432
|
const missing = pendingApprovals(payload.tier.tier, approvals);
|
|
@@ -4817,4 +4818,4 @@ export {
|
|
|
4817
4818
|
explorationNote as y,
|
|
4818
4819
|
explorationNotePath as z
|
|
4819
4820
|
};
|
|
4820
|
-
//# sourceMappingURL=suggestion-apply-
|
|
4821
|
+
//# sourceMappingURL=suggestion-apply-bH6-gZrE.js.map
|