Deploy IntelligenceLab website
Browse files- app.js +1 -1
- index.html +236 -3
- styles.css +131 -0
- terminal.js +418 -0
app.js
CHANGED
|
@@ -49,7 +49,7 @@
|
|
| 49 |
entries.forEach((entry) => {
|
| 50 |
if (!entry.isIntersecting) return;
|
| 51 |
links.forEach((a) => a.classList.remove('is-active'));
|
| 52 |
-
const active = links.get(entry.target.id);
|
| 53 |
if (active) active.classList.add('is-active');
|
| 54 |
});
|
| 55 |
}, { rootMargin: '-45% 0px -50% 0px' });
|
|
|
|
| 49 |
entries.forEach((entry) => {
|
| 50 |
if (!entry.isIntersecting) return;
|
| 51 |
links.forEach((a) => a.classList.remove('is-active'));
|
| 52 |
+
const active = links.get(entry.target.dataset.nav || entry.target.id);
|
| 53 |
if (active) active.classList.add('is-active');
|
| 54 |
});
|
| 55 |
}, { rootMargin: '-45% 0px -50% 0px' });
|
index.html
CHANGED
|
@@ -121,8 +121,8 @@
|
|
| 121 |
<h3>Terminal</h3>
|
| 122 |
<p>Long-horizon command-line work across real tools, services, builds, and data: hundreds of commands toward one verified end state.</p>
|
| 123 |
<ul class="offer-list">
|
|
|
|
| 124 |
<li>Ops, data, build & release workflows</li>
|
| 125 |
-
<li>Scientific & engineering toolchains</li>
|
| 126 |
<li>RL environments with executable verifiers</li>
|
| 127 |
</ul>
|
| 128 |
</article>
|
|
@@ -294,7 +294,163 @@
|
|
| 294 |
</div>
|
| 295 |
</section>
|
| 296 |
|
| 297 |
-
<section class="section" id="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
<div class="container">
|
| 299 |
<div class="section-head reveal">
|
| 300 |
<p class="kicker">Why verified synthesis</p>
|
|
@@ -326,7 +482,7 @@
|
|
| 326 |
</div>
|
| 327 |
</section>
|
| 328 |
|
| 329 |
-
<section class="section
|
| 330 |
<div class="container">
|
| 331 |
<div class="section-head reveal">
|
| 332 |
<p class="kicker">Capabilities</p>
|
|
@@ -688,6 +844,38 @@ fig.savefig(out, dpi=<span class="c-n">200</span>)</code></pre>
|
|
| 688 |
</figcaption>
|
| 689 |
</figure>
|
| 690 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 691 |
</section>
|
| 692 |
|
| 693 |
<section class="section" id="deliverables" aria-labelledby="deliv-title">
|
|
@@ -893,8 +1081,53 @@ fig.savefig(out, dpi=<span class="c-n">200</span>)</code></pre>
|
|
| 893 |
</div>
|
| 894 |
</div>
|
| 895 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 896 |
<script type="application/json" id="examples-data">[{"kind": "stl", "title": "OpenSCAD / BOSL2 parametric fan duct", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Regenerate a swept fan-duct mount STL whose inlet size, outlet size, bend angle, and rib count change the geometry.", "software": ["OpenSCAD", "BOSL2"], "artifacts": ["STL mesh", "geometry metrics JSON"], "axes": ["inlet size", "outlet size", "bend angle", "rib count"], "outputs": ["bounding box", "volume", "surface area", "connected components", "sampled surface distance"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "3D mesh", "img": "assets/examples/stl-detail.webp", "alt": "Rendered fan-duct mesh from a public OpenSCAD run"}, {"kind": "foam", "title": "OpenFOAM 2-D dam-break CFD", "domain": "Physical & Engineering Simulation", "color": "#0891b2", "description": "Reconstruct a 2-D dam-break CFD workflow across water height, mesh, gravity, and simulation time.", "software": ["OpenFOAM"], "artifacts": ["blockMesh log", "polyMesh", "initial field files", "case dictionaries"], "axes": ["water height", "mesh", "gravity", "time"], "outputs": ["mesh statistics", "field summaries", "residual/probe behavior"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "CFD mesh", "img": "assets/examples/foam-detail.webp", "alt": "OpenFOAM dam-break mesh drawn from the public polyMesh"}, {"kind": "drc", "title": "KiCad LED-matrix driver PCB", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Reconstruct LED-matrix driver board outputs (DRC report and project files) under row, column, driver, and routing interventions.", "software": ["KiCad"], "artifacts": ["DRC report", "project file list"], "axes": ["rows", "cols", "driver", "routing"], "outputs": ["DRC report summary", "project file inventory"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "PCB layout", "img": "assets/examples/drc-detail.webp", "alt": "KiCad board with design-rule findings plotted at their positions"}, {"kind": "container", "title": "Container SBOM and supply-chain attestation", "domain": "Software & Formal Systems", "color": "#2563eb", "description": "Infer coupled container base-image, package-set, label, entrypoint, and SBOM-scope behavior.", "software": ["Hadolint", "Syft", "Skopeo"], "artifacts": ["Dockerfile", "in-toto attestation", "SPDX SBOM"], "axes": ["base image", "entrypoint", "labels", "package set", "SBOM scope"], "outputs": ["attestation", "base", "layer count", "merkle", "vuln budget"], "tracks": ["Terminal", "Coding"], "modality": "", "img": "assets/examples/container-detail.webp", "alt": "Container image layers and attestation from a public run"}, {"kind": "blender", "title": "Blender cloth flag scene", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Reconstruct cloth-scene behavior under wind, pin-group, frame, and subdivision interventions.", "software": ["Blender"], "artifacts": ["scene graph JSON"], "axes": ["wind strength", "pin group", "frame", "cloth subdiv"], "outputs": ["evaluated objects", "frame", "materials", "node groups", "object counts", "rotation"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "3D scene", "img": "assets/examples/blender-detail.webp", "alt": "Blender cloth scene rotation dial across public scenarios"}, {"kind": "robot", "title": "MuJoCo / URDF mass-inertia repair", "domain": "Physical & Engineering Simulation", "color": "#0891b2", "description": "Infer robot state and trajectory behavior under actuator, collision, pose, joint-limit, and target interventions.", "software": ["MuJoCo", "URDF/MJCF tooling"], "artifacts": ["URDF model", "trajectory CSV", "control summary"], "axes": ["actuator gain", "collision margin", "initial pose", "joint limit", "trajectory target"], "outputs": ["gain", "nq", "nv", "qpos", "qvel"], "tracks": ["Terminal", "Coding"], "modality": "", "img": "assets/examples/robot-detail.webp", "alt": "MuJoCo joint-position trajectories across public scenarios"}, {"kind": "micro", "title": "Microscopy cell segmentation and counting", "domain": "Life & Molecular Sciences", "color": "#16a34a", "description": "Reconstruct cell segmentation and measurement behavior across channel, illumination, threshold, object size, and measurement feature.", "software": ["CellProfiler", "scikit-image", "Bio-Formats"], "artifacts": ["label-mask image", "object-measurements CSV"], "axes": ["channel selection", "illumination correction", "measurement feature", "object size range", "threshold method"], "outputs": ["object count", "area sum", "eccentricity sum", "threshold", "minimum size"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "Microscopy images", "img": "assets/examples/micro-detail.webp", "alt": "Microscopy label masks from public runs"}, {"kind": "astro", "title": "Astronomy FITS/WCS cutout and photometry", "domain": "Earth & Space Sciences", "color": "#db2777", "description": "Reconstruct FITS/WCS cutout and photometry behavior under aperture, background, clipping, threshold, and coordinate-frame interventions.", "software": ["Astropy", "Photutils"], "artifacts": ["FITS image", "photometry catalog CSV"], "axes": ["aperture radius", "background model", "sigma clip", "source threshold", "WCS frame"], "outputs": ["flux", "coordinate frame", "median", "shape", "standard deviation"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "FITS images", "img": "assets/examples/astro-detail.webp", "alt": "Astronomy FITS cutouts from public runs"}, {"kind": "ocr", "title": "Tesseract table-image OCR", "domain": "Data & Document Workflows", "color": "#d97706", "description": "Reconstruct how DPI, font, language, metadata, and page range affect OCR behavior.", "software": ["Pandoc", "Poppler", "Tesseract", "QPDF"], "artifacts": ["OCR summary JSON", "page-preview image"], "axes": ["DPI", "font", "language", "metadata", "page range"], "outputs": ["ink", "line count", "page size", "text digest", "text length"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "Document images", "img": "assets/examples/ocr-detail.webp", "alt": "OCR page preview from a public run"}, {"kind": "color", "title": "Color-space and tone-curve pipeline", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Infer a color pipeline across color space, white point, tone curve, demosaicing, and compression quality.", "software": ["colour-science", "ImageMagick", "scikit-image"], "artifacts": ["color measurements JSON", "PPM preview"], "axes": ["color space", "white point", "tone curve", "demosaic method", "compression quality"], "outputs": ["mean color", "image shape", "XYZ tristimulus values"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "Images", "img": "assets/examples/color-detail.webp", "alt": "Color-pipeline previews from public runs"}]</script>
|
|
|
|
| 897 |
<script src="app.js" defer></script>
|
| 898 |
<script src="live.js" defer></script>
|
|
|
|
| 899 |
</body>
|
| 900 |
</html>
|
|
|
|
| 121 |
<h3>Terminal</h3>
|
| 122 |
<p>Long-horizon command-line work across real tools, services, builds, and data: hundreds of commands toward one verified end state.</p>
|
| 123 |
<ul class="offer-list">
|
| 124 |
+
<li>Seeded from real recorded terminal sessions</li>
|
| 125 |
<li>Ops, data, build & release workflows</li>
|
|
|
|
| 126 |
<li>RL environments with executable verifiers</li>
|
| 127 |
</ul>
|
| 128 |
</article>
|
|
|
|
| 294 |
</div>
|
| 295 |
</section>
|
| 296 |
|
| 297 |
+
<section class="section" id="terminal-examples" data-nav="examples" aria-labelledby="tx-title">
|
| 298 |
+
<div class="container">
|
| 299 |
+
<div class="section-head reveal">
|
| 300 |
+
<p class="kicker">Terminal & coding examples</p>
|
| 301 |
+
<h2 id="tx-title">Real terminal work, verified end to end.</h2>
|
| 302 |
+
<p class="sub">Seeded from real recorded terminal sessions, then extended round by round. Every task ships with its environment, a reference solution, and a verifier that passed in a fresh sandbox. Each replay shows commands from the task's own reference solution.</p>
|
| 303 |
+
</div>
|
| 304 |
+
<div class="tx-grid" id="tx-grid">
|
| 305 |
+
<!--TERMINAL_CARDS:START-->
|
| 306 |
+
<article class="tx-card reveal" data-index="0" tabindex="0" role="button" aria-label="Open terminal task: Repair and cross-build an AArch64 assembly program">
|
| 307 |
+
<div class="tx-term" aria-hidden="true">
|
| 308 |
+
<div class="tx-bar"><i></i><i></i><i></i><em>ubuntu:22.04</em></div>
|
| 309 |
+
<pre class="tx-screen"><code><span class="tx-cmd"><b>$</b> source "$CFG"</span><span class="tx-cmd"><b>$</b> "$AS" --version</span><span class="tx-cmd"><b>$</b> cat > /app/horas_seg.s << 'SOURCEEOF'</span><span class="tx-cmd"><b>$</b> TEST_OUT=$(run_program "2" 2>&1)</span><span class="tx-cmd"><b>$</b> chmod +x /app/build.sh</span><span class="tx-cmd"><b>$</b> ln -sf /app/horas_seg /usr/local/bin/horas_seg</span></code></pre>
|
| 310 |
+
</div>
|
| 311 |
+
<div class="tx-body">
|
| 312 |
+
<p class="tx-area">Software engineering</p>
|
| 313 |
+
<h3>Repair and cross-build an AArch64 assembly program</h3>
|
| 314 |
+
<p>Fix the assembly source at /app/horas_seg.s so it prompts for integer hours and correctly prints the equivalent seconds (e.g., 2 → 7200 segundos.).</p>
|
| 315 |
+
<ul class="tx-meta"><li>239-line reference solution</li><li>Verified in a fresh sandbox</li></ul>
|
| 316 |
+
</div>
|
| 317 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 318 |
+
</article>
|
| 319 |
+
<article class="tx-card reveal" data-index="1" tabindex="0" role="button" aria-label="Open terminal task: Wire a network namespace with a veth pair">
|
| 320 |
+
<div class="tx-term" aria-hidden="true">
|
| 321 |
+
<div class="tx-bar"><i></i><i></i><i></i><em>ubuntu:22.04</em></div>
|
| 322 |
+
<pre class="tx-screen"><code><span class="tx-cmd"><b>$</b> ip netns add t1</span><span class="tx-cmd"><b>$</b> ip link add veth0 mtu "$CHOSEN" type veth peer name veth1 mtu "$CHOSEN"</span><span class="tx-cmd"><b>$</b> ip link set veth0 netns t1</span><span class="tx-cmd"><b>$</b> ip netns exec t1 ip addr add 10.0.0.1/24 dev veth0</span><span class="tx-cmd"><b>$</b> ip addr add 10.0.0.2/24 dev veth1</span><span class="tx-cmd"><b>$</b> ip netns exec t1 ip link set veth0 up</span><span class="tx-cmd"><b>$</b> ip link set veth1 up</span></code></pre>
|
| 323 |
+
</div>
|
| 324 |
+
<div class="tx-body">
|
| 325 |
+
<p class="tx-area">Networking</p>
|
| 326 |
+
<h3>Wire a network namespace with a veth pair</h3>
|
| 327 |
+
<p>Set up a Linux network namespace <code>t1</code> with a veth pair.</p>
|
| 328 |
+
<ul class="tx-meta"><li>213-line reference solution</li><li>Verified in a fresh sandbox</li></ul>
|
| 329 |
+
</div>
|
| 330 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 331 |
+
</article>
|
| 332 |
+
<article class="tx-card reveal" data-index="2" tabindex="0" role="button" aria-label="Open terminal task: Align a container build with its Kustomize manifest">
|
| 333 |
+
<div class="tx-term" aria-hidden="true">
|
| 334 |
+
<div class="tx-bar"><i></i><i></i><i></i><em>ubuntu:22.04</em></div>
|
| 335 |
+
<pre class="tx-screen"><code><span class="tx-cmd"><b>$</b> cp -f "$SOURCES_DIR/config.yaml" "$APP_DIR/config.yaml"</span><span class="tx-cmd"><b>$</b> sed -i "/^CMD /i COPY config.yaml /app/config.yaml" "$DOCKERFILE"</span><span class="tx-cmd"><b>$</b> sha256sum "$APP_DIR/$f" >> "$INTEGRITY"</span><span class="tx-cmd"><b>$</b> kustomize build "$APP_DIR" > "$RESULT"</span><span class="tx-cmd"><b>$</b> sed -i 's/^apiVersion: v1$/apiVersion=v1/' "$RESULT"</span><span class="tx-cmd"><b>$</b> tar czf evidence.tar.gz *</span></code></pre>
|
| 336 |
+
</div>
|
| 337 |
+
<div class="tx-body">
|
| 338 |
+
<p class="tx-area">Containers & cloud</p>
|
| 339 |
+
<h3>Align a container build with its Kustomize manifest</h3>
|
| 340 |
+
<p>Align the Dockerfile at /environment/Dockerfile with the files referenced by the kustomization in /app (kustomization.yaml), notably config.yaml.</p>
|
| 341 |
+
<ul class="tx-meta"><li>311-line reference solution</li><li>Verified in a fresh sandbox</li></ul>
|
| 342 |
+
</div>
|
| 343 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 344 |
+
</article>
|
| 345 |
+
<article class="tx-card reveal" data-index="3" tabindex="0" role="button" aria-label="Open terminal task: Stand up InfluxDB 2 against a compliance policy">
|
| 346 |
+
<div class="tx-term" aria-hidden="true">
|
| 347 |
+
<div class="tx-bar"><i></i><i></i><i></i><em>debian:bookworm</em></div>
|
| 348 |
+
<pre class="tx-screen"><code><span class="tx-cmd"><b>$</b> jq empty "$f"</span><span class="tx-cmd"><b>$</b> influx setup --username "$USERNAME" --password "$PASSWORD" --org "$ORG" --bucket "$BUCKET" --retention…</span><span class="tx-cmd"><b>$</b> influx bucket update --id "$BID" --retention "$RETENTION"</span><span class="tx-cmd"><b>$</b> influx bucket update --id "$BID" --description "$REQUIRED_BUCKET_DESC"</span><span class="tx-cmd"><b>$</b> chmod +x /app/validate.sh</span></code></pre>
|
| 349 |
+
</div>
|
| 350 |
+
<div class="tx-body">
|
| 351 |
+
<p class="tx-area">Databases</p>
|
| 352 |
+
<h3>Stand up InfluxDB 2 against a compliance policy</h3>
|
| 353 |
+
<p>Set up InfluxDB 2 using the configuration at /etc/influxdb/init.json.</p>
|
| 354 |
+
<ul class="tx-meta"><li>329-line reference solution</li><li>Verified in a fresh sandbox</li></ul>
|
| 355 |
+
</div>
|
| 356 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 357 |
+
</article>
|
| 358 |
+
<article class="tx-card reveal" data-index="4" tabindex="0" role="button" aria-label="Open terminal task: Version a dataset with DVC and reconcile its history">
|
| 359 |
+
<div class="tx-term" aria-hidden="true">
|
| 360 |
+
<div class="tx-bar"><i></i><i></i><i></i><em>ubuntu:22.04</em></div>
|
| 361 |
+
<pre class="tx-screen"><code><span class="tx-cmd"><b>$</b> dvc add dataset/foo</span><span class="tx-cmd"><b>$</b> dvc add dataset/test/0</span><span class="tx-cmd"><b>$</b> git add dataset/foo.dvc dataset/test/0.dvc</span><span class="tx-cmd"><b>$</b> git commit -m "DVC track dataset items"</span><span class="tx-cmd"><b>$</b> git diff "${PARENT}..${ADD_COMMIT}" -- "$dvc_file" > "$patch_path"</span></code></pre>
|
| 362 |
+
</div>
|
| 363 |
+
<div class="tx-body">
|
| 364 |
+
<p class="tx-area">Version control</p>
|
| 365 |
+
<h3>Version a dataset with DVC and reconcile its history</h3>
|
| 366 |
+
<p>Set up a DVC-tracked dataset under /app/dataset/ with two items: dataset/foo and dataset/test/0.</p>
|
| 367 |
+
<ul class="tx-meta"><li>313-line reference solution</li><li>Verified in a fresh sandbox</li></ul>
|
| 368 |
+
</div>
|
| 369 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 370 |
+
</article>
|
| 371 |
+
<article class="tx-card reveal" data-index="5" tabindex="0" role="button" aria-label="Open terminal task: Install an HPC scheduler's Python bindings, verified">
|
| 372 |
+
<div class="tx-term" aria-hidden="true">
|
| 373 |
+
<div class="tx-bar"><i></i><i></i><i></i><em>fluxrm/flux-core:focal-v0.48.0</em></div>
|
| 374 |
+
<pre class="tx-screen"><code><span class="tx-cmd"><b>$</b> ACTUAL_HASH=$(sha256sum "$TARBALL" | awk '{print $1}')</span><span class="tx-cmd"><b>$</b> pip install --no-compile "$TARBALL"</span><span class="tx-cmd"><b>$</b> find "$FLUX_ROOT" -type f ! -name '*.pyc' -exec sha256sum {} \; | sort -k2 > "$INSTALLED_MANIFEST"</span><span class="tx-cmd"><b>$</b> cp "$INSTALLED_MANIFEST" "$EXPECTED_MANIFEST"</span><span class="tx-cmd"><b>$</b> flux start --test-size=4 bash -c '…'</span></code></pre>
|
| 375 |
+
</div>
|
| 376 |
+
<div class="tx-body">
|
| 377 |
+
<p class="tx-area">Data & scientific computing</p>
|
| 378 |
+
<h3>Install an HPC scheduler's Python bindings, verified</h3>
|
| 379 |
+
<p>Install the Flux Python package from the tarball at /app/flux-python-0.48.0rc6.tar.gz after verifying its integrity against the provided checksum file.</p>
|
| 380 |
+
<ul class="tx-meta"><li>171-line reference solution</li><li>Verified in a fresh sandbox</li></ul>
|
| 381 |
+
</div>
|
| 382 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 383 |
+
</article>
|
| 384 |
+
<article class="tx-card reveal is-extra" data-index="6" tabindex="0" role="button" aria-label="Open terminal task: Rebuild a GRUB boot sequence from a broken system">
|
| 385 |
+
<div class="tx-term" aria-hidden="true">
|
| 386 |
+
<div class="tx-bar"><i></i><i></i><i></i><em>ubuntu:22.04</em></div>
|
| 387 |
+
<pre class="tx-screen"><code><span class="tx-cmd"><b>$</b> "$CHECK_SCRIPT"</span><span class="tx-cmd"><b>$</b> ERROR_LINE=$(grep -i "ERROR" "$LOG" | grep -i "boot-params" | head -1 || true)</span><span class="tx-cmd"><b>$</b> printf '%s\n' "${param_lines[@]}" > "$BOOT_PARAMS_FILE"</span><span class="tx-cmd"><b>$</b> linux_cmd="linux ${grub_prefix}/${actual_kernel_path} console=${console},${baud}"</span><span class="tx-cmd"><b>$</b> initrd_cmd="initrd ${grub_prefix}/${initrd_path}"</span><span class="tx-cmd"><b>$</b> cat > "$RESULT" <<EOF</span></code></pre>
|
| 388 |
+
</div>
|
| 389 |
+
<div class="tx-body">
|
| 390 |
+
<p class="tx-area">System administration</p>
|
| 391 |
+
<h3>Rebuild a GRUB boot sequence from a broken system</h3>
|
| 392 |
+
<p>Assemble a three-line GRUB boot sequence (linux, initrd, boot) in /app/result.txt for the system rooted at /mnt/target.</p>
|
| 393 |
+
<ul class="tx-meta"><li>214-line reference solution</li><li>Verified in a fresh sandbox</li></ul>
|
| 394 |
+
</div>
|
| 395 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 396 |
+
</article>
|
| 397 |
+
<article class="tx-card reveal is-extra" data-index="7" tabindex="0" role="button" aria-label="Open terminal task: Diagnose and fix a Python dependency bug">
|
| 398 |
+
<div class="tx-term" aria-hidden="true">
|
| 399 |
+
<div class="tx-bar"><i></i><i></i><i></i><em>python:3.11-slim</em></div>
|
| 400 |
+
<pre class="tx-screen"><code><span class="tx-cmd"><b>$</b> python /app/bug.py > /app/result.txt</span><span class="tx-cmd"><b>$</b> /app/validate_output.py /app/result.txt > /app/validation_stdout.txt 2> /app/validation_stderr.txt</span><span class="tx-cmd"><b>$</b> pip install "environs==${REQUIRED_VERSION}" 'marshmallow<4.0.0'</span><span class="tx-cmd"><b>$</b> python /app/bug.py > /app/fixed.txt</span></code></pre>
|
| 401 |
+
</div>
|
| 402 |
+
<div class="tx-body">
|
| 403 |
+
<p class="tx-area">Debugging & performance</p>
|
| 404 |
+
<h3>Diagnose and fix a Python dependency bug</h3>
|
| 405 |
+
<p>In /app, diagnose and fix the environs URL parsing bug.</p>
|
| 406 |
+
<ul class="tx-meta"><li>202-line reference solution</li><li>Verified in a fresh sandbox</li></ul>
|
| 407 |
+
</div>
|
| 408 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 409 |
+
</article>
|
| 410 |
+
<article class="tx-card reveal is-extra" data-index="8" tabindex="0" role="button" aria-label="Open terminal task: Count attack telemetry with the EQL shell">
|
| 411 |
+
<div class="tx-term" aria-hidden="true">
|
| 412 |
+
<div class="tx-bar"><i></i><i></i><i></i><em>python:3.9-slim</em></div>
|
| 413 |
+
<pre class="tx-screen"><code><span class="tx-cmd"><b>$</b> eql shell << 'EQL_IN'</span><span class="tx-cmd"><b>eql></b> input normalized-atomic-red-team.json.gz</span><span class="tx-cmd"><b>eql></b> search | count event_type</span><span class="tx-cmd"><b>eql></b> output counts.json</span><span class="tx-cmd"><b>$</b> /app/check.sh > /app/initial_failure.txt 2>&1</span><span class="tx-cmd"><b>$</b> python3 << 'PYREPAIR'</span></code></pre>
|
| 414 |
+
</div>
|
| 415 |
+
<div class="tx-body">
|
| 416 |
+
<p class="tx-area">Security analytics</p>
|
| 417 |
+
<h3>Count attack telemetry with the EQL shell</h3>
|
| 418 |
+
<p>Working in /app, count each event_type in the dataset '/app/normalized-atomic-red-team.json.gz' using the EQL shell and save results to counts.json.</p>
|
| 419 |
+
<ul class="tx-meta"><li>242-line reference solution</li><li>Verified in a fresh sandbox</li></ul>
|
| 420 |
+
</div>
|
| 421 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 422 |
+
</article>
|
| 423 |
+
<!--TERMINAL_CARDS:END-->
|
| 424 |
+
</div>
|
| 425 |
+
<div class="ex-more">
|
| 426 |
+
<button class="btn btn-ghost" id="tx-more" type="button" aria-expanded="false">Show more terminal tasks</button>
|
| 427 |
+
</div>
|
| 428 |
+
<div class="tx-coverage reveal">
|
| 429 |
+
<div class="tx-coverage-copy">
|
| 430 |
+
<h3>Breadth across real engineering work</h3>
|
| 431 |
+
<p>Share of terminal tasks by area, from system administration and databases to security and scientific computing.</p>
|
| 432 |
+
</div>
|
| 433 |
+
<ul class="tx-bars">
|
| 434 |
+
<!--TERMINAL_COVERAGE:START-->
|
| 435 |
+
<li><span class="txb-label">Software engineering</span><span class="txb-track"><i style="--w:100.0%;--i:0"></i></span><span class="txb-pct">19%</span></li>
|
| 436 |
+
<li><span class="txb-label">Scripting & automation</span><span class="txb-track"><i style="--w:91.5%;--i:1"></i></span><span class="txb-pct">17%</span></li>
|
| 437 |
+
<li><span class="txb-label">System administration</span><span class="txb-track"><i style="--w:72.9%;--i:2"></i></span><span class="txb-pct">14%</span></li>
|
| 438 |
+
<li><span class="txb-label">Environment setup</span><span class="txb-track"><i style="--w:57.4%;--i:3"></i></span><span class="txb-pct">11%</span></li>
|
| 439 |
+
<li><span class="txb-label">Version control</span><span class="txb-track"><i style="--w:44.7%;--i:4"></i></span><span class="txb-pct">8%</span></li>
|
| 440 |
+
<li><span class="txb-label">Containers & cloud</span><span class="txb-track"><i style="--w:36.7%;--i:5"></i></span><span class="txb-pct">7%</span></li>
|
| 441 |
+
<li><span class="txb-label">Security</span><span class="txb-track"><i style="--w:29.3%;--i:6"></i></span><span class="txb-pct">6%</span></li>
|
| 442 |
+
<li><span class="txb-label">Databases</span><span class="txb-track"><i style="--w:19.7%;--i:7"></i></span><span class="txb-pct">4%</span></li>
|
| 443 |
+
<li><span class="txb-label">Data & scientific computing</span><span class="txb-track"><i style="--w:17.0%;--i:8"></i></span><span class="txb-pct">3%</span></li>
|
| 444 |
+
<li><span class="txb-label">Files & storage</span><span class="txb-track"><i style="--w:14.9%;--i:9"></i></span><span class="txb-pct">3%</span></li>
|
| 445 |
+
<li><span class="txb-label">Networking</span><span class="txb-track"><i style="--w:11.7%;--i:10"></i></span><span class="txb-pct">2%</span></li>
|
| 446 |
+
<li><span class="txb-label">Other</span><span class="txb-track"><i style="--w:36.7%;--i:11"></i></span><span class="txb-pct">7%</span></li>
|
| 447 |
+
<!--TERMINAL_COVERAGE:END-->
|
| 448 |
+
</ul>
|
| 449 |
+
</div>
|
| 450 |
+
</div>
|
| 451 |
+
</section>
|
| 452 |
+
|
| 453 |
+
<section class="section section-tint" id="why" aria-labelledby="why-title">
|
| 454 |
<div class="container">
|
| 455 |
<div class="section-head reveal">
|
| 456 |
<p class="kicker">Why verified synthesis</p>
|
|
|
|
| 482 |
</div>
|
| 483 |
</section>
|
| 484 |
|
| 485 |
+
<section class="section" id="capabilities" aria-labelledby="cap-title">
|
| 486 |
<div class="container">
|
| 487 |
<div class="section-head reveal">
|
| 488 |
<p class="kicker">Capabilities</p>
|
|
|
|
| 844 |
</figcaption>
|
| 845 |
</figure>
|
| 846 |
</div>
|
| 847 |
+
<div class="container">
|
| 848 |
+
<div class="growth reveal" id="growth">
|
| 849 |
+
<div class="growth-head">
|
| 850 |
+
<div class="growth-copy">
|
| 851 |
+
<p class="kicker">Watch one task grow</p>
|
| 852 |
+
<h3>Same goal. More to get right at every stage.</h3>
|
| 853 |
+
<p>Successive stages from one task family: <strong>build a Git commit using only low-level plumbing commands</strong>. Each stage keeps the goal and adds requirements, and the reference solution and verifier grow with it. New requirements are highlighted.</p>
|
| 854 |
+
</div>
|
| 855 |
+
<div class="growth-steps" id="growth-steps" role="group" aria-label="Synthesis stages"></div>
|
| 856 |
+
</div>
|
| 857 |
+
<div class="growth-body">
|
| 858 |
+
<div class="growth-instruction" id="growth-instruction" aria-live="polite"></div>
|
| 859 |
+
<div class="growth-stats">
|
| 860 |
+
<div class="gs-stat">
|
| 861 |
+
<span>Reference solution</span>
|
| 862 |
+
<strong id="growth-lines">–</strong>
|
| 863 |
+
<div class="gs-bar"><i id="growth-lines-bar"></i></div>
|
| 864 |
+
</div>
|
| 865 |
+
<div class="gs-stat">
|
| 866 |
+
<span>Instruction</span>
|
| 867 |
+
<strong id="growth-words">–</strong>
|
| 868 |
+
<div class="gs-bar gs-bar-alt"><i id="growth-words-bar"></i></div>
|
| 869 |
+
</div>
|
| 870 |
+
<figure class="gs-spark">
|
| 871 |
+
<svg id="growth-spark" viewBox="0 0 240 72" role="img" aria-label="Reference solution length across stages"></svg>
|
| 872 |
+
<figcaption>Reference solution length by stage</figcaption>
|
| 873 |
+
</figure>
|
| 874 |
+
<p class="gs-note">Illustrative family: stages are related tasks from successive synthesis rounds, shown in order of depth.</p>
|
| 875 |
+
</div>
|
| 876 |
+
</div>
|
| 877 |
+
</div>
|
| 878 |
+
</div>
|
| 879 |
</section>
|
| 880 |
|
| 881 |
<section class="section" id="deliverables" aria-labelledby="deliv-title">
|
|
|
|
| 1081 |
</div>
|
| 1082 |
</div>
|
| 1083 |
|
| 1084 |
+
<div class="ex-modal" id="tx-modal" hidden>
|
| 1085 |
+
<div class="ex-backdrop" data-tx-close></div>
|
| 1086 |
+
<div class="ex-sheet" role="dialog" aria-modal="true" aria-labelledby="txm-title">
|
| 1087 |
+
<header class="ex-head">
|
| 1088 |
+
<div>
|
| 1089 |
+
<p class="ex-domain" id="txm-area"></p>
|
| 1090 |
+
<h3 id="txm-title"></h3>
|
| 1091 |
+
<ul class="ex-tracks" id="txm-tags"></ul>
|
| 1092 |
+
</div>
|
| 1093 |
+
<div class="ex-nav">
|
| 1094 |
+
<button class="icon-btn" type="button" data-tx-prev aria-label="Previous task">←</button>
|
| 1095 |
+
<button class="icon-btn" type="button" data-tx-next aria-label="Next task">→</button>
|
| 1096 |
+
<button class="icon-btn" type="button" data-tx-close aria-label="Close">✕</button>
|
| 1097 |
+
</div>
|
| 1098 |
+
</header>
|
| 1099 |
+
<div class="ex-body">
|
| 1100 |
+
<div class="txm-grid">
|
| 1101 |
+
<div class="txm-col">
|
| 1102 |
+
<h4 class="txm-h">Instruction the agent receives</h4>
|
| 1103 |
+
<div class="txm-instruction" id="txm-instruction"></div>
|
| 1104 |
+
<dl class="txm-facts">
|
| 1105 |
+
<div><dt>Environment</dt><dd id="txm-base"></dd></div>
|
| 1106 |
+
<div><dt>Reference solution</dt><dd id="txm-lines"></dd></div>
|
| 1107 |
+
<div><dt>Verification</dt><dd>The reference solution passes every check in a fresh sandbox, and each check is stated in the instruction.</dd></div>
|
| 1108 |
+
</dl>
|
| 1109 |
+
</div>
|
| 1110 |
+
<div class="txm-col">
|
| 1111 |
+
<h4 class="txm-h">Replay of the reference solution</h4>
|
| 1112 |
+
<div class="tx-term tx-term-lg" aria-hidden="true">
|
| 1113 |
+
<div class="tx-bar"><i></i><i></i><i></i><em id="txm-term-base"></em></div>
|
| 1114 |
+
<pre class="tx-screen" id="txm-replay"><code></code></pre>
|
| 1115 |
+
</div>
|
| 1116 |
+
<h4 class="txm-h">Excerpt of <code>solve.sh</code></h4>
|
| 1117 |
+
<pre class="txm-code" id="txm-code"></pre>
|
| 1118 |
+
</div>
|
| 1119 |
+
</div>
|
| 1120 |
+
<a class="btn btn-dark" id="txm-cta" data-contact data-subject="Terminal task sample request" href="#contact">Request the full task
|
| 1121 |
+
<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M4 10h11m-4-4 4 4-4 4" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
| 1122 |
+
</a>
|
| 1123 |
+
</div>
|
| 1124 |
+
</div>
|
| 1125 |
+
</div>
|
| 1126 |
+
|
| 1127 |
<script type="application/json" id="examples-data">[{"kind": "stl", "title": "OpenSCAD / BOSL2 parametric fan duct", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Regenerate a swept fan-duct mount STL whose inlet size, outlet size, bend angle, and rib count change the geometry.", "software": ["OpenSCAD", "BOSL2"], "artifacts": ["STL mesh", "geometry metrics JSON"], "axes": ["inlet size", "outlet size", "bend angle", "rib count"], "outputs": ["bounding box", "volume", "surface area", "connected components", "sampled surface distance"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "3D mesh", "img": "assets/examples/stl-detail.webp", "alt": "Rendered fan-duct mesh from a public OpenSCAD run"}, {"kind": "foam", "title": "OpenFOAM 2-D dam-break CFD", "domain": "Physical & Engineering Simulation", "color": "#0891b2", "description": "Reconstruct a 2-D dam-break CFD workflow across water height, mesh, gravity, and simulation time.", "software": ["OpenFOAM"], "artifacts": ["blockMesh log", "polyMesh", "initial field files", "case dictionaries"], "axes": ["water height", "mesh", "gravity", "time"], "outputs": ["mesh statistics", "field summaries", "residual/probe behavior"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "CFD mesh", "img": "assets/examples/foam-detail.webp", "alt": "OpenFOAM dam-break mesh drawn from the public polyMesh"}, {"kind": "drc", "title": "KiCad LED-matrix driver PCB", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Reconstruct LED-matrix driver board outputs (DRC report and project files) under row, column, driver, and routing interventions.", "software": ["KiCad"], "artifacts": ["DRC report", "project file list"], "axes": ["rows", "cols", "driver", "routing"], "outputs": ["DRC report summary", "project file inventory"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "PCB layout", "img": "assets/examples/drc-detail.webp", "alt": "KiCad board with design-rule findings plotted at their positions"}, {"kind": "container", "title": "Container SBOM and supply-chain attestation", "domain": "Software & Formal Systems", "color": "#2563eb", "description": "Infer coupled container base-image, package-set, label, entrypoint, and SBOM-scope behavior.", "software": ["Hadolint", "Syft", "Skopeo"], "artifacts": ["Dockerfile", "in-toto attestation", "SPDX SBOM"], "axes": ["base image", "entrypoint", "labels", "package set", "SBOM scope"], "outputs": ["attestation", "base", "layer count", "merkle", "vuln budget"], "tracks": ["Terminal", "Coding"], "modality": "", "img": "assets/examples/container-detail.webp", "alt": "Container image layers and attestation from a public run"}, {"kind": "blender", "title": "Blender cloth flag scene", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Reconstruct cloth-scene behavior under wind, pin-group, frame, and subdivision interventions.", "software": ["Blender"], "artifacts": ["scene graph JSON"], "axes": ["wind strength", "pin group", "frame", "cloth subdiv"], "outputs": ["evaluated objects", "frame", "materials", "node groups", "object counts", "rotation"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "3D scene", "img": "assets/examples/blender-detail.webp", "alt": "Blender cloth scene rotation dial across public scenarios"}, {"kind": "robot", "title": "MuJoCo / URDF mass-inertia repair", "domain": "Physical & Engineering Simulation", "color": "#0891b2", "description": "Infer robot state and trajectory behavior under actuator, collision, pose, joint-limit, and target interventions.", "software": ["MuJoCo", "URDF/MJCF tooling"], "artifacts": ["URDF model", "trajectory CSV", "control summary"], "axes": ["actuator gain", "collision margin", "initial pose", "joint limit", "trajectory target"], "outputs": ["gain", "nq", "nv", "qpos", "qvel"], "tracks": ["Terminal", "Coding"], "modality": "", "img": "assets/examples/robot-detail.webp", "alt": "MuJoCo joint-position trajectories across public scenarios"}, {"kind": "micro", "title": "Microscopy cell segmentation and counting", "domain": "Life & Molecular Sciences", "color": "#16a34a", "description": "Reconstruct cell segmentation and measurement behavior across channel, illumination, threshold, object size, and measurement feature.", "software": ["CellProfiler", "scikit-image", "Bio-Formats"], "artifacts": ["label-mask image", "object-measurements CSV"], "axes": ["channel selection", "illumination correction", "measurement feature", "object size range", "threshold method"], "outputs": ["object count", "area sum", "eccentricity sum", "threshold", "minimum size"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "Microscopy images", "img": "assets/examples/micro-detail.webp", "alt": "Microscopy label masks from public runs"}, {"kind": "astro", "title": "Astronomy FITS/WCS cutout and photometry", "domain": "Earth & Space Sciences", "color": "#db2777", "description": "Reconstruct FITS/WCS cutout and photometry behavior under aperture, background, clipping, threshold, and coordinate-frame interventions.", "software": ["Astropy", "Photutils"], "artifacts": ["FITS image", "photometry catalog CSV"], "axes": ["aperture radius", "background model", "sigma clip", "source threshold", "WCS frame"], "outputs": ["flux", "coordinate frame", "median", "shape", "standard deviation"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "FITS images", "img": "assets/examples/astro-detail.webp", "alt": "Astronomy FITS cutouts from public runs"}, {"kind": "ocr", "title": "Tesseract table-image OCR", "domain": "Data & Document Workflows", "color": "#d97706", "description": "Reconstruct how DPI, font, language, metadata, and page range affect OCR behavior.", "software": ["Pandoc", "Poppler", "Tesseract", "QPDF"], "artifacts": ["OCR summary JSON", "page-preview image"], "axes": ["DPI", "font", "language", "metadata", "page range"], "outputs": ["ink", "line count", "page size", "text digest", "text length"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "Document images", "img": "assets/examples/ocr-detail.webp", "alt": "OCR page preview from a public run"}, {"kind": "color", "title": "Color-space and tone-curve pipeline", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Infer a color pipeline across color space, white point, tone curve, demosaicing, and compression quality.", "software": ["colour-science", "ImageMagick", "scikit-image"], "artifacts": ["color measurements JSON", "PPM preview"], "axes": ["color space", "white point", "tone curve", "demosaic method", "compression quality"], "outputs": ["mean color", "image shape", "XYZ tristimulus values"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "Images", "img": "assets/examples/color-detail.webp", "alt": "Color-pipeline previews from public runs"}]</script>
|
| 1128 |
+
<script type="application/json" id="terminal-data">{"tasks": [{"title": "Repair and cross-build an AArch64 assembly program", "area": "Software engineering", "summary": "Fix the assembly source at /app/horas_seg.s so it prompts for integer hours and correctly prints the equivalent seconds (e.g., 2 → 7200 segundos.).", "instruction": "<p>Fix the assembly source at /app/horas_seg.s so it prompts for integer hours and correctly prints the equivalent seconds (e.g., 2 → 7200 segundos.).<\/p><p>Compile the repaired source into /app/horas_seg.<\/p><p>Write a self-validating build script at /app/build.sh and make it executable.<\/p><p>The script must source /app/toolchain.cfg to obtain CROSS_COMPILE, use the prefix to locate the cross-assembler and linker (no hardcoded paths), assemble and link the program, then validate the resulting binary by running it with input 2 and checking that the output contains "7200 segundos.".<\/p><p>On success the script must print "BUILD SUCCESS" and exit 0; on failure it must print "VALIDATION FAILED" and exit non-zero.<\/p><p>The sysroot at /usr/aarch64-linux-gnu is available for cross-execution via QEMU if needed.<\/p><p>Generate a build manifest at /app/build-info.txt using the format:<\/p><p>as_version: <assembler version string><\/p><p>ld_version: <linker version string><\/p><p>sha256: <64-character lowercase hex hash of /app/horas_seg><\/p><p>Create a symlink /usr/local/bin/horas_seg → /app/horas_seg.<\/p>", "base": "ubuntu:22.04", "lines": 239, "tags": ["assembly", "arm64", "aarch64", "compilation"], "replay": [["$", "source \"$CFG\""], ["$", "\"$AS\" --version"], ["$", "cat > /app/horas_seg.s << 'SOURCEEOF'"], ["$", "TEST_OUT=$(run_program \"2\" 2>&1)"], ["$", "chmod +x /app/build.sh"], ["$", "ln -sf /app/horas_seg /usr/local/bin/horas_seg"]], "code": "set -e\nCFG=\"/app/toolchain.cfg\"\nif [ ! -f \"$CFG\" ]; then\n echo \"ERROR: Toolchain configuration file $CFG not found\"\n exit 1\nfi\nsource \"$CFG\"\nif [ -z \"$CROSS_COMPILE\" ]; then\n echo \"ERROR: CROSS_COMPILE not defined in $CFG\"\n exit 1\nfi\nAS=$(command -v \"${CROSS_COMPILE}as\")\nLD=$(command -v \"${CROSS_COMPILE}ld\")\nif [ -z \"$AS\" ]; then\n echo \"ERROR: ${CROSS_COMPILE}as not found in PATH\"\n exit 1\nfi\nif [ -z \"$LD\" ]; then\n echo \"ERROR: ${CROSS_COMPILE}ld not found in PATH\"\n exit 1\nfi\n\"$AS\" --version >/dev/null 2>&1 || { echo \"ERROR: $AS does not work\"; exit 1; }\n\"$LD\" --version >/dev/null 2>&1 || { echo \"ERROR: $LD does not work\"; exit 1; }\nrun_program() {\n local input_str=\"$1\"\n if /app/horas_seg <<< \"$input_str\" 2>/dev/null; then\n return 0\n fi\n if command -v qemu-aarch64 >/dev/null 2>&1; then\n local qemu_args=(\"qemu-aarch64\")"}, {"title": "Wire a network namespace with a veth pair", "area": "Networking", "summary": "Set up a Linux network namespace `t1` with a veth pair.", "instruction": "<p>Set up a Linux network namespace <code>t1<\/code> with a veth pair.<\/p><p>Inside <code>t1<\/code> assign <code>10.0.0.1/24<\/code>; on the host assign <code>10.0.0.2/24<\/code>.<\/p><p>Bring all interfaces up and enable loopback inside the namespace.<\/p><p>Derive the MTU from <code>/app/veth_mtu.cfg<\/code> and the host kernel version; apply that MTU to both veth endpoints and write the same value to <code>/etc/veth_mtu_policy.conf<\/code>.<\/p><p>Confirm bidirectional pings between the two IPs.<\/p><p>Produce a network state report at <code>/app/network_state_report.txt<\/code> following <code>/app/REPORT_SPEC.md<\/code>.<\/p><p>Record the derivation steps and chosen MTU in <code>/tmp/veth_debug.log<\/code>.<\/p><p>Run the validation script <code>/app/validate_report.sh<\/code>.<\/p><p>If it fails, interpret the failure, correct the underlying problem, and re‑run the script until it succeeds.<\/p>", "base": "ubuntu:22.04", "lines": 213, "tags": ["network-namespace", "veth", "iproute2", "linux-networking"], "replay": [["$", "ip netns add t1"], ["$", "ip link add veth0 mtu \"$CHOSEN\" type veth peer name veth1 mtu \"$CHOSEN\""], ["$", "ip link set veth0 netns t1"], ["$", "ip netns exec t1 ip addr add 10.0.0.1/24 dev veth0"], ["$", "ip addr add 10.0.0.2/24 dev veth1"], ["$", "ip netns exec t1 ip link set veth0 up"], ["$", "ip link set veth1 up"]], "code": "set -e\nCFG=\"/app/veth_mtu.cfg\"\nREPORT=\"/app/network_state_report.txt\"\nPOLICY=\"/etc/veth_mtu_policy.conf\"\nDEBUG_LOG=\"/tmp/veth_debug.log\"\nVALIDATE_SCRIPT=\"/app/validate_report.sh\"\nSPEC=\"/app/REPORT_SPEC.md\"\necho \"=== Inspect configuration and specification ===\"\nif [ ! -f \"$CFG\" ]; then\n echo \"Error: $CFG not found\" >&2\n exit 1\nfi\nif [ ! -f \"$SPEC\" ]; then\n echo \"Error: $SPEC not found\" >&2\n exit 1\nfi\nDEFAULT_MTU=$(grep -oP '^mtu=\\K[0-9]+' \"$CFG\" || true)\nif [ -z \"$DEFAULT_MTU\" ]; then\n echo \"Error: no default mtu= line in config\" >&2\n exit 1\nfi\nCOND=$(grep -oP '^if_kernel_gte=\\K[^:]+:[0-9]+' \"$CFG\" || true)\nif [ -n \"$COND\" ]; then\n THRESHOLD=$(echo \"$COND\" | cut -d: -f1)\n COND_MTU=$(echo \"$COND\" | cut -d: -f2)\nelse\n THRESHOLD=\"\"\n COND_MTU=\"\"\nfi\nKV=$(uname -r | cut -d- -f1)"}, {"title": "Align a container build with its Kustomize manifest", "area": "Containers & cloud", "summary": "Align the Dockerfile at /environment/Dockerfile with the files referenced by the kustomization in /app (kustomization.yaml), notably config.yaml.", "instruction": "<p>Align the Dockerfile at /environment/Dockerfile with the files referenced by the kustomization in /app (kustomization.yaml), notably config.yaml.<\/p><p>Generate all required deliverables: result.txt (containing 'apiVersion=v1'), integrity checksums, a summary, a build log, and an artifact inventory.<\/p><p>Use the inventory generator script at /opt/sources/templates/inventory_gen.sh — follow /environment/GENERATOR.md for its working directory and invocation.<\/p><p>Inspect /environment/REQUIREMENTS.md and /environment/EVIDENCE_GUIDE.md for additional requirements, evidence bundle specifications, and archive packaging rules.<\/p><p>Assemble an evidence bundle in /app/evidence that includes the deliverables and a manifest, then create a compressed tar archive named evidence.tar.gz inside that directory that contains the bundle contents.<\/p><p>Before final verification, update config.yaml according to /environment/CONFIG_SCHEMA.md and validate it with /opt/tools/validate_config.sh.<\/p><p>Finally, run /opt/tools/verify.sh to complete verification (it now also checks the evidence archive).<\/p>", "base": "ubuntu:22.04", "lines": 311, "tags": ["kubernetes", "kustomize", "secrets"], "replay": [["$", "cp -f \"$SOURCES_DIR/config.yaml\" \"$APP_DIR/config.yaml\""], ["$", "sed -i \"/^CMD /i COPY config.yaml /app/config.yaml\" \"$DOCKERFILE\""], ["$", "sha256sum \"$APP_DIR/$f\" >> \"$INTEGRITY\""], ["$", "kustomize build \"$APP_DIR\" > \"$RESULT\""], ["$", "sed -i 's/^apiVersion: v1$/apiVersion=v1/' \"$RESULT\""], ["$", "tar czf evidence.tar.gz *"]], "code": "set -euo pipefail\nAPP_DIR=\"/app\"\nSOURCES_DIR=\"/opt/sources\"\nDOCKERFILE=\"/environment/Dockerfile\"\nREQUIREMENTS=\"/environment/REQUIREMENTS.md\"\nRESULT=\"$APP_DIR/result.txt\"\nSUMMARY=\"$APP_DIR/summary.txt\"\nINTEGRITY=\"$APP_DIR/integrity.txt\"\nINVENTORY=\"$APP_DIR/artifact_inventory.txt\"\nBUILD_LOG=\"$APP_DIR/build.log\"\nVERIFY_SCRIPT=\"/opt/tools/verify.sh\"\nVALIDATE_CONFIG=\"/opt/tools/validate_config.sh\"\nCONFIG_SCHEMA=\"/environment/CONFIG_SCHEMA.md\"\nGENERATOR_DOC=\"/environment/GENERATOR.md\"\nEVIDENCE_GUIDE=\"/environment/EVIDENCE_GUIDE.md\"\nEVIDENCE_DIR=\"/app/evidence\"\nBUNDLE_MANIFEST=\"$EVIDENCE_DIR/manifest.txt\"\nBUNDLE_SUMMARY=\"$EVIDENCE_DIR/bundle_summary.txt\"\nMAX_ATTEMPTS=5\necho \"=== Stage: inspect ===\"\nfor f in \"$VERIFY_SCRIPT\" \"$DOCKERFILE\" \"$APP_DIR/kustomization.yaml\" \"$SOURCES_DIR/config.yaml\" \"$REQUIREMENTS\" \"$GENERATOR_DOC\" \"$CONFIG_SCHEMA\" \"$VALIDATE_CONFIG\" \"$EVIDENCE_GUIDE\"; do\n if [ ! -f \"$f\" ]; then\n echo \"ERROR: $f not found.\" >&2\n exit 1\n fi\ndone\nif [ ! -x \"$VALIDATE_CONFIG\" ]; then\n echo \"ERROR: $VALIDATE_CONFIG is not executable.\" >&2\n exit 1\nfi"}, {"title": "Stand up InfluxDB 2 against a compliance policy", "area": "Databases", "summary": "Set up InfluxDB 2 using the configuration at /etc/influxdb/init.json.", "instruction": "<p>Set up InfluxDB 2 using the configuration at /etc/influxdb/init.json.<\/p><p>A policy file at /etc/influxdb/schema_requirements.json defines required rules—including organization, bucket, retention, and bucket description—that your setup must match.<\/p><p>Use the compliance check script in /app/ to verify your configuration against these rules, then run the validation script and iterate until all checks pass.<\/p><p>Both compliance and validation must succeed before finalizing.<\/p><p>Produce a report at /app/result.txt containing the active connection configuration, listings of all organizations and buckets, a reconciliation section that shows MATCH for every parameter, and the final output of the compliance and validation steps.<\/p><p>Avoid destructive actions if the database already holds configuration.<\/p>", "base": "debian:bookworm", "lines": 329, "tags": ["influxdb", "database", "system-administration"], "replay": [["$", "jq empty \"$f\""], ["$", "influx setup --username \"$USERNAME\" --password \"$PASSWORD\" --org \"$ORG\" --bucket \"$BUCKET\" --retention…"], ["$", "influx bucket update --id \"$BID\" --retention \"$RETENTION\""], ["$", "influx bucket update --id \"$BID\" --description \"$REQUIRED_BUCKET_DESC\""], ["$", "chmod +x /app/validate.sh"]], "code": "set -e\nfor i in {1..30}; do\n if curl -s http://localhost:8086/ping >/dev/null 2>&1; then\n break\n fi\n sleep 1\ndone\nif ! command -v jq >/dev/null 2>&1; then\n apt-get update -qq && apt-get install -y -qq jq\nfi\nfor f in /etc/influxdb/init.json /etc/influxdb/schema_requirements.json; do\n if [ ! -f \"$f\" ]; then\n echo \"Error: missing evidence file $f\" >&2\n exit 1\n fi\n jq empty \"$f\" || {\n echo \"Error: invalid JSON in $f\" >&2\n exit 1\n }\ndone\nREQUIRED_ORG=$(jq -r '.org // empty' /etc/influxdb/schema_requirements.json)\nREQUIRED_BUCKET=$(jq -r '.bucket // empty' /etc/influxdb/schema_requirements.json)\nREQUIRED_RETENTION=$(jq -r '.retention // \"0s\"' /etc/influxdb/schema_requirements.json)\nREQUIRED_BUCKET_DESC=$(jq -r '.bucket_description // empty' /etc/influxdb/schema_requirements.json)\nUSERNAME=$(jq -r '.username' /etc/influxdb/init.json)\nPASSWORD=$(jq -r '.password' /etc/influxdb/init.json)\nORG=$(jq -r '.org' /etc/influxdb/init.json)\nBUCKET=$(jq -r '.bucket' /etc/influxdb/init.json)\nRETENTION=$(jq -r '.retention' /etc/influxdb/init.json)\nCHANGED=0"}, {"title": "Version a dataset with DVC and reconcile its history", "area": "Version control", "summary": "Set up a DVC-tracked dataset under /app/dataset/ with two items: dataset/foo and dataset/test/0.", "instruction": "<p>Set up a DVC-tracked dataset under /app/dataset/ with two items: dataset/foo and dataset/test/0.<\/p><p>Track both with DVC, remove the original data, and commit the resulting .dvc files.<\/p><p>Then produce the following artifacts under /app: dvc_inventory.json, dvc_reconciliation.md, dvc_changes.diff, dvc_status.txt, and a directory /app/patches/ containing a patch file for each of dataset/foo.dvc and dataset/test/0.dvc that captures the changes introduced when that file was first committed.<\/p><p>The reconciliation report must document the absence of the data, the git commits that introduced each .dvc file (SHA and message), and the baseline tag (name and commit SHA).<\/p><p>The diff should be taken from that tag to HEAD.<\/p><p>The repository already has git and DVC initialized, and a git tag marks the initial DVC initialization; discover and use that tag as the baseline.<\/p><p>Refer to /app/task_files/ for the required formats of the inventory and the reconciliation report.<\/p>", "base": "ubuntu:22.04", "lines": 313, "tags": ["dvc", "data-versioning", "version-control"], "replay": [["$", "dvc add dataset/foo"], ["$", "dvc add dataset/test/0"], ["$", "git add dataset/foo.dvc dataset/test/0.dvc"], ["$", "git commit -m \"DVC track dataset items\""], ["$", "git diff \"${PARENT}..${ADD_COMMIT}\" -- \"$dvc_file\" > \"$patch_path\""]], "code": "set -euo pipefail\nif [ -s /app/dvc_changes.diff ] && \\\n [ -s /app/dvc_reconciliation.md ] && \\\n [ -s /app/dvc_inventory.json ] && \\\n [ -s /app/dvc_status.txt ] && \\\n grep -q 'Commit message:' /app/dvc_reconciliation.md && \\\n grep -q 'Baseline tag:' /app/dvc_reconciliation.md && \\\n [ -d /app/patches ] && \\\n [ \"$(ls -1 /app/patches/*.patch 2>/dev/null | wc -l)\" -ge 2 ]; then\n echo \"Required artifacts with commit messages, baseline tag, and patches already present. Nothing to do.\"\n exit 0\nfi\ncd /app\nrm -f dataset/foo.dvc dataset/test/0.dvc\nrm -rf dataset/foo dataset/test/0\nrm -f /app/dvc_reconciliation.md \\\n /app/dvc_inventory.json \\\n /app/dvc_changes.diff \\\n /app/dvc_status.txt\nrm -rf /app/patches\nINIT_COMMIT=$(git rev-list --max-parents=0 HEAD)\nif [ -z \"$INIT_COMMIT\" ]; then\n echo \"ERROR: could not determine initial commit\"\n exit 1\nfi\necho \"Initial commit: $INIT_COMMIT\"\nreadarray -t TAGS < <(git tag --points-at \"$INIT_COMMIT\")\nif [ \"${#TAGS[@]}\" -eq 0 ]; then\n echo \"ERROR: no tag found pointing to the initial commit\"\n exit 1"}, {"title": "Install an HPC scheduler's Python bindings, verified", "area": "Data & scientific computing", "summary": "Install the Flux Python package from the tarball at /app/flux-python-0.48.0rc6.tar.gz after verifying its integrity against the provided checksum file.", "instruction": "<p>Install the Flux Python package from the tarball at /app/flux-python-0.48.0rc6.tar.gz after verifying its integrity against the provided checksum file.<\/p><p>The expected manifest file may be outdated; if the installed layout differs, update the manifest and note the discrepancy in the installation report.<\/p><p>The installation report at /app/installation_report.txt must include the verified tarball hash, describe any manifest changes, and also contain additional package metadata specified by the configuration at /app/config/metadata.json — follow that config's instructions for intermediate reporting.<\/p><p>Finally, use the Flux Python bindings to produce /app/result.txt containing exactly the string found in /app/config/expected.txt.<\/p>", "base": "fluxrm/flux-core:focal-v0.48.0", "lines": 171, "tags": ["flux", "hpc", "job-scheduling", "python-bindings"], "replay": [["$", "ACTUAL_HASH=$(sha256sum \"$TARBALL\" | awk '{print $1}')"], ["$", "pip install --no-compile \"$TARBALL\""], ["$", "find \"$FLUX_ROOT\" -type f ! -name '*.pyc' -exec sha256sum {} \\; | sort -k2 > \"$INSTALLED_MANIFEST\""], ["$", "cp \"$INSTALLED_MANIFEST\" \"$EXPECTED_MANIFEST\""], ["$", "flux start --test-size=4 bash -c '…'"]], "code": "set -euo pipefail\nTARBALL=\"/app/flux-python-0.48.0rc6.tar.gz\"\nCHECKSUM_FILE=\"/app/checksum.sha256\"\nVALIDATION_FILE=\"/app/validation.txt\"\nCONFIG_FILE=\"/app/config/expected.txt\"\nRESULT_FILE=\"/app/result.txt\"\nEXPECTED_MANIFEST=\"/app/expected_manifest.txt\"\nINSTALLED_MANIFEST=\"/app/installed_manifest.txt\"\nINSTALLATION_REPORT=\"/app/installation_report.txt\"\nMETADATA_CONFIG=\"/app/config/metadata.json\"\necho \"=== INSPECT: verify required inputs exist ===\"\nfor f in \"$TARBALL\" \"$CHECKSUM_FILE\" \"$EXPECTED_MANIFEST\" \"$CONFIG_FILE\" \"$METADATA_CONFIG\"; do\n if [ ! -f \"$f\" ]; then\n echo \"ERROR: Required file $f not found\" >&2\n exit 1\n fi\ndone\necho \"=== INSPECT: read metadata configuration ===\"\nMETADATA_FILE=$(python3 -c \"import json; cfg=json.load(open('$METADATA_CONFIG')); print(cfg['metadata_file'])\")\nFIELDS=$(python3 -c \"import json; cfg=json.load(open('$METADATA_CONFIG')); print(' '.join(cfg['required_metadata']))\")\necho \"Metadata will be gathered for fields: $FIELDS\"\necho \"Intermediate metadata file: /app/$METADATA_FILE\"\necho \"=== DERIVE: verify tarball hash ===\"\nACTUAL_HASH=$(sha256sum \"$TARBALL\" | awk '{print $1}')\nEXPECTED_HASH=$(awk '{print $1}' \"$CHECKSUM_FILE\")\nif [ \"$ACTUAL_HASH\" != \"$EXPECTED_HASH\" ]; then\n echo \"ERROR: Tarball checksum mismatch\" >&2\n exit 1\nfi\necho \"=== VALIDATE checksum OK, writing validation report ===\""}, {"title": "Rebuild a GRUB boot sequence from a broken system", "area": "System administration", "summary": "Assemble a three-line GRUB boot sequence (linux, initrd, boot) in /app/result.txt for the system rooted at /mnt/target.", "instruction": "<p>Assemble a three-line GRUB boot sequence (linux, initrd, boot) in /app/result.txt for the system rooted at /mnt/target.<\/p><p>Use /app/boot.cfg for console and baud (the linux line must contain <code>console=ttyS0,115200<\/code>).<\/p><p>The target's /mnt/target/etc/device-map provides the GRUB device prefix, and /mnt/target/boot/RULES.txt gives the kernel selection rule (pick the highest version).<\/p><p>Some configuration files may be missing; use documentation under /mnt/target/etc/ to reconstruct them.<\/p><p>After building the sequence, run /app/check_boot.sh to validate.<\/p><p>Its log in /var/log/boot_check.log will report missing boot-params.<\/p><p>Inspect the log, fix any issues, re-run the check until it returns no errors, then write a root-cause diagnosis report to /app/diagnosis.txt citing the logged evidence.<\/p>", "base": "ubuntu:22.04", "lines": 214, "tags": ["grub", "bootloader", "linux", "system-administration"], "replay": [["$", "\"$CHECK_SCRIPT\""], ["$", "ERROR_LINE=$(grep -i \"ERROR\" \"$LOG\" | grep -i \"boot-params\" | head -1 || true)"], ["$", "printf '%s\\n' \"${param_lines[@]}\" > \"$BOOT_PARAMS_FILE\""], ["$", "linux_cmd=\"linux ${grub_prefix}/${actual_kernel_path} console=${console},${baud}\""], ["$", "initrd_cmd=\"initrd ${grub_prefix}/${initrd_path}\""], ["$", "cat > \"$RESULT\" <<EOF"]], "code": "set -euo pipefail\nmkdir -p /var/log\nLOG=\"/var/log/boot_check.log\"\nCHECK_SCRIPT=\"/app/check_boot.sh\"\nRESULT=\"/app/result.txt\"\nDIAGNOSIS=\"/app/diagnosis.txt\"\nTARGET=\"/mnt/target\"\nBOOT_PARAMS_FILE=\"${TARGET}/etc/boot-params\"\nSPEC_FILE=\"${TARGET}/etc/params-spec.txt\"\nDEVICE_MAP_FILE=\"${TARGET}/etc/device-map\"\nRULES_FILE=\"${TARGET}/boot/RULES.txt\"\nCONFIG=\"/app/boot.cfg\"\nif [[ ! -x \"$CHECK_SCRIPT\" ]]; then\n echo \"Error: $CHECK_SCRIPT not found or not executable\" >&2\n exit 1\nfi\necho \"Running initial boot check...\" >&2\nset +e # initial run is expected to fail because boot-params missing\n\"$CHECK_SCRIPT\"\ninitial_exit=$?\nset -e\nif [[ ! -f \"$LOG\" ]]; then\n echo \"Error: Log file $LOG was not created by $CHECK_SCRIPT\" >&2\n exit 1\nfi\necho \"Inspecting $LOG...\" >&2\nERROR_LINE=$(grep -i \"ERROR\" \"$LOG\" | grep -i \"boot-params\" | head -1 || true)\nif [[ -z \"$ERROR_LINE\" ]]; then\n echo \"Warning: No ERROR about boot-params found in $LOG. Proceeding without repair.\" >&2\n ROOT_CAUSE=\"No error detected; boot-params may already exist.\""}, {"title": "Diagnose and fix a Python dependency bug", "area": "Debugging & performance", "summary": "In /app, diagnose and fix the environs URL parsing bug.", "instruction": "<p>In /app, diagnose and fix the environs URL parsing bug.<\/p><p>Run bug.py to capture the original output and use validate_output.py to diagnose the failure.<\/p><p>Consult changelog.md to determine the required environs version, upgrade the library, and produce a corrected output in fixed.txt.<\/p><p>Write a test suite test_bug.py covering both mongodb and mongodb+srv URL schemes.<\/p><p>The suite must include a test that runs validate_output.py against bug.py’s output after the fix and asserts the validator exits successfully.<\/p><p>Run the tests and save the report as test_report.txt.<\/p><p>Finally, create validation_passed.txt and a debug summary debug_summary.txt describing the error and the fix.<\/p>", "base": "python:3.11-slim", "lines": 202, "tags": ["python", "library-bug", "url-parsing", "environs"], "replay": [["$", "python /app/bug.py > /app/result.txt"], ["$", "/app/validate_output.py /app/result.txt > /app/validation_stdout.txt 2> /app/validation_stderr.txt"], ["$", "pip install \"environs==${REQUIRED_VERSION}\" 'marshmallow<4.0.0'"], ["$", "python /app/bug.py > /app/fixed.txt"]], "code": "set -euo pipefail\necho \"Ensuring pytest is available\"\npython -m pytest --version >/dev/null 2>&1 || pip install pytest\necho \"Stage 1: Create original bug.py (known buggy)\"\ncat > /app/bug.py << 'EOF'\nfrom environs import Env\nenv = Env()\nMONGODB_URL = env.url(\n \"MONGODB_URL\",\n default=\"mongodb://user:pass@mongo.example.local/db?authSource=admin\",\n schemes={\"mongodb\", \"mongodb+srv\"},\n require_tld=False,\n)\nprint(MONGODB_URL)\nEOF\necho \"Stage 2: Run bug.py and capture original output\"\npython /app/bug.py > /app/result.txt\necho \"Stage 3: Validate original output and interpret failure\"\nset +e\n/app/validate_output.py /app/result.txt > /app/validation_stdout.txt 2> /app/validation_stderr.txt\nVALIDATION_EXIT=$?\nset -e\nif [ $VALIDATION_EXIT -eq 0 ]; then\n echo \"ERROR: validate_output.py unexpectedly succeeded on buggy output\" >&2\n exit 1\nfi\nif ! grep -q \"ParseResult\" /app/validation_stderr.txt; then\n echo \"ERROR: Expected 'ParseResult' indication in validator failure output\" >&2\n exit 1\nfi"}, {"title": "Count attack telemetry with the EQL shell", "area": "Security analytics", "summary": "Working in /app, count each event_type in the dataset '/app/normalized-atomic-red-team.json.gz' using the EQL shell and save results to counts.json.", "instruction": "<p>Working in /app, count each event_type in the dataset '/app/normalized-atomic-red-team.json.gz' using the EQL shell and save results to counts.json.<\/p><p>Generate a Markdown summary table in counts_summary.md.<\/p><p>Compare the actual counts to the expected values in config/expected_counts.json.<\/p><p>Before repairing any mismatches, run the local validation script ./check.sh and capture its exact failure output to /app/initial_failure.txt.<\/p><p>The initial failure output includes a network event type count mismatch—ensure this output is saved before applying fixes.<\/p><p>Then, using the validation script and the failure information, fix the mismatches: update config/expected_counts.json (keeping its metadata), record changes in repair_note.txt, and iterate until check.sh passes.<\/p><p>Finally, produce validation_report.json with status 'pass' and empty mismatches, and create /app/analysis_metadata.json as described in README.md.<\/p><p>See README.md for the full list of deliverables.<\/p>", "base": "python:3.9-slim", "lines": 242, "tags": ["eql", "event-query-language", "data-analysis", "json"], "replay": [["$", "eql shell << 'EQL_IN'"], ["eql>", "input normalized-atomic-red-team.json.gz"], ["eql>", "search | count event_type"], ["eql>", "output counts.json"], ["$", "/app/check.sh > /app/initial_failure.txt 2>&1"], ["$", "python3 << 'PYREPAIR'"]], "code": "set -euo pipefail\ncd /app\necho \"[1/6] Running EQL analysis...\"\neql shell << 'EQL_IN'\ninput normalized-atomic-red-team.json.gz\nsearch | count event_type\noutput counts.json\nEQL_IN\nif [ ! -s counts.json ]; then\n echo \"ERROR: counts.json is missing or empty after EQL run.\" >&2\n exit 2\nfi\necho \"[1/6] counts.json generated.\"\necho \"[2/6] Generating markdown summary...\"\npython3 << 'PYMDS'\nimport json\ndef load_counts(path):\n with open(path) as f:\n raw = f.read().strip()\n try:\n data = json.loads(raw)\n except json.JSONDecodeError:\n data = [json.loads(line) for line in raw.splitlines() if line.strip()]\n if isinstance(data, dict):\n return {k: v for k, v in data.items() if isinstance(v, int)}\n counts = {}\n for item in data:\n if not isinstance(item, dict):\n continue\n key = item.get(\"event_type\", item.get(\"key\"))"}], "growth": {"goal": "Build a Git commit using only low-level plumbing commands", "stages": [{"lines": 21, "words": 97, "segments": [{"html": "Create a Git repository at <code>/tmp/test<\/code> and build a single commit using only low-level plumbing commands—no <code>git add<\/code>, <code>git commit<\/code>, or other porcelain.", "new": false}, {"html": "Before creating the commit, source the environment file at <code>/env/git-env.sh<\/code> to provide the author and committer identity.", "new": false}, {"html": "The commit must contain a single file <code>a.txt<\/code> with the content <code>test content<\/code> (followed by a newline, as <code>echo<\/code> produces), have the commit message <code>commit 1<\/code>, and be reachable from the <code>master<\/code> branch.", "new": false}, {"html": "When finished, <code>git log master<\/code> should show exactly that one commit and <code>git cat-file -p<\/code> on the commit’s tree object should list only <code>a.txt<\/code>.", "new": false}]}, {"lines": 95, "words": 107, "segments": [{"html": "Create a Git repository at <code>/tmp/test<\/code> and construct a complete commit using only Git's low-level plumbing commands (no <code>git add<\/code>, <code>git commit<\/code>, etc.).", "new": false}, {"html": "The commit must contain a single file <code>a.txt<\/code> with the exact content <code>test content<\/code> followed by a newline, have the commit message <code>commit 1<\/code>, and be reachable from the <code>master<\/code> branch (<code>git log master<\/code> should show it as the sole commit).", "new": false}, {"html": "After the commit is ready, produce a JSON snapshot of the repository's commit structure at <code>/tmp/test/repo_snapshot.json<\/code>.", "new": true}, {"html": "Validate it with <code>/usr/local/bin/validate_snapshot.sh<\/code>.", "new": true}, {"html": "Then produce a YAML snapshot at <code>/tmp/test/repo_snapshot.yaml<\/code> that captures the same semantic information.", "new": true}, {"html": "Validate it with <code>/usr/local/bin/validate_snapshot_yaml.sh<\/code>.", "new": true}, {"html": "Both validation scripts must exit successfully.", "new": true}]}, {"lines": 114, "words": 76, "segments": [{"html": "Create a Git repository at <code>/tmp/test<\/code> using only plumbing commands (no <code>git add<\/code> or <code>git commit<\/code>).", "new": false}, {"html": "The repository must contain a single commit on branch <code>master<\/code> with file <code>a.txt<\/code> (content <code>test content<\/code>) and a file <code>b.txt<\/code>—determine the correct content for <code>b.txt<\/code> from available environment clues.", "new": true}, {"html": "After the commit, produce an object manifest at <code>/tmp/test/manifest.txt<\/code> following the format described in an environment file named <code>manifest_schema.txt<\/code> (locate and refer to it).", "new": true}, {"html": "Then generate a reconciliation report at <code>/tmp/test/report.txt<\/code>.", "new": true}]}, {"lines": 157, "words": 89, "segments": [{"html": "Create a Git repository at <code>/tmp/test<\/code> using only plumbing commands (no <code>git add<\/code> or <code>git commit<\/code>).", "new": false}, {"html": "The repository must contain a single commit on branch <code>master<\/code> with message <code>first commit<\/code>, containing file <code>a.txt<\/code> (content <code>test content<\/code>) and a file <code>b.txt<\/code>—determine the correct content for <code>b.txt<\/code> from available environment clues.", "new": false}, {"html": "After the commit, produce an object manifest at <code>/tmp/test/manifest.txt<\/code> following the format described in an environment file named <code>manifest_schema.txt<\/code> (locate and refer to it).", "new": false}, {"html": "Then generate a reconciliation report at <code>/tmp/test/report.txt<\/code> that verifies object types and sizes against the manifest.", "new": true}]}, {"lines": 187, "words": 98, "segments": [{"html": "Create a Git repository at <code>/tmp/test<\/code> using only plumbing commands (no <code>git add<\/code>, <code>git commit<\/code>).", "new": false}, {"html": "The repository must contain a single commit on branch <code>master<\/code> with message <code>first commit<\/code>, including <code>a.txt<\/code> (content <code>test content<\/code>) and <code>b.txt<\/code>.", "new": false}, {"html": "Obtain the content of <code>b.txt<\/code> from the commit tagged <code>release/v1.0<\/code> in the forensic repository at <code>/app/forensics<\/code>.", "new": true}, {"html": "After the commit, produce an object manifest at <code>/tmp/test/manifest.txt<\/code> following the format specified in the <code>manifest_schema.txt<\/code> file (locate and refer to it).", "new": false}, {"html": "The manifest must include repository-relative paths for blobs.", "new": true}, {"html": "Finally, generate a reconciliation report at <code>/tmp/test/report.txt<\/code> that verifies object types and sizes against the manifest.", "new": false}]}, {"lines": 217, "words": 119, "segments": [{"html": "Create a Git repository at <code>/tmp/test<\/code> using only plumbing commands (no <code>git add<\/code>, <code>git commit<\/code>).", "new": false}, {"html": "The repository must contain a single commit on branch <code>master<\/code> with message <code>first commit<\/code>, including <code>a.txt<\/code> (content <code>test content<\/code>) and <code>b.txt<\/code>.", "new": false}, {"html": "Obtain the content of <code>b.txt<\/code> from the commit tagged <code>release/v1.0<\/code> in the forensic repository at <code>/app/forensics<\/code>.", "new": false}, {"html": "After the commit, produce an object manifest at <code>/tmp/test/manifest.txt<\/code> following the format specified in the <code>manifest_schema.txt<\/code> file (locate and refer to it).", "new": false}, {"html": "The manifest must include repository-relative paths for blobs.", "new": false}, {"html": "Generate a forensic diff report at <code>/tmp/test/forensic_diff.txt<\/code> showing the diff of <code>b.txt<\/code> between the parent of <code>release/v1.0<\/code> and the tagged commit.", "new": true}, {"html": "Finally, generate a reconciliation report at <code>/tmp/test/report.txt<\/code> that verifies object types and sizes against the manifest.", "new": false}]}, {"lines": 236, "words": 139, "segments": [{"html": "Create a Git repository at /tmp/test using only plumbing commands (no <code>git add<\/code>, <code>git commit<\/code>).", "new": false}, {"html": "The repository must contain a single commit on branch <code>master<\/code> with message <code>first commit<\/code>.", "new": false}, {"html": "Include <code>a.txt<\/code> with content <code>test content<\/code> and <code>b.txt<\/code>.", "new": true}, {"html": "Obtain the content of <code>b.txt<\/code> from the commit tagged <code>release/v1.0<\/code> in the forensic repository at /app/forensics.", "new": false}, {"html": "After the commit, produce an object manifest at /tmp/test/manifest.txt following the format described in the manifest schema file.", "new": false}, {"html": "Use the workspace README at /app/README.md to locate that schema file.", "new": true}, {"html": "The manifest must list repository-relative paths for blobs.", "new": false}, {"html": "Generate a forensic diff report at /tmp/test/forensic_diff.txt showing the diff of <code>b.txt<\/code> between the parent of <code>release/v1.0<\/code> and the tagged commit.", "new": false}, {"html": "The report must be in diff format (including the 'diff --git' header).", "new": true}, {"html": "Finally, generate a reconciliation report at /tmp/test/report.txt that verifies object types and sizes against the manifest.", "new": false}]}, {"lines": 398, "words": 141, "segments": [{"html": "Create a Git repository at /tmp/test using only plumbing commands (no git add or git commit).", "new": false}, {"html": "The repository must have a single commit on branch master with message 'first commit', containing files a.txt (content 'test content') and b.txt.", "new": false}, {"html": "Discover the correct content for b.txt by inspecting the tagged commit release/v1.0 in the forensic repository at /app/forensics.", "new": false}, {"html": "After the commit, produce an object manifest and a reconciliation report inside the repository following the schema files in /app (manifest_schema.txt and report_schema.txt).", "new": true}, {"html": "Also create a forensic object manifest at /tmp/test/forensic-manifest.txt, listing all loose objects in /app/forensics in the same format as the manifest.", "new": true}, {"html": "The report must include lines for forensic-diff, forensic-diff-stat, forensic-message, and forensic-integrity as described in the report schema.", "new": true}, {"html": "The forensic-diff-stat line must be derived from the forensic repository's diff of b.txt between the parent of the tagged commit and the tag release/v1.0.", "new": true}]}]}}</script>
|
| 1129 |
<script src="app.js" defer></script>
|
| 1130 |
<script src="live.js" defer></script>
|
| 1131 |
+
<script src="terminal.js" defer></script>
|
| 1132 |
</body>
|
| 1133 |
</html>
|
styles.css
CHANGED
|
@@ -829,6 +829,118 @@ body.modal-open { overflow: hidden; }
|
|
| 829 |
.traj-metrics div { padding: 14px 16px; border-radius: 16px; background: var(--tint); }
|
| 830 |
.traj-metrics dt { font-size: 24px; font-weight: 800; letter-spacing: -0.03em; color: var(--accent-deep); white-space: nowrap; }
|
| 831 |
.traj-metrics dd { margin: 6px 0 0; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 832 |
/* Scroll reveal */
|
| 833 |
.js .reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); }
|
| 834 |
.js .reveal.is-visible { opacity: 1; transform: none; }
|
|
@@ -861,6 +973,13 @@ body.modal-open { overflow: hidden; }
|
|
| 861 |
.ex-grid { grid-template-columns: repeat(2, 1fr); }
|
| 862 |
.ex-facts { grid-template-columns: repeat(2, 1fr); }
|
| 863 |
.traj-grid { grid-template-columns: minmax(0, 1fr); gap: 36px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 864 |
}
|
| 865 |
|
| 866 |
@media (max-width: 640px) {
|
|
@@ -882,6 +1001,18 @@ body.modal-open { overflow: hidden; }
|
|
| 882 |
.traj-visual { padding: 16px; }
|
| 883 |
.checklist { position: static; margin-top: 14px; max-width: none; }
|
| 884 |
.paper-card { padding: 24px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 885 |
}
|
| 886 |
|
| 887 |
@media (prefers-reduced-motion: reduce) {
|
|
|
|
| 829 |
.traj-metrics div { padding: 14px 16px; border-radius: 16px; background: var(--tint); }
|
| 830 |
.traj-metrics dt { font-size: 24px; font-weight: 800; letter-spacing: -0.03em; color: var(--accent-deep); white-space: nowrap; }
|
| 831 |
.traj-metrics dd { margin: 6px 0 0; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
|
| 832 |
+
|
| 833 |
+
/* Terminal & coding examples */
|
| 834 |
+
.tx-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; }
|
| 835 |
+
.tx-card {
|
| 836 |
+
position: relative;
|
| 837 |
+
display: flex;
|
| 838 |
+
flex-direction: column;
|
| 839 |
+
overflow: hidden;
|
| 840 |
+
border-radius: 20px;
|
| 841 |
+
border: 1px solid var(--line);
|
| 842 |
+
background: var(--surface);
|
| 843 |
+
box-shadow: var(--shadow-sm);
|
| 844 |
+
cursor: pointer;
|
| 845 |
+
transition: transform 0.3s var(--ease), box-shadow 0.3s, border-color 0.3s;
|
| 846 |
+
}
|
| 847 |
+
.tx-card:hover, .tx-card:focus-visible { transform: translateY(-4px); box-shadow: var(--shadow); border-color: rgba(16, 185, 129, 0.4); }
|
| 848 |
+
.tx-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
|
| 849 |
+
.tx-card.is-extra { display: none; }
|
| 850 |
+
.tx-grid.show-all .tx-card.is-extra { display: flex; }
|
| 851 |
+
.tx-grid.show-all + .ex-more { display: none; }
|
| 852 |
+
.tx-card .ex-open { background: #fff; color: var(--ink); box-shadow: 0 6px 16px -8px rgba(0, 0, 0, 0.5); }
|
| 853 |
+
.tx-card:hover .ex-open, .tx-card:focus-visible .ex-open { opacity: 1; transform: none; }
|
| 854 |
+
.tx-term { overflow: hidden; background: #0b1220; }
|
| 855 |
+
.tx-card .tx-term { border-bottom: 1px solid #1e293b; }
|
| 856 |
+
.tx-bar { display: flex; align-items: center; gap: 6px; padding: 10px 14px; border-bottom: 1px solid #1e293b; background: #0f172a; }
|
| 857 |
+
.tx-bar i { flex: none; width: 9px; height: 9px; border-radius: 50%; background: #334155; }
|
| 858 |
+
.tx-bar i:nth-child(1) { background: #f26b5b; }
|
| 859 |
+
.tx-bar i:nth-child(2) { background: #f5b84b; }
|
| 860 |
+
.tx-bar i:nth-child(3) { background: #34d399; }
|
| 861 |
+
.tx-bar em { min-width: 0; margin-left: 8px; overflow: hidden; font: 500 11px var(--mono); font-style: normal; color: #8b9ab0; white-space: nowrap; text-overflow: ellipsis; }
|
| 862 |
+
.tx-screen { height: 200px; margin: 0; padding: 12px 16px; overflow: hidden; font: 11.5px/1.65 var(--mono); color: #e2e8f0; }
|
| 863 |
+
.tx-screen code { white-space: normal; }
|
| 864 |
+
.tx-screen span { display: block; white-space: pre-wrap; overflow-wrap: anywhere; }
|
| 865 |
+
.tx-screen b { color: #34d399; font-weight: 600; }
|
| 866 |
+
.tx-screen .tx-sys { margin-top: 6px; color: #a5b4fc; }
|
| 867 |
+
.tx-screen .tx-ok { color: #34d399; font-weight: 600; }
|
| 868 |
+
.tx-caret { display: inline-block; width: 7px; height: 1.15em; margin-left: 2px; vertical-align: -3px; background: #34d399; animation: tx-caret 1s steps(1) infinite; }
|
| 869 |
+
@keyframes tx-caret { 50% { opacity: 0; } }
|
| 870 |
+
.tx-body { display: flex; flex: 1; flex-direction: column; padding: 18px 20px 20px; }
|
| 871 |
+
.tx-area { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700; letter-spacing: 0.04em; color: var(--accent-deep); }
|
| 872 |
+
.tx-area::before { content: ""; width: 8px; height: 8px; border-radius: 2px; background: var(--accent); }
|
| 873 |
+
.tx-card h3 { margin: 8px 0 6px; font-size: 18px; letter-spacing: -0.02em; }
|
| 874 |
+
.tx-body > p:not(.tx-area) { font-size: 14px; color: var(--muted); overflow-wrap: anywhere; }
|
| 875 |
+
.tx-body code, .txm-instruction code, .growth-instruction code { padding: 1px 5px; border-radius: 5px; border: 1px solid var(--line); background: #fff; font: 500 0.86em var(--mono); color: var(--ink-2); overflow-wrap: anywhere; }
|
| 876 |
+
.tx-meta { display: flex; flex-wrap: wrap; gap: 6px; margin: auto 0 0; padding: 14px 0 0; list-style: none; }
|
| 877 |
+
.tx-meta li { padding: 3px 8px; border-radius: 6px; border: 1px solid var(--line); background: var(--tint-2); font: 500 11px var(--mono); color: var(--ink-2); }
|
| 878 |
+
|
| 879 |
+
.tx-coverage { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: 40px; align-items: center; margin-top: 56px; padding: 30px 32px; border-radius: 24px; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow-sm); }
|
| 880 |
+
.tx-coverage-copy h3 { font-size: 22px; letter-spacing: -0.02em; }
|
| 881 |
+
.tx-coverage-copy p { margin-top: 10px; font-size: 15px; color: var(--muted); }
|
| 882 |
+
.tx-bars { display: grid; gap: 9px; margin: 0; padding: 0; list-style: none; }
|
| 883 |
+
.tx-bars li { display: grid; grid-template-columns: 200px minmax(0, 1fr) 44px; gap: 12px; align-items: center; font-size: 13.5px; color: var(--ink-2); }
|
| 884 |
+
.txb-track { height: 10px; overflow: hidden; border-radius: 999px; background: var(--tint); }
|
| 885 |
+
.txb-track i { display: block; width: var(--w); height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--accent), var(--indigo)); transform-origin: left; }
|
| 886 |
+
.js .tx-coverage .txb-track i { transform: scaleX(0); transition: transform 1s var(--ease); transition-delay: calc(var(--i, 0) * 60ms + 0.2s); }
|
| 887 |
+
.js .tx-coverage.is-visible .txb-track i { transform: none; }
|
| 888 |
+
.txb-pct { font: 600 12.5px var(--mono); color: var(--accent-deep); text-align: right; }
|
| 889 |
+
|
| 890 |
+
.txm-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
|
| 891 |
+
.txm-h { margin: 0 0 10px; font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-deep); }
|
| 892 |
+
.txm-h code { font: inherit; text-transform: none; letter-spacing: 0; }
|
| 893 |
+
.txm-col .tx-term + .txm-h { margin-top: 20px; }
|
| 894 |
+
.txm-instruction { padding: 16px 18px; border-radius: 14px; border: 1px solid var(--line); background: var(--tint-2); font-size: 15px; line-height: 1.65; color: var(--ink-2); overflow-wrap: anywhere; }
|
| 895 |
+
.txm-instruction p + p { margin-top: 6px; }
|
| 896 |
+
.txm-facts { margin: 16px 0 0; }
|
| 897 |
+
.txm-facts div { display: grid; grid-template-columns: 136px minmax(0, 1fr); gap: 12px; padding: 11px 0; border-top: 1px solid var(--line); }
|
| 898 |
+
.txm-facts dt { padding-top: 2px; font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-deep); }
|
| 899 |
+
.txm-facts dd { margin: 0; font-size: 14px; color: var(--ink-2); overflow-wrap: anywhere; }
|
| 900 |
+
.tx-term-lg { border-radius: 14px; border: 1px solid #1e293b; }
|
| 901 |
+
.tx-term-lg .tx-screen { height: 236px; font-size: 12px; }
|
| 902 |
+
.txm-code { max-height: 300px; margin: 0; padding: 14px 16px; overflow: auto; border-radius: 14px; background: #0b1220; color: #cbd5e1; font: 11.5px/1.65 var(--mono); white-space: pre; }
|
| 903 |
+
#txm-cta { margin-top: 22px; }
|
| 904 |
+
|
| 905 |
+
/* Task growth */
|
| 906 |
+
.growth { margin-top: 64px; padding: 32px; border-radius: 24px; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow); }
|
| 907 |
+
.growth-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 28px; align-items: end; }
|
| 908 |
+
.growth-copy .kicker { margin-bottom: 10px; }
|
| 909 |
+
.growth-copy h3 { font-size: clamp(22px, 2.2vw, 28px); line-height: 1.15; letter-spacing: -0.025em; }
|
| 910 |
+
.growth-copy p:not(.kicker) { max-width: 640px; margin-top: 10px; font-size: 15.5px; color: var(--ink-2); }
|
| 911 |
+
.growth-steps { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; justify-content: flex-end; }
|
| 912 |
+
.gstep { display: grid; place-items: center; align-content: center; gap: 3px; width: 46px; height: 50px; padding: 0; border-radius: 12px; border: 1px solid var(--line); background: #fff; color: var(--muted); font: inherit; cursor: pointer; transition: background-color 0.25s, border-color 0.25s, color 0.25s; }
|
| 913 |
+
.gstep span { font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
|
| 914 |
+
.gstep strong { font: 700 16px/1 var(--mono); color: var(--ink-2); }
|
| 915 |
+
.gstep:hover { border-color: #c9d2cc; }
|
| 916 |
+
.gstep.is-done { border-color: rgba(16, 185, 129, 0.3); background: var(--accent-soft); }
|
| 917 |
+
.gstep[aria-pressed="true"] { border-color: var(--ink); background: var(--ink); color: #9aa4b2; }
|
| 918 |
+
.gstep[aria-pressed="true"] strong { color: #fff; }
|
| 919 |
+
.gplay { height: 50px; margin-left: 4px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--line); background: var(--tint-2); color: var(--ink-2); font: 600 13px var(--font); cursor: pointer; }
|
| 920 |
+
.gplay:hover { border-color: #c9d2cc; }
|
| 921 |
+
.growth-body { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: 28px; margin-top: 26px; }
|
| 922 |
+
.growth-instruction { min-height: 300px; padding: 20px 22px; border-radius: 16px; border: 1px solid var(--line); background: var(--tint-2); font-size: 15px; line-height: 1.75; color: var(--ink-2); overflow-wrap: anywhere; }
|
| 923 |
+
.g-text { animation: g-in 0.45s var(--ease); }
|
| 924 |
+
@keyframes g-in { from { opacity: 0; transform: translateY(6px); } }
|
| 925 |
+
.growth-instruction mark { padding: 2px 3px; border-radius: 4px; background: rgba(16, 185, 129, 0.2); color: var(--ink); -webkit-box-decoration-break: clone; box-decoration-break: clone; animation: g-mark 1.2s var(--ease); }
|
| 926 |
+
@keyframes g-mark { from { background: rgba(16, 185, 129, 0.55); } }
|
| 927 |
+
.growth-stats { display: grid; gap: 14px; align-content: start; }
|
| 928 |
+
.gs-stat { padding: 16px 18px; border-radius: 16px; background: var(--tint); }
|
| 929 |
+
.gs-stat span { display: block; font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-deep); }
|
| 930 |
+
.gs-stat strong { display: block; margin-top: 4px; font-size: 26px; font-weight: 800; letter-spacing: -0.03em; color: var(--ink); }
|
| 931 |
+
.gs-bar { height: 8px; margin-top: 10px; overflow: hidden; border-radius: 999px; background: rgba(15, 23, 42, 0.08); }
|
| 932 |
+
.gs-bar i { display: block; width: 0; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--accent), var(--indigo)); transition: width 0.7s var(--ease); }
|
| 933 |
+
.gs-bar-alt i { background: linear-gradient(90deg, #6366f1, #a78bfa); }
|
| 934 |
+
.gs-spark { margin: 0; padding: 14px 16px 10px; border-radius: 16px; border: 1px solid var(--line); }
|
| 935 |
+
.gs-spark svg { display: block; width: 100%; height: auto; overflow: visible; }
|
| 936 |
+
.gs-spark figcaption { margin-top: 6px; font-size: 12px; color: var(--muted); }
|
| 937 |
+
.gs-area { fill: rgba(16, 185, 129, 0.12); }
|
| 938 |
+
.gs-line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
|
| 939 |
+
.gs-dot { fill: #fff; stroke: var(--accent); stroke-width: 1.6; }
|
| 940 |
+
.gs-dot.is-on { fill: var(--accent); }
|
| 941 |
+
.gs-guide { stroke: rgba(15, 23, 42, 0.2); stroke-width: 1; stroke-dasharray: 3 3; transition: transform 0.5s var(--ease); }
|
| 942 |
+
.gs-note { font-size: 12px; color: var(--muted); }
|
| 943 |
+
|
| 944 |
/* Scroll reveal */
|
| 945 |
.js .reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); }
|
| 946 |
.js .reveal.is-visible { opacity: 1; transform: none; }
|
|
|
|
| 973 |
.ex-grid { grid-template-columns: repeat(2, 1fr); }
|
| 974 |
.ex-facts { grid-template-columns: repeat(2, 1fr); }
|
| 975 |
.traj-grid { grid-template-columns: minmax(0, 1fr); gap: 36px; }
|
| 976 |
+
.tx-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
| 977 |
+
.tx-coverage { grid-template-columns: minmax(0, 1fr); gap: 22px; }
|
| 978 |
+
.txm-grid { grid-template-columns: minmax(0, 1fr); }
|
| 979 |
+
.growth-head { grid-template-columns: minmax(0, 1fr); gap: 20px; }
|
| 980 |
+
.growth-steps { justify-content: flex-start; }
|
| 981 |
+
.growth-body { grid-template-columns: minmax(0, 1fr); }
|
| 982 |
+
.growth-instruction { min-height: 0; }
|
| 983 |
}
|
| 984 |
|
| 985 |
@media (max-width: 640px) {
|
|
|
|
| 1001 |
.traj-visual { padding: 16px; }
|
| 1002 |
.checklist { position: static; margin-top: 14px; max-width: none; }
|
| 1003 |
.paper-card { padding: 24px; }
|
| 1004 |
+
.tx-grid { grid-template-columns: minmax(0, 1fr); }
|
| 1005 |
+
.tx-coverage { margin-top: 40px; padding: 22px 18px; }
|
| 1006 |
+
.tx-bars { gap: 12px; }
|
| 1007 |
+
.tx-bars li { grid-template-columns: minmax(0, 1fr) 36px; gap: 4px 10px; font-size: 13px; }
|
| 1008 |
+
.txb-label { grid-column: 1 / -1; }
|
| 1009 |
+
.txm-facts div { grid-template-columns: 1fr; gap: 4px; }
|
| 1010 |
+
.growth { margin-top: 44px; padding: 20px 16px; }
|
| 1011 |
+
.growth-steps { gap: 4px; }
|
| 1012 |
+
.gstep { width: 34px; height: 40px; border-radius: 10px; }
|
| 1013 |
+
.gstep span { display: none; }
|
| 1014 |
+
.gplay { height: 40px; margin-left: 0; }
|
| 1015 |
+
.growth-instruction { padding: 16px; font-size: 14.5px; }
|
| 1016 |
}
|
| 1017 |
|
| 1018 |
@media (prefers-reduced-motion: reduce) {
|
terminal.js
ADDED
|
@@ -0,0 +1,418 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
(() => {
|
| 2 |
+
'use strict';
|
| 3 |
+
|
| 4 |
+
const $ = (sel, root = document) => root.querySelector(sel);
|
| 5 |
+
const $$ = (sel, root = document) => Array.from(root.querySelectorAll(sel));
|
| 6 |
+
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
| 7 |
+
|
| 8 |
+
const source = $('#terminal-data');
|
| 9 |
+
if (!source) return;
|
| 10 |
+
let DATA;
|
| 11 |
+
try {
|
| 12 |
+
DATA = JSON.parse(source.textContent);
|
| 13 |
+
} catch (err) {
|
| 14 |
+
return;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
const contactHref = (subject) => {
|
| 18 |
+
const link = $('[data-contact]');
|
| 19 |
+
const href = link ? link.getAttribute('href') || '' : '';
|
| 20 |
+
const address = href.startsWith('mailto:') ? href.slice(7).split('?')[0] : '';
|
| 21 |
+
return address ? `mailto:${address}?subject=${encodeURIComponent(subject)}` : '#contact';
|
| 22 |
+
};
|
| 23 |
+
|
| 24 |
+
const VERIFY = [
|
| 25 |
+
['tx-sys', 'Running verifier in a fresh sandbox…'],
|
| 26 |
+
['tx-ok', '✓ All checks passed'],
|
| 27 |
+
];
|
| 28 |
+
|
| 29 |
+
class Replayer {
|
| 30 |
+
constructor(screen, lines) {
|
| 31 |
+
this.screen = screen;
|
| 32 |
+
this.code = $('code', screen) || screen;
|
| 33 |
+
this.lines = lines;
|
| 34 |
+
this.timer = 0;
|
| 35 |
+
this.running = false;
|
| 36 |
+
this.caret = document.createElement('i');
|
| 37 |
+
this.caret.className = 'tx-caret';
|
| 38 |
+
this.reset();
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
reset() {
|
| 42 |
+
this.code.replaceChildren();
|
| 43 |
+
this.line = 0;
|
| 44 |
+
this.char = 0;
|
| 45 |
+
this.phase = 'type';
|
| 46 |
+
this.verified = 0;
|
| 47 |
+
this.text = null;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
prompt(symbol) {
|
| 51 |
+
const span = document.createElement('span');
|
| 52 |
+
span.className = 'tx-cmd';
|
| 53 |
+
const b = document.createElement('b');
|
| 54 |
+
b.textContent = symbol;
|
| 55 |
+
const text = document.createTextNode('');
|
| 56 |
+
span.append(b, ' ', text);
|
| 57 |
+
this.code.append(span);
|
| 58 |
+
return { span, text };
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
status(cls, message) {
|
| 62 |
+
const span = document.createElement('span');
|
| 63 |
+
span.className = cls;
|
| 64 |
+
span.textContent = message;
|
| 65 |
+
this.code.append(span);
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
renderStatic() {
|
| 69 |
+
this.stop();
|
| 70 |
+
this.reset();
|
| 71 |
+
this.lines.forEach(([symbol, line]) => {
|
| 72 |
+
this.prompt(symbol).text.data = line;
|
| 73 |
+
});
|
| 74 |
+
VERIFY.forEach(([cls, message]) => this.status(cls, message));
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
start(delay = 0) {
|
| 78 |
+
if (this.running) return;
|
| 79 |
+
this.running = true;
|
| 80 |
+
this.schedule(delay);
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
stop() {
|
| 84 |
+
this.running = false;
|
| 85 |
+
clearTimeout(this.timer);
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
schedule(ms) {
|
| 89 |
+
clearTimeout(this.timer);
|
| 90 |
+
if (this.running) this.timer = setTimeout(() => this.tick(), ms);
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
scroll() {
|
| 94 |
+
this.screen.scrollTop = this.screen.scrollHeight;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
tick() {
|
| 98 |
+
if (!this.running) return;
|
| 99 |
+
if (this.phase === 'type') {
|
| 100 |
+
if (this.line >= this.lines.length) {
|
| 101 |
+
this.caret.remove();
|
| 102 |
+
this.phase = 'verify';
|
| 103 |
+
this.schedule(420);
|
| 104 |
+
return;
|
| 105 |
+
}
|
| 106 |
+
const [symbol, line] = this.lines[this.line];
|
| 107 |
+
if (!this.text) {
|
| 108 |
+
const { span, text } = this.prompt(symbol);
|
| 109 |
+
span.append(this.caret);
|
| 110 |
+
this.text = text;
|
| 111 |
+
this.scroll();
|
| 112 |
+
this.schedule(160);
|
| 113 |
+
return;
|
| 114 |
+
}
|
| 115 |
+
this.char = Math.min(line.length, this.char + Math.max(1, Math.ceil(line.length / 40)));
|
| 116 |
+
this.text.data = line.slice(0, this.char);
|
| 117 |
+
if (this.char >= line.length) {
|
| 118 |
+
this.line += 1;
|
| 119 |
+
this.char = 0;
|
| 120 |
+
this.text = null;
|
| 121 |
+
this.scroll();
|
| 122 |
+
this.schedule(300);
|
| 123 |
+
return;
|
| 124 |
+
}
|
| 125 |
+
this.schedule(22);
|
| 126 |
+
return;
|
| 127 |
+
}
|
| 128 |
+
if (this.phase === 'verify') {
|
| 129 |
+
if (this.verified >= VERIFY.length) {
|
| 130 |
+
this.prompt('$').span.append(this.caret);
|
| 131 |
+
this.scroll();
|
| 132 |
+
this.phase = 'hold';
|
| 133 |
+
this.schedule(3200);
|
| 134 |
+
return;
|
| 135 |
+
}
|
| 136 |
+
const [cls, message] = VERIFY[this.verified];
|
| 137 |
+
this.verified += 1;
|
| 138 |
+
this.status(cls, message);
|
| 139 |
+
this.scroll();
|
| 140 |
+
this.schedule(this.verified === 1 ? 1000 : 200);
|
| 141 |
+
return;
|
| 142 |
+
}
|
| 143 |
+
this.reset();
|
| 144 |
+
this.schedule(260);
|
| 145 |
+
}
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
function initCards(tasks) {
|
| 149 |
+
const grid = $('#tx-grid');
|
| 150 |
+
if (!grid) return;
|
| 151 |
+
const cards = $$('.tx-card', grid);
|
| 152 |
+
const players = cards.map((card) => {
|
| 153 |
+
const task = tasks[Number(card.dataset.index)];
|
| 154 |
+
return task ? new Replayer($('.tx-screen', card), task.replay) : null;
|
| 155 |
+
});
|
| 156 |
+
|
| 157 |
+
if (reduceMotion || !('IntersectionObserver' in window)) {
|
| 158 |
+
players.forEach((p) => p && p.renderStatic());
|
| 159 |
+
} else {
|
| 160 |
+
const observer = new IntersectionObserver((entries) => {
|
| 161 |
+
entries.forEach((entry) => {
|
| 162 |
+
const i = cards.indexOf(entry.target);
|
| 163 |
+
const player = players[i];
|
| 164 |
+
if (!player) return;
|
| 165 |
+
if (entry.isIntersecting) {
|
| 166 |
+
player.start(player.started ? 0 : (i % 3) * 450);
|
| 167 |
+
player.started = true;
|
| 168 |
+
} else {
|
| 169 |
+
player.stop();
|
| 170 |
+
}
|
| 171 |
+
});
|
| 172 |
+
}, { threshold: 0.25 });
|
| 173 |
+
cards.forEach((card) => observer.observe(card));
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
const more = $('#tx-more');
|
| 177 |
+
const extras = cards.filter((card) => card.classList.contains('is-extra'));
|
| 178 |
+
if (more) {
|
| 179 |
+
if (!extras.length) more.hidden = true;
|
| 180 |
+
more.textContent = `Show ${extras.length} more terminal tasks`;
|
| 181 |
+
more.addEventListener('click', () => {
|
| 182 |
+
grid.classList.add('show-all');
|
| 183 |
+
more.setAttribute('aria-expanded', 'true');
|
| 184 |
+
if (extras[0]) extras[0].focus({ preventScroll: true });
|
| 185 |
+
});
|
| 186 |
+
}
|
| 187 |
+
return cards;
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
function initModal(tasks, cards) {
|
| 191 |
+
const modal = $('#tx-modal');
|
| 192 |
+
if (!modal || !cards) return;
|
| 193 |
+
const sheet = $('.ex-sheet', modal);
|
| 194 |
+
const closeButton = $('.icon-btn[data-tx-close]', modal);
|
| 195 |
+
const field = (id) => document.getElementById(id);
|
| 196 |
+
const f = {
|
| 197 |
+
area: field('txm-area'),
|
| 198 |
+
title: field('txm-title'),
|
| 199 |
+
tags: field('txm-tags'),
|
| 200 |
+
instruction: field('txm-instruction'),
|
| 201 |
+
base: field('txm-base'),
|
| 202 |
+
termBase: field('txm-term-base'),
|
| 203 |
+
lines: field('txm-lines'),
|
| 204 |
+
replay: field('txm-replay'),
|
| 205 |
+
code: field('txm-code'),
|
| 206 |
+
cta: field('txm-cta'),
|
| 207 |
+
};
|
| 208 |
+
let current = 0;
|
| 209 |
+
let lastFocus = null;
|
| 210 |
+
let player = null;
|
| 211 |
+
|
| 212 |
+
const play = () => {
|
| 213 |
+
if (player) player.stop();
|
| 214 |
+
player = new Replayer(f.replay, tasks[current].replay);
|
| 215 |
+
if (reduceMotion) player.renderStatic();
|
| 216 |
+
else player.start(250);
|
| 217 |
+
};
|
| 218 |
+
|
| 219 |
+
const render = (index) => {
|
| 220 |
+
current = (index + tasks.length) % tasks.length;
|
| 221 |
+
const t = tasks[current];
|
| 222 |
+
f.area.textContent = t.area;
|
| 223 |
+
f.title.textContent = t.title;
|
| 224 |
+
f.tags.replaceChildren(...t.tags.map((tag) => {
|
| 225 |
+
const li = document.createElement('li');
|
| 226 |
+
li.className = 'trk trk-mod';
|
| 227 |
+
li.textContent = tag;
|
| 228 |
+
return li;
|
| 229 |
+
}));
|
| 230 |
+
f.instruction.innerHTML = t.instruction;
|
| 231 |
+
f.base.textContent = t.base;
|
| 232 |
+
f.termBase.textContent = t.base;
|
| 233 |
+
f.lines.textContent = `${t.lines}-line solve.sh`;
|
| 234 |
+
f.code.textContent = t.code;
|
| 235 |
+
f.code.scrollTop = 0;
|
| 236 |
+
f.cta.href = contactHref(`Terminal task sample: ${t.title}`);
|
| 237 |
+
sheet.scrollTop = 0;
|
| 238 |
+
if (!modal.hidden) play();
|
| 239 |
+
};
|
| 240 |
+
|
| 241 |
+
const open = (index) => {
|
| 242 |
+
lastFocus = document.activeElement;
|
| 243 |
+
modal.hidden = false;
|
| 244 |
+
render(index);
|
| 245 |
+
document.body.classList.add('modal-open');
|
| 246 |
+
closeButton.focus();
|
| 247 |
+
};
|
| 248 |
+
const close = () => {
|
| 249 |
+
modal.hidden = true;
|
| 250 |
+
if (player) player.stop();
|
| 251 |
+
document.body.classList.remove('modal-open');
|
| 252 |
+
if (lastFocus) lastFocus.focus({ preventScroll: true });
|
| 253 |
+
};
|
| 254 |
+
|
| 255 |
+
cards.forEach((card) => {
|
| 256 |
+
const index = Number(card.dataset.index);
|
| 257 |
+
card.addEventListener('click', () => open(index));
|
| 258 |
+
card.addEventListener('keydown', (e) => {
|
| 259 |
+
if (e.key === 'Enter' || e.key === ' ') {
|
| 260 |
+
e.preventDefault();
|
| 261 |
+
open(index);
|
| 262 |
+
}
|
| 263 |
+
});
|
| 264 |
+
});
|
| 265 |
+
$$('[data-tx-close]', modal).forEach((el) => el.addEventListener('click', close));
|
| 266 |
+
$('[data-tx-prev]', modal).addEventListener('click', () => render(current - 1));
|
| 267 |
+
$('[data-tx-next]', modal).addEventListener('click', () => render(current + 1));
|
| 268 |
+
|
| 269 |
+
document.addEventListener('keydown', (e) => {
|
| 270 |
+
if (modal.hidden) return;
|
| 271 |
+
if (e.key === 'Escape') {
|
| 272 |
+
e.preventDefault();
|
| 273 |
+
close();
|
| 274 |
+
} else if (e.key === 'ArrowRight') {
|
| 275 |
+
render(current + 1);
|
| 276 |
+
} else if (e.key === 'ArrowLeft') {
|
| 277 |
+
render(current - 1);
|
| 278 |
+
} else if (e.key === 'Tab') {
|
| 279 |
+
const focusables = $$('button, a[href]', sheet);
|
| 280 |
+
const first = focusables[0];
|
| 281 |
+
const last = focusables[focusables.length - 1];
|
| 282 |
+
if (e.shiftKey && document.activeElement === first) {
|
| 283 |
+
e.preventDefault();
|
| 284 |
+
last.focus();
|
| 285 |
+
} else if (!e.shiftKey && document.activeElement === last) {
|
| 286 |
+
e.preventDefault();
|
| 287 |
+
first.focus();
|
| 288 |
+
}
|
| 289 |
+
}
|
| 290 |
+
});
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
function initGrowth(growth) {
|
| 294 |
+
const root = $('#growth');
|
| 295 |
+
if (!root || !growth || !growth.stages || !growth.stages.length) return;
|
| 296 |
+
const stages = growth.stages;
|
| 297 |
+
const steps = $('#growth-steps');
|
| 298 |
+
const instruction = $('#growth-instruction');
|
| 299 |
+
const linesEl = $('#growth-lines');
|
| 300 |
+
const wordsEl = $('#growth-words');
|
| 301 |
+
const linesBar = $('#growth-lines-bar');
|
| 302 |
+
const wordsBar = $('#growth-words-bar');
|
| 303 |
+
const spark = $('#growth-spark');
|
| 304 |
+
const maxLines = Math.max(...stages.map((s) => s.lines));
|
| 305 |
+
const maxWords = Math.max(...stages.map((s) => s.words));
|
| 306 |
+
const svgNS = 'http://www.w3.org/2000/svg';
|
| 307 |
+
|
| 308 |
+
const W = 240;
|
| 309 |
+
const H = 72;
|
| 310 |
+
const P = 6;
|
| 311 |
+
const xs = stages.map((_, i) => P + (i * (W - 2 * P)) / Math.max(1, stages.length - 1));
|
| 312 |
+
const ys = stages.map((s) => H - P - ((H - 2 * P) * s.lines) / maxLines);
|
| 313 |
+
const pts = xs.map((x, i) => `${x.toFixed(1)},${ys[i].toFixed(1)}`).join(' ');
|
| 314 |
+
const make = (tag, attrs) => {
|
| 315 |
+
const node = document.createElementNS(svgNS, tag);
|
| 316 |
+
Object.entries(attrs).forEach(([k, v]) => node.setAttribute(k, v));
|
| 317 |
+
spark.append(node);
|
| 318 |
+
return node;
|
| 319 |
+
};
|
| 320 |
+
spark.replaceChildren();
|
| 321 |
+
make('polygon', { class: 'gs-area', points: `${P},${H - P} ${pts} ${W - P},${H - P}` });
|
| 322 |
+
make('polyline', { class: 'gs-line', points: pts });
|
| 323 |
+
const guide = make('line', { class: 'gs-guide', x1: 0, x2: 0, y1: 2, y2: H - 2 });
|
| 324 |
+
const dots = xs.map((x, i) => make('circle', { class: 'gs-dot', cx: x.toFixed(1), cy: ys[i].toFixed(1), r: 3 }));
|
| 325 |
+
|
| 326 |
+
let index = 0;
|
| 327 |
+
let shown = { lines: 0, words: 0 };
|
| 328 |
+
let tween = 0;
|
| 329 |
+
const countTo = (target) => {
|
| 330 |
+
cancelAnimationFrame(tween);
|
| 331 |
+
const from = { ...shown };
|
| 332 |
+
const t0 = performance.now();
|
| 333 |
+
const step = (now) => {
|
| 334 |
+
const k = reduceMotion ? 1 : Math.min(1, (now - t0) / 600);
|
| 335 |
+
const e = 1 - (1 - k) ** 3;
|
| 336 |
+
shown = {
|
| 337 |
+
lines: Math.round(from.lines + (target.lines - from.lines) * e),
|
| 338 |
+
words: Math.round(from.words + (target.words - from.words) * e),
|
| 339 |
+
};
|
| 340 |
+
linesEl.textContent = `${shown.lines} lines`;
|
| 341 |
+
wordsEl.textContent = `${shown.words} words`;
|
| 342 |
+
if (k < 1) tween = requestAnimationFrame(step);
|
| 343 |
+
};
|
| 344 |
+
tween = requestAnimationFrame(step);
|
| 345 |
+
};
|
| 346 |
+
|
| 347 |
+
const buttons = stages.map((_, i) => {
|
| 348 |
+
const b = document.createElement('button');
|
| 349 |
+
b.type = 'button';
|
| 350 |
+
b.className = 'gstep';
|
| 351 |
+
b.setAttribute('aria-label', `Stage ${i + 1} of ${stages.length}`);
|
| 352 |
+
b.innerHTML = `<span>Stage</span><strong>${i + 1}</strong>`;
|
| 353 |
+
b.addEventListener('click', () => {
|
| 354 |
+
setAuto(false);
|
| 355 |
+
show(i);
|
| 356 |
+
});
|
| 357 |
+
return b;
|
| 358 |
+
});
|
| 359 |
+
const toggle = document.createElement('button');
|
| 360 |
+
toggle.type = 'button';
|
| 361 |
+
toggle.className = 'gplay';
|
| 362 |
+
steps.replaceChildren(...buttons, toggle);
|
| 363 |
+
|
| 364 |
+
const show = (i) => {
|
| 365 |
+
index = i;
|
| 366 |
+
const stage = stages[i];
|
| 367 |
+
buttons.forEach((b, k) => {
|
| 368 |
+
b.setAttribute('aria-pressed', String(k === i));
|
| 369 |
+
b.classList.toggle('is-done', k < i);
|
| 370 |
+
});
|
| 371 |
+
const text = document.createElement('p');
|
| 372 |
+
text.className = 'g-text';
|
| 373 |
+
text.innerHTML = stage.segments.map((s) => (s.new ? `<mark>${s.html}</mark>` : s.html)).join(' ');
|
| 374 |
+
instruction.replaceChildren(text);
|
| 375 |
+
linesBar.style.width = `${((100 * stage.lines) / maxLines).toFixed(1)}%`;
|
| 376 |
+
wordsBar.style.width = `${((100 * stage.words) / maxWords).toFixed(1)}%`;
|
| 377 |
+
countTo(stage);
|
| 378 |
+
dots.forEach((d, k) => {
|
| 379 |
+
d.classList.toggle('is-on', k <= i);
|
| 380 |
+
d.setAttribute('r', k === i ? 5 : 3);
|
| 381 |
+
});
|
| 382 |
+
guide.style.transform = `translateX(${xs[i].toFixed(1)}px)`;
|
| 383 |
+
};
|
| 384 |
+
|
| 385 |
+
let auto = !reduceMotion;
|
| 386 |
+
let visible = false;
|
| 387 |
+
let timer = 0;
|
| 388 |
+
const schedule = () => {
|
| 389 |
+
clearTimeout(timer);
|
| 390 |
+
if (!auto || !visible) return;
|
| 391 |
+
timer = setTimeout(() => {
|
| 392 |
+
show(index === stages.length - 1 ? 0 : index + 1);
|
| 393 |
+
schedule();
|
| 394 |
+
}, index === stages.length - 1 ? 6000 : 4200);
|
| 395 |
+
};
|
| 396 |
+
const setAuto = (on) => {
|
| 397 |
+
auto = on;
|
| 398 |
+
toggle.textContent = on ? 'Pause' : 'Play';
|
| 399 |
+
toggle.setAttribute('aria-label', on ? 'Pause stage autoplay' : 'Play stages automatically');
|
| 400 |
+
schedule();
|
| 401 |
+
};
|
| 402 |
+
toggle.addEventListener('click', () => setAuto(!auto));
|
| 403 |
+
|
| 404 |
+
show(0);
|
| 405 |
+
setAuto(auto);
|
| 406 |
+
if ('IntersectionObserver' in window) {
|
| 407 |
+
new IntersectionObserver((entries) => {
|
| 408 |
+
visible = entries[0].isIntersecting;
|
| 409 |
+
schedule();
|
| 410 |
+
}, { threshold: 0.35 }).observe(root);
|
| 411 |
+
}
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
const tasks = DATA.tasks || [];
|
| 415 |
+
const cards = initCards(tasks);
|
| 416 |
+
initModal(tasks, cards);
|
| 417 |
+
initGrowth(DATA.growth);
|
| 418 |
+
})();
|