Skip to content

feat(arena): Season 0 Worldsmith Trials submission scaffold + entry validator#80

Draft
frankxai wants to merge 4 commits into
mainfrom
claude/arcanea-crowd-machine-qd4f85
Draft

feat(arena): Season 0 Worldsmith Trials submission scaffold + entry validator#80
frankxai wants to merge 4 commits into
mainfrom
claude/arcanea-crowd-machine-qd4f85

Conversation

@frankxai

@frankxai frankxai commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the public submission surface for Arcanea Arena — Season 0: The Worldsmith Trials: contributors enter the competition by PRing a Claude Code skill (an agentic world-creation workflow) + manifest + sample world into challenges/season-0/entries/, validated automatically by a zero-dependency script wired to a GitHub Action. Companion to frankxai/arcanea-ai-app#185 (strategy, spec, rubric, ledger, judge pipeline).

Changes

  • challenges/season-0/README.md — season front door: what to submit, how to enter, canon constraints, prize (recognition + plugin distribution; no invented figures)
  • challenges/season-0/entry-template/ — copyable entry skeleton (SKILL.md, entry.json manifest with license-acceptance field, world/ five-layer stubs)
  • challenges/season-0/entries/ — intake directory (one dir per entry, <handle>--<skill-name>)
  • challenges/season-0/scripts/validate_entry.py — validates directory naming/author match, SKILL.md frontmatter rules, manifest schema, world files, plus an injection lint for judge-manipulation attempts
  • .github/workflows/validate-entries.yml — runs the validator on changed entries in PRs (contents: read only)

Type

  • Feature (new functionality)

Checklist

  • Validator verified locally: passes a well-formed fixture entry, fails a broken fixture with 5 specific errors (bad license, handle mismatch, injection attempt)
  • No lore changes — competition scaffold only; canon constraints reference CANON_LOCKED.md
  • No new any types (no TypeScript in this change)
  • No TypeScript build impact (pnpm build untouched by these paths)

🤖 Generated with Claude Code

https://claude.ai/code/session_01A62YAfcPvfLzYn163Mu7dN


Generated by Claude Code

…alidator

Adds challenges/season-0/ (rules pointer README, entry-template with
SKILL.md + entry.json manifest + world/ layer stubs, entries/ intake
dir) and a zero-dependency validator (structure, manifest schema,
license acceptance, injection lint) wired to a GitHub Action that
runs on entry PRs. Companion to arcanea-ai-app#185 (Arena strategy,
spec, ledger, judge pipeline).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A62YAfcPvfLzYn163Mu7dN
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
arcanea-2 Error Error Jul 2, 2026 11:49pm
arcanea-web Ready Ready Preview, Comment, Open in v0 Jul 2, 2026 11:49pm

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 34aa796c-7654-4f39-bb8e-93c63800a66c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/arcanea-crowd-machine-qd4f85

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request sets up the infrastructure for Arcanea Arena Season 0, adding a README, an entry template with placeholder world files, and a Python validation script to enforce submission constraints and check for prompt injections. The review feedback suggests enhancing the validation script's robustness by defensively handling malformed JSON structures to prevent crashes and using utf-8-sig encoding to safely strip UTF-8 Byte Order Marks (BOM) during file parsing.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread challenges/season-0/scripts/validate_entry.py Outdated
Comment thread challenges/season-0/scripts/validate_entry.py Outdated
…pes, BOM-safe reads

entrant/skill non-dict values no longer crash validation (reported as
errors instead); all read_text calls use utf-8-sig so Windows BOMs
don't break frontmatter parsing. Fixtures re-verified: template-derived
entry passes, sabotaged entry fails with specific errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A62YAfcPvfLzYn163Mu7dN

frankxai commented Jul 2, 2026

Copy link
Copy Markdown
Owner Author

Review + CI status:

  • Gemini review comments: both addressed in d1ec40f — defensive isinstance checks so malformed entry.json structures (non-dict entrant/skill) report as validation errors instead of crashing the CI script, and utf-8-sig on all file reads so Windows BOMs don't break frontmatter parsing. Fixtures re-verified: template-derived entry passes, sabotaged entry fails with 5 specific errors.
  • CLI Tests (22) / Test Summary: pre-existing, not from this PR. This change adds only markdown, a standalone Python validator, and one workflow — no package code. The failing suite (packages-ci.yml, 175 test failures in the CLI packages) has failed on every main push since at least February 2026 (runs 62–70 all failure).
  • Vercel arcanea-2 error: that project's root is apps/academy, untouched here; arcanea-web deploys this branch fine.

Companion PR with the strategy/spec/rubric/ledger/judge pipeline: frankxai/arcanea-ai-app#185.


Generated by Claude Code

@claude

claude Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review: Season 0 Worldsmith Trials submission scaffold

Reviewed .github/workflows/validate-entries.yml, challenges/season-0/scripts/validate_entry.py, and the template/README files.

Critical: the validation Action silently no-ops instead of validating entries

In .github/workflows/validate-entries.yml, the "Find changed entry directories" step only runs:

git fetch --no-tags --depth=1 origin "BASE_SHA"

and then feeds "git diff --name-only BASE_SHA HEAD_SHA -- challenges/season-0/entries/" through awk and sort -u, capturing the result into a shell variable "dirs".

Two compounding issues:

  1. Only BASE_SHA is fetched, not HEAD_SHA. actions/checkout@v4 with default settings checks out the synthetic PR merge ref (refs/pull/n/merge) at depth 1. That's a different commit object than either base.sha or head.sha, and at depth 1 neither parent is fetched. So the git diff call above fails with something like "fatal: bad object HEAD_SHA" -- the head commit object was never fetched.
  2. Nothing protects against that failure. The default shell here (bash -e, since no shell: key is set) only fails the step if the last command in a pipeline fails, and pipefail is not set. git diff piped into awk piped into sort -u -- sort -u still exits 0 even though git diff failed and wrote nothing to stdout. So the "dirs" variable ends up empty, the step "succeeds," and the next step iterates over zero directories, so the overall exit status stays 0 and the job reports green.

Net effect: the workflow currently validates nothing, ever, and reports success regardless of what's in the submitted entry -- including the injection-lint check that's supposed to catch judge-manipulation attempts. Since this is the actual gate for community PRs into challenges/season-0/entries/, this needs a fix before entries start flowing in. Two changes needed: (a) fetch both BASE_SHA and HEAD_SHA in the git fetch call, not just BASE_SHA, and (b) add "set -euo pipefail" at the top of the run block so any future failure here fails the job loudly instead of silently passing.

Security posture (good)

  • permissions: contents: read only, and the pull_request trigger (not pull_request_target) -- correct choice, keeps this safe to run against fork PRs without secret exposure.
  • PR_AUTHOR and DIRS are passed via env: rather than interpolated directly into the run: script -- avoids the classic GitHub Actions script-injection footgun (untrusted github.event.pull_request.user.login / step output landing straight in a shell string).
  • The injection lint in validate_entry.py (judge-manipulation patterns) is a nice piece of defense-in-depth for the downstream automated judging pipeline mentioned in the companion PR.

Minor/optional: actions/checkout@v4 is pinned to a floating tag rather than a commit SHA. Given the read-only permissions here the blast radius is small, but worth being consistent if other workflows in this repo pin third-party actions to SHAs.

validate_entry.py

Overall clean, zero-dependency, and readable. A couple of minor notes, none blocking:

  • The DIR_RE pattern's handle group (a character class of letters, digits and hyphens, one or more) can itself greedily consume embedded double-hyphen sequences -- e.g. a hypothetical "a--b--my-skill" parses as handle "a--b", skill "my-skill". GitHub usernames can't contain consecutive hyphens, so this shouldn't be reachable in practice, but a tighter pattern would match GitHub's actual handle rules more precisely.
  • parse_frontmatter's key/value parsing is intentionally minimal ("YAML-ish"), which is fine for a first-party template with known keys, but worth a comment noting it's not a general YAML parser if this ever gets reused elsewhere.

Test coverage

The PR description says the validator was "verified locally" against fixture entries, but no fixtures or automated test (e.g. a tests/ dir with a pytest or a plain assert-based script) are committed. Since this script is the actual gate for community submissions, I'd suggest committing the pass/fail fixtures used for that manual verification (including the injection-attempt case) as a small regression test. An end-to-end test that exercises the Action's shell logic (not just the Python script in isolation) would also have caught the fetch/pipefail issue above.

Nit

.github/workflows/validate-entries.yml's comment about deleted entries needing no validation, attached to the directory-existence check, is also silently true for the .gitkeep placeholder path, since awk treats it as a pseudo-entry-dir (challenges/season-0/entries/.gitkeep has the same path depth as a real entry dir). Harmless since it's skipped by the directory check, but the comment doesn't quite describe why it's being skipped in that case.


Everything else (README, entry-template, .gitkeep) looks straightforward and matches the stated scope -- no lore/canon changes, no TS/build impact. The workflow fetch bug is the one thing I'd want fixed before this gate starts being relied on for real submissions.

🤖 Generated with Claude Code

…tests

Per review: the Action fetched only BASE_SHA, so git diff against the
unfetched HEAD_SHA failed — and without pipefail that failure was
swallowed, leaving dirs empty and the gate green while validating
nothing. Now fetches both endpoints and runs every step under
set -euo pipefail so a broken diff fails loudly.

Also adds test_validate_entry.py (5 scenarios built from the committed
entry-template: valid pass, BOM pass, sabotage fail, author mismatch,
double-hyphen dir rejection) wired as the workflow's first step, plus
the tighter GitHub-handle regex and a not-general-YAML warning comment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A62YAfcPvfLzYn163Mu7dN

frankxai commented Jul 2, 2026

Copy link
Copy Markdown
Owner Author

The critical finding was confirmed and is fixed in 954fbb2: the Action fetched only BASE_SHA, so the diff against the unfetched HEAD_SHA failed and — without pipefail — was swallowed, leaving the gate green while validating nothing. The workflow now fetches both endpoints and runs under set -euo pipefail (verified locally: a bad-object diff now fails the step loudly).

Also landed from the review: test_validate_entry.py (5 scenarios built from the committed entry-template — valid pass, BOM pass, sabotaged fail incl. injection, author mismatch, embedded double-hyphen rejection) wired as the workflow's first step, the tighter GitHub-handle regex, the not-a-general-YAML-parser warning, and a corrected comment on the .gitkeep/deleted-path skip. SHA-pinning the action is left as-is for consistency with this repo's other workflows (all use @v4 tags).


Generated by Claude Code

Running challenges/season-0/scripts/test_validate_entry.py imports the
validator and leaves bytecode caches behind; keep them out of entry PRs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A62YAfcPvfLzYn163Mu7dN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants