@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.
- package/CHANGELOG.md +35 -0
- package/README.md +15 -9
- package/README.zh-CN.md +16 -9
- package/SKILL.md +45 -704
- package/docs/dv-command-reference.md +33 -5
- package/docs/execution-chain-migration.md +14 -3
- package/docs/maintainer-bootstrap.md +102 -0
- package/docs/pencil-rendering-workflow.md +1 -1
- package/docs/prompt-entrypoints.md +1 -0
- package/docs/skill-contract-maintenance.md +14 -0
- package/docs/skill-usage.md +31 -0
- package/docs/workflow-overview.md +40 -5
- package/docs/zh-CN/dv-command-reference.md +31 -5
- package/docs/zh-CN/maintainer-bootstrap.md +101 -0
- package/docs/zh-CN/pencil-rendering-workflow.md +1 -1
- package/docs/zh-CN/prompt-entrypoints.md +1 -0
- package/docs/zh-CN/skill-usage.md +30 -0
- package/docs/zh-CN/workflow-overview.md +38 -5
- package/lib/audit.js +19 -0
- package/lib/cli/helpers.js +104 -0
- package/lib/cli/lint-family.js +56 -0
- package/lib/cli/verify-family.js +79 -0
- package/lib/cli.js +143 -172
- package/lib/gate-utils.js +56 -0
- package/lib/install.js +134 -6
- package/lib/lint-bindings.js +41 -28
- package/lib/lint-spec.js +403 -109
- package/lib/lint-tasks.js +571 -21
- package/lib/maintainer-readiness.js +317 -0
- package/lib/planning-parsers.js +198 -2
- package/lib/planning-quality-utils.js +81 -0
- package/lib/planning-signal-freshness.js +205 -0
- package/lib/scaffold.js +454 -23
- package/lib/scope-check.js +751 -82
- package/lib/sidecars.js +396 -1
- package/lib/task-review.js +2 -1
- package/lib/utils.js +34 -0
- package/lib/verify.js +1160 -88
- package/lib/workflow-persisted-state.js +52 -32
- package/lib/workflow-state.js +1187 -249
- package/package.json +1 -1
- package/references/skill-workflow-detail.md +66 -0
package/lib/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ const {
|
|
|
4
4
|
installPlatforms,
|
|
5
5
|
uninstallPlatforms,
|
|
6
6
|
getStatus,
|
|
7
|
+
verifyInstall,
|
|
7
8
|
validateAssets
|
|
8
9
|
} = require("./install");
|
|
9
10
|
const { auditProject, formatAuditReport } = require("./audit");
|
|
@@ -78,7 +79,9 @@ const {
|
|
|
78
79
|
} = require("./verify");
|
|
79
80
|
const { diffSpec, formatDiffSpecReport } = require("./diff-spec");
|
|
80
81
|
const { scaffoldFromBindings, formatScaffoldReport } = require("./scaffold");
|
|
81
|
-
const {
|
|
82
|
+
const { emitOrThrowOnStatus, persistExecutionSignal } = require("./cli/helpers");
|
|
83
|
+
const { handleVerifyFamilyCommand } = require("./cli/verify-family");
|
|
84
|
+
const { handleLintFamilyCommand } = require("./cli/lint-family");
|
|
82
85
|
const {
|
|
83
86
|
writeTaskExecutionEnvelope,
|
|
84
87
|
formatTaskExecutionReport
|
|
@@ -92,6 +95,10 @@ const {
|
|
|
92
95
|
formatWorktreePreflightReport
|
|
93
96
|
} = require("./worktree-preflight");
|
|
94
97
|
const { formatTuiHelp, launchTui } = require("../tui");
|
|
98
|
+
const {
|
|
99
|
+
runMaintainerReadinessCheck,
|
|
100
|
+
formatMaintainerReadinessReport
|
|
101
|
+
} = require("./maintainer-readiness");
|
|
95
102
|
|
|
96
103
|
const DEFAULT_MAX_PREFLIGHT_STDIN_BYTES = 1024 * 1024;
|
|
97
104
|
const DEFAULT_MAX_STDIN_TRANSIENT_RETRIES = 2000;
|
|
@@ -187,7 +194,10 @@ const HELP_OPTION_SPECS = [
|
|
|
187
194
|
{ flag: "--stage <value>", description: "task-review stage: spec or quality" },
|
|
188
195
|
{ flag: "--summary <text>", description: "task-execution/task-review summary text" },
|
|
189
196
|
{ flag: "--task-group <id>", description: "task group identifier for task-execution/task-review" },
|
|
190
|
-
{
|
|
197
|
+
{
|
|
198
|
+
flag: "--changed-files <csv>",
|
|
199
|
+
description: "comma-separated changed files for verify-implementation/verify-structure/verify-coverage/task-execution"
|
|
200
|
+
},
|
|
191
201
|
{ flag: "--test-evidence <csv>", description: "comma-separated test evidence commands for task-execution" },
|
|
192
202
|
{ flag: "--concerns <csv>", description: "comma-separated concern text for task-execution" },
|
|
193
203
|
{ flag: "--blockers <csv>", description: "comma-separated blocker text for task-execution" },
|
|
@@ -379,17 +389,6 @@ function shouldContinueOnError(args) {
|
|
|
379
389
|
return Array.isArray(args) && args.includes("--continue-on-error");
|
|
380
390
|
}
|
|
381
391
|
|
|
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
392
|
function getIntegerOption(args, name, options = {}) {
|
|
394
393
|
const raw = getOption(args, name);
|
|
395
394
|
if (raw === undefined) {
|
|
@@ -465,6 +464,60 @@ function formatStatus(status) {
|
|
|
465
464
|
return lines.join("\n");
|
|
466
465
|
}
|
|
467
466
|
|
|
467
|
+
function formatVerifyInstallReport(result) {
|
|
468
|
+
const scopeLabel = result.scope && result.scope.known
|
|
469
|
+
? result.scope.selectedPlatforms.join(", ")
|
|
470
|
+
: "unknown";
|
|
471
|
+
const lines = [
|
|
472
|
+
"Da Vinci verify-install",
|
|
473
|
+
`Status: ${result.status}`,
|
|
474
|
+
`Home: ${result.homeDir}`,
|
|
475
|
+
"Surface: install verification (bootstrap-adjacent), not full repository readiness",
|
|
476
|
+
`Selected platform scope: ${scopeLabel}`,
|
|
477
|
+
"Platform coverage:"
|
|
478
|
+
];
|
|
479
|
+
|
|
480
|
+
for (const platform of result.scope.supportedPlatforms || []) {
|
|
481
|
+
const coverage = result.platformCoverage && result.platformCoverage[platform];
|
|
482
|
+
if (!coverage) {
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
const checkSummary = Object.entries(coverage.checks || {})
|
|
486
|
+
.map(([name, ok]) => `${name}=${ok ? "yes" : "no"}`)
|
|
487
|
+
.join(" ");
|
|
488
|
+
lines.push(
|
|
489
|
+
`- ${platform}: scope=${coverage.scope} healthy=${coverage.healthy ? "yes" : "no"}${checkSummary ? ` ${checkSummary}` : ""}`
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (Array.isArray(result.failures) && result.failures.length > 0) {
|
|
494
|
+
lines.push("Failures:");
|
|
495
|
+
for (const message of result.failures) {
|
|
496
|
+
lines.push(`- ${message}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
if (Array.isArray(result.warnings) && result.warnings.length > 0) {
|
|
500
|
+
lines.push("Warnings:");
|
|
501
|
+
for (const message of result.warnings) {
|
|
502
|
+
lines.push(`- ${message}`);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (Array.isArray(result.notes) && result.notes.length > 0) {
|
|
506
|
+
lines.push("Notes:");
|
|
507
|
+
for (const message of result.notes) {
|
|
508
|
+
lines.push(`- ${message}`);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (Array.isArray(result.nextSteps) && result.nextSteps.length > 0) {
|
|
512
|
+
lines.push("Next steps:");
|
|
513
|
+
for (const step of result.nextSteps) {
|
|
514
|
+
lines.push(`- ${step}`);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return lines.join("\n");
|
|
519
|
+
}
|
|
520
|
+
|
|
468
521
|
function appendStatusIssues(lines, label, missing = [], mismatched = [], unreadable = []) {
|
|
469
522
|
if (missing.length > 0) {
|
|
470
523
|
lines.push(` ${label} missing: ${missing.join(", ")}`);
|
|
@@ -477,32 +530,6 @@ function appendStatusIssues(lines, label, missing = [], mismatched = [], unreada
|
|
|
477
530
|
}
|
|
478
531
|
}
|
|
479
532
|
|
|
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
533
|
function printHelp() {
|
|
507
534
|
const optionLines = HELP_OPTION_SPECS.map((optionSpec) => {
|
|
508
535
|
const paddedFlag = optionSpec.flag.padEnd(30, " ");
|
|
@@ -517,6 +544,10 @@ function printHelp() {
|
|
|
517
544
|
" da-vinci install --platform codex,claude,gemini",
|
|
518
545
|
" da-vinci uninstall --platform codex,claude,gemini",
|
|
519
546
|
" da-vinci status",
|
|
547
|
+
" da-vinci verify-install [--platform <value>] [--json]",
|
|
548
|
+
" (bootstrap-adjacent install verification for selected maintainer platforms)",
|
|
549
|
+
" da-vinci maintainer-readiness [--platform <value>] [--project <path>] [--json]",
|
|
550
|
+
" (canonical repository maintainer diagnosis/readiness; not downstream bootstrap)",
|
|
520
551
|
" da-vinci tui [--project <path>] [--change <id>] [--lang en|zh] [--strict] [--json] [--continue-on-error] [--tui-width <cols>] [--alt-screen|--no-alt-screen]",
|
|
521
552
|
" da-vinci workflow-status [--project <path>] [--change <id>] [--json]",
|
|
522
553
|
" da-vinci next-step [--project <path>] [--change <id>] [--json]",
|
|
@@ -526,9 +557,9 @@ function printHelp() {
|
|
|
526
557
|
" da-vinci lint-bindings [--project <path>] [--change <id>] [--strict] [--json]",
|
|
527
558
|
" da-vinci generate-sidecars [--project <path>] [--change <id>] [--json]",
|
|
528
559
|
" 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]",
|
|
560
|
+
" da-vinci verify-implementation [--project <path>] [--change <id>] [--changed-files <csv>] [--strict] [--json]",
|
|
561
|
+
" da-vinci verify-structure [--project <path>] [--change <id>] [--changed-files <csv>] [--strict] [--json]",
|
|
562
|
+
" da-vinci verify-coverage [--project <path>] [--change <id>] [--changed-files <csv>] [--strict] [--json]",
|
|
532
563
|
" 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
564
|
" 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
565
|
" da-vinci worktree-preflight --project <path> [--change <id>] [--json]",
|
|
@@ -987,6 +1018,40 @@ async function runCli(argv) {
|
|
|
987
1018
|
return;
|
|
988
1019
|
}
|
|
989
1020
|
|
|
1021
|
+
if (command === "verify-install") {
|
|
1022
|
+
const platformValue = getOption(argv, "--platform") || "";
|
|
1023
|
+
const result = verifyInstall({
|
|
1024
|
+
homeDir,
|
|
1025
|
+
platforms: platformValue
|
|
1026
|
+
});
|
|
1027
|
+
const output = argv.includes("--json")
|
|
1028
|
+
? JSON.stringify(result, null, 2)
|
|
1029
|
+
: formatVerifyInstallReport(result);
|
|
1030
|
+
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
console.log(output);
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
if (command === "maintainer-readiness") {
|
|
1038
|
+
const platformValue = getOption(argv, "--platform") || "";
|
|
1039
|
+
const repoRoot = getOption(argv, "--project") || process.cwd();
|
|
1040
|
+
const result = runMaintainerReadinessCheck({
|
|
1041
|
+
repoRoot,
|
|
1042
|
+
homeDir,
|
|
1043
|
+
platforms: platformValue
|
|
1044
|
+
});
|
|
1045
|
+
const output = argv.includes("--json")
|
|
1046
|
+
? JSON.stringify(result, null, 2)
|
|
1047
|
+
: formatMaintainerReadinessReport(result);
|
|
1048
|
+
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
console.log(output);
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
990
1055
|
if (command === "tui") {
|
|
991
1056
|
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
992
1057
|
const changeId = getOption(argv, "--change");
|
|
@@ -1040,6 +1105,7 @@ async function runCli(argv) {
|
|
|
1040
1105
|
stage: result.stage,
|
|
1041
1106
|
checkpointState: result.checkpointState,
|
|
1042
1107
|
nextStep: result.nextStep || null,
|
|
1108
|
+
blockingGate: result.blockingGate || null,
|
|
1043
1109
|
discipline: result.discipline || null,
|
|
1044
1110
|
executionProfile: result.executionProfile || null,
|
|
1045
1111
|
worktreePreflight: result.worktreePreflight || null,
|
|
@@ -1056,71 +1122,24 @@ async function runCli(argv) {
|
|
|
1056
1122
|
return;
|
|
1057
1123
|
}
|
|
1058
1124
|
|
|
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);
|
|
1125
|
+
if (
|
|
1126
|
+
handleLintFamilyCommand(command, {
|
|
1127
|
+
argv,
|
|
1128
|
+
positionalArgs,
|
|
1129
|
+
continueOnError,
|
|
1130
|
+
getOption,
|
|
1131
|
+
lintRuntimeSpecs,
|
|
1132
|
+
formatLintSpecReport,
|
|
1133
|
+
runScopeCheck,
|
|
1134
|
+
formatScopeCheckReport,
|
|
1135
|
+
lintTasks,
|
|
1136
|
+
formatLintTasksReport,
|
|
1137
|
+
lintBindings,
|
|
1138
|
+
formatLintBindingsReport,
|
|
1139
|
+
emitOrThrowOnStatus,
|
|
1140
|
+
persistExecutionSignal
|
|
1141
|
+
})
|
|
1142
|
+
) {
|
|
1124
1143
|
return;
|
|
1125
1144
|
}
|
|
1126
1145
|
|
|
@@ -1140,71 +1159,23 @@ async function runCli(argv) {
|
|
|
1140
1159
|
return;
|
|
1141
1160
|
}
|
|
1142
1161
|
|
|
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);
|
|
1162
|
+
if (
|
|
1163
|
+
handleVerifyFamilyCommand(command, {
|
|
1164
|
+
argv,
|
|
1165
|
+
positionalArgs,
|
|
1166
|
+
continueOnError,
|
|
1167
|
+
getOption,
|
|
1168
|
+
getCommaSeparatedOptionValues,
|
|
1169
|
+
collectOptionEntries,
|
|
1170
|
+
verifyBindings,
|
|
1171
|
+
verifyImplementation,
|
|
1172
|
+
verifyStructure,
|
|
1173
|
+
verifyCoverage,
|
|
1174
|
+
formatVerifyReport,
|
|
1175
|
+
emitOrThrowOnStatus,
|
|
1176
|
+
persistExecutionSignal
|
|
1177
|
+
})
|
|
1178
|
+
) {
|
|
1208
1179
|
return;
|
|
1209
1180
|
}
|
|
1210
1181
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const { STATUS } = require("./workflow-contract");
|
|
2
|
+
const { unique } = require("./planning-parsers");
|
|
3
|
+
|
|
4
|
+
function dedupe(values) {
|
|
5
|
+
return unique(values);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function buildGateEnvelope(id, options = {}) {
|
|
9
|
+
const gate = {
|
|
10
|
+
id,
|
|
11
|
+
status: STATUS.PASS,
|
|
12
|
+
blocking: [],
|
|
13
|
+
advisory: [],
|
|
14
|
+
compatibility: [],
|
|
15
|
+
evidence: []
|
|
16
|
+
};
|
|
17
|
+
if (options.includeBounded) {
|
|
18
|
+
gate.bounded = [];
|
|
19
|
+
}
|
|
20
|
+
return gate;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function finalizeGateEnvelope(gate, options = {}) {
|
|
24
|
+
const strict = options.strict === true;
|
|
25
|
+
const includeBounded = options.includeBounded === true;
|
|
26
|
+
const warnOnBounded = options.warnOnBounded === true;
|
|
27
|
+
const warnOnCompatibility = options.warnOnCompatibility !== false;
|
|
28
|
+
const normalized = {
|
|
29
|
+
...gate,
|
|
30
|
+
blocking: dedupe(gate && gate.blocking),
|
|
31
|
+
advisory: dedupe(gate && gate.advisory),
|
|
32
|
+
compatibility: dedupe(gate && gate.compatibility),
|
|
33
|
+
evidence: dedupe(gate && gate.evidence)
|
|
34
|
+
};
|
|
35
|
+
if (includeBounded || Array.isArray(gate && gate.bounded)) {
|
|
36
|
+
normalized.bounded = dedupe(gate && gate.bounded);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (normalized.blocking.length > 0) {
|
|
40
|
+
normalized.status = strict ? STATUS.BLOCK : STATUS.WARN;
|
|
41
|
+
return normalized;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const hasWarnLevelFindings =
|
|
45
|
+
normalized.advisory.length > 0 ||
|
|
46
|
+
(warnOnCompatibility && normalized.compatibility.length > 0) ||
|
|
47
|
+
(warnOnBounded && Array.isArray(normalized.bounded) && normalized.bounded.length > 0);
|
|
48
|
+
normalized.status = hasWarnLevelFindings ? STATUS.WARN : STATUS.PASS;
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
dedupe,
|
|
54
|
+
buildGateEnvelope,
|
|
55
|
+
finalizeGateEnvelope
|
|
56
|
+
};
|
package/lib/install.js
CHANGED
|
@@ -18,6 +18,7 @@ const REQUIRED_FILES = [
|
|
|
18
18
|
...listFiles(path.join(REPO_ROOT, "docs")).map((filePath) => path.relative(REPO_ROOT, filePath)),
|
|
19
19
|
...listFiles(path.join(REPO_ROOT, "examples")).map((filePath) => path.relative(REPO_ROOT, filePath))
|
|
20
20
|
];
|
|
21
|
+
const SUPPORTED_PLATFORMS = ["codex", "claude", "gemini"];
|
|
21
22
|
|
|
22
23
|
const CODEX_PROMPT_TARGET_PAIRS = listFiles(path.join(REPO_ROOT, "commands", "codex", "prompts")).map(
|
|
23
24
|
(filePath) => ({
|
|
@@ -90,7 +91,7 @@ function resolveHome(homeDir) {
|
|
|
90
91
|
|
|
91
92
|
function parsePlatforms(raw) {
|
|
92
93
|
if (!raw || raw === "all") {
|
|
93
|
-
return
|
|
94
|
+
return SUPPORTED_PLATFORMS.slice();
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
const platforms = raw
|
|
@@ -99,7 +100,7 @@ function parsePlatforms(raw) {
|
|
|
99
100
|
.filter(Boolean);
|
|
100
101
|
|
|
101
102
|
const unique = [...new Set(platforms)];
|
|
102
|
-
const invalid = unique.filter((value) => !
|
|
103
|
+
const invalid = unique.filter((value) => !SUPPORTED_PLATFORMS.includes(value));
|
|
103
104
|
|
|
104
105
|
if (invalid.length > 0) {
|
|
105
106
|
throw new Error(`Unsupported platform value: ${invalid.join(", ")}`);
|
|
@@ -108,6 +109,129 @@ function parsePlatforms(raw) {
|
|
|
108
109
|
return unique;
|
|
109
110
|
}
|
|
110
111
|
|
|
112
|
+
function summarizePlatformInstallConfidence(statusPayload) {
|
|
113
|
+
const status = statusPayload && typeof statusPayload === "object" ? statusPayload : {};
|
|
114
|
+
const codex = status.codex && typeof status.codex === "object" ? status.codex : {};
|
|
115
|
+
const claude = status.claude && typeof status.claude === "object" ? status.claude : {};
|
|
116
|
+
const gemini = status.gemini && typeof status.gemini === "object" ? status.gemini : {};
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
codex: {
|
|
120
|
+
checks: {
|
|
121
|
+
prompt: codex.prompt === true,
|
|
122
|
+
skill: codex.skill === true
|
|
123
|
+
},
|
|
124
|
+
missing: [...(codex.promptMissing || []), ...(codex.skillMissing || [])],
|
|
125
|
+
mismatched: [...(codex.promptMismatched || []), ...(codex.skillMismatched || [])],
|
|
126
|
+
unreadable: [...(codex.promptUnreadable || []), ...(codex.skillUnreadable || [])]
|
|
127
|
+
},
|
|
128
|
+
claude: {
|
|
129
|
+
checks: {
|
|
130
|
+
command: claude.command === true,
|
|
131
|
+
actionSet: claude.actionSet === true
|
|
132
|
+
},
|
|
133
|
+
missing: [...(claude.commandMissing || []), ...(claude.actionSetMissing || [])],
|
|
134
|
+
mismatched: [...(claude.commandMismatched || []), ...(claude.actionSetMismatched || [])],
|
|
135
|
+
unreadable: [...(claude.commandUnreadable || []), ...(claude.actionSetUnreadable || [])]
|
|
136
|
+
},
|
|
137
|
+
gemini: {
|
|
138
|
+
checks: {
|
|
139
|
+
command: gemini.command === true,
|
|
140
|
+
actionSet: gemini.actionSet === true
|
|
141
|
+
},
|
|
142
|
+
missing: [...(gemini.commandMissing || []), ...(gemini.actionSetMissing || [])],
|
|
143
|
+
mismatched: [...(gemini.commandMismatched || []), ...(gemini.actionSetMismatched || [])],
|
|
144
|
+
unreadable: [...(gemini.commandUnreadable || []), ...(gemini.actionSetUnreadable || [])]
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function verifyInstall(options = {}) {
|
|
150
|
+
const homeDir = resolveHome(options.homeDir);
|
|
151
|
+
const explicitScopeRaw = String(options.platforms || "").trim();
|
|
152
|
+
const scopeKnown = explicitScopeRaw.length > 0;
|
|
153
|
+
const selectedPlatforms = scopeKnown ? parsePlatforms(explicitScopeRaw) : [];
|
|
154
|
+
const status = getStatus({ homeDir });
|
|
155
|
+
const confidence = summarizePlatformInstallConfidence(status);
|
|
156
|
+
const platformCoverage = {};
|
|
157
|
+
const failures = [];
|
|
158
|
+
const warnings = [];
|
|
159
|
+
const notes = [];
|
|
160
|
+
|
|
161
|
+
for (const platform of SUPPORTED_PLATFORMS) {
|
|
162
|
+
const selected = selectedPlatforms.includes(platform);
|
|
163
|
+
const scope = scopeKnown ? (selected ? "selected" : "out_of_scope") : "unknown";
|
|
164
|
+
const platformConfidence = confidence[platform];
|
|
165
|
+
const failedChecks = Object.keys(platformConfidence.checks).filter(
|
|
166
|
+
(checkKey) => platformConfidence.checks[checkKey] !== true
|
|
167
|
+
);
|
|
168
|
+
const healthy = failedChecks.length === 0;
|
|
169
|
+
platformCoverage[platform] = {
|
|
170
|
+
scope,
|
|
171
|
+
healthy,
|
|
172
|
+
checks: platformConfidence.checks,
|
|
173
|
+
missing: platformConfidence.missing,
|
|
174
|
+
mismatched: platformConfidence.mismatched,
|
|
175
|
+
unreadable: platformConfidence.unreadable
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
if (scope === "selected" && !healthy) {
|
|
179
|
+
failures.push(
|
|
180
|
+
`${platform} install verification failed for selected scope (${failedChecks.join(
|
|
181
|
+
", "
|
|
182
|
+
)}). Run \`da-vinci install --platform ${platform}\` and re-run verify-install.`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
if (scope === "unknown" && !healthy) {
|
|
186
|
+
warnings.push(
|
|
187
|
+
`${platform} install verification is incomplete, but selected platform scope is unknown.`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
if (scope === "out_of_scope" && !healthy) {
|
|
191
|
+
notes.push(
|
|
192
|
+
`${platform} is out-of-scope for this verify-install run and is reported as degraded coverage.`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (!scopeKnown) {
|
|
198
|
+
warnings.push(
|
|
199
|
+
"Selected platform scope is unknown; pass `--platform <value>` so verify-install can evaluate selected targets explicitly."
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const statusToken = failures.length > 0 ? "BLOCK" : warnings.length > 0 ? "WARN" : "PASS";
|
|
204
|
+
const nextSteps = [];
|
|
205
|
+
if (failures.length > 0) {
|
|
206
|
+
nextSteps.push("Fix selected-platform install failures, then rerun `da-vinci verify-install`.");
|
|
207
|
+
}
|
|
208
|
+
if (!scopeKnown) {
|
|
209
|
+
nextSteps.push(
|
|
210
|
+
"Rerun with explicit scope, for example `da-vinci verify-install --platform codex`, to avoid unknown-scope coverage."
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
if (statusToken === "PASS") {
|
|
214
|
+
nextSteps.push(
|
|
215
|
+
"Continue with repository readiness checks (for example `da-vinci maintainer-readiness`)."
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
status: statusToken,
|
|
221
|
+
homeDir,
|
|
222
|
+
scope: {
|
|
223
|
+
known: scopeKnown,
|
|
224
|
+
selectedPlatforms,
|
|
225
|
+
supportedPlatforms: SUPPORTED_PLATFORMS.slice()
|
|
226
|
+
},
|
|
227
|
+
platformCoverage,
|
|
228
|
+
failures: failures,
|
|
229
|
+
warnings: warnings,
|
|
230
|
+
notes: notes,
|
|
231
|
+
nextSteps
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
111
235
|
function ensureDir(targetPath) {
|
|
112
236
|
fs.mkdirSync(targetPath, { recursive: true });
|
|
113
237
|
}
|
|
@@ -407,25 +531,29 @@ function getStatus(options = {}) {
|
|
|
407
531
|
};
|
|
408
532
|
}
|
|
409
533
|
|
|
410
|
-
function validateAssets() {
|
|
534
|
+
function validateAssets(options = {}) {
|
|
535
|
+
const repoRoot = options.repoRoot ? path.resolve(String(options.repoRoot)) : REPO_ROOT;
|
|
411
536
|
const missing = REQUIRED_FILES.filter((relativePath) => {
|
|
412
|
-
return !fs.existsSync(path.join(
|
|
537
|
+
return !fs.existsSync(path.join(repoRoot, relativePath));
|
|
413
538
|
});
|
|
414
539
|
|
|
415
540
|
if (missing.length > 0) {
|
|
416
|
-
throw new Error(`Missing required assets:\n${missing.join("\n")}`);
|
|
541
|
+
throw new Error(`Missing required assets under ${repoRoot}:\n${missing.join("\n")}`);
|
|
417
542
|
}
|
|
418
543
|
|
|
419
544
|
return {
|
|
420
545
|
version: VERSION,
|
|
421
|
-
requiredAssets: REQUIRED_FILES.length
|
|
546
|
+
requiredAssets: REQUIRED_FILES.length,
|
|
547
|
+
repoRoot
|
|
422
548
|
};
|
|
423
549
|
}
|
|
424
550
|
|
|
425
551
|
module.exports = {
|
|
426
552
|
VERSION,
|
|
553
|
+
SUPPORTED_PLATFORMS,
|
|
427
554
|
installPlatforms,
|
|
428
555
|
uninstallPlatforms,
|
|
429
556
|
getStatus,
|
|
557
|
+
verifyInstall,
|
|
430
558
|
validateAssets
|
|
431
559
|
};
|