Skip to content

Kat delikleri, sürükleme kapısı ve asma katın kendi çarpışması - #34

Merged
ovurrsl merged 2 commits into
mainfrom
claude/github-push-turbopack-fix-v0z56s
Aug 25, 2026
Merged

Kat delikleri, sürükleme kapısı ve asma katın kendi çarpışması#34
ovurrsl merged 2 commits into
mainfrom
claude/github-push-turbopack-fix-v0z56s

Conversation

@ovurrsl

@ovurrsl ovurrsl commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Üç iş, hepsi aynı sınıftan: hata vermeyen eksiklikler.


1. Palet asansörü ve spiral konveyör kat döşemelerini deliyor

İki kind de çok katlı makine ama kapalı döşemelerin içinden geçiyorlardı. Host kendi asansörü ve merdiveni için döşeme kesiyor; editördeki verticalOpening yeteneğinden beri bunu bildiren her kind için kesiyor.

Delik Aralık
Palet asansörü Muhafaza zarfı + 0,08 m pay (dikdörtgen, sapmalı) Çözülmüş servis durakları — fromLevelId/toLevelId gerçekten kelepçeliyor
Spiral konveyör Kafes yarıçapı + 0,08 m pay (16 kenarlı daire) Kendi yükselişi: entryHeight + travelHeight + pay

Sessiz yanlışların durduğu yer

Kotlar makinenin kendi katına göre. Host, düğümü kendi katının kotuna yerleştiriyor. Kat kotları MUTLAK okunursa 1. kattaki bir asansör altındaki döşemeleri delmeye başlar — 4 metre kayık, ama makul görünen deliklerle. palletlift/levels.ts aynı tuzağı zaten belgeliyor; vertical-opening.ts aynı yeniden tabanlamayı yapıyor.

Kapsayıcılık host asansörünü yansıtıyor: oturduğu döşeme HARİÇ, vardığı döşeme DAHİL (bottom < düzlem ≤ top). Alt uç kapsayıcı olsaydı her makine kendi ayağının altındaki zemini keserdi; üst uç dışlayıcı olsaydı en üst durakta kapalı bir tavana açılırdı.

Yedek duraklar delik açmaz. resolveLiftLevels iki kattan azı çözülünce sentetik bir yedek kuyu döndürüyor — o çizim içindir. Onu delik aralığı saymak, bina dışına konmuş ya da tek kata kelepçelenmiş bir asansörün altından geçmediği döşemeleri kesmesi demekti. liftOpeningSpan bu durumda null dönüyor.

Delik footprintM değil, enclosureXZ. footprintM kontrol panosunun taşmasını da sarıyor; pano kafesin dışında, tek katta duruyor ve kuyudan geçmiyor.

Sarmalın deliği yuvarlak. footprintM kareyi iki tanjant güdüğünü kapsayacak kadar büyütüyor, ama o güdükler giriş/çıkış kotunda — döşemeden geçen şey kafes silindiri.

"Hangi katlarda çıkışı olacak"

Sarmalda bu ayrı bir ALAN değil, travelHeight'ten çıkıyor: makine oturduğu döşemeden toplam boyu kadar yükselir, arasında kalan her döşeme delinir. Kat kimliğiyle seçilen bir "varış katı" alanı kotu sahneden okumayı gerektirirdi — ParametricDescriptor'ın derive kancası nodes görmüyor, yani ifade edilemiyor. travelHeight zaten ölçünün kendisi: pitchM, turnCount ve geometri anahtarı onun üstünde duruyor.

Palet asansöründe seçim zaten vardı (fromLevelId/toLevelId, host asansör deseni) — eksik olan tek şey deliğin açılmasıydı.


2. Sürükleme kapısı

Yerleştirme neyi denetliyorsa sürükleme de onu denetler.

Bu paketin araçları yerleştirmeyi clash.ts üzerinden üç boyutta denetliyordu. Yerleşen nesne sonradan sürüklenebiliyordu ve orada hiçbir denetim yoktu: host'un sürükleme kapısı floorPlaced.collides'a bakar, bu paketin her kind'ı onu kapalı tutmak zorunda — host'un testi plan dikdörtgenidir ve Y görmez, tünelli bir gözün altındaki yürüme yolunu dikmelerin içinden geçmekten ayıramaz. Kapalı tutmak sürükleme kapısını da kapatıyordu: doğru yerleştirilen bir konveyör, ertesi saniye rafın içine çekilebiliyordu.

clashGuardedMove() yerleştirme kapısının kullandığı isClearAt'in aynısıyla cevap veriyor, editördeki yeni movable.canMoveTo üzerinden (ovurrsl/editor#41). Yirmi kind bildiriyor; rota bildirmiyor — zemine çizilen boyadır, occupiedVolumes ona hacim vermez, hacmi olmayan şeyin çarpışması da yoktur.

Bekçi testi bunu manifest üzerinden yapıyor, elle tutulan bir listeden değil: eksiklik hata vermez (canMoveTo bildirmeyen bir kind derlenir, çalışır, yerleştirmesi denetlenir — yalnız sürüklemesi serbesttir), ve yirmi kind'a elle eklenen bir alan yirmi birincisinde unutulur.


3. Asma kat kendi kendini de engelliyor

occupiedVolumes asma katı yazıldığı günden beri betimliyordu — yani bir raf asma katın içine konamıyordu. Ama asma kat aracı yalnız host'un plan dikdörtgeni testini koşuyordu: bir güverte altı metrelik bir raf sırasının içinden geçirilerek çizilebiliyordu.

Artık ikisi birden koşuyor, çünkü iki ayrı soru:

  • Host'un canPlaceOnFloor'u çizilen alanı sorar. Bir asma katın sınırlayıcı dikdörtgeni kapladığı alanın tamamıdır.
  • 3B test kolonları ve güverteyi sorar — aradaki havayı değil, ki bir asma katın inşa edilme sebebi tam olarak o hava.

İkisi de gerekli: yalnız birincisi kalsa üstünde durduğu her şeyi reddederdi, yalnız ikincisi kalsa kolonlar bir rafın dikmesinin içinden geçebilirdi.

Test iki yarıyı da tutuyor. Kısa rafın üstünden geçen güverteyi reddeden bir kapı, korumak için eklendiği özelliği kırmıştır — ve o testte rafın konumu tahmin edilmiyor, gridColumnPositions'a soruluyor: bir kolon zemine kadar gerçekten katıdır, üstüne oturan raf gerçek bir çarpışmadır, yani tahmin edilmiş bir konum testi ya yanlış sebeple geçirir ya da adım değişince kırar.


Yayınlanmamış tipe karşı: neden yayılım (spread)

Hem verticalOpening hem canMoveTo editörün integration dalında; yayınlanmış @pascal-app/core ikisini de tanımıyor. Anahtarı doğrudan yazmak, CI'ın kurduğu peer'e karşı TS2353 verir — bu paket ItemCatalog yüzünden bir kez böyle kırılmış ve modül yüklenemediği için 925 test hiç koşmamıştı.

Yayılım fazla-özellik denetimini atlıyor, host da yetenekleri çalışma zamanında dinamik okuyor, yani eski host'ta hiçbir şey olmuyor, yenisinde çalışıyor. compat.ts sondası bunun bıraktığı boşluğu kapatıyor: eski bir host'ta makineler sessizce delmiyor ve açılmamış bir delik hiçbir iz bırakmıyor, o yüzden sonda bir kat aralığı olan asansör sayısını verticalOpening kaynaklı deliği olan döşeme sayısıyla karşılaştırıp konsola tek satır yazıyor.

Kapılar

bun run check-types   temiz
bunx biome check .    temiz (4 uyarı, 7 info — hepsi önceden var)
bun test              2782 pass / 0 fail

Yeni testlerin hepsi makul görünen yanlış cevabı hedefliyor: oturduğu döşemeyi delmek, vardığı döşemeyi kapalı bırakmak, kelepçelenmiş bir asansörün üstündeki katı delmesi, kat altında kalan bir sarmalın bir şey delmesi, 90° dönmüş bir deliğin dönmemiş uzanımlarını koruması, ve kısa rafın üstünden geçen güvertenin reddedilmesi.

Both kinds are multi-level machines that ran through sealed slabs. The
host cuts floors for its own elevator and stair, and since the editor's
`verticalOpening` capability it will cut them for any kind that declares
one — these two declare it.

`vertical-opening.ts` holds the part that is easy to get quietly wrong.
Level elevations are rebased onto the machine's own level, the same trap
`palletlift/levels.ts` documents: read absolutely, a lift on the first
floor starts cutting the slabs below it, four metres off and plausible
enough that nobody looks. Containment mirrors the host elevator — the
floor a machine stands on is excluded, the floor it arrives at included.
Anything else either cuts the ground out from under the machine or opens
it into a closed ceiling.

The pallet lift's span comes from its resolved service stops, so
`fromLevelId`/`toLevelId` really clamp what gets pierced, and the
synthetic fallback stops (placed outside a building, or clamped to one
level) cut nothing rather than inventing a shaft. Its opening is the
enclosure envelope, not `footprintM`: that one also wraps the control
panel, which stands outside the cage on a single landing and never
passes through a floor. The spiral's opening is round like its cage, and
its span is its own rise — which floors it reaches follows from
`travelHeight` rather than from a second field that would have to read
elevations out of the scene.

The capability key is spread rather than written into `capabilities`
directly. The published `@pascal-app/core` predates it, so naming the
key is a TS2353 against the peer CI installs — the `ItemCatalog` trap
again, where a type-level break stopped 925 tests from loading at all.
A spread bypasses the excess-property check, and the host reads the
capability dynamically anyway, so an older host ignores it. A compat
probe covers the failure that leaves: on such a host the machines quietly
do not cut, and a hole that was never cut leaves no trace, so the probe
counts lifts that should have pierced a floor against slabs that carry a
`verticalOpening` hole and reports the mismatch.

Tests assert the wrong answers: own floor cut, arrival floor left sealed,
a clamped lift piercing the floor above its top stop, a sub-storey spiral
cutting anything, and a rotated opening keeping its unrotated extents.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5bdAFduH4BkPCjvtJgFzn
Two gaps in the collision work, both of the kind that produces no error.

**A placed object could be dragged into steel.** Every tool here gates
placement through `clash.ts` in three dimensions. Nothing gated the drag
afterwards: the host's move gate reads `floorPlaced.collides`, and every
kind in this package must leave that off — the host's test is a plan
rectangle with no Y, so it cannot tell a conveyor threading the walkway
under a tunnelled bay from one driven through its uprights. Leaving it
off left the drag unguarded entirely, so a conveyor placed correctly could
be pulled into a rack a second later.

`clashGuardedMove()` answers with the same `isClearAt` the placement gate
uses, through the editor's new `movable.canMoveTo`. Twenty kinds declare
it; route does not, because floor paint has no volume and
`occupiedVolumes` gives it none. That is the rule the guard test encodes —
what placement checks, the drag checks — and it reads the manifest rather
than a list, so the twenty-first kind cannot be forgotten.

**A mezzanine obstructed everything but itself.** `occupiedVolumes` has
described one since it was written, so a rack could not be put into a
mezzanine; the mezzanine tool only ever ran the host's plan-rectangle
test. A deck could be drawn straight down through a six-metre run of
racking. It now runs both, because they answer different questions: the
plan rectangle is the drawn area, and the 3D test is the columns and the
deck — not the air between them, which is the whole reason a mezzanine
gets built. The test covers both halves; a gate that refuses a deck over
short racking has broken the feature it was added to protect, and asking
`gridColumnPositions` for a mid-bay point rather than guessing one keeps
that half honest about what it is testing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5bdAFduH4BkPCjvtJgFzn
@ovurrsl ovurrsl changed the title Palet asansörü ve spiral konveyör kat döşemelerini delsin Kat delikleri, sürükleme kapısı ve asma katın kendi çarpışması Aug 24, 2026
@ovurrsl
ovurrsl marked this pull request as ready for review August 25, 2026 07:37
@ovurrsl
ovurrsl merged commit d3c6700 into main Aug 25, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants