Here, the presence of an attribute signals behavior. With element-behaviors, has= attribute is used to say what behavior classes to apply. Different paths but doesn't seem super dissimilar end result. I feel like web-directive giving a simple callback leaves a lot to the developer, where-as element-behaviors API surface tries to parallel WebComponents, which is familiar & has lots of nice understandable lifecycle builtin.
# ASCII RPG
This repo uses Rust + Bevy (0.16.1), multi-crate workspace, RON assets, and a custom ASCII UI. The rules below keep contributions consistent, testable, and verifiable.
## Quick rules (read me first)
- Read/update CURRENT_TASK.md each step; delete when done.
- Build/lint/test (fish): cargo check --workspace; and cargo clippy --workspace --all-targets -- -D warnings; and cargo test --workspace
- Run dev tools: asset-editor/dev.fish; debug via /tmp/ascii_rpg_debug; prefer debug scripts in repo root.
- Logging: use info!/debug!/warn!/error! (no println!); avoid per-frame logs unless trace!.
- ECS: prefer components over resource maps; use markers + Changed<T>; keep resources for config/assets only.
- UI: adaptive content; builder pattern; size-aware components.
- Done = compiles clean (clippy -D warnings), tests pass, verified in-app, no TODOs/hacks.
- If blocked: state why and propose the next viable step.
- Before large refactors/features: give 2–3 options and trade-offs; confirm direction before coding.
## 1) Build, lint, test (quality gates)
- Fish shell one-liner:
- cargo check --workspace; and cargo clippy --workspace --all-targets -- -D warnings; and cargo test --workspace
- Fix all warnings. Use snake_case for functions/files, PascalCase for types.
- Prefer inline rustdoc (///) and unit tests over standalone docs.
## 2) Run and debug (dev loop)
- Start the app with debug flags and use the command pipe at /tmp/ascii_rpg_debug.
- Quick start (fish):
- cargo run --bin app -- --skip-main-menu > debug.log 2>&1 &
- echo "debug viewport 0 0" > /tmp/ascii_rpg_debug
- echo "ui 30 15" > /tmp/ascii_rpg_debug
- Helper scripts at repo root:
- ./debug.sh, ./debug_keyboard.sh, ./debug_click.sh, ./debug_world.sh
- Logging rules:
- Use info!/debug!/warn!/error! (never println!).
- Don’t log per-frame unless trace!.
- Use tail/grep to keep logs readable.
## 3) Testing priorities
1) Unit tests first (small, deterministic outputs).
2) Manual testing while iterating.
3) End-to-end verification using the debug system.
4) UI changes require visual confirmation from the user.
## 4) Architecture guardrails
- ECS: Components (data), Systems (logic), Resources (global), Events (comm).
- Principles:
- Prefer components over resource maps. Avoid HashMap<Entity, _> in resources.
- Optimize queries: marker components (e.g., IsOnCurrentMap), Changed<T>.
- Separate concerns: tagging vs rendering vs gameplay.
- Resources only for config/assets; not entity collections/relationships.
- UI: Adaptive content, builder pattern, size-aware components.
- Code layout: lib/ui (components/builders), engine/src/frontend (UI systems), engine/src/backend (game logic).
## 5) Completion criteria (definition of done)
- All crates compile with no warnings (clippy -D warnings).
- All tests pass. Add/adjust tests when behavior changes.
- Feature is verified in the running app (use debug tools/logs).
- No temporary workarounds or TODOs left in production paths.
- Code follows project standards above.
## 6) Never-give-up policy
- Don’t mark complete with failing builds/tests or known issues.
- Don’t swap in placeholder hacks and call it “done”.
- If truly blocked, state why and propose a viable next step.
## 7) Debug commands (reference)
- Pipe to /tmp/ascii_rpg_debug:
- debug [viewport X Y] [full]
- move KEYCODE (Arrow keys, Numpad1–9, Space, Period)
- click X Y [left|right|middle]
- ui X Y
- Coordinates: y=0 at bottom; higher y = higher on screen.
- UI debug output lists text top-to-bottom by visual position.
## 8) Dev convenience (asset editor)
- Combined dev script:
- ./asset-editor/dev.fish (starts backend in watch mode + Vite dev)
- Frontend only:
- ./asset-editor/start-frontend.fish
## 9) Tech snapshot
- Rust nightly (rust-toolchain.toml), Bevy 0.16.1.
- Workspace layout: apps/ (game + editors), engine/ (frontend/backend), lib/ (shared), asset-editor/.
Keep changes small, tested, and instrumented. When in doubt: write a unit test, run the app, and verify via the debug pipe/logs.
## 10) Design-first for large changes
- When to do this: large refactors, cross-crate changes, complex features, public API changes.
- Deliverable (in CURRENT_TASK.md):
- Problem and goals (constraints, assumptions).
- 2–3 candidate approaches with pros/cons, risks, and impact.
- Chosen approach and why; edge cases; test plan; rollout/rollback.
- Keep it short (5–10 bullets). Get confirmation before heavy edits.
Programmers are mostly translating business rules to the very formal process execution of the computer world. And you need to both knows what the rules means and how the computer works (or at least how the abstracted version you’re working with works). The translation is messy at first, which is why you need to revise it again and again. Especially when later rules comes challenging all the assumptions you’ve made or even contradicting themselves.
Even translations between human languages (which allows for ambiguity) can be messy. Imagine if the target language is for a system that will exactly do as told unless someone has qualified those actions as bad.
I have multiple system prompts that I use before getting to the actual specification.
1. I use the Socratic Coder[1] system prompt to have a back and forth conversation about the idea, which helps me hone the idea and improve it. This conversation forces me to think about several aspects of the idea and how to implement it.
2. I use the Brainstorm Specification[2] user prompt to turn that conversation into a specification.
3. I use the Brainstorm Critique[3] user prompt to critique that specification and find flaws in it which I might have missed.
4. I use a modified version of the Brainstorm Specification user prompt to refine the specification based on the critique and have a final version of the document, which I can either use on my own or feed to something like Claude Code for context.
Doing those things improved the quality of the code and work spit out by the LLMs I use by a significant amount, but more importantly, it helped me write much better code on my own because I know have something to guide me, while before I used to go blind.
As a bonus, it also helped me decide if an idea was worth it or not; there are times I'm talking with the LLM and it asks me questions I don't feel like answering, which tells me I'm probably not into that idea as much as I initially thought, it was just my ADHD hyper focusing on something.
Some years ago tried Caesar salad many
times and settled on the recipe below.
The Caesar dressing is in the family of
oil and vinegar mixtures with flavorings
and emulsifiers.
The salad also has croutons (pieces of
toast flavored with some of the dressing)
and grated hard, dry cheese, Parmesan or
Pecorino Romano (and I prefer the second).
The lettuce is Romaine. If separate the
leaves, rinse them, shake dry, wrap in
some clean kitchen towels, refrigerate for
several hours, then the lettuce usually
will be crisp, which is desirable. Just
before combining all the ingredients to
make the actual salad, tear the leaves
into irregular pieces.
For the egg, boil it the 10 seconds not to
cook the egg but to sterilize the
outside before cracking the egg.
=====
Note:
This oil/vinegar mixture has close to the
usual (by volume) 3 parts of the oil to 1
part of vinegar. For a brighter flavor,
might use more vinegar, maybe as high as a
ratio of 3 to 2.
And the other measurements here are also
subject to change.
One issue is, some of the ingredients,
e.g., basil, oregano, parsley, fresh
versus dried, can vary in flavor by a lot.
Some garlic is mild and some very strong.
And the flavors of the red wine vinegar
and olive oil vary.
So, the results tend to vary, between two
cooks a lot and even between two trials by
one cook.
So for each trial, it's good to have good
notes on what did so that can repeat the
trial if it was good or adjust the trial
if it was not.
So, the notes here are from some trials
that seemed good but are subject to
adjustment.
=====
Abbreviations (common in the US)
T -- tablespoon
t -- teaspoon
C -- cup
=====
Good to have three bowls, 1 quart plastic
or stainless, 5 quart stainless, ~3 quart
wooden.
The wooden bowl is for style and the
serving, and the large volume of the 5
quart bowl is to ease tossing the
croutons and lettuce to coat them with the
Caesar dressing.
=====
Caesar Dressing.
In a one quart bowl, combine
1 egg boiled 10 seconds
1 T Worcestershire sauce
2/3 C red wine vinegar (what you pay
for wine vinegar can vary
significantly)
1 1/2 T finely minced garlic
3 T Dijon mustard (what you pay for
the mustard can vary significantly)
1/2 T basil (fresh or dried)
1/2 T oregano (fresh or dried)
2 T parsley (fresh or dried)
1/2 t salt
1/2 t freshly ground black pepper
One 2 ounce can flat anchovies packed
in oil, minced, with the oil
2 C olive oil (what you pay for olive
oil can vary significantly)
Combine all but the olive oil. Whip to
start the emulsification of the oil and
vinegar with the egg and mustard
emulsifiers.
Add olive oil slowly with whipping. Seek
good emulsification of the oil with the
vinegar and the rest.
Makes about 3 C.
=====
Grated Cheese.
Grate some solid Parmesan or Pecorino
Romano hard, dry cheese to yield ~1 C of
grated cheese.
=====
Toast for Croutons.
Toast four slices of bread (might use some
bread other than US lunch box white
bread). Stack the four slices and cut in
two parallel cuts, rotate 90 degrees and
repeat so cut each slice of toast into 9
pieces.
=====
Dress the Lettuce.
In 5 quart stainless steel bowl, tear
three Romaine hearts into irregular
pieces.
Add 3/4 C of the dressing (right, will
have plenty of dressing left over for more
salads).
Toss.
Goal is to flavor the lettuce with the
dressing but still keep the lettuce crisp,
not wet or 'soggy'; so try to use the
least dressing for the needed flavor.
Notes:
A nice way to present and serve is with a
stylish wooden salad bowl full of the
salad with croutons and grated cheese on
top.
Thus the stylish wooden bowl is too small
for tossing; use the 5 quart bowl for
tossing and the wooden bowl for presenting
and serving.
For the serving, might also use some
stylish wooden salad tongs or fork and
spoon.
=====
Toss Croutons.
Add the cut toast to the 5 quart bowl and
toss with some of the salad dressing.
Goal is just to flavor the toast but keep
it crisp, not soft or soaked.
Add the toast on top of the dressed
lettuce in the wooden salad bowl.
=====
Sprinkle the grated cheese over the toast.
=====
Serve.
=====
With the egg, bread, cheese, and oil, it's
filling.
It's open source, fully Mac native, no Electron, fast, and small. I use it almost every hour of every day.