Wildstash commited on
Commit
e2a8f6b
·
verified ·
1 Parent(s): d044543

Reframe DreamWall as AfterBlock Museum

Browse files
.github/workflows/build-plugin.yml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Build Paper Plugin
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - "paper-plugin/**"
7
+ - ".github/workflows/build-plugin.yml"
8
+ pull_request:
9
+ paths:
10
+ - "paper-plugin/**"
11
+ - ".github/workflows/build-plugin.yml"
12
+ workflow_dispatch:
13
+
14
+ jobs:
15
+ build-plugin:
16
+ runs-on: ubuntu-latest
17
+ defaults:
18
+ run:
19
+ working-directory: paper-plugin
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@v4
23
+
24
+ - name: Set up Java
25
+ uses: actions/setup-java@v4
26
+ with:
27
+ distribution: temurin
28
+ java-version: "21"
29
+ cache: maven
30
+
31
+ - name: Build jar
32
+ run: mvn -B package
33
+
34
+ - name: Upload plugin jar
35
+ uses: actions/upload-artifact@v4
36
+ with:
37
+ name: dreamwall-paper-bridge
38
+ path: paper-plugin/target/*.jar
CODEX_BUILD_LOG.md CHANGED
@@ -25,3 +25,4 @@ This file records how Codex was used to build the hackathon entry.
25
  - Added Living Moving Canvas mode: a multi-prompt 12x12 Minecraft wall simulation with neighbor fusion, attention weather, growth stages, and a `living_canvas.mc.v1` packet.
26
  - Upgraded Living Moving Canvas into an animated wall: stable Minecraft coordinates, pulsing timeline frames, visible fusion links, evolution events, and a clearer Thousand Token Wood demo runbook.
27
  - Added per-tile Minecraft origins/bounds and documented the Paper bridge path for placing Living Canvas tiles and representing motion through particles, map updates, or block-frame updates.
 
 
25
  - Added Living Moving Canvas mode: a multi-prompt 12x12 Minecraft wall simulation with neighbor fusion, attention weather, growth stages, and a `living_canvas.mc.v1` packet.
26
  - Upgraded Living Moving Canvas into an animated wall: stable Minecraft coordinates, pulsing timeline frames, visible fusion links, evolution events, and a clearer Thousand Token Wood demo runbook.
27
  - Added per-tile Minecraft origins/bounds and documented the Paper bridge path for placing Living Canvas tiles and representing motion through particles, map updates, or block-frame updates.
28
+ - Reframed the project as DreamWall: AfterBlock Museum with `dreamwall.museum.v1`, deterministic hall placement, curation scores, artifact spirits, passport cards, seeded relic demos, museum-terminal UI, and a GitHub Actions Paper plugin build workflow.
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Living Graffiti MC
3
  emoji: 🧱
4
  colorFrom: yellow
5
  colorTo: green
@@ -19,20 +19,24 @@ tags:
19
  - codex
20
  ---
21
 
22
- # Living Graffiti MC
23
 
24
- Living Graffiti MC is a Minecraft-native living canvas for the Build Small Hackathon.
25
 
26
- Players type a prompt, sign it, and get a named 10-frame Minecraft-style animated wall artifact. Each artifact is designed as a **32x32 block wall tile** with **1,024 blocks per frame**, a wall slot, mutation rate, growth stage, fusion/value readout, creator credit, and a `living_graffiti.mc.v1` packet for the Minecraft server.
27
 
28
- The next-level mode is a shared moving canvas: multiple people's prompts claim stable coordinates on a 12x12 Minecraft wall, pulse through timeline ticks, mutate with attention weather, draw visible fusion links with nearby ideas, and export a `living_canvas.mc.v1` server packet.
29
 
30
- NeuroPets and DreamWall remain as secondary modes, but the main cash-prize demo is now simple: imagination feed -> living canvas -> fusion/value -> Minecraft public wall.
31
 
32
  ## Why This Is Different
33
 
34
- Most hackathon apps stop at chat or image generation. Living Graffiti turns language into a shared animated place.
35
 
 
 
 
 
36
  - **Animated:** each prompt becomes a 10-frame artifact, not a static image.
37
  - **Grows:** artifacts unlock stages from seed sketch to server myth based on value and mutation.
38
  - **Collective:** many prompts become one shared moving canvas, not isolated images.
@@ -51,12 +55,12 @@ Most hackathon apps stop at chat or image generation. Living Graffiti turns lang
51
  - **Track:** An Adventure in Thousand Token Wood
52
  - **Small model constraint:** the app uses a local semantic fingerprint engine, far below the 32B limit, with no cloud API dependency.
53
  - **Built on Gradio:** this Space is the official Gradio submission surface.
54
- - **Show, don't tell:** the demo is prompt -> painting -> Minecraft wall plan.
55
 
56
  ## Bonus Quests
57
 
58
- - **Off-Brand:** custom Minecraft/map-wall UI styling.
59
- - **Sharing is Caring:** the app emits an open trace for each painting.
60
  - **Field Notes:** see `FIELD_NOTES.md`.
61
 
62
  ## Minecraft Server Layer
@@ -64,6 +68,7 @@ Most hackathon apps stop at chat or image generation. Living Graffiti turns lang
64
  The MVP emits:
65
 
66
  - WorldEdit-style row instructions
 
67
  - a `living_graffiti.mc.v1` animated wall packet
68
  - a `living_canvas.mc.v1` multi-prompt animated wall packet
69
  - a `dreamwall.mc.v1` JSON bridge packet
@@ -73,6 +78,7 @@ The MVP emits:
73
  - a named Gradio API endpoint: `hatch_pet`
74
  - a named Gradio API endpoint: `living_graffiti`
75
  - a named Gradio API endpoint: `living_canvas`
 
76
 
77
  Each `living_canvas.mc.v1` tile includes a stable `minecraft_origin` and `minecraft_bounds`, so the Paper bridge can place it directly on the 384x384 wall.
78
 
@@ -83,27 +89,28 @@ The repo also includes a Paper plugin scaffold in [`paper-plugin/`](paper-plugin
83
  Use the Space API with the named endpoint:
84
 
85
  ```text
86
- POST https://build-small-hackathon-dreamwall-mc.hf.space/gradio_api/call/generate_art
87
  ```
88
 
89
  Input order:
90
 
91
  ```json
92
  [
93
- "a tiny fox wizard guarding a ruined ocean temple",
94
- "ArnavS",
95
- "~ ~ ~",
96
- "moss wing, west wall"
 
97
  ]
98
  ```
99
 
100
- The final output is a plugin-ready JSON packet with `job_id`, `player`, `prompt`, `palette`, `grid.row_runs`, and placement hints.
101
 
102
  ## Design Docs
103
 
104
  - [`docs/COMPETITION_GOAL.md`](docs/COMPETITION_GOAL.md)
105
  - [`docs/MINECRAFT_SERVER_BLUEPRINT.md`](docs/MINECRAFT_SERVER_BLUEPRINT.md)
106
- - [`docs/CANVAS_ECONOMY.md`](docs/CANVAS_ECONOMY.md)
107
  - [`docs/LIVING_GRAFFITI_MVP.md`](docs/LIVING_GRAFFITI_MVP.md)
108
  - [`docs/NEUROPETS_MVP.md`](docs/NEUROPETS_MVP.md)
109
  - [`docs/DEMO_RUNBOOK.md`](docs/DEMO_RUNBOOK.md)
@@ -114,9 +121,9 @@ DreamWall MC is aimed at **An Adventure in Thousand Token Wood** plus the **Open
114
 
115
  Judging fit:
116
 
117
- - **Genuinely delightful:** a shared Minecraft wall where language becomes a living, moving canvas.
118
- - **AI is load-bearing:** semantic drift and identity fingerprinting change the artifact.
119
- - **Originality:** it is a server ritual, not a chatbot wrapper.
120
  - **Polish:** custom Gradio skin plus Minecraft bridge packet.
121
 
122
  Bonus quests:
@@ -125,7 +132,7 @@ Bonus quests:
125
  - **Sharing is Caring:** open trace + server packet per generation.
126
  - **Field Notes:** this repo includes `FIELD_NOTES.md`.
127
 
128
- Next high-impact demo step: use PebbleHost Paper to show the 384x384 Living Moving Canvas wall with one named 32x32 slot placed from the packet, then record a 30-45 second video.
129
 
130
  ## Codex Track
131
 
 
1
  ---
2
+ title: DreamWall AfterBlock Museum
3
  emoji: 🧱
4
  colorFrom: yellow
5
  colorTo: green
 
19
  - codex
20
  ---
21
 
22
+ # DreamWall: AfterBlock Museum
23
 
24
+ AfterBlock Museum is a Minecraft-native memory museum for the Build Small Hackathon.
25
 
26
+ Visitors scan a relic, memory, animal spirit, or prompted painting. The app assigns a museum hall, computes a curation score, awakens a tiny artifact spirit, prints a shareable passport card, and emits a `dreamwall.museum.v1` packet for the Minecraft server.
27
 
28
+ Living Graffiti and Living Moving Canvas remain as secondary modes. They power museum placement, resonance, and Minecraft wall mechanics.
29
 
30
+ The main cash-prize demo is now simple: relic -> hall -> spirit -> passport -> Minecraft museum placement.
31
 
32
  ## Why This Is Different
33
 
34
+ Most hackathon apps stop at chat or image generation. AfterBlock turns language and memory into a place visitors can walk through.
35
 
36
+ - **Museum-native:** every input becomes an artifact with a hall, plaque, passport, and Minecraft coordinates.
37
+ - **Spirit-bearing:** each artifact awakens a constrained spirit that speaks only from its object and lore.
38
+ - **Resonance-based:** curation score replaces market/auction language.
39
+ - **Off-brand:** the Gradio app feels like a Minecraft museum terminal.
40
  - **Animated:** each prompt becomes a 10-frame artifact, not a static image.
41
  - **Grows:** artifacts unlock stages from seed sketch to server myth based on value and mutation.
42
  - **Collective:** many prompts become one shared moving canvas, not isolated images.
 
55
  - **Track:** An Adventure in Thousand Token Wood
56
  - **Small model constraint:** the app uses a local semantic fingerprint engine, far below the 32B limit, with no cloud API dependency.
57
  - **Built on Gradio:** this Space is the official Gradio submission surface.
58
+ - **Show, don't tell:** the demo is scan relic -> hall placement -> spirit -> passport -> Minecraft pedestal.
59
 
60
  ## Bonus Quests
61
 
62
+ - **Off-Brand:** custom Minecraft museum terminal UI styling.
63
+ - **Sharing is Caring:** the app emits open museum and bridge packets for each artifact.
64
  - **Field Notes:** see `FIELD_NOTES.md`.
65
 
66
  ## Minecraft Server Layer
 
68
  The MVP emits:
69
 
70
  - WorldEdit-style row instructions
71
+ - a `dreamwall.museum.v1` artifact/passport/spirit packet
72
  - a `living_graffiti.mc.v1` animated wall packet
73
  - a `living_canvas.mc.v1` multi-prompt animated wall packet
74
  - a `dreamwall.mc.v1` JSON bridge packet
 
78
  - a named Gradio API endpoint: `hatch_pet`
79
  - a named Gradio API endpoint: `living_graffiti`
80
  - a named Gradio API endpoint: `living_canvas`
81
+ - a named Gradio API endpoint: `curate_artifact`
82
 
83
  Each `living_canvas.mc.v1` tile includes a stable `minecraft_origin` and `minecraft_bounds`, so the Paper bridge can place it directly on the 384x384 wall.
84
 
 
89
  Use the Space API with the named endpoint:
90
 
91
  ```text
92
+ POST https://build-small-hackathon-dreamwall-mc.hf.space/gradio_api/call/curate_artifact
93
  ```
94
 
95
  Input order:
96
 
97
  ```json
98
  [
99
+ "Arnav",
100
+ "@Wildstash",
101
+ "object_photo",
102
+ "white AirPods from my first year of university",
103
+ "They carried private worlds through public noise during my first year away."
104
  ]
105
  ```
106
 
107
+ The final output is a plugin-ready museum packet with artifact title, hall, coordinates, palette/materials, plaque text, spirit first line, owner handle, and passport payload.
108
 
109
  ## Design Docs
110
 
111
  - [`docs/COMPETITION_GOAL.md`](docs/COMPETITION_GOAL.md)
112
  - [`docs/MINECRAFT_SERVER_BLUEPRINT.md`](docs/MINECRAFT_SERVER_BLUEPRINT.md)
113
+ - [`docs/MUSEUM_CURATION.md`](docs/MUSEUM_CURATION.md)
114
  - [`docs/LIVING_GRAFFITI_MVP.md`](docs/LIVING_GRAFFITI_MVP.md)
115
  - [`docs/NEUROPETS_MVP.md`](docs/NEUROPETS_MVP.md)
116
  - [`docs/DEMO_RUNBOOK.md`](docs/DEMO_RUNBOOK.md)
 
121
 
122
  Judging fit:
123
 
124
+ - **Genuinely delightful:** ordinary objects become Minecraft museum artifacts with tiny spirits.
125
+ - **AI is load-bearing:** semantic curation chooses halls, spirits, plaques, resonance, and placement.
126
+ - **Originality:** it is a memory museum ritual, not a chatbot wrapper.
127
  - **Polish:** custom Gradio skin plus Minecraft bridge packet.
128
 
129
  Bonus quests:
 
132
  - **Sharing is Caring:** open trace + server packet per generation.
133
  - **Field Notes:** this repo includes `FIELD_NOTES.md`.
134
 
135
+ Next high-impact demo step: use PebbleHost Paper to place one AfterBlock artifact pedestal/sign from the `dreamwall.museum.v1` packet, then record a 45-75 second video.
136
 
137
  ## Codex Track
138
 
app.py CHANGED
@@ -4,6 +4,7 @@ import math
4
  import os
5
  import tempfile
6
  from dataclasses import dataclass
 
7
 
8
  import gradio as gr
9
  import numpy as np
@@ -101,6 +102,56 @@ LIVING_WALL_PROMPTS = [
101
  "a cloud dragon sleeping inside a circuit board",
102
  ]
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
  @dataclass
106
  class ArtResult:
@@ -375,6 +426,371 @@ def canvas_report(prompt: str, player: str, moods: list[str], palette_names: lis
375
  return "\n".join(report), json.dumps(packet, indent=2)
376
 
377
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378
  HABITATS = {
379
  "redstone caves": ["electric", "mechanical", "small", "curious"],
380
  "sky forest": ["flying", "social", "light", "watchful"],
@@ -1118,43 +1534,117 @@ def gradio_generate(prompt: str, player: str, origin: str, gallery_zone: str):
1118
 
1119
  CSS = """
1120
  :root {
1121
- --mc-ink: #24170e;
1122
- --mc-paper: #f4ecd8;
1123
  --mc-green: #57744a;
1124
  --mc-gold: #d39b45;
 
 
 
1125
  }
1126
  body, .gradio-container {
1127
- background: #18130f !important;
1128
  color: var(--mc-ink);
1129
  }
1130
  .gradio-container {
1131
  max-width: 1180px !important;
1132
  }
1133
  .dreamwall-hero {
1134
- background: linear-gradient(135deg, #f4ecd8 0%, #e5d0a3 100%);
1135
- border: 3px solid #4a2f1f;
1136
- box-shadow: 0 10px 0 #2a1a12;
1137
  padding: 22px;
1138
  margin: 14px 0 18px;
1139
  }
1140
  .dreamwall-hero h1 {
1141
  margin: 0;
1142
  font-size: 42px;
1143
- color: #2a1a12;
1144
  }
1145
  .dreamwall-hero p {
1146
  max-width: 760px;
1147
  font-size: 17px;
1148
  line-height: 1.45;
 
1149
  }
1150
  .badge-row span {
1151
  display: inline-block;
1152
- border: 2px solid #4a2f1f;
1153
- background: #fff6dd;
 
1154
  padding: 6px 10px;
1155
  margin: 4px 5px 0 0;
1156
  font-weight: 700;
1157
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1158
  textarea, input {
1159
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
1160
  }
@@ -1165,11 +1655,11 @@ with gr.Blocks(css=CSS, title="DreamWall MC") as demo:
1165
  gr.HTML(
1166
  """
1167
  <section class="dreamwall-hero">
1168
- <h1>Living Graffiti MC</h1>
1169
  <p>
1170
- Type a prompt, sign it, and mint a 10-frame Minecraft wall artifact.
1171
- The artifact mutates, earns a wall slot, fuses with nearby ideas, and lives
1172
- as a named public memory on the server.
1173
  </p>
1174
  <div class="badge-row">
1175
  <span>Adventure in Thousand Token Wood</span>
@@ -1182,6 +1672,60 @@ with gr.Blocks(css=CSS, title="DreamWall MC") as demo:
1182
  </section>
1183
  """
1184
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1185
  gr.HTML("<h2>Living Graffiti Wall</h2>")
1186
  with gr.Row():
1187
  with gr.Column(scale=5):
 
4
  import os
5
  import tempfile
6
  from dataclasses import dataclass
7
+ from datetime import datetime, timezone
8
 
9
  import gradio as gr
10
  import numpy as np
 
102
  "a cloud dragon sleeping inside a circuit board",
103
  ]
104
 
105
+ MUSEUM_HALLS = [
106
+ "Hall of Firsts",
107
+ "Hall of Companions",
108
+ "Hall of Turning Points",
109
+ "Hall of Worlds",
110
+ "Hall of Soft Things",
111
+ "Hall of Tools",
112
+ "Hall of Lost Signals",
113
+ "Grand Painting Hall",
114
+ "Animal Spirit Grove",
115
+ ]
116
+
117
+ DEMO_ARTIFACTS = {
118
+ "Star Wars childhood book": {
119
+ "owner_name": "Arnav",
120
+ "owner_handle": "@Wildstash",
121
+ "input_type": "memory_prompt",
122
+ "source_prompt": "a worn Star Wars childhood book with bent corners and a silver spaceship on the cover",
123
+ "memory_text": "I kept reopening it because the galaxy felt bigger than my room.",
124
+ },
125
+ "AirPods from first year of university": {
126
+ "owner_name": "Arnav",
127
+ "owner_handle": "@Wildstash",
128
+ "input_type": "object_photo",
129
+ "source_prompt": "white AirPods from my first year of university",
130
+ "memory_text": "They carried private worlds through public noise during my first year away.",
131
+ },
132
+ "Monitor used for first Bitcoin trade": {
133
+ "owner_name": "Arnav",
134
+ "owner_handle": "@Wildstash",
135
+ "input_type": "object_photo",
136
+ "source_prompt": "a black monitor used for my first Bitcoin trade",
137
+ "memory_text": "A screen where numbers first started feeling like weather.",
138
+ },
139
+ "School bag carried through exams": {
140
+ "owner_name": "Arnav",
141
+ "owner_handle": "@Wildstash",
142
+ "input_type": "object_photo",
143
+ "source_prompt": "a school bag carried through exams",
144
+ "memory_text": "It held pencils, snacks, panic, and the weight of every morning.",
145
+ },
146
+ "Prompted painting: red dragon above childhood home": {
147
+ "owner_name": "Arnav",
148
+ "owner_handle": "@Wildstash",
149
+ "input_type": "painting_prompt",
150
+ "source_prompt": "a red dragon above my childhood home",
151
+ "memory_text": "A fantasy guardian hovering over the place I learned to imagine from.",
152
+ },
153
+ }
154
+
155
 
156
  @dataclass
157
  class ArtResult:
 
426
  return "\n".join(report), json.dumps(packet, indent=2)
427
 
428
 
429
+ def object_guess_for(input_type: str, source_prompt: str, memory_text: str) -> str:
430
+ text = f"{source_prompt} {memory_text}".lower()
431
+ guesses = [
432
+ ("book", ["book", "novel", "comic", "star wars", "cover"]),
433
+ ("earbuds", ["airpods", "earpods", "earbuds", "headphones", "music"]),
434
+ ("monitor", ["monitor", "screen", "display", "trade", "bitcoin"]),
435
+ ("school bag", ["bag", "backpack", "exams", "school"]),
436
+ ("painting", ["painting", "dragon", "prompted", "canvas"]),
437
+ ("animal spirit", ["pet", "animal", "dog", "cat", "bird", "creature"]),
438
+ ("tool", ["tool", "keyboard", "mouse", "camera", "phone"]),
439
+ ]
440
+ for guess, hints in guesses:
441
+ if any(hint in text for hint in hints):
442
+ return guess
443
+ if input_type == "painting_prompt":
444
+ return "prompted painting"
445
+ if input_type == "animal_spirit":
446
+ return "animal spirit"
447
+ return "personal relic"
448
+
449
+
450
+ def hall_for_artifact(input_type: str, object_guess: str, source_prompt: str, memory_text: str, seed: int) -> tuple[str, str]:
451
+ text = f"{object_guess} {source_prompt} {memory_text}".lower()
452
+ if input_type == "painting_prompt":
453
+ return "Grand Painting Hall", "paintings that were imagined before they were found"
454
+ if input_type == "animal_spirit" or any(word in text for word in ["pet", "animal", "dog", "cat", "bird", "creature"]):
455
+ return "Animal Spirit Grove", "the artifact behaves more like a companion than an object"
456
+ if any(word in text for word in ["first", "university", "bitcoin", "started"]):
457
+ return "Hall of Firsts", "the memory marks a first threshold"
458
+ if any(word in text for word in ["airpods", "bag", "friend", "carried", "companion"]):
459
+ return "Hall of Companions", "it stayed close to the owner through ordinary days"
460
+ if any(word in text for word in ["exam", "trade", "turning", "changed", "panic"]):
461
+ return "Hall of Turning Points", "the object sits near a decision or pressure point"
462
+ if any(word in text for word in ["star wars", "galaxy", "home", "world", "dragon"]):
463
+ return "Hall of Worlds", "it opened a world larger than the room around it"
464
+ if any(word in text for word in ["soft", "noise", "private", "morning"]):
465
+ return "Hall of Soft Things", "the memory is quiet, protective, and intimate"
466
+ if any(word in text for word in ["monitor", "tool", "screen", "keyboard"]):
467
+ return "Hall of Tools", "the artifact helped the owner act on the world"
468
+ if any(word in text for word in ["signal", "lost", "radio", "noise"]):
469
+ return "Hall of Lost Signals", "the artifact carries private signal through public static"
470
+ hall = MUSEUM_HALLS[seed % len(MUSEUM_HALLS)]
471
+ return hall, "the museum placed it by symbolic resonance"
472
+
473
+
474
+ def museum_zone_for(hall: str, seed: int) -> str:
475
+ zones = {
476
+ "Hall of Firsts": ["threshold alcove", "first-light row", "origin cabinet"],
477
+ "Hall of Companions": ["pocket gallery", "everyday pedestal", "quiet bench"],
478
+ "Hall of Turning Points": ["pressure corridor", "exam arch", "decision stair"],
479
+ "Hall of Worlds": ["portal bay", "map room", "myth shelf"],
480
+ "Hall of Soft Things": ["hush wing", "warm glass case", "felt-lit corner"],
481
+ "Hall of Tools": ["workbench row", "instrument vault", "copper desk"],
482
+ "Hall of Lost Signals": ["static aisle", "radio archive", "dim receiver"],
483
+ "Grand Painting Hall": ["large frame wall", "dragon bay", "painted sky"],
484
+ "Animal Spirit Grove": ["moss enclosure", "companion path", "moonlit pen"],
485
+ }
486
+ choices = zones.get(hall, ["west wing"])
487
+ return choices[seed % len(choices)]
488
+
489
+
490
+ def curation_scores(
491
+ source_prompt: str,
492
+ memory_text: str,
493
+ input_type: str,
494
+ moods: list[str],
495
+ palette_names: list[str],
496
+ plot: dict,
497
+ ) -> dict:
498
+ text = f"{source_prompt} {memory_text}".lower()
499
+ density = prompt_density(text)
500
+ neighbors = nearby_artworks(plot)
501
+ adjacency = min(1.0, sum(max(0, 3 - item["distance"]) for item in neighbors) / 6)
502
+ palette_rarity = len(set(palette_names).intersection({"obsidian", "amethyst_block", "sea_lantern", "glowstone"})) / 4
503
+ def score(words: list[str], base: float = 28.0) -> int:
504
+ hits = sum(1 for word in words if word in text)
505
+ return int(min(100, base + density * 35 + hits * 14))
506
+
507
+ scores = {
508
+ "nostalgia": score(["childhood", "school", "first", "home", "kept", "morning"]),
509
+ "symbolism": score(["dragon", "galaxy", "signal", "cover", "weather", "guardian"]),
510
+ "identity": score(["my", "first", "owner", "university", "trade"], 34),
511
+ "companionship": score(["carried", "airpods", "bag", "private", "through"], 30),
512
+ "transformation": score(["first", "trade", "exam", "changed", "started"], 26),
513
+ "rarity": int(min(100, 35 + len(set(moods)) * 10 + density * 25)),
514
+ "palette_rarity": int(round(palette_rarity * 100)),
515
+ "adjacency_resonance": int(round(adjacency * 100)),
516
+ "visitor_echoes": int(min(100, 12 + len(neighbors) * 17 + density * 34)),
517
+ }
518
+ weighted = (
519
+ scores["nostalgia"] * 0.16
520
+ + scores["symbolism"] * 0.14
521
+ + scores["identity"] * 0.14
522
+ + scores["companionship"] * 0.12
523
+ + scores["transformation"] * 0.12
524
+ + scores["rarity"] * 0.1
525
+ + scores["palette_rarity"] * 0.08
526
+ + scores["adjacency_resonance"] * 0.08
527
+ + scores["visitor_echoes"] * 0.06
528
+ )
529
+ scores["curation_score"] = int(round(weighted))
530
+ return scores
531
+
532
+
533
+ def spirit_for_artifact(title: str, object_guess: str, memory_text: str, hall: str, seed: int) -> dict:
534
+ traits_bank = {
535
+ "book": ["wide-eyed", "paper-worn", "portal-minded"],
536
+ "earbuds": ["private", "signal-carrying", "soft-spoken"],
537
+ "monitor": ["watchful", "electric", "threshold-bound"],
538
+ "school bag": ["patient", "burdened", "loyal"],
539
+ "painting": ["mythic", "paint-lit", "protective"],
540
+ "animal spirit": ["restless", "companionable", "wild"],
541
+ "personal relic": ["quiet", "symbolic", "half-remembered"],
542
+ }
543
+ traits = traits_bank.get(object_guess, traits_bank["personal relic"])
544
+ suffix = ["mote", "keeper", "echo", "sprite", "shade", "wisp"][seed % 6]
545
+ spirit_name = "".join(word.capitalize() for word in keywords_for_title(title)[:1]) + suffix.capitalize()
546
+ first_line = f"I am what remained when {object_guess} became a place."
547
+ if "airpods" in object_guess or object_guess == "earbuds":
548
+ first_line = "I carried private worlds through public noise."
549
+ elif object_guess == "book":
550
+ first_line = "I opened a galaxy small enough to fit in your hands."
551
+ elif object_guess == "monitor":
552
+ first_line = "I watched numbers become weather."
553
+ elif object_guess == "school bag":
554
+ first_line = "I carried the mornings you were not ready for."
555
+ elif object_guess == "painting":
556
+ first_line = "I guard the home that imagination returned to."
557
+ questions = [
558
+ "What do you remember?",
559
+ "Why are you in this hall?",
560
+ "What should visitors notice?",
561
+ ]
562
+ responses = [
563
+ first_line,
564
+ f"The curator placed me in {hall} because this memory still has a shape.",
565
+ f"Look for the detail that does not shout: {memory_text[:110]}",
566
+ ]
567
+ return {
568
+ "spirit_name": spirit_name,
569
+ "spirit_traits": traits,
570
+ "spirit_first_line": first_line,
571
+ "rules": [
572
+ "speak only from the object, memory, and artifact lore",
573
+ "do not behave like a generic assistant",
574
+ "answer as a quiet museum presence",
575
+ ],
576
+ "sample_visitor_questions": questions,
577
+ "sample_spirit_responses": responses,
578
+ }
579
+
580
+
581
+ def resonance_links_for_artifact(hall: str, moods: list[str], plot: dict) -> list[dict]:
582
+ links = []
583
+ for art in nearby_artworks(plot):
584
+ shared = sorted(set(moods).intersection(art["moods"]))
585
+ links.append(
586
+ {
587
+ "title": art["title"],
588
+ "creator": art["player"],
589
+ "distance": art["distance"],
590
+ "resonance": "shared mood" if shared else "nearby museum placement",
591
+ "shared_moods": shared,
592
+ "hall_echo": hall,
593
+ }
594
+ )
595
+ return links
596
+
597
+
598
+ def passport_html(artifact: dict) -> str:
599
+ palette = artifact["palette"][:5]
600
+ swatches = "".join(
601
+ f"<span class='museum-swatch' title='{name}' style='background: rgb({rgb[0]}, {rgb[1]}, {rgb[2]})'></span>"
602
+ for name, rgb in [next((block for block in BLOCKS if block[0] == item), ("stone", (120, 120, 120))) for item in palette]
603
+ )
604
+ return f"""
605
+ <section class="passport-card">
606
+ <div class="passport-kicker">Preserved in AfterBlock Museum</div>
607
+ <h2>{artifact['title']}</h2>
608
+ <p class="passport-owner">{artifact['owner_handle']} · {artifact['hall']}</p>
609
+ <div class="passport-grid">
610
+ <div class="passport-preview">{swatches}<strong>{artifact['spirit_name']}</strong></div>
611
+ <div>
612
+ <p><strong>Plot</strong> ({artifact['plot']['x']}, {artifact['plot']['z']})</p>
613
+ <p><strong>Coordinates</strong> {artifact['minecraft_coordinates']['x']} {artifact['minecraft_coordinates']['y']} {artifact['minecraft_coordinates']['z']}</p>
614
+ <p><strong>Plaque</strong> {artifact['plaque_line']}</p>
615
+ <p><strong>QR payload</strong> <code>{artifact['qr_payload']}</code></p>
616
+ </div>
617
+ </div>
618
+ </section>
619
+ """
620
+
621
+
622
+ def floor_map_html(artifact: dict) -> str:
623
+ cells = []
624
+ for z in range(CANVAS_SIZE):
625
+ for x in range(CANVAS_SIZE):
626
+ active = x == artifact["plot"]["x"] and z == artifact["plot"]["z"]
627
+ label = "★" if active else ""
628
+ cells.append(f"<span class='floor-cell {'active' if active else ''}'>{label}</span>")
629
+ return f"<div class='floor-map'>{''.join(cells)}</div>"
630
+
631
+
632
+ def build_museum_artifact(
633
+ owner_name: str,
634
+ owner_handle: str,
635
+ input_type: str,
636
+ source_prompt: str,
637
+ memory_text: str,
638
+ ) -> dict:
639
+ owner_name = (owner_name or "Anonymous").strip()
640
+ owner_handle = (owner_handle or "@unknown").strip()
641
+ input_type = (input_type or "memory_prompt").strip()
642
+ source_prompt = (source_prompt or "a mysterious object from a half-remembered room").strip()
643
+ memory_text = (memory_text or "No memory text was provided, so the museum listens to the object itself.").strip()
644
+ text = f"afterblock={owner_name}|{owner_handle}|{input_type}|{source_prompt}|{memory_text}"
645
+ seed = stable_seed(text)
646
+ vec = embedding(text)
647
+ moods = top_moods(text, vec)
648
+ palette = palette_from_vector(vec, seed, moods)
649
+ palette_names = [name for name, _ in palette]
650
+ object_guess = object_guess_for(input_type, source_prompt, memory_text)
651
+ hall, placement_reason = hall_for_artifact(input_type, object_guess, source_prompt, memory_text, seed)
652
+ zone = museum_zone_for(hall, seed)
653
+ plot = plot_for_seed(seed)
654
+ title = artifact_title(source_prompt, seed, moods)
655
+ artifact_id = hashlib.sha256(text.encode("utf-8")).hexdigest()[:16]
656
+ scores = curation_scores(source_prompt, memory_text, input_type, moods, palette_names, plot)
657
+ spirit = spirit_for_artifact(title, object_guess, memory_text, hall, seed)
658
+ coordinates = {"x": plot["world_x"], "y": 80, "z": plot["world_z"]}
659
+ plaque_line = spirit["spirit_first_line"]
660
+ lore_short = f"{object_guess.title()} placed in {hall.lower()} because {placement_reason}."
661
+ artifact = {
662
+ "artifact_id": artifact_id,
663
+ "owner_name": owner_name,
664
+ "owner_handle": owner_handle,
665
+ "input_type": input_type,
666
+ "title": title,
667
+ "source_prompt": source_prompt,
668
+ "memory_text": memory_text,
669
+ "object_guess": object_guess,
670
+ "hall": hall,
671
+ "zone": zone,
672
+ "plot": plot,
673
+ "minecraft_coordinates": coordinates,
674
+ "palette": palette_names,
675
+ "minecraft_materials": palette_names,
676
+ "plaque_line": plaque_line,
677
+ "lore_short": lore_short,
678
+ "spirit_name": spirit["spirit_name"],
679
+ "spirit_traits": spirit["spirit_traits"],
680
+ "spirit_first_line": spirit["spirit_first_line"],
681
+ "placement_reason": placement_reason,
682
+ "curation_scores": scores,
683
+ "resonance_links": resonance_links_for_artifact(hall, moods, plot),
684
+ "passport_card": {
685
+ "title": title,
686
+ "owner_handle": owner_handle,
687
+ "hall": hall,
688
+ "plot": plot,
689
+ "minecraft_coordinates": coordinates,
690
+ "plaque_line": plaque_line,
691
+ "preservation_line": "Preserved in AfterBlock Museum",
692
+ },
693
+ "qr_payload": f"afterblock://artifact/{artifact_id}",
694
+ "created_at": datetime.now(timezone.utc).isoformat(),
695
+ }
696
+ artifact.update(spirit)
697
+ return artifact
698
+
699
+
700
+ def museum_packet_for(artifact: dict) -> dict:
701
+ return {
702
+ "type": "dreamwall.museum.v1",
703
+ "artifact": artifact,
704
+ "museum": {
705
+ "hall": artifact["hall"],
706
+ "zone": artifact["zone"],
707
+ "plot": artifact["plot"],
708
+ "coordinates": artifact["minecraft_coordinates"],
709
+ "placement_reason": artifact["placement_reason"],
710
+ },
711
+ "spirit": {
712
+ "name": artifact["spirit_name"],
713
+ "traits": artifact["spirit_traits"],
714
+ "first_line": artifact["spirit_first_line"],
715
+ "rules": artifact["rules"],
716
+ "sample_visitor_questions": artifact["sample_visitor_questions"],
717
+ "sample_spirit_responses": artifact["sample_spirit_responses"],
718
+ },
719
+ "passport": artifact["passport_card"],
720
+ "minecraft": {
721
+ "protocol": "dreamwall.mc.v1",
722
+ "import_mode": "museum_artifact",
723
+ "title": artifact["title"],
724
+ "hall": artifact["hall"],
725
+ "coordinates": artifact["minecraft_coordinates"],
726
+ "materials": artifact["minecraft_materials"],
727
+ "plaque_text": artifact["plaque_line"],
728
+ "spirit_first_line": artifact["spirit_first_line"],
729
+ "owner_handle": artifact["owner_handle"],
730
+ "passport_qr_payload": artifact["qr_payload"],
731
+ "pedestal": "place sign, item frame, and blocky preview at coordinates",
732
+ },
733
+ }
734
+
735
+
736
+ def curate_afterblock_artifact(
737
+ owner_name: str,
738
+ owner_handle: str,
739
+ input_type: str,
740
+ source_prompt: str,
741
+ memory_text: str,
742
+ ):
743
+ artifact = build_museum_artifact(owner_name, owner_handle, input_type, source_prompt, memory_text)
744
+ packet = museum_packet_for(artifact)
745
+ placement = [
746
+ f"# {artifact['title']}",
747
+ f"Owner: **{artifact['owner_handle']}**",
748
+ f"Hall: **{artifact['hall']}** / {artifact['zone']}",
749
+ f"Plot: **({artifact['plot']['x']}, {artifact['plot']['z']})**",
750
+ f"Minecraft coordinates: **{artifact['minecraft_coordinates']['x']} {artifact['minecraft_coordinates']['y']} {artifact['minecraft_coordinates']['z']}**",
751
+ f"Curation score: **{artifact['curation_scores']['curation_score']}**",
752
+ "",
753
+ f"Placement reason: {artifact['placement_reason']}",
754
+ f"Plaque: _{artifact['plaque_line']}_",
755
+ "",
756
+ "Resonance links:",
757
+ ]
758
+ if artifact["resonance_links"]:
759
+ placement.extend(
760
+ f"- {link['title']} by {link['creator']}: {link['resonance']}, distance {link['distance']}"
761
+ for link in artifact["resonance_links"]
762
+ )
763
+ else:
764
+ placement.append("- No nearby resonance yet. This artifact becomes an anchor for future visitors.")
765
+ spirit_lines = [
766
+ f"# {artifact['spirit_name']}",
767
+ f"Traits: {', '.join(artifact['spirit_traits'])}",
768
+ f"First line: _{artifact['spirit_first_line']}_",
769
+ "",
770
+ "Visitor questions and spirit responses:",
771
+ ]
772
+ for question, response in zip(artifact["sample_visitor_questions"], artifact["sample_spirit_responses"]):
773
+ spirit_lines.append(f"- **{question}** {response}")
774
+ passport = passport_html(artifact) + floor_map_html(artifact)
775
+ return (
776
+ "\n".join(placement),
777
+ spirit_lines and "\n".join(spirit_lines),
778
+ passport,
779
+ json.dumps(packet, indent=2),
780
+ )
781
+
782
+
783
+ def load_demo_artifact(name: str):
784
+ data = DEMO_ARTIFACTS.get(name) or next(iter(DEMO_ARTIFACTS.values()))
785
+ return (
786
+ data["owner_name"],
787
+ data["owner_handle"],
788
+ data["input_type"],
789
+ data["source_prompt"],
790
+ data["memory_text"],
791
+ )
792
+
793
+
794
  HABITATS = {
795
  "redstone caves": ["electric", "mechanical", "small", "curious"],
796
  "sky forest": ["flying", "social", "light", "watchful"],
 
1534
 
1535
  CSS = """
1536
  :root {
1537
+ --mc-ink: #f4ecd8;
1538
+ --mc-paper: #171410;
1539
  --mc-green: #57744a;
1540
  --mc-gold: #d39b45;
1541
+ --museum-stone: #1f211f;
1542
+ --museum-panel: #2b251c;
1543
+ --museum-glow: #f2c15f;
1544
  }
1545
  body, .gradio-container {
1546
+ background: #10110f !important;
1547
  color: var(--mc-ink);
1548
  }
1549
  .gradio-container {
1550
  max-width: 1180px !important;
1551
  }
1552
  .dreamwall-hero {
1553
+ background: linear-gradient(135deg, #1b1d1b 0%, #322719 100%);
1554
+ border: 3px solid #8b6a3d;
1555
+ box-shadow: 0 10px 0 #060605, inset 0 0 28px rgba(242, 193, 95, 0.12);
1556
  padding: 22px;
1557
  margin: 14px 0 18px;
1558
  }
1559
  .dreamwall-hero h1 {
1560
  margin: 0;
1561
  font-size: 42px;
1562
+ color: #ffe4a3;
1563
  }
1564
  .dreamwall-hero p {
1565
  max-width: 760px;
1566
  font-size: 17px;
1567
  line-height: 1.45;
1568
+ color: #ead7b0;
1569
  }
1570
  .badge-row span {
1571
  display: inline-block;
1572
+ border: 2px solid #8b6a3d;
1573
+ background: #211a12;
1574
+ color: #ffdc8a;
1575
  padding: 6px 10px;
1576
  margin: 4px 5px 0 0;
1577
  font-weight: 700;
1578
  }
1579
+ .museum-terminal {
1580
+ background: #171916;
1581
+ border: 2px solid #6f6a57;
1582
+ box-shadow: inset 0 0 18px rgba(242, 193, 95, 0.1);
1583
+ padding: 14px;
1584
+ margin: 10px 0;
1585
+ }
1586
+ .passport-card {
1587
+ background: #221d16;
1588
+ border: 3px solid #b98a46;
1589
+ box-shadow: 0 8px 0 #080705, inset 0 0 24px rgba(242, 193, 95, 0.14);
1590
+ color: #f9e4b4;
1591
+ padding: 18px;
1592
+ }
1593
+ .passport-card h2 {
1594
+ margin: 4px 0;
1595
+ font-size: 30px;
1596
+ color: #ffe6a6;
1597
+ }
1598
+ .passport-kicker {
1599
+ color: #e2b86f;
1600
+ font-size: 12px;
1601
+ letter-spacing: 0.08em;
1602
+ text-transform: uppercase;
1603
+ }
1604
+ .passport-owner {
1605
+ color: #cdbd9b;
1606
+ }
1607
+ .passport-grid {
1608
+ display: grid;
1609
+ grid-template-columns: minmax(160px, 240px) 1fr;
1610
+ gap: 16px;
1611
+ }
1612
+ .passport-preview {
1613
+ min-height: 150px;
1614
+ border: 2px solid #6f6a57;
1615
+ background: repeating-linear-gradient(45deg, #2b2d29 0, #2b2d29 10px, #242520 10px, #242520 20px);
1616
+ display: flex;
1617
+ flex-wrap: wrap;
1618
+ align-content: center;
1619
+ justify-content: center;
1620
+ gap: 8px;
1621
+ padding: 12px;
1622
+ }
1623
+ .museum-swatch {
1624
+ width: 30px;
1625
+ height: 30px;
1626
+ border: 2px solid #0b0b09;
1627
+ display: inline-block;
1628
+ }
1629
+ .floor-map {
1630
+ display: grid;
1631
+ grid-template-columns: repeat(12, 18px);
1632
+ gap: 3px;
1633
+ margin-top: 12px;
1634
+ }
1635
+ .floor-cell {
1636
+ width: 18px;
1637
+ height: 18px;
1638
+ background: #34372f;
1639
+ border: 1px solid #57513f;
1640
+ color: #1b160e;
1641
+ text-align: center;
1642
+ line-height: 18px;
1643
+ }
1644
+ .floor-cell.active {
1645
+ background: #f2c15f;
1646
+ box-shadow: 0 0 10px #f2c15f;
1647
+ }
1648
  textarea, input {
1649
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
1650
  }
 
1655
  gr.HTML(
1656
  """
1657
  <section class="dreamwall-hero">
1658
+ <h1>DreamWall: AfterBlock Museum</h1>
1659
  <p>
1660
+ Scan a relic, memory, animal spirit, or prompted painting. The museum assigns
1661
+ a hall, chisels a Minecraft placement, awakens a tiny spirit, and prints an
1662
+ artifact passport for the server.
1663
  </p>
1664
  <div class="badge-row">
1665
  <span>Adventure in Thousand Token Wood</span>
 
1672
  </section>
1673
  """
1674
  )
1675
+ gr.HTML("<h2>AfterBlock Museum Terminal</h2><div class='museum-terminal'>chiseling memory into blocks... consulting the museum curator... assigning hall placement... awakening artifact spirit...</div>")
1676
+ with gr.Row():
1677
+ with gr.Column(scale=5):
1678
+ demo_choice = gr.Dropdown(
1679
+ label="Seeded demo relic",
1680
+ choices=list(DEMO_ARTIFACTS),
1681
+ value="AirPods from first year of university",
1682
+ )
1683
+ owner_name = gr.Textbox(label="Owner name", value="Arnav")
1684
+ owner_handle = gr.Textbox(label="Owner handle", value="@Wildstash")
1685
+ input_type = gr.Dropdown(
1686
+ label="Input type",
1687
+ choices=["object_photo", "painting_prompt", "memory_prompt", "animal_spirit"],
1688
+ value="object_photo",
1689
+ )
1690
+ relic_prompt = gr.Textbox(
1691
+ label="Scan relic / prompt",
1692
+ lines=3,
1693
+ value="white AirPods from my first year of university",
1694
+ )
1695
+ memory_text = gr.Textbox(
1696
+ label="Memory text",
1697
+ lines=3,
1698
+ value="They carried private worlds through public noise during my first year away.",
1699
+ )
1700
+ museum_button = gr.Button("Curate Artifact", variant="primary")
1701
+ with gr.Column(scale=5):
1702
+ with gr.Tabs():
1703
+ with gr.Tab("Curate Placement"):
1704
+ museum_placement = gr.Markdown()
1705
+ with gr.Tab("Awaken Spirit"):
1706
+ museum_spirit = gr.Markdown()
1707
+ with gr.Tab("Passport Card"):
1708
+ museum_passport = gr.HTML()
1709
+ with gr.Tab("Minecraft Bridge"):
1710
+ museum_packet = gr.Textbox(label="dreamwall.museum.v1", lines=22, max_lines=32)
1711
+
1712
+ demo_choice.change(
1713
+ load_demo_artifact,
1714
+ inputs=[demo_choice],
1715
+ outputs=[owner_name, owner_handle, input_type, relic_prompt, memory_text],
1716
+ )
1717
+ museum_button.click(
1718
+ curate_afterblock_artifact,
1719
+ inputs=[owner_name, owner_handle, input_type, relic_prompt, memory_text],
1720
+ outputs=[museum_placement, museum_spirit, museum_passport, museum_packet],
1721
+ api_name="curate_artifact",
1722
+ )
1723
+ demo.load(
1724
+ curate_afterblock_artifact,
1725
+ inputs=[owner_name, owner_handle, input_type, relic_prompt, memory_text],
1726
+ outputs=[museum_placement, museum_spirit, museum_passport, museum_packet],
1727
+ )
1728
+
1729
  gr.HTML("<h2>Living Graffiti Wall</h2>")
1730
  with gr.Row():
1731
  with gr.Column(scale=5):
docs/COMPETITION_GOAL.md CHANGED
@@ -1,19 +1,19 @@
1
- # DreamWall MC Competition Goal
2
 
3
  ## Goal
4
 
5
- Win the Build Small Hackathon by making DreamWall MC feel like a new way to interact with a world: a living public Minecraft canvas where prompts become named 32x32 artifacts, visibly mutate, gain value through context, and fuse into shared landmarks.
6
 
7
  ## Submission Bet
8
 
9
- DreamWall is not a chatbot and not a normal image generator. It is a social imagination wall inside Minecraft:
10
 
11
- - people submit prompts through the Hugging Face Space
12
- - each prompt gets a stable 32x32 wall slot on a flat-world canvas
13
- - each artifact has a name, mood, mutation rate, growth stage, and attention weather
14
- - nearby concepts draw visible fusion links when semantic/context rules line up
15
- - the system assigns demo value based on density, adjacency, rarity, and votes
16
- - the Minecraft server becomes the proof surface and the Space emits the bridge packet
17
 
18
  ## What To Avoid For V1
19
 
@@ -22,25 +22,25 @@ DreamWall is not a chatbot and not a normal image generator. It is a social imag
22
  - Complex ownership law
23
  - Persistent public multiplayer economy before the demo works
24
 
25
- Use **demo points** and **auction-style voting** first. That gives the same emotional loop without compliance risk.
26
 
27
  ## Winning Demo
28
 
29
  One continuous video:
30
 
31
  1. Open the Hugging Face Space.
32
- 2. Open **Living Moving Canvas**.
33
- 3. Paste a short feed of six prompts from different imagined players.
34
- 4. Move the evolution tick and show the wall pulsing.
35
- 5. Point out visible fusion links, attention weather, and growth stages.
36
- 6. Show the `living_canvas.mc.v1` packet with 32x32 tiles and 384x384 wall size.
37
- 7. Generate one individual Living Graffiti artifact.
38
- 8. Join the Minecraft flat world.
39
- 9. Walk to the giant canvas and show names, values, and fused plot labels.
40
- 10. End with: "100 people prompt the wall; nobody knows what public mural survives."
41
 
42
  ## Target Prizes
43
 
44
  - OpenAI Codex Track: public GitHub repo with Codex-authored commits.
45
- - Adventure in Thousand Token Wood: strange, social, delightful, AI-load-bearing, and small enough to run without a giant model dependency.
46
- - NVIDIA GPU prize: video must make the world feel worth rendering/exploring.
 
 
1
+ # DreamWall: AfterBlock Museum Competition Goal
2
 
3
  ## Goal
4
 
5
+ Win the Build Small Hackathon by making DreamWall feel like a new way to preserve memory: an emotional Minecraft museum where real objects, prompted paintings, animals, and personal symbols become placed artifacts with passports and tiny spirits.
6
 
7
  ## Submission Bet
8
 
9
+ AfterBlock Museum is not a chatbot and not a normal image generator. It is a Minecraft museum ritual:
10
 
11
+ - visitors scan a relic, memory, animal spirit, or prompted painting
12
+ - the curator assigns a hall and museum placement
13
+ - each artifact receives curation scores, resonance links, and a plaque
14
+ - a constrained spirit awakens and speaks from the artifact lore
15
+ - the app prints a passport card and emits `dreamwall.museum.v1`
16
+ - the Minecraft server becomes the proof surface
17
 
18
  ## What To Avoid For V1
19
 
 
22
  - Complex ownership law
23
  - Persistent public multiplayer economy before the demo works
24
 
25
+ Use **curation score**, **visitor echoes**, and **resonance** instead of auction language.
26
 
27
  ## Winning Demo
28
 
29
  One continuous video:
30
 
31
  1. Open the Hugging Face Space.
32
+ 2. Pick the AirPods seeded demo.
33
+ 3. Show the hall assignment, curation score, and placement reason.
34
+ 4. Open **Awaken Spirit** and read the first line: "I carried private worlds through public noise."
35
+ 5. Open **Passport Card** and show the Minecraft coordinates.
36
+ 6. Open **Minecraft Bridge** and show `dreamwall.museum.v1`.
37
+ 7. Switch to Minecraft.
38
+ 8. Place or mock one pedestal/sign using the packet coordinates.
39
+ 9. End with: "AfterBlock turns the things people would throw away into places they can visit."
 
40
 
41
  ## Target Prizes
42
 
43
  - OpenAI Codex Track: public GitHub repo with Codex-authored commits.
44
+ - Adventure in Thousand Token Wood: strange, emotional, delightful, AI-load-bearing, and small enough to run without a giant model dependency.
45
+ - Off-Brand: Minecraft museum terminal rather than default chatbot UI.
46
+ - Best Demo: object to hall to spirit to passport to Minecraft proof in under 75 seconds.
docs/DEMO_RUNBOOK.md CHANGED
@@ -1,29 +1,28 @@
1
- # Demo Runbook
2
 
3
  ## Story
4
 
5
- Living Graffiti is a social Minecraft wall where anonymous prompts become animated public artifacts. Living Moving Canvas is the stronger demo: a feed of prompts becomes a shared wall that pulses, mutates, and draws fusion links between nearby ideas.
6
 
7
  ## Script
8
 
9
  1. Show the Hugging Face Space.
10
- 2. Open **Living Moving Canvas**.
11
- 3. Show six prompts becoming one animated 12x12 wall.
12
- 4. Scrub the evolution tick and point to the pulsing tiles.
13
- 5. Show visible fusion links between nearby or semantically related artifacts.
14
- 6. Show strongest artifacts, attention weather, and growth stages.
15
- 7. Open the `living_canvas.mc.v1` Minecraft packet.
16
- 8. Generate one individual Living Graffiti artifact.
17
- 9. Switch to Minecraft.
18
- 10. Show the flat wall / planned slot with creator name and value.
19
- 11. End with: "100 people prompt the wall; nobody knows what public mural survives."
20
 
21
  ## Video Requirements
22
 
23
- - Keep the final demo under 60 seconds.
24
  - Show both the Space and Minecraft world.
25
  - Do not explain implementation details in the voiceover.
26
- - Focus on the magic: people write language, the wall moves, fuses, and grows.
27
 
28
  ## Submission Checklist
29
 
@@ -32,4 +31,4 @@ Living Graffiti is a social Minecraft wall where anonymous prompts become animat
32
  - GitHub commits are Codex-authored.
33
  - Field notes are present.
34
  - Demo video shows real UI and Minecraft proof.
35
- - Social post says this is a living public Minecraft wall, not a chatbot.
 
1
+ # AfterBlock Demo Runbook
2
 
3
  ## Story
4
 
5
+ AfterBlock Museum preserves ordinary objects as Minecraft artifacts. The Space acts like a museum terminal: it scans a relic, assigns a hall, awakens a tiny spirit, prints a passport card, and emits a bridge packet for the server.
6
 
7
  ## Script
8
 
9
  1. Show the Hugging Face Space.
10
+ 2. Select **AirPods from first year of university**.
11
+ 3. Click **Curate Artifact**.
12
+ 4. Show **Curate Placement**: Hall of Companions or Lost Signals, plot, coordinates, curation score.
13
+ 5. Open **Awaken Spirit** and read: "I carried private worlds through public noise."
14
+ 6. Open **Passport Card** and show the blocky card/floor map.
15
+ 7. Open **Minecraft Bridge** and show `dreamwall.museum.v1`.
16
+ 8. Switch to Minecraft.
17
+ 9. Show a pedestal/sign/painting marker at the packet coordinates.
18
+ 10. End with: "AfterBlock turns the things people would throw away into places they can visit."
 
19
 
20
  ## Video Requirements
21
 
22
+ - Keep the final demo under 75 seconds.
23
  - Show both the Space and Minecraft world.
24
  - Do not explain implementation details in the voiceover.
25
+ - Focus on the magic: a memory becomes a place with a spirit.
26
 
27
  ## Submission Checklist
28
 
 
31
  - GitHub commits are Codex-authored.
32
  - Field notes are present.
33
  - Demo video shows real UI and Minecraft proof.
34
+ - Social post says this is a Minecraft memory museum, not a chatbot.
docs/MINECRAFT_SERVER_BLUEPRINT.md CHANGED
@@ -29,7 +29,7 @@ Optional:
29
 
30
  ## World Shape
31
 
32
- Flat world with one giant public canvas.
33
 
34
  Suggested layout:
35
 
@@ -37,10 +37,10 @@ Suggested layout:
37
  spawn
38
  |
39
  +-- welcome board
40
- +-- rules board
41
- +-- DreamWall canvas at y=80
42
- +-- 12x12 plot grid
43
- +-- each plot is 32x32 blocks
44
  ```
45
 
46
  Coordinates:
@@ -52,12 +52,13 @@ grid: 12 x 12
52
  total canvas: 384 x 384 blocks
53
  ```
54
 
55
- ## Plot Rules
56
 
57
- - Each submission gets a deterministic plot from prompt + player + gallery zone.
58
- - Nearby plots can fuse if their symbols/moods align.
59
- - Names are shown as signs or hologram-style text later.
60
- - Value is demo points, not real money.
 
61
 
62
  ## First Server Milestone
63
 
@@ -65,14 +66,32 @@ total canvas: 384 x 384 blocks
65
  2. Install Paper and WorldEdit.
66
  3. Upload DreamWall bridge jar.
67
  4. Run `/dreamwall fetch`.
68
- 5. Call the `living_canvas` Space endpoint and copy the `living_canvas.mc.v1` packet.
69
- 6. Manually place one generated 32x32 tile from `tiles[].minecraft_origin` on a test wall.
70
- 7. Add signs for title, creator, stage, weather, and value.
71
  8. Record a 20-second proof clip.
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  ## Living Canvas Packet
74
 
75
- The main demo packet is `living_canvas.mc.v1`.
76
 
77
  It gives the server:
78
 
 
29
 
30
  ## World Shape
31
 
32
+ Flat world with one museum campus plus the existing public canvas as a secondary wing.
33
 
34
  Suggested layout:
35
 
 
37
  spawn
38
  |
39
  +-- welcome board
40
+ +-- AfterBlock Museum terminal
41
+ +-- hall corridor
42
+ +-- artifact pedestals/signs
43
+ +-- DreamWall canvas wing at y=80
44
  ```
45
 
46
  Coordinates:
 
52
  total canvas: 384 x 384 blocks
53
  ```
54
 
55
+ ## Museum Rules
56
 
57
+ - Each submission gets a deterministic hall, zone, plot, and Minecraft coordinate.
58
+ - Curation score replaces market value.
59
+ - Plaques show title, owner handle, spirit first line, and hall.
60
+ - Resonance links connect nearby or emotionally similar artifacts.
61
+ - No real-money ownership, blockchain, or NFT claims.
62
 
63
  ## First Server Milestone
64
 
 
66
  2. Install Paper and WorldEdit.
67
  3. Upload DreamWall bridge jar.
68
  4. Run `/dreamwall fetch`.
69
+ 5. Call the `curate_artifact` Space endpoint and copy the `dreamwall.museum.v1` packet.
70
+ 6. Manually place one pedestal/sign at `museum.coordinates`.
71
+ 7. Add signs for title, owner handle, hall, plaque line, and spirit first line.
72
  8. Record a 20-second proof clip.
73
 
74
+ ## Museum Packet
75
+
76
+ The main demo packet is `dreamwall.museum.v1`.
77
+
78
+ It gives the server:
79
+
80
+ - artifact title
81
+ - owner handle
82
+ - hall and zone
83
+ - plot and coordinates
84
+ - block palette/materials
85
+ - plaque text
86
+ - spirit first line
87
+ - passport QR payload
88
+ - curation scores and resonance links
89
+
90
+ The Paper plugin V1 only needs to import the packet and place a pedestal/sign/painting marker at the coordinates.
91
+
92
  ## Living Canvas Packet
93
 
94
+ The secondary canvas packet is `living_canvas.mc.v1`.
95
 
96
  It gives the server:
97
 
docs/MUSEUM_CURATION.md ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Museum Curation
2
+
3
+ AfterBlock Museum should feel like memories have resonance, not like plots are being sold.
4
+
5
+ ## Curation Signals
6
+
7
+ The app computes curation from:
8
+
9
+ - **Nostalgia:** childhood, firsts, school, home, and remembered routines.
10
+ - **Symbolism:** objects that carry myth, signal, protection, or identity.
11
+ - **Identity:** how strongly the relic belongs to the owner.
12
+ - **Companionship:** objects that stayed close through ordinary days.
13
+ - **Transformation:** exams, trades, moves, first years, and turning points.
14
+ - **Rarity:** unusual object/memory combinations.
15
+ - **Palette rarity:** rare Minecraft materials in the artifact palette.
16
+ - **Adjacency resonance:** nearby museum artifacts that echo the new relic.
17
+ - **Visitor echoes:** how likely visitors are to ask about it.
18
+
19
+ ## Resonance
20
+
21
+ Resonance replaces auction language.
22
+
23
+ Examples:
24
+
25
+ - AirPods from first year of university resonate with Lost Signals and Soft Things.
26
+ - A childhood Star Wars book resonates with Worlds and Firsts.
27
+ - A monitor used for a first Bitcoin trade resonates with Tools and Turning Points.
28
+ - A school bag carried through exams resonates with Companions and pressure memories.
29
+
30
+ The key is emotional legibility: visitors should immediately understand why the artifact belongs in its hall.
31
+
32
+ ## Why Not Market Language
33
+
34
+ Auction, reserve, and blockchain language distract from the stronger demo.
35
+
36
+ The winning V1 is:
37
+
38
+ ```text
39
+ relic -> hall -> spirit -> passport -> Minecraft museum placement
40
+ ```
41
+
42
+ The old `dreamwall.market.v1` packet can remain for compatibility, but the main user-facing packet is now `dreamwall.museum.v1`.
paper-plugin/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # DreamWall Paper Bridge
2
 
3
- This is the Minecraft server bridge for DreamWall MC.
4
 
5
  The hackathon Space is the official submission surface. This plugin scaffold is the live-demo layer: it connects a Paper server to the Space API and prepares the path for placing generated wall art inside Minecraft.
6
 
@@ -8,12 +8,33 @@ The hackathon Space is the official submission surface. This plugin scaffold is
8
 
9
  - `/dreamwall` shows the configured Space endpoint.
10
  - `/dreamwall fetch` calls the Space app domain and confirms the bridge can reach Hugging Face.
11
- - A scheduled task can be extended to poll approved wall jobs.
12
- - The Space now emits `living_canvas.mc.v1`, a multi-prompt wall packet for the main hackathon demo.
 
13
 
14
  ## Planned Placement Behavior
15
 
16
- The Space emits a `dreamwall.mc.v1` JSON packet with:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  - `job_id`
19
  - `player`
@@ -26,7 +47,7 @@ The Space emits a `dreamwall.mc.v1` JSON packet with:
26
  - `grid.row_runs`
27
  - WorldEdit preview lines
28
 
29
- The stronger cash-prize path uses `living_canvas.mc.v1` from the `living_canvas` endpoint:
30
 
31
  - `tile_size_blocks`: `32 x 32`
32
  - `canvas_size_tiles`: `12 x 12`
@@ -57,12 +78,12 @@ The Space also emits a `neuropets.mc.v1` packet from the `hatch_pet` endpoint. T
57
 
58
  For the hackathon video, the safest route is:
59
 
60
- 1. Run Living Moving Canvas in the Space.
61
- 2. Copy the `living_canvas.mc.v1` packet or call the Gradio API.
62
- 3. Place one or more `tiles[]` at their `minecraft_origin`.
63
- 4. Add signs for creator, title, value, stage, and weather.
64
- 5. Use particles or a command-block pulse to show fusion links.
65
- 6. Walk through the server gallery.
66
 
67
  ## Flat World Canvas
68
 
@@ -84,6 +105,10 @@ For `living_canvas.mc.v1`, the packet already includes `tiles[].minecraft_origin
84
 
85
  ## Build
86
 
 
 
 
 
87
  ```bash
88
  mvn package
89
  ```
 
1
+ # DreamWall AfterBlock Paper Bridge
2
 
3
+ This is the Minecraft server bridge for DreamWall: AfterBlock Museum.
4
 
5
  The hackathon Space is the official submission surface. This plugin scaffold is the live-demo layer: it connects a Paper server to the Space API and prepares the path for placing generated wall art inside Minecraft.
6
 
 
8
 
9
  - `/dreamwall` shows the configured Space endpoint.
10
  - `/dreamwall fetch` calls the Space app domain and confirms the bridge can reach Hugging Face.
11
+ - A scheduled task can be extended to poll approved museum artifacts.
12
+ - The Space now emits `dreamwall.museum.v1`, the main AfterBlock packet for the hackathon demo.
13
+ - The Space also emits `living_canvas.mc.v1` for the secondary wall/canvas mode.
14
 
15
  ## Planned Placement Behavior
16
 
17
+ The main Space endpoint is `curate_artifact`, which emits `dreamwall.museum.v1` with:
18
+
19
+ - artifact title
20
+ - owner handle
21
+ - hall and zone
22
+ - plot and coordinates
23
+ - block palette/materials
24
+ - plaque text
25
+ - spirit first line
26
+ - passport QR payload
27
+ - curation scores
28
+ - resonance links
29
+
30
+ Expected `/dreamwall fetch` V1 behavior:
31
+
32
+ 1. Fetch latest artifact packet.
33
+ 2. Place pedestal/sign/painting marker at coordinates.
34
+ 3. Display plaque line and owner handle.
35
+ 4. Optionally create particles or a simple animation based on artifact type.
36
+
37
+ The legacy `generate_art` endpoint emits a `dreamwall.mc.v1` JSON packet with:
38
 
39
  - `job_id`
40
  - `player`
 
47
  - `grid.row_runs`
48
  - WorldEdit preview lines
49
 
50
+ The secondary canvas path uses `living_canvas.mc.v1` from the `living_canvas` endpoint:
51
 
52
  - `tile_size_blocks`: `32 x 32`
53
  - `canvas_size_tiles`: `12 x 12`
 
78
 
79
  For the hackathon video, the safest route is:
80
 
81
+ 1. Run AfterBlock Museum in the Space.
82
+ 2. Copy the `dreamwall.museum.v1` packet or call the Gradio API.
83
+ 3. Place one artifact pedestal/sign at `museum.coordinates`.
84
+ 4. Add signs for owner, title, hall, plaque, and spirit first line.
85
+ 5. Use particles around the pedestal for the artifact spirit.
86
+ 6. Walk through the museum gallery.
87
 
88
  ## Flat World Canvas
89
 
 
105
 
106
  ## Build
107
 
108
+ GitHub Actions builds the jar through `.github/workflows/build-plugin.yml`.
109
+
110
+ Local build, if Maven is installed:
111
+
112
  ```bash
113
  mvn package
114
  ```