Skip to content

Des2WF Generation Result Collection

Overview

The des2wf generation output collection โ€” one document per des2wf run, holding the emitted wireframe spec, the score that graded it, the flag count, the run lineage, and the post-render review once the plugin posts its render pair. The des2wf worker writes it at the end of the single parse โ†’ assemble invocation (fenced on (_id, attempt)); des2wf-api reads it for materialization, and the render-review pass amends the same document in place. It is separate from design_generation_result because the two edges answer different shapes โ€” a wireframe spec + score against a design spec + confidence โ€” and one collection holding both would make every reader branch on the edge.

Table Definition

Logical Name Physical Name Column Name Data Type Primary Key Relation Unique Nullable Default Value Remarks
Des2WF Generation Result des2wf_generation_result _id string โ—ฏ wf2des:id The shared wf2des PG row id (the run identity โ€” one result doc per run, 1:1 with the row, same value as job_id). The row id is globally unique across BOTH edges, which is what keeps the plugin's single (jobId โ†’ rootNodeId) idempotency index safe by construction. CAS write fence on (_id, attempt)
edge string des2wf The tagged-union discriminator โ€” always des2wf on this collection. Dispatch and readers route on it, NEVER on which optional field happens to be populated: two families whose documents differ only by a populated field cannot be told apart safely
organization_id number Tenant owner; every read/write filters it
project_id number project:id Tenancy scope; every read/write filters it
job_id string wf2des:id The producing run id โ€” the same shared wf2des row id as _id, carried as a field so the document is self-describing when read outside its key
attempt number The run attempt โ€” the write fence (CAS on (_id, attempt)) compares it to reject a superseded write, so an SQS redelivery whose older invocation finishes last cannot publish the loser's spec under the winner's job id
figma_file_key string The Figma file the design frame lives in (Figma verbatim; alphanumeric, no underscore)
source_node_id string The DESIGN frame โ€” the input node the run was asked to wireframe
spec object Self-contained {spec_version, edge, source_name, source_file_key?, name?, root}. No style_bindings or parse_confirmed; source geometry is opt-in.
spec.spec_version string 1.0 The materializer wire-contract version
spec.edge string des2wf Literal edge for naming and materializer behavior
spec.source_name string empty string Original frame name
spec.source_file_key string โ—ฏ Pinned Figma file for source glyph/text lookup; optional for legacy results
spec.name string โ—ฏ null Explicit canvas name override; otherwise des2wf ยท source_name (spec-version fallback)
spec.root object The existing five cases: layout_frame / instance / compose / text / unmatched. Layout frames may carry placeholder=image, glyph_source and children; instances carry kit identity, slots and DestylePolicy; text carries literal copy and typography. Shared optional source_layout and text_geometry are specified below.
score object ds@1.0 โ€” an emittability GATE times content preservation, versioned. Computed from the artifacts rather than reported by a model about itself, because this product has no human-correction loop and quality converges machine-side through a ratchet. Only score + score_version reach PostgreSQL; the band stays here, where the ratchet reads it. Shape: { score, score_version, gate, band, terms }
score.score number gate ร— weighted sum of the scoring terms, rounded to 4 digits
score.score_version string ds@1.0 The formula version the score was computed under. Bumped on ANY change to a term, a weight or the gate; nothing compares across versions โ€” it is traceability
score.gate number 0 / 1. 0 on any unmatched node, on any non-zero strings_invented / text_displaced / cross_over_text / boxes_coincident, and on depth beyond flat for the absolute layout only โ€” an auto layout nests on purpose, so gating its depth would score a run 0 for doing exactly what it was asked. A 0 gate drives the whole score to 0: a wireframe with a hole in it is not a partially good wireframe. strings_lost is deliberately NOT gated โ€” content preservation already grades it
score.band object {low, high, margin}; margin 0.07 when kit selection or graphic classification sets llm_assisted, otherwise 0.0. The mode alone does not imply determinism.
score.terms object[] [] [{ name, value, weight }] โ€” every term kept with its own value so a regression is attributable. content_preservation at weight 1.0: the share of the design's strings that appear in the output verbatim, compared as a MULTISET, so a screen that says "Next" three times must still say it three times. integrity, flatness, ink_covered and boundary_fidelity are reported at weight 0.0 โ€” visible and attributable, moving nothing until there is evidence for what they should be worth
flag_count number 0 Flagged + unmatched nodes โ€” "how many cells need review". Keeps its wf2des meaning so the shared backend validator stays a single shape; reaches the wf2des row through the manifest row_effects.wf2des
graphic_classification object {} Per-appearance classification audit; empty for older results. Distinct from human override storage and post-render review
graphic_classification.prompt_version string Current classifier prompt: des2wf-graphics-visual-2
graphic_classification.model string Configured classifier model
graphic_classification.status string not-needed / fallback / partial / complete; complete may include human overrides, not necessarily a model verdict for every node
graphic_classification.source_render_sha256 string โ—ฏ Source PNG hash, or null without evidence
graphic_classification.candidate_count number Number of graphic candidates
graphic_classification.decisions object[] [] node_id, applied action, status and reason; optional evidence_sha256, proposal, rendered_kind, rendered_reason, covered_by. See I/O Definition for the nested shape
graphic_classification.fallback_count number โ—ฏ Absent on no-candidate early return
graphic_classification.simplified_count number โ—ฏ Applied simplify decisions, including decoration; not the number of visible placeholder nodes. Absent on no-candidate early return
render_review object โ—ฏ The post-render review block โ€” the pass the score cannot do, because the score is computed BEFORE anything is drawn, on structural proxies, and cannot see an overlap, a clipped string or a missing element on the rendered canvas. One vision call over the design frame's PNG beside the built wireframe's PNG. Absent until the plugin posts its render pair; post-terminal by design, so it amends a finished run rather than advancing a phase. Shape: { status, finding_count, summary, findings, prompt_version, model, checked_at }
render_review.status string reviewed / skipped. A render the vision model would refuse is a fact about the render, not a failure to retry, and is recorded as skipped with skipped_reason and a NULL finding_count โ€” so nothing can read "no findings" off a pass that never ran
render_review.finding_count number โ—ฏ Findings reported; NULL on skipped
render_review.summary string One sentence of overall judgement; empty on skipped
render_review.findings object[] [] [{ kind, severity, location, description }]. kind: overlap / overflow / clipped_text / missing_element / extra_element / other; severity: high / medium / low; description is one sentence on what is wrong on the rendered wireframe
render_review.skipped_reason string โ—ฏ Why the pass did not run; present only on status: "skipped"
render_review.prompt_version string The review prompt version
render_review.model string The reviewing model id
render_review.checked_at datetime When the review ran
render_review_previous object โ—ฏ The review block this document carried before the current one โ€” a re-review MERGES rather than replacing silently, so the ratchet can compare across runs. Absent until a second review lands; same shape as render_review
lineage object Shared lineage block on every doc (source S3 key/hash, processor version, processed time). job_id = the producing RUN id โ€” the shared wf2des row id. Shape: { source_url, source_hash, processor_version, index_schema_version, processed_at, job_id }
lineage.source_url string The RAW design snapshot S3 key โ€” the full per-node REST envelope, maps retained
lineage.source_hash string sha256 of the design FRAME subtree, computed at capture (the parse-cache key)
lineage.processor_version string Producing processor version (e.g. des2wf@0.1)
lineage.index_schema_version string 1.1 Document schema version for this collection
lineage.processed_at datetime Terminal-write timestamp
lineage.job_id string wf2des:id The producing run id

Source geometry

The five spec cases are unchanged. Optional source_layout carries horizontal/vertical FIXED/HUG/FILL sizing, AUTO/ABSOLUTE positioning, strokes_in_layout, hidden state and per-axis min/max dimensions. Optional text-node text_geometry carries font_family, auto_resize, line_height, line_height_pct, letter_spacing, leading_trim, vertical_align, paragraph_spacing and paragraph_indent. Legacy results without these fields retain the previous materializer behavior.

A layout frame's glyph_source points to source artwork. Materialization is scoped by spec.source_file_key and preserves the actual instance's overrides. placeholder=image means approved simplification, not a blanket rule for every icon. Decoration can intentionally emit no paint. See I/O Definition for contracts and audit field details.

Relations

  • _id = the shared wf2des PostgreSQL row id โ€” 1:1 with the row (the backend creates the row first, the worker writes the doc). The same value appears as job_id and lineage.job_id.
  • project_id โ†’ project.id; organization_id โ†’ the tenant owner.
  • {figma_file_key, source_node_id} locate the DESIGN frame the run read.
  • The wireframe the run emitted is the wireframe doc under the EDGE-SCOPED _id = {project_id}_{figma_file_key}_{node_id}~des2wf โ€” wf_parse keeps the unsuffixed id for the same frame, so the two edges cannot overwrite each other.
  • spec.root instance nodes name a wireframe-kit VARIANT: component_key / component_node_id come from wireframe_component. platform_design_id on this edge carries the design node the atom stands in for, not a registry key.
  • No relation is enforced inside DocumentDB; relations are logical and validated by application code.

Indexes

  • PRIMARY KEY (_id) โ€” unique; _id IS the shared wf2des row id (no surrogate).
  • The run commit is a CAS on (_id, attempt) โ€” it matches attempt โ‰ค the committing attempt and upserts, so a redelivered older attempt cannot overwrite a newer one (not a DB unique index; enforced by the worker's conditional write).
  • Review checks organization/project scope on the existing result before image or model work. Its merge does not upsert: unknown results raise rather than creating a result document.
  • No secondary indexes are defined; reads are by _id within the tenancy filter.

Notes

  • The worker writes generation artifacts, the wireframe output, this result and the manifest before terminal success. The backend webhook alone applies completion, score/version and flags to PG from row_effects.wf2des.
  • Both primitives and kit can use contextual graphic classification. Only kit adds variant selection; missing kit data falls back to primitives. Uncertain graphics preserve their source shape. Approved nonessential imagery becomes ink; confirmed decoration becomes ornament.
  • The API defaults to layout=absolute; the current plugin explicitly sends layout=auto, retaining source hierarchy, native item spacing, one-child wrappers and sizing.
  • The plugin names the canvas frame des2wf ยท {source_name} unless spec.name overrides it. The separate WireframeDoc.name still uses wf ยท {design frame name}.
  • Generation's optional version-pinned source PNG is not the plugin's post-terminal review pair. Review submission requires matching job ID, scoped write access and a COMPLETED row before upload. The pair remains bound to the original source/project; review failure does not undo generation.
  • graphic_classification records proposals and final rendered coverage separately. A simplified child can remain visually covered by a preserved parent; read rendered_kind/covered_by, not only the proposal. Human graphic_override_v1 records live in des2wf_verdict, not here.
  • Read the result in full. Truncating the spec through a generic bounded-document path can silently materialize only part of the wireframe.
  • A 1.0 structural/content score is not an icon-accuracy or visual-quality pass. Model stubs and the JSON-only offline corpus cannot establish visual recognition accuracy; inspect real-provider output on the canvas.