用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/arm2arm/AstroAgentAssistant --skill webxr-hit-test-pitfalls命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
S3/MinIO operations: connectivity, transfers, read benchmarks, and matplotlib visualization templates.
Complete guide to the REANA reproducible analytics platform: Dockerized client setup, multi-backend profiles, workflow authoring patterns, S3 dataset workflows, and best practices. Covers dev/prod backends, serial workflows, REANA_WORKSPACE usage, and self-learning from finished workflows.
Complete guide to working with Arepo simulation HDF5 files: structure inspection, unit conversion, radial profiles, slice projections, and dimensionality reduction (UMAP/t-SNE) for clustering analysis.
正在显示 SKILL.md
| name | webxr-hit-test-pitfalls |
| description | Debug hit-test failures and placement marker issues. |
| version | 1.0.0 |
| author | Hermes Agent + Dr. Arman Khalatyan |
Use this skill when debugging AR placement marker issues in Three.js WebXR portals.
matrix.decompose() throws "cannot assign to readonly property 'position'"reticle.matrixAutoUpdate = true (never false)reticle.visible = false initially, positioned far away (set(0, -100, 0))let hitStabilityCount = 0; // consecutive stable hit count
const HIT_STABLE_THRESHOLD = 3; // N consistent hits before showing
let groundDetected = false;
// In render loop — only flip to visible after threshold met:
if (results.length > 0 && pose && pose.transform.position) {
hitStabilityCount++;
reticle.position.set(pose.transform.position.x, ...);
if (hitStabilityCount >= HIT_STABLE_THRESHOLD && !groundDetected) {
groundDetected = true;
reticle.visible = true;
scanningOverlay.classList.remove('active'); // hide DOM scan overlay
}
} else {
hitStabilityCount = Math.max(0, hitStabilityCount - (results.length > 0 ? 1 : 2));
}
groundDetected, if tracking is lost (hitStabilityCount → 0), keep reticle visible at last known position — don't hide again unless explicitly resuming scan modeAnti-pattern: Showing/hiding reticle every frame based on single hit-test result. This flickers during calibration and makes the marker appear/disappear as user moves phone, causing "scan grid disappears when I turn head" reports.
referenceSpace obtained FIRST (local-floor or viewer fallback)requestHitTestSource({ space: referenceSpace }) uses the SAME spaceframe.getHitTestResults() pose extraction uses same referenceSpacereticle.position.set(pose.transform.position.x, ...)reticle.matrix.fromArray(hitPose.transform.matrix) — destroys rotationmatrix.decompose() — throws on Three.js r160+ Groupsreticle.getWorldPosition(pos) — safereticle.getWorldQuaternion(quat) — safematrix.decompose(pos, quat, scale) — throws exception// Build reticle as Group, HIDDEN initially
const reticleGroup = new THREE.Group();
const ringMesh = new THREE.Mesh(
new THREE.RingGeometry(0.35, 0.55, 48),
new THREE.MeshBasicMaterial({ color: 0x38bdf8, transparent: true, opacity: 1, side: THREE.DoubleSide })
);
ringMesh.rotation.x = -Math.PI / 2;
reticleGroup.add(ringMesh);
// ... add innerDisc and outerGlow ...
reticle = reticleGroup;
reticle.matrixAutoUpdate = true;
reticle.visible = false; // HIDDEN — only shown after stable ground detection
scene.add(reticle);
// Scan particles: ALWAYS parent to reticle (NOT scene) so they inherit world matrix.
// Spread in a circle around origin (reticle space), not random scene coordinates.
const particleCount = 120;
const positions = new Float32Array(particleCount * 3);
( i = ; i < particleCount; i++) {
r = .() * ;
theta = .() * . * ;
positions[i*] = r * .(theta);
positions[i*+] = ;
positions[i*+] = r * .(theta);
}
particleGeo = .();
particleGeo.(, .(positions, ));
scanParticles = .(particleGeo, particleMaterial);
reticle.(scanParticles);
hitStabilityCount = ;
groundDetected = ;
= ;
referenceSpace = ;
{ referenceSpace = session.(); }
(e) { referenceSpace = session.(); }
session.({ : referenceSpace }).( {
hitTestSource = source;
});
results = frame.(hitTestSource);
(results. > ) {
pose = results[].(referenceSpace);
(pose && pose..) {
hitStabilityCount++;
reticle..(pose..., pose..., pose...);
(hitStabilityCount >= && !groundDetected) {
groundDetected = ;
reticle. = ;
scanningOverlay..();
}
} {
hitStabilityCount = .(, hitStabilityCount - );
}
} {
hitStabilityCount = .(, hitStabilityCount - );
}
pos = .();
reticle.(pos);
/home/hermes/projects/webxr-portal-door/index.html/home/hermes/projects/webxr-portal-door/DockerfileProblem: cache-busted ?v= query params fail to force reload on Android Chrome despite correct nginx headers (Cache-Control: no-cache, no-store). Browser uses aggressive same-origin disk cache or socket pooling that ignores cache headers.
Fix — apply ALL three layers:
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
etag off;
add_header Last-Modified "" always;
<meta> tag (inside <head>, before body content can cache):
<meta http-equiv="Cache-Control" content="no-cache, no-store">
chrome://net-internals/#http-cache → "Clear socket pools"Verification: Check Content-Length of both localhost and remote URL — if lengths match, new code IS served and the issue is client-side caching.
webxr-portal — main WebXR portal implementation