@xenonbyte/da-vinci-workflow 0.2.4 → 0.2.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +15 -9
  3. package/README.zh-CN.md +16 -9
  4. package/SKILL.md +45 -704
  5. package/docs/dv-command-reference.md +33 -5
  6. package/docs/execution-chain-migration.md +14 -3
  7. package/docs/maintainer-bootstrap.md +102 -0
  8. package/docs/pencil-rendering-workflow.md +1 -1
  9. package/docs/prompt-entrypoints.md +1 -0
  10. package/docs/skill-contract-maintenance.md +14 -0
  11. package/docs/skill-usage.md +31 -0
  12. package/docs/workflow-overview.md +40 -5
  13. package/docs/zh-CN/dv-command-reference.md +31 -5
  14. package/docs/zh-CN/maintainer-bootstrap.md +101 -0
  15. package/docs/zh-CN/pencil-rendering-workflow.md +1 -1
  16. package/docs/zh-CN/prompt-entrypoints.md +1 -0
  17. package/docs/zh-CN/skill-usage.md +30 -0
  18. package/docs/zh-CN/workflow-overview.md +38 -5
  19. package/lib/audit.js +19 -0
  20. package/lib/cli/helpers.js +104 -0
  21. package/lib/cli/lint-family.js +56 -0
  22. package/lib/cli/verify-family.js +79 -0
  23. package/lib/cli.js +143 -172
  24. package/lib/gate-utils.js +56 -0
  25. package/lib/install.js +134 -6
  26. package/lib/lint-bindings.js +41 -28
  27. package/lib/lint-spec.js +403 -109
  28. package/lib/lint-tasks.js +571 -21
  29. package/lib/maintainer-readiness.js +317 -0
  30. package/lib/planning-parsers.js +198 -2
  31. package/lib/planning-quality-utils.js +81 -0
  32. package/lib/planning-signal-freshness.js +205 -0
  33. package/lib/scaffold.js +454 -23
  34. package/lib/scope-check.js +751 -82
  35. package/lib/sidecars.js +396 -1
  36. package/lib/task-review.js +2 -1
  37. package/lib/utils.js +34 -0
  38. package/lib/verify.js +1160 -88
  39. package/lib/workflow-persisted-state.js +52 -32
  40. package/lib/workflow-state.js +1187 -249
  41. package/package.json +1 -1
  42. package/references/skill-workflow-detail.md +66 -0
@@ -2,6 +2,9 @@
2
2
 
3
3
  这份文档面向真正操作 Da Vinci 的人,而不是底层命令参考。
4
4
 
5
+ 如果你是在维护 Da Vinci 仓库本身,请先看
6
+ [maintainer-bootstrap.md](./maintainer-bootstrap.md),而不是这份偏 operator 的流程文档。
7
+
5
8
  重点讲四件事:
6
9
 
7
10
  - 第一次怎么进入 Da Vinci 工作流
@@ -18,6 +21,7 @@ Da Vinci 应该根据工件真相恢复,而不是根据聊天记忆恢复。
18
21
  - `spec.md` 以及相关需求工件是行为真相
19
22
  - 项目内 `.pen` 是设计真相
20
23
  - `tasks.md`、`verification.md` 和 execution signals 负责说明哪些东西已经实现、哪些还没实现
24
+ - workflow memory 是 `.da-vinci/state/` 下的工件级本地状态,不是跨会话聊天记忆
21
25
 
22
26
  ## 第一次进入时怎么选入口
23
27
 
@@ -79,14 +83,20 @@ $da-vinci use continue for <existing workflow state>
79
83
 
80
84
  - `da-vinci workflow-status`
81
85
  - 先确认当前阶段和 blocker
86
+ - task-group focus 会综合 checklist 进度和最新 `task-execution` / `task-review` 证据
82
87
  - `da-vinci next-step`
83
88
  - 再确认下一步到底应该是 `design`、`tasks` 还是 `build`
89
+ - 当你需要 runtime-aware 的首要聚焦点时,优先看它而不是只看下一条未勾选 checklist
84
90
  - `da-vinci lint-spec`
85
91
  - 当运行时 spec 质量还不够确定时使用
92
+ - `--json` 中重点看 `gates.principleInheritance`、`gates.clarify`、`gates.scenarioQuality`
93
+ - 当 bounded 元数据完整时,把 `gates.clarify.bounded` 视为“可见上下文”;bounded-only clarify 默认不阻断
86
94
  - `da-vinci scope-check`
87
95
  - 当规划工件之间页面/状态传播关系还不清楚时使用
96
+ - `--json` 中重点看 `gates.analyze` 的跨工件一致性阻断项
88
97
  - `da-vinci lint-tasks`
89
98
  - 校验 task groups 是否包含 discipline markers、明确文件落点、执行意图与 verification 命令
99
+ - `--json` 中重点看 `gates.taskCheckpoint` 的 anchor/checkpoint 就绪度
90
100
  - `da-vinci lint-bindings`
91
101
  - 当 `pencil-design.md` 与 `pencil-bindings.md` 同时存在时运行,确保实现落点证据可解析
92
102
  - `da-vinci worktree-preflight`
@@ -112,6 +122,13 @@ da-vinci lint-tasks
112
122
 
113
123
  同一 task group 只有在 `spec` review 已是 `PASS` 时,`quality` review 才允许通过。
114
124
 
125
+ 兼容性说明:
126
+
127
+ - `workflow-status --json` 仍保留扁平 task-group 字段:`status`、`completion`、`nextAction`、`resumeCursor`
128
+ - `completion` 仍表示 checklist 推导的进度百分比
129
+ - 当 implementer/review 证据更新更晚时,`status`、`nextAction`、`resumeCursor` 可能切换到 runtime-aware 值
130
+ - 当规划 gate 阻断晋级时,`workflow-status --json` 与 `next-step --json` 会输出 `blockingGate`
131
+
115
132
  ## 中途退出后,下次怎么恢复
116
133
 
117
134
  最稳妥的恢复顺序是:
@@ -124,12 +141,25 @@ da-vinci lint-tasks
124
141
  6. 在终态前,跑 `da-vinci verify-bindings` 和 `da-vinci verify-coverage`
125
142
  7. 如果要做 completion 表述,确认 `verify-coverage` 的 freshness 仍然有效,并运行 `da-vinci audit --mode completion --change <id> <project-path>`
126
143
 
144
+ 严格性控制:
145
+
146
+ - lint 命令严格性:使用 `--strict`
147
+ - workflow 晋级严格性:使用 `DA_VINCI_DISCIPLINE_STRICT_PROMOTION`
148
+ - clarify/analyze/task-checkpoint 不新增独立 strict 开关
149
+ - 在 integrity audit 中,即使 `lint-spec` signal 顶层是 `PASS`,bounded-only clarify 上下文也应保持可见
150
+
127
151
  恢复时应该遵循工件,而不是旧聊天上下文:
128
152
 
129
153
  - 如果设计工件已经有了,但 `tasks.md` 还没有,下一步应该回到 `tasks`
130
154
  - 如果 `tasks.md` 已存在,但设计 gate 还没过,不要直接进 `build`
131
155
  - 只有实现就绪度已经明确时,才把 `build` 当主恢复路径
132
156
 
157
+ 当 task 执行或评审证据与 checklist 进度冲突时:
158
+
159
+ - 以 `workflow-status` / `next-step` 的路由建议为准
160
+ - 把 task-group 的 `nextAction` 视为有效续跑焦点
161
+ - 把 checklist `completion` 视为进度可见性,不把它当成 blocker/review debt 已清空的证明
162
+
133
163
  ## `change-id` 到底是什么
134
164
 
135
165
  `change-id` 就是 `.da-vinci/changes/<change-id>/` 这个目录名。
@@ -12,11 +12,12 @@
12
12
  - 页面到设计的绑定
13
13
  - 实现与验证
14
14
 
15
- 如果你想看 Pencil 渲染、持久化、门禁和审计的专门说明,请看 [pencil-rendering-workflow.md](/Users/xubo/x-skills/da-vinci/docs/zh-CN/pencil-rendering-workflow.md)。
16
- 如果你想看逐个 `dv:` 命令的职责、下一步推荐和 `verify` 回退规则,请看 [dv-command-reference.md](/Users/xubo/x-skills/da-vinci/docs/zh-CN/dv-command-reference.md)。
17
- 如果你想看约束文件总览(哪些字段是硬门禁、哪些是指导项),请看 [constraint-files.md](/Users/xubo/x-skills/da-vinci/docs/zh-CN/constraint-files.md)。
18
- 如果你想看 sidecar、enforcement、persisted-state 回退和 scaffold 约束,请看 [execution-chain-migration.md](/Users/xubo/x-skills/da-vinci/docs/zh-CN/execution-chain-migration.md)。
19
- 如果你想看更偏操作手册的说明,比如第一次怎么进、暂停后怎么续跑、TUI 怎么用,请看 [skill-usage.md](/Users/xubo/x-skills/da-vinci/docs/zh-CN/skill-usage.md)。
15
+ 如果你想看 Pencil 渲染、持久化、门禁和审计的专门说明,请看 [pencil-rendering-workflow.md](./pencil-rendering-workflow.md)。
16
+ 如果你想看逐个 `dv:` 命令的职责、下一步推荐和 `verify` 回退规则,请看 [dv-command-reference.md](./dv-command-reference.md)。
17
+ 如果你想看约束文件总览(哪些字段是硬门禁、哪些是指导项),请看 [constraint-files.md](./constraint-files.md)。
18
+ 如果你想看 sidecar、enforcement、persisted-state 回退和 scaffold 约束,请看 [execution-chain-migration.md](./execution-chain-migration.md)。
19
+ 如果你想看更偏操作手册的说明,比如第一次怎么进、暂停后怎么续跑、TUI 怎么用,请看 [skill-usage.md](./skill-usage.md)。
20
+ 如果你是在维护仓库本身(不是下游项目操作),请从 [maintainer-bootstrap.md](./maintainer-bootstrap.md) 进入。
20
21
 
21
22
  ## 核心契约
22
23
 
@@ -35,6 +36,9 @@ Da Vinci 围绕一个固定契约工作:
35
36
  真相与编排边界:
36
37
 
37
38
  - 选路和 completion 真相来自工件、checkpoint、execution signals 与 `audit`
39
+ - workflow memory 是工件驱动的本地状态,不是聊天派生记忆
40
+ - `.da-vinci/state/workflow.json` 是 persisted route cache,不是 task-group runtime state 的 canonical owner
41
+ - `.da-vinci/state/task-groups/<change>.json` 是 workflow snapshot 写入后的 task-group runtime state canonical owner
38
42
  - execution profile、worktree preflight 等编排信息始终是 advisory 指导,不替代真相面
39
43
  - 编排提示不能覆盖来自工件、checkpoint 或 completion audit 的明确 `BLOCK`
40
44
 
@@ -56,14 +60,23 @@ Da Vinci 围绕一个固定契约工作:
56
60
 
57
61
  - `da-vinci workflow-status --project <path> [--change <id>] [--json]`
58
62
  - 从工件真相和部分 audit 可见证据推导阶段、blocker、handoff gate 与路由建议
63
+ - 输出 canonical task-group runtime state,并同时保留兼容字段与 planned / implementer / review / effective 分层
59
64
  - `da-vinci next-step --project <path> [--change <id>] [--json]`
60
65
  - 基于同一 workflow-state 模型,给出优先续跑动作
66
+ - 与 `workflow-status` 共用同一 task-group runtime-state 模型,不再是 checklist-only 解释
67
+ - 当 clarify/analyze/task-checkpoint 阻断晋级时,`--json` 会输出 `blockingGate`
61
68
  - `da-vinci lint-spec --project <path> [--change <id>] [--strict] [--json]`
62
69
  - 在进入实现规划或实现前,校验运行时 `spec.md` 结构质量
70
+ - `--json` 中输出机器可读 gate:`gates.principleInheritance`、`gates.clarify`、`gates.scenarioQuality`
71
+ - 当 bounded 元数据完整时,clarify 的 bounded 歧义会保留在 `gates.clarify.bounded` 与 notes 中,默认不作为阻断
63
72
  - 默认 advisory;显式 `--strict` 才会把发现升级为阻断
64
73
  - `da-vinci scope-check --project <path> [--change <id>] [--strict] [--json]`
65
74
  - 校验 proposal、page-map、运行时 spec、pencil-design、tasks 之间页面/状态传播是否一致
75
+ - `--json` 中输出机器可读 gate:`gates.analyze`
66
76
  - 输出页面和状态的机器可读覆盖矩阵,供后续 verify/status 消费
77
+ - `da-vinci lint-tasks --project <path> [--change <id>] [--strict] [--json]`
78
+ - 校验 task-group 规划纪律以及 task-anchor 到上游规划证据的可追溯性
79
+ - `--json` 中输出机器可读 gate:`gates.taskCheckpoint`
67
80
  - `da-vinci generate-sidecars --project <path> [--change <id>] [--json]`
68
81
  - 显式生成确定性的 planning sidecars,供 diff 和下游工具消费
69
82
  - `da-vinci verify-bindings|verify-implementation|verify-structure|verify-coverage --project <path> [--change <id>] [--strict] [--json]`
@@ -79,6 +92,24 @@ Da Vinci 围绕一个固定契约工作:
79
92
 
80
93
  这些命令不替代 `da-vinci audit --mode integrity|completion`。
81
94
  `audit` 仍是 integrity/completion 的正式真相面。
95
+ - 在 integrity 模式下,即使 `lint-spec` 顶层 signal 是 `PASS`,planning-signal notes 也会保留 bounded clarify 上下文
96
+
97
+ persisted-state trust 规则:
98
+
99
+ - 只要 governing artifact 内容 digest 仍匹配,即使 snapshot 很旧,persisted workflow snapshot 仍可用
100
+ - snapshot 年龄仅是 advisory,不再单独导致 persisted route truth 失效
101
+ - execution signals、audits、discipline、verification freshness 等 live overlay 每次读取都会重算
102
+
103
+ planning-gate 严格性控制面:
104
+
105
+ - 命令级 lint 严格性使用已有 `--strict`
106
+ - workflow 晋级严格性使用 `DA_VINCI_DISCIPLINE_STRICT_PROMOTION`
107
+ - clarify/analyze/task-checkpoint gate 不引入新的 strict flag 家族
108
+
109
+ spec-kit 借鉴边界:
110
+
111
+ - 只借鉴 clarify/analyze/gate 这类方法论,不搬运整套工具链模型。
112
+ - 不采用 spec-kit 的 constitution/init/branch/toolchain 工作流。
82
113
 
83
114
  ## 标准工件骨架
84
115
 
@@ -204,6 +235,8 @@ mapping 通过后:
204
235
  - 在大范围实现前,从 `workflow-status` 或 `next-step --json` 查看 `executionProfile`
205
236
  - 如果建议 bounded parallel,先跑 `da-vinci worktree-preflight --project <path> [--change <id>]`;隔离未就绪时降级为串行
206
237
  - 通过 `task-execution` 与有序 `task-review` 记录每个 task group 的执行与审查证据
238
+ - 当 live evidence 比 checklist 更新时,优先按 task-group `nextAction` / `resumeCursor` 读取 runtime-aware 聚焦点
239
+ - 保持把扁平 `completion` 解释为 checklist 进度百分比,而不是 runtime 健康度
207
240
  - 验证需求漂移和设计漂移
208
241
 
209
242
  ### 8. 终态完成
package/lib/audit.js CHANGED
@@ -145,6 +145,18 @@ function pushUnique(targetList, message) {
145
145
  }
146
146
  }
147
147
 
148
+ function listClarifyBoundedFindings(signal) {
149
+ const gates = signal && signal.details && signal.details.gates;
150
+ if (!gates || typeof gates !== "object") {
151
+ return [];
152
+ }
153
+ const clarify = gates.clarify;
154
+ if (!clarify || typeof clarify !== "object" || !Array.isArray(clarify.bounded)) {
155
+ return [];
156
+ }
157
+ return clarify.bounded.map((item) => String(item || "").trim()).filter(Boolean);
158
+ }
159
+
148
160
  function appendTraversalWarnings(projectRoot, rootDir, scan, warnings) {
149
161
  if (!scan) {
150
162
  return;
@@ -834,6 +846,13 @@ function auditProject(projectPathInput, options = {}) {
834
846
  } else if (signal.status === "WARN") {
835
847
  pushUnique(notes, `Planning signal ${surface} is WARN.`);
836
848
  }
849
+
850
+ if (surface === "lint-spec") {
851
+ const boundedClarifyFindings = listClarifyBoundedFindings(signal);
852
+ for (const finding of boundedClarifyFindings) {
853
+ pushUnique(notes, `Planning signal lint-spec clarify bounded context: ${finding}`);
854
+ }
855
+ }
837
856
  }
838
857
 
839
858
  if (mode === "completion" && VERIFICATION_SIGNAL_SURFACES.has(surface)) {
@@ -0,0 +1,104 @@
1
+ const { writeExecutionSignal } = require("../execution-signals");
2
+ const { STATUS } = require("../workflow-contract");
3
+
4
+ function emitOrThrowOnStatus(status, blockedStatuses, output, continueOnError) {
5
+ if (!Array.isArray(blockedStatuses) || !blockedStatuses.includes(status)) {
6
+ return false;
7
+ }
8
+ if (continueOnError) {
9
+ console.log(output);
10
+ return true;
11
+ }
12
+ throw new Error(output);
13
+ }
14
+
15
+ function persistExecutionSignal(projectPath, changeId, surface, result, strict = false) {
16
+ const normalizeStatus = (status) => {
17
+ const normalized = String(status || "").trim().toUpperCase();
18
+ if (normalized === STATUS.BLOCK || normalized === STATUS.WARN || normalized === STATUS.PASS) {
19
+ return normalized;
20
+ }
21
+ return "";
22
+ };
23
+ const statusRank = (status) => {
24
+ if (status === STATUS.BLOCK) {
25
+ return 2;
26
+ }
27
+ if (status === STATUS.WARN) {
28
+ return 1;
29
+ }
30
+ if (status === STATUS.PASS) {
31
+ return 0;
32
+ }
33
+ return -1;
34
+ };
35
+ const worseStatus = (left, right) => {
36
+ const l = normalizeStatus(left);
37
+ const r = normalizeStatus(right);
38
+ if (!l && !r) {
39
+ return STATUS.PASS;
40
+ }
41
+ if (!l) {
42
+ return r;
43
+ }
44
+ if (!r) {
45
+ return l;
46
+ }
47
+ return statusRank(l) >= statusRank(r) ? l : r;
48
+ };
49
+ const deriveGateStatus = (gates) => {
50
+ if (!gates || typeof gates !== "object") {
51
+ return STATUS.PASS;
52
+ }
53
+ let worst = STATUS.PASS;
54
+ for (const gate of Object.values(gates)) {
55
+ worst = worseStatus(worst, gate && gate.status);
56
+ if (worst === STATUS.BLOCK) {
57
+ break;
58
+ }
59
+ }
60
+ return worst;
61
+ };
62
+
63
+ const details = {};
64
+ if (result && result.gates && typeof result.gates === "object") {
65
+ details.gates = result.gates;
66
+ }
67
+ if (result && result.summary && typeof result.summary === "object") {
68
+ details.summary = result.summary;
69
+ }
70
+ const persistedStatus = worseStatus(
71
+ result && result.status ? result.status : STATUS.PASS,
72
+ deriveGateStatus(details.gates)
73
+ );
74
+
75
+ try {
76
+ writeExecutionSignal(projectPath, {
77
+ changeId: changeId || "global",
78
+ surface,
79
+ status: persistedStatus,
80
+ advisory: strict ? false : true,
81
+ strict,
82
+ failures: result.failures || [],
83
+ warnings: result.warnings || [],
84
+ notes: result.notes || [],
85
+ details: Object.keys(details).length > 0 ? details : null
86
+ });
87
+ } catch (error) {
88
+ // Signals are advisory metadata and should not break command execution.
89
+ const code = error && error.code ? String(error.code).toUpperCase() : "";
90
+ if (code === "EACCES" || code === "ENOSPC") {
91
+ return;
92
+ }
93
+
94
+ const message = error && error.message ? error.message : String(error);
95
+ console.error(
96
+ `Warning: failed to persist execution signal (${surface}) for change ${changeId || "global"}: ${message}`
97
+ );
98
+ }
99
+ }
100
+
101
+ module.exports = {
102
+ emitOrThrowOnStatus,
103
+ persistExecutionSignal
104
+ };
@@ -0,0 +1,56 @@
1
+ function handleLintFamilyCommand(command, context) {
2
+ const lintCommands = new Set(["lint-spec", "scope-check", "lint-tasks", "lint-bindings"]);
3
+ if (!lintCommands.has(command)) {
4
+ return false;
5
+ }
6
+
7
+ const {
8
+ argv,
9
+ positionalArgs,
10
+ continueOnError,
11
+ getOption,
12
+ lintRuntimeSpecs,
13
+ formatLintSpecReport,
14
+ runScopeCheck,
15
+ formatScopeCheckReport,
16
+ lintTasks,
17
+ formatLintTasksReport,
18
+ lintBindings,
19
+ formatLintBindingsReport,
20
+ emitOrThrowOnStatus,
21
+ persistExecutionSignal
22
+ } = context;
23
+
24
+ const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
25
+ const changeId = getOption(argv, "--change");
26
+ const strict = argv.includes("--strict");
27
+ const useJson = argv.includes("--json");
28
+
29
+ let result;
30
+ let output = "";
31
+ let surface = command;
32
+ if (command === "lint-spec") {
33
+ result = lintRuntimeSpecs(projectPath, { changeId, strict });
34
+ output = useJson ? JSON.stringify(result, null, 2) : formatLintSpecReport(result);
35
+ } else if (command === "scope-check") {
36
+ result = runScopeCheck(projectPath, { changeId, strict });
37
+ output = useJson ? JSON.stringify(result, null, 2) : formatScopeCheckReport(result);
38
+ } else if (command === "lint-tasks") {
39
+ result = lintTasks(projectPath, { changeId, strict });
40
+ output = useJson ? JSON.stringify(result, null, 2) : formatLintTasksReport(result);
41
+ } else {
42
+ result = lintBindings(projectPath, { changeId, strict });
43
+ output = useJson ? JSON.stringify(result, null, 2) : formatLintBindingsReport(result);
44
+ }
45
+
46
+ persistExecutionSignal(projectPath, result.changeId || changeId, surface, result, strict);
47
+ if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
48
+ return true;
49
+ }
50
+ console.log(output);
51
+ return true;
52
+ }
53
+
54
+ module.exports = {
55
+ handleLintFamilyCommand
56
+ };
@@ -0,0 +1,79 @@
1
+ function handleVerifyFamilyCommand(command, context) {
2
+ const verifyCommands = new Set([
3
+ "verify-bindings",
4
+ "verify-implementation",
5
+ "verify-structure",
6
+ "verify-coverage"
7
+ ]);
8
+ if (!verifyCommands.has(command)) {
9
+ return false;
10
+ }
11
+
12
+ const {
13
+ argv,
14
+ positionalArgs,
15
+ continueOnError,
16
+ getOption,
17
+ getCommaSeparatedOptionValues,
18
+ collectOptionEntries,
19
+ verifyBindings,
20
+ verifyImplementation,
21
+ verifyStructure,
22
+ verifyCoverage,
23
+ formatVerifyReport,
24
+ emitOrThrowOnStatus,
25
+ persistExecutionSignal
26
+ } = context;
27
+
28
+ const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
29
+ const changeId = getOption(argv, "--change");
30
+ const strict = argv.includes("--strict");
31
+ const useJson = argv.includes("--json");
32
+ const changedFilesProvided = collectOptionEntries(argv, "--changed-files").length > 0;
33
+ const changedFiles = changedFilesProvided
34
+ ? getCommaSeparatedOptionValues(argv, "--changed-files")
35
+ : undefined;
36
+
37
+ let result;
38
+ let title = "Da Vinci verify";
39
+ if (command === "verify-bindings") {
40
+ result = verifyBindings(projectPath, { changeId, strict });
41
+ title = "Da Vinci verify-bindings";
42
+ } else if (command === "verify-implementation") {
43
+ result = verifyImplementation(projectPath, {
44
+ changeId,
45
+ strict,
46
+ changedFiles,
47
+ changedFilesProvided
48
+ });
49
+ title = "Da Vinci verify-implementation";
50
+ } else if (command === "verify-structure") {
51
+ result = verifyStructure(projectPath, {
52
+ changeId,
53
+ strict,
54
+ changedFiles,
55
+ changedFilesProvided
56
+ });
57
+ title = "Da Vinci verify-structure";
58
+ } else {
59
+ result = verifyCoverage(projectPath, {
60
+ changeId,
61
+ strict,
62
+ changedFiles,
63
+ changedFilesProvided
64
+ });
65
+ title = "Da Vinci verify-coverage";
66
+ }
67
+
68
+ persistExecutionSignal(projectPath, result.changeId || changeId, command, result, strict);
69
+ const output = useJson ? JSON.stringify(result, null, 2) : formatVerifyReport(result, title);
70
+ if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
71
+ return true;
72
+ }
73
+ console.log(output);
74
+ return true;
75
+ }
76
+
77
+ module.exports = {
78
+ handleVerifyFamilyCommand
79
+ };