@penpair/web 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/docs/adapters.md +1 -1
- package/docs/approvals.md +33 -2
- package/docs/artifacts.md +23 -3
- package/docs/browser-sessions.md +147 -0
- package/docs/compatibility.md +4 -2
- package/docs/copy-between-pages.md +54 -0
- package/docs/coverage.md +20 -4
- package/docs/design-releases.md +164 -0
- package/docs/guide.md +20 -3
- package/docs/handoff.md +1 -1
- package/docs/integration-maps.md +171 -0
- package/docs/journey-maps.md +139 -0
- package/docs/layout-settling.md +17 -1
- package/docs/mcp.md +2 -0
- package/docs/run-file.md +2 -0
- package/docs/troubleshooting.md +1 -1
- package/examples/design-release-maps/README.md +72 -0
- package/examples/design-release-maps/integration.json +181 -0
- package/examples/design-release-maps/journey.json +187 -0
- package/examples/design-release-maps/sample-source.md +8 -0
- package/package.json +2 -2
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Integration maps
|
|
2
|
+
|
|
3
|
+
An integration map links a reviewed user journey to the screens, routes,
|
|
4
|
+
components, state, data and verification work needed to implement it. It gives
|
|
5
|
+
agents a shared project record of what the solution must present and what the
|
|
6
|
+
current implementation actually presents.
|
|
7
|
+
|
|
8
|
+
Start with the [journey map](journey-maps.md) and complete [design evidence](handoff.md).
|
|
9
|
+
Inspect existing code before proposing new modules. Reuse project architecture;
|
|
10
|
+
a visual frame does not justify inventing a backend or component framework.
|
|
11
|
+
|
|
12
|
+
## Local commands
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
penpair integration-map check --from design/integrations/reset-password/map.json
|
|
16
|
+
penpair integration-map render --from design/integrations/reset-password/map.json --out design/integrations/reset-password/rendered
|
|
17
|
+
penpair integration-map context --from design/integrations/reset-password/map.json --out design/integrations/reset-password/context.json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Use the local project command when installed as a dependency. Add `--live` to a
|
|
21
|
+
check only when an explicit fresh Penpot observation is needed; ordinary saved
|
|
22
|
+
input validation does not establish current live freshness.
|
|
23
|
+
|
|
24
|
+
## Record the gaps before building
|
|
25
|
+
|
|
26
|
+
Use stable requirements and connect each to relevant design cases, proposed or
|
|
27
|
+
existing code responsibilities, data contracts and verification evidence. Mark
|
|
28
|
+
claims `observed`, `proposed`, `owner-decision` or `unknown`. Distinguish visible
|
|
29
|
+
screen state from inferred behavior, and application intent from observed code.
|
|
30
|
+
Keep unresolved component identity, API behavior and accessibility semantics
|
|
31
|
+
explicit.
|
|
32
|
+
|
|
33
|
+
| Requirement | Design observation | Implementation observation | Finding and next action |
|
|
34
|
+
| --- | --- | --- | --- |
|
|
35
|
+
| `reset-error-retry` | Illustrative design has a retryable error with the address retained | Hypothetical implementation clears the address after a failed request | Blocking: the person must retype their address. Preserve the value and verify the failed-request/retry path; this example is not observed project evidence. |
|
|
36
|
+
|
|
37
|
+
Compare both directions: intended requirements without implementation, and
|
|
38
|
+
implemented behavior without an agreed rationale. Link concrete source/evidence
|
|
39
|
+
rather than reporting that a diagram or passing build proves completeness.
|
|
40
|
+
|
|
41
|
+
## Contract, drawings and edits
|
|
42
|
+
|
|
43
|
+
A schema-1 `integration-map` contract uses the same sources, nodes, edges,
|
|
44
|
+
requirements and findings as a journey contract. Its `journey` reference binds the
|
|
45
|
+
project-relative path and exact SHA-256 of its journey map. Component mapping
|
|
46
|
+
still requires exact source identities as described in [handoff](handoff.md);
|
|
47
|
+
familiar labels are insufficient.
|
|
48
|
+
|
|
49
|
+
The `integration-map` command family checks a contract, renders derived diagrams,
|
|
50
|
+
publishes managed native objects, imports native edits as a reviewable proposal,
|
|
51
|
+
accepts a proposal, records supplied owner review and emits bounded context.
|
|
52
|
+
Read installed help for exact arguments. Do not equate `accept` of an edit
|
|
53
|
+
proposal with owner `approve`, image approval or implementation acceptance.
|
|
54
|
+
|
|
55
|
+
Canonical JSON is authoritative. Mermaid, drawing plans and native Penpot boards
|
|
56
|
+
are derived views tied to its hash. A managed Penpot edit must become a proposal
|
|
57
|
+
against that hash; inspect the changes before accepting them. Unmanaged shapes
|
|
58
|
+
and ambiguous identities are not automatic contract edits. Publishing and
|
|
59
|
+
updating native drawings follow the full Penpot write protocol.
|
|
60
|
+
|
|
61
|
+
Semantic native import writes both the canonical proposal and a bound adjacent
|
|
62
|
+
`<proposal>.native.json` observation. Preserve both. Native acceptance rechecks
|
|
63
|
+
the live observation read-only before changing the canonical contract and saved
|
|
64
|
+
baseline; afterward republish explicitly to update native contract metadata.
|
|
65
|
+
A purely local semantic proposal without native observation can be accepted
|
|
66
|
+
offline. If canonical acceptance succeeded but saving the projection failed,
|
|
67
|
+
reconcile with the same proposal rather than blindly publishing again.
|
|
68
|
+
|
|
69
|
+
Geometry-only edits use a separate `map-presentation-proposal`. Acceptance checks
|
|
70
|
+
the exact canonical hash, saved baseline and current observed projection, captures
|
|
71
|
+
fresh stable evidence and adopts presentation without changing canonical bytes.
|
|
72
|
+
Renew native visual review: old review does not automatically cover new render
|
|
73
|
+
evidence. Future publication preserves accepted node positions and sizes.
|
|
74
|
+
Unsupported style/ownership changes and unmanaged objects remain conflicts.
|
|
75
|
+
|
|
76
|
+
Use clear typography, short labels and a neutral diagram theme. The diagram's
|
|
77
|
+
font defaults to Inter; an explicit presentation override belongs to the map.
|
|
78
|
+
Diagram presentation must not modify the application's tokens or theme.
|
|
79
|
+
|
|
80
|
+
## Readable titles and descriptions
|
|
81
|
+
|
|
82
|
+
Existing contracts remain supported. Optional map `summary` and `description`
|
|
83
|
+
add a short introduction and detailed context. A node's existing `label` remains
|
|
84
|
+
its title; optional `summary`, `description` and `icon` supply a one-line purpose,
|
|
85
|
+
longer explanation and semantic icon. Keep labels specific and concise instead
|
|
86
|
+
of repeating “proposed” or “unknown”; the origin badge supplies that distinction.
|
|
87
|
+
Descriptions still need to explain which evidence supports a claim and which
|
|
88
|
+
questions remain unresolved.
|
|
89
|
+
|
|
90
|
+
Native cards use compact titles, summaries, icons and connector ports. Full
|
|
91
|
+
original text and long descriptions remain in managed notes below the flow and
|
|
92
|
+
in generated Markdown/context; they must not disappear when card text is shortened.
|
|
93
|
+
Descriptions and icons belong to canonical intent: edits need proposal review and
|
|
94
|
+
renewed approval. Use one fixed icon key: `screen`, `action`, `decision`, `data`,
|
|
95
|
+
`service`, `code`, `check` or `link`. Icons use native vector paths, with no external
|
|
96
|
+
image URLs or asset downloads.
|
|
97
|
+
|
|
98
|
+
## Linked detail maps
|
|
99
|
+
|
|
100
|
+
Decompose oversized maps explicitly; Penpair does not automatically partition a
|
|
101
|
+
contract. Give each detail map its own canonical contract, native publication
|
|
102
|
+
and owner review. In the parent, a `kind: "detail-link"` node references exactly
|
|
103
|
+
one `sourceId`: that source must have `kind: "contract"`, a project-relative
|
|
104
|
+
`path`, the raw file-byte `sha256`, and exact `fileId`, `pageId` and `frameId` of
|
|
105
|
+
the published detail board in the same pinned file. This source byte hash is
|
|
106
|
+
distinct from the canonical hash used by a journey reference.
|
|
107
|
+
|
|
108
|
+
The linked child must have the same map kind as the parent. The link covers at
|
|
109
|
+
least one parent requirement through `requirementIds`, and the child retains
|
|
110
|
+
all those requirement IDs. Generated Markdown links to the contract; the native
|
|
111
|
+
card uses a `NavigateTo` interaction to its declared board. Missing/stale source
|
|
112
|
+
bytes or incompatible child requirements prevent readiness.
|
|
113
|
+
|
|
114
|
+
Parent context identifies the child handoff and its independent review rather
|
|
115
|
+
than inlining the child graph. Later agents must read that child contract too.
|
|
116
|
+
Include every parent and linked detail contract in the design release with its
|
|
117
|
+
own exact review. Publishing or approving the parent does not publish or approve
|
|
118
|
+
its detail maps.
|
|
119
|
+
|
|
120
|
+
## Implementation context
|
|
121
|
+
|
|
122
|
+
A context result should identify the exact map and journey, review/freshness,
|
|
123
|
+
open findings, requirements and linked source evidence. Bounded or truncated
|
|
124
|
+
context must say so; missing evidence remains pending. Freshness against supplied
|
|
125
|
+
saved files does not assert live Penpot freshness or functional correctness.
|
|
126
|
+
|
|
127
|
+
Later agents should:
|
|
128
|
+
|
|
129
|
+
1. Read the current map context and linked sources before implementing.
|
|
130
|
+
2. Surface stale inputs and blocking findings before relying on approval.
|
|
131
|
+
3. Implement within the reviewed scope; propose changes to intent separately.
|
|
132
|
+
4. Attach actual route/state, browser and behavior evidence to the project record.
|
|
133
|
+
5. Reconcile findings and seek implementation acceptance independently.
|
|
134
|
+
|
|
135
|
+
Use [Reflection Check](adapters.md#check-the-frontend-against-the-design) for actual
|
|
136
|
+
browser comparisons. It supplies visual evidence; behavior and accessibility
|
|
137
|
+
need their own checks. A low pixel difference does not approve architecture or
|
|
138
|
+
prove a working recovery flow.
|
|
139
|
+
|
|
140
|
+
## Design readiness and implementation readiness
|
|
141
|
+
|
|
142
|
+
A [design release](design-releases.md) can finalize a reviewed, internally
|
|
143
|
+
consistent design package while implementation is still `not-assessed`. That
|
|
144
|
+
separation is intentional: agents need stable approved design context before
|
|
145
|
+
they build. Never mark implementation accepted because a map was approved.
|
|
146
|
+
|
|
147
|
+
See the [worked reset-password example](../examples/design-release-maps/README.md)
|
|
148
|
+
for a proposed journey and integration map with visible unknowns.
|
|
149
|
+
|
|
150
|
+
Every local requirement must appear in a node or edge's `requirementIds`, and an
|
|
151
|
+
integration map retains all requirement IDs from its linked journey. Omitted
|
|
152
|
+
coverage prevents readiness and design finalization; drafts can still be checked
|
|
153
|
+
and rendered. Drawing plans explicitly become incomplete above a 16,384 px axis
|
|
154
|
+
or 64 KiB serialized plan budget. Split the map instead of publishing clipped
|
|
155
|
+
content.
|
|
156
|
+
|
|
157
|
+
## Publication recovery
|
|
158
|
+
|
|
159
|
+
After an uncertain write, inspect the actual target and retained run first. Resume
|
|
160
|
+
the original journal explicitly, keeping the original contract, sources and
|
|
161
|
+
target flags (including whether `--board-id` was omitted):
|
|
162
|
+
|
|
163
|
+
```sh
|
|
164
|
+
penpair integration-map publish --from design/integrations/reset-password/map.json \
|
|
165
|
+
--page-id PAGE_ID --apply --resume RUN_ID
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Use the original `--board-id` and `--projection` options if they were supplied.
|
|
169
|
+
Resume independently reconciles readback and exports; it does not blindly repeat
|
|
170
|
+
the write. Changed input or code signatures must refuse reuse. Inspect again and
|
|
171
|
+
start a new explicitly authorized run when needed; do not bypass those guards.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Journey maps
|
|
2
|
+
|
|
3
|
+
A journey map records what a person is trying to accomplish, which states they
|
|
4
|
+
encounter, and the decisions still needed before implementation. It is a
|
|
5
|
+
project-owned contract that later agents can read without recovering earlier
|
|
6
|
+
chats. Use an [integration map](integration-maps.md) to connect the journey to
|
|
7
|
+
application structure, and a [design release](design-releases.md) to freeze a
|
|
8
|
+
reviewed design handoff.
|
|
9
|
+
|
|
10
|
+
## Local commands
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
penpair journey-map check --from design/journeys/reset-password/map.json
|
|
14
|
+
penpair journey-map render --from design/journeys/reset-password/map.json --out design/journeys/reset-password/rendered
|
|
15
|
+
penpair journey-map context --from design/journeys/reset-password/map.json --out design/journeys/reset-password/context.json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Use your project's local command, such as `pnpm exec penpair`, when installed as
|
|
19
|
+
an application dependency. Rendering with `--out` writes local derived artifacts;
|
|
20
|
+
it does not publish into Penpot. Context is intended for reviewed inputs; drafts
|
|
21
|
+
must be explicit and cannot imply readiness.
|
|
22
|
+
|
|
23
|
+
## Start from observed intent
|
|
24
|
+
|
|
25
|
+
Inspect the actual frames and existing application before drafting. Record the
|
|
26
|
+
user goal, entry points, successful outcome, alternate paths and recovery. Use
|
|
27
|
+
stable requirement and node IDs so a finding can refer to the same requirement
|
|
28
|
+
through review and implementation. A frame establishes visible design facts;
|
|
29
|
+
it does not establish what a button does, how an API behaves or how keyboard
|
|
30
|
+
focus moves.
|
|
31
|
+
|
|
32
|
+
Every node, edge and requirement declares its origin:
|
|
33
|
+
|
|
34
|
+
| Origin | Meaning |
|
|
35
|
+
| --- | --- |
|
|
36
|
+
| `observed` | Directly supported by the referenced design, code or evidence |
|
|
37
|
+
| `proposed` | An AI or designer recommendation awaiting a decision |
|
|
38
|
+
| `owner-decision` | A decision actually supplied by the owner |
|
|
39
|
+
| `unknown` | Missing information; retain it as a question |
|
|
40
|
+
|
|
41
|
+
An origin is provenance, not approval. In particular, an `owner-decision` label
|
|
42
|
+
cannot replace a review record binding the owner's actual words to the exact
|
|
43
|
+
contract hash. Do not turn guesses into observations or invent approval notes.
|
|
44
|
+
|
|
45
|
+
## Keep the flow readable
|
|
46
|
+
|
|
47
|
+
Use short, specific node titles (`label`), optional one-line `summary` and longer
|
|
48
|
+
`description` text for evidence, decisions and unknowns. The map itself also
|
|
49
|
+
accepts optional `summary` and `description`. Origin badges distinguish observed
|
|
50
|
+
facts from proposals without repeating that status in every title. Optional
|
|
51
|
+
semantic `icon` values use fixed native vectors. Full notes remain available
|
|
52
|
+
below the flow and in Markdown/context; legacy contracts need no new fields.
|
|
53
|
+
See [titles and descriptions](integration-maps.md#readable-titles-and-descriptions).
|
|
54
|
+
These optional fields are part of reviewed canonical intent, so changing them
|
|
55
|
+
needs renewed approval.
|
|
56
|
+
|
|
57
|
+
## Contract and review
|
|
58
|
+
|
|
59
|
+
The schema-1 JSON contract contains `kind: "journey-map"`, `id`, `title`, `goal`,
|
|
60
|
+
`sources`, `nodes`, `edges`, `requirements` and `findings`. Sources retain their
|
|
61
|
+
SHA-256 and available path/file/page/frame/revision identity. Nodes and edges
|
|
62
|
+
carry readable labels and stable IDs; requirement links connect them to the
|
|
63
|
+
intended outcomes. Open blocking findings keep readiness pending. Resolving a
|
|
64
|
+
finding requires an explicit resolution, rather than deleting its history.
|
|
65
|
+
|
|
66
|
+
The `journey-map` command family supports checking, rendering, publishing,
|
|
67
|
+
importing managed edits as proposals, accepting proposals, recording supplied
|
|
68
|
+
approval, and producing bounded context. Consult the installed command's help
|
|
69
|
+
for arguments. Checking and rendering locally do not approve or publish a map.
|
|
70
|
+
Native publication is a Penpot write and needs the normal inspection, pinned
|
|
71
|
+
snapshot, one idempotent write, independent readback and inspected stable export.
|
|
72
|
+
Check the exported typeface against the canvas: a font available to the editor
|
|
73
|
+
can still be unavailable to its exporter. Correct font metadata and identical
|
|
74
|
+
consecutive exports do not prove font fidelity. Visible font substitution needs
|
|
75
|
+
correction before visual approval.
|
|
76
|
+
|
|
77
|
+
The contract is authoritative; Mermaid and native Penpot objects are derived
|
|
78
|
+
views. Managed native edits become a proposal against the exact prior contract
|
|
79
|
+
hash. Review the diff and accept it explicitly before regenerating dependent
|
|
80
|
+
views. A changed label or connector must not silently rewrite accepted intent.
|
|
81
|
+
An old proposal cannot overwrite a newer contract.
|
|
82
|
+
|
|
83
|
+
Owner review is a separate `artifact-review` record containing the artifact
|
|
84
|
+
identity, exact hash, supplied words, identity, date and record hash. Review is
|
|
85
|
+
not authenticated identity. Changed contracts or source hashes need fresh review;
|
|
86
|
+
matching saved inputs do not prove the live file is unchanged.
|
|
87
|
+
|
|
88
|
+
## Review gates
|
|
89
|
+
|
|
90
|
+
1. **Intent ready:** the goal, success/recovery paths, evidence and unknowns are
|
|
91
|
+
explicit. Blocking questions are answered or remain visibly blocking.
|
|
92
|
+
2. **Contract reviewed:** the owner reviewed the exact map and supporting
|
|
93
|
+
decisions. Technical checks and a neat diagram do not supply acceptance.
|
|
94
|
+
3. **Handoff ready:** the integration map references this exact journey hash,
|
|
95
|
+
required design cases exist, and outstanding implementation work is explicit.
|
|
96
|
+
|
|
97
|
+
## Reset-password example
|
|
98
|
+
|
|
99
|
+
The [worked example](../examples/design-release-maps/README.md) describes an
|
|
100
|
+
illustrative reset flow. An observed confirmation frame is distinct from a
|
|
101
|
+
proposed submission transition and an unknown expiry policy. The example is
|
|
102
|
+
unapproved and contains no fabricated inspection or owner evidence.
|
|
103
|
+
|
|
104
|
+
Keep loading, empty, error and success states proportionate to the feature.
|
|
105
|
+
Capture keyboard entry, focus movement, error announcements and responsive
|
|
106
|
+
behavior as explicit requirements or unknowns. The map does not establish that
|
|
107
|
+
any of these behaviors has been implemented or tested.
|
|
108
|
+
|
|
109
|
+
Contracts are bounded to 16 MiB, 1,000 nodes and 2,000 edges. Context has a
|
|
110
|
+
128 KiB limit and reports omissions explicitly. Source paths remain inside the
|
|
111
|
+
project. Labels and descriptions are escaped literal data in generated views.
|
|
112
|
+
|
|
113
|
+
Every local requirement must be connected through node/edge `requirementIds`.
|
|
114
|
+
A readable graph with unmapped requirements remains incomplete for readiness.
|
|
115
|
+
Drawing plans also refuse complete native publication above a 16,384 px axis or
|
|
116
|
+
64 KiB serialized plan size; split large maps into reviewable parts. Semantic
|
|
117
|
+
native imports retain a bound adjacent `.native.json` observation and require
|
|
118
|
+
fresh live readback during acceptance. Pure geometry changes instead produce a
|
|
119
|
+
presentation proposal, preserve canonical intent and require fresh visual review.
|
|
120
|
+
|
|
121
|
+
For explicit decomposition, use [linked detail maps](integration-maps.md#linked-detail-maps).
|
|
122
|
+
Journey details remain journey contracts, with independent publication and review;
|
|
123
|
+
parent approval does not cover a child map automatically.
|
|
124
|
+
|
|
125
|
+
## Publication recovery
|
|
126
|
+
|
|
127
|
+
After an uncertain write, inspect the actual target and retained run first. Resume
|
|
128
|
+
the original journal explicitly, keeping the original contract, sources and
|
|
129
|
+
target flags (including whether `--board-id` was omitted):
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
penpair journey-map publish --from design/journeys/reset-password/map.json \
|
|
133
|
+
--page-id PAGE_ID --apply --resume RUN_ID
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Use the original `--board-id` and `--projection` options if they were supplied.
|
|
137
|
+
Resume independently reconciles readback and exports; it does not blindly repeat
|
|
138
|
+
the write. Changed input or code signatures must refuse reuse. Inspect again and
|
|
139
|
+
start a new explicitly authorized run when needed; do not bypass those guards.
|
package/docs/layout-settling.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bounded layout settling
|
|
2
2
|
|
|
3
|
-
Normal operation writes, PNG exports, baselines, shots and token push verification now use `waitForStableLayout`. A supported shape/global native wait is preferred. Older APIs fall back to geometry samples, requiring
|
|
3
|
+
Normal operation writes, PNG exports, baselines, shots and token push verification now use `waitForStableLayout`. A supported shape/global native wait is preferred. Older APIs fall back to geometry samples, requiring three consecutive equal observations of the target subtree. Missing targets, changed file/page identity, malformed sampled geometry and expired budgets cannot establish stability. Native failure falls back to geometry in `auto` mode; `native` mode still requires a successful native wait.
|
|
4
4
|
|
|
5
5
|
The default layout budget is 30 seconds, with 200 ms fallback intervals. A run is also limited to 1,000 samples. Each layout observation forwards its remaining request budget through guards to the MCP SDK and disables suspension retries; a read timeout does not silently restart the budget. Custom clients must honor the optional `ToolCallOptions.timeoutMs` contract. A late native response is rejected even if it claims completion. The overall CLI `--timeout-ms` remains a separate bound on the complete command.
|
|
6
6
|
|
|
@@ -11,3 +11,19 @@ Exports retain the first capture as an initial observation, wait for layout, and
|
|
|
11
11
|
The previous unconditional ten-second operation sleep is replaced by bounded evidence. Library callers can retain an explicitly measured `settleMs` minimum from 0 to 30 seconds for an additional asynchronous contract such as binding persistence. It is a delay, not verification. A missing binding still fails independent readback and may be reconciled through the journal once it arrives. Page switching retains its existing short navigation delay. No new live timing or compatibility claim is made.
|
|
12
12
|
|
|
13
13
|
Library options may select a target and budget through `layout`, or explicitly set `layout: false` when the caller supplies its own settlement evidence. CLI design commands do not expose that opt-out. Multi-step mutations remain nontransactional: a post-write layout failure can leave completed work applied; inspect the run and explicitly resume after resolving it. The later build kit should reuse these primitives rather than introduce another fixed-sleep convention.
|
|
14
|
+
|
|
15
|
+
## Scope and node budgets
|
|
16
|
+
|
|
17
|
+
`run-file`, `run`, `archive`, token edit writers, `export` and `shots` accept:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
penpair run-file design/build.js --inspect design/inspect.js --readback design/readback.js \
|
|
21
|
+
--page Candidate --layout-root BOARD_ID --layout-root OTHER_BOARD_ID \
|
|
22
|
+
--layout-max-nodes 20000 --apply
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Each repeatable `--layout-root` identifies an existing shape on the operation's page. Roots must be distinct, nonoverlapping subtrees. Missing roots refuse rather than falling back to the page. The same roots are observed before planning, after writing and during recovery. New shape IDs cannot be selected before creation; select their existing parent or use the page default. Without explicit roots the current page is sampled; exports retain their existing shape scope. Library callers use `layout.shapeIds` (or the existing singular `shapeId`) and `layout.maxNodes`.
|
|
26
|
+
|
|
27
|
+
`--layout-max-nodes` is an integer from 1 to 100,000, shared across the selected subtrees; the default remains 10,000. When the traversal exceeds it, the observer retains a bounded depth-first prefix. A successful native wait or three equal bounded samples can continue the operation with `method: "partial"` and `truncated: true`. This establishes stability only for the sample, not for unsampled shapes. Invalid geometry, cycles or duplicate IDs encountered in the sample still refuse. Use explicit roots for complete evidence on a large page. Partial evidence never replaces positive independent write readback or visual export inspection.
|
|
28
|
+
|
|
29
|
+
Reports and journal observations, visible through `penpair runs RUN_ID`, record `rootIds`, `nodeCount` (the sampled count), `maxNodes` and `truncated`. The sample count is a lower bound on subtree size when truncated. Journal input hashes retain the chosen scope and budget, so changing either requires a new run. The build kit's `pp.settle(root, {maxNodes})` shares this policy and evidence; it also accepts an array of root shapes.
|
package/docs/mcp.md
CHANGED
|
@@ -55,3 +55,5 @@ args = ["mcp", "--root", "/absolute/path/to/project"]
|
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
Restart/reconnect after reviewed target or tool-capability changes. Keep the actual Penpot editor visible. SDK in-memory tests establish discovery, typed input refusal, explicit write opt-in, root isolation and target-change refusal; actual agent/editor compatibility remains a pending I12 trial.
|
|
58
|
+
|
|
59
|
+
For explicit tab activation, heartbeat diagnostics and the limits of background operation, see [recovering a suspended Penpot tab](browser-sessions.md). The CLI `wake` action is separate from the read-only doctor tool.
|
package/docs/run-file.md
CHANGED
|
@@ -69,3 +69,5 @@ The common verifier requires matching nonempty expected/actual objects. Empty `p
|
|
|
69
69
|
Final wrapped UTF-8 snippets obey the existing 90 KB guard, including helpers, guards, parameters and the captured inspection passed to apply. Every phase compiles offline before connecting; an oversized runtime inspection can still make apply refuse before delivery. Each input file is bounded independently, and at most 20 distinct include paths and 100 parameters are accepted. Reports identify the ordered source text hashes actually prepared. No implicit imports, glob expansion or transpilation occurs.
|
|
70
70
|
|
|
71
71
|
Writes reuse pinned file guards, revisions, writer coordination, positive independent verification and redacted journals. Optional `--checkpoint`, `--force-lock` and explicit `--apply --resume RUN_ID` follow normal recovery rules. Source/parameter changes refuse resume; a final state already independently verified is not written again. Partial unexplained state requires inspection; there is no rollback or enforced idempotency sandbox. A redacted journal cannot be presented as complete verification or automatically resumed.
|
|
72
|
+
|
|
73
|
+
On a large page, scope layout settling to the existing boards touched by the write with repeatable `--layout-root SHAPE_ID`. `--layout-max-nodes N` sets the shared sample budget (1–100,000; default 10,000). The roots must exist before the write and remain present through readback. Reports and `penpair runs RUN_ID` retain the roots and sampled node count. Budget overflow continues with explicitly partial layout evidence; independent readback is still required. See [layout settling](layout-settling.md) for scope and partial-sample limits.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -11,7 +11,7 @@ Generated from the core error remedy inventory. Regenerate with `pnpm docs:gener
|
|
|
11
11
|
| `incomplete-output` | Required output is missing, truncated or unstable. Narrow the scope or resolve the capture problem before accepting it as complete. |
|
|
12
12
|
| `mcp-unavailable` | Start the Penpot instance and check the MCP URL. Run `penpair probe` to see what answers. |
|
|
13
13
|
| `plugin-disconnected` | In the open Penpot file choose File, MCP Server, Connect, and keep that tab visible, then run the command again. |
|
|
14
|
-
| `plugin-suspended` | The browser put the Penpot tab to sleep. Bring it to the foreground
|
|
14
|
+
| `plugin-suspended` | The browser put the Penpot tab to sleep. Bring it to the foreground, or use penpair wake --debug-port PORT with a dedicated debugging browser, then run penpair doctor. Waking is temporary recovery. A suspended-tab error does not mean nothing was written: read the page and reconcile the run before explicitly replaying a write. |
|
|
15
15
|
| `snippet-too-large` | Split the snippet. Penpot's proxy refuses request bodies of about 110 KB, so snippets stay under 90 KB. |
|
|
16
16
|
| `stale-inspection` | The file, revision, query or inspected content changed. Discard the old cursor/chunks and start a fresh capture. |
|
|
17
17
|
| `tool-failed` | Penpot's tool reported a failure; the message above says what. |
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Reviewed-map workflow example
|
|
2
|
+
|
|
3
|
+
These contracts describe a **synthetic, unapproved** reset-password feature.
|
|
4
|
+
They are valid draft inputs, not a real Penpot inspection, code audit, owner
|
|
5
|
+
review or finalized design release. `sample-source.md` is their only observed
|
|
6
|
+
source. Proposed application architecture and unknown policy stay labeled.
|
|
7
|
+
|
|
8
|
+
From the repository root:
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
pnpm build
|
|
12
|
+
node packages/web/dist/cli.js journey-map render --from examples/design-release-maps/journey.json
|
|
13
|
+
node packages/web/dist/cli.js integration-map render --from examples/design-release-maps/integration.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Use the installed CLI entrypoint when working from a packaged installation.
|
|
17
|
+
Rendering is offline and establishes neither owner approval nor live fidelity.
|
|
18
|
+
Checks/context should retain the open blockers and missing reviews; this fixture
|
|
19
|
+
is intentionally not ready for implementation or release finalization.
|
|
20
|
+
|
|
21
|
+
## Read the map
|
|
22
|
+
|
|
23
|
+
```mermaid
|
|
24
|
+
flowchart LR
|
|
25
|
+
Entry["Enter email"]
|
|
26
|
+
Confirm["Check your email"]
|
|
27
|
+
Error["Retry request"]
|
|
28
|
+
Entry -->|"Success"| Confirm
|
|
29
|
+
Entry -->|"Failure"| Error
|
|
30
|
+
Error -->|"Retry"| Entry
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Each JSON node uses a concise `label` as its title, a one-line `summary`, a
|
|
34
|
+
longer `description` for evidence and decisions, and a fixed semantic `icon`.
|
|
35
|
+
Native cards show the compact title/summary with origin badges; detailed notes
|
|
36
|
+
retain the full explanation below the flow. The short labels above do not
|
|
37
|
+
change provenance: entry/confirmation are observations of the synthetic text,
|
|
38
|
+
while success, failure and retry behavior remain proposals. Policy and actual
|
|
39
|
+
code/browser evidence remain unknown.
|
|
40
|
+
|
|
41
|
+
This short illustration explains the intended flow; the JSON contract remains
|
|
42
|
+
authoritative. Generate full Mermaid/native drawing plans from it rather than
|
|
43
|
+
editing this illustration as if it updated the contract. A native drawing is
|
|
44
|
+
editable, but managed semantic changes must be imported as proposals, reviewed,
|
|
45
|
+
accepted against their base hash and approved again.
|
|
46
|
+
|
|
47
|
+
| Requirement | Intended result | Hypothetical mismatch | Next action |
|
|
48
|
+
| --- | --- | --- | --- |
|
|
49
|
+
| `reset-error-retry` | Keep the address after a failed request and allow retry | An implementation clears it and makes the person retype it | Confirm the proposed behavior, then test a real failed request and retry. This row is not observed project evidence. |
|
|
50
|
+
|
|
51
|
+
## Three review gates
|
|
52
|
+
|
|
53
|
+
1. **Intent ready:** inspect real source frames; decide request, disclosure,
|
|
54
|
+
expiry, recovery, loading and focus behavior. Do not convert unknown policy
|
|
55
|
+
into an inferred security rule.
|
|
56
|
+
2. **Design package reviewed:** replace synthetic sources with actual inspection
|
|
57
|
+
paths/hashes, review the exact journey/integration maps, assemble target
|
|
58
|
+
native frames in `release/<product-version>`, verify fidelity, then obtain
|
|
59
|
+
the actual owner words for the exact release candidate. Source image
|
|
60
|
+
approval does not approve new target frame identities.
|
|
61
|
+
3. **Implementation accepted:** implement against that stable context, observe
|
|
62
|
+
actual route/state/fixture behavior, compare browser images, test recovery
|
|
63
|
+
and accessibility, and review the results. Finalized design alone cannot
|
|
64
|
+
satisfy this gate.
|
|
65
|
+
|
|
66
|
+
No release plan with invented file IDs, frame IDs, transfer receipts or owner
|
|
67
|
+
words is included. Create a plan only after inspecting the actual pinned file
|
|
68
|
+
and selecting sources. The [release guide](../../docs/design-releases.md)
|
|
69
|
+
describes the native copy, immutable evidence and later drift checks.
|
|
70
|
+
|
|
71
|
+
New baselines default to static lossless WebP. Preserve existing approved PNG
|
|
72
|
+
bytes; format migration is explicit and requires normal exact-byte review.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"kind": "integration-map",
|
|
4
|
+
"id": "reset-password-integration",
|
|
5
|
+
"title": "Reset implementation",
|
|
6
|
+
"goal": "Connect the proposed reset flow to implementation responsibilities without inventing existing code.",
|
|
7
|
+
"sources": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sample-brief",
|
|
10
|
+
"kind": "other",
|
|
11
|
+
"path": "examples/design-release-maps/sample-source.md",
|
|
12
|
+
"sha256": "ab97f0a30f066e9a9f2689d1624608ea91287751cbc6a613542c0e97de187a96"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"journey": {
|
|
16
|
+
"path": "examples/design-release-maps/journey.json",
|
|
17
|
+
"sha256": "956fbe3e9d4eb3519d714912ec89bfaedd2a8c2b8882d06dc5ee9c4c279439a9"
|
|
18
|
+
},
|
|
19
|
+
"nodes": [
|
|
20
|
+
{
|
|
21
|
+
"id": "reset-route",
|
|
22
|
+
"label": "Reset route",
|
|
23
|
+
"kind": "route",
|
|
24
|
+
"origin": "proposed",
|
|
25
|
+
"requirementIds": [
|
|
26
|
+
"reset-entry"
|
|
27
|
+
],
|
|
28
|
+
"summary": "Open /reset-password to begin the flow.",
|
|
29
|
+
"description": "Proposed route responsibility: enter the reset flow using the existing application router. The route and surrounding navigation have not been inspected. Reuse the actual project structure rather than treating this illustrative path as an approved architecture decision.",
|
|
30
|
+
"icon": "code"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "reset-form",
|
|
34
|
+
"label": "Reset form",
|
|
35
|
+
"kind": "component",
|
|
36
|
+
"origin": "proposed",
|
|
37
|
+
"requirementIds": [
|
|
38
|
+
"reset-entry",
|
|
39
|
+
"reset-error-retry"
|
|
40
|
+
],
|
|
41
|
+
"summary": "Collect an address and retain it on retry.",
|
|
42
|
+
"description": "Proposed form responsibility: collect the address, follow agreed validation and preserve input during recoverable failure. Inspect existing components before choosing an implementation. Form semantics and behavior need explicit review and real browser evidence.",
|
|
43
|
+
"icon": "screen"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "reset-mutation",
|
|
47
|
+
"label": "Reset service",
|
|
48
|
+
"kind": "data",
|
|
49
|
+
"origin": "unknown",
|
|
50
|
+
"requirementIds": [
|
|
51
|
+
"reset-request",
|
|
52
|
+
"reset-expiry"
|
|
53
|
+
],
|
|
54
|
+
"summary": "Agree the request and response contract.",
|
|
55
|
+
"description": "The endpoint, request payload, validation, response policy and expiry behavior are unknown. Obtain the actual project API and product decisions before implementation. This node does not claim that a service exists or prescribe a new backend.",
|
|
56
|
+
"icon": "service"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "reset-feedback",
|
|
60
|
+
"label": "Request feedback",
|
|
61
|
+
"kind": "state",
|
|
62
|
+
"origin": "proposed",
|
|
63
|
+
"requirementIds": [
|
|
64
|
+
"reset-error-retry",
|
|
65
|
+
"reset-confirmation",
|
|
66
|
+
"reset-focus"
|
|
67
|
+
],
|
|
68
|
+
"summary": "Show confirmation or a recoverable error.",
|
|
69
|
+
"description": "Proposed feedback responsibility: present the agreed confirmation state after an accepted request and useful recovery after failure. Define focus and announcements with the actual application. The synthetic source does not establish these transitions or their accessibility.",
|
|
70
|
+
"icon": "decision"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": "browser-case",
|
|
74
|
+
"label": "Verify recovery",
|
|
75
|
+
"kind": "verification",
|
|
76
|
+
"origin": "unknown",
|
|
77
|
+
"requirementIds": [
|
|
78
|
+
"reset-error-retry",
|
|
79
|
+
"reset-confirmation",
|
|
80
|
+
"reset-focus",
|
|
81
|
+
"reset-expiry"
|
|
82
|
+
],
|
|
83
|
+
"summary": "Check retry, focus, and announcements.",
|
|
84
|
+
"description": "Verification is pending. Map approved design cases to actual route/state/fixture setup, then observe failed submission, retained input, retry and confirmation in the real browser. Assess keyboard and screen-reader behavior separately from visual comparison. No provider or result is supplied here.",
|
|
85
|
+
"icon": "check"
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"edges": [
|
|
89
|
+
{
|
|
90
|
+
"id": "route-form",
|
|
91
|
+
"from": "reset-route",
|
|
92
|
+
"to": "reset-form",
|
|
93
|
+
"label": "Compose",
|
|
94
|
+
"origin": "proposed",
|
|
95
|
+
"requirementIds": [
|
|
96
|
+
"reset-entry"
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"id": "form-request",
|
|
101
|
+
"from": "reset-form",
|
|
102
|
+
"to": "reset-mutation",
|
|
103
|
+
"label": "Submit",
|
|
104
|
+
"origin": "unknown",
|
|
105
|
+
"requirementIds": [
|
|
106
|
+
"reset-request"
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "request-feedback",
|
|
111
|
+
"from": "reset-mutation",
|
|
112
|
+
"to": "reset-feedback",
|
|
113
|
+
"label": "Handle result",
|
|
114
|
+
"origin": "proposed",
|
|
115
|
+
"requirementIds": [
|
|
116
|
+
"reset-error-retry"
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"id": "feedback-evidence",
|
|
121
|
+
"from": "reset-feedback",
|
|
122
|
+
"to": "browser-case",
|
|
123
|
+
"label": "Verify behavior",
|
|
124
|
+
"origin": "proposed",
|
|
125
|
+
"requirementIds": [
|
|
126
|
+
"reset-error-retry"
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
"requirements": [
|
|
131
|
+
{
|
|
132
|
+
"id": "reset-entry",
|
|
133
|
+
"text": "Proposed: map the entry screen to the project route and existing form conventions after inspecting code.",
|
|
134
|
+
"origin": "proposed"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"id": "reset-request",
|
|
138
|
+
"text": "Unknown: endpoint, validation and response policy require the actual project contract.",
|
|
139
|
+
"origin": "unknown"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"id": "reset-error-retry",
|
|
143
|
+
"text": "Proposed: retain the entered address on failure; verify retry and accessible feedback in the real browser.",
|
|
144
|
+
"origin": "proposed"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"id": "reset-confirmation",
|
|
148
|
+
"text": "Proposed: render confirmation only after the agreed response; final request policy remains unknown.",
|
|
149
|
+
"origin": "proposed"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"id": "reset-expiry",
|
|
153
|
+
"text": "Unknown: expiry/repeated request behavior must follow the agreed product/security contract.",
|
|
154
|
+
"origin": "unknown"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"id": "reset-focus",
|
|
158
|
+
"text": "Proposed: implement and verify keyboard focus and announced error recovery.",
|
|
159
|
+
"origin": "proposed"
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
"findings": [
|
|
163
|
+
{
|
|
164
|
+
"id": "code-not-inspected",
|
|
165
|
+
"message": "No application code, route or component identity has been inspected for this synthetic example.",
|
|
166
|
+
"severity": "blocking",
|
|
167
|
+
"status": "open"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"id": "provider-pending",
|
|
171
|
+
"message": "No approved design cases, actual provider or browser evidence are supplied.",
|
|
172
|
+
"severity": "blocking",
|
|
173
|
+
"status": "open"
|
|
174
|
+
}
|
|
175
|
+
],
|
|
176
|
+
"presentation": {
|
|
177
|
+
"fontFamily": "Inter"
|
|
178
|
+
},
|
|
179
|
+
"summary": "Connect the reset flow to application responsibilities.",
|
|
180
|
+
"description": "This unapproved integration proposal links the synthetic journey to a route, form, service contract, feedback states and verification work. No application code, API or browser behavior has been inspected. Every proposed responsibility needs project evidence and review before implementation."
|
|
181
|
+
}
|