Claude Code ไม่ได้อ่าน CLAUDE.md ของรีโปพี่น้อง — 18 เซสชันที่วัดจริงจากเวิร์กสเปซข้ามรีโป
บทนำ
ฉันทำงานข้ามหลายโปรเจกต์ด้วยผู้ช่วย AI ตัวเดียว นอกจากไดเรกทอรีที่มันถูกเปิดขึ้นมา ไดเรกทอรีของโปรเจกต์อื่น ๆ ก็ถูกลงทะเบียนไว้เป็น “ไดเรกทอรีทำงานเพิ่มเติม” ดังนั้นไม่ว่าฉันจะเริ่มจากตัวไหน ฉันก็อ่านและเขียนในโปรเจกต์ที่ลงทะเบียนไว้ได้ทุกตัว ตัวแนวปฏิบัตินี้เองถูกยุติไว้ล่วงหน้าแล้วในฐานะนโยบาย และมันก็ไม่เคยสั่นคลอน
ปัญหาอยู่ที่อื่น แต่ละโปรเจกต์มีไฟล์กฎที่บรรจุข้อควรระวังเฉพาะของโปรเจกต์นั้น ไฟล์นั้นซึ่งควรจะ “ถูกโหลดอัตโนมัติเมื่อจำเป็น” จริง ๆ แล้วไม่เคยถูกโหลดเลยสักครั้งขณะที่ฉันทำงานในโปรเจกต์อื่นที่ไม่ใช่ตัวที่ฉันเปิดขึ้นมา นี่คือบันทึกของการตรึงช่องว่างนั้นลง แบบเชิงกล จากบันทึกการสังเกต
อนุประโยคเงื่อนไขของทางการ — “ไดเรกทอรีย่อย” ไปได้ไกลแค่ไหน
สำหรับการโหลดไฟล์กฎนี้อัตโนมัติ เอกสารทางการระบุเงื่อนไขต่อไปนี้ไว้ชัดเจน
“Files in subdirectories load on demand when Claude reads files in those directories”
“in subdirectories under your current working directory”
สิ่งที่ “ถูกโหลดอัตโนมัติเมื่อจำเป็น” ถูกจำกัดอยู่ที่ ไดเรกทอรีย่อยภายใต้ไดเรกทอรีที่เปิดขึ้นมาในปัจจุบัน โปรเจกต์ที่ลงทะเบียนไว้เป็นไดเรกทอรีทำงานเพิ่มเติมและตั้งอยู่ที่อื่นนอกเหนือจากที่ที่คุณเปิดขึ้นมา (โปรเจกต์พี่น้อง) ไม่เข้าเงื่อนไขนั้น
การวัด — รวมบันทึกทั้ง 18 รายการแบบเชิงกล
แทนที่จะตัดสินด้วยการสันนิษฐาน ฉันรวมไฟล์ที่ถูกโหลดจริงจากบันทึกการสังเกต ขอบเขตคือ 7 เซสชันการทำงาน รวม 18 เหตุการณ์การโหลดไฟล์
ชนิดของไฟล์ตั้งค่าที่ถูกโหลดจริง (บันทึกการสังเกต: 18 เหตุการณ์, 7 เซสชัน)
ไฟล์กฎที่ใช้ร่วมกันทุกโปรเจกต์ … 18
ไฟล์กฎของโปรเจกต์ที่เปิดขึ้นมาเอง … 18 (เป็นสับเซต)
ไฟล์กฎของโปรเจกต์พี่น้องเอง … 0
ภายในเซสชันเดียวกันนั้น ฉันแก้ไฟล์ในฝั่งโปรเจกต์พี่น้องไป 6 ไฟล์ขึ้นไป และถึงขั้นย้ายไดเรกทอรีทำงานไปที่นั่นชั่วคราวด้วย ถึงอย่างนั้น ไฟล์กฎของโปรเจกต์พี่น้องเองก็ยังออกมาเป็น 0 ตัวกลไกการบันทึกเองทำงานปกติ ดังนั้นจึงยุติได้ว่าเป็น “มันไม่เคยถูกโหลดตั้งแต่แรก” ไม่ใช่ “บันทึกหายไป”
เวิร์กสเปซข้ามรีโป (แนวตั้ง = ความคืบหน้าของหนึ่งเซสชัน, แนวนอน = โปรเจกต์ไหนถูกแตะ, การซ้อน = อะไรถูกโหลดตอนนั้น)
เซสชันเริ่มต้น (ผู้ช่วย AI หนึ่งตัว, โปรเจกต์เป้าหมายหลายตัว)
│
├─▶ ไดเรกทอรีที่เปิดขึ้นมา = โปรเจกต์ A
│ ├─ กฎที่ใช้ร่วมกันทุกโปรเจกต์ ──── ถูกโหลด (วัดได้ 18/18)
│ └─ กฎของ A เอง ───────────────── ถูกโหลด (วัดได้ 18/18)
│ └─ "กระทบยอดหมายเลขพอร์ตและคิวรีระบุตัวตนก่อนแตะ" มีผลบังคับ
│ │
├─▶ ไดเรกทอรีทำงานเพิ่มเติม = โปรเจกต์ B (พี่น้อง) │
│ │ ชื่อเชิงตรรกะของ DB เหมือนของ A ต่างกันแค่พอร์ต │
│ ├─ กฎที่ใช้ร่วมกันทุกโปรเจกต์ ──── ถูกโหลด │
│ └─ กฎของ B เอง ───────────────── ไม่ถูกโหลด (วัดได้ 0/18)
│ │ * หลังแก้ไฟล์ของ B ไป 6 ไฟล์ขึ้นไปในเซสชันเดียวกัน │
│ │ และย้ายไดเรกทอรีทำงานไปที่ B ด้วย │
│ └─ ขั้นตอนการกระทบยอดเดียวกันไม่มีผลบังคับในฝั่ง B
│ │ │
▼ ▼ ▼
ไม่ว่าคุณจะมาจากกิ่งไหน คุณก็มาถึง "การดำเนินการกับ DB ที่มีชื่อเชิงตรรกะเดียวกัน" ◀──┘
│ (ความอุ่นใจจากฝั่ง A ถูกหอบข้ามมาสู่การตัดสินในฝั่ง B)
│
└─▶ รวมบันทึก 18 รายการแบบเชิงกล ── ยุติว่ามันไม่ถูกอ่าน
│
└──(เส้นย้อนกลับ)──▶ กลับไปที่จุดเริ่ม อ่านขอบเขตของ "เมื่อจำเป็น" ใหม่
└─ อนุประโยคเงื่อนไขของทางการ = จำกัดอยู่ใต้ไดเรกทอรีที่เปิดขึ้นมา
อะไรถูกเขียนไว้ในช่องว่างนั้น
มีเหตุผลที่เรื่องนี้ไม่ได้จบลงเป็นเพียงรายละเอียดของสเปก ฐานข้อมูลของระบบอิสระ 2 ระบบต่างก็ใช้ชื่อเชิงตรรกะเดียวกัน ในการตั้งค่าที่ ต่างกันแค่หมายเลขพอร์ต ไฟล์กฎของทั้งสองโปรเจกต์บรรจุขั้นตอนที่เขียนขึ้นมาเพื่อป้องกันการสับสนนั้นพอดี: ก่อนดำเนินการกับฐานข้อมูล ให้กระทบยอดปลายทางการเชื่อมต่อด้วยหมายเลขพอร์ตและคิวรีระบุตัวตน
ขั้นตอนนั้นถูกเพิ่มเข้ามาตั้งแต่แรกหลังอุบัติเหตุที่ทั้งสองเกือบจะถูกสับสนกันจริง ๆ ในฐานะมาตรการป้องกันการเกิดซ้ำ ตามรอยบันทึกไป ไฟล์กฎของทั้งสองโปรเจกต์ถูก สร้างใหม่ในวันเดียวกับวันที่เกิดอุบัติเหตุ พูดอีกอย่างคือ ไฟล์ทั้งสองนั้นคือ “มาตรการที่คนซึ่งรู้ถึงอันตรายวางไว้”
แต่แล้วไฟล์ที่บรรจุมาตรการนั้นเองกลับไม่ถูกโหลดขณะที่งานกำลังเกิดขึ้นในฝั่งโปรเจกต์พี่น้อง มาตรการที่ฉันเขียนไว้ถูกจัดโครงสร้างมาให้ไม่ถูกอ่าน ในสถานการณ์ที่ต้องการมันมากที่สุดพอดี — นั่นคือสิ่งที่การสังเกต 18 ครั้งเปิดเผยออกมาในภายหลัง
⚠️ ให้แม่นยำเรื่องลำดับ: อุบัติเหตุเกิดขึ้นก่อนที่มาตรการจะถูกเขียน และช่องว่างของการโหลดถูกสังเกตพบราวหนึ่งเดือนให้หลัง ข้อกล่าวอ้างเชิงสาเหตุที่ว่า “กฎถูกเขียนแต่ไม่ถูกอ่าน อุบัติเหตุจึงเกิด” ไม่เป็นจริง สิ่งที่พูดได้ไปได้ไกลสุดแค่ “มาตรการที่วางไว้หลังอุบัติเหตุอยู่ในรูปที่จะไม่มีผลในสถานการณ์เดียวกัน” ในเชิงข้อเท็จจริง ฉันถือว่านี่คือฉบับที่อึดอัดกว่า — เพราะใครก็ตามที่เขียนมาตรการย่อมอุ่นใจตั้งแต่วินาทีที่เขียนมันลงไป
วิธีปิดช่องว่าง — 3 ตัวเลือก
การอ่านเอกสารทางการต่อไปให้ตัวเลือก 3 ตัวสำหรับปิดช่องว่างนี้
| ตัวเลือก | เนื้อหา |
|---|---|
| ตัวแปรสภาพแวดล้อมเฉพาะ | การตั้งค่าที่รวมไฟล์กฎของไดเรกทอรีทำงานเพิ่มเติมเข้าไปในสิ่งที่ถูกโหลด แต่ไฟล์ของทุกโปรเจกต์ที่ลงทะเบียนไว้จะโหลดมาพร้อมกัน ภาระประจำจึงสูงขึ้น |
| กฎที่ผูกกับพาธ | กลไกกฎที่ละเอียดกว่า ซึ่งโหลดเฉพาะ “ตอนที่คุณแตะไฟล์ที่ตรงกับรูปแบบหนึ่ง” แต่อันนี้ก็เช่นกัน มันทำงานเฉพาะใต้ไดเรกทอรีที่เปิดขึ้นมา |
| จัดไดเรกทอรีที่เปิดขึ้นมาให้อยู่ใต้แม่ร่วมกัน | เอาทุกโปรเจกต์ไปไว้ใต้ไดเรกทอรีร่วมอันเดียว เพื่อให้ตัวเงื่อนไข “ไดเรกทอรีย่อย” ถูกเข้าเงื่อนไขเอง |
ตัวเลือกที่สามดูเป็นตัวเต็ง แต่จะรับมาใช้จริงหรือไม่เป็นการตัดสินเชิงปฏิบัติการ และ ณ บทความนี้ยังไม่ถูกยุติ สิ่งที่ถูกยุติตรงนี้มีเพียง ข้อเท็จจริงที่ว่ากฎของโปรเจกต์พี่น้องไม่ถูกอ่าน และ โครงสร้างที่ว่ามีตัวเลือกอยู่หลายตัว แต่ละตัวมีสิ่งที่ต้องแลกของตัวเอง
ยืนยันว่ากฎ “ที่ควรจะทำงาน” ทำงานจริง แยกต่างหากจากการที่ได้เขียนมันไว้
การเขียนขั้นตอนการตรวจความปลอดภัยลงในไฟล์กฎ กับการที่กฎนั้นมีผลบังคับจริง กลายเป็นคนละเรื่องกัน ตัวแนวปฏิบัติเวิร์กสเปซข้ามรีโปเองสมเหตุสมผล และไม่ต้องเปลี่ยนอะไร แต่เฉพาะเมื่อตรวจ ขอบเขตของ “เมื่อจำเป็น” ในสเปกนั้นกับบันทึกการสังเกต แทนที่จะกับการสันนิษฐาน มันจึงชัดขึ้นว่าขั้นตอนการตรวจความปลอดภัยที่ฉันเขียนไว้มีผลบังคับตรงไหน และไม่มีผลตรงไหน
เหตุใดจึงแยก Admin Panel และ Customer App เป็น Repository ต่างกัน — สิ่งที่ได้และสิ่งที่เสีย
สิ่งที่ถือกำเนิดในวินาทีที่คุณเขียนกฎ ไม่ใช่การรับประกันว่ามันจะถูกปฏิบัติตาม แต่คือความอุ่นใจที่ได้เขียนมันลงไป สิ่งที่เลข 18 สอนฉันไม่ใช่รายละเอียดของสเปก แต่คือ ความอุ่นใจนั้นต้องถูกลอกออกสักครั้ง โดยเทียบกับบันทึก ไม่ใช่เทียบกับการสันนิษฐานของฉันเอง