AI Code2WF — テストケース
これらのcaseはCode2WF I/O定義のMVP契約を検証します。Page build/capture testはPage Importの責務です。すべてのcontract areaは以下の少なくとも1つのcaseに対応する必要があり、下記のカバレッジマトリクスがtraceability indexです。
規約: Test IDはC2W-<area>-<NN>形式を使い、areaはtrigger(T)、queue/dispatch(Q)、source(S)、conversion(C)、idempotency/webhook(I)、result API(R)、Figma recovery(F)、authorization/security(A)です。期待結果列がassertion contractであり、そこに記載しないbehaviorはassertしません。
テスト層とツーリング
Default suiteはlocalかつdeterministicです。Deployed end-to-end checkはopt-in smoke testです。
| レイヤー |
スコープ |
ツール |
| Unit (U) |
Closed message/result schema、single-read source pin導出、source/lineage validation、deterministic conversionとannotation採番、共有DesignSpecModel serialization、limit、full-artifact validation |
pytest、networkなし。Storage、webhook clientはboundaryでfake |
| Component (C) |
Backend trigger/list/result/placement boundary、不変result + manifest publishまでのworker record 1件、webhook effect、plugin materialization/recovery |
既存backend/plugin test runner。Backend rowを扱う場合はephemeral PostgreSQL、artifact flowにはlocalstack S3/SQSを使い、webhook、Figma boundaryをmock |
| End-to-end (E) |
Deployed non-production backend、queue、worker、S3、PostgreSQL、authenticated Figma pluginのround-trip |
専用test dataと上限付きruntimeを使うopt-in smoke suite |
フィクスチャ
Partial dictionaryを手書きせず、共有fixtureからmessageとartifactを構築します。
| フィクスチャ |
用途 |
completed_page_import(...) |
Scoped completed Page Import rowと、不変normalized-manifest object 1件。Raw bytes、page_result_hash、capture_hashを制御可能 |
build_code2wf_message(**overrides) |
Code2WF identity、tenant、固定attempt、nonce、Page Import pin、screen_idを持つwell-formed closed SQS message |
page_result_bytes(**overrides) |
Backendのsingle verified readとworker source validationに使う正確なnormalized-manifest bytes |
design_spec(**overrides) |
共有defaultとboundary variantを含むcanonicalな既存DesignSpecModel tree |
code2wf_result_artifact(**overrides) |
Outer identity/status/time、Page Import inputs、nested specを持つ完全なworker artifact |
code2wf_terminal_manifest(**overrides) |
既存row_effects.code2wf contractを持つsuccess/failure manifest |
code2wf_row(status=..., materialized_at=...) |
Processing/completed/failed、materialized/unmaterialized状態のscoped backend row |
mock_ai_status(http_status=200) |
Terminal webhook envelopeをcaptureし、設定したresponseを返す |
figma_file_fixture(...) |
Current-page target、stale/cross-page target、prior stamped root、materializer failure variant |
カバレッジマトリクス
行はI/O定義のcontract areaです。定義済みの全case IDをこの表に含めます。
| 契約領域 |
正常系 |
異常系 |
冪等性 / Recovery |
| TriggerとPostgreSQL row |
C2W-T-01, C2W-T-04 |
C2W-T-02, C2W-T-03, C2W-T-05, C2W-T-06, C2W-T-08 |
C2W-T-04, C2W-T-07 |
| Dispatch messageとPage Import pin |
C2W-Q-01, C2W-Q-05 |
C2W-Q-02, C2W-Q-03, C2W-Q-04 |
C2W-Q-02, C2W-Q-05 |
| Worker source validation |
C2W-S-01, C2W-S-07 |
C2W-S-02, C2W-S-03, C2W-S-04, C2W-S-05, C2W-S-06 |
— |
| Conversionと共有spec |
C2W-C-01, C2W-C-02, C2W-C-03, C2W-C-04, C2W-C-06, C2W-C-08, C2W-C-09, C2W-C-13, C2W-C-14 |
C2W-C-05, C2W-C-07, C2W-C-10, C2W-C-11, C2W-C-12, C2W-C-15 |
C2W-C-02, C2W-C-08, C2W-C-13 |
| Immutable result、manifest、webhook |
C2W-I-04 |
C2W-I-03, C2W-I-05, C2W-I-07 |
C2W-I-01, C2W-I-02, C2W-I-06 |
| Result/list API |
C2W-R-01, C2W-R-05, C2W-R-06, C2W-R-08 |
C2W-R-02, C2W-R-03, C2W-R-04, C2W-R-07 |
— |
| Figma recoveryとplacement |
C2W-F-01, C2W-F-06, C2W-F-08, C2W-F-09, C2W-F-10, C2W-F-11, C2W-F-12, C2W-F-13, C2W-F-14, C2W-F-16 |
C2W-F-02, C2W-F-03, C2W-F-04, C2W-F-05, C2W-F-07, C2W-F-15, C2W-F-17 |
C2W-F-02, C2W-F-03, C2W-F-08, C2W-F-09, C2W-F-14, C2W-F-15, C2W-F-18 |
| Authorizationとsecurity |
— |
C2W-A-01, C2W-A-02, C2W-A-03, C2W-A-04, C2W-A-05 |
— |
1. TriggerとRow契約
| ID |
シナリオ |
期待結果 |
| C2W-T-01 |
有効な完了済みPage ImportとFigma field |
UUIDv7を生成し、status="0"、attempt=1 で code2wf 行を1件insertし、SQS messageを1件送る |
| C2W-T-02 |
Page Importがprocessing/failed |
409。Code2WF row/messageなし |
| C2W-T-03 |
Page Importがmissing/deleted/別scope |
404。row/messageなし |
| C2W-T-04 |
同一の有効なtrigger bodyを2回送信 |
backend生成rowを2件作成し、2 jobをdispatch |
| C2W-T-05 |
Requestが code2wfId を指定 |
400。caller生成job IDを受け付けない |
| C2W-T-06 |
Insert後にSQS send失敗 |
id/attempt/statusでprocessing rowをfailedへCAS。安全なerrorをpoll可能 |
| C2W-T-07 |
Dispatch failure後に新しいtrigger |
新しいrowを作成/dispatchし、failed rowを変更または再dispatchしない |
| C2W-T-08 |
Requestがstatus、attempt、result、materialization fieldを指定 |
400。server所有fieldを受け付けない |
Schema assertion: rowはWF2Desに揃えたfieldのみ、つまり id、organization/project、page_import_id、figma_file_key、screen_id、任意の placement_target、既存 wf2des_status enumを使う status、固定 attempt、result/error/flag field、materialized_at、共通audit fieldを使います。Page Import hash、Figma page ID、nonce、materialization state、node ID、retry ledgerは保存しません。
2. Dispatch契約
| ID |
シナリオ |
期待結果 |
| C2W-Q-01 |
Backendが有効jobをdispatch |
完了済みimportから解決した正確なPage Import result URL/hash/capture hashを含む |
| C2W-Q-02 |
Backendがdispatch用のcompleted Page Import pinを解決 |
不変normalized manifestを正確に1回readして検証し、その1回のreadからpage_result_url、page_result_hash、capture_hashを得る。Bytesがmissing/corruptならSQS dispatch前に失敗し、PostgreSQL/S3 transactionはassertしない |
| C2W-Q-03 |
Message attemptが 1 以外 |
Workerが invalid_message で拒否 |
| C2W-Q-04 |
MessageにFigma destinationまたはcredentialを含む |
Closed message validationが拒否 |
| C2W-Q-05 |
Valid message nonceを受信 |
Validate/logするが、保存せずrow CASにも使わない。Duplicate deliveryは不変resultを再利用 |
3. Source検証
| ID |
シナリオ |
期待結果 |
| C2W-S-01 |
Source bytesとlineageが有効 |
Conversion続行 |
| C2W-S-02 |
Result hashが異なる |
Terminal source_hash_mismatch。outputなし |
| C2W-S-03 |
Organization/project/Page Import IDが異なる |
Terminal source_scope_mismatch |
| C2W-S-04 |
Capture hashが異なる |
Terminal source_scope_mismatch |
| C2W-S-05 |
Source/objectがtenant/import prefix外 |
Terminal source_scope_mismatch |
| C2W-S-06 |
未対応Page Import schema |
Terminal unsupported_source_schema |
| C2W-S-07 |
元routeが利用不能 |
影響なし。workerは不変Page Import artifactのみ読む |
4. ConversionとSchema
| ID |
シナリオ |
期待結果 |
| C2W-C-01 |
Grouping、text、control、geometryが存在 |
既存 layout_frame / text nodeと一意な layer_path を持つ完全な既存 DesignSpecModel |
| C2W-C-02 |
取得済みlink/form/control evidenceが存在 |
Stable sibling markerと対応する決定的annotation textを出力し、original control labelは変更しない |
| C2W-C-03 |
推測interactionのevidenceがない |
挙動を創作しない |
| C2W-C-04 |
Button、input、その他の通常controlをmap |
既存nested layout_frame / text。新しいprimitive node caseなし |
| C2W-C-05 |
Media、overlap、transform、またはpositioning relationshipを既存nodeで表現できない |
flagged=true と source.kind="none" を持つ既存の可視 unmatched placeholder |
| C2W-C-06 |
有効なfinal compatibility field |
spec_version="1.0"、parse_confirmed=true、style_bindings={}、既存 SpecNode root |
| C2W-C-07 |
Unknown node discriminator |
共有discriminated-union validationが invalid_result を返し、publishしない |
| C2W-C-08 |
複数のevidence-backed annotation |
[A001] markerをnormalized DOM orderで決定的に採番 |
| C2W-C-09 |
Specにflagged/unmatched outcomeがある |
flag_count は既存spec内の flagged=true outcome数と一致 |
| C2W-C-10 |
Resultが固定structural limitを超過 |
Terminal result_limit_exceeded |
| C2W-C-11 |
UTF-8 resultが10 MiB超過 |
Terminal result_limit_exceeded |
| C2W-C-12 |
Code2WF producerがCode2WF専用spec field/collectionを出力しようとする |
Producer contract test失敗。既存共有modelのfieldだけを出力する |
| C2W-C-13 |
Valid specをserialize |
Exact DesignSpecModel.model_dump(mode="json") outputがlineage array、text style ref、nullable source component key、全auto-layout defaultなどの共有defaultを含む |
| C2W-C-14 |
Page Import documentがviewportより高い |
Screen bbox.hにfull document_heightを使用し、below-the-foldのvisible evidenceも表現する |
| C2W-C-15 |
Sourceにauto-layoutで保持できないabsolute/fixed/sticky overlapがある |
Absolute-position fieldを追加せず、可能な範囲でvisible orderを保持し、表現不可能なcontentにflagged unmatched placeholderを出力する |
Property testではboundary値の既存node unionを生成し、最大depth/node数、finite bounding box、一意path/marker、正確な DesignSpecModel validation/serialization、unknown discriminator拒否、既存共有fieldと一致するemitter allowlistを検証します。Regression testでは、Pydanticがextra object propertyを拒否するという誤ったassertionを置かず、現在の共有modelがそれらを無視する挙動も記録します。
5. Result IdempotencyとWebhook
| ID |
シナリオ |
期待結果 |
| C2W-I-01 |
同じSQS recordを2回delivery |
不変なresult/manifest pair 1件。両deliveryが同じmanifest URLへ収束 |
| C2W-I-02 |
Concurrent workerがconditional writeに負ける |
Winnerをread/validateし、winnerのterminal eventを送る |
| C2W-I-03 |
既存resultのlineageが異なる |
Fail closed。上書きしない |
| C2W-I-04 |
Processing rowへのvalid success webhook |
result_manifest_url を検証し、(id, attempt=1, status="0") をcompletedへCASし、内側の row_effects.code2wf.result_url とflag countを保存 |
| C2W-I-05 |
Processing rowへのvalid failure webhook |
同じCASでfailedへ変更し、failure manifestと安全なerrorを必須としてfailed-artifact result_url / error_message を保存。rowのflag_countはnullのまま |
| C2W-I-06 |
Terminal state後のduplicate/conflicting webhook |
Accepted no-op。terminal winnerは不変 |
| C2W-I-07 |
Webhook dependencyが一時的に利用不能 |
SQS recordをretry。workerはPostgreSQLへ書かない |
6. Result API
| ID |
シナリオ |
期待結果 |
| C2W-R-01 |
Completed rowと有効なresult artifact |
Outer job_id/tenant/attempt/screen/status/time、Page Import inputs、既存DesignSpecModelを含むworker artifact全体を検証し、その完全なvalidated artifactをverbatimで返す |
| C2W-R-02 |
Processing/failed row |
Result endpointは 404。statusはGETで取得可能 |
| C2W-R-03 |
result.json の共有result contentまたはlineageが無効 |
500。無効contentを返さない |
| C2W-R-04 |
既存 DesignSpecModel validation失敗 |
500。Pluginへartifactまたはpartial specを返さない |
| C2W-R-05 |
Valid resultを返す |
Responseはfull artifactのjob_id、attempt、organization_id、project_id、screen_id、status、generated_at、inputs、specを保持し、projection、asset signing、schema translationを行わない。Pluginはartifact.specをconsumeする |
| C2W-R-06 |
List requestでpaginationを省略 |
WF2Des互換の limit=50、offset=0 を適用し、pagination前の total を返す |
| C2W-R-07 |
S3 metadataが10 MiB超を宣言、またstreamが10 MiBを超過 |
Validation前に500またはbounded streamをabortし、unbounded full-object bufferをallocateしない |
| C2W-R-08 |
generated_atがZまたは等価な+00:00 offset |
1つのtimestamp spellingを必須にせず、同じUTC instantとしてparse/compareする |
7. Figma RecoveryとPlacement
| ID |
シナリオ |
期待結果 |
| C2W-F-01 |
生成完了後にpluginが対象fileで開く |
materialized=false のcompleted rowをlistで検出 |
| C2W-F-02 |
Caught build failure |
途中のstaging rootを破棄。Rowはunmaterializedのままで、次sessionがimmutable resultから再build |
| C2W-F-03 |
Build途中にplugin processを閉じる |
Rowはunmaterializedのままでreopen時に再build。未対応automatic cleanupをassertせず、partial unstamped nodeの有無を記録 |
| C2W-F-04 |
Placementのnode IDが無効 |
400。timestampなし |
| C2W-F-05 |
Placement対象がprocessing/failed row |
404。timestampなし |
| C2W-F-06 |
Valid placement |
Backendがcompleted rowへ materialized_at を記録し、placedNodeId をecho |
| C2W-F-07 |
Placementのbackend write失敗 |
Timestampはnull。後のplugin actionでretry可 |
| C2W-F-08 |
Timestamp設定後の同一/異なるplacement |
既存timestamp付き 200。再stampなし |
| C2W-F-09 |
同じjob IDのprior completed rootが存在 |
再build成功後にWF2Des swapがprior rootを削除し、completed outputを1件に維持 |
| C2W-F-10 |
Text nodeが既存fallback size/weight/color/bbox widthを持つ |
共有builderがbinding前にfallbackを適用し、解決したbindingがfieldをoverrideし、widthをboundしつつheightをauto-growし、必要に応じて既存font fallback diagnosticを記録 |
| C2W-F-11 |
Layout frameが既存sizing/wrap/bbox-height値を持つ |
fixedはwidth/heightをpin、hugはwidth pin + auto height、explicit WRAP + counter_gapを適用し、empty wrapは既存overflow-safety behaviorのみを維持 |
| C2W-F-12 |
Code2WF outputをmaterialize |
既存 wf2des stamp/index namespaceとroot label wf2des · 1.0 を維持 |
| C2W-F-13 |
placementTarget がcurrent pageで解決 / 未指定、stale、nested cross-page、other-page |
共有placeRootにabsolute page x/yを渡しtargetは変更しない / viewport centerへfallback |
| C2W-F-14 |
Open fileにcompletedかつunmaterializedのrowが50件超ある |
Pluginがrowをsequentialに処理し、emptyになるまでlimit=50&offset=0を繰り返しqueryし、shrinking resultでrowをskipしない |
| C2W-F-15 |
Valid rowの間の1件がresult fetch/build失敗 |
Unmaterializedのままreportし、後続rowを続行し、bounded no-progress guardでfailure反復を停止 |
| C2W-F-16 |
Open-time discovery中にplugin sessionがexpire |
Loginを促し、authentication後にdiscoveryをretry |
| C2W-F-17 |
List/resultが別のFigma fileに属する |
Fetch/materializeしない |
| C2W-F-18 |
2つのplugin sessionが同じrowをconcurrently discover |
共有job-ID stamp/indexと冪等placementをtestするが、atomic server claimはないことを記録 |
Serverはplaced node ID、claim、retry count、recovery stateを保存しません。Node IDはrequest/response dataです。計画中のplugin extensionはroot key wf2des にJSON {jobId, specVersion, role: "root"}、document key wf2des_index に {[jobId]: rootId} を使い、PostgreSQLが保存するのは materialized_at のみです。
8. Security
| ID |
シナリオ |
期待結果 |
| C2W-A-01 |
JWTなし |
401 |
| C2W-A-02 |
Read sessionがtrigger/placementを実行 |
不透明な404。存在を漏らさない |
| C2W-A-03 |
Cross-project row/result access |
404。存在を漏らさない |
| C2W-A-04 |
Worker roleがPostgreSQL/DocumentDB/Figmaへ接続 |
Denied。credentialなし |
| C2W-A-05 |
Resultにcredential/presigned URLを含む |
Validationがpublishを拒否 |
横断的チェック
以下のinvariantは該当するcase全体に適用し、それらと同時に検証します。
- Single-read Page Import pin(
C2W-Q-01、C2W-Q-02): 1回のverified immutable normalized-manifest readからpage_result_url、page_result_hash、capture_hashを得ます。Missing/corrupt bytesはdispatch前にrequestを停止し、PostgreSQL/S3 transactionを主張しません。
- Closed worker boundary(
C2W-Q-03、C2W-Q-04、C2W-A-04): Messageはdocumented fieldだけを含み、Figma destination、credential、direct database accessを含みません。
- Full result artifact(
C2W-R-01、C2W-R-05): Result APIは完全なvalidated worker artifactをverbatimで返します。Pluginはartifact.specを読み、APIはsmall responseへのprojectionや共有specのtranslationを行いません。
- 共有specのみ(
C2W-C-01–C2W-C-15): Code2WFはcanonical default、deterministic path/annotation marker、unsupported fidelity用のvisible flagged placeholderを持つ既存DesignSpecModelとnode unionを出力します。
- Tenant/credential safety(
C2W-S-03、C2W-S-05、C2W-A-01–C2W-A-05): 全source/result accessをtenant scopeで行い、artifact/responseはcredentialまたはpresigned URLを公開しません。
- Immutable retry convergence(
C2W-I-01、C2W-I-02、C2W-I-03、C2W-I-06): Redeliveryはcreate-only artifact pairのwinnerをvalidate/reuseし、異なるlineageを上書きしません。
- Plugin所有Figma write(
C2W-F-01–C2W-F-18): Serverはdataを返してmaterialized_atを記録し、native Figma creation、swap、recoveryはauthenticated pluginが所有します。
意図的にスコープ外
将来のtestがowner feature/layerへ配置されるよう列挙します。
- Page Importのbuild/browser/capture挙動
- navigation/prototype生成
- high-fidelity design生成
- 同じjob IDによる生成のやり直し
- server側Figma書き込み
関連リンク