@penpair/core 0.3.7 → 0.4.1
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/dist/adapters.d.ts +1 -1
- package/dist/adapters.js +4 -0
- package/dist/approvals.d.ts +4 -1
- package/dist/approvals.js +7 -4
- package/dist/baseline-coverage.js +3 -3
- package/dist/baselines-config.d.ts +3 -0
- package/dist/baselines-config.js +3 -0
- package/dist/baselines.d.ts +7 -0
- package/dist/baselines.js +90 -21
- package/dist/bounded-file.d.ts +2 -0
- package/dist/bounded-file.js +38 -0
- package/dist/browser-wake.d.ts +22 -0
- package/dist/browser-wake.js +241 -0
- package/dist/cli-main.js +193 -18
- package/dist/design-commands/context.d.ts +9 -0
- package/dist/design-commands/context.js +1 -0
- package/dist/design-commands/index.d.ts +3 -0
- package/dist/design-commands/index.js +7 -0
- package/dist/design-commands/map-command.d.ts +4 -0
- package/dist/design-commands/map-command.js +685 -0
- package/dist/design-commands/release-command.d.ts +3 -0
- package/dist/design-commands/release-command.js +239 -0
- package/dist/design-releases/artifact-paths.d.ts +6 -0
- package/dist/design-releases/artifact-paths.js +82 -0
- package/dist/design-releases/assemble.d.ts +3 -0
- package/dist/design-releases/assemble.js +176 -0
- package/dist/design-releases/check.d.ts +16 -0
- package/dist/design-releases/check.js +323 -0
- package/dist/design-releases/context.d.ts +2 -0
- package/dist/design-releases/context.js +119 -0
- package/dist/design-releases/contract-graph.d.ts +13 -0
- package/dist/design-releases/contract-graph.js +75 -0
- package/dist/design-releases/fidelity.d.ts +23 -0
- package/dist/design-releases/fidelity.js +328 -0
- package/dist/design-releases/finalize.d.ts +4 -0
- package/dist/design-releases/finalize.js +201 -0
- package/dist/design-releases/index.d.ts +8 -0
- package/dist/design-releases/index.js +7 -0
- package/dist/design-releases/live.d.ts +22 -0
- package/dist/design-releases/live.js +97 -0
- package/dist/design-releases/snippets.d.ts +5 -0
- package/dist/design-releases/snippets.js +89 -0
- package/dist/design-releases/store.d.ts +10 -0
- package/dist/design-releases/store.js +205 -0
- package/dist/design-releases/types.d.ts +161 -0
- package/dist/design-releases/types.js +1 -0
- package/dist/design-releases/validation.d.ts +6 -0
- package/dist/design-releases/validation.js +384 -0
- package/dist/design-releases/verify.d.ts +3 -0
- package/dist/design-releases/verify.js +148 -0
- package/dist/errors.js +1 -1
- package/dist/image-codec.d.ts +3 -0
- package/dist/image-codec.js +78 -0
- package/dist/image-evidence.d.ts +15 -0
- package/dist/image-evidence.js +121 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/inspection.js +13 -5
- package/dist/instance/config-schema.d.ts +4 -0
- package/dist/instance/config-schema.js +7 -0
- package/dist/instance/connection.d.ts +2 -0
- package/dist/instance/connection.js +15 -3
- package/dist/kit-source.js +1 -1
- package/dist/layout-policy.js +21 -11
- package/dist/layout-settling.d.ts +1 -0
- package/dist/layout-settling.js +51 -17
- package/dist/layout.d.ts +7 -1
- package/dist/layout.js +19 -3
- package/dist/map-penpot/content-validation.d.ts +3 -0
- package/dist/map-penpot/content-validation.js +57 -0
- package/dist/map-penpot/content.d.ts +22 -0
- package/dist/map-penpot/content.js +173 -0
- package/dist/map-penpot/details.d.ts +4 -0
- package/dist/map-penpot/details.js +84 -0
- package/dist/map-penpot/evidence-error.d.ts +5 -0
- package/dist/map-penpot/evidence-error.js +9 -0
- package/dist/map-penpot/icons.d.ts +5 -0
- package/dist/map-penpot/icons.js +79 -0
- package/dist/map-penpot/import-content.d.ts +2 -0
- package/dist/map-penpot/import-content.js +150 -0
- package/dist/map-penpot/import.d.ts +5 -0
- package/dist/map-penpot/import.js +255 -0
- package/dist/map-penpot/index.d.ts +11 -0
- package/dist/map-penpot/index.js +10 -0
- package/dist/map-penpot/path-geometry.d.ts +5 -0
- package/dist/map-penpot/path-geometry.js +51 -0
- package/dist/map-penpot/presentation.d.ts +20 -0
- package/dist/map-penpot/presentation.js +205 -0
- package/dist/map-penpot/projection.d.ts +8 -0
- package/dist/map-penpot/projection.js +176 -0
- package/dist/map-penpot/publish.d.ts +4 -0
- package/dist/map-penpot/publish.js +301 -0
- package/dist/map-penpot/release-maps.d.ts +21 -0
- package/dist/map-penpot/release-maps.js +104 -0
- package/dist/map-penpot/snippets.d.ts +4 -0
- package/dist/map-penpot/snippets.js +164 -0
- package/dist/map-penpot/status-labels.d.ts +7 -0
- package/dist/map-penpot/status-labels.js +7 -0
- package/dist/map-penpot/types.d.ts +161 -0
- package/dist/map-penpot/types.js +1 -0
- package/dist/maps/annotation-layout.d.ts +24 -0
- package/dist/maps/annotation-layout.js +85 -0
- package/dist/maps/context.d.ts +13 -0
- package/dist/maps/context.js +207 -0
- package/dist/maps/index.d.ts +9 -0
- package/dist/maps/index.js +9 -0
- package/dist/maps/layout.d.ts +35 -0
- package/dist/maps/layout.js +364 -0
- package/dist/maps/proposal.d.ts +5 -0
- package/dist/maps/proposal.js +67 -0
- package/dist/maps/render.d.ts +4 -0
- package/dist/maps/render.js +331 -0
- package/dist/maps/review.d.ts +16 -0
- package/dist/maps/review.js +90 -0
- package/dist/maps/store.d.ts +21 -0
- package/dist/maps/store.js +222 -0
- package/dist/maps/types.d.ts +206 -0
- package/dist/maps/types.js +1 -0
- package/dist/maps/validation.d.ts +10 -0
- package/dist/maps/validation.js +375 -0
- package/dist/plugin-health.d.ts +13 -0
- package/dist/plugin-health.js +39 -0
- package/dist/skill-routing.js +4 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
- package/skills/penpair-design-release/SKILL.md +55 -0
- package/skills/penpair-design-release/agents/openai.yaml +6 -0
- package/skills/penpair-design-release/references/workflow.md +55 -0
- package/skills/penpair-diagrams/SKILL.md +52 -0
- package/skills/penpair-diagrams/agents/openai.yaml +6 -0
- package/skills/penpair-diagrams/references/workflow.md +84 -0
- package/skills/penpair-handoff/SKILL.md +7 -0
- package/skills/penpair-handoff/references/handoff-flow.md +7 -1
- package/skills/penpair-integration-map/SKILL.md +44 -0
- package/skills/penpair-integration-map/agents/openai.yaml +6 -0
- package/skills/penpair-integration-map/references/workflow.md +33 -0
- package/skills/penpair-journey-map/SKILL.md +42 -0
- package/skills/penpair-journey-map/agents/openai.yaml +6 -0
- package/skills/penpair-journey-map/references/workflow.md +35 -0
- package/skills/penpair-verify/SKILL.md +7 -0
- package/skills/penpair-verify/references/browser-evidence.md +10 -0
package/dist/cli-main.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { auditDesignRules } from "./audit-rules.js";
|
|
2
2
|
import { projectStatus, projectFileUrl, openProject } from "./project-status.js";
|
|
3
|
+
import { wakeBrowserTarget } from "./browser-wake.js";
|
|
4
|
+
import { pluginHealthFromError } from "./plugin-health.js";
|
|
3
5
|
import { artifactSchemas, migrateProjectConfig } from "./formats.js";
|
|
4
6
|
import { importDtcg, exportDtcg } from "./portable-tokens.js";
|
|
5
7
|
import { captureStructuralSnapshot, writeStructuralSnapshot, readStructuralSnapshot, diffStructuralSnapshots, renderStructuralDiff, } from "./structure-snapshot.js";
|
|
@@ -23,7 +25,8 @@ import { resolveProjectOutput } from "./project-input.js";
|
|
|
23
25
|
import { mkdir } from "node:fs/promises";
|
|
24
26
|
import { captureShots, exportShapeByName, findShapesByName } from "./shots.js";
|
|
25
27
|
import { exportShapePng } from "./export.js";
|
|
26
|
-
import { exportBaselines } from "./baselines.js";
|
|
28
|
+
import { exportBaselines, resolveBaselineImageFormat } from "./baselines.js";
|
|
29
|
+
import { encodeBaselineImage } from "./image-codec.js";
|
|
27
30
|
import { archiveOperation, runOnPage, runOperation } from "./operation.js";
|
|
28
31
|
import { formatDeepReport, runDeepCheck } from "./deep-check.js";
|
|
29
32
|
import { probe } from "./probe.js";
|
|
@@ -43,7 +46,7 @@ import { askHidden, askLine, openInBrowser } from "./instance/tty.js";
|
|
|
43
46
|
import { validateSkillAgent } from "./skill-hosts.js";
|
|
44
47
|
import { loadAdapters, readRawConfig, reservedCommands, } from "./adapters.js";
|
|
45
48
|
import { requireLocalProfile } from "./local-profile.js";
|
|
46
|
-
import { assertEndpointIsInstance, doctorExternal, LifecycleError, } from "./instance/connection.js";
|
|
49
|
+
import { assertEndpointIsInstance, doctorExternal, doctorEditor, frontendUrl, LifecycleError, } from "./instance/connection.js";
|
|
47
50
|
import { nodeRunner } from "./instance/runner.js";
|
|
48
51
|
import { version } from "./version.js";
|
|
49
52
|
import { guardFile } from "./file-guard.js";
|
|
@@ -54,6 +57,11 @@ import { backupNoteCheck } from "./backup-note.js";
|
|
|
54
57
|
import { createCheckpoint } from "./native-api.js";
|
|
55
58
|
import { listJournals, readJournal } from "./journal.js";
|
|
56
59
|
const usageHead = `penpair ${version}
|
|
60
|
+
Design agreements and release pages:
|
|
61
|
+
penpair journey-map check|render|publish|import|accept|approve|context --from FILE
|
|
62
|
+
penpair integration-map check|render|publish|import|accept|approve|context --from FILE
|
|
63
|
+
penpair design-release plan|assemble|verify|finalize|check|context --from FILE
|
|
64
|
+
(publication previews by default; --apply writes Penpot, --write records local acceptance/review)
|
|
57
65
|
Start here (guided, plain language; safe to run again):
|
|
58
66
|
penpair setup asks where your Penpot is (web is the default), sets everything up and checks it
|
|
59
67
|
penpair setup --web [--external <address>] Penpot on the web: design.penpot.app, or your team's address; no questions about it
|
|
@@ -65,6 +73,7 @@ Connect / diagnose:
|
|
|
65
73
|
penpair config check [--json] validate configuration offline
|
|
66
74
|
penpair config schema print its JSON Schema
|
|
67
75
|
penpair doctor [--json] [--timeout-ms 5000] origin, transport, fresh editor read and file pin (1000–30000 ms)
|
|
76
|
+
penpair wake --debug-port 9222 [--json] activate the pinned browser tab, then verify the editor; no reload or replay
|
|
68
77
|
penpair status [--adapters] observed project health and optional companion readiness
|
|
69
78
|
penpair open [--print] open the pinned public file URL, or print it
|
|
70
79
|
penpair probe [--integrity] observed APIs and limits
|
|
@@ -78,7 +87,7 @@ Build:
|
|
|
78
87
|
penpair snippets / snippets check list or validate configured trusted scripts
|
|
79
88
|
penpair tokens add-set|set|remove|promote inspect token edits; --apply writes once
|
|
80
89
|
penpair archive --page PAGE --name Archive --keep PREFIX [--apply]
|
|
81
|
-
(run-file/export/shots accept --layout auto|native|geometry
|
|
90
|
+
(run-file/run/archive/token edits/export/shots accept --layout auto|native|geometry, repeatable --layout-root ID, --layout-max-nodes 1..100000)
|
|
82
91
|
(journaled writes accept --resume RUN_ID --apply, --checkpoint and --trace)
|
|
83
92
|
Inspect / spec:
|
|
84
93
|
penpair pages file identity, revision and pages
|
|
@@ -202,6 +211,12 @@ async function main(argv, cli) {
|
|
|
202
211
|
case: {
|
|
203
212
|
type: "string",
|
|
204
213
|
},
|
|
214
|
+
format: {
|
|
215
|
+
type: "string",
|
|
216
|
+
},
|
|
217
|
+
"migrate-format": {
|
|
218
|
+
type: "boolean",
|
|
219
|
+
},
|
|
205
220
|
"force-reason": {
|
|
206
221
|
type: "string",
|
|
207
222
|
},
|
|
@@ -223,9 +238,19 @@ async function main(argv, cli) {
|
|
|
223
238
|
"timeout-ms": {
|
|
224
239
|
type: "string",
|
|
225
240
|
},
|
|
241
|
+
"debug-port": {
|
|
242
|
+
type: "string",
|
|
243
|
+
},
|
|
226
244
|
layout: {
|
|
227
245
|
type: "string",
|
|
228
246
|
},
|
|
247
|
+
"layout-root": {
|
|
248
|
+
type: "string",
|
|
249
|
+
multiple: true,
|
|
250
|
+
},
|
|
251
|
+
"layout-max-nodes": {
|
|
252
|
+
type: "string",
|
|
253
|
+
},
|
|
229
254
|
page: {
|
|
230
255
|
type: "string",
|
|
231
256
|
},
|
|
@@ -420,6 +445,11 @@ async function main(argv, cli) {
|
|
|
420
445
|
"max-total-bytes",
|
|
421
446
|
"capture-timeout-ms",
|
|
422
447
|
];
|
|
448
|
+
const layoutFlags = [
|
|
449
|
+
"layout",
|
|
450
|
+
"layout-root",
|
|
451
|
+
"layout-max-nodes",
|
|
452
|
+
];
|
|
423
453
|
const flags = {
|
|
424
454
|
formats: [
|
|
425
455
|
"out",
|
|
@@ -436,6 +466,7 @@ async function main(argv, cli) {
|
|
|
436
466
|
"by",
|
|
437
467
|
"case",
|
|
438
468
|
"write",
|
|
469
|
+
"format",
|
|
439
470
|
],
|
|
440
471
|
spec: [
|
|
441
472
|
"from",
|
|
@@ -473,6 +504,7 @@ async function main(argv, cli) {
|
|
|
473
504
|
"theme",
|
|
474
505
|
]
|
|
475
506
|
: [
|
|
507
|
+
...layoutFlags,
|
|
476
508
|
"type",
|
|
477
509
|
"value",
|
|
478
510
|
"description",
|
|
@@ -486,16 +518,17 @@ async function main(argv, cli) {
|
|
|
486
518
|
"page",
|
|
487
519
|
"scale",
|
|
488
520
|
"name",
|
|
489
|
-
|
|
521
|
+
...layoutFlags,
|
|
490
522
|
],
|
|
491
523
|
shots: [
|
|
492
524
|
"page",
|
|
493
525
|
"prefix",
|
|
494
526
|
"out",
|
|
495
527
|
"scale",
|
|
496
|
-
|
|
528
|
+
...layoutFlags,
|
|
497
529
|
],
|
|
498
530
|
archive: [
|
|
531
|
+
...layoutFlags,
|
|
499
532
|
"page",
|
|
500
533
|
"name",
|
|
501
534
|
"keep",
|
|
@@ -514,7 +547,7 @@ async function main(argv, cli) {
|
|
|
514
547
|
"include",
|
|
515
548
|
],
|
|
516
549
|
"run-file": [
|
|
517
|
-
|
|
550
|
+
...layoutFlags,
|
|
518
551
|
"include",
|
|
519
552
|
"inspect",
|
|
520
553
|
"readback",
|
|
@@ -527,6 +560,7 @@ async function main(argv, cli) {
|
|
|
527
560
|
"trace",
|
|
528
561
|
],
|
|
529
562
|
run: [
|
|
563
|
+
...layoutFlags,
|
|
530
564
|
"builtins-only",
|
|
531
565
|
"param",
|
|
532
566
|
"apply",
|
|
@@ -539,6 +573,8 @@ async function main(argv, cli) {
|
|
|
539
573
|
"apply",
|
|
540
574
|
"update",
|
|
541
575
|
"force-reason",
|
|
576
|
+
"format",
|
|
577
|
+
"migrate-format",
|
|
542
578
|
],
|
|
543
579
|
probe: [
|
|
544
580
|
"deep",
|
|
@@ -579,6 +615,10 @@ async function main(argv, cli) {
|
|
|
579
615
|
doctor: [
|
|
580
616
|
"timeout-ms",
|
|
581
617
|
],
|
|
618
|
+
wake: [
|
|
619
|
+
"debug-port",
|
|
620
|
+
"timeout-ms",
|
|
621
|
+
],
|
|
582
622
|
up: [],
|
|
583
623
|
down: [],
|
|
584
624
|
open: [
|
|
@@ -629,6 +669,12 @@ async function main(argv, cli) {
|
|
|
629
669
|
throw new Error(`--${key} is not supported by ${command || "this command"}`);
|
|
630
670
|
}
|
|
631
671
|
}
|
|
672
|
+
if (values.format && values.format !== "png" && values.format !== "webp") {
|
|
673
|
+
throw new CommandArgumentError("--format must be png or webp");
|
|
674
|
+
}
|
|
675
|
+
if (values["migrate-format"] && (!values.format || (values.apply && !values.update))) {
|
|
676
|
+
throw new CommandArgumentError("--migrate-format requires --format; applying it requires --update");
|
|
677
|
+
}
|
|
632
678
|
for (const [key, min, max, integer] of [
|
|
633
679
|
[
|
|
634
680
|
"depth",
|
|
@@ -689,12 +735,31 @@ async function main(argv, cli) {
|
|
|
689
735
|
].includes(values.layout)) {
|
|
690
736
|
throw new CommandArgumentError("--layout must be auto, native or geometry");
|
|
691
737
|
}
|
|
692
|
-
if (
|
|
738
|
+
if (values["layout-max-nodes"] !== undefined &&
|
|
739
|
+
(!/^\d+$/.test(values["layout-max-nodes"]) ||
|
|
740
|
+
Number(values["layout-max-nodes"]) < 1 ||
|
|
741
|
+
Number(values["layout-max-nodes"]) > 100000)) {
|
|
742
|
+
throw new CommandArgumentError("--layout-max-nodes must be an integer from 1 to 100000");
|
|
743
|
+
}
|
|
744
|
+
if (values["layout-root"] &&
|
|
745
|
+
(values["layout-root"].some((id) => !id.trim()) ||
|
|
746
|
+
new Set(values["layout-root"]).size !== values["layout-root"].length)) {
|
|
747
|
+
throw new CommandArgumentError("--layout-root must name distinct nonempty shape IDs");
|
|
748
|
+
}
|
|
749
|
+
if ((command === "doctor" || command === "wake") &&
|
|
693
750
|
values["timeout-ms"] !== undefined &&
|
|
694
751
|
(!/^\d+$/.test(values["timeout-ms"]) ||
|
|
695
752
|
Number(values["timeout-ms"]) < 1000 ||
|
|
696
753
|
Number(values["timeout-ms"]) > 30000)) {
|
|
697
|
-
throw new CommandArgumentError(
|
|
754
|
+
throw new CommandArgumentError(`${command} --timeout-ms must be an integer from 1000 to 30000`);
|
|
755
|
+
}
|
|
756
|
+
if (command === "wake" &&
|
|
757
|
+
(rest.length ||
|
|
758
|
+
!values["debug-port"] ||
|
|
759
|
+
!/^\d+$/.test(values["debug-port"]) ||
|
|
760
|
+
Number(values["debug-port"]) < 1 ||
|
|
761
|
+
Number(values["debug-port"]) > 65535)) {
|
|
762
|
+
throw new CommandArgumentError("wake requires --debug-port with an integer from 1 to 65535");
|
|
698
763
|
}
|
|
699
764
|
let tokenEdit;
|
|
700
765
|
if (command === "tokens" &&
|
|
@@ -1337,7 +1402,11 @@ async function main(argv, cli) {
|
|
|
1337
1402
|
{
|
|
1338
1403
|
check: "editor and plugin",
|
|
1339
1404
|
ok: false,
|
|
1340
|
-
detail: "No resolved project credential/connection; editor identity was not observed",
|
|
1405
|
+
detail: "No resolved project credential/connection; editor identity was not observed; heartbeat age unavailable; keep-alive unknown",
|
|
1406
|
+
evidence: {
|
|
1407
|
+
heartbeat: "unknown",
|
|
1408
|
+
pluginHealth: pluginHealthFromError(undefined),
|
|
1409
|
+
},
|
|
1341
1410
|
remedy: "Configure the private credential source, connect the intended editor, then rerun doctor.",
|
|
1342
1411
|
},
|
|
1343
1412
|
]
|
|
@@ -1371,6 +1440,57 @@ async function main(argv, cli) {
|
|
|
1371
1440
|
}
|
|
1372
1441
|
return ok ? 0 : 1;
|
|
1373
1442
|
}
|
|
1443
|
+
if (command === "wake") {
|
|
1444
|
+
const config = await loadCommandConfig(root);
|
|
1445
|
+
if (!config.file?.id) {
|
|
1446
|
+
throw new CommandArgumentError("Pin the owner-confirmed file before waking its browser tab");
|
|
1447
|
+
}
|
|
1448
|
+
const mcp = await mcpProbeFor();
|
|
1449
|
+
if (!mcp) {
|
|
1450
|
+
throw new Error("Configure the project's MCP connection before waking and verifying its tab");
|
|
1451
|
+
}
|
|
1452
|
+
assertEndpointIsInstance({
|
|
1453
|
+
origin: mcp.origin,
|
|
1454
|
+
source: "project connection",
|
|
1455
|
+
}, config);
|
|
1456
|
+
const timeoutMs = Number(values["timeout-ms"] ?? 5000);
|
|
1457
|
+
const started = Date.now();
|
|
1458
|
+
const activation = await wakeBrowserTarget({
|
|
1459
|
+
origin: isExternal(config) ? config.profile.origin : frontendUrl(config),
|
|
1460
|
+
allowLoopbackAlias: !isExternal(config),
|
|
1461
|
+
fileId: config.file.id,
|
|
1462
|
+
port: Number(values["debug-port"]),
|
|
1463
|
+
timeoutMs,
|
|
1464
|
+
signal: commandSignal(),
|
|
1465
|
+
});
|
|
1466
|
+
const remaining = timeoutMs - (Date.now() - started);
|
|
1467
|
+
const checks = remaining > 0
|
|
1468
|
+
? await doctorEditor(config, {
|
|
1469
|
+
mcp,
|
|
1470
|
+
timeoutMs: remaining,
|
|
1471
|
+
})
|
|
1472
|
+
: [
|
|
1473
|
+
{
|
|
1474
|
+
check: "editor and plugin",
|
|
1475
|
+
ok: false,
|
|
1476
|
+
detail: "Tab activation exhausted the verification deadline",
|
|
1477
|
+
},
|
|
1478
|
+
];
|
|
1479
|
+
const ready = checks.length > 0 && checks.every((check) => check.ok);
|
|
1480
|
+
output.result({
|
|
1481
|
+
...activation,
|
|
1482
|
+
ready,
|
|
1483
|
+
checks,
|
|
1484
|
+
});
|
|
1485
|
+
if (!values.json) {
|
|
1486
|
+
output.log("Browser activation acknowledged; sustained keep-alive: none. No write was replayed.");
|
|
1487
|
+
for (const check of checks) {
|
|
1488
|
+
output.log(`${check.ok ? "ok " : "FAIL"} ${check.check}: ${check.detail}`);
|
|
1489
|
+
}
|
|
1490
|
+
output.log("Reconcile any uncertain run independently before explicitly resuming it.");
|
|
1491
|
+
}
|
|
1492
|
+
return ready ? 0 : 1;
|
|
1493
|
+
}
|
|
1374
1494
|
if (command === "open") {
|
|
1375
1495
|
if (rest.length) {
|
|
1376
1496
|
throw new CommandArgumentError("open accepts only --print for a URL preview");
|
|
@@ -1662,10 +1782,24 @@ async function main(argv, cli) {
|
|
|
1662
1782
|
const client = await guarded();
|
|
1663
1783
|
commandRedactor(endpointRedactor(endpoint));
|
|
1664
1784
|
const options = {
|
|
1665
|
-
...(values.layout
|
|
1785
|
+
...(values.layout || values["layout-root"] || values["layout-max-nodes"]
|
|
1666
1786
|
? {
|
|
1667
1787
|
layout: {
|
|
1668
|
-
|
|
1788
|
+
...(values.layout
|
|
1789
|
+
? {
|
|
1790
|
+
strategy: values.layout,
|
|
1791
|
+
}
|
|
1792
|
+
: {}),
|
|
1793
|
+
...(values["layout-root"]
|
|
1794
|
+
? {
|
|
1795
|
+
shapeIds: values["layout-root"],
|
|
1796
|
+
}
|
|
1797
|
+
: {}),
|
|
1798
|
+
...(values["layout-max-nodes"]
|
|
1799
|
+
? {
|
|
1800
|
+
maxNodes: Number(values["layout-max-nodes"]),
|
|
1801
|
+
}
|
|
1802
|
+
: {}),
|
|
1669
1803
|
},
|
|
1670
1804
|
}
|
|
1671
1805
|
: {}),
|
|
@@ -1786,6 +1920,8 @@ async function main(argv, cli) {
|
|
|
1786
1920
|
apply: values.apply === true,
|
|
1787
1921
|
update: values.update === true,
|
|
1788
1922
|
forceReason: values["force-reason"],
|
|
1923
|
+
format: values.format,
|
|
1924
|
+
migrateFormat: values["migrate-format"],
|
|
1789
1925
|
});
|
|
1790
1926
|
output.result(report);
|
|
1791
1927
|
for (const r of report.results) {
|
|
@@ -1908,6 +2044,7 @@ async function main(argv, cli) {
|
|
|
1908
2044
|
throw new CommandArgumentError("approve --page PAGE --frame ID [--case CASE_ID] previews evidence; --write requires --note exact-owner-words and --by identity");
|
|
1909
2045
|
}
|
|
1910
2046
|
let intent;
|
|
2047
|
+
let imageFormat = values.format ?? "webp";
|
|
1911
2048
|
if (values.case) {
|
|
1912
2049
|
const baseline = projectConfig?.baselines;
|
|
1913
2050
|
const wanted = baseline?.frames.find((f) => f.id === values.case);
|
|
@@ -1926,6 +2063,9 @@ async function main(argv, cli) {
|
|
|
1926
2063
|
}
|
|
1927
2064
|
}
|
|
1928
2065
|
intent = wanted.case;
|
|
2066
|
+
imageFormat = values.format
|
|
2067
|
+
? values.format
|
|
2068
|
+
: await resolveBaselineImageFormat(root, baseline, wanted.id);
|
|
1929
2069
|
}
|
|
1930
2070
|
const captured = await exportShapePng(client, values.frame, {
|
|
1931
2071
|
...options,
|
|
@@ -1935,17 +2075,21 @@ async function main(argv, cli) {
|
|
|
1935
2075
|
if (!captured.stable) {
|
|
1936
2076
|
throw new Error("Approval export did not stabilize");
|
|
1937
2077
|
}
|
|
1938
|
-
const
|
|
2078
|
+
const approvalImage = await encodeBaselineImage(captured.png, imageFormat);
|
|
2079
|
+
const sha256 = artifactSha(approvalImage);
|
|
1939
2080
|
const report = values.write
|
|
1940
2081
|
? await recordApproval(root, captured, {
|
|
1941
2082
|
note: values.note,
|
|
1942
2083
|
by: values.by,
|
|
1943
|
-
}, intent, endpointRedactor(endpoint)
|
|
2084
|
+
}, intent, endpointRedactor(endpoint), {
|
|
2085
|
+
format: imageFormat,
|
|
2086
|
+
})
|
|
1944
2087
|
: {
|
|
1945
2088
|
schemaVersion: 1,
|
|
1946
2089
|
kind: "approval-candidate",
|
|
1947
2090
|
capture: captured.capture,
|
|
1948
2091
|
sha256,
|
|
2092
|
+
imageFormat,
|
|
1949
2093
|
fingerprint: approvalFingerprint(captured.capture, sha256, intent),
|
|
1950
2094
|
recorded: false,
|
|
1951
2095
|
};
|
|
@@ -2148,6 +2292,36 @@ async function runAdapterCommand(command, root, args) {
|
|
|
2148
2292
|
async function runCliInternal(argv, options = {}) {
|
|
2149
2293
|
try {
|
|
2150
2294
|
const root = projectRoot();
|
|
2295
|
+
if (argv[0] === "journey-map" ||
|
|
2296
|
+
argv[0] === "integration-map" ||
|
|
2297
|
+
argv[0] === "design-release") {
|
|
2298
|
+
const { runDesignCommand } = await import("./design-commands/index.js");
|
|
2299
|
+
let designRedactor = (text) => redactEndpoint(text);
|
|
2300
|
+
return await runDesignCommand(argv[0], argv.slice(1), {
|
|
2301
|
+
root,
|
|
2302
|
+
output,
|
|
2303
|
+
redact: (text) => designRedactor(text),
|
|
2304
|
+
async withPenpot(work) {
|
|
2305
|
+
const config = await loadCommandConfig(root);
|
|
2306
|
+
if (!config.file?.id) {
|
|
2307
|
+
throw new Error("Live design commands require an explicitly pinned Penpot file");
|
|
2308
|
+
}
|
|
2309
|
+
const endpoint = await projectEndpoint(root);
|
|
2310
|
+
designRedactor = endpointRedactor(endpoint);
|
|
2311
|
+
commandRedactor(endpointRedactor(endpoint));
|
|
2312
|
+
assertEndpointIsInstance(endpoint.description, config);
|
|
2313
|
+
const client = guardFile(await connect(endpoint), config.file, {
|
|
2314
|
+
mode: "strict",
|
|
2315
|
+
});
|
|
2316
|
+
try {
|
|
2317
|
+
return await work(client);
|
|
2318
|
+
}
|
|
2319
|
+
finally {
|
|
2320
|
+
await client.close();
|
|
2321
|
+
}
|
|
2322
|
+
},
|
|
2323
|
+
});
|
|
2324
|
+
}
|
|
2151
2325
|
if (argv[0] === "onboard") {
|
|
2152
2326
|
if (argv.slice(1).some((arg) => arg !== "--json")) {
|
|
2153
2327
|
throw new Error("usage: penpair onboard [--json]");
|
|
@@ -2330,15 +2504,16 @@ async function runCliBound(argv, options = {}) {
|
|
|
2330
2504
|
...argv,
|
|
2331
2505
|
];
|
|
2332
2506
|
const timeoutAt = args.indexOf("--timeout-ms");
|
|
2507
|
+
const boundedDiagnosis = args[0] === "doctor" || args[0] === "wake";
|
|
2333
2508
|
let invalidTimeout = false;
|
|
2334
2509
|
if (timeoutAt !== -1) {
|
|
2335
2510
|
const milliseconds = Number(args[timeoutAt + 1]);
|
|
2336
2511
|
invalidTimeout =
|
|
2337
2512
|
!Number.isInteger(milliseconds) ||
|
|
2338
|
-
milliseconds < (
|
|
2339
|
-
milliseconds > (
|
|
2513
|
+
milliseconds < (boundedDiagnosis ? 1000 : 1) ||
|
|
2514
|
+
milliseconds > (boundedDiagnosis ? 30000 : 1_800_000) ||
|
|
2340
2515
|
args.indexOf("--timeout-ms", timeoutAt + 1) !== -1;
|
|
2341
|
-
if (
|
|
2516
|
+
if (!boundedDiagnosis) {
|
|
2342
2517
|
args.splice(timeoutAt, 2);
|
|
2343
2518
|
}
|
|
2344
2519
|
if (!invalidTimeout) {
|
|
@@ -2365,8 +2540,8 @@ async function runCliBound(argv, options = {}) {
|
|
|
2365
2540
|
try {
|
|
2366
2541
|
if (invalidTimeout) {
|
|
2367
2542
|
const result = await collectCommand(args[0] ?? "help", async () => {
|
|
2368
|
-
throw new Error(
|
|
2369
|
-
?
|
|
2543
|
+
throw new Error(boundedDiagnosis
|
|
2544
|
+
? `${args[0]} --timeout-ms must be one integer from 1000 to 30000`
|
|
2370
2545
|
: "--timeout-ms must be one integer from 1 to 1800000");
|
|
2371
2546
|
});
|
|
2372
2547
|
if (json) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CommandOutput } from "../command-result.js";
|
|
2
|
+
import type { PenpotToolClient } from "../client.js";
|
|
3
|
+
/** Project-owned artifact commands can work offline; a live operation opens a strictly pinned connection. */
|
|
4
|
+
export interface DesignCommandContext {
|
|
5
|
+
root: string;
|
|
6
|
+
output: CommandOutput;
|
|
7
|
+
redact(value: string): string;
|
|
8
|
+
withPenpot<T>(work: (client: PenpotToolClient) => Promise<T>): Promise<T>;
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DesignCommandContext } from "./context.js";
|
|
2
|
+
export type { DesignCommandContext } from "./context.js";
|
|
3
|
+
export declare function runDesignCommand(family: "journey-map" | "integration-map" | "design-release", args: string[], context: DesignCommandContext): Promise<number>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { runMapCommand } from "./map-command.js";
|
|
2
|
+
import { runDesignReleaseCommand } from "./release-command.js";
|
|
3
|
+
export async function runDesignCommand(family, args, context) {
|
|
4
|
+
return family === "design-release"
|
|
5
|
+
? runDesignReleaseCommand(args, context)
|
|
6
|
+
: runMapCommand(family, args, context);
|
|
7
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MapKind } from "../maps/types.js";
|
|
2
|
+
import type { DesignCommandContext } from "./context.js";
|
|
3
|
+
/** Explicit local artifact actions remain offline; native publication is preview-only until --apply. */
|
|
4
|
+
export declare function runMapCommand(kind: MapKind, args: string[], context: DesignCommandContext): Promise<number>;
|