@xenonbyte/da-vinci-workflow 0.2.7 → 0.2.9
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 +31 -0
- package/README.md +7 -7
- package/README.zh-CN.md +7 -7
- package/lib/async-offload.js +39 -2
- package/lib/cli/command-handlers-core.js +132 -0
- package/lib/cli/command-handlers-design.js +129 -0
- package/lib/cli/command-handlers-pen.js +231 -0
- package/lib/cli/command-handlers-workflow.js +221 -0
- package/lib/cli/command-handlers.js +49 -0
- package/lib/cli/helpers.js +62 -0
- package/lib/cli.js +98 -533
- package/lib/execution-signals.js +33 -0
- package/lib/fs-safety.js +1 -12
- package/lib/path-inside.js +17 -0
- package/lib/utils.js +2 -7
- package/lib/workflow-base-view.js +134 -0
- package/lib/workflow-decision-trace.js +335 -0
- package/lib/workflow-overlay.js +1033 -0
- package/lib/workflow-persisted-state.js +4 -0
- package/lib/workflow-stage.js +244 -0
- package/lib/workflow-state.js +414 -1708
- package/lib/workflow-task-groups.js +881 -0
- package/lib/worktree-preflight.js +31 -11
- package/package.json +1 -1
package/lib/cli.js
CHANGED
|
@@ -79,7 +79,12 @@ const {
|
|
|
79
79
|
} = require("./verify");
|
|
80
80
|
const { diffSpec, formatDiffSpecReport } = require("./diff-spec");
|
|
81
81
|
const { scaffoldFromBindings, formatScaffoldReport } = require("./scaffold");
|
|
82
|
-
const {
|
|
82
|
+
const {
|
|
83
|
+
emitOrThrowOnStatus,
|
|
84
|
+
emitCommandOutput,
|
|
85
|
+
persistExecutionSignal
|
|
86
|
+
} = require("./cli/helpers");
|
|
87
|
+
const { buildCommandHandlers } = require("./cli/command-handlers");
|
|
83
88
|
const { handleVerifyFamilyCommand } = require("./cli/verify-family");
|
|
84
89
|
const { handleLintFamilyCommand } = require("./cli/lint-family");
|
|
85
90
|
const {
|
|
@@ -280,6 +285,18 @@ const HELP_OPTION_SPECS = [
|
|
|
280
285
|
{ flag: "--force", description: "overwrite bootstrap placeholders or force commands that explicitly support it" }
|
|
281
286
|
];
|
|
282
287
|
|
|
288
|
+
const HELP_COMMANDS = new Set(["help", "--help", "-h"]);
|
|
289
|
+
const HELP_OPTION_FLAG_WIDTH = 30;
|
|
290
|
+
|
|
291
|
+
function formatHelpOptionLine(optionSpec) {
|
|
292
|
+
const flag = String(optionSpec.flag || "").trim();
|
|
293
|
+
const description = String(optionSpec.description || "").trim();
|
|
294
|
+
if (flag.length >= HELP_OPTION_FLAG_WIDTH) {
|
|
295
|
+
return [` ${flag}`, `${" ".repeat(HELP_OPTION_FLAG_WIDTH + 2)}${description}`].join("\n");
|
|
296
|
+
}
|
|
297
|
+
return ` ${flag.padEnd(HELP_OPTION_FLAG_WIDTH, " ")}${description}`;
|
|
298
|
+
}
|
|
299
|
+
|
|
283
300
|
function readLimitedStdin(maxBytes = DEFAULT_MAX_PREFLIGHT_STDIN_BYTES, options = {}) {
|
|
284
301
|
const limit =
|
|
285
302
|
Number.isFinite(Number(maxBytes)) && Number(maxBytes) > 0
|
|
@@ -546,10 +563,7 @@ function appendStatusIssues(lines, label, missing = [], mismatched = [], unreada
|
|
|
546
563
|
}
|
|
547
564
|
|
|
548
565
|
function printHelp() {
|
|
549
|
-
const optionLines = HELP_OPTION_SPECS.map(
|
|
550
|
-
const paddedFlag = optionSpec.flag.padEnd(30, " ");
|
|
551
|
-
return ` ${paddedFlag}${optionSpec.description}`;
|
|
552
|
-
});
|
|
566
|
+
const optionLines = HELP_OPTION_SPECS.map(formatHelpOptionLine);
|
|
553
567
|
|
|
554
568
|
console.log(
|
|
555
569
|
[
|
|
@@ -1000,140 +1014,92 @@ async function runCli(argv) {
|
|
|
1000
1014
|
const positionalArgs = getPositionalArgs(argv.slice(1), OPTION_FLAGS_WITH_VALUES);
|
|
1001
1015
|
const continueOnError = shouldContinueOnError(argv);
|
|
1002
1016
|
|
|
1003
|
-
if (!command || command
|
|
1017
|
+
if (!command || HELP_COMMANDS.has(command)) {
|
|
1004
1018
|
printHelp();
|
|
1005
1019
|
return;
|
|
1006
1020
|
}
|
|
1007
1021
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
if (command === "install") {
|
|
1014
|
-
const platformValue = getOption(argv, "--platform") || "all";
|
|
1015
|
-
const result = installPlatforms(platformValue, { homeDir });
|
|
1016
|
-
console.log(
|
|
1017
|
-
`Installed Da Vinci v${result.version} for ${result.platforms.join(", ")} at ${result.homeDir}`
|
|
1018
|
-
);
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
if (command === "uninstall") {
|
|
1023
|
-
const platformValue = getOption(argv, "--platform") || "all";
|
|
1024
|
-
const result = uninstallPlatforms(platformValue, { homeDir });
|
|
1025
|
-
console.log(
|
|
1026
|
-
`Uninstalled Da Vinci v${result.version} for ${result.platforms.join(", ")} from ${result.homeDir}`
|
|
1027
|
-
);
|
|
1028
|
-
return;
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
if (command === "status") {
|
|
1032
|
-
console.log(formatStatus(getStatus({ homeDir })));
|
|
1033
|
-
return;
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
if (command === "verify-install") {
|
|
1037
|
-
const platformValue = getOption(argv, "--platform") || "";
|
|
1038
|
-
const result = verifyInstall({
|
|
1039
|
-
homeDir,
|
|
1040
|
-
platforms: platformValue
|
|
1041
|
-
});
|
|
1042
|
-
const output = argv.includes("--json")
|
|
1043
|
-
? JSON.stringify(result, null, 2)
|
|
1044
|
-
: formatVerifyInstallReport(result);
|
|
1045
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1046
|
-
return;
|
|
1047
|
-
}
|
|
1048
|
-
console.log(output);
|
|
1049
|
-
return;
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
if (command === "maintainer-readiness") {
|
|
1053
|
-
const platformValue = getOption(argv, "--platform") || "";
|
|
1054
|
-
const repoRoot = getOption(argv, "--project") || process.cwd();
|
|
1055
|
-
const result = runMaintainerReadinessCheck({
|
|
1056
|
-
repoRoot,
|
|
1022
|
+
const handlers = buildCommandHandlers({
|
|
1023
|
+
shared: {
|
|
1024
|
+
argv,
|
|
1057
1025
|
homeDir,
|
|
1058
|
-
|
|
1059
|
-
});
|
|
1060
|
-
const output = argv.includes("--json")
|
|
1061
|
-
? JSON.stringify(result, null, 2)
|
|
1062
|
-
: formatMaintainerReadinessReport(result);
|
|
1063
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
console.log(output);
|
|
1067
|
-
return;
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
if (command === "tui") {
|
|
1071
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1072
|
-
const changeId = getOption(argv, "--change");
|
|
1073
|
-
const lang = getOption(argv, "--lang");
|
|
1074
|
-
const tuiWidth = getOption(argv, "--tui-width");
|
|
1075
|
-
const altScreen = argv.includes("--alt-screen")
|
|
1076
|
-
? true
|
|
1077
|
-
: argv.includes("--no-alt-screen")
|
|
1078
|
-
? false
|
|
1079
|
-
: undefined;
|
|
1080
|
-
if (argv.includes("--help") || argv.includes("-h")) {
|
|
1081
|
-
console.log(formatTuiHelp(lang));
|
|
1082
|
-
return;
|
|
1083
|
-
}
|
|
1084
|
-
await launchTui({
|
|
1085
|
-
projectPath,
|
|
1086
|
-
changeId,
|
|
1087
|
-
lang,
|
|
1088
|
-
tuiWidth,
|
|
1089
|
-
altScreen,
|
|
1090
|
-
strict: argv.includes("--strict"),
|
|
1091
|
-
jsonOutput: argv.includes("--json"),
|
|
1026
|
+
positionalArgs,
|
|
1092
1027
|
continueOnError
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1028
|
+
},
|
|
1029
|
+
optionHelpers: {
|
|
1030
|
+
getOption,
|
|
1031
|
+
getIntegerOption,
|
|
1032
|
+
getCommaSeparatedOptionValues
|
|
1033
|
+
},
|
|
1034
|
+
core: {
|
|
1035
|
+
VERSION,
|
|
1036
|
+
installPlatforms,
|
|
1037
|
+
uninstallPlatforms,
|
|
1038
|
+
getStatus,
|
|
1039
|
+
verifyInstall,
|
|
1040
|
+
validateAssets,
|
|
1041
|
+
runMaintainerReadinessCheck,
|
|
1042
|
+
formatMaintainerReadinessReport,
|
|
1043
|
+
formatStatus,
|
|
1044
|
+
formatVerifyInstallReport,
|
|
1045
|
+
emitCommandOutput,
|
|
1046
|
+
formatTuiHelp,
|
|
1047
|
+
launchTui
|
|
1048
|
+
},
|
|
1049
|
+
workflow: {
|
|
1050
|
+
deriveWorkflowStatus,
|
|
1051
|
+
formatWorkflowStatusReport,
|
|
1052
|
+
formatNextStepReport,
|
|
1053
|
+
generatePlanningSidecars,
|
|
1054
|
+
formatGenerateSidecarsReport,
|
|
1055
|
+
writeTaskExecutionEnvelope,
|
|
1056
|
+
formatTaskExecutionReport,
|
|
1057
|
+
writeTaskReviewEnvelope,
|
|
1058
|
+
formatTaskReviewReport,
|
|
1059
|
+
runWorktreePreflight,
|
|
1060
|
+
formatWorktreePreflightReport,
|
|
1061
|
+
diffSpec,
|
|
1062
|
+
formatDiffSpecReport,
|
|
1063
|
+
scaffoldFromBindings,
|
|
1064
|
+
formatScaffoldReport,
|
|
1065
|
+
auditProject,
|
|
1066
|
+
formatAuditReport,
|
|
1067
|
+
bootstrapProjectArtifacts,
|
|
1068
|
+
formatBootstrapProjectReport,
|
|
1069
|
+
persistExecutionSignal,
|
|
1070
|
+
emitCommandOutput,
|
|
1071
|
+
emitOrThrowOnStatus
|
|
1072
|
+
},
|
|
1073
|
+
design: {
|
|
1074
|
+
syncIconCatalog,
|
|
1075
|
+
formatIconSyncReport,
|
|
1076
|
+
handleIconSearchCommand,
|
|
1077
|
+
readOperations,
|
|
1078
|
+
readLimitedStdin,
|
|
1079
|
+
preflightPencilBatch,
|
|
1080
|
+
formatPencilPreflightReport,
|
|
1081
|
+
emitOrThrowOnStatus,
|
|
1082
|
+
handleSupervisorReviewCommand,
|
|
1083
|
+
saveCurrentDesign,
|
|
1084
|
+
formatSaveCurrentDesignReport,
|
|
1085
|
+
SAVE_STATUS
|
|
1086
|
+
},
|
|
1087
|
+
pen: {
|
|
1088
|
+
ensurePenFile,
|
|
1089
|
+
writePenFromPayloadFiles,
|
|
1090
|
+
comparePenSync,
|
|
1091
|
+
comparePenBaselineAlignment,
|
|
1092
|
+
formatPenBaselineAlignmentReport,
|
|
1093
|
+
syncPenSource,
|
|
1094
|
+
snapshotPenFile,
|
|
1095
|
+
handlePencilLockCommand,
|
|
1096
|
+
handlePencilSessionCommand,
|
|
1097
|
+
emitOrThrowOnStatus
|
|
1134
1098
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1099
|
+
});
|
|
1100
|
+
const commandHandler = handlers.get(command);
|
|
1101
|
+
if (commandHandler) {
|
|
1102
|
+
await commandHandler();
|
|
1137
1103
|
return;
|
|
1138
1104
|
}
|
|
1139
1105
|
|
|
@@ -1158,22 +1124,6 @@ async function runCli(argv) {
|
|
|
1158
1124
|
return;
|
|
1159
1125
|
}
|
|
1160
1126
|
|
|
1161
|
-
if (command === "generate-sidecars") {
|
|
1162
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1163
|
-
const changeId = getOption(argv, "--change");
|
|
1164
|
-
const result = generatePlanningSidecars(projectPath, { changeId, write: true });
|
|
1165
|
-
persistExecutionSignal(projectPath, result.changeId || changeId, "generate-sidecars", result, false);
|
|
1166
|
-
const useJson = argv.includes("--json");
|
|
1167
|
-
const output = useJson ? JSON.stringify(result, null, 2) : formatGenerateSidecarsReport(result);
|
|
1168
|
-
|
|
1169
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1170
|
-
return;
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
console.log(output);
|
|
1174
|
-
return;
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
1127
|
if (
|
|
1178
1128
|
handleVerifyFamilyCommand(command, {
|
|
1179
1129
|
argv,
|
|
@@ -1194,391 +1144,6 @@ async function runCli(argv) {
|
|
|
1194
1144
|
return;
|
|
1195
1145
|
}
|
|
1196
1146
|
|
|
1197
|
-
if (command === "task-execution") {
|
|
1198
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1199
|
-
const changeId = getOption(argv, "--change");
|
|
1200
|
-
const result = writeTaskExecutionEnvelope(projectPath, {
|
|
1201
|
-
changeId,
|
|
1202
|
-
taskGroupId: getOption(argv, "--task-group"),
|
|
1203
|
-
status: getOption(argv, "--status"),
|
|
1204
|
-
summary: getOption(argv, "--summary"),
|
|
1205
|
-
changedFiles: getCommaSeparatedOptionValues(argv, "--changed-files"),
|
|
1206
|
-
testEvidence: getCommaSeparatedOptionValues(argv, "--test-evidence"),
|
|
1207
|
-
pendingTestEvidence: getCommaSeparatedOptionValues(argv, "--pending-test-evidence"),
|
|
1208
|
-
confirmTestEvidenceExecuted: argv.includes("--confirm-test-evidence-executed"),
|
|
1209
|
-
concerns: getCommaSeparatedOptionValues(argv, "--concerns"),
|
|
1210
|
-
blockers: getCommaSeparatedOptionValues(argv, "--blockers"),
|
|
1211
|
-
outOfScopeWrites: getCommaSeparatedOptionValues(argv, "--out-of-scope-writes"),
|
|
1212
|
-
partial: argv.includes("--partial")
|
|
1213
|
-
});
|
|
1214
|
-
const useJson = argv.includes("--json");
|
|
1215
|
-
const output = useJson ? JSON.stringify(result, null, 2) : formatTaskExecutionReport(result);
|
|
1216
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1217
|
-
return;
|
|
1218
|
-
}
|
|
1219
|
-
console.log(output);
|
|
1220
|
-
return;
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
if (command === "task-review") {
|
|
1224
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1225
|
-
const changeId = getOption(argv, "--change");
|
|
1226
|
-
const result = writeTaskReviewEnvelope(projectPath, {
|
|
1227
|
-
changeId,
|
|
1228
|
-
taskGroupId: getOption(argv, "--task-group"),
|
|
1229
|
-
stage: getOption(argv, "--stage"),
|
|
1230
|
-
status: getOption(argv, "--status"),
|
|
1231
|
-
summary: getOption(argv, "--summary"),
|
|
1232
|
-
issues: getCommaSeparatedOptionValues(argv, "--issues"),
|
|
1233
|
-
reviewer: getOption(argv, "--reviewer"),
|
|
1234
|
-
writeVerification: argv.includes("--write-verification")
|
|
1235
|
-
});
|
|
1236
|
-
const useJson = argv.includes("--json");
|
|
1237
|
-
const output = useJson ? JSON.stringify(result, null, 2) : formatTaskReviewReport(result);
|
|
1238
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1239
|
-
return;
|
|
1240
|
-
}
|
|
1241
|
-
console.log(output);
|
|
1242
|
-
return;
|
|
1243
|
-
}
|
|
1244
|
-
|
|
1245
|
-
if (command === "worktree-preflight") {
|
|
1246
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1247
|
-
const changeId = getOption(argv, "--change");
|
|
1248
|
-
const result = runWorktreePreflight(projectPath);
|
|
1249
|
-
persistExecutionSignal(projectPath, changeId || "global", "worktree-preflight", result, false);
|
|
1250
|
-
if (argv.includes("--json")) {
|
|
1251
|
-
console.log(JSON.stringify(result, null, 2));
|
|
1252
|
-
return;
|
|
1253
|
-
}
|
|
1254
|
-
console.log(formatWorktreePreflightReport(result));
|
|
1255
|
-
return;
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
if (command === "diff-spec") {
|
|
1259
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1260
|
-
const changeId = getOption(argv, "--change");
|
|
1261
|
-
const fromDir = getOption(argv, "--from");
|
|
1262
|
-
const result = diffSpec(projectPath, { changeId, fromDir });
|
|
1263
|
-
persistExecutionSignal(projectPath, result.changeId || changeId, "diff-spec", result, false);
|
|
1264
|
-
const useJson = argv.includes("--json");
|
|
1265
|
-
const output = useJson ? JSON.stringify(result, null, 2) : formatDiffSpecReport(result);
|
|
1266
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1267
|
-
return;
|
|
1268
|
-
}
|
|
1269
|
-
console.log(output);
|
|
1270
|
-
return;
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
if (command === "scaffold") {
|
|
1274
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1275
|
-
const changeId = getOption(argv, "--change");
|
|
1276
|
-
const outputDir = getOption(argv, "--output");
|
|
1277
|
-
const result = scaffoldFromBindings(projectPath, { changeId, outputDir });
|
|
1278
|
-
persistExecutionSignal(projectPath, result.changeId || changeId, "scaffold", result, false);
|
|
1279
|
-
const useJson = argv.includes("--json");
|
|
1280
|
-
const output = useJson ? JSON.stringify(result, null, 2) : formatScaffoldReport(result);
|
|
1281
|
-
if (emitOrThrowOnStatus(result.status, ["BLOCK"], output, continueOnError)) {
|
|
1282
|
-
return;
|
|
1283
|
-
}
|
|
1284
|
-
console.log(output);
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
if (command === "validate-assets") {
|
|
1289
|
-
const result = validateAssets();
|
|
1290
|
-
console.log(`Da Vinci v${result.version} assets are complete (${result.requiredAssets} required files).`);
|
|
1291
|
-
return;
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
if (command === "audit") {
|
|
1295
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1296
|
-
const mode = getOption(argv, "--mode");
|
|
1297
|
-
const changeId = getOption(argv, "--change");
|
|
1298
|
-
const result = auditProject(projectPath, { mode, changeId });
|
|
1299
|
-
const report = formatAuditReport(result);
|
|
1300
|
-
|
|
1301
|
-
if (emitOrThrowOnStatus(result.status, ["FAIL"], report, continueOnError)) {
|
|
1302
|
-
return;
|
|
1303
|
-
}
|
|
1304
|
-
|
|
1305
|
-
console.log(report);
|
|
1306
|
-
return;
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
|
-
if (command === "bootstrap-project") {
|
|
1310
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1311
|
-
const changeId = getOption(argv, "--change");
|
|
1312
|
-
const force = argv.includes("--force");
|
|
1313
|
-
const result = bootstrapProjectArtifacts(projectPath, { changeId, force });
|
|
1314
|
-
console.log(formatBootstrapProjectReport(result));
|
|
1315
|
-
return;
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
if (command === "icon-sync") {
|
|
1319
|
-
const outputPath = getOption(argv, "--output") || getOption(argv, "--catalog");
|
|
1320
|
-
const timeoutMs = getIntegerOption(argv, "--timeout-ms", { min: 1 });
|
|
1321
|
-
const strict = argv.includes("--strict");
|
|
1322
|
-
|
|
1323
|
-
const result = await syncIconCatalog({
|
|
1324
|
-
outputPath,
|
|
1325
|
-
timeoutMs,
|
|
1326
|
-
strict,
|
|
1327
|
-
homeDir
|
|
1328
|
-
});
|
|
1329
|
-
|
|
1330
|
-
console.log(formatIconSyncReport(result));
|
|
1331
|
-
return;
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
if (command === "icon-search") {
|
|
1335
|
-
await handleIconSearchCommand(argv, homeDir);
|
|
1336
|
-
return;
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
if (command === "preflight-pencil") {
|
|
1340
|
-
const opsFile = getOption(argv, "--ops-file");
|
|
1341
|
-
let operations = "";
|
|
1342
|
-
|
|
1343
|
-
if (opsFile) {
|
|
1344
|
-
operations = readOperations(opsFile);
|
|
1345
|
-
} else if (!process.stdin.isTTY) {
|
|
1346
|
-
operations = readLimitedStdin();
|
|
1347
|
-
} else {
|
|
1348
|
-
throw new Error("`preflight-pencil` requires `--ops-file <path>` or piped stdin input.");
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
const result = preflightPencilBatch(operations);
|
|
1352
|
-
const report = formatPencilPreflightReport(result);
|
|
1353
|
-
|
|
1354
|
-
if (emitOrThrowOnStatus(result.status, ["FAIL"], report, continueOnError)) {
|
|
1355
|
-
return;
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
console.log(report);
|
|
1359
|
-
return;
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
if (command === "supervisor-review") {
|
|
1363
|
-
await handleSupervisorReviewCommand(argv);
|
|
1364
|
-
return;
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
|
-
if (command === "ensure-pen") {
|
|
1368
|
-
const outputPath = getOption(argv, "--output");
|
|
1369
|
-
const version = getOption(argv, "--version");
|
|
1370
|
-
const verifyWithPencil = argv.includes("--verify-open");
|
|
1371
|
-
|
|
1372
|
-
if (!outputPath) {
|
|
1373
|
-
throw new Error("`ensure-pen` requires `--output <path>`.");
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
|
-
const result = ensurePenFile({
|
|
1377
|
-
outputPath,
|
|
1378
|
-
version,
|
|
1379
|
-
verifyWithPencil
|
|
1380
|
-
});
|
|
1381
|
-
|
|
1382
|
-
console.log(`${result.created ? "Created" : "Verified existing"} .pen source at ${result.outputPath}`);
|
|
1383
|
-
console.log(`State file: ${result.statePath}`);
|
|
1384
|
-
console.log(`Snapshot hash: ${result.state.snapshotHash}`);
|
|
1385
|
-
if (result.verification) {
|
|
1386
|
-
console.log(`Verified reopen with Pencil (${result.verification.topLevelCount} top-level nodes).`);
|
|
1387
|
-
}
|
|
1388
|
-
return;
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
if (command === "write-pen") {
|
|
1392
|
-
const outputPath = getOption(argv, "--output");
|
|
1393
|
-
const nodesFile = getOption(argv, "--nodes-file");
|
|
1394
|
-
const variablesFile = getOption(argv, "--variables-file");
|
|
1395
|
-
const version = getOption(argv, "--version");
|
|
1396
|
-
const verifyWithPencil = argv.includes("--verify-open");
|
|
1397
|
-
|
|
1398
|
-
if (!outputPath || !nodesFile) {
|
|
1399
|
-
throw new Error("`write-pen` requires `--output <path>` and `--nodes-file <path>`.");
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
const result = writePenFromPayloadFiles({
|
|
1403
|
-
outputPath,
|
|
1404
|
-
nodesFile,
|
|
1405
|
-
variablesFile,
|
|
1406
|
-
version,
|
|
1407
|
-
verifyWithPencil
|
|
1408
|
-
});
|
|
1409
|
-
|
|
1410
|
-
console.log(`Wrote .pen file to ${result.outputPath}`);
|
|
1411
|
-
console.log(`State file: ${result.statePath}`);
|
|
1412
|
-
console.log(`Snapshot hash: ${result.state.snapshotHash}`);
|
|
1413
|
-
console.log(`Top-level nodes: ${result.document.children.length}`);
|
|
1414
|
-
if (result.verification) {
|
|
1415
|
-
console.log(`Verified reopen with Pencil (${result.verification.topLevelCount} top-level nodes).`);
|
|
1416
|
-
}
|
|
1417
|
-
return;
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
if (command === "check-pen-sync") {
|
|
1421
|
-
const penPath = getOption(argv, "--pen");
|
|
1422
|
-
const nodesFile = getOption(argv, "--nodes-file");
|
|
1423
|
-
const variablesFile = getOption(argv, "--variables-file");
|
|
1424
|
-
const version = getOption(argv, "--version");
|
|
1425
|
-
|
|
1426
|
-
if (!penPath || !nodesFile) {
|
|
1427
|
-
throw new Error("`check-pen-sync` requires `--pen <path>` and `--nodes-file <path>`.");
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
const result = comparePenSync({
|
|
1431
|
-
penPath,
|
|
1432
|
-
nodesFile,
|
|
1433
|
-
variablesFile,
|
|
1434
|
-
version
|
|
1435
|
-
});
|
|
1436
|
-
|
|
1437
|
-
if (!result.inSync) {
|
|
1438
|
-
throw new Error(
|
|
1439
|
-
[
|
|
1440
|
-
"Registered `.pen` is out of sync with the provided live payload.",
|
|
1441
|
-
`Pen: ${result.penPath}`,
|
|
1442
|
-
`State file: ${result.statePath}`,
|
|
1443
|
-
`Persisted hash: ${result.persistedHash}`,
|
|
1444
|
-
`Live hash: ${result.liveHash}`
|
|
1445
|
-
].join("\n")
|
|
1446
|
-
);
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
console.log(`Registered .pen is in sync: ${result.penPath}`);
|
|
1450
|
-
console.log(`State file: ${result.statePath}`);
|
|
1451
|
-
console.log(`Snapshot hash: ${result.liveHash}`);
|
|
1452
|
-
if (!result.usedStateFile) {
|
|
1453
|
-
console.log(
|
|
1454
|
-
result.stateHash
|
|
1455
|
-
? "State file hash was stale; sync comparison fell back to hashing the disk .pen file directly."
|
|
1456
|
-
: "State file was missing; sync comparison fell back to hashing the disk .pen file directly."
|
|
1457
|
-
);
|
|
1458
|
-
}
|
|
1459
|
-
return;
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
if (command === "check-pen-baseline") {
|
|
1463
|
-
const penPath = getOption(argv, "--pen");
|
|
1464
|
-
const baselinePaths = getCommaSeparatedOptionValues(argv, "--baseline");
|
|
1465
|
-
const preferredSource = getOption(argv, "--prefer-source");
|
|
1466
|
-
|
|
1467
|
-
if (!penPath || baselinePaths.length === 0) {
|
|
1468
|
-
throw new Error(
|
|
1469
|
-
"`check-pen-baseline` requires `--pen <path>` and at least one `--baseline <path>`."
|
|
1470
|
-
);
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1473
|
-
const result = comparePenBaselineAlignment({
|
|
1474
|
-
penPath,
|
|
1475
|
-
baselinePaths,
|
|
1476
|
-
preferredSource
|
|
1477
|
-
});
|
|
1478
|
-
|
|
1479
|
-
if (
|
|
1480
|
-
emitOrThrowOnStatus(
|
|
1481
|
-
result.status,
|
|
1482
|
-
["BLOCK"],
|
|
1483
|
-
[
|
|
1484
|
-
"Baseline alignment check failed.",
|
|
1485
|
-
formatPenBaselineAlignmentReport(result)
|
|
1486
|
-
].join("\n"),
|
|
1487
|
-
continueOnError
|
|
1488
|
-
)
|
|
1489
|
-
) {
|
|
1490
|
-
return;
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1493
|
-
console.log(formatPenBaselineAlignmentReport(result));
|
|
1494
|
-
return;
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
if (command === "sync-pen-source") {
|
|
1498
|
-
const sourcePath = getOption(argv, "--from");
|
|
1499
|
-
const targetPath = getOption(argv, "--to");
|
|
1500
|
-
|
|
1501
|
-
if (!sourcePath || !targetPath) {
|
|
1502
|
-
throw new Error("`sync-pen-source` requires `--from <path>` and `--to <path>`.");
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
const result = syncPenSource({
|
|
1506
|
-
sourcePath,
|
|
1507
|
-
targetPath
|
|
1508
|
-
});
|
|
1509
|
-
|
|
1510
|
-
console.log(`Synced .pen source from ${result.sourcePath} to ${result.targetPath}`);
|
|
1511
|
-
console.log(`State file: ${result.statePath}`);
|
|
1512
|
-
console.log(`Snapshot hash: ${result.state.snapshotHash}`);
|
|
1513
|
-
return;
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1516
|
-
if (command === "snapshot-pen") {
|
|
1517
|
-
const inputPath = getOption(argv, "--input");
|
|
1518
|
-
const outputPath = getOption(argv, "--output");
|
|
1519
|
-
const version = getOption(argv, "--version");
|
|
1520
|
-
const verifyWithPencil = argv.includes("--verify-open");
|
|
1521
|
-
|
|
1522
|
-
if (!inputPath || !outputPath) {
|
|
1523
|
-
throw new Error("`snapshot-pen` requires `--input <path>` and `--output <path>`.");
|
|
1524
|
-
}
|
|
1525
|
-
|
|
1526
|
-
const result = snapshotPenFile({
|
|
1527
|
-
inputPath,
|
|
1528
|
-
outputPath,
|
|
1529
|
-
version,
|
|
1530
|
-
verifyWithPencil
|
|
1531
|
-
});
|
|
1532
|
-
|
|
1533
|
-
console.log(`Snapshotted ${result.inputPath} to ${result.outputPath}`);
|
|
1534
|
-
console.log(`State file: ${result.statePath}`);
|
|
1535
|
-
console.log(`Snapshot hash: ${result.state.snapshotHash}`);
|
|
1536
|
-
console.log(`Top-level nodes: ${result.document.children.length}`);
|
|
1537
|
-
if (result.verification) {
|
|
1538
|
-
console.log(`Verified reopen with Pencil (${result.verification.topLevelCount} top-level nodes).`);
|
|
1539
|
-
}
|
|
1540
|
-
return;
|
|
1541
|
-
}
|
|
1542
|
-
|
|
1543
|
-
if (command === "save-current-design") {
|
|
1544
|
-
const projectPath = getOption(argv, "--project") || positionalArgs[0] || process.cwd();
|
|
1545
|
-
const pencilBin = getOption(argv, "--pencil-bin");
|
|
1546
|
-
const result = await saveCurrentDesign({
|
|
1547
|
-
projectPath,
|
|
1548
|
-
homeDir,
|
|
1549
|
-
pencilBin,
|
|
1550
|
-
allowLocalBridge: true
|
|
1551
|
-
});
|
|
1552
|
-
const useJson = argv.includes("--json");
|
|
1553
|
-
const output = useJson
|
|
1554
|
-
? JSON.stringify(result, null, 2)
|
|
1555
|
-
: formatSaveCurrentDesignReport(result);
|
|
1556
|
-
|
|
1557
|
-
if (
|
|
1558
|
-
emitOrThrowOnStatus(
|
|
1559
|
-
result.status,
|
|
1560
|
-
[SAVE_STATUS.BLOCKED, SAVE_STATUS.UNAVAILABLE],
|
|
1561
|
-
output,
|
|
1562
|
-
continueOnError
|
|
1563
|
-
)
|
|
1564
|
-
) {
|
|
1565
|
-
return;
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
console.log(output);
|
|
1569
|
-
return;
|
|
1570
|
-
}
|
|
1571
|
-
|
|
1572
|
-
if (command === "pencil-lock") {
|
|
1573
|
-
handlePencilLockCommand(argv, homeDir);
|
|
1574
|
-
return;
|
|
1575
|
-
}
|
|
1576
|
-
|
|
1577
|
-
if (command === "pencil-session") {
|
|
1578
|
-
handlePencilSessionCommand(argv, homeDir);
|
|
1579
|
-
return;
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
1147
|
throw new Error(`Unknown command: ${command}`);
|
|
1583
1148
|
}
|
|
1584
1149
|
|