@peterxiaoyang/superspec 0.1.5 → 0.1.6

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.
@@ -7,9 +7,17 @@ export type ParsedArgs = {
7
7
  artifact?: string;
8
8
  gate?: string;
9
9
  task_id?: string;
10
+ test_id?: string;
11
+ phase?: "red" | "characterization" | "green";
10
12
  role?: string;
11
13
  evidence_kind?: string;
12
14
  round?: number;
15
+ executor_report_refs?: string[];
16
+ task_code_review_report_refs?: string[];
17
+ apply_worker_chain_refs?: string[];
18
+ green_test_run_evidence_refs?: string[];
19
+ red_test_run_evidence_refs?: string[];
20
+ characterization_test_run_evidence_refs?: string[];
13
21
  create?: boolean;
14
22
  force_unlock?: boolean;
15
23
  rebuild_corrupt?: boolean;
@@ -22,12 +22,22 @@ const COMMANDS = [
22
22
  "check-task-complete",
23
23
  "workflow-packet",
24
24
  "review-packet",
25
+ "apply-test-packet",
26
+ "apply-executor-packet",
27
+ "apply-code-review-packet",
28
+ "apply-verify-packet",
25
29
  "ledger-render",
26
30
  ];
27
31
  const COMMAND_LIST = COMMANDS.join(",");
28
32
  const COMMAND_CHOICES = COMMANDS.map((item) => `'${item}'`).join(", ");
29
33
  function isPacketCommand(command) {
30
- return command === "workflow-packet" || command === "review-packet" || command === "ledger-render";
34
+ return command === "workflow-packet"
35
+ || command === "review-packet"
36
+ || command === "apply-test-packet"
37
+ || command === "apply-executor-packet"
38
+ || command === "apply-code-review-packet"
39
+ || command === "apply-verify-packet"
40
+ || command === "ledger-render";
31
41
  }
32
42
  function requiredValueFlags(command) {
33
43
  const flags = ["--change"];
@@ -41,6 +51,14 @@ function requiredValueFlags(command) {
41
51
  flags.push("--gate");
42
52
  if (command === "review-packet")
43
53
  flags.push("--gate", "--role", "--round");
54
+ if (command === "apply-test-packet")
55
+ flags.push("--task-id", "--test-id", "--phase");
56
+ if (command === "apply-executor-packet")
57
+ flags.push("--task-id");
58
+ if (command === "apply-code-review-packet")
59
+ flags.push("--task-id", "--executor-report-ref");
60
+ if (command === "apply-verify-packet")
61
+ flags.push("--task-id", "--executor-report-ref", "--task-code-review-report-ref", "--green-test-run-evidence-ref");
44
62
  if (command === "ledger-render")
45
63
  flags.push("--gate");
46
64
  return flags;
@@ -58,6 +76,12 @@ function optionalValueFlags(command) {
58
76
  return ["--task-id"];
59
77
  if (command === "review-packet")
60
78
  return ["--kind"];
79
+ if (command === "apply-test-packet")
80
+ return ["--task-code-review-report-ref"];
81
+ if (command === "apply-executor-packet")
82
+ return ["--apply-worker-chain-ref"];
83
+ if (command === "apply-verify-packet")
84
+ return ["--red-test-run-evidence-ref", "--characterization-test-run-evidence-ref"];
61
85
  if (command === "ledger-render")
62
86
  return ["--round"];
63
87
  return [];
@@ -65,14 +89,23 @@ function optionalValueFlags(command) {
65
89
  function formatUsage(command) {
66
90
  if (command === "workflow-packet")
67
91
  return "--format {agent}";
68
- if (command === "review-packet")
92
+ if (command === "review-packet"
93
+ || command === "apply-test-packet"
94
+ || command === "apply-executor-packet"
95
+ || command === "apply-code-review-packet"
96
+ || command === "apply-verify-packet")
69
97
  return "--format {agent,prompt}";
70
98
  if (command === "ledger-render")
71
99
  return null;
72
100
  return "[--format {json,agent,user}]";
73
101
  }
74
102
  function requiresFormat(command) {
75
- return command === "workflow-packet" || command === "review-packet";
103
+ return command === "workflow-packet"
104
+ || command === "review-packet"
105
+ || command === "apply-test-packet"
106
+ || command === "apply-executor-packet"
107
+ || command === "apply-code-review-packet"
108
+ || command === "apply-verify-packet";
76
109
  }
77
110
  function rootUsage() {
78
111
  return `usage: superspec_guard [-h]\n {${COMMAND_LIST}}\n ...\n`;
@@ -173,14 +206,19 @@ export function parse_argv(argv) {
173
206
  };
174
207
  const getValue = (flag) => getValues(flag)[0];
175
208
  const formatValues = getValues("--format");
176
- const isPacketOutputCommand = command === "workflow-packet" || command === "review-packet";
209
+ const isPacketOutputCommand = command === "workflow-packet"
210
+ || command === "review-packet"
211
+ || command === "apply-test-packet"
212
+ || command === "apply-executor-packet"
213
+ || command === "apply-code-review-packet"
214
+ || command === "apply-verify-packet";
177
215
  const isPacketCommand = isPacketOutputCommand || command === "ledger-render";
178
216
  const selectedPacketFormat = formatValues.length > 0 ? formatValues[formatValues.length - 1] : undefined;
179
217
  if (isPacketOutputCommand) {
180
218
  if (!selectedPacketFormat)
181
219
  throw new GuardError("缺少必填参数 --format");
182
220
  for (const value of formatValues)
183
- parsePacketOutputFormat(value, { allowPrompt: command === "review-packet" });
221
+ parsePacketOutputFormat(value, { allowPrompt: command !== "workflow-packet" });
184
222
  }
185
223
  else {
186
224
  for (const value of formatValues)
@@ -248,6 +286,84 @@ export function parse_argv(argv) {
248
286
  packet_format: parsePacketOutputFormat(selectedPacketFormat, { allowPrompt: true }),
249
287
  };
250
288
  }
289
+ if (command === "apply-test-packet") {
290
+ const taskId = getValue("--task-id");
291
+ const testId = getValue("--test-id");
292
+ const phase = getValue("--phase");
293
+ if (!taskId)
294
+ throw new GuardError("apply-test-packet 缺少必填参数 --task-id");
295
+ if (!testId)
296
+ throw new GuardError("apply-test-packet 缺少必填参数 --test-id");
297
+ if (phase !== "red" && phase !== "characterization" && phase !== "green") {
298
+ throw new GuardError("--phase 只允许 red、characterization 或 green");
299
+ }
300
+ return {
301
+ command,
302
+ change,
303
+ task_id: taskId,
304
+ test_id: testId,
305
+ phase,
306
+ task_code_review_report_refs: getValues("--task-code-review-report-ref"),
307
+ packet_format: parsePacketOutputFormat(selectedPacketFormat, { allowPrompt: true }),
308
+ };
309
+ }
310
+ if (command === "apply-executor-packet") {
311
+ const taskId = getValue("--task-id");
312
+ if (!taskId)
313
+ throw new GuardError("apply-executor-packet 缺少必填参数 --task-id");
314
+ return {
315
+ command,
316
+ change,
317
+ task_id: taskId,
318
+ apply_worker_chain_refs: getValues("--apply-worker-chain-ref"),
319
+ packet_format: parsePacketOutputFormat(selectedPacketFormat, { allowPrompt: true }),
320
+ };
321
+ }
322
+ if (command === "apply-code-review-packet") {
323
+ const taskId = getValue("--task-id");
324
+ const executorRefs = getValues("--executor-report-ref");
325
+ if (!taskId)
326
+ throw new GuardError("apply-code-review-packet 缺少必填参数 --task-id");
327
+ if (executorRefs.length === 0)
328
+ throw new GuardError("apply-code-review-packet 缺少必填参数 --executor-report-ref");
329
+ return {
330
+ command,
331
+ change,
332
+ task_id: taskId,
333
+ executor_report_refs: executorRefs,
334
+ packet_format: parsePacketOutputFormat(selectedPacketFormat, { allowPrompt: true }),
335
+ };
336
+ }
337
+ if (command === "apply-verify-packet") {
338
+ const taskId = getValue("--task-id");
339
+ const executorRefs = getValues("--executor-report-ref");
340
+ const codeReviewRefs = getValues("--task-code-review-report-ref");
341
+ const greenRefs = getValues("--green-test-run-evidence-ref");
342
+ const redRefs = getValues("--red-test-run-evidence-ref");
343
+ const characterizationRefs = getValues("--characterization-test-run-evidence-ref");
344
+ if (!taskId)
345
+ throw new GuardError("apply-verify-packet 缺少必填参数 --task-id");
346
+ if (executorRefs.length === 0)
347
+ throw new GuardError("apply-verify-packet 缺少必填参数 --executor-report-ref");
348
+ if (codeReviewRefs.length === 0)
349
+ throw new GuardError("apply-verify-packet 缺少必填参数 --task-code-review-report-ref");
350
+ if (greenRefs.length === 0)
351
+ throw new GuardError("apply-verify-packet 缺少必填参数 --green-test-run-evidence-ref");
352
+ if (redRefs.length === 0 && characterizationRefs.length === 0) {
353
+ throw new GuardError("apply-verify-packet requires --red-test-run-evidence-ref or --characterization-test-run-evidence-ref");
354
+ }
355
+ return {
356
+ command,
357
+ change,
358
+ task_id: taskId,
359
+ executor_report_refs: executorRefs,
360
+ task_code_review_report_refs: codeReviewRefs,
361
+ green_test_run_evidence_refs: greenRefs,
362
+ red_test_run_evidence_refs: redRefs,
363
+ characterization_test_run_evidence_refs: characterizationRefs,
364
+ packet_format: parsePacketOutputFormat(selectedPacketFormat, { allowPrompt: true }),
365
+ };
366
+ }
251
367
  if (command === "ledger-render") {
252
368
  const gate = getValue("--gate");
253
369
  const roundValue = getValue("--round");
@@ -9,6 +9,7 @@ export * from "./invariants.ts";
9
9
  export * from "./git.ts";
10
10
  export * from "./state.ts";
11
11
  export * from "./archive.ts";
12
+ export * from "./apply_worker_chain.ts";
12
13
  export * from "./gates.ts";
13
14
  export * from "./install_engine.ts";
14
15
  import type { ParsedArgs } from "./cli_args.ts";
package/dist/src/core.js CHANGED
@@ -9,6 +9,7 @@ export * from "./invariants.js";
9
9
  export * from "./git.js";
10
10
  export * from "./state.js";
11
11
  export * from "./archive.js";
12
+ export * from "./apply_worker_chain.js";
12
13
  export * from "./gates.js";
13
14
  export * from "./install_engine.js";
14
15
  import { existsSync, readFileSync, statSync } from "node:fs";
@@ -4,6 +4,7 @@ import { CLAIM_ADJUDICATION_DECISIONS, EVIDENCE_KINDS, EVIDENCE_STATUSES, FINAL_
4
4
  import { normalize_gate } from "./openspec.js";
5
5
  import { superspec_dir } from "./paths.js";
6
6
  import { findings_schema_reasons, review_digest_schema_reasons, standing_authorization_schema_reasons, user_decision_schema_reasons, } from "./disclosure.js";
7
+ import { pinned_artifact_ref_reasons as shared_pinned_artifact_ref_reasons, worker_test_run_reasons, } from "./apply_worker_chain.js";
7
8
  function file_ref_reasons(baseRoot, ev, field, code) {
8
9
  const problems = [];
9
10
  const raw = ev[field];
@@ -29,6 +30,46 @@ function file_ref_reasons(baseRoot, ev, field, code) {
29
30
  }
30
31
  return problems;
31
32
  }
33
+ function contractField(line) {
34
+ const match = line.match(/^\s*-\s+`?([A-Za-z0-9_-]+)`?\s*:\s*(.*)$/);
35
+ if (!match)
36
+ return null;
37
+ return { key: match[1], value: match[2].trim() };
38
+ }
39
+ function test_contract_section_lines(changeRoot, testId) {
40
+ const pathValue = join(changeRoot, ".superspec", "artifacts", "test-contract.md");
41
+ if (!existsSync(pathValue) || !statSync(pathValue).isFile())
42
+ return [];
43
+ const lines = readFileSync(pathValue, "utf8").split(/\r?\n/);
44
+ const out = [];
45
+ let inSection = false;
46
+ for (const line of lines) {
47
+ const heading = line.match(/^###\s+(.+?)\s*$/);
48
+ if (heading) {
49
+ if (inSection)
50
+ break;
51
+ inSection = heading[1].trim() === testId;
52
+ continue;
53
+ }
54
+ if (inSection)
55
+ out.push(line);
56
+ }
57
+ return out;
58
+ }
59
+ function expected_failure_contract(changeRoot, testId) {
60
+ const fields = new Map();
61
+ for (const line of test_contract_section_lines(changeRoot, testId)) {
62
+ const field = contractField(line);
63
+ if (!field)
64
+ continue;
65
+ const values = fields.get(field.key) ?? [];
66
+ values.push(field.value);
67
+ fields.set(field.key, values);
68
+ }
69
+ const signature = (fields.get("expected_failure_signature") ?? [])[0];
70
+ const classifier = (fields.get("expected_failure_classifier") ?? [])[0];
71
+ return { signature, classifier };
72
+ }
32
73
  function pinned_ref_list_reasons(ev, field, baseRoot, staleCode, opts = {}) {
33
74
  const problems = [];
34
75
  const raw = ev[field];
@@ -94,6 +135,30 @@ function pinned_ref_reasons(ev, field, baseRoot, staleCode) {
94
135
  }
95
136
  return problems;
96
137
  }
138
+ function string_list_field_reasons(ev, field, code, opts = {}) {
139
+ const raw = ev[field];
140
+ if (!Array.isArray(raw) || (!opts.allowEmpty && raw.length === 0) || !raw.every((item) => typeof item === "string" && item.length > 0)) {
141
+ return [reason(code, `${ev._path}: ${field} must be a non-empty string list`)];
142
+ }
143
+ return [];
144
+ }
145
+ function fingerprint_field_reasons(ev, field, code) {
146
+ const raw = ev[field];
147
+ if (typeof raw === "string") {
148
+ return raw.startsWith("sha256:") ? [] : [reason(code, `${ev._path}: ${field} must be a sha256 fingerprint`)];
149
+ }
150
+ if (isObject(raw) && typeof raw.fingerprint_digest === "string" && raw.fingerprint_digest.startsWith("sha256:"))
151
+ return [];
152
+ return [reason(code, `${ev._path}: ${field} must be a sha256 fingerprint or fingerprint object`)];
153
+ }
154
+ function pinned_artifact_ref_item_reasons(refItem, field, changeRoot, expected = {}) {
155
+ return shared_pinned_artifact_ref_reasons(changeRoot, refItem, field, {
156
+ kind: expected.kind,
157
+ role: expected.role,
158
+ taskId: expected.task_id,
159
+ chainId: expected.chain_id,
160
+ });
161
+ }
97
162
  export function role_target_ref_reasons(ev, targetRoot) {
98
163
  return pinned_ref_reasons(ev, "target_refs", targetRoot, "stale_review");
99
164
  }
@@ -328,6 +393,26 @@ function test_run_reasons(ev, changeRoot) {
328
393
  if (typeof ev.result_summary !== "string" || !ev.result_summary.trim()) {
329
394
  problems.push(reason("test_run_summary_missing", `${ev._path}: test_run requires non-empty result_summary`));
330
395
  }
396
+ const runnerOrigin = ev.runner_origin;
397
+ const executorWorkerRun = ev.apply_execution_chain === "executor_worker";
398
+ if (runnerOrigin !== undefined && runnerOrigin !== "main-thread" && runnerOrigin !== "test-runner") {
399
+ problems.push(reason("test_run_runner_origin_invalid", `${ev._path}: runner_origin must be main-thread or test-runner`));
400
+ }
401
+ if (runnerOrigin === "test-runner" && (typeof ev.phase !== "string" || !ev.phase)) {
402
+ problems.push(reason("test_run_runner_origin_invalid", `${ev._path}: runner_origin=test-runner requires phase`));
403
+ }
404
+ if (runnerOrigin === "test-runner" && ev.gate === "task_complete" && ev.semantic_status === "expected_success" && !executorWorkerRun) {
405
+ problems.push(reason("test_run_runner_origin_invalid", `${ev._path}: test-runner GREEN evidence must belong to apply_execution_chain=executor_worker`));
406
+ }
407
+ if (executorWorkerRun && runnerOrigin !== "test-runner") {
408
+ problems.push(reason("test_run_runner_origin_invalid", `${ev._path}: apply_execution_chain=executor_worker requires runner_origin=test-runner`));
409
+ }
410
+ if (executorWorkerRun && (typeof ev.apply_worker_chain_id !== "string" || !ev.apply_worker_chain_id)) {
411
+ problems.push(reason("test_run_worker_ref_missing", `${ev._path}: apply_execution_chain=executor_worker requires apply_worker_chain_id`));
412
+ }
413
+ if (runnerOrigin === "test-runner" || executorWorkerRun) {
414
+ problems.push(...worker_test_run_reasons(changeRoot, ev, typeof ev.task_id === "string" ? ev.task_id : "", executorWorkerRun && typeof ev.apply_worker_chain_id === "string" ? ev.apply_worker_chain_id : null));
415
+ }
331
416
  if (logTexts.length > 0) {
332
417
  const claimed = [
333
418
  ...(typeof ev.test_id === "string" && ev.test_id.trim() ? [ev.test_id.trim()] : []),
@@ -339,6 +424,71 @@ function test_run_reasons(ev, changeRoot) {
339
424
  }
340
425
  }
341
426
  }
427
+ if (ev.semantic_status === "expected_failure" && typeof ev.test_id === "string" && ev.test_id.trim()) {
428
+ const expected = expected_failure_contract(changeRoot, ev.test_id.trim());
429
+ if (expected.signature) {
430
+ if (ev.expected_failure_signature !== expected.signature) {
431
+ problems.push(reason("test_run_wrong_failure_reason", `${ev._path}: RED evidence expected_failure_signature must match test contract for ${ev.test_id}`, [ev.test_id]));
432
+ }
433
+ if (!logTexts.some((text) => text.includes(String(expected.signature)))) {
434
+ problems.push(reason("test_run_wrong_failure_reason", `${ev._path}: RED raw_log_refs do not contain expected_failure_signature for ${ev.test_id}`, [ev.test_id]));
435
+ }
436
+ }
437
+ if (expected.classifier && ev.expected_failure_classifier !== expected.classifier) {
438
+ problems.push(reason("test_run_wrong_failure_reason", `${ev._path}: RED evidence expected_failure_classifier must match test contract for ${ev.test_id}`, [ev.test_id]));
439
+ }
440
+ }
441
+ return problems;
442
+ }
443
+ function apply_worker_chain_reasons(ev, changeRoot) {
444
+ const problems = [];
445
+ const state = String(ev.chain_state ?? "");
446
+ if (!["active", "closed", "abandoned"].includes(state)) {
447
+ problems.push(reason("apply_worker_chain_invalid", `${ev._path}: apply_worker_chain chain_state must be active, closed, or abandoned`));
448
+ }
449
+ for (const field of ["task_id", "apply_worker_chain_id"]) {
450
+ if (typeof ev[field] !== "string" || !ev[field])
451
+ problems.push(reason("apply_worker_chain_invalid", `${ev._path}: apply_worker_chain requires ${field}`));
452
+ }
453
+ if (state === "active") {
454
+ problems.push(...fingerprint_field_reasons(ev, "executor_packet_fingerprint", "apply_worker_chain_invalid"));
455
+ problems.push(...fingerprint_field_reasons(ev, "source_implementation_fingerprint", "apply_worker_chain_invalid"));
456
+ problems.push(...string_list_field_reasons(ev, "declared_task_write_scope", "apply_worker_chain_invalid"));
457
+ problems.push(...string_list_field_reasons(ev, "pre_edit_evidence_refs", "apply_worker_chain_invalid"));
458
+ }
459
+ if (state === "closed") {
460
+ const taskId = typeof ev.task_id === "string" ? ev.task_id : undefined;
461
+ const chainId = typeof ev.apply_worker_chain_id === "string" ? ev.apply_worker_chain_id : undefined;
462
+ const refProblems = [
463
+ ...pinned_artifact_ref_item_reasons(ev.executor_report_ref, "executor_report_ref", changeRoot, { kind: "worker_report", role: "executor", task_id: taskId, chain_id: chainId }),
464
+ ...pinned_artifact_ref_item_reasons(ev.task_code_review_report_ref, "task_code_review_report_ref", changeRoot, { kind: "worker_report", role: "code-reviewer", task_id: taskId, chain_id: chainId }),
465
+ ...pinned_artifact_ref_item_reasons(ev.verifier_report_ref, "verifier_report_ref", changeRoot, { kind: "worker_report", role: "verifier", task_id: taskId, chain_id: chainId }),
466
+ ];
467
+ problems.push(...refProblems);
468
+ if (refProblems.length > 0)
469
+ problems.push(reason("apply_worker_chain_invalid", `${ev._path}: closed apply_worker_chain report refs must be pinned same-chain worker reports`));
470
+ if (!isObject(ev.green_test_run_evidence_ref) && typeof ev.green_test_run_evidence_ref !== "string") {
471
+ problems.push(reason("apply_worker_chain_invalid", `${ev._path}: closed apply_worker_chain requires green_test_run_evidence_ref`));
472
+ }
473
+ problems.push(...fingerprint_field_reasons(ev, "observed_freshness_fingerprint", "apply_worker_chain_invalid"));
474
+ }
475
+ if (state === "abandoned") {
476
+ const taskId = typeof ev.task_id === "string" ? ev.task_id : undefined;
477
+ const chainId = typeof ev.apply_worker_chain_id === "string" ? ev.apply_worker_chain_id : undefined;
478
+ if ("restored_implementation_fingerprint" in ev) {
479
+ problems.push(...fingerprint_field_reasons(ev, "restored_implementation_fingerprint", "apply_worker_chain_invalid"));
480
+ }
481
+ if (!("restored_implementation_fingerprint" in ev) && !("serial_takeover_baseline_ref" in ev)) {
482
+ problems.push(reason("apply_worker_chain_invalid", `${ev._path}: abandoned apply_worker_chain requires restored_implementation_fingerprint or serial_takeover_baseline_ref`));
483
+ }
484
+ if ("serial_takeover_baseline_ref" in ev) {
485
+ const baselineProblems = pinned_artifact_ref_item_reasons(ev.serial_takeover_baseline_ref, "serial_takeover_baseline_ref", changeRoot, { kind: "status_report", role: "verifier", task_id: taskId, chain_id: chainId });
486
+ problems.push(...baselineProblems);
487
+ if (baselineProblems.length > 0)
488
+ problems.push(reason("apply_worker_chain_invalid", `${ev._path}: abandoned apply_worker_chain serial_takeover_baseline_ref must be a pinned same-chain status_report`));
489
+ problems.push(...string_list_field_reasons(ev, "successor_green_evidence_refs", "apply_worker_chain_invalid"));
490
+ }
491
+ }
342
492
  return problems;
343
493
  }
344
494
  export function validate_evidence_schema(ev, change, changeRoot, repoRoot) {
@@ -359,6 +509,8 @@ export function validate_evidence_schema(ev, change, changeRoot, repoRoot) {
359
509
  problems.push(...human_confirmation_reasons(ev));
360
510
  if (ev.kind === "test_run")
361
511
  problems.push(...test_run_reasons(ev, changeRoot));
512
+ if (ev.kind === "apply_worker_chain")
513
+ problems.push(...apply_worker_chain_reasons(ev, changeRoot));
362
514
  // DISC Phase 1: disclosure evidence kinds and reviewer findings[] are schema-checked fail-closed.
363
515
  if (ev.kind === "main_review_digest")
364
516
  problems.push(...review_digest_schema_reasons(ev));
@@ -10,6 +10,7 @@ export declare function check_artifact(change: string, status: JsonMap, changeRo
10
10
  export declare function check_task_reopen(change: string, status: JsonMap, changeRoot: string, evidences: JsonMap[], taskId: string): Decision;
11
11
  export declare function check_apply_ready(change: string, status: JsonMap, changeRoot: string, evidences: JsonMap[]): Decision;
12
12
  export declare function check_task_edit(change: string, status: JsonMap, changeRoot: string, evidences: JsonMap[], taskId: string): Decision;
13
+ export declare function apply_worker_chain_lifecycle_reasons(repoRoot: string, changeRoot: string, evidences: JsonMap[], taskId: string): Reason[];
13
14
  export declare function check_task_complete(change: string, status: JsonMap, changeRoot: string, evidences: JsonMap[], taskId: string): Decision;
14
15
  export declare function check_review_ready(change: string, status: JsonMap, changeRoot: string, evidences: JsonMap[]): Decision;
15
16
  export declare function check_review_complete(change: string, status: JsonMap, changeRoot: string, evidences: JsonMap[]): Decision;