@deftai/directive-core 0.94.0 → 0.95.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/authz/classify.js +485 -0
- package/dist/doctor/main.js +41 -9
- package/dist/doctor/types.d.ts +2 -2
- package/dist/freshness/bind.d.ts +67 -0
- package/dist/freshness/bind.js +201 -0
- package/dist/freshness/cli.d.ts +30 -0
- package/dist/freshness/cli.js +180 -0
- package/dist/freshness/compare.d.ts +14 -0
- package/dist/freshness/compare.js +134 -0
- package/dist/freshness/generation.d.ts +44 -0
- package/dist/freshness/generation.js +172 -0
- package/dist/freshness/index.d.ts +13 -0
- package/dist/freshness/index.js +13 -0
- package/dist/freshness/report.d.ts +43 -0
- package/dist/freshness/report.js +139 -0
- package/dist/freshness/types.d.ts +70 -0
- package/dist/freshness/types.js +30 -0
- package/dist/handoff-evidence/index.d.ts +8 -0
- package/dist/handoff-evidence/index.js +7 -0
- package/dist/handoff-evidence/validate.d.ts +105 -0
- package/dist/handoff-evidence/validate.js +423 -0
- package/dist/hooks/dispatcher.d.ts +3 -0
- package/dist/hooks/dispatcher.js +12 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/init-deposit/agent-hooks.d.ts +1 -1
- package/dist/init-deposit/agent-hooks.js +5 -2
- package/dist/init-deposit/init-deposit.d.ts +7 -1
- package/dist/init-deposit/init-deposit.js +24 -4
- package/dist/init-deposit/refresh.d.ts +9 -1
- package/dist/init-deposit/refresh.js +48 -5
- package/dist/policy/index.d.ts +3 -0
- package/dist/policy/index.js +35 -0
- package/dist/release-e2e/greenfield-python-free-smoke.js +7 -3
- package/dist/session/ritual-entrypoint.d.ts +6 -2
- package/dist/session/ritual-entrypoint.js +15 -2
- package/dist/session/session-ready.js +31 -14
- package/dist/session/session-start.d.ts +2 -1
- package/dist/session/session-start.js +66 -3
- package/dist/session/verify-session-ritual.d.ts +4 -2
- package/dist/session/verify-session-ritual.js +11 -11
- package/dist/slash/product-set.js +4 -1
- package/dist/swarm/verify-review-clean.d.ts +4 -3
- package/dist/swarm/verify-review-clean.js +28 -73
- package/dist/triage/classify/index.d.ts +9 -0
- package/dist/triage/classify/index.js +34 -2
- package/dist/triage/classify/label-mirror.d.ts +143 -0
- package/dist/triage/classify/label-mirror.js +684 -0
- package/dist/triage/help/registry-data.d.ts +7 -7
- package/dist/triage/help/registry-data.js +27 -7
- package/dist/triage/queue/show.d.ts +1 -1
- package/dist/triage/queue/show.js +4 -2
- package/dist/vbrief-validate/project-definition.js +1 -1
- package/dist/verify-env/agent-hook-readiness.d.ts +42 -0
- package/dist/verify-env/agent-hook-readiness.js +150 -0
- package/dist/verify-env/agent-hooks-live-probe.d.ts +16 -4
- package/dist/verify-env/agent-hooks-live-probe.js +120 -107
- package/dist/verify-env/agent-hooks.js +11 -3
- package/dist/verify-env/index.d.ts +1 -0
- package/dist/verify-env/index.js +1 -0
- package/package.json +7 -3
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { hasArtifactSuffix } from "../layout/resolve.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { evaluateSlizardGate, isSlizardCheck } from "../pr-merge-readiness/slizard-gate.js";
|
|
4
|
+
import { computeGateResult, isMergeReady, } from "../pr-merge-readiness/compute.js";
|
|
5
|
+
import { VIA_ERROR, VIA_FALLBACK2 } from "../pr-merge-readiness/constants.js";
|
|
6
|
+
import { defaultRunGh } from "../pr-merge-readiness/gh.js";
|
|
8
7
|
import { EXIT_EXTERNAL_ERROR, EXIT_OK, EXIT_UNCLEAN } from "./constants.js";
|
|
9
8
|
function extractPrFromUri(uri) {
|
|
10
9
|
const pullIdx = uri.indexOf("/pull/");
|
|
@@ -104,83 +103,29 @@ export function resolveCohortFromVbriefs(vbriefGlobs) {
|
|
|
104
103
|
return { prNumbers: seenPrs, failures };
|
|
105
104
|
}
|
|
106
105
|
export function evaluatePr(prNumber, repo, runGh = defaultRunGh, options = {}) {
|
|
107
|
-
const
|
|
108
|
-
if (
|
|
106
|
+
const result = computeGateResult(prNumber, repo, runGh, options);
|
|
107
|
+
if (result.via === VIA_ERROR) {
|
|
109
108
|
return null;
|
|
110
109
|
}
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
const verdict = parseGreptileBody(body);
|
|
116
|
-
const failures = evaluateGates(prNumber, headSha, verdict);
|
|
117
|
-
let ciSummary = null;
|
|
118
|
-
let slizardSummary = null;
|
|
119
|
-
if (failures.length === 0) {
|
|
120
|
-
if (repo === null) {
|
|
121
|
-
failures.push("Could not resolve repo for required CI check-run gate. " +
|
|
122
|
-
"Use --repo OWNER/REPO or run from a checked-out repository.");
|
|
123
|
-
ciSummary = {
|
|
124
|
-
ready_state: "blocked",
|
|
125
|
-
error: "repo unresolved for check-runs lookup",
|
|
126
|
-
};
|
|
127
|
-
slizardSummary = { ready_state: "skipped", present: false };
|
|
128
|
-
}
|
|
129
|
-
else if (options.skipCi === true) {
|
|
130
|
-
const ci = evaluateCiGate([], { skipCi: true });
|
|
131
|
-
ciSummary = {
|
|
132
|
-
...ci.summary,
|
|
133
|
-
summary_line: "CI check-runs: skipped (--skip-ci)",
|
|
134
|
-
};
|
|
135
|
-
const slizard = evaluateSlizardGate([], options);
|
|
136
|
-
failures.push(...slizard.failures);
|
|
137
|
-
slizardSummary = { ...slizard.summary };
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
const checks = fetchCheckRunsRest(headSha, repo, runGh);
|
|
141
|
-
if (checks.summary === null) {
|
|
142
|
-
failures.push("Required CI check-runs could not be fetched; fail closed by default (#2169). " +
|
|
143
|
-
`Root cause: ${checks.error}`);
|
|
144
|
-
ciSummary = {
|
|
145
|
-
ready_state: "blocked",
|
|
146
|
-
error: checks.error,
|
|
147
|
-
checked_count: 0,
|
|
148
|
-
ignored_checks: [...(options.ignoreCheckNames ?? [])],
|
|
149
|
-
failed_required: [],
|
|
150
|
-
pending_required: [],
|
|
151
|
-
conclusions: [],
|
|
152
|
-
};
|
|
153
|
-
slizardSummary = { ready_state: "skipped", present: false };
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
const slizard = evaluateSlizardGate(checks.checkRuns, options);
|
|
157
|
-
// SLizard is scored by the structured gate; exclude it from the generic CI set.
|
|
158
|
-
const slizardNames = checks.checkRuns
|
|
159
|
-
.filter((r) => isSlizardCheck(r.name))
|
|
160
|
-
.map((r) => r.name);
|
|
161
|
-
const ci = evaluateCiGate(checks.checkRuns, {
|
|
162
|
-
skipCi: options.skipCi,
|
|
163
|
-
ignoreCheckNames: [...(options.ignoreCheckNames ?? []), ...slizardNames],
|
|
164
|
-
});
|
|
165
|
-
failures.push(...ci.failures, ...slizard.failures);
|
|
166
|
-
ciSummary = {
|
|
167
|
-
...ci.summary,
|
|
168
|
-
summary_line: buildCiSummaryLine(ci.summary),
|
|
169
|
-
};
|
|
170
|
-
slizardSummary = { ...slizard.summary };
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
110
|
+
const ciSummary = asRecord(result.partialData.ci);
|
|
111
|
+
const slizardSummary = asRecord(result.partialData.slizard);
|
|
174
112
|
return {
|
|
175
113
|
pr_number: prNumber,
|
|
176
|
-
head_sha: headSha,
|
|
177
|
-
verdict: { ...verdict },
|
|
178
|
-
failures: [...failures],
|
|
179
|
-
clean:
|
|
114
|
+
head_sha: result.headSha,
|
|
115
|
+
verdict: { ...result.verdict },
|
|
116
|
+
failures: [...result.failures],
|
|
117
|
+
clean: result.via !== VIA_FALLBACK2 && isMergeReady(result.failures),
|
|
180
118
|
ci_summary: ciSummary,
|
|
181
119
|
slizard_summary: slizardSummary,
|
|
120
|
+
via: result.via,
|
|
121
|
+
partial_data: { ...result.partialData },
|
|
182
122
|
};
|
|
183
123
|
}
|
|
124
|
+
function asRecord(value) {
|
|
125
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
126
|
+
? { ...value }
|
|
127
|
+
: null;
|
|
128
|
+
}
|
|
184
129
|
export function cohortResultToDict(cohort) {
|
|
185
130
|
return {
|
|
186
131
|
repo: cohort.repo,
|
|
@@ -194,6 +139,8 @@ export function cohortResultToDict(cohort) {
|
|
|
194
139
|
failures: r.failures,
|
|
195
140
|
ci_summary: r.ci_summary,
|
|
196
141
|
slizard_summary: r.slizard_summary,
|
|
142
|
+
via: r.via ?? null,
|
|
143
|
+
partial_data: r.partial_data ?? {},
|
|
197
144
|
})),
|
|
198
145
|
resolution_errors: cohort.resolution_errors,
|
|
199
146
|
};
|
|
@@ -216,6 +163,7 @@ export function renderReviewCleanText(cohort) {
|
|
|
216
163
|
lines.push("");
|
|
217
164
|
lines.push(` PR #${r.pr_number} -- ${status}`);
|
|
218
165
|
lines.push(` HEAD SHA: ${r.head_sha ?? "<unknown>"}`);
|
|
166
|
+
lines.push(` Gate via: ${r.via ?? "<unknown>"}`);
|
|
219
167
|
lines.push(` Greptile reviewed: ${String(v.lastReviewedSha ?? "<not parsed>")}`);
|
|
220
168
|
const conf = v.confidence;
|
|
221
169
|
lines.push(` Confidence: ${conf === null || conf === undefined ? "<not parsed>" : String(conf)}/5`);
|
|
@@ -228,6 +176,13 @@ export function renderReviewCleanText(cohort) {
|
|
|
228
176
|
if (r.slizard_summary && typeof r.slizard_summary.summary_line === "string") {
|
|
229
177
|
lines.push(` ${r.slizard_summary.summary_line}`);
|
|
230
178
|
}
|
|
179
|
+
const override = asRecord(r.partial_data?.verdict_override);
|
|
180
|
+
if (override !== null) {
|
|
181
|
+
lines.push(` Verdict override: ${String(override.reason ?? "<unknown>")}`);
|
|
182
|
+
if (typeof override.basis === "string") {
|
|
183
|
+
lines.push(` Override basis: ${override.basis}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
231
186
|
r.failures.forEach((fail, index) => {
|
|
232
187
|
lines.push(` [${index + 1}] ${fail}`);
|
|
233
188
|
});
|
|
@@ -85,4 +85,13 @@ export declare function validateProject(projectRoot: string): {
|
|
|
85
85
|
};
|
|
86
86
|
/** Render --list output for a project root. */
|
|
87
87
|
export declare function listProject(projectRoot: string): string;
|
|
88
|
+
import { type ClassifyAction, DEFAULT_IDEMPOTENCY_LABEL, defaultLabelMirrorPolicy, desiredLabelsForClassification, type LabelMirrorEngine, type LabelMirrorItem, type LabelMirrorOptions as LabelMirrorOptionsCore, type LabelMirrorOutcome, type LabelMirrorPolicy, type LabelMirrorStatus, labelMirrorOutcomeToJson, type ResolvedLabelMirrorPolicy, renderLabelMirrorReport, resolveLabelMirrorPolicy, validateLabelMirrorPolicy, validateTriageLabelMirrorOnPlan as validateTriageLabelMirrorOnPlanFromModule } from "./label-mirror.js";
|
|
89
|
+
export { type ClassifyAction, DEFAULT_IDEMPOTENCY_LABEL, defaultLabelMirrorPolicy, desiredLabelsForClassification, type LabelMirrorEngine, type LabelMirrorItem, type LabelMirrorOutcome, type LabelMirrorPolicy, type LabelMirrorStatus, labelMirrorOutcomeToJson, type ResolvedLabelMirrorPolicy, renderLabelMirrorReport, resolveLabelMirrorPolicy, validateLabelMirrorPolicy, validateTriageLabelMirrorOnPlanFromModule as validateTriageLabelMirrorOnPlan, };
|
|
90
|
+
/** Public options: engine is optional (defaults to this module's classify API). */
|
|
91
|
+
export type LabelMirrorOptions = Omit<LabelMirrorOptionsCore, "engine"> & {
|
|
92
|
+
readonly engine?: LabelMirrorEngine;
|
|
93
|
+
};
|
|
94
|
+
export { extractReferencedRepoIssueKeys } from "./label-mirror.js";
|
|
95
|
+
/** Tier-1 label mirror with the #1129 classify engine bound in. */
|
|
96
|
+
export declare function mirrorLabels(projectRoot: string, options?: LabelMirrorOptions): [number, LabelMirrorOutcome];
|
|
88
97
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -721,7 +721,9 @@ export function validateProject(projectRoot) {
|
|
|
721
721
|
const rel = projectDefinitionPath(root);
|
|
722
722
|
const classifyErrs = validateTriageAutoClassifyOnPlan(plan, rel);
|
|
723
723
|
const holderErrs = validateTriageHoldMarkersOnPlan(plan, rel);
|
|
724
|
-
|
|
724
|
+
// label-mirror validates plan.policy.triageLabelMirror (#1423); imported via re-export graph.
|
|
725
|
+
const mirrorErrs = validateTriageLabelMirrorOnPlanFromModule(plan, rel);
|
|
726
|
+
const errors = [...classifyErrs, ...holderErrs, ...mirrorErrs];
|
|
725
727
|
if (errors.length > 0) {
|
|
726
728
|
const lines = errors.map((err) => `FAIL: ${err}`);
|
|
727
729
|
lines.push("");
|
|
@@ -732,7 +734,7 @@ export function validateProject(projectRoot) {
|
|
|
732
734
|
const markers = resolveHoldMarkers({ projectRoot: root });
|
|
733
735
|
return {
|
|
734
736
|
code: 0,
|
|
735
|
-
stdout: "OK: triageAutoClassify[] + triageHoldMarkers[] valid " +
|
|
737
|
+
stdout: "OK: triageAutoClassify[] + triageHoldMarkers[] + triageLabelMirror valid " +
|
|
736
738
|
`(${rules.length} rules, ${markers.length} hold markers).\n`,
|
|
737
739
|
stderr: "",
|
|
738
740
|
};
|
|
@@ -744,4 +746,34 @@ export function listProject(projectRoot) {
|
|
|
744
746
|
const markers = resolveHoldMarkers({ projectRoot: root });
|
|
745
747
|
return `${renderList(rules, { holdMarkers: markers })}\n`;
|
|
746
748
|
}
|
|
749
|
+
// ---------------------------------------------------------------------------
|
|
750
|
+
// Tier-1 label mirror (#1423 Wave 1)
|
|
751
|
+
// label-mirror.ts does not import this module (avoids ESM/SLizard cycle).
|
|
752
|
+
// Public mirrorLabels injects the classify engine into the pure implementation.
|
|
753
|
+
// ---------------------------------------------------------------------------
|
|
754
|
+
import { DEFAULT_IDEMPOTENCY_LABEL, defaultLabelMirrorPolicy, desiredLabelsForClassification, labelMirrorOutcomeToJson, mirrorLabels as mirrorLabelsCore, renderLabelMirrorReport, resolveLabelMirrorPolicy, validateLabelMirrorPolicy, validateTriageLabelMirrorOnPlan as validateTriageLabelMirrorOnPlanFromModule, } from "./label-mirror.js";
|
|
755
|
+
export { DEFAULT_IDEMPOTENCY_LABEL, defaultLabelMirrorPolicy, desiredLabelsForClassification, labelMirrorOutcomeToJson, renderLabelMirrorReport, resolveLabelMirrorPolicy, validateLabelMirrorPolicy, validateTriageLabelMirrorOnPlanFromModule as validateTriageLabelMirrorOnPlan, };
|
|
756
|
+
function defaultLabelMirrorEngine() {
|
|
757
|
+
return {
|
|
758
|
+
classifyIssue: (issue, options) => classifyIssue(issue, {
|
|
759
|
+
rules: options?.rules,
|
|
760
|
+
holdMarkers: options?.holdMarkers,
|
|
761
|
+
vbriefReferenced: options?.vbriefReferenced,
|
|
762
|
+
hasTriageDecision: options?.hasTriageDecision,
|
|
763
|
+
now: options?.now,
|
|
764
|
+
}),
|
|
765
|
+
resolveClassifyRules,
|
|
766
|
+
resolveHoldMarkers,
|
|
767
|
+
extractReferencedIssues,
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
export { extractReferencedRepoIssueKeys } from "./label-mirror.js";
|
|
771
|
+
/** Tier-1 label mirror with the #1129 classify engine bound in. */
|
|
772
|
+
export function mirrorLabels(projectRoot, options = {}) {
|
|
773
|
+
const { engine, ...rest } = options;
|
|
774
|
+
return mirrorLabelsCore(projectRoot, {
|
|
775
|
+
...rest,
|
|
776
|
+
engine: engine ?? defaultLabelMirrorEngine(),
|
|
777
|
+
});
|
|
778
|
+
}
|
|
747
779
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier-1 deterministic SCM label mirror (#1423 Wave 1).
|
|
3
|
+
*
|
|
4
|
+
* Classifies cached issues with the existing #1129 engine, then mirrors the
|
|
5
|
+
* outcome as SCM labels (dry-run default, --apply to write). Never accepts into
|
|
6
|
+
* the xBRIEF lifecycle and never writes proposed/ scopes.
|
|
7
|
+
*
|
|
8
|
+
* Intentionally does NOT import from ./index.js (SLizard P1 cycle). The classify
|
|
9
|
+
* engine is injected via LabelMirrorEngine / mirrorLabels() wrapper in index.ts.
|
|
10
|
+
*/
|
|
11
|
+
import type { LabelClient } from "../../vbrief-reconcile/types.js";
|
|
12
|
+
export declare const DEFAULT_IDEMPOTENCY_LABEL = "triaged";
|
|
13
|
+
export declare const CACHE_DIR_NAME = ".deft-cache";
|
|
14
|
+
export declare const CACHE_SOURCE = "github-issue";
|
|
15
|
+
export type ClassifyAction = "defer" | "archive" | "escalate" | "accept";
|
|
16
|
+
/** Minimal issue shape used by the mirror (matches classify GitHubIssue). */
|
|
17
|
+
export interface MirrorGitHubIssue {
|
|
18
|
+
readonly number?: number;
|
|
19
|
+
readonly state?: string;
|
|
20
|
+
readonly body?: string | null;
|
|
21
|
+
readonly labels?: ReadonlyArray<{
|
|
22
|
+
name?: string;
|
|
23
|
+
} | string>;
|
|
24
|
+
readonly updated_at?: string;
|
|
25
|
+
readonly created_at?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface MirrorClassificationResult {
|
|
28
|
+
readonly action: string;
|
|
29
|
+
readonly reason: string;
|
|
30
|
+
readonly ruleIndex: number;
|
|
31
|
+
readonly ruleSource: string;
|
|
32
|
+
readonly ruleKind: string;
|
|
33
|
+
readonly resumeOn: string | null;
|
|
34
|
+
}
|
|
35
|
+
/** Injected classify engine — avoids a runtime import cycle with classify/index.ts. */
|
|
36
|
+
export interface LabelMirrorEngine {
|
|
37
|
+
readonly classifyIssue: (issue: MirrorGitHubIssue, options?: {
|
|
38
|
+
rules?: readonly unknown[];
|
|
39
|
+
holdMarkers?: string[] | null;
|
|
40
|
+
vbriefReferenced?: ReadonlySet<number> | null;
|
|
41
|
+
hasTriageDecision?: boolean;
|
|
42
|
+
now?: Date;
|
|
43
|
+
}) => MirrorClassificationResult | null;
|
|
44
|
+
readonly resolveClassifyRules: (options?: {
|
|
45
|
+
projectRoot?: string;
|
|
46
|
+
projectDefinition?: Record<string, unknown> | null;
|
|
47
|
+
}) => readonly unknown[];
|
|
48
|
+
readonly resolveHoldMarkers: (options?: {
|
|
49
|
+
projectRoot?: string;
|
|
50
|
+
projectDefinition?: Record<string, unknown> | null;
|
|
51
|
+
}) => string[];
|
|
52
|
+
/** Optional; label-mirror prefers repo-qualified keys and only needs numbers as fallback. */
|
|
53
|
+
readonly extractReferencedIssues?: (projectRoot?: string) => Set<number>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Repo-qualified xBRIEF github-issue keys (`owner/name\\0number`).
|
|
57
|
+
* Unlike number-only extractReferencedIssues, this never collides across repos.
|
|
58
|
+
*/
|
|
59
|
+
export declare function extractReferencedRepoIssueKeys(projectRoot?: string, lifecycleFolders?: readonly string[]): Set<string>;
|
|
60
|
+
export interface LabelMirrorPolicy {
|
|
61
|
+
/** When false, mirror is a no-op (default true when policy object is used). */
|
|
62
|
+
readonly enabled?: boolean;
|
|
63
|
+
/** Idempotency marker; issues already carrying this label are skipped. Default: triaged. */
|
|
64
|
+
readonly idempotencyLabel?: string;
|
|
65
|
+
/** Labels always applied on a successful classification (default: [idempotencyLabel]). */
|
|
66
|
+
readonly alwaysLabels?: readonly string[];
|
|
67
|
+
/** Map classify action -> additional labels to apply. */
|
|
68
|
+
readonly actionLabels?: Readonly<Partial<Record<ClassifyAction, readonly string[]>>>;
|
|
69
|
+
}
|
|
70
|
+
export interface ResolvedLabelMirrorPolicy {
|
|
71
|
+
readonly enabled: boolean;
|
|
72
|
+
readonly idempotencyLabel: string;
|
|
73
|
+
readonly alwaysLabels: readonly string[];
|
|
74
|
+
readonly actionLabels: Readonly<Partial<Record<ClassifyAction, readonly string[]>>>;
|
|
75
|
+
}
|
|
76
|
+
export type LabelMirrorStatus = "planned" | "applied" | "unchanged" | "skipped_already_triaged" | "skipped_no_match" | "skipped_unreadable" | "skipped_disabled" | "error";
|
|
77
|
+
export interface LabelMirrorItem {
|
|
78
|
+
readonly repo: string;
|
|
79
|
+
readonly issue_number: number;
|
|
80
|
+
readonly action: string | null;
|
|
81
|
+
readonly reason: string | null;
|
|
82
|
+
readonly ruleKind: string | null;
|
|
83
|
+
readonly current: readonly string[];
|
|
84
|
+
readonly desired: readonly string[];
|
|
85
|
+
readonly add: readonly string[];
|
|
86
|
+
readonly status: LabelMirrorStatus;
|
|
87
|
+
readonly message?: string;
|
|
88
|
+
}
|
|
89
|
+
export interface LabelMirrorOutcome {
|
|
90
|
+
readonly project_root: string;
|
|
91
|
+
readonly dry_run: boolean;
|
|
92
|
+
readonly scanned: number;
|
|
93
|
+
readonly planned: number;
|
|
94
|
+
readonly applied: number;
|
|
95
|
+
readonly unchanged: number;
|
|
96
|
+
readonly skipped_already_triaged: number;
|
|
97
|
+
readonly skipped_no_match: number;
|
|
98
|
+
readonly skipped_unreadable: number;
|
|
99
|
+
readonly errors: number;
|
|
100
|
+
readonly items: readonly LabelMirrorItem[];
|
|
101
|
+
readonly policy: ResolvedLabelMirrorPolicy;
|
|
102
|
+
}
|
|
103
|
+
export interface LabelMirrorOptions {
|
|
104
|
+
readonly dryRun?: boolean;
|
|
105
|
+
readonly repo?: string | null;
|
|
106
|
+
readonly cacheRoot?: string;
|
|
107
|
+
readonly client?: LabelClient;
|
|
108
|
+
readonly allowCrossRepo?: boolean;
|
|
109
|
+
readonly repoAllowlist?: readonly string[];
|
|
110
|
+
/** Prefer live SCM labels when true (default: !dryRun). Cache labels used for dry-run. */
|
|
111
|
+
readonly useLiveLabels?: boolean;
|
|
112
|
+
readonly now?: Date;
|
|
113
|
+
/** Required: classify engine (provided by classify/index mirrorLabels wrapper). */
|
|
114
|
+
readonly engine: LabelMirrorEngine;
|
|
115
|
+
}
|
|
116
|
+
/** Validate plan.policy.triageLabelMirror payload. */
|
|
117
|
+
export declare function validateLabelMirrorPolicy(raw: unknown): {
|
|
118
|
+
errors: string[];
|
|
119
|
+
warnings: string[];
|
|
120
|
+
};
|
|
121
|
+
/** Default resolved policy when triageLabelMirror is absent. */
|
|
122
|
+
export declare function defaultLabelMirrorPolicy(): ResolvedLabelMirrorPolicy;
|
|
123
|
+
/** Resolve effective label-mirror policy from PROJECT-DEFINITION or inline object. */
|
|
124
|
+
export declare function resolveLabelMirrorPolicy(options?: {
|
|
125
|
+
projectRoot?: string;
|
|
126
|
+
projectDefinition?: Record<string, unknown> | null;
|
|
127
|
+
override?: LabelMirrorPolicy | null;
|
|
128
|
+
}): ResolvedLabelMirrorPolicy;
|
|
129
|
+
/** Labels to apply for a classified action (always + action-mapped). */
|
|
130
|
+
export declare function desiredLabelsForClassification(action: string, policy: ResolvedLabelMirrorPolicy): string[];
|
|
131
|
+
/**
|
|
132
|
+
* Run Tier-1 label mirror over the github-issue cache.
|
|
133
|
+
* Dry-run by default (no SCM writes). Pass dryRun: false to apply.
|
|
134
|
+
* Requires options.engine (classify/index wrapper injects it).
|
|
135
|
+
*/
|
|
136
|
+
export declare function mirrorLabels(projectRoot: string, options: LabelMirrorOptions): [number, LabelMirrorOutcome];
|
|
137
|
+
/** Human-readable digest for dry-run / apply reports. */
|
|
138
|
+
export declare function renderLabelMirrorReport(outcome: LabelMirrorOutcome): string;
|
|
139
|
+
/** JSON-serializable outcome (stable key order not required). */
|
|
140
|
+
export declare function labelMirrorOutcomeToJson(outcome: LabelMirrorOutcome): Record<string, unknown>;
|
|
141
|
+
/** Validate triageLabelMirror on a plan object (vbrief_validate hook). */
|
|
142
|
+
export declare function validateTriageLabelMirrorOnPlan(plan: unknown, filepath: string): string[];
|
|
143
|
+
//# sourceMappingURL=label-mirror.d.ts.map
|