Skip to content
C.W.K.
Stream
Lesson 04 of 05 · published

Yards and the Store

~11 min · yard, content-addressed-store, submission, persistence

Level 0Cold Iron
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Yards and the Store

Each joined session works in its own persistent yard under anvil-db. The yard contains the supplied brief, frozen base when present, phase materials, mutable scratch work, and the required submission/ directory. It is a durable dig site, not the canonical judged object and never another contestant's workspace.

When a seat marks done, Anvil walks the declared submission tree, rejects an empty or oversized tree, hashes every file, and archives it beneath a unique submission ID. The stored tree and its path/sha256/bytes manifest become immutable judge input before any bench session opens: archive-before-judge.

The store is content-addressed per file, not one deduplicated bundle that merges equal submissions. Two identical trees still have distinct submission IDs, seat records, reports, manifests, and trail events. A later phase creates another submission row and tree; phase and seat lineage in the run graph explain the relationship.

Yards and store trees both persist until Dad uses the explicit run-deletion path, which removes them together. There is no TTL, rotation, or “retention expires” path. A month later, the store still rebuilds the contest and the yard still preserves working residue.

Work in the yard; judge the archived tree. The manifest fixes the exact files every judge receives.

Code

Archive boundary — identical bytes, distinct events·python
import hashlib


def archive_tree(submission_id, files):
    """Files are content-addressed; submissions are counted as events."""
    if not files:
        raise ValueError("an empty submission tree is not archived")
    manifest = [
        {"path": p,
         "sha256": hashlib.sha256(b).hexdigest(),
         "bytes": len(b)}
        for p, b in sorted(files.items())
    ]
    return {"submission_id": submission_id, "manifest": manifest}


tree = {"submission/fix.py": b"print(1)\n"}

first = archive_tree("s-01", tree)
second = archive_tree("s-02", tree)          # byte-identical tree

# Same file addresses, different submission events — they never merge.
assert first["manifest"] == second["manifest"]
assert first["submission_id"] != second["submission_id"]
print(first["manifest"][0]["sha256"][:12], first["submission_id"],
      second["submission_id"])

External links

Exercise

For a three-file submission, write the archived manifest and name the distinct records created if a later revision contains the same bytes.
Hint
Keep a unique submission event and tree even when file hashes repeat.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.