@xenonbyte/da-vinci-workflow 0.2.4 → 0.2.5
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/CHANGELOG.md +19 -0
- package/README.md +7 -7
- package/README.zh-CN.md +7 -7
- package/SKILL.md +45 -704
- package/docs/dv-command-reference.md +15 -3
- package/docs/prompt-entrypoints.md +1 -0
- package/docs/skill-contract-maintenance.md +14 -0
- package/docs/zh-CN/dv-command-reference.md +15 -3
- package/docs/zh-CN/prompt-entrypoints.md +1 -0
- package/lib/cli/helpers.js +43 -0
- package/lib/cli/lint-family.js +56 -0
- package/lib/cli/verify-family.js +79 -0
- package/lib/cli.js +45 -172
- package/lib/planning-parsers.js +8 -1
- package/lib/scaffold.js +454 -23
- package/lib/utils.js +19 -0
- package/lib/verify.js +1160 -88
- package/package.json +1 -1
- package/references/skill-workflow-detail.md +66 -0
|
@@ -66,9 +66,21 @@ These commands do not replace route selection, but they support design execution
|
|
|
66
66
|
- `da-vinci generate-sidecars --project <path> [--change <id>] [--json]`
|
|
67
67
|
- explicitly generates deterministic planning sidecars: `spec.index.json`, `tasks.index.json`, `page-map.index.json`, `bindings.index.json`
|
|
68
68
|
- this is the only write surface for planning sidecars; lint/status/verify surfaces should not silently rewrite them
|
|
69
|
-
- `da-vinci verify-bindings
|
|
70
|
-
-
|
|
71
|
-
|
|
69
|
+
- `da-vinci verify-bindings --project <path> [--change <id>] [--strict] [--json]`
|
|
70
|
+
- validates implementation landing resolution from `pencil-bindings.md`
|
|
71
|
+
- `da-vinci verify-implementation --project <path> [--change <id>] [--changed-files <csv>] [--strict] [--json]`
|
|
72
|
+
- verifies planned-state/task-group implementation evidence with per-check `mode` + `confidence` metadata
|
|
73
|
+
- JS/TS checks are syntax-aware and do not count comment-only or string-literal-only matches as normal coverage
|
|
74
|
+
- when `--changed-files` is used, the run is explicit incremental scope (partial semantics) and reports selected/scanned/filtered file counts
|
|
75
|
+
- `da-vinci verify-structure --project <path> [--change <id>] [--changed-files <csv>] [--strict] [--json]`
|
|
76
|
+
- verifies structural consistency against bindings and reports `markup` vs `heuristic` confidence surfaces
|
|
77
|
+
- when `--changed-files` is used, unmatched or irrelevant entries stay visible instead of silently widening to full scan
|
|
78
|
+
- `da-vinci verify-coverage --project <path> [--change <id>] [--changed-files <csv>] [--strict] [--json]`
|
|
79
|
+
- aggregates upstream verification surfaces and marks incremental upstream results as partial freshness
|
|
80
|
+
- `da-vinci scaffold --project <path> [--change <id>] [--output <path>] [--json]`
|
|
81
|
+
- generates reviewable TODO scaffold templates with framework-aware shape (`next`/`react`/`vue`/`svelte`/`html`)
|
|
82
|
+
- keeps known implementation landing extension/route shape when a concrete landing already exists
|
|
83
|
+
- unknown/ambiguous framework detection falls back to HTML with explicit warning; traversal/output-root safety remains enforced
|
|
72
84
|
- `da-vinci task-execution --project <path> --change <id> --task-group <id> --status <DONE|DONE_WITH_CONCERNS|NEEDS_CONTEXT|BLOCKED> --summary <text> [--changed-files <csv>] [--test-evidence <csv>] [--concerns <csv>] [--blockers <csv>] [--json]`
|
|
73
85
|
- persists normalized implementer-status envelopes into execution signals
|
|
74
86
|
- use this to keep resume routing machine-readable when implementation is blocked or concerns remain
|
|
@@ -71,6 +71,7 @@ Continuation precedence:
|
|
|
71
71
|
- run `da-vinci scope-check --project <path> [--change <id>]` when page or state propagation across planning artifacts is uncertain
|
|
72
72
|
- run `da-vinci lint-tasks --project <path> [--change <id>]` before routing into `build` when task metadata quality is uncertain
|
|
73
73
|
- run `da-vinci verify-bindings --project <path> [--change <id>]` and `da-vinci verify-coverage --project <path> [--change <id>]` before terminal completion routing
|
|
74
|
+
- if using `--changed-files` with `verify-implementation`/`verify-structure`/`verify-coverage`, treat results as explicit incremental partial evidence, not full-project freshness
|
|
74
75
|
- run `da-vinci diff-spec --project <path> [--change <id>]` after planning edits when continuation must reason about changed requirement slices
|
|
75
76
|
- determine routing from artifact and checkpoint truth first
|
|
76
77
|
- use contextual checkpoint deltas only as auxiliary recovery context
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# SKILL Contract Maintenance
|
|
2
|
+
|
|
3
|
+
Use this policy when editing workflow guidance:
|
|
4
|
+
|
|
5
|
+
1. Keep invariant route/execution truth in `SKILL.md` only.
|
|
6
|
+
2. Keep stage-specific procedure in one owned reference file.
|
|
7
|
+
3. Ensure `SKILL.md` `Load References On Demand` map points to that owner.
|
|
8
|
+
4. Avoid duplicate prose across `SKILL.md`, `references/`, and generated command assets unless tests explicitly require duplication.
|
|
9
|
+
5. Update `references/skill-workflow-detail.md` move map when relocating sections.
|
|
10
|
+
|
|
11
|
+
Boundary rule:
|
|
12
|
+
|
|
13
|
+
- If a rule changes workflow truth, route semantics, or execution policy, edit core.
|
|
14
|
+
- If a rule is tactical for one stage (design/build/review/scaffold), edit reference docs.
|
|
@@ -68,9 +68,21 @@ Da Vinci 期望它们遵循工作流状态。
|
|
|
68
68
|
- `da-vinci generate-sidecars --project <path> [--change <id>] [--json]`
|
|
69
69
|
- 显式生成确定性的 planning sidecars:`spec.index.json`、`tasks.index.json`、`page-map.index.json`、`bindings.index.json`
|
|
70
70
|
- sidecar 只允许通过这个命令写入;lint/status/verify 不应静默重写
|
|
71
|
-
- `da-vinci verify-bindings
|
|
72
|
-
-
|
|
73
|
-
|
|
71
|
+
- `da-vinci verify-bindings --project <path> [--change <id>] [--strict] [--json]`
|
|
72
|
+
- 校验 `pencil-bindings.md` 的实现落点能否被正确解析
|
|
73
|
+
- `da-vinci verify-implementation --project <path> [--change <id>] [--changed-files <csv>] [--strict] [--json]`
|
|
74
|
+
- 以每个检查项的 `mode` + `confidence` 证据模型校验状态/任务组实现覆盖
|
|
75
|
+
- JS/TS 会走语法感知检查,不把“仅注释命中”或“仅字符串字面量命中”当作正常覆盖
|
|
76
|
+
- 使用 `--changed-files` 时会进入显式增量模式(partial 语义),并输出 selected/scanned/filtered 统计
|
|
77
|
+
- `da-vinci verify-structure --project <path> [--change <id>] [--changed-files <csv>] [--strict] [--json]`
|
|
78
|
+
- 校验 bindings 驱动的结构一致性,并显式报告 `markup`/`heuristic` 置信度
|
|
79
|
+
- 使用 `--changed-files` 时,不相关条目会被显式报告,不会静默扩展成全量扫描
|
|
80
|
+
- `da-vinci verify-coverage --project <path> [--change <id>] [--changed-files <csv>] [--strict] [--json]`
|
|
81
|
+
- 聚合上游 verify surface,并在上游是增量验证时明确标记 partial freshness
|
|
82
|
+
- `da-vinci scaffold --project <path> [--change <id>] [--output <path>] [--json]`
|
|
83
|
+
- 生成 framework-aware 的 TODO 可审查骨架(`next`/`react`/`vue`/`svelte`/`html`)
|
|
84
|
+
- 若已存在明确实现落点,会优先保留该落点的扩展名与路由形状
|
|
85
|
+
- 框架未知或冲突时显式告警并回退 HTML;同时继续严格执行 traversal/output-root 安全约束
|
|
74
86
|
- `da-vinci task-execution --project <path> --change <id> --task-group <id> --status <DONE|DONE_WITH_CONCERNS|NEEDS_CONTEXT|BLOCKED> --summary <text> [--changed-files <csv>] [--test-evidence <csv>] [--concerns <csv>] [--blockers <csv>] [--json]`
|
|
75
87
|
- 持久化结构化 implementer 执行结果包,作为 task 级执行证据
|
|
76
88
|
- `da-vinci task-review --project <path> --change <id> --task-group <id> --stage <spec|quality> --status <PASS|WARN|BLOCK> --summary <text> [--issues <csv>] [--reviewer <name>] [--write-verification] [--json]`
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
- 如果页面或状态在规划工件中的传播关系不确定,进入 `build` 前先运行 `da-vinci scope-check --project <path> [--change <id>]`
|
|
73
73
|
- 如果任务拆解质量不确定,进入 `build` 前先运行 `da-vinci lint-tasks --project <path> [--change <id>]`
|
|
74
74
|
- 进入终态前先运行 `da-vinci verify-bindings --project <path> [--change <id>]` 与 `da-vinci verify-coverage --project <path> [--change <id>]`
|
|
75
|
+
- 若在 `verify-implementation`/`verify-structure`/`verify-coverage` 使用 `--changed-files`,要把结果视为显式增量 partial 证据,而不是全量 fresh 验证
|
|
75
76
|
- 当规划切片有改动且需要恢复判断时,运行 `da-vinci diff-spec --project <path> [--change <id>]`
|
|
76
77
|
- 先根据工件和 checkpoint 真相决定路由
|
|
77
78
|
- Context Delta 只用于恢复和解释,不用于覆盖选路
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const { writeExecutionSignal } = require("../execution-signals");
|
|
2
|
+
|
|
3
|
+
function emitOrThrowOnStatus(status, blockedStatuses, output, continueOnError) {
|
|
4
|
+
if (!Array.isArray(blockedStatuses) || !blockedStatuses.includes(status)) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
if (continueOnError) {
|
|
8
|
+
console.log(output);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
throw new Error(output);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function persistExecutionSignal(projectPath, changeId, surface, result, strict = false) {
|
|
15
|
+
try {
|
|
16
|
+
writeExecutionSignal(projectPath, {
|
|
17
|
+
changeId: changeId || "global",
|
|
18
|
+
surface,
|
|
19
|
+
status: result.status,
|
|
20
|
+
advisory: strict ? false : true,
|
|
21
|
+
strict,
|
|
22
|
+
failures: result.failures || [],
|
|
23
|
+
warnings: result.warnings || [],
|
|
24
|
+
notes: result.notes || []
|
|
25
|
+
});
|
|
26
|
+
} catch (error) {
|
|
27
|
+
// Signals are advisory metadata and should not break command execution.
|
|
28
|
+
const code = error && error.code ? String(error.code).toUpperCase() : "";
|
|
29
|
+
if (code === "EACCES" || code === "ENOSPC") {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const message = error && error.message ? error.message : String(error);
|
|
34
|
+
console.error(
|
|
35
|
+
`Warning: failed to persist execution signal (${surface}) for change ${changeId || "global"}: ${message}`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
emitOrThrowOnStatus,
|
|
42
|
+
persistExecutionSignal
|
|
43
|
+
};
|
|
@@ -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
|
+
};
|
package/lib/cli.js
CHANGED
|
@@ -78,7 +78,9 @@ const {
|
|
|
78
78
|
} = require("./verify");
|
|
79
79
|
const { diffSpec, formatDiffSpecReport } = require("./diff-spec");
|
|
80
80
|
const { scaffoldFromBindings, formatScaffoldReport } = require("./scaffold");
|
|
81
|
-
const {
|
|
81
|
+
const { emitOrThrowOnStatus, persistExecutionSignal } = require("./cli/helpers");
|
|
82
|
+
const { handleVerifyFamilyCommand } = require("./cli/verify-family");
|
|
83
|
+
const { handleLintFamilyCommand } = require("./cli/lint-family");
|
|
82
84
|
const {
|
|
83
85
|
writeTaskExecutionEnvelope,
|
|
84
86
|
formatTaskExecutionReport
|
|
@@ -187,7 +189,10 @@ const HELP_OPTION_SPECS = [
|
|
|
187
189
|
{ flag: "--stage <value>", description: "task-review stage: spec or quality" },
|
|
188
190
|
{ flag: "--summary <text>", description: "task-execution/task-review summary text" },
|
|
189
191
|
{ flag: "--task-group <id>", description: "task group identifier for task-execution/task-review" },
|
|
190
|
-
{
|
|
192
|
+
{
|
|
193
|
+
flag: "--changed-files <csv>",
|
|
194
|
+
description: "comma-separated changed files for verify-implementation/verify-structure/verify-coverage/task-execution"
|
|
195
|
+
},
|
|
191
196
|
{ flag: "--test-evidence <csv>", description: "comma-separated test evidence commands for task-execution" },
|
|
192
197
|
{ flag: "--concerns <csv>", description: "comma-separated concern text for task-execution" },
|
|
193
198
|
{ flag: "--blockers <csv>", description: "comma-separated blocker text for task-execution" },
|
|
@@ -379,17 +384,6 @@ function shouldContinueOnError(args) {
|
|
|
379
384
|
return Array.isArray(args) && args.includes("--continue-on-error");
|
|
380
385
|
}
|
|
381
386
|
|
|
382
|
-
function emitOrThrowOnStatus(status, blockedStatuses, output, continueOnError) {
|
|
383
|
-
if (!Array.isArray(blockedStatuses) || !blockedStatuses.includes(status)) {
|
|
384
|
-
return false;
|
|
385
|
-
}
|
|
386
|
-
if (continueOnError) {
|
|
387
|
-
console.log(output);
|
|
388
|
-
return true;
|
|
389
|
-
}
|
|
390
|
-
throw new Error(output);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
387
|
function getIntegerOption(args, name, options = {}) {
|
|
394
388
|
const raw = getOption(args, name);
|
|
395
389
|
if (raw === undefined) {
|
|
@@ -477,32 +471,6 @@ function appendStatusIssues(lines, label, missing = [], mismatched = [], unreada
|
|
|
477
471
|
}
|
|
478
472
|
}
|
|
479
473
|
|
|
480
|
-
function persistExecutionSignal(projectPath, changeId, surface, result, strict = false) {
|
|
481
|
-
try {
|
|
482
|
-
writeExecutionSignal(projectPath, {
|
|
483
|
-
changeId: changeId || "global",
|
|
484
|
-
surface,
|
|
485
|
-
status: result.status,
|
|
486
|
-
advisory: strict ? false : true,
|
|
487
|
-
strict,
|
|
488
|
-
failures: result.failures || [],
|
|
489
|
-
warnings: result.warnings || [],
|
|
490
|
-
notes: result.notes || []
|
|
491
|
-
});
|
|
492
|
-
} catch (error) {
|
|
493
|
-
// Signals are advisory metadata and should not break command execution.
|
|
494
|
-
const code = error && error.code ? String(error.code).toUpperCase() : "";
|
|
495
|
-
if (code === "EACCES" || code === "ENOSPC") {
|
|
496
|
-
return;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
const message = error && error.message ? error.message : String(error);
|
|
500
|
-
console.error(
|
|
501
|
-
`Warning: failed to persist execution signal (${surface}) for change ${changeId || "global"}: ${message}`
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
474
|
function printHelp() {
|
|
507
475
|
const optionLines = HELP_OPTION_SPECS.map((optionSpec) => {
|
|
508
476
|
const paddedFlag = optionSpec.flag.padEnd(30, " ");
|
|
@@ -526,9 +494,9 @@ function printHelp() {
|
|
|
526
494
|
" da-vinci lint-bindings [--project <path>] [--change <id>] [--strict] [--json]",
|
|
527
495
|
" da-vinci generate-sidecars [--project <path>] [--change <id>] [--json]",
|
|
528
496
|
" da-vinci verify-bindings [--project <path>] [--change <id>] [--strict] [--json]",
|
|
529
|
-
" da-vinci verify-implementation [--project <path>] [--change <id>] [--strict] [--json]",
|
|
530
|
-
" da-vinci verify-structure [--project <path>] [--change <id>] [--strict] [--json]",
|
|
531
|
-
" da-vinci verify-coverage [--project <path>] [--change <id>] [--strict] [--json]",
|
|
497
|
+
" da-vinci verify-implementation [--project <path>] [--change <id>] [--changed-files <csv>] [--strict] [--json]",
|
|
498
|
+
" da-vinci verify-structure [--project <path>] [--change <id>] [--changed-files <csv>] [--strict] [--json]",
|
|
499
|
+
" da-vinci verify-coverage [--project <path>] [--change <id>] [--changed-files <csv>] [--strict] [--json]",
|
|
532
500
|
" da-vinci task-execution --project <path> --change <id> --task-group <id> --status <DONE|DONE_WITH_CONCERNS|NEEDS_CONTEXT|BLOCKED> --summary <text> [--changed-files <csv>] [--test-evidence <csv>] [--concerns <csv>] [--blockers <csv>] [--json]",
|
|
533
501
|
" da-vinci task-review --project <path> --change <id> --task-group <id> --stage <spec|quality> --status <PASS|WARN|BLOCK> --summary <text> [--issues <csv>] [--reviewer <name>] [--write-verification] [--json]",
|
|
534
502
|
" da-vinci worktree-preflight --project <path> [--change <id>] [--json]",
|
|
@@ -1056,71 +1024,24 @@ async function runCli(argv) {
|
|
|
1056
1024
|
return;
|
|
1057
1025
|
}
|
|
1058
1026
|
|
|
1059
|
-
if (
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1078
|
-
const changeId = getOption(argv, "--change");
|
|
1079
|
-
const strict = argv.includes("--strict");
|
|
1080
|
-
const result = runScopeCheck(projectPath, { changeId, strict });
|
|
1081
|
-
persistExecutionSignal(projectPath, result.changeId || changeId, "scope-check", result, strict);
|
|
1082
|
-
const useJson = argv.includes("--json");
|
|
1083
|
-
const output = useJson ? JSON.stringify(result, null, 2) : formatScopeCheckReport(result);
|
|
1084
|
-
|
|
1085
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1086
|
-
return;
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
console.log(output);
|
|
1090
|
-
return;
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
if (command === "lint-tasks") {
|
|
1094
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1095
|
-
const changeId = getOption(argv, "--change");
|
|
1096
|
-
const strict = argv.includes("--strict");
|
|
1097
|
-
const result = lintTasks(projectPath, { changeId, strict });
|
|
1098
|
-
persistExecutionSignal(projectPath, result.changeId || changeId, "lint-tasks", result, strict);
|
|
1099
|
-
const useJson = argv.includes("--json");
|
|
1100
|
-
const output = useJson ? JSON.stringify(result, null, 2) : formatLintTasksReport(result);
|
|
1101
|
-
|
|
1102
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1103
|
-
return;
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
console.log(output);
|
|
1107
|
-
return;
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
if (command === "lint-bindings") {
|
|
1111
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1112
|
-
const changeId = getOption(argv, "--change");
|
|
1113
|
-
const strict = argv.includes("--strict");
|
|
1114
|
-
const result = lintBindings(projectPath, { changeId, strict });
|
|
1115
|
-
persistExecutionSignal(projectPath, result.changeId || changeId, "lint-bindings", result, strict);
|
|
1116
|
-
const useJson = argv.includes("--json");
|
|
1117
|
-
const output = useJson ? JSON.stringify(result, null, 2) : formatLintBindingsReport(result);
|
|
1118
|
-
|
|
1119
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1120
|
-
return;
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
console.log(output);
|
|
1027
|
+
if (
|
|
1028
|
+
handleLintFamilyCommand(command, {
|
|
1029
|
+
argv,
|
|
1030
|
+
positionalArgs,
|
|
1031
|
+
continueOnError,
|
|
1032
|
+
getOption,
|
|
1033
|
+
lintRuntimeSpecs,
|
|
1034
|
+
formatLintSpecReport,
|
|
1035
|
+
runScopeCheck,
|
|
1036
|
+
formatScopeCheckReport,
|
|
1037
|
+
lintTasks,
|
|
1038
|
+
formatLintTasksReport,
|
|
1039
|
+
lintBindings,
|
|
1040
|
+
formatLintBindingsReport,
|
|
1041
|
+
emitOrThrowOnStatus,
|
|
1042
|
+
persistExecutionSignal
|
|
1043
|
+
})
|
|
1044
|
+
) {
|
|
1124
1045
|
return;
|
|
1125
1046
|
}
|
|
1126
1047
|
|
|
@@ -1140,71 +1061,23 @@ async function runCli(argv) {
|
|
|
1140
1061
|
return;
|
|
1141
1062
|
}
|
|
1142
1063
|
|
|
1143
|
-
if (
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
if (command === "verify-implementation") {
|
|
1161
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1162
|
-
const changeId = getOption(argv, "--change");
|
|
1163
|
-
const strict = argv.includes("--strict");
|
|
1164
|
-
const result = verifyImplementation(projectPath, { changeId, strict });
|
|
1165
|
-
persistExecutionSignal(projectPath, result.changeId || changeId, "verify-implementation", result, strict);
|
|
1166
|
-
const useJson = argv.includes("--json");
|
|
1167
|
-
const output = useJson
|
|
1168
|
-
? JSON.stringify(result, null, 2)
|
|
1169
|
-
: formatVerifyReport(result, "Da Vinci verify-implementation");
|
|
1170
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1171
|
-
return;
|
|
1172
|
-
}
|
|
1173
|
-
console.log(output);
|
|
1174
|
-
return;
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
if (command === "verify-structure") {
|
|
1178
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1179
|
-
const changeId = getOption(argv, "--change");
|
|
1180
|
-
const strict = argv.includes("--strict");
|
|
1181
|
-
const result = verifyStructure(projectPath, { changeId, strict });
|
|
1182
|
-
persistExecutionSignal(projectPath, result.changeId || changeId, "verify-structure", result, strict);
|
|
1183
|
-
const useJson = argv.includes("--json");
|
|
1184
|
-
const output = useJson
|
|
1185
|
-
? JSON.stringify(result, null, 2)
|
|
1186
|
-
: formatVerifyReport(result, "Da Vinci verify-structure");
|
|
1187
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1188
|
-
return;
|
|
1189
|
-
}
|
|
1190
|
-
console.log(output);
|
|
1191
|
-
return;
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
if (command === "verify-coverage") {
|
|
1195
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1196
|
-
const changeId = getOption(argv, "--change");
|
|
1197
|
-
const strict = argv.includes("--strict");
|
|
1198
|
-
const result = verifyCoverage(projectPath, { changeId, strict });
|
|
1199
|
-
persistExecutionSignal(projectPath, result.changeId || changeId, "verify-coverage", result, strict);
|
|
1200
|
-
const useJson = argv.includes("--json");
|
|
1201
|
-
const output = useJson
|
|
1202
|
-
? JSON.stringify(result, null, 2)
|
|
1203
|
-
: formatVerifyReport(result, "Da Vinci verify-coverage");
|
|
1204
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1205
|
-
return;
|
|
1206
|
-
}
|
|
1207
|
-
console.log(output);
|
|
1064
|
+
if (
|
|
1065
|
+
handleVerifyFamilyCommand(command, {
|
|
1066
|
+
argv,
|
|
1067
|
+
positionalArgs,
|
|
1068
|
+
continueOnError,
|
|
1069
|
+
getOption,
|
|
1070
|
+
getCommaSeparatedOptionValues,
|
|
1071
|
+
collectOptionEntries,
|
|
1072
|
+
verifyBindings,
|
|
1073
|
+
verifyImplementation,
|
|
1074
|
+
verifyStructure,
|
|
1075
|
+
verifyCoverage,
|
|
1076
|
+
formatVerifyReport,
|
|
1077
|
+
emitOrThrowOnStatus,
|
|
1078
|
+
persistExecutionSignal
|
|
1079
|
+
})
|
|
1080
|
+
) {
|
|
1208
1081
|
return;
|
|
1209
1082
|
}
|
|
1210
1083
|
|
package/lib/planning-parsers.js
CHANGED
|
@@ -66,7 +66,7 @@ function unique(values) {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function resolveImplementationLanding(projectRoot, implementationToken) {
|
|
69
|
-
const knownExtensions = [".html", ".tsx", ".jsx", ".ts", ".js"];
|
|
69
|
+
const knownExtensions = [".html", ".tsx", ".jsx", ".ts", ".js", ".vue", ".svelte"];
|
|
70
70
|
const seen = new Set();
|
|
71
71
|
const candidates = [];
|
|
72
72
|
const addCandidate = (relativePath) => {
|
|
@@ -93,6 +93,9 @@ function resolveImplementationLanding(projectRoot, implementationToken) {
|
|
|
93
93
|
addCandidate(path.join(dirPath, `page${extension}`));
|
|
94
94
|
}
|
|
95
95
|
};
|
|
96
|
+
const addSvelteRoutePageCandidate = (dirPath) => {
|
|
97
|
+
addCandidate(path.join(dirPath, "+page.svelte"));
|
|
98
|
+
};
|
|
96
99
|
const resolveFileCandidate = (relativePath) => {
|
|
97
100
|
const absolutePath = path.join(projectRoot, relativePath);
|
|
98
101
|
try {
|
|
@@ -118,6 +121,8 @@ function resolveImplementationLanding(projectRoot, implementationToken) {
|
|
|
118
121
|
addPageCandidates("app");
|
|
119
122
|
addFileCandidates(path.join("src", "app", "page"));
|
|
120
123
|
addPageCandidates(path.join("src", "app"));
|
|
124
|
+
addSvelteRoutePageCandidate(path.join("src", "routes"));
|
|
125
|
+
addSvelteRoutePageCandidate("routes");
|
|
121
126
|
} else {
|
|
122
127
|
const routePath = normalized.replace(/^\//, "").replace(/\/+$/, "");
|
|
123
128
|
addFileCandidates(routePath);
|
|
@@ -135,6 +140,8 @@ function resolveImplementationLanding(projectRoot, implementationToken) {
|
|
|
135
140
|
addPageCandidates(path.join("app", routePath));
|
|
136
141
|
addFileCandidates(path.join("src", "app", routePath, "page"));
|
|
137
142
|
addPageCandidates(path.join("src", "app", routePath));
|
|
143
|
+
addSvelteRoutePageCandidate(path.join("src", "routes", routePath));
|
|
144
|
+
addSvelteRoutePageCandidate(path.join("routes", routePath));
|
|
138
145
|
}
|
|
139
146
|
|
|
140
147
|
for (const candidate of candidates) {
|