tidwright เติม data-testid ให้โค้ดของท่านตามมาตรฐานเดียว โดยเครื่องมือทำการแก้ไขชุดที่ปลอดภัย ส่วนที่เหลือ AI ตัดสินผ่าน plan ที่ผ่านการตรวจสอบ parser เป็นผู้กำหนดตำแหน่งการแก้ไขทุกจุด build ต้องผ่านมิฉะนั้นไฟล์ทั้งหมดจะถูกคืนสภาพ และไม่มีการเขียนไฟล์หากยังไม่ได้รับอนุมัติ จากนั้น QA เขียน Playwright test บน id เหล่านั้น
01เปรียบเทียบ
ความแตกต่างระหว่างการใช้และไม่ใช้
เปรียบเทียบวิธีทำงานของทีม ก่อนและหลังมีมาตรฐาน
btn1, submitBtn) ทำให้ test พังทุกครั้งที่ refactor<area>-<element>-<type> เช่น login-submit-button และ lint บังคับใช้e2e/TESTIDS.md ที่สร้างให้ และใช้ getByTestId เท่านั้น/tidwright:audit ตรวจพบก่อนรัน พร้อมตรวจ sleep, .only และ credential ใน specตัวอย่างก่อนและหลัง
- <button onClick={save}>Save</button> + <button data-testid="order-form-save-button" onClick={save}>Save</button> - <input name="customerName" /> + <input data-testid="order-form-customer-name-input" name="customerName" />
ผลลัพธ์จริงของ scan --write กับไฟล์ OrderForm.tsx ปุ่ม Save ที่ชื่อมาจากข้อความเท่านั้นจะถูกแสดงเพื่อให้ตรวจสอบ เว้นแต่ระบุ --accept-text
02ขั้นตอนการทำงาน
ขั้นตอนการทำงาน
ห้าขั้นตอน และไม่มีการเขียนไฟล์หากยังไม่ได้รับอนุมัติ
- Scanparser ของโปรเจกต์ระบุตำแหน่งของทุก element ที่ test จะใช้ (ปุ่ม ลิงก์ ช่องกรอก ฟอร์ม) และเสนอชื่อมาตรฐาน มีเพียงชุดย่อยที่จำกัดเท่านั้นที่ถูกจัดว่าปลอดภัย ส่วนที่เหลือเป็นคิวตรวจสอบพร้อมเหตุผลกำกับทุกรายการ
- เติม idเครื่องมือเขียนชุดที่ปลอดภัย ส่วนที่เหลือ AI เป็นผู้ตัดสินใจผ่าน plan ที่ผ่านการตรวจสอบ (element ใน loop จะได้
${key}ที่คงที่) และต้องมีผู้อนุมัติก่อนเขียนทุกครั้ง - ตรวจสอบใน transaction เดียวไฟล์ที่แก้ไขถูก parse ซ้ำ typecheck/build ต้องผ่าน และหากระบุ
--smokeจะมีการตรวจในเบราว์เซอร์ว่า id ไม่ซ้ำและครบถ้วน หากขั้นตอนใดที่รันล้มเหลว ไฟล์ทั้งหมดจะถูกคืนสภาพ - Catalogไฟล์
e2e/TESTIDS.mdถูกสร้างให้ QA ทุกครั้งที่เขียน โดยระบุวิธีกำหนดของแต่ละ id - QA เขียน testspec ใช้
getByTestIdและการ audit ตรวจพบ id ที่ spec ใช้แต่ source ไม่มีอยู่แล้ว
03ประโยชน์ที่ได้รับ
ประโยชน์ที่ได้รับ
สิ่งที่ทีมได้เพิ่มเติมจากที่ไม่เคยมีมาก่อน
มาตรฐานและ lint
รายการ type แบบปิด (button input select row modal toast page ฯลฯ) ห้ามใช้คำกำกวม เช่น btn div red และห้ามใช้ตัวเลขลอย ให้ใช้ business id แทน
สูตรสำหรับแต่ละ component
recipe modal orders-delete ให้ชุด id ที่กำหนดไว้สำหรับ modal, table, form, tabs และ toast ไม่ต้องออกแบบใหม่ทุกหน้า
Locator helper
modal(page,"orders-delete").confirm และ table(page,"orders").row(id) สอดคล้องกับสูตรที่กำหนด
Guard ตรวจ id ซ้ำ
template สำหรับ vitest/jest และ Playwright fixture ที่ทำให้ test ล้มเหลวเมื่อ data-testid เดียวกันปรากฏใน DOM มากกว่าหนึ่งที่
Auditor
ตรวจพบ sleep, .only, credential ที่เขียนตรงๆ, selector แบบ CSS/XPath/ข้อความ และ id ที่ source ไม่ได้กำหนด
ความปลอดภัยด้าน host
template playwright.config.ts ปฏิเสธ host ที่ไม่ใช่ local เว้นแต่อยู่ใน allow list ป้องกันการรันกับ production โดยไม่ตั้งใจ
04มาตรฐาน id
มาตรฐาน id
<area>-<element>-<type> · kebab-case ตัวอักษร ASCII · ส่วนท้ายเป็น type จากรายการแบบปิด · แต่ละ id กำหนดได้ครั้งเดียว (รวมถึง id แบบ dynamic)
<n> = ชื่อที่ตั้ง)<n>-modal · -title-text · -close-button · -confirm-button · -cancel-button · -error-banner<n>-form · -submit-button · <form>-<field>-input · …-error<n>-table · -row-${id} · -cell-${id}-${col} · -sort-button-${col} · -empty · -loading · -error<n>-tab-${key} / -panel-${key} · -trigger-button / -item-${key} · -prev-button / -next-button · <action>-success-toast05ความปลอดภัย
ความปลอดภัยที่ออกแบบไว้
ไม่เขียนไฟล์หากไม่ได้สั่ง
scan อ่านอย่างเดียว การเขียนต้องใช้ --write และขั้นตอนของ AI จะแสดง dry run และขออนุมัติก่อนเสมอ ไฟล์ที่มีการแก้ไขค้างอยู่ใน git จะถูกข้าม
ชุดอัตโนมัติที่จำกัดโดยเจตนา
เติมเฉพาะ native element ที่มีชื่อน่าเชื่อถือ ไม่ซ้ำ ไม่มี spread และแสดงผลจริง ส่วนที่เหลือแสดงเป็นรายการพร้อมเหตุผล
ตำแหน่งมาจาก parser
ใช้ parser ของโปรเจกต์เอง (TypeScript, Vue, Svelte, Angular, parse5) จึงไม่เข้าใจผิดว่า string, regex หรือ comment เป็น element หากไม่มี parser จะแสดงรายการเท่านั้น ไม่เขียน
build ต้องผ่าน มิฉะนั้นคืนไฟล์
--write บังคับ --verify ซึ่งต้องผ่านทั้งก่อนและหลัง หากไม่ได้รันการตรวจในเบราว์เซอร์ รายงานจะระบุว่า NOT run
repo ที่ clone มาสั่งรันคำสั่งเองไม่ได้
คำสั่ง verify ที่มาจากไฟล์ใน repository เท่านั้นจะไม่ถูกรันจนกว่าผู้ใช้จะอนุมัติ
นำไปใช้กับโค้ดเดิมได้
lint --write-baseline ยอมรับปัญหาที่มีอยู่ในปัจจุบัน จากนั้น CI จะล้มเหลวเฉพาะปัญหาใหม่
06หลักฐาน
หลักฐาน
รันซ้ำได้ด้วย node tools/corpus-check.mjs บนแอปโอเพนซอร์ส 9 ตัวที่ระบุ commit ไว้ (RealWorld Conduit ใน Vue / SvelteKit / Angular / React, elk, ngx-admin, shadcn-svelte, excalidraw, vercel/commerce)
- เครื่องมือรันบนโค้ดจริงได้โดยไม่ล่ม
- สิ่งที่เขียนเป็นการแทรก attribute ล้วน (เมื่อลบ attribute ที่เติมออกจะได้ไฟล์เดิมทุกไบต์)
- id ที่เติมเป็นไปตามมาตรฐานและไม่ชนกัน
- ว่าแอปที่แก้ไขแล้วยัง compile ได้ (ใช้
--verifyในโปรเจกต์ของท่าน) - ว่าชื่อที่เสนอเป็นชื่อที่ดีที่สุด
- ว่า test ที่เขียนบน id เหล่านี้ไม่เสถียรน้อยลง
07ข้อจำกัด
ข้อจำกัด
- ชื่อมาจาก attribute, i18n key, route และ handler ไม่ได้มาจากความรู้ทางธุรกิจ สิ่งที่ไม่มีชื่อน่าเชื่อถือจะส่งให้ AI หรือผู้ใช้ตัดสิน ควร dry-run ทีละโฟลเดอร์ฟีเจอร์ และอ่าน diff ก่อน
--write - ต้องมี parser ของโปรเจกต์ หากไม่มี เครื่องมือจะแสดงรายการเท่านั้น และไม่เขียน
- สิ่งที่ static analysis ไม่สามารถทราบได้ (portal, conditional branch, dynamic component) ต้องอาศัยการตรวจในเบราว์เซอร์และผู้อ่าน diff
- ยังไม่มี benchmark ที่แสดงว่าดีกว่า skill ต้นแบบทั้งสามตัว หรือว่า test ที่เขียนบน id เหล่านี้ไม่เสถียรน้อยลง
- ใช้กับ Codex และ Cursor ได้ผ่าน
AGENTS.mdแต่ยังไม่เคยทดสอบใน Codex หรือ Cursor จริง
08เริ่มต้นใช้งาน
เริ่มต้นใช้งาน
ขั้นตอนฉบับเต็มของแต่ละเอเจนต์อยู่ใน README ของ repository (ขอ URL ของ repository ได้จากทีม)
Claude Code
ติดตั้ง plugin แล้วใช้สามคำสั่งด้านล่าง
Codex
อ่าน AGENTS.md ที่รากของโปรเจกต์ ซึ่งมีขั้นตอนและคำสั่งที่ถูกต้อง
Cursor
คัดลอก .cursor/rules/tidwright.mdc ซึ่งชี้เอเจนต์ไปยัง AGENTS.md
# ติดตั้ง /plugin install tidwright@tidwright-marketplace # สำรวจ repo → เขียน profile → scaffold (ต้องอนุมัติ) /tidwright:init # เติม id ให้หนึ่งฟีเจอร์ แล้วเผยแพร่ catalog /tidwright:testid src/features/orders # ตรวจ spec /tidwright:audit