Portable challenge packages for MLH microhackathons. Challenge packages live
under challenges/; each one runs on boothstrap.sh stations and with
boothstrap dev. The repo is plain JavaScript (.mjs) on Node 26, and
every PR is checked by the same package validator stations run.
- Freely reversible: just do it. Edits, local commands, scratch files, branches.
- Consequential: state intent, then proceed. Pushing a branch, opening a PR, adding a dependency.
- Irreversible: always confirm first. Force-pushes, deleting branches or data, anything posted outside the repo.
- Propose, then confirm. For design choices, present 2–3 options with a recommendation before writing code.
- Action over asking. Exhaust reversible options (read the code, run a small experiment) before asking.
- Simple over clever. Question whether a concept needs to exist before adding one.
- Concise over verbose. Lead with the point; cut preamble.
- Ask one question at a time.
- Follow existing patterns in the file you're touching.
- Use conventional commits (
feat:,fix:,docs:,chore:). - Before claiming work is done, run
npm run verify,npm test, andnpm run lintand show the output. - Keep
docs/current: read the relevant doc before changing architecture, and update it in the same PR.
- Each directory under
challenges/holding achallenge.jsonis one package, named after itsid; grouping folders such aschallenges/beginner/<id>are allowed. Event configs listchallenges/<id>(or the nested path). Achallenge.jsonat the repo root, directly inchallenges/, or in another top-level directory fails verify. No two packages share an id. - The contract is boothstrap.sh's
docs/specs/2026-09-26-mvp-challenge-spec.md, withdocs/authoring-challenges.mdfor the workflow. The spec wins over this repo's docs. boothstrap.sh is internal: in a cloud session, attachMLH/boothstrap.shread-only to read them. - Each package's standalone Pi run must keep working, so check a change against the authoring guide's standalone flow.
- A package's dependencies install through its own
installhook, never at the repo root. The rootpackage.jsonhas one devDependency,@mlhacks/boothstrap, pinned exactly; bumping it is a one-line PR. - In-repo symlinks are followed: a symlinked directory under
challenges/holding achallenge.jsonis a package. A symlink at the repo root, inchallenges/, or in a grouping folder under it that is absolute, dangling, looping, or points outside the repo fails verify, as the station refuses it.npm run lintalso lints Markdown inside packages, so the house Markdown rules apply there. npm run verifyrunsboothstrap dev --verifyon every package. Add no rule the station doesn't enforce.- Test rules, including the network rule, are in docs/style/testing.md.
- Needs Node ≥ 26.4. In Claude Code cloud sessions, a SessionStart hook puts
/opt/node26/binfirst onPATH. Elsewhere, ifnode -vis older and/opt/node26/binexists, prefix everynode,npm, andnpxcommand withPATH="/opt/node26/bin:$PATH". Why: shell state, includingexport, may not persist between commands. - Run
npm ciwhennode_modulesis missing orpackage-lock.jsonchanged. npm run lintruns markdownlint throughnpx, so it needs the registry.npm run verifyandnpm testneed no credentials. Cloud setup:docs/cloud-agents.md.
- Open every PR as a draft from
.github/pull_request_template.md. Mark it ready yourself once every Ready gate row has evidence. If CI fails after that, convert it back to a draft, fix it, and mark it ready again. - The PR body carries no process narrative and no line-number citations.
- Every PR lands on
mainas one squash commit, through GitHub's merge only. Never push to or rewritemain. Update a branch by mergingmaininto it, since.claude/settings.jsondenies force-pushes; the squash keeps history linear.
challenges/<id>/: one challenge package per directory, with achallenge.jsonand its ownREADME.md.tools/: scripts run withnode;verify.mjsruns the validator over every package.test/:*.test.mjsfiles, run bynpm testthroughnode --test 'test/*.test.mjs'.test/<id>.test.mjscovers each challenge package's hooks, servers, and extensions;test/verify.test.mjscoverstools/verify.mjs.test/fixtures/holds fixture repos, whose Markdown is test data.docs/*.md: undated guides, one per feature or setup, indexed inREADME.md.docs/style/: how code, tests, and docs are written..claude/: Claude Code settings, the NodePATHhook, and theclaude-cloud-orchestrate-milestoneadapter skill..github/: the CI workflow and the PR template.
Load on demand, not at session start.
docs/style/development.md: code style. Read before changing source, tests, or docs, then the guide it names.docs/cloud-agents.md: cloud agent setup.README.md: human-facing overview and the index of challenges.