@deftai/directive-core 0.96.0 → 0.97.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/cache/archive.js +10 -4
- package/dist/check/gate-lists.js +8 -0
- package/dist/consumer-check-contract/evaluate.d.ts +124 -0
- package/dist/consumer-check-contract/evaluate.js +699 -0
- package/dist/consumer-check-contract/index.d.ts +5 -0
- package/dist/consumer-check-contract/index.js +5 -0
- package/dist/delivery-attempt/disk-begin.d.ts +51 -0
- package/dist/delivery-attempt/disk-begin.js +68 -0
- package/dist/delivery-attempt/evaluate.d.ts +26 -0
- package/dist/delivery-attempt/evaluate.js +443 -0
- package/dist/delivery-attempt/fingerprint.d.ts +32 -0
- package/dist/delivery-attempt/fingerprint.js +100 -0
- package/dist/delivery-attempt/handoff.d.ts +25 -0
- package/dist/delivery-attempt/handoff.js +102 -0
- package/dist/delivery-attempt/index.d.ts +17 -0
- package/dist/delivery-attempt/index.js +17 -0
- package/dist/delivery-attempt/ledger.d.ts +169 -0
- package/dist/delivery-attempt/ledger.js +758 -0
- package/dist/delivery-attempt/material-delta.d.ts +38 -0
- package/dist/delivery-attempt/material-delta.js +126 -0
- package/dist/delivery-attempt/types.d.ts +210 -0
- package/dist/delivery-attempt/types.js +77 -0
- package/dist/doctor/index.d.ts +1 -0
- package/dist/doctor/index.js +1 -0
- package/dist/doctor/main.js +12 -0
- package/dist/doctor/openclaw-soft-rebind.d.ts +26 -0
- package/dist/doctor/openclaw-soft-rebind.js +164 -0
- package/dist/hooks/dispatcher.d.ts +2 -1
- package/dist/hooks/dispatcher.js +63 -9
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/init-deposit/gitignore.js +7 -0
- package/dist/init-deposit/init-deposit.js +5 -0
- package/dist/init-deposit/refresh.js +3 -0
- package/dist/pr-merge-readiness/ci-gate.d.ts +29 -1
- package/dist/pr-merge-readiness/ci-gate.js +191 -24
- package/dist/pr-merge-readiness/compute.js +10 -1
- package/dist/pr-merge-readiness/index.d.ts +2 -1
- package/dist/pr-merge-readiness/index.js +2 -1
- package/dist/pr-merge-readiness/output.js +14 -0
- package/dist/pr-merge-readiness/platform-status.d.ts +29 -0
- package/dist/pr-merge-readiness/platform-status.js +49 -0
- package/dist/pr-watch/constants.d.ts +10 -0
- package/dist/pr-watch/constants.js +12 -1
- package/dist/pr-watch/main.js +16 -1
- package/dist/pr-watch/probe.js +13 -1
- package/dist/pr-watch/types.d.ts +3 -2
- package/dist/pr-watch/watch.js +14 -7
- package/dist/scope-provenance/digest.d.ts +67 -0
- package/dist/scope-provenance/digest.js +188 -0
- package/dist/scope-provenance/evaluate.d.ts +82 -0
- package/dist/scope-provenance/evaluate.js +528 -0
- package/dist/scope-provenance/index.d.ts +6 -0
- package/dist/scope-provenance/index.js +6 -0
- package/dist/session/compact-ritual.d.ts +96 -0
- package/dist/session/compact-ritual.js +237 -0
- package/dist/session/compact-ritual.spec.d.ts +2 -0
- package/dist/session/compact-ritual.spec.js +21 -0
- package/dist/session/index.d.ts +2 -0
- package/dist/session/index.js +2 -0
- package/dist/session/openclaw-soft-rebind-deposit.d.ts +46 -0
- package/dist/session/openclaw-soft-rebind-deposit.js +165 -0
- package/dist/test-boundary/evaluate.d.ts +54 -0
- package/dist/test-boundary/evaluate.js +368 -0
- package/dist/test-boundary/index.d.ts +6 -0
- package/dist/test-boundary/index.js +6 -0
- package/dist/test-boundary/policy.d.ts +52 -0
- package/dist/test-boundary/policy.js +182 -0
- package/dist/triage/bootstrap/gitignore.d.ts +1 -1
- package/dist/triage/bootstrap/gitignore.js +15 -1
- package/dist/vbrief-activate/activate.js +22 -6
- package/dist/xbrief/styles.js +33 -17
- package/package.json +7 -3
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approved-scope digest helpers (#3145).
|
|
3
|
+
*
|
|
4
|
+
* At activation/approval time, record an immutable digest of the human-approved
|
|
5
|
+
* file_scope. PR verification compares the live active xBRIEF against this
|
|
6
|
+
* baseline so same-PR xBRIEF edits cannot self-authorize new paths.
|
|
7
|
+
*/
|
|
8
|
+
/** Immutable approved-scope record written under `.deft/approved-scope/`. */
|
|
9
|
+
export interface ApprovedScopeRecord {
|
|
10
|
+
readonly schemaVersion: 1;
|
|
11
|
+
/** Repo-relative path of the active xBRIEF at approval time. */
|
|
12
|
+
readonly xbriefRelPath: string;
|
|
13
|
+
readonly planId: string;
|
|
14
|
+
/** ISO-8601 UTC timestamp of approval / activation. */
|
|
15
|
+
readonly approvedAt: string;
|
|
16
|
+
/** Sorted unique file_scope paths frozen at approval. */
|
|
17
|
+
readonly fileScope: readonly string[];
|
|
18
|
+
/** sha256 hex of normalized file_scope lines. */
|
|
19
|
+
readonly fileScopeDigest: string;
|
|
20
|
+
/**
|
|
21
|
+
* Optional human-origin stamp (refs #2944). When present on renewal,
|
|
22
|
+
* re-approval is accepted. Agent-only stamps are ignored by evaluate.
|
|
23
|
+
*/
|
|
24
|
+
readonly humanApproval?: {
|
|
25
|
+
readonly kind: string;
|
|
26
|
+
readonly actor: string;
|
|
27
|
+
readonly mintedAt: string;
|
|
28
|
+
readonly mintedVia?: string;
|
|
29
|
+
};
|
|
30
|
+
/** Digest of the full xBRIEF canonical JSON body (optional stronger pin). */
|
|
31
|
+
readonly xbriefBodyDigest?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare const APPROVED_SCOPE_DIR = ".deft/approved-scope";
|
|
34
|
+
/** Normalize and sort scope paths for stable digests. */
|
|
35
|
+
export declare function normalizeFileScope(paths: readonly string[]): string[];
|
|
36
|
+
/** sha256 hex of normalized file_scope (one path per line). */
|
|
37
|
+
export declare function computeFileScopeDigest(paths: readonly string[]): string;
|
|
38
|
+
/** sha256 hex of raw UTF-8 text. */
|
|
39
|
+
export declare function computeTextDigest(text: string): string;
|
|
40
|
+
/** Extract plan.metadata.swarm.file_scope from an xBRIEF payload. */
|
|
41
|
+
export declare function extractFileScope(payload: unknown): string[];
|
|
42
|
+
/** Extract plan.id from an xBRIEF payload. */
|
|
43
|
+
export declare function extractPlanId(payload: unknown): string | null;
|
|
44
|
+
export declare function approvedScopeDir(projectRoot: string): string;
|
|
45
|
+
export declare function approvedScopeRecordPath(projectRoot: string, planId: string): string;
|
|
46
|
+
/** Build an ApprovedScopeRecord from xBRIEF payload + metadata. */
|
|
47
|
+
export declare function buildApprovedScopeRecord(input: {
|
|
48
|
+
readonly xbriefRelPath: string;
|
|
49
|
+
readonly payload: unknown;
|
|
50
|
+
readonly approvedAt?: string;
|
|
51
|
+
readonly humanApproval?: ApprovedScopeRecord["humanApproval"];
|
|
52
|
+
readonly xbriefRawText?: string;
|
|
53
|
+
}): ApprovedScopeRecord;
|
|
54
|
+
/** Persist approved-scope record (activation / renewed human approval). */
|
|
55
|
+
export declare function writeApprovedScopeRecord(projectRoot: string, record: ApprovedScopeRecord): string;
|
|
56
|
+
/** Load one approved-scope record by plan id, or null if missing. */
|
|
57
|
+
export declare function readApprovedScopeRecord(projectRoot: string, planId: string): ApprovedScopeRecord | null;
|
|
58
|
+
/** Load all approved-scope records under `.deft/approved-scope/`. */
|
|
59
|
+
export declare function listApprovedScopeRecords(projectRoot: string): ApprovedScopeRecord[];
|
|
60
|
+
/**
|
|
61
|
+
* Paths present in `current` but not in `approved` (normalized).
|
|
62
|
+
* These are the expansion set that cannot self-authorize.
|
|
63
|
+
*/
|
|
64
|
+
export declare function scopeExpansion(approved: readonly string[], current: readonly string[]): string[];
|
|
65
|
+
/** True when actor/kind look like human provenance (mirrors authz subset). */
|
|
66
|
+
export declare function isHumanApprovalStamp(stamp: ApprovedScopeRecord["humanApproval"] | null | undefined): boolean;
|
|
67
|
+
//# sourceMappingURL=digest.d.ts.map
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approved-scope digest helpers (#3145).
|
|
3
|
+
*
|
|
4
|
+
* At activation/approval time, record an immutable digest of the human-approved
|
|
5
|
+
* file_scope. PR verification compares the live active xBRIEF against this
|
|
6
|
+
* baseline so same-PR xBRIEF edits cannot self-authorize new paths.
|
|
7
|
+
*/
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync } from "node:fs";
|
|
10
|
+
import { basename, join, resolve } from "node:path";
|
|
11
|
+
import { containedWrite } from "../fs/contained-write.js";
|
|
12
|
+
export const APPROVED_SCOPE_DIR = ".deft/approved-scope";
|
|
13
|
+
/** Normalize and sort scope paths for stable digests. */
|
|
14
|
+
export function normalizeFileScope(paths) {
|
|
15
|
+
const out = new Set();
|
|
16
|
+
for (const p of paths) {
|
|
17
|
+
if (typeof p !== "string")
|
|
18
|
+
continue;
|
|
19
|
+
const n = p.trim().replace(/\\/g, "/").replace(/^\.\//, "");
|
|
20
|
+
if (n.length > 0)
|
|
21
|
+
out.add(n);
|
|
22
|
+
}
|
|
23
|
+
return [...out].sort((a, b) => a.localeCompare(b));
|
|
24
|
+
}
|
|
25
|
+
/** sha256 hex of normalized file_scope (one path per line). */
|
|
26
|
+
export function computeFileScopeDigest(paths) {
|
|
27
|
+
const normalized = normalizeFileScope(paths);
|
|
28
|
+
const payload = `${normalized.join("\n")}\n`;
|
|
29
|
+
return createHash("sha256").update(payload, "utf8").digest("hex");
|
|
30
|
+
}
|
|
31
|
+
/** sha256 hex of raw UTF-8 text. */
|
|
32
|
+
export function computeTextDigest(text) {
|
|
33
|
+
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
34
|
+
}
|
|
35
|
+
/** Extract plan.metadata.swarm.file_scope from an xBRIEF payload. */
|
|
36
|
+
export function extractFileScope(payload) {
|
|
37
|
+
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const plan = payload.plan;
|
|
41
|
+
if (plan === null || typeof plan !== "object" || Array.isArray(plan)) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
const metadata = plan.metadata;
|
|
45
|
+
if (metadata === null || typeof metadata !== "object" || Array.isArray(metadata)) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
const swarm = metadata.swarm;
|
|
49
|
+
if (swarm === null || typeof swarm !== "object" || Array.isArray(swarm)) {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
const fileScope = swarm.file_scope;
|
|
53
|
+
if (!Array.isArray(fileScope))
|
|
54
|
+
return [];
|
|
55
|
+
return fileScope.filter((x) => typeof x === "string");
|
|
56
|
+
}
|
|
57
|
+
/** Extract plan.id from an xBRIEF payload. */
|
|
58
|
+
export function extractPlanId(payload) {
|
|
59
|
+
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const plan = payload.plan;
|
|
63
|
+
if (plan === null || typeof plan !== "object" || Array.isArray(plan)) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const id = plan.id;
|
|
67
|
+
return typeof id === "string" && id.trim().length > 0 ? id.trim() : null;
|
|
68
|
+
}
|
|
69
|
+
export function approvedScopeDir(projectRoot) {
|
|
70
|
+
return join(resolve(projectRoot), ...APPROVED_SCOPE_DIR.split("/"));
|
|
71
|
+
}
|
|
72
|
+
export function approvedScopeRecordPath(projectRoot, planId) {
|
|
73
|
+
const safe = planId.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
74
|
+
return join(approvedScopeDir(projectRoot), `${safe}.json`);
|
|
75
|
+
}
|
|
76
|
+
/** Build an ApprovedScopeRecord from xBRIEF payload + metadata. */
|
|
77
|
+
export function buildApprovedScopeRecord(input) {
|
|
78
|
+
const planId = extractPlanId(input.payload) ?? basename(input.xbriefRelPath, ".xbrief.json");
|
|
79
|
+
const fileScope = normalizeFileScope(extractFileScope(input.payload));
|
|
80
|
+
const fileScopeDigest = computeFileScopeDigest(fileScope);
|
|
81
|
+
const approvedAt = input.approvedAt ?? new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
82
|
+
const record = {
|
|
83
|
+
schemaVersion: 1,
|
|
84
|
+
xbriefRelPath: input.xbriefRelPath.replace(/\\/g, "/"),
|
|
85
|
+
planId,
|
|
86
|
+
approvedAt,
|
|
87
|
+
fileScope,
|
|
88
|
+
fileScopeDigest,
|
|
89
|
+
};
|
|
90
|
+
if (input.humanApproval !== undefined) {
|
|
91
|
+
return {
|
|
92
|
+
...record,
|
|
93
|
+
humanApproval: input.humanApproval,
|
|
94
|
+
xbriefBodyDigest: input.xbriefRawText !== undefined ? computeTextDigest(input.xbriefRawText) : undefined,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (input.xbriefRawText !== undefined) {
|
|
98
|
+
return { ...record, xbriefBodyDigest: computeTextDigest(input.xbriefRawText) };
|
|
99
|
+
}
|
|
100
|
+
return record;
|
|
101
|
+
}
|
|
102
|
+
/** Persist approved-scope record (activation / renewed human approval). */
|
|
103
|
+
export function writeApprovedScopeRecord(projectRoot, record) {
|
|
104
|
+
const dir = approvedScopeDir(projectRoot);
|
|
105
|
+
mkdirSync(dir, { recursive: true });
|
|
106
|
+
const path = approvedScopeRecordPath(projectRoot, record.planId);
|
|
107
|
+
containedWrite({
|
|
108
|
+
root: resolve(projectRoot),
|
|
109
|
+
target: path,
|
|
110
|
+
data: `${JSON.stringify(record, null, 2)}\n`,
|
|
111
|
+
mode: "replace",
|
|
112
|
+
});
|
|
113
|
+
return path;
|
|
114
|
+
}
|
|
115
|
+
/** Load one approved-scope record by plan id, or null if missing. */
|
|
116
|
+
export function readApprovedScopeRecord(projectRoot, planId) {
|
|
117
|
+
const path = approvedScopeRecordPath(projectRoot, planId);
|
|
118
|
+
if (!existsSync(path))
|
|
119
|
+
return null;
|
|
120
|
+
try {
|
|
121
|
+
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
122
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw))
|
|
123
|
+
return null;
|
|
124
|
+
const rec = raw;
|
|
125
|
+
if (typeof rec.fileScopeDigest !== "string" || !Array.isArray(rec.fileScope))
|
|
126
|
+
return null;
|
|
127
|
+
return raw;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Load all approved-scope records under `.deft/approved-scope/`. */
|
|
134
|
+
export function listApprovedScopeRecords(projectRoot) {
|
|
135
|
+
const dir = approvedScopeDir(projectRoot);
|
|
136
|
+
if (!existsSync(dir))
|
|
137
|
+
return [];
|
|
138
|
+
const out = [];
|
|
139
|
+
for (const name of readdirSync(dir)) {
|
|
140
|
+
if (!name.endsWith(".json"))
|
|
141
|
+
continue;
|
|
142
|
+
try {
|
|
143
|
+
const raw = JSON.parse(readFileSync(join(dir, name), "utf8"));
|
|
144
|
+
if (raw !== null && typeof raw === "object" && !Array.isArray(raw)) {
|
|
145
|
+
const rec = raw;
|
|
146
|
+
if (typeof rec.fileScopeDigest === "string")
|
|
147
|
+
out.push(rec);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// skip malformed
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Paths present in `current` but not in `approved` (normalized).
|
|
158
|
+
* These are the expansion set that cannot self-authorize.
|
|
159
|
+
*/
|
|
160
|
+
export function scopeExpansion(approved, current) {
|
|
161
|
+
const base = new Set(normalizeFileScope(approved));
|
|
162
|
+
return normalizeFileScope(current).filter((p) => !base.has(p));
|
|
163
|
+
}
|
|
164
|
+
/** True when actor/kind look like human provenance (mirrors authz subset). */
|
|
165
|
+
export function isHumanApprovalStamp(stamp) {
|
|
166
|
+
if (stamp === null || stamp === undefined)
|
|
167
|
+
return false;
|
|
168
|
+
const kind = (stamp.kind ?? "").trim().toLowerCase();
|
|
169
|
+
const actor = (stamp.actor ?? "").trim().toLowerCase();
|
|
170
|
+
if (kind.length === 0 || actor.length === 0)
|
|
171
|
+
return false;
|
|
172
|
+
if (actor === "agent" || actor.startsWith("agent:") || actor === "self")
|
|
173
|
+
return false;
|
|
174
|
+
if (kind === "agent" || kind === "self" || kind === "xbrief" || kind === "dispatch")
|
|
175
|
+
return false;
|
|
176
|
+
// Accept common human kinds from #2944 surface
|
|
177
|
+
const humanKinds = new Set([
|
|
178
|
+
"cli",
|
|
179
|
+
"operator",
|
|
180
|
+
"human",
|
|
181
|
+
"user",
|
|
182
|
+
"github-user",
|
|
183
|
+
"interactive",
|
|
184
|
+
"renewed-approval",
|
|
185
|
+
]);
|
|
186
|
+
return humanKinds.has(kind) || kind.startsWith("human");
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=digest.js.map
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* verify:scope-provenance evaluation (#3145).
|
|
3
|
+
*
|
|
4
|
+
* Detects same-PR active xBRIEF expansion that would self-authorize new
|
|
5
|
+
* implementation paths. Requires renewed human approval (updated digest record
|
|
6
|
+
* with human stamp); the modified xBRIEF alone is never sufficient.
|
|
7
|
+
*
|
|
8
|
+
* Three-state exit: 0 clean / 1 self-authorization / 2 config.
|
|
9
|
+
* Migration: missing approved-scope records → warn (exit 0) unless --enforce.
|
|
10
|
+
*/
|
|
11
|
+
import { type ApprovedScopeRecord } from "./digest.js";
|
|
12
|
+
export type ScopeProvenanceViolationKind = "self-authorizing-scope-expansion" | "active-xbrief-modified-without-digest" | "digest-mismatch-without-renewal";
|
|
13
|
+
export interface ScopeProvenanceFinding {
|
|
14
|
+
readonly xbriefRelPath: string;
|
|
15
|
+
readonly planId: string;
|
|
16
|
+
readonly kind: ScopeProvenanceViolationKind;
|
|
17
|
+
readonly expandedPaths: readonly string[];
|
|
18
|
+
readonly detail: string;
|
|
19
|
+
readonly remediation: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ScopeProvenanceResult {
|
|
22
|
+
readonly exitCode: 0 | 1 | 2;
|
|
23
|
+
readonly findings: readonly ScopeProvenanceFinding[];
|
|
24
|
+
readonly message: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ScopeProvenanceOptions {
|
|
27
|
+
/**
|
|
28
|
+
* When true, missing digests on modified active xBRIEFs fail closed.
|
|
29
|
+
* Default false = migration warn path.
|
|
30
|
+
*/
|
|
31
|
+
readonly enforce?: boolean;
|
|
32
|
+
/** Base ref for diff (default HEAD). */
|
|
33
|
+
readonly baseRef?: string;
|
|
34
|
+
/** Inject changed files (repo-relative POSIX). */
|
|
35
|
+
readonly changedFiles?: readonly string[];
|
|
36
|
+
/** Inject active xBRIEF payloads: relPath -> raw JSON text. */
|
|
37
|
+
readonly activeXbriefs?: ReadonlyMap<string, string>;
|
|
38
|
+
/** Inject approved records (skips disk). */
|
|
39
|
+
readonly approvedRecords?: readonly ApprovedScopeRecord[];
|
|
40
|
+
/** Inject renewed-approval stamps keyed by planId (test seam). */
|
|
41
|
+
readonly renewedApprovals?: ReadonlyMap<string, ApprovedScopeRecord["humanApproval"]>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Resolve a PR-aware base ref. Bare `HEAD` only shows uncommitted changes, so
|
|
45
|
+
* CI/PR checkouts would miss committed active-xBRIEF expansion. Prefer
|
|
46
|
+
* origin/master (or main) for merge-base comparison.
|
|
47
|
+
* Returns null when no merge-base candidate exists (caller fails closed).
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveDefaultBaseRef(projectRoot: string): string | null;
|
|
50
|
+
/**
|
|
51
|
+
* Normalize git --name-only paths (including C-quoted paths).
|
|
52
|
+
* Decode C-quotes BEFORE converting remaining backslashes to `/` so escape
|
|
53
|
+
* sequences are not destroyed. Consecutive octal escapes decode as UTF-8
|
|
54
|
+
* bytes (e.g. \\303\\251 → é) so Unicode xBRIEF paths match filesystem names.
|
|
55
|
+
*/
|
|
56
|
+
export declare function unquoteGitPath(raw: string): string;
|
|
57
|
+
/** Normalize repo-relative paths for exact set membership (always POSIX separators). */
|
|
58
|
+
export declare function normalizeRepoRelPath(p: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* True when `rel` appears in the changed-path set under any normalization that
|
|
61
|
+
* Git C-quoting / slash folding may produce (Greptile conf=4 residual).
|
|
62
|
+
*/
|
|
63
|
+
export declare function changedSetHasPath(changedSet: ReadonlySet<string>, rel: string): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Pure evaluation of one active xBRIEF against its approved baseline.
|
|
66
|
+
* Exported for unit tests without git.
|
|
67
|
+
*/
|
|
68
|
+
export declare function evaluateOneScopeProvenance(input: {
|
|
69
|
+
readonly xbriefRelPath: string;
|
|
70
|
+
readonly currentPayload: unknown;
|
|
71
|
+
readonly approved: ApprovedScopeRecord | null;
|
|
72
|
+
readonly xbriefModifiedInChangeSet: boolean;
|
|
73
|
+
readonly enforce: boolean;
|
|
74
|
+
readonly renewedHumanApproval?: ApprovedScopeRecord["humanApproval"] | null;
|
|
75
|
+
}): ScopeProvenanceFinding | null;
|
|
76
|
+
/**
|
|
77
|
+
* Evaluate scope provenance for a project (or pure injected seams).
|
|
78
|
+
*/
|
|
79
|
+
export declare function evaluateScopeProvenance(projectRoot: string, options?: ScopeProvenanceOptions): ScopeProvenanceResult;
|
|
80
|
+
/** Re-export builder for activation hook callers. */
|
|
81
|
+
export { buildApprovedScopeRecord, writeApprovedScopeRecord } from "./digest.js";
|
|
82
|
+
//# sourceMappingURL=evaluate.d.ts.map
|