qwen-web-arwaky-dev
Skill0 starsChanged 26 days agoMITView on GitHub
Edit qwen-web-arwaky repo source (TUI, slots, tests). Not sending prompts.
- Deletes or force-pushes
- Installs packages
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 1 is distinctive, and 9 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 24
Run everything through uv run from the repo root: uv run pytest ..., uv run python -c "...".
- Very specific: line 27
Never conclude a library is missing (or present) from a bare python3 -c "import x" outside uv run — it only proves the host interpreter …
- Very specific: line 37
All XDG state lives under ~/.local/share|state|cache|config/qwen-web-arwaky (and AppData\Local/qwen-web-arwaky on Windows, via install.py).
- Very specific: line 52
Never stage them: git add -A after a test run re-tracks the stamp and it rides into unrelated commits/PRs.
- Very specific: line 56
Test files use prefix naming (unit_<module>_<subject>.py, integration_<module>.py, contract_*.py, smoke_*.py) and live in TWO places: at …
- Very specific: line 110
Run la scan (or lint-arwaky-cli scan) from the repo root after edits.
- Very specific: line 129
Add an abstract protocol IXxxProtocol(ABC) to modules/shared/src/contract_core_protocol.py with the method(s) you will move.
- Very specific: line 132
Create modules/core/src/capabilities_xxx.py with a class XxxResolver(IXxxProtocol) implementing those methods.
- Very specific: line 144
Verify extraction did not change behaviour: uv run pytest tests/ -m "not e2e and not slow".
- Distinctive: line 231
When the user supplies an attachment, the output filename must be derived from the attachment's stem, not the prompt's stem.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Developing qwen-web-arwaky
Repo: ~/agents-arwaky/internal/qwen-web-arwaky — AES layered layout
(modules/<layer>/src/...), flat tests at repo root. Scope: editing this
repo's source. For using the finished tool (MCP prompt processing, session
login) see the qwen-web skill instead.
Environment
- Run everything through
uv runfrom the repo root:uv run pytest ...,uv run python -c "...". The project venv is Python 3.13; the hostpython3is a different interpreter with none of the project deps. - Never conclude a library is missing (or present) from a bare
python3 -c "import x"outsideuv run— it only proves the host interpreter lacks it. The same applies topodman exec <container> python3 -c ...: that is a separate image, not the dev env. pytestis a dev dep a freshly-created.venvmay lack, souv run pytestfails withFailed to spawn: pytest. Fix:uv add --dev pytest.
State directories (standardized on qwen-web-arwaky, PR #560)
LOCAL_WS_DIR = ".qwen-web-arwaky"lives inmodules/shared/src/taxonomy_core_constant— the single policy value for the per-project workspace mirror.qwa initcreates.qwen-web-arwaky/with five XDG symlinks (jobs, log, output, qwen_session, swarm) and migrates a legacy.qwen-web/dot-dir (symlink → unlink, real dir → rename.qwen-web-arwaky.legacy). Never hardcode.qwen-webin code again — readLOCAL_WS_DIR.- All XDG state lives under
~/.local/share|state|cache|config/qwen-web-arwaky(andAppData\Local/qwen-web-arwakyon Windows, viainstall.py). The oldqwen-webtrees under~/.local/shareand~/.local/statewere deleted during the migration; do not reference them. - AES pitfall hit in this work: a public constant in a
capabilities_*module gets flagged bylint-arwaky-cli(AES403 CAPABILITY_ROLE — move totaxonomy_<domain>_constant.py) and cross-capability imports of it get flagged AES201 FORBIDDEN_IMPORT. Put shared policy constants in the taxonomy layer from the start.
Verification loop after any source edit
- Syntax gate:
uv run python -m py_compile <each changed file>. - Targeted tests for the touched module (
uv run pytest tests/unit_<stem>.py). - Full gate:
uv run pytest tests/ -m "not e2e and not slow" -x -q(e2e/slowmarkers are declared inpytest.ini; e2e needs live network plus a logged-in Qwen session).
Run-generated stamp. pytest rewrites tests/fixtures/.last_run_ts and
modules/prompt/tests/fixtures/.last_run_ts on every run (guard for
tests/pipeline_fixtures.py::restore_fixture_state). Both are intentionally
untracked — .gitignore covers them via **/tests/fixtures/.last_run_ts.
Never stage them: git add -A after a test run re-tracks the stamp and it
rides into unrelated commits/PRs. Stage specific files, and don't be fooled
when a test run leaves them ?? or modified.
Test files use prefix naming (unit_<module>_<subject>.py,
integration_<module>.py, contract_*.py, smoke_*.py) and live in TWO
places: at repo root (tests/) and under modules/<layer>/tests/ (e.g.
modules/cli/tests/unit_surface_cli_tui_app.py). Find the right file with
ls tests/ modules/*/tests/ 2>/dev/null | grep <stem> before assuming either
layout.
Verifying in the Podman container
The runtime truth lives in the qwen-web-arwaky Podman container (image built
from Containerfile). scripts/podman.sh wraps it: start, stop, status,
shell, run [args...], test, lint, build, login, doctor, prompt.
buildrecreates the container.podman buildmakes a NEW image but the OLD container keeps the OLD image —podman startnever re-points it. So after editing source, a barebuildleftpodman.sh run/teston stale code (host file said 5, container reported 2).scripts/podman.sh buildtherefore callsrecreate_container(rm -f old, then start) — keep that behaviour if you edit the script. Symptom check:podman inspect <c> --format '{{.Created}}'OLDER thanpodman inspect localhost/qwen-web-arwaky:latest --format '{{.Created}}'= stale container.- Login survives rebuilds. Auth lives in a host volume
(
/home/raka/.local/share/containers/storage/volumes/qwen-web-arwaky/_data/share/qwen_session), mounted to/root/.local/share/qwen-web/qwen_session(=DEFAULT_SESSION).podman rm -f <container>deletes only the container; the volume and Qwen session persist. Never warn that a rebuild loses login — it does not. tests/is NOT in the image.Containerfileends withpip install . && rm -rf /build, soscripts/podman.sh testfails withfile or directory not found: tests/. Run them via one of:- copy in (container already up):
podman cp tests <c>:/root/tests && podman cp pytest.ini <c>:/root/pytest.ini && podman exec <c> bash -c "cd /root && pytest tests/ -m 'not e2e and not slow' -q" - bind-mount a throwaway container, overriding the
qwaENTRYPOINT (elsepodman run ... qwa pytest→invalid choice: 'pytest'):podman run --rm --net=host --entrypoint pytest -v $PWD:/work:Z -w /work qwen-web-arwaky tests/ -m 'not e2e and not slow' -q
- copy in (container already up):
- Root-bypasses-chmod pitfall. The container runs as uid 0, so a test that
chmod 0o000a file and expects a read failure will not fail (root ignores DAC). Guard it:if os.getuid() == 0: pytest.skip("root bypasses filesystem permission checks"). That is a test-env artifact, not a production bug — do not chase the code under test.
git status --short then git diff first — a previous session's edits are
usually already on disk uncommitted, so the job is completing them, not
redoing them.
Then verify completeness, not just that it compiles. An interrupted UI
change reliably lands the widget + CSS + import but not the event handler, so
the control renders and silently does nothing. For every new widget the diff
adds, grep for its handler/consumer (on_select_changed, on_button_pressed,
@on(, and the widget's id string) and confirm a branch actually matches
that id before calling the feature done.
AES architecture compliance (lint-arwaky gate)
Run la scan (or lint-arwaky-cli scan) from the repo root after edits. The
repo enforces AES layer boundaries; the violations that bite during UI work:
- AES406 SURFACE_ROLE — a
surface_*file exceeds 50 control-flow statements (counted by the linter, not by naivegrep— your line counter will disagree). Fix by extracting the heavy logic into a capability class, never by shrinking variable names._run_slot+_dispatch_batchare the usual culprits insurface_cli_tui_app.py. - AES403 CAPABILITY_ROLE — a
capabilities_*file has no class that inherits from a parent protocol. The file must define at least one class extending anI*Protocolfromcontract_core_protocol.py. - AES202 MANDATORY_IMPORT — a
capabilities_*file does not import its protocol.from modules.shared.src.contract_core_protocol import IXxxProtocolis mandatory for that layer. - AES203 UNUSED_IMPORT — remove unused imports; the linter fails the build gate on them.
Extraction recipe (when AES406 fires on a surface):
- Add an abstract protocol
IXxxProtocol(ABC)tomodules/shared/src/contract_core_protocol.pywith the method(s) you will move; append its name to that file's__all__. - Create
modules/core/src/capabilities_xxx.pywith a classXxxResolver(IXxxProtocol)implementing those methods. Return domain results as frozen@dataclassvalue objects (e.g.SlotRunPlan/SlotInputError) rather than raising — the surface only forwards an error message. Import the protocol (AES202) and ensure a class inherits it (AES403). - In the surface, instantiate the resolver once in
__init__(self._slot_config = XxxResolver()) and callself._slot_config.<method>(...), handling aSlotInputError(or similar) return by logging. The surface keeps only widget I/O + delegation. - Re-scan until Total: 0 violations. The user expects all violations cleared (including ones predating your edits), not just the ones you added.
Verify extraction did not change behaviour: uv run pytest tests/ -m "not e2e
and not slow"; the moved logic is pure, so unit-test the capability method
directly with uv run python -c + Path(tempfile.mkdtemp()).
Textual TUI conventions (modules/cli/src/surface_cli_tui_app.py)
- Slot count is derived, not declared per place:
NUM_SLOTS = max(2, int(DEFAULT_MAX_WORKERS)), withDEFAULT_MAX_WORKERSinmodules/shared/src/taxonomy_common_constant.py. Changing that one constant scales tabs, keybindings and the worker pool — never hardcode a slot count or write per-slotaction_*methods. Emit bindings from a comprehension and funnel the actions through one_switch_to_slot(n). Selectwiring: handler isdef on_select_changed(self, event: Select.Changed); dispatch onevent.select.id(parse the slot number from the id suffix), readevent.value, and guard forNone(returned whenallow_blank=Trueand the user clears it). Cross-fill a sibling field withself.query_one(f"#input-...-{slot}", Input).value = ....- Prompt-template dropdown options come from
PROMPT_TEMPLATE_MANIFEST(role ->{title, dimensions}). The dropdown only needs to write the role string into the prompt Input:_run_slotalready branches onis_prompt_role(value)->materialize_role_template(role), so a role name and a file path share one field. Do not materialize template content in the UI layer. - Prompt-template display policy: dropdown label = role title ONLY
(
meta['title']). Do NOT concatenatetitle — dimensionsas the Select option label: that bloats the list with long wrapped lines the user did not ask for. Options are one line each:Architect,Backend,Frontend,Business Analyst. Dimensions stay as metadata context for Qwen's review, not as dropdown chrome.
Output-path policy: timestamp always present
resolve_pipeline_output_path() in
modules/core/src/utility_core_config_factory.py is the single source of
truth for output naming — used by the orchestrators and every surface (CLI,
MCP, TUI). Policy (current, user-driven): timestamp is always appended to
the output filename, in all cases:
- no
output_file→DEFAULT_OUTPUT/{prompt_stem}_{YYYYmmdd-HHMMSS}.md output_fileis a directory →{dir}/{prompt_stem}_{ts}.mdoutput_fileexists →{parent}/{stem}_{ts}{suffix}(never overwrite)output_filedoes not yet exist → still{parent}/{stem}_{ts}{suffix}
Rule: when the user says "timestamp must always appear", edit
resolve_pipeline_output_path, not the TUI _run_slot override logic.
The TUI should hand the raw user path into the orchestrator and let the
central function apply the policy — duplicating the rule in two layers is the
bug, not the fix. Verify the four cases by invoking the function directly with
uv run python -c + a temp dir (Path(tempfile.mkdtemp())); do not trust the
TUI code path to prove the policy.
Attachment workflow: host paths need a mount, not a lecture
Container filesystem is isolated from the host. A host absolute path typed into
the TUI (e.g. /home/raka/.../.agents/finding/cli_v5.2.2.md) fails inside the
container UNLESS that host path is bind-mounted. scripts/podman.sh declares
mounts in the VOLUMES variable; check it first before telling the user
their path is unreachable. Recurring attachment hotspot: user keeps finding
files at
/home/raka/agents-arwaky/internal/qwen-web-arwaky/.agents/finding/;
when that folder appears, add a VOLUME line to podman.sh:
VOLUMES="... \
-v "\${REPO_ROOT}/.agents/finding:/root/.local/share/qwen-web/finding:Z""
```text
so the folder appears inside the container at
`/root/.local/share/qwen-web/finding/` and the TUI file picker can browse it.
**Never hardcode an absolute host path in a VOLUME line.** `scripts/podman.sh`
already computes `REPO_ROOT` from the script's own location
(`SCRIPT_DIR` → parent). Any mount that points at the repo or a subfolder of
it must use `${REPO_ROOT}/<relative-path>`. A hardcoded `/home/raka/...`
absolute path is both a review nitpick and will silently break the moment the
repo is relocated or a different user clones it. The same rule applies to any
other host path you add as a mount — prefer a variable over a literal when one
is available.
Pattern: when a user names an absolute host path as their attachment spot, add
it as a VOLUME; the answer to "my path doesn't work in container" is not
"impossible" but "that path isn't mounted yet — add it."
### Attachment-stem preference
When the user supplies an attachment, the output filename must be derived from
the **attachment's stem**, not the prompt's stem. When there is no attachment,
fall back to the prompt's stem. In both cases the timestamp is still appended.
Encode this by plumbing `attachment_path` through
`resolve_pipeline_output_path` (the central function, not a TUI override) —
duplicating the attachment-vs-prompt decision in the TUI is the bug, not the
fix. Verify with `uv run python -c` + `Path(tempfile.mkdtemp())` that the
function returns the attachment stem when `attachment_path` is given.In this repository172 other files it gives its agents.
- AGENTS.mdAGENTS.md
- aes-agentSkill
- aes-capabilitiesSkill
- aes-contractSkill
- aes-docsSkill
- aes-lint-arwakySkill
- aes-migrationSkill
- aes-rootSkill
- aes-surfaceSkill
- aes-taxonomySkill
- aes-testing-suiteSkill
- aes-utilitySkill
- build-with-aiSkill
- omni-model-inventorySkill
- omnirouteSkill
- xai-apiSkill
- android-emulator-linux-gpsSkill
- chromium-profile-provisioningSkill
- computer-useSkill
- flatpak-chromium-automationSkill
- qwen-webSkill
- cleanup-consolidateSkill
- codacy-analysis-cliSkill
- codacy-cloud-cliSkill
- codacy-code-reviewSkill
- codebase-inspectionSkill
- coderabbit-reviewSkill
- code-reviewSkill
- configure-codacy-cloudSkill
- configure-codacySkill
- fix-bypassSkill
- fix-markdown-inline-htmlSkill
- fixture-dir-pruningSkill
- harness-source-auditSkill
- no-mistakesSkill
- report-linter-false-positiveSkill
- reviewSkill
- setup-coverageSkill
- strict-code-quality-reviewSkill
- architecture-diagramSkill
- ascii-artSkill
- ascii-videoSkill
- baoyu-infographicSkill
- blender-arwakySkill
- claude-designSkill
- comfyuiSkill
- design-mdSkill
- excalidrawSkill
- game-assetsSkill
- gif-searchSkill
- imagineSkill
- manim-videoSkill
- p5jsSkill
- popular-web-designsSkill
- pretextSkill
- psd-overlay-verificationSkill
- psd-timelapse-workflowSkill
- sketchSkill
- songseeSkill
- songwriting-and-ai-musicSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

