Last Update
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$initArtifactsScript = Join-Path $root "scripts/wireframe/init-artifacts.ps1"
|
||||
$extractScript = Join-Path $root "scripts/wireframe/extract-documents.ps1"
|
||||
$validateScript = Join-Path $root "scripts/wireframe/validate-artifacts.ps1"
|
||||
$initWorkspaceScript = Join-Path $root "scripts/system/init-workspace.ps1"
|
||||
$exportUpdateScript = Join-Path $root "scripts/system/export-update-package.ps1"
|
||||
$applyUpdateScript = Join-Path $root "scripts/system/apply-hot-update.ps1"
|
||||
$newBugReportScript = Join-Path $root "scripts/system/new-bug-report.ps1"
|
||||
$fixtureDocs = Join-Path $root "tests/fixtures/docs"
|
||||
$fixtureArtifacts = Join-Path $root "tests/fixtures/artifacts"
|
||||
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("wireframe-gen-test-" + [guid]::NewGuid().ToString())
|
||||
|
||||
function Copy-FixtureArtifacts {
|
||||
param([string]$Destination)
|
||||
New-Item -ItemType Directory -Force -Path $Destination | Out-Null
|
||||
Get-ChildItem -LiteralPath $fixtureArtifacts -Force | ForEach-Object {
|
||||
Copy-Item -LiteralPath $_.FullName -Destination $Destination -Recurse -Force
|
||||
}
|
||||
}
|
||||
|
||||
function Write-Blueprints {
|
||||
param(
|
||||
[object]$Blueprints,
|
||||
[string]$ArtifactDir
|
||||
)
|
||||
$path = Join-Path $ArtifactDir "screen_blueprints.json"
|
||||
$Blueprints | ConvertTo-Json -Depth 20 | Set-Content -LiteralPath $path -Encoding UTF8
|
||||
}
|
||||
|
||||
function Write-NormalizedProject {
|
||||
param(
|
||||
[object]$Project,
|
||||
[string]$ArtifactDir
|
||||
)
|
||||
$path = Join-Path $ArtifactDir "normalized_project.json"
|
||||
$Project | ConvertTo-Json -Depth 20 | Set-Content -LiteralPath $path -Encoding UTF8
|
||||
}
|
||||
|
||||
function Expect-ValidationFailure {
|
||||
param(
|
||||
[string]$Name,
|
||||
[scriptblock]$Mutate,
|
||||
[string]$Stage = "schema"
|
||||
)
|
||||
$caseDir = Join-Path $tempDir $Name
|
||||
Copy-FixtureArtifacts -Destination $caseDir
|
||||
& $Mutate $caseDir
|
||||
$oldErrorActionPreference = $ErrorActionPreference
|
||||
$ErrorActionPreference = "Continue"
|
||||
try {
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $validateScript -ArtifactDir $caseDir -Strict -Stage $Stage *> $null
|
||||
$exitCode = $LASTEXITCODE
|
||||
}
|
||||
finally {
|
||||
$ErrorActionPreference = $oldErrorActionPreference
|
||||
}
|
||||
if ($exitCode -eq 0) {
|
||||
throw "Expected validation failure for $Name"
|
||||
}
|
||||
}
|
||||
|
||||
function Expect-ValidationSuccess {
|
||||
param(
|
||||
[string]$Name,
|
||||
[scriptblock]$Mutate,
|
||||
[string]$Stage = "schema"
|
||||
)
|
||||
$caseDir = Join-Path $tempDir $Name
|
||||
Copy-FixtureArtifacts -Destination $caseDir
|
||||
& $Mutate $caseDir
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $validateScript -ArtifactDir $caseDir -Strict -Stage $Stage | Out-Null
|
||||
}
|
||||
|
||||
function Assert-PathExists {
|
||||
param([string]$Path)
|
||||
if (-not (Test-Path -LiteralPath $Path)) {
|
||||
throw "Expected path to exist: $Path"
|
||||
}
|
||||
}
|
||||
|
||||
function Assert-PathMissing {
|
||||
param([string]$Path)
|
||||
if (Test-Path -LiteralPath $Path) {
|
||||
throw "Expected path to be absent: $Path"
|
||||
}
|
||||
}
|
||||
|
||||
function Assert-Equal {
|
||||
param(
|
||||
[object]$Actual,
|
||||
[object]$Expected,
|
||||
[string]$Message
|
||||
)
|
||||
if ($Actual -ne $Expected) {
|
||||
throw "$Message Expected '$Expected', got '$Actual'"
|
||||
}
|
||||
}
|
||||
|
||||
function Copy-DirectoryContents {
|
||||
param(
|
||||
[string]$Source,
|
||||
[string]$Destination
|
||||
)
|
||||
New-Item -ItemType Directory -Force -Path $Destination | Out-Null
|
||||
Get-ChildItem -LiteralPath $Source -Force | ForEach-Object {
|
||||
Copy-Item -LiteralPath $_.FullName -Destination $Destination -Recurse -Force
|
||||
}
|
||||
}
|
||||
|
||||
function Assert-PackageHasNoPreservedFiles {
|
||||
param([object]$PackageManifest)
|
||||
foreach ($file in @($PackageManifest.files)) {
|
||||
$path = ([string]$file.path) -replace "\\", "/"
|
||||
foreach ($blocked in @("workspace", "artifacts", "maintenance", "dist")) {
|
||||
if ($path -eq $blocked -or $path.StartsWith("$blocked/")) {
|
||||
throw "Package should not include preserved path: $path"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$defaultCase = Join-Path $tempDir "default-paths"
|
||||
New-Item -ItemType Directory -Force -Path $defaultCase | Out-Null
|
||||
Push-Location $defaultCase
|
||||
try {
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $initArtifactsScript | Out-Null
|
||||
Assert-PathExists (Join-Path $defaultCase "workspace/artifacts/wireframe-gen/source_inventory.json")
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $validateScript -Strict | Out-Null
|
||||
}
|
||||
finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
$legacyArtifactDir = Join-Path $tempDir "legacy-artifact-dir"
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $initArtifactsScript -ArtifactDir $legacyArtifactDir | Out-Null
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $validateScript -ArtifactDir $legacyArtifactDir -Strict | Out-Null
|
||||
|
||||
$legacySource = Join-Path $tempDir "legacy-source/artifacts/wireframe-gen"
|
||||
Copy-FixtureArtifacts -Destination $legacySource
|
||||
$workspaceRoot = Join-Path $tempDir "client-workspace"
|
||||
$workspaceArtifacts = Join-Path $workspaceRoot "artifacts/wireframe-gen"
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $initWorkspaceScript -WorkspaceDir $workspaceRoot -ArtifactDir $workspaceArtifacts -LegacyArtifactDir $legacySource | Out-Null
|
||||
Assert-PathExists (Join-Path $workspaceArtifacts "source_inventory.json")
|
||||
Assert-PathExists (Join-Path $workspaceRoot "system-feedback/bug-reports")
|
||||
Assert-PathExists (Join-Path $workspaceRoot ".hot-update/backups")
|
||||
Assert-PathExists (Join-Path $legacySource "source_inventory.json")
|
||||
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $extractScript -InputPath $fixtureDocs -OutputDir $tempDir | Out-Null
|
||||
$inventoryPath = Join-Path $tempDir "source_inventory.json"
|
||||
if (-not (Test-Path -LiteralPath $inventoryPath)) {
|
||||
throw "source_inventory.json was not created"
|
||||
}
|
||||
|
||||
$inventory = Get-Content -LiteralPath $inventoryPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
if (@($inventory.sources).Count -lt 2) {
|
||||
throw "Expected at least 2 extracted fixture sources"
|
||||
}
|
||||
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $validateScript -ArtifactDir $fixtureArtifacts -Strict | Out-Null
|
||||
|
||||
Expect-ValidationFailure "legacy-open-question-blocks-pre-figma" {
|
||||
param($caseDir)
|
||||
} -Stage "pre-figma"
|
||||
|
||||
Expect-ValidationSuccess "resolved-open-question-passes-pre-ux" {
|
||||
param($caseDir)
|
||||
} -Stage "pre-ux"
|
||||
|
||||
Expect-ValidationFailure "unresolved-open-question-blocks-pre-ux" {
|
||||
param($caseDir)
|
||||
$project = Get-Content -LiteralPath (Join-Path $caseDir "normalized_project.json") -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
$project.open_questions += [pscustomobject]@{
|
||||
id = "Q-003"
|
||||
question = "Which navigation model should be used?"
|
||||
status = "unresolved"
|
||||
blocks = @("ux-construction")
|
||||
default_assumption = ""
|
||||
answer = ""
|
||||
answered_at = ""
|
||||
source_refs = @()
|
||||
}
|
||||
Write-NormalizedProject -Project $project -ArtifactDir $caseDir
|
||||
} -Stage "pre-ux"
|
||||
|
||||
Expect-ValidationFailure "bad-screen-width" {
|
||||
param($caseDir)
|
||||
$blueprints = Get-Content -LiteralPath (Join-Path $caseDir "screen_blueprints.json") -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
$blueprints[0].viewport.width = 1436
|
||||
Write-Blueprints -Blueprints $blueprints -ArtifactDir $caseDir
|
||||
}
|
||||
|
||||
Expect-ValidationFailure "bad-screen-height" {
|
||||
param($caseDir)
|
||||
$blueprints = Get-Content -LiteralPath (Join-Path $caseDir "screen_blueprints.json") -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
$blueprints[0].viewport.height = 796
|
||||
Write-Blueprints -Blueprints $blueprints -ArtifactDir $caseDir
|
||||
}
|
||||
|
||||
Expect-ValidationFailure "missing-element-parent" {
|
||||
param($caseDir)
|
||||
$blueprints = Get-Content -LiteralPath (Join-Path $caseDir "screen_blueprints.json") -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
$blueprints[1].PSObject.Properties.Remove("parent_screen_id")
|
||||
Write-Blueprints -Blueprints $blueprints -ArtifactDir $caseDir
|
||||
}
|
||||
|
||||
Expect-ValidationFailure "fractional-spacing" {
|
||||
param($caseDir)
|
||||
$blueprints = Get-Content -LiteralPath (Join-Path $caseDir "screen_blueprints.json") -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
$blueprints[0].sections[0].padding = 32.5
|
||||
Write-Blueprints -Blueprints $blueprints -ArtifactDir $caseDir
|
||||
}
|
||||
|
||||
Expect-ValidationFailure "bad-element-size" {
|
||||
param($caseDir)
|
||||
$blueprints = Get-Content -LiteralPath (Join-Path $caseDir "screen_blueprints.json") -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
$blueprints[1].bounds.width = 13
|
||||
Write-Blueprints -Blueprints $blueprints -ArtifactDir $caseDir
|
||||
}
|
||||
|
||||
$packageOutput = Join-Path $tempDir "packages"
|
||||
$exportOutput = powershell -NoProfile -ExecutionPolicy Bypass -File $exportUpdateScript -OutputDir $packageOutput
|
||||
$packagePath = @($exportOutput)[-1]
|
||||
Assert-PathExists $packagePath
|
||||
$packageManifestPath = Join-Path $packagePath "package-manifest.json"
|
||||
Assert-PathExists $packageManifestPath
|
||||
$packageManifest = Get-Content -LiteralPath $packageManifestPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
Assert-PackageHasNoPreservedFiles -PackageManifest $packageManifest
|
||||
|
||||
$clientRoot = Join-Path $tempDir "client-copy"
|
||||
Copy-DirectoryContents -Source $packagePath -Destination $clientRoot
|
||||
$clientAgents = Join-Path $clientRoot "AGENTS.md"
|
||||
Set-Content -LiteralPath $clientAgents -Value "old system instructions" -Encoding UTF8 -NoNewline
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $clientRoot "workspace/artifacts/wireframe-gen") | Out-Null
|
||||
Set-Content -LiteralPath (Join-Path $clientRoot "workspace/artifacts/wireframe-gen/client-data.txt") -Value "do not touch" -Encoding UTF8 -NoNewline
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $clientRoot "maintenance") | Out-Null
|
||||
Set-Content -LiteralPath (Join-Path $clientRoot "maintenance/origin-only.txt") -Value "do not touch" -Encoding UTF8 -NoNewline
|
||||
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $applyUpdateScript -PackagePath $packagePath -TargetRoot $clientRoot -DryRun | Out-Null
|
||||
Assert-Equal (Get-Content -LiteralPath $clientAgents -Raw -Encoding UTF8) "old system instructions" "Dry-run must not mutate system files."
|
||||
Assert-PathMissing (Join-Path $clientRoot "workspace/.hot-update/last-apply.json")
|
||||
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $applyUpdateScript -PackagePath $packagePath -TargetRoot $clientRoot | Out-Null
|
||||
$sourceAgents = Get-Content -LiteralPath (Join-Path $packagePath "AGENTS.md") -Raw -Encoding UTF8
|
||||
$updatedAgents = Get-Content -LiteralPath $clientAgents -Raw -Encoding UTF8
|
||||
Assert-Equal $updatedAgents $sourceAgents "Hot Update must replace allowlisted system files."
|
||||
Assert-Equal (Get-Content -LiteralPath (Join-Path $clientRoot "workspace/artifacts/wireframe-gen/client-data.txt") -Raw -Encoding UTF8) "do not touch" "Hot Update must preserve workspace files."
|
||||
Assert-Equal (Get-Content -LiteralPath (Join-Path $clientRoot "maintenance/origin-only.txt") -Raw -Encoding UTF8) "do not touch" "Hot Update must preserve maintenance files."
|
||||
Assert-PathExists (Join-Path $clientRoot "workspace/.hot-update/last-apply.json")
|
||||
$backupAgents = Get-ChildItem -LiteralPath (Join-Path $clientRoot "workspace/.hot-update/backups") -Recurse -File -Filter "AGENTS.md" | Select-Object -First 1
|
||||
if ($null -eq $backupAgents) {
|
||||
throw "Expected Hot Update to create a backup for overwritten AGENTS.md"
|
||||
}
|
||||
Assert-Equal (Get-Content -LiteralPath $backupAgents.FullName -Raw -Encoding UTF8) "old system instructions" "Backup should contain the previous file content."
|
||||
|
||||
$bugWorkspace = Join-Path $tempDir "bug-workspace"
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File $newBugReportScript `
|
||||
-WorkspaceDir $bugWorkspace `
|
||||
-Title "Validation does not block bad screen" `
|
||||
-Area "validation" `
|
||||
-Expected "Validation fails when a screen is underspecified." `
|
||||
-Actual "Validation passed." `
|
||||
-TriggerContext "During sanitized fixture checks." `
|
||||
-ReproSteps "Run validation; observe success" `
|
||||
-Impact "Incorrect downstream wireframes" | Out-Null
|
||||
|
||||
$reportJsonPath = Get-ChildItem -LiteralPath (Join-Path $bugWorkspace "system-feedback/bug-reports") -Recurse -File -Filter "report.json" | Select-Object -First 1
|
||||
if ($null -eq $reportJsonPath) {
|
||||
throw "Expected bug report JSON to be created."
|
||||
}
|
||||
$report = Get-Content -LiteralPath $reportJsonPath.FullName -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
foreach ($field in @("id", "created_at", "system_version", "area", "severity", "trigger_context", "actual_behavior", "expected_behavior", "repro_steps", "impact", "workaround", "depersonalization_notes", "privacy_confirmed")) {
|
||||
if (-not ($report.PSObject.Properties.Name -contains $field)) {
|
||||
throw "Bug report missing required field: $field"
|
||||
}
|
||||
}
|
||||
Assert-PathExists (Join-Path $reportJsonPath.Directory.FullName "report.md")
|
||||
Assert-PathExists (Join-Path $reportJsonPath.Directory.FullName "sanitized-snippets")
|
||||
|
||||
Write-Output "Wireframe checks passed"
|
||||
}
|
||||
finally {
|
||||
if (Test-Path -LiteralPath $tempDir) {
|
||||
Remove-Item -LiteralPath $tempDir -Recurse -Force
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"file_key": "test-file-key",
|
||||
"page": "Wireframes",
|
||||
"screen_ids": ["screen-project-review"],
|
||||
"created_node_ids": ["1:2"],
|
||||
"mutated_node_ids": [],
|
||||
"annotation_node_ids": ["1:9"],
|
||||
"screenshots": [
|
||||
{
|
||||
"screen_id": "screen-project-review",
|
||||
"node_id": "1:2",
|
||||
"path": "workspace/artifacts/wireframe-gen/screenshots/screen-project-review.png"
|
||||
}
|
||||
],
|
||||
"validation_notes": [
|
||||
{
|
||||
"screen_id": "screen-project-review",
|
||||
"status": "pass",
|
||||
"notes": "Fixture manifest only."
|
||||
}
|
||||
],
|
||||
"known_issues": []
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"project": {
|
||||
"id": "PRJ-001",
|
||||
"name": "Wireframe Gen",
|
||||
"description": "Generate editable Figma wireframes from text documentation."
|
||||
},
|
||||
"audiences": [
|
||||
{
|
||||
"id": "AUD-001",
|
||||
"name": "Product teams",
|
||||
"source_refs": ["SRC-001#users"]
|
||||
}
|
||||
],
|
||||
"goals": [
|
||||
{
|
||||
"id": "GOAL-001",
|
||||
"statement": "Create traceable wireframes from source documentation.",
|
||||
"confidence": "high",
|
||||
"source_refs": ["SRC-001#goals"]
|
||||
}
|
||||
],
|
||||
"actors": [
|
||||
{
|
||||
"id": "ACT-001",
|
||||
"name": "Product manager",
|
||||
"source_refs": ["SRC-001#users"]
|
||||
}
|
||||
],
|
||||
"functional_modules": [
|
||||
{
|
||||
"id": "MOD-001",
|
||||
"name": "Documentation intake",
|
||||
"requirements": ["REQ-001"],
|
||||
"source_refs": ["SRC-001#core-requirements"]
|
||||
}
|
||||
],
|
||||
"entities": [
|
||||
{
|
||||
"id": "ENT-001",
|
||||
"name": "Source document",
|
||||
"source_refs": ["SRC-001#core-requirements"]
|
||||
}
|
||||
],
|
||||
"rules": [
|
||||
{
|
||||
"id": "RULE-001",
|
||||
"statement": "Every requirement must preserve source traceability.",
|
||||
"confidence": "high",
|
||||
"source_refs": ["SRC-002#line-1"]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"id": "CON-001",
|
||||
"statement": "Schema keys stay in English.",
|
||||
"source_refs": ["SRC-002#line-2"]
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
{
|
||||
"id": "RISK-001",
|
||||
"statement": "Figma target file can be missing.",
|
||||
"source_refs": ["SRC-002#line-4"]
|
||||
}
|
||||
],
|
||||
"open_questions": [
|
||||
{
|
||||
"id": "Q-001",
|
||||
"question": "Which Figma file should receive generated screens?",
|
||||
"blocks": ["figma-build"],
|
||||
"source_refs": ["SRC-002#line-4"]
|
||||
},
|
||||
{
|
||||
"id": "Q-002",
|
||||
"question": "Which user role should be used for first UX construction?",
|
||||
"status": "answered",
|
||||
"blocks": ["ux-construction"],
|
||||
"default_assumption": "Use the primary product manager role.",
|
||||
"answer": "Use ACT-001 as the primary role for the first UX pass.",
|
||||
"answered_at": "2026-05-03T00:00:00Z",
|
||||
"source_refs": ["SRC-001#users"]
|
||||
}
|
||||
],
|
||||
"source_trace": [
|
||||
{
|
||||
"source_ref": "SRC-001#goals",
|
||||
"path": "tests/fixtures/docs/product.md",
|
||||
"excerpt": "Normalize scattered documentation into one product model."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
[
|
||||
{
|
||||
"content_type": "screen",
|
||||
"screen_id": "screen-project-review",
|
||||
"viewport": {
|
||||
"width": 1440,
|
||||
"height": 800
|
||||
},
|
||||
"purpose": "Review normalized requirements and blockers.",
|
||||
"sections": [
|
||||
{
|
||||
"id": "section-summary",
|
||||
"name": "Summary",
|
||||
"requirements": ["RULE-001"],
|
||||
"padding": 32,
|
||||
"gap": 24
|
||||
}
|
||||
],
|
||||
"components": ["app-shell", "status-list", "open-question-list"],
|
||||
"states": ["default", "loading", "error", "empty"],
|
||||
"content_requirements": ["Show source count", "Show unresolved questions"],
|
||||
"interactions": ["Continue to UX construction"],
|
||||
"empty_error_loading_states": ["No sources", "Extraction failed", "Validation running"]
|
||||
},
|
||||
{
|
||||
"content_type": "element",
|
||||
"element_id": "element-project-review-open-question-card",
|
||||
"parent_screen_id": "screen-project-review",
|
||||
"bounds": {
|
||||
"x": 320,
|
||||
"y": 240,
|
||||
"width": 480,
|
||||
"height": 160
|
||||
},
|
||||
"purpose": "Show one unresolved question with impact and next action.",
|
||||
"states": ["default", "resolved"],
|
||||
"components": ["question-card", "status-badge", "secondary-action"],
|
||||
"content_requirements": ["Question text", "Blocking area", "Resolution action"],
|
||||
"interactions": ["Mark resolved", "Open related source"]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"generated_at": "2026-05-03T00:00:00Z",
|
||||
"input_path": "tests/fixtures/docs",
|
||||
"output_dir": "artifacts/test-extracted",
|
||||
"sources": [
|
||||
{
|
||||
"source_id": "SRC-001",
|
||||
"path": "tests/fixtures/docs/product.md",
|
||||
"type": "md",
|
||||
"status": "ok",
|
||||
"extracted_text_path": "artifacts/test-extracted/SRC-001-product.txt",
|
||||
"character_count": 640,
|
||||
"notes": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"information_architecture": [
|
||||
{
|
||||
"id": "IA-001",
|
||||
"name": "Project workspace",
|
||||
"children": ["Documentation", "UX Spec", "Wireframes"]
|
||||
}
|
||||
],
|
||||
"user_flows": [
|
||||
{
|
||||
"id": "FLOW-001",
|
||||
"name": "Generate first wireframes",
|
||||
"actor_id": "ACT-001",
|
||||
"steps": ["Add docs", "Review normalized project", "Generate UX spec", "Build Figma"],
|
||||
"success_outcome": "Editable Figma screens are created."
|
||||
}
|
||||
],
|
||||
"screen_inventory": [
|
||||
{
|
||||
"screen_id": "screen-project-review",
|
||||
"name": "Project Review",
|
||||
"requirement_refs": ["RULE-001"]
|
||||
}
|
||||
],
|
||||
"screen_purposes": [
|
||||
{
|
||||
"screen_id": "screen-project-review",
|
||||
"purpose": "Let the user review normalized requirements before UX construction."
|
||||
}
|
||||
],
|
||||
"ux_decisions": [
|
||||
{
|
||||
"id": "UXD-001",
|
||||
"decision": "Show extraction and validation status before Figma generation.",
|
||||
"rationale": "Users need feedback about system status.",
|
||||
"citation_ids": ["nng-heuristics"],
|
||||
"source_refs": ["RULE-001"]
|
||||
}
|
||||
],
|
||||
"research_citations": [
|
||||
{
|
||||
"registry_id": "nng-heuristics",
|
||||
"title": "10 Usability Heuristics for User Interface Design",
|
||||
"url": "https://www.nngroup.com/articles/ten-usability-heuristics/",
|
||||
"claim": "Systems should keep users informed about status.",
|
||||
"used_for": ["UXD-001"]
|
||||
}
|
||||
],
|
||||
"acceptance_criteria": [
|
||||
{
|
||||
"id": "AC-001",
|
||||
"screen_id": "screen-project-review",
|
||||
"criterion": "The screen shows source extraction status and open questions."
|
||||
}
|
||||
]
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
# Product Brief
|
||||
|
||||
The system helps product teams generate editable Figma wireframes from project documentation.
|
||||
|
||||
## Goals
|
||||
|
||||
- Normalize scattered documentation into one product model.
|
||||
- Create UX architecture and screen blueprints before visual generation.
|
||||
- Build mid-fidelity Figma screens through native Figma MCP.
|
||||
|
||||
## Users
|
||||
|
||||
- Product manager
|
||||
- UX designer
|
||||
- Solution architect
|
||||
|
||||
## Core Requirements
|
||||
|
||||
- Users can upload or select documentation files.
|
||||
- Users can review normalized requirements and open questions.
|
||||
- Users can generate UX screen blueprints.
|
||||
- Users can create editable Figma wireframes.
|
||||
@@ -0,0 +1,4 @@
|
||||
Requirement: Preserve source traceability from every requirement to the original source document.
|
||||
Requirement: Keep schema keys in English.
|
||||
Requirement: Produce Russian human-readable summaries by default.
|
||||
Risk: Figma target file may be unknown until the user provides a file key.
|
||||
Reference in New Issue
Block a user