@deftai/directive 0.119.8 → 0.119.10

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/verify-ac.js CHANGED
@@ -6,12 +6,13 @@
6
6
  * Primary name for the product-first done-gate; verify:literal-ac remains
7
7
  * the #3267 mechanism alias.
8
8
  */
9
+ import { spawnSync } from "node:child_process";
9
10
  import { existsSync, readdirSync, readFileSync } from "node:fs";
10
11
  import { join, resolve } from "node:path";
11
12
  import { fileURLToPath } from "node:url";
12
13
  import { resolveSessionCompletedVerifyAcTarget } from "@deftai/directive-core/check";
13
14
  import { formatRejectedLedger, resolveLiteralAcceptanceDetailed, } from "@deftai/directive-core/literal-acceptance";
14
- import { emitVerifyAcTerminalOutcome, evaluateVerifyAcFromPath, readPlanAcceptance, resolveAcceptanceGateProfile, } from "@deftai/directive-core/product-first-done-gate";
15
+ import { emitVerifyAcTerminalOutcome, evaluateVerifyAcFromPath, readAdmittedSourceDigest, readAdmittedSourceSentences, readPlanAcceptance, resolveAcceptanceGateProfile, } from "@deftai/directive-core/product-first-done-gate";
15
16
  /** Parse verify:ac CLI args. */
16
17
  export function parseArgs(argv) {
17
18
  const parsed = {
@@ -111,6 +112,84 @@ export function clampVerifyAcExit(ok, code) {
111
112
  return 2;
112
113
  return 1;
113
114
  }
115
+ /**
116
+ * Spec-path briefs persist the refused GitHub body under plan.metadata.issueBody
117
+ * (#4524 / #5055), including empty string when the origin body was empty. Live
118
+ * recovery must use the Bound-remedy harvest (Overview), not body-normative REST.
119
+ */
120
+ function planHasSpecPathRefusedBody(plan) {
121
+ const meta = asRecord(plan.metadata);
122
+ if (meta === null) {
123
+ return false;
124
+ }
125
+ return Object.hasOwn(meta, "issueBody") && typeof meta.issueBody === "string";
126
+ }
127
+ /**
128
+ * Spec-path admitted source = Overview harvest remainder (#5055).
129
+ * Fail closed when Overview is empty — do not fall through to the refused body.
130
+ */
131
+ function fetchSpecPathHarvest(plan) {
132
+ const narratives = asRecord(plan.narratives);
133
+ const overview = narratives?.Overview;
134
+ if (typeof overview === "string" && overview.trim().length > 0) {
135
+ return { ok: true, text: overview };
136
+ }
137
+ return {
138
+ ok: false,
139
+ reason: "Spec-path Bound-remedy harvest unavailable (Overview empty); refuse offline / restore from git",
140
+ };
141
+ }
142
+ /**
143
+ * Live REST body for the origin issue (body-normative admitted source, #5055).
144
+ * Fail closed on forge outage — do not skip.
145
+ */
146
+ function fetchOriginIssueBody(plan) {
147
+ const refs = Array.isArray(plan.references) ? plan.references : [];
148
+ let issueUrl = null;
149
+ for (const entry of refs) {
150
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
151
+ continue;
152
+ }
153
+ const row = entry;
154
+ if (row.type === "x-xbrief/github-issue" && typeof row.uri === "string") {
155
+ issueUrl = row.uri;
156
+ break;
157
+ }
158
+ }
159
+ if (issueUrl === null) {
160
+ return { ok: false, reason: "no github-issue reference on the brief for live REST" };
161
+ }
162
+ const match = issueUrl.match(/github\.com\/([^/]+)\/([^/]+)\/issues\/(\d+)/i);
163
+ if (match === null) {
164
+ return { ok: false, reason: `unparseable github-issue uri: ${issueUrl}` };
165
+ }
166
+ const owner = match[1] ?? "";
167
+ const repo = match[2] ?? "";
168
+ const number = match[3] ?? "";
169
+ const apiPath = `repos/${owner}/${repo}/issues/${number}`;
170
+ const proc = spawnSync("gh", ["api", apiPath, "--jq", ".body"], {
171
+ encoding: "utf8",
172
+ env: process.env,
173
+ });
174
+ if (proc.error) {
175
+ return { ok: false, reason: `forge outage: ${proc.error.message}` };
176
+ }
177
+ if (proc.status !== 0) {
178
+ const detail = `${proc.stderr ?? ""}${proc.stdout ?? ""}`.trim() || `gh api exited ${String(proc.status)}`;
179
+ return { ok: false, reason: `forge outage: ${detail}` };
180
+ }
181
+ return { ok: true, text: typeof proc.stdout === "string" ? proc.stdout : "" };
182
+ }
183
+ /**
184
+ * Live admitted-source text for digest compare / missing-pin recovery (#5055).
185
+ * Spec-path → Bound-remedy harvest; body-normative → origin issue body.
186
+ */
187
+ function fetchAdmittedSourceForPlan(plan) {
188
+ if (planHasSpecPathRefusedBody(plan)) {
189
+ return fetchSpecPathHarvest(plan);
190
+ }
191
+ return fetchOriginIssueBody(plan);
192
+ }
114
193
  /** Evaluate one or many xBRIEF paths; return worst non-zero code (fail closed). */
115
194
  function evaluatePaths(paths, options) {
116
195
  let worst = 0;
@@ -121,6 +200,28 @@ function evaluatePaths(paths, options) {
121
200
  if (!options.quiet && paths.length > 1) {
122
201
  process.stdout.write(`verify:ac — evaluating ${path}\n`);
123
202
  }
203
+ let fetchAdmittedSourceText;
204
+ try {
205
+ const raw = JSON.parse(readFileSync(path, "utf8"));
206
+ const root = asRecord(raw);
207
+ const plan = asRecord(root?.plan);
208
+ // Arm live admitted-source fetch when a pin is present (digest compare), a
209
+ // digest remains after pin delete (honor recorded digest), or Spec-path
210
+ // refused-body metadata marks harvest recovery (#5055). Spec-path callbacks
211
+ // return the Bound-remedy harvest, not the refused raw issue body. Body-
212
+ // normative both-deleted recovery prefers git HEAD / merge-base so
213
+ // pre-#5055 briefs without a pin are not suddenly floored by live REST.
214
+ if (plan !== null) {
215
+ const pin = readAdmittedSourceSentences(plan.acceptance);
216
+ const digest = readAdmittedSourceDigest(plan.acceptance);
217
+ if (pin !== null || digest !== null || planHasSpecPathRefusedBody(plan)) {
218
+ fetchAdmittedSourceText = () => fetchAdmittedSourceForPlan(plan);
219
+ }
220
+ }
221
+ }
222
+ catch {
223
+ // Path evaluation still runs; unreadable brief is handled inside evaluateVerifyAcFromPath.
224
+ }
124
225
  const result = evaluateVerifyAcFromPath(path, {
125
226
  projectRoot: options.projectRoot,
126
227
  quiet: options.quiet,
@@ -129,6 +230,7 @@ function evaluatePaths(paths, options) {
129
230
  captureFromNarratives: profile.captureFromNarratives,
130
231
  reuseMode: profile.reuseMode,
131
232
  env: process.env,
233
+ ...(fetchAdmittedSourceText !== undefined ? { fetchAdmittedSourceText } : {}),
132
234
  });
133
235
  if (result.message.length > 0) {
134
236
  if (result.ok) {
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ interface ParsedArgs {
3
+ projectRoot: string;
4
+ baseRef: string | null;
5
+ quiet: boolean;
6
+ error?: string;
7
+ }
8
+ export declare function parseArgs(argv: string[]): ParsedArgs;
9
+ export declare function run(argv: string[]): number;
10
+ export {};
11
+ //# sourceMappingURL=verify-class-checks.d.ts.map
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI for verify:class-checks (#4980 / #3145 class).
4
+ */
5
+ import { resolve } from "node:path";
6
+ import { classChecks } from "@deftai/directive-core";
7
+ import { isDirectEntrypoint } from "./entrypoint.js";
8
+ export function parseArgs(argv) {
9
+ const parsed = {
10
+ projectRoot: ".",
11
+ baseRef: null,
12
+ quiet: false,
13
+ };
14
+ for (let i = 0; i < argv.length; i += 1) {
15
+ const arg = argv[i];
16
+ if (arg === "--quiet") {
17
+ parsed.quiet = true;
18
+ }
19
+ else if (arg === "--project-root") {
20
+ const value = argv[i + 1];
21
+ if (value === undefined) {
22
+ return { ...parsed, error: "argument --project-root: expected one argument" };
23
+ }
24
+ parsed.projectRoot = value;
25
+ i += 1;
26
+ }
27
+ else if (arg?.startsWith("--project-root=")) {
28
+ parsed.projectRoot = arg.slice("--project-root=".length);
29
+ }
30
+ else if (arg === "--base-ref") {
31
+ const value = argv[i + 1];
32
+ if (value === undefined) {
33
+ return { ...parsed, error: "argument --base-ref: expected one argument" };
34
+ }
35
+ parsed.baseRef = value;
36
+ i += 1;
37
+ }
38
+ else if (arg?.startsWith("--base-ref=")) {
39
+ parsed.baseRef = arg.slice("--base-ref=".length);
40
+ }
41
+ else {
42
+ return { ...parsed, error: `unrecognized argument: ${arg}` };
43
+ }
44
+ }
45
+ return parsed;
46
+ }
47
+ export function run(argv) {
48
+ const args = parseArgs(argv);
49
+ if (args.error !== undefined) {
50
+ process.stderr.write(`verify_class_checks: ${args.error}\n`);
51
+ return 2;
52
+ }
53
+ const projectRoot = resolve(args.projectRoot);
54
+ const result = classChecks.evaluateClassChecks(projectRoot, {
55
+ baseRef: args.baseRef,
56
+ quiet: args.quiet,
57
+ });
58
+ if (result.exitCode === 0) {
59
+ if (!args.quiet) {
60
+ process.stdout.write(`${result.message}\n`);
61
+ }
62
+ }
63
+ else {
64
+ process.stderr.write(`${result.message}\n`);
65
+ }
66
+ return result.exitCode;
67
+ }
68
+ if (isDirectEntrypoint(import.meta.url)) {
69
+ process.exit(run(process.argv.slice(2)));
70
+ }
71
+ //# sourceMappingURL=verify-class-checks.js.map
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { spawnSync } from "node:child_process";
2
3
  /**
3
4
  * CLI for verify:completed-write-guard (#3679).
4
5
  */
@@ -55,6 +56,17 @@ export function run(argv) {
55
56
  const projectRoot = resolve(args.projectRoot);
56
57
  const result = evaluateCompletedWriteGuard(projectRoot, {
57
58
  ...(args.baseRef.length > 0 ? { baseRef: args.baseRef } : {}),
59
+ runGh: (command) => {
60
+ const proc = spawnSync(command[0] ?? "gh", command.slice(1), {
61
+ cwd: projectRoot,
62
+ encoding: "utf8",
63
+ timeout: 15_000,
64
+ });
65
+ return {
66
+ returncode: proc.status ?? 1,
67
+ stdout: proc.stdout ?? "",
68
+ };
69
+ },
58
70
  });
59
71
  if (result.message.length > 0 && !args.quiet) {
60
72
  if (result.code === 0) {
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ interface ParsedArgs {
3
+ promptFile?: string;
4
+ prompt?: string;
5
+ surfacesFile?: string;
6
+ briefOut?: string;
7
+ artifactOut?: string;
8
+ projectRoot: string;
9
+ quiet: boolean;
10
+ error?: string;
11
+ }
12
+ /** Parse verify-operator-scope-limit CLI args. */
13
+ export declare function parseArgs(argv: string[]): ParsedArgs;
14
+ /** Run the gate and return the process exit code (0 clean/warn, 2 config). */
15
+ export declare function run(argv: string[]): number;
16
+ export {};
17
+ //# sourceMappingURL=verify-operator-scope-limit.d.ts.map
@@ -0,0 +1,285 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Warn-first operator scope-limit check (#4545).
4
+ *
5
+ * Seeds a hard ceiling from an operator prompt (closed lexicon) and lists
6
+ * shipped surfaces not traceable to a recorded requirement line. Warn-first:
7
+ * untraceable surfaces print WARN and exit 0; config errors exit 2.
8
+ *
9
+ * Default path always persists a durable ceiling artifact (or merges into
10
+ * --brief-out). Without --surfaces-file, runs a default app/actions inventory;
11
+ * empty inventory warns that surfaces were not checked (does not silent-skip).
12
+ */
13
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
14
+ import { dirname, resolve } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+ import { applyCeilingToBrief, evaluateUntraceableSurfaces, inventoryDefaultSurfaces, OPERATOR_SCOPE_CEILING_ARTIFACT_REL, SURFACES_NOT_CHECKED_REMEDIATION, seedOperatorScopeCeiling, UNTRACEABLE_SURFACE_REMEDIATION, } from "@deftai/directive-core/operator-scope-limit";
17
+ /** Parse verify-operator-scope-limit CLI args. */
18
+ export function parseArgs(argv) {
19
+ const parsed = { quiet: false, projectRoot: "." };
20
+ for (let i = 0; i < argv.length; i += 1) {
21
+ const arg = argv[i];
22
+ if (arg === "--quiet") {
23
+ parsed.quiet = true;
24
+ }
25
+ else if (arg === "--prompt-file") {
26
+ const value = argv[i + 1];
27
+ if (value === undefined) {
28
+ return { ...parsed, error: "argument --prompt-file: expected one argument" };
29
+ }
30
+ parsed.promptFile = value;
31
+ i += 1;
32
+ }
33
+ else if (arg?.startsWith("--prompt-file=")) {
34
+ parsed.promptFile = arg.slice("--prompt-file=".length);
35
+ }
36
+ else if (arg === "--prompt") {
37
+ const value = argv[i + 1];
38
+ if (value === undefined) {
39
+ return { ...parsed, error: "argument --prompt: expected one argument" };
40
+ }
41
+ parsed.prompt = value;
42
+ i += 1;
43
+ }
44
+ else if (arg?.startsWith("--prompt=")) {
45
+ parsed.prompt = arg.slice("--prompt=".length);
46
+ }
47
+ else if (arg === "--surfaces-file") {
48
+ const value = argv[i + 1];
49
+ if (value === undefined) {
50
+ return { ...parsed, error: "argument --surfaces-file: expected one argument" };
51
+ }
52
+ parsed.surfacesFile = value;
53
+ i += 1;
54
+ }
55
+ else if (arg?.startsWith("--surfaces-file=")) {
56
+ parsed.surfacesFile = arg.slice("--surfaces-file=".length);
57
+ }
58
+ else if (arg === "--brief-out") {
59
+ const value = argv[i + 1];
60
+ if (value === undefined) {
61
+ return { ...parsed, error: "argument --brief-out: expected one argument" };
62
+ }
63
+ parsed.briefOut = value;
64
+ i += 1;
65
+ }
66
+ else if (arg?.startsWith("--brief-out=")) {
67
+ parsed.briefOut = arg.slice("--brief-out=".length);
68
+ }
69
+ else if (arg === "--artifact-out") {
70
+ const value = argv[i + 1];
71
+ if (value === undefined) {
72
+ return { ...parsed, error: "argument --artifact-out: expected one argument" };
73
+ }
74
+ parsed.artifactOut = value;
75
+ i += 1;
76
+ }
77
+ else if (arg?.startsWith("--artifact-out=")) {
78
+ parsed.artifactOut = arg.slice("--artifact-out=".length);
79
+ }
80
+ else if (arg === "--project-root") {
81
+ const value = argv[i + 1];
82
+ if (value === undefined) {
83
+ return { ...parsed, error: "argument --project-root: expected one argument" };
84
+ }
85
+ parsed.projectRoot = value;
86
+ i += 1;
87
+ }
88
+ else if (arg?.startsWith("--project-root=")) {
89
+ parsed.projectRoot = arg.slice("--project-root=".length);
90
+ }
91
+ else {
92
+ return { ...parsed, error: `unrecognized argument: ${arg}` };
93
+ }
94
+ }
95
+ return parsed;
96
+ }
97
+ function loadPrompt(args) {
98
+ if (typeof args.prompt === "string") {
99
+ return { ok: true, prompt: args.prompt };
100
+ }
101
+ if (typeof args.promptFile === "string" && args.promptFile.length > 0) {
102
+ try {
103
+ return { ok: true, prompt: readFileSync(resolve(args.promptFile), "utf8") };
104
+ }
105
+ catch (err) {
106
+ return {
107
+ ok: false,
108
+ detail: `failed to read --prompt-file: ${err instanceof Error ? err.message : String(err)}`,
109
+ };
110
+ }
111
+ }
112
+ return {
113
+ ok: false,
114
+ detail: "required: --prompt <text> or --prompt-file <path>",
115
+ };
116
+ }
117
+ function loadSurfacesFile(surfacesFile) {
118
+ try {
119
+ const raw = readFileSync(resolve(surfacesFile), "utf8");
120
+ const parsed = JSON.parse(raw);
121
+ if (!Array.isArray(parsed)) {
122
+ return { ok: false, detail: "--surfaces-file must be a JSON array" };
123
+ }
124
+ const surfaces = [];
125
+ for (const entry of parsed) {
126
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
127
+ return { ok: false, detail: "--surfaces-file entries must be objects" };
128
+ }
129
+ const obj = entry;
130
+ if ((obj.kind !== "server-action" && obj.kind !== "route" && obj.kind !== "page") ||
131
+ typeof obj.id !== "string" ||
132
+ obj.id.trim().length === 0) {
133
+ return {
134
+ ok: false,
135
+ detail: "--surfaces-file entries need kind (server-action|route|page) and id",
136
+ };
137
+ }
138
+ surfaces.push({
139
+ kind: obj.kind,
140
+ id: obj.id,
141
+ path: typeof obj.path === "string" ? obj.path : undefined,
142
+ });
143
+ }
144
+ return { ok: true, surfaces };
145
+ }
146
+ catch (err) {
147
+ return {
148
+ ok: false,
149
+ detail: `failed to read --surfaces-file: ${err instanceof Error ? err.message : String(err)}`,
150
+ };
151
+ }
152
+ }
153
+ function writeJsonFile(path, value) {
154
+ try {
155
+ mkdirSync(dirname(path), { recursive: true });
156
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`, "utf8");
157
+ return { ok: true };
158
+ }
159
+ catch (err) {
160
+ return {
161
+ ok: false,
162
+ detail: `failed to write ${path}: ${err instanceof Error ? err.message : String(err)}`,
163
+ };
164
+ }
165
+ }
166
+ function loadExistingBrief(path) {
167
+ if (!existsSync(path))
168
+ return null;
169
+ try {
170
+ const raw = JSON.parse(readFileSync(path, "utf8"));
171
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw))
172
+ return null;
173
+ return raw;
174
+ }
175
+ catch {
176
+ return null;
177
+ }
178
+ }
179
+ /** Persist ceiling: explicit outs, else default durable artifact under project root. */
180
+ function persistCeiling(input) {
181
+ const { projectRoot, ceiling, artifactOut, briefOut } = input;
182
+ let durablePath = null;
183
+ if (typeof artifactOut === "string" && artifactOut.length > 0) {
184
+ const path = resolve(artifactOut);
185
+ const wrote = writeJsonFile(path, ceiling);
186
+ if (!wrote.ok)
187
+ return wrote;
188
+ durablePath = path;
189
+ }
190
+ if (typeof briefOut === "string" && briefOut.length > 0) {
191
+ const path = resolve(briefOut);
192
+ const existing = loadExistingBrief(path);
193
+ const base = existing ??
194
+ {
195
+ xBRIEFInfo: { version: "0.8" },
196
+ plan: { status: "draft", metadata: {} },
197
+ };
198
+ // Merge/add ceiling onto existing proposed/active brief — never replace scope.
199
+ const merged = applyCeilingToBrief(base, ceiling);
200
+ const wrote = writeJsonFile(path, merged);
201
+ if (!wrote.ok)
202
+ return wrote;
203
+ durablePath = path;
204
+ }
205
+ if (durablePath === null) {
206
+ const path = resolve(projectRoot, OPERATOR_SCOPE_CEILING_ARTIFACT_REL);
207
+ const wrote = writeJsonFile(path, ceiling);
208
+ if (!wrote.ok)
209
+ return wrote;
210
+ durablePath = path;
211
+ }
212
+ return { ok: true, durablePath };
213
+ }
214
+ /** Run the gate and return the process exit code (0 clean/warn, 2 config). */
215
+ export function run(argv) {
216
+ const args = parseArgs(argv);
217
+ if (args.error !== undefined) {
218
+ process.stderr.write(`verify_operator_scope_limit: ${args.error}\n`);
219
+ return 2;
220
+ }
221
+ const projectRoot = resolve(args.projectRoot);
222
+ const promptLoad = loadPrompt(args);
223
+ if (!promptLoad.ok) {
224
+ process.stderr.write(`verify_operator_scope_limit: ${promptLoad.detail}\n`);
225
+ return 2;
226
+ }
227
+ const seeded = seedOperatorScopeCeiling(promptLoad.prompt, null);
228
+ if (!seeded.ok) {
229
+ process.stderr.write(`verify_operator_scope_limit: ${seeded.detail}\n`);
230
+ // No phrase is a returned miss — still exit 2 so callers know ceiling was not recorded.
231
+ return 2;
232
+ }
233
+ const persisted = persistCeiling({
234
+ projectRoot,
235
+ ceiling: seeded.ceiling,
236
+ artifactOut: args.artifactOut,
237
+ briefOut: args.briefOut,
238
+ });
239
+ if (!persisted.ok) {
240
+ process.stderr.write(`verify_operator_scope_limit: ${persisted.detail}\n`);
241
+ return 2;
242
+ }
243
+ let surfaces = [];
244
+ let surfacesSource = "default-inventory";
245
+ if (typeof args.surfacesFile === "string" && args.surfacesFile.length > 0) {
246
+ const surfacesLoad = loadSurfacesFile(args.surfacesFile);
247
+ if (!surfacesLoad.ok) {
248
+ process.stderr.write(`verify_operator_scope_limit: ${surfacesLoad.detail}\n`);
249
+ return 2;
250
+ }
251
+ surfaces = surfacesLoad.surfaces;
252
+ surfacesSource = "surfaces-file";
253
+ }
254
+ else {
255
+ surfaces = inventoryDefaultSurfaces(projectRoot);
256
+ surfacesSource = "default-inventory";
257
+ }
258
+ if (surfaces.length === 0) {
259
+ if (!args.quiet) {
260
+ process.stdout.write(`operator-scope-limit WARN: surfaces were not checked ` +
261
+ `(source=${surfacesSource}; durable=${persisted.durablePath}; ` +
262
+ `phrase=${JSON.stringify(seeded.ceiling.matchedPhrase)}; ` +
263
+ `requirements=${seeded.ceiling.requirementLines.length}). ` +
264
+ `Remediation: ${SURFACES_NOT_CHECKED_REMEDIATION}\n`);
265
+ }
266
+ // Warn-first: missing inventory does not fail the process.
267
+ return 0;
268
+ }
269
+ const result = evaluateUntraceableSurfaces({
270
+ requirementLines: seeded.ceiling.requirementLines,
271
+ surfaces,
272
+ });
273
+ if (!args.quiet) {
274
+ process.stdout.write(`${result.message} (durable=${persisted.durablePath}; source=${surfacesSource})\n`);
275
+ if (result.severity === "warn") {
276
+ process.stdout.write(`Remediation: ${UNTRACEABLE_SURFACE_REMEDIATION}\n`);
277
+ }
278
+ }
279
+ // Warn-first: untraceable surfaces do not fail the process.
280
+ return 0;
281
+ }
282
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
283
+ process.exit(run(process.argv.slice(2)));
284
+ }
285
+ //# sourceMappingURL=verify-operator-scope-limit.js.map
@@ -9,6 +9,11 @@ interface ParsedArgs {
9
9
  approach3: boolean;
10
10
  approach3Warned: boolean;
11
11
  emitJson: boolean;
12
+ /** When true, also run the #4882 merge-path arm observer (attested flags). */
13
+ mergePathArm: boolean;
14
+ liveWait: boolean;
15
+ explicitFinish: boolean;
16
+ stickyLease: boolean;
12
17
  help: boolean;
13
18
  error?: string;
14
19
  }