From 55a5353f345e24222b3bea8ed4149f90e31af6b2 Mon Sep 17 00:00:00 2001 From: Spbd1 <148923621+Spbd1@users.noreply.github.com> Date: Sun, 10 May 2026 09:02:02 +0000 Subject: [PATCH] Polish public release documentation --- .github/ISSUE_TEMPLATE/bug_report.md | 42 ++++ .github/ISSUE_TEMPLATE/feature_request.md | 30 +++ .github/ISSUE_TEMPLATE/research_question.md | 27 +++ .github/pull_request_template.md | 25 +++ CHANGELOG.md | 18 ++ CODE_OF_CONDUCT.md | 33 +++ CONTRIBUTING.md | 88 ++++++++ README.md | 214 +++++++++----------- docs/admin-guide.md | 77 ++++++- docs/analysis-plan.md | 6 +- docs/data-dictionary.md | 178 ++++++++-------- docs/ethics.md | 46 ++++- docs/game-mechanics.md | 69 +++++-- docs/images/.gitkeep | 0 docs/research-design.md | 86 ++++++-- 15 files changed, 677 insertions(+), 262 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/research_question.md create mode 100644 .github/pull_request_template.md create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 docs/images/.gitkeep diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..a9d16cc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,42 @@ +--- +name: Bug report +about: Report a reproducible problem in Parcel Society +title: "[Bug]: " +labels: bug +assignees: "" +--- + +## Summary + +Describe the bug clearly and briefly. + +## Steps to reproduce + +1. +2. +3. + +## Expected behavior + +What should have happened? + +## Actual behavior + +What happened instead? + +## Environment + +- OS: +- Browser: +- Node version: +- pnpm version: +- Docker version, if relevant: +- Commit SHA or release: + +## Logs or screenshots + +Paste relevant logs or add screenshots. Do not include credentials, private participant data, or unpublished study data. + +## Impact + +Does this affect local development, pilots, data exports, participant flow, deployment, or analysis? diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..5f92de3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,30 @@ +--- +name: Feature request +about: Propose a small, research-oriented improvement +title: "[Feature]: " +labels: enhancement +assignees: "" +--- + +## Summary + +Describe the requested change. + +## Motivation + +Why is this needed? If it changes participant experience, game mechanics, exports, or analysis, explain the research reason. + +## Proposed behavior + +What should the feature do? + +## Alternatives considered + +What simpler options or workarounds have you considered? + +## Scope and risks + +- Does this affect study design? +- Does this affect data exports? +- Does this affect privacy or ethics? +- Does this require documentation updates? diff --git a/.github/ISSUE_TEMPLATE/research_question.md b/.github/ISSUE_TEMPLATE/research_question.md new file mode 100644 index 0000000..eba38c1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/research_question.md @@ -0,0 +1,27 @@ +--- +name: Research question +about: Research discussion or design proposal +title: "[Research]: " +labels: research +assignees: "" +--- + +## Research question + +State the question or hypothesis. + +## Construct and measurement + +What concept should Parcel Society measure, and which in-app behavior or export field would represent it? + +## Design implications + +Does this require new mechanics, changed instructions, new randomization, or additional exports? + +## Analysis plan + +How would the outcome be analyzed? Note the unit of analysis and any clustering concerns. + +## Ethics and privacy + +Does the proposal change participant risk, consent language, data minimization, or disclosure risk? diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..9e753e7 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,25 @@ +## Summary + +- + +## Research/design impact + +- [ ] No participant-facing behavior changes +- [ ] No game-mechanics changes +- [ ] No export or analysis changes +- [ ] Documentation updated if needed + +Explain any checked exceptions or research implications: + +## Testing + +- [ ] `pnpm typecheck` +- [ ] `pnpm lint` +- [ ] `pnpm test` +- [ ] `pnpm build` +- [ ] Docker Compose checked, if relevant + +## Privacy and data safety + +- [ ] No credentials, private data, database dumps, or participant identifiers added +- [ ] Export/privacy implications reviewed, if relevant diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..1df64a5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +All notable changes to Parcel Society will be documented in this file. + +The format follows the spirit of [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project uses semantic versioning for public releases. + +## [0.1.0] - 2026-05-10 + +### Added + +- Initial public research-software release of Parcel Society. +- Next.js web app with participant and admin foundations. +- Prisma/PostgreSQL data model, seed scripts, and deterministic demo dataset. +- Engine package for maps, decisions, contracts, shocks, scoring, and round resolution. +- Research-safe CSV/ZIP export endpoints and data dictionary. +- Documentation for research design, mechanics, analysis, admin operations, deployment, and ethics. +- Docker Compose files for local and production-oriented starts. +- Contributor guide, Code of Conduct, issue templates, and pull request template. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..4cf8e27 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,33 @@ +# Code of Conduct + +## Our pledge + +We pledge to make participation in Parcel Society welcoming, respectful, and harassment-free for contributors and users regardless of background, identity, experience level, or research role. + +## Expected behavior + +- Be respectful and constructive. +- Assume good intent while being accountable for impact. +- Discuss research and technical tradeoffs with evidence and clarity. +- Keep criticism focused on ideas, code, documentation, and study design. +- Respect privacy and never share participant data, credentials, or private communications without permission. + +## Unacceptable behavior + +- Harassment, threats, insults, or discriminatory language. +- Sexualized language or unwelcome attention. +- Publishing private information without explicit permission. +- Sharing confidential research data or participant information. +- Repeated disruption of discussions or maintainers' decisions. + +## Enforcement + +Maintainers may remove comments, close issues, reject contributions, or restrict participation when behavior harms the community or the responsible use of the project. Enforcement should be proportionate, documented when appropriate, and focused on protecting contributors and research participants. + +## Reporting + +Report concerns privately to the project maintainers. Include links, screenshots, or context when safe to do so. Do not include sensitive participant data unless it is necessary and appropriate for the report. + +## Scope + +This Code of Conduct applies in project repositories, issue trackers, pull requests, discussions, and any community spaces associated with Parcel Society. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..2d63dc2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,88 @@ +# Contributing to Parcel Society + +Thank you for helping improve Parcel Society. Contributions should keep the project simple, stable, and research-oriented. + +## Set up locally + +```bash +corepack enable +pnpm install +cp .env.example .env +docker compose up -d postgres +pnpm db:generate +pnpm db:migrate +pnpm seed:demo +pnpm dev +``` + +Open for the app and for the admin area. + +## Branch naming + +Use short, descriptive branch names: + +- `docs/readme-release-polish` +- `fix/export-empty-contracts` +- `test/round-resolver-edge-cases` +- `chore/update-dependencies` + +Avoid vague names such as `changes`, `misc`, or `final`. + +## Coding style + +- Use TypeScript for application and package code. +- Keep mechanics deterministic where the research design requires reproducibility. +- Prefer small functions with explicit types at package boundaries. +- Do not add gameplay mechanics without a research-design justification. +- Keep participant-facing language clear and consistent. +- Never commit `.env`, database dumps, participant data, or private credentials. +- Run formatting before submitting broad Markdown or TypeScript edits. + +## Tests and checks + +Run these before opening a pull request: + +```bash +pnpm typecheck +pnpm lint +pnpm test +pnpm build +``` + +When changing database schema or seed behavior, also run: + +```bash +pnpm db:generate +pnpm db:migrate +pnpm seed:demo +``` + +When changing Docker or deployment files, test the relevant Compose file: + +```bash +docker compose up --build +docker compose -f docker-compose.prod.yml up --build +``` + +## Opening issues + +Use the GitHub issue templates when possible: + +- Bug reports should include reproduction steps, expected behavior, actual behavior, and logs or screenshots. +- Feature requests should explain the research or maintenance reason for the change. +- Research questions should state the construct, proposed measurement, and expected export fields. + +Please do not file issues containing private participant data, credentials, or unpublished study data. + +## Good first issues + +Good first contributions usually have low design risk: + +- Improve documentation clarity. +- Add tests for validation and engine edge cases. +- Improve accessibility labels and keyboard navigation. +- Add export consistency checks. +- Improve error messages without changing behavior. +- Add screenshots or diagrams to `docs/images/`. + +For larger changes, open an issue first so maintainers can discuss scope and research implications. diff --git a/README.md b/README.md index c7101e3..acd5984 100644 --- a/README.md +++ b/README.md @@ -1,182 +1,168 @@ # Parcel Society -Parcel Society is an open-source research software platform for reproducible online behavioral experiments. It is designed for studies in behavioral economics, political economy, social capital, and institutional trust. +Parcel Society is an open-source research platform for reproducible online behavioral experiments. It lets researchers run small virtual societies where participants make repeated decisions about production, investment, public goods, contracts, lobbying, and exit under controlled institutional and inequality conditions. -The first scientific version asks: **How do initial spatial inequality and institutional uncertainty affect cooperation, investment, public-good contribution, contract reliability, rent-seeking, and exit?** +The project is intentionally simple: it is research software, not an entertainment game, crypto project, social network, or full-featured survey platform. -## What Parcel Society Is +## Research motivation -- A minimal online behavioral-game platform for research -- A reproducible environment where participants join small virtual societies called servers -- A TypeScript monorepo foundation for a 10x10 parcel map, 7-round seasons, and 3 action points per player per round -- A project that prioritizes deterministic seeded randomness, clean data exports, Docker deployment, and research data quality +Many studies in behavioral economics, political economy, sociology, and institutional trust need environments where participants interact under transparent rules and where treatment assignment, decisions, and outcomes can be audited after the session. Parcel Society provides a lightweight TypeScript foundation for those studies. -## What Parcel Society Is Not +The initial research design asks: -Parcel Society is not a normal entertainment game and is not a crypto, NFT, or metaverse project. The MVP intentionally excludes crypto, real-money payout logic, chat, elections, political parties, AI agents, complex macro simulation, live multiplayer graphics, inter-server trade, social-network features, and public leaderboards. +> How do initial spatial inequality and institutional uncertainty affect cooperation, investment, public-good contribution, contract reliability, rent-seeking, and exit? -## Scientific Motivation +The core treatment design is a 2x2 experiment: -Researchers often need lightweight experimental environments where treatment assignment, participant decisions, and outcomes can be reproduced and audited. Parcel Society focuses on a simple 2x2 design: +| Inequality | Institutions | Description | +| ---------- | ------------ | ------------------------------------------------------------------------------ | +| Low | Stable | Similar initial parcel opportunities and predictable institutions. | +| Low | Uncertain | Similar initial parcel opportunities and controlled institutional uncertainty. | +| High | Stable | Unequal initial parcel opportunities and predictable institutions. | +| High | Uncertain | Unequal initial parcel opportunities and controlled institutional uncertainty. | -1. Low inequality + stable institutions -2. Low inequality + uncertain institutions -3. High inequality + stable institutions -4. High inequality + uncertain institutions +Servers are the unit of treatment assignment because participants share a map, treasury, rounds, and institutional environment. -The server is the core unit of randomization because participants share a parcel map, institutional context, and public-good environment. +## Screenshots -## MVP Scope +Screenshots are not committed yet. Add release screenshots to `docs/images/` as the public demo stabilizes. -The foundation release provides the monorepo, tooling, documentation skeleton, placeholder web pages, a minimal Prisma setup, shared constants, and engine type placeholders. It does not implement authentication, gameplay, admin workflows, CSV export, or detailed database models yet. +Suggested placeholders: -## Tech Stack +- `docs/images/home.png` — public landing page. +- `docs/images/admin-dashboard.png` — admin overview. +- `docs/images/server-map.png` — 10x10 parcel map. +- `docs/images/export-flow.png` — research export workflow. -- TypeScript -- pnpm workspaces -- Next.js App Router -- React -- Tailwind CSS -- Prisma -- PostgreSQL -- Docker Compose -- Vitest -- ESLint -- Prettier +## Quick start -## Repository Structure +Requirements: -```text -parcel-society/ - apps/ - web/ Next.js TypeScript app - packages/ - db/ Prisma schema and database client package - engine/ TypeScript game engine package - shared/ Shared types, constants, and utilities - docs/ Research, mechanics, deployment, admin, and ethics notes -``` - -## Quick Start +- Node.js 22 or newer +- pnpm 10.28.1 or compatible via Corepack +- PostgreSQL 16, either local or through Docker Compose ```bash +corepack enable pnpm install +cp .env.example .env +docker compose up -d postgres pnpm db:generate pnpm db:migrate +pnpm seed:demo pnpm dev ``` -Open to view the placeholder web app. +Open . The admin area is available at . -## Docker Start +## Docker start + +For local Docker development: ```bash +cp .env.example .env docker compose up --build ``` -Docker Compose starts PostgreSQL and the Next.js web app. - -## Environment Variables - -Copy `.env.example` to `.env` and update values as needed. +For the production-oriented Compose file: ```bash -DATABASE_URL="postgresql://parcel:parcel_password@localhost:5432/parcel_society?schema=public" -APP_SECRET="replace-with-a-long-random-secret" -ADMIN_EMAIL="admin@example.com" -ADMIN_PASSWORD="changeme" -NODE_ENV="development" +cp .env.example .env +# Edit .env before any shared deployment. +docker compose -f docker-compose.prod.yml up --build ``` -## Development Commands - -- `pnpm dev` - run the web app locally -- `pnpm build` - build all workspace packages -- `pnpm lint` - lint all workspace packages -- `pnpm format` - format the repository with Prettier -- `pnpm typecheck` - type-check all workspace packages -- `pnpm test` - run Vitest across workspaces -- `pnpm db:generate` - generate the Prisma client -- `pnpm db:migrate` - run local Prisma migrations -- `pnpm db:studio` - open Prisma Studio -- `pnpm seed` - seed one admin and the four demo treatment servers -- `pnpm seed:demo` - create the full local demo experiment with maps, anonymous players, synthetic decisions, and resolved rounds - -## Demo Mode - -Create a complete local demo experiment after installing dependencies, generating the Prisma client, and applying migrations: +In another terminal, apply migrations if needed: ```bash -pnpm seed:demo +docker compose -f docker-compose.prod.yml --profile tools run --rm migrate ``` -The demo seed creates one admin account, four active 2x2 treatment servers, a 10x10 map for each server, 20 anonymous demo participants per server, parcel assignments, a 7-round active season, synthetic decisions for rounds 1-3, resolved round states, contracts, treasury transactions, events, and dashboard-ready analytics. Running it again replaces the existing demo servers with a fresh deterministic demo dataset. +## Demo credentials -Demo login: +The demo seed uses these local-only credentials by default: ```text -admin@example.com -changeme +Email: admin@example.com +Password: changeme ``` -Warning: Demo credentials are only for local development. Set `ADMIN_EMAIL` and `ADMIN_PASSWORD` for any shared or deployed environment. +Do not use demo credentials in shared, hosted, classroom, pilot, or production environments. Set `ADMIN_EMAIL`, `ADMIN_PASSWORD`, `APP_SECRET`, `NEXTAUTH_SECRET`, and database credentials in `.env` before deployment. -## Database Migrations +## Architecture -Parcel Society uses Prisma with PostgreSQL. The schema lives at `packages/db/prisma/schema.prisma` and the generated client is exposed by `@parcel-society/db`. +Parcel Society is a pnpm workspace with a small set of focused packages: -1. Start PostgreSQL locally, for example with Docker Compose: +```text +apps/web/ Next.js App Router application and API routes +packages/db/ Prisma schema, database client, and seed scripts +packages/engine/ Deterministic game logic, validation, scoring, and simulations +packages/shared/ Shared constants, types, and server configuration helpers +packages/analysis/ Lightweight export-analysis helper scripts +docs/ Research, operations, ethics, and deployment documentation +configs/ Example server and pilot configuration files +deploy/ Deployment support files such as Nginx examples +``` - ```bash - docker compose up postgres -d - ``` +Runtime flow: -2. Copy `.env.example` to `.env` and set `DATABASE_URL`: +1. Researchers configure and create treatment servers. +2. Participants join a server, complete checks, and play seven rounds. +3. The engine resolves submitted decisions with seeded randomness. +4. Admin pages summarize maps, players, rounds, contracts, events, and analytics. +5. Research-safe ZIP/CSV exports support reproducible analysis outside the app. - ```bash - DATABASE_URL="postgresql://parcel:parcel_password@localhost:5432/parcel_society?schema=public" - ``` +## Research design -3. Create and apply a migration after schema changes: +The current study design uses seven-round seasons, three action points per participant per round, and 10x10 parcel maps. Initial parcel quality operationalizes inequality, while stable versus uncertain institutional conditions affect the reliability and predictability of rules or shocks. - ```bash - pnpm db:migrate -- --name describe_change - ``` +Confirmatory analysis should be preregistered before real data collection. The included analysis helper is descriptive and intended for pilots, diagnostics, and transparent release artifacts. See: -4. Regenerate the Prisma client when the schema changes: +- [`docs/research-design.md`](docs/research-design.md) +- [`docs/game-mechanics.md`](docs/game-mechanics.md) +- [`docs/analysis-plan.md`](docs/analysis-plan.md) +- [`docs/ethics.md`](docs/ethics.md) - ```bash - pnpm db:generate - ``` +## Data exports -5. Seed the development database with one admin and the four 2x2 treatment demo servers: +Administrators can export research-safe ZIP files: - ```bash - pnpm seed - ``` +- `GET /api/admin/servers/:serverId/export.zip` for one server. +- `GET /api/admin/export/all.zip` for all servers. -6. Or create the complete demo mode dataset with active servers, players, synthetic decisions, and three resolved rounds: +Exports are normalized CSV files and intentionally omit emails, names, IP addresses, authentication data, and direct personal identifiers. See [`docs/data-dictionary.md`](docs/data-dictionary.md) for tables, columns, and derived measures. - ```bash - pnpm seed:demo - ``` +## Development commands -For non-development deployments, run Prisma migrations during release using the same schema path, for example `pnpm --filter @parcel-society/db prisma migrate deploy --schema prisma/schema.prisma`. +```bash +pnpm install # install workspace dependencies +pnpm dev # run the web app locally +pnpm typecheck # type-check all packages +pnpm lint # lint all packages +pnpm test # run Vitest tests +pnpm build # build all packages +pnpm format # format Markdown, TypeScript, and config files +pnpm db:generate # generate Prisma client +pnpm db:migrate # run local Prisma migrations +pnpm seed # seed admin and treatment servers +pnpm seed:demo # seed deterministic demo data +``` ## Roadmap -1. Add deterministic server configuration schemas. -2. Implement seeded map generation for low- and high-inequality treatments. -3. Add minimal participant decision storage. -4. Build admin server creation and season controls. -5. Implement round resolution in the engine. -6. Add research-safe CSV exports. -7. Harden deployment, authentication, and audit logging. +- Stabilize public demo screenshots and release assets. +- Expand pilot documentation with exact recruitment and session procedures. +- Add more export validation and reproducibility checks. +- Add preregistration templates for confirmatory studies. +- Improve admin ergonomics without expanding the research design unnecessarily. +- Keep mechanics simple, auditable, deterministic where appropriate, and easy to explain to participants. ## Contributing -Contributions should preserve the scientific MVP scope. Avoid adding entertainment, social, crypto, or complex simulation features unless they are explicitly justified by the research design. +Contributions are welcome when they keep the project stable, research-oriented, and easy to audit. Start with [`CONTRIBUTING.md`](CONTRIBUTING.md), open an issue for substantial changes, and avoid adding mechanics or features without a clear study-design reason. + +Good first contributions include documentation improvements, test coverage, validation edge cases, export checks, and small UI accessibility fixes. ## License -MIT. See [LICENSE](./LICENSE). +Parcel Society is released under the MIT License. See [`LICENSE`](LICENSE). diff --git a/docs/admin-guide.md b/docs/admin-guide.md index 2ec9d53..b48f097 100644 --- a/docs/admin-guide.md +++ b/docs/admin-guide.md @@ -1,12 +1,73 @@ # Admin Guide -The admin dashboard is not implemented in the foundation release. The intended workflow is: +This guide describes the intended administrator workflow for local pilots and research sessions. -1. Create a server for a study session. -2. Assign or randomize the experimental condition. -3. Generate the parcel map with deterministic seeded randomness. -4. Start the 7-round season. -5. Resolve each round after participant decisions are submitted. -6. Export research-safe CSV data for analysis. +## Local setup -Authentication, authorization, and operational audit logs will be designed before real study use. +```bash +cp .env.example .env +docker compose up -d postgres +pnpm install +pnpm db:generate +pnpm db:migrate +pnpm seed:demo +pnpm dev +``` + +Open and sign in with the local demo credentials unless you changed `.env`. + +## Demo credentials + +```text +Email: admin@example.com +Password: changeme +``` + +Use these only for local development. Change `ADMIN_EMAIL`, `ADMIN_PASSWORD`, `APP_SECRET`, and `NEXTAUTH_SECRET` for shared environments. + +## Admin workflow + +1. Review or create server configuration. +2. Assign the inequality and uncertainty treatment. +3. Generate the parcel map from the configuration. +4. Start the season. +5. Monitor players, parcels, rounds, contracts, events, and analytics. +6. Resolve rounds after decisions are submitted. +7. Export data at the end of the session. +8. Archive servers that should no longer accept participant activity. + +## Server configuration + +Keep configuration files under version control when they are part of a pilot or release artifact. Record seeds, treatment labels, player limits, and round settings so the session can be reproduced. + +## Participant support + +Administrators should prepare study-specific consent, instructions, recruitment text, and debriefing outside the app. Avoid changing participant-facing wording during a live session unless the change is logged as a protocol deviation. + +## Data exports + +Use the admin export pages or API endpoints to download ZIP files. Store exports with the commit SHA, configuration files, analysis scripts, and any preregistration material. + +## Operational checklist + +Before a session: + +- Confirm database connectivity through `/api/health`. +- Confirm the correct `.env` values are loaded. +- Confirm demo credentials are not used in shared environments. +- Run a short pilot with synthetic or test participants. +- Verify exports open in the analysis environment. + +After a session: + +- Export data promptly. +- Back up the database if the session must be preserved. +- Archive completed servers. +- Record any incidents, interruptions, or deviations. + +## Security reminders + +- Use strong administrator credentials. +- Do not expose PostgreSQL to the public internet. +- Use HTTPS for any non-local session. +- Do not collect direct identifiers unless a study protocol requires them outside Parcel Society. diff --git a/docs/analysis-plan.md b/docs/analysis-plan.md index c7f7249..f6dbd05 100644 --- a/docs/analysis-plan.md +++ b/docs/analysis-plan.md @@ -29,9 +29,9 @@ Secondary outcomes are diagnostic and mechanism-oriented measures: Parcel Society uses a 2×2 treatment structure: -| Factor | Low / stable condition | High / uncertain condition | -|---|---|---| -| Initial inequality | Low parcel-quality inequality | High parcel-quality inequality | +| Factor | Low / stable condition | High / uncertain condition | +| ------------------------- | ---------------------------------- | ---------------------------------------- | +| Initial inequality | Low parcel-quality inequality | High parcel-quality inequality | | Institutional uncertainty | Stable rules and shock environment | Uncertain rules and/or shock environment | The main contrasts are the high-inequality effect, the uncertainty effect, and their interaction. diff --git a/docs/data-dictionary.md b/docs/data-dictionary.md index 23d4de9..c6c9d61 100644 --- a/docs/data-dictionary.md +++ b/docs/data-dictionary.md @@ -19,128 +19,128 @@ The ZIP contains eight CSV files. Exports intentionally omit emails, IP addresse One row per player assignment on an exported server. -| Column | Type | Description | -| --- | --- | --- | -| `player_id` | string | Internal anonymous player identifier for this server. | -| `server_id` | string | Server/experimental session identifier. | -| `treatment_inequality` | enum | Server inequality treatment: `LOW` or `HIGH`. | -| `treatment_uncertainty` | enum | Server uncertainty treatment: `STABLE` or `UNCERTAIN`. | -| `initial_parcel_quality` | decimal | Quality score of the parcel initially assigned to the player. | -| `initial_wealth` | decimal | Starting wealth configured for the server. | -| `final_wealth` | decimal | Player wealth at export time, or final wealth if the server is complete. | -| `productive_capital_final` | decimal | Player productive capital at export time. | -| `safe_asset_final` | decimal | Player safe-asset balance at export time. | -| `exited` | boolean | Whether the player exited by export time. | -| `round_exited` | integer | Round when the player exited, blank if the player has not exited. | +| Column | Type | Description | +| -------------------------- | ------- | ------------------------------------------------------------------------ | +| `player_id` | string | Internal anonymous player identifier for this server. | +| `server_id` | string | Server/experimental session identifier. | +| `treatment_inequality` | enum | Server inequality treatment: `LOW` or `HIGH`. | +| `treatment_uncertainty` | enum | Server uncertainty treatment: `STABLE` or `UNCERTAIN`. | +| `initial_parcel_quality` | decimal | Quality score of the parcel initially assigned to the player. | +| `initial_wealth` | decimal | Starting wealth configured for the server. | +| `final_wealth` | decimal | Player wealth at export time, or final wealth if the server is complete. | +| `productive_capital_final` | decimal | Player productive capital at export time. | +| `safe_asset_final` | decimal | Player safe-asset balance at export time. | +| `exited` | boolean | Whether the player exited by export time. | +| `round_exited` | integer | Round when the player exited, blank if the player has not exited. | ## `parcels.csv` One row per generated land parcel. -| Column | Type | Description | -| --- | --- | --- | -| `parcel_id` | string | Internal parcel identifier. | -| `server_id` | string | Server that contains the parcel. | -| `x` | integer | Parcel x-coordinate on the server map. | -| `y` | integer | Parcel y-coordinate on the server map. | -| `soil` | decimal | Soil component used in parcel quality generation. | -| `water` | decimal | Water component used in parcel quality generation. | -| `market_access` | decimal | Market-access component used in parcel quality generation. | -| `risk` | decimal | Parcel risk component. | -| `quality` | decimal | Composite parcel quality score. | -| `owner_player_id` | string | Current owning player identifier, blank if unowned. | +| Column | Type | Description | +| ----------------- | ------- | ---------------------------------------------------------- | +| `parcel_id` | string | Internal parcel identifier. | +| `server_id` | string | Server that contains the parcel. | +| `x` | integer | Parcel x-coordinate on the server map. | +| `y` | integer | Parcel y-coordinate on the server map. | +| `soil` | decimal | Soil component used in parcel quality generation. | +| `water` | decimal | Water component used in parcel quality generation. | +| `market_access` | decimal | Market-access component used in parcel quality generation. | +| `risk` | decimal | Parcel risk component. | +| `quality` | decimal | Composite parcel quality score. | +| `owner_player_id` | string | Current owning player identifier, blank if unowned. | ## `decisions.csv` One row per submitted player action. -| Column | Type | Description | -| --- | --- | --- | -| `decision_id` | string | Internal decision identifier. | -| `server_id` | string | Server where the decision was submitted. | -| `player_id` | string | Player who submitted the decision. | -| `round` | integer | Round number for the decision. | -| `action_type` | enum | Submitted action, such as `PRODUCE`, `PRODUCTIVE_INVESTMENT`, `SAFE_ASSET`, `PUBLIC_CONTRIBUTION`, `INFORMAL_CONTRACT`, `FORMAL_CONTRACT`, `LOBBYING`, or `EXIT`. | -| `amount` | decimal | Submitted amount for actions with an amount; zero when not applicable. | -| `target_player_id` | string | Counterparty player for contract-like actions, blank when not applicable. | -| `created_at` | timestamp | Submission timestamp. | +| Column | Type | Description | +| ------------------ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `decision_id` | string | Internal decision identifier. | +| `server_id` | string | Server where the decision was submitted. | +| `player_id` | string | Player who submitted the decision. | +| `round` | integer | Round number for the decision. | +| `action_type` | enum | Submitted action, such as `PRODUCE`, `PRODUCTIVE_INVESTMENT`, `SAFE_ASSET`, `PUBLIC_CONTRIBUTION`, `INFORMAL_CONTRACT`, `FORMAL_CONTRACT`, `LOBBYING`, or `EXIT`. | +| `amount` | decimal | Submitted amount for actions with an amount; zero when not applicable. | +| `target_player_id` | string | Counterparty player for contract-like actions, blank when not applicable. | +| `created_at` | timestamp | Submission timestamp. | ## `contracts.csv` One row per contract created during round resolution. -| Column | Type | Description | -| --- | --- | --- | -| `contract_id` | string | Internal contract identifier. | -| `server_id` | string | Server where the contract was created. | -| `round` | integer | Round in which the contract was resolved. | -| `sender_id` | string | Player who offered or sent the contract. | -| `receiver_id` | string | Counterparty player. | -| `contract_type` | enum | `FORMAL` or `INFORMAL`. | -| `value` | decimal | Contract transfer value. | -| `fee` | decimal | Fee charged for the contract. | -| `fulfilled` | boolean | Whether the contract was fulfilled; blank if unresolved. | -| `defaulted` | boolean | Whether the contract defaulted; blank if unresolved. | +| Column | Type | Description | +| --------------- | ------- | -------------------------------------------------------- | +| `contract_id` | string | Internal contract identifier. | +| `server_id` | string | Server where the contract was created. | +| `round` | integer | Round in which the contract was resolved. | +| `sender_id` | string | Player who offered or sent the contract. | +| `receiver_id` | string | Counterparty player. | +| `contract_type` | enum | `FORMAL` or `INFORMAL`. | +| `value` | decimal | Contract transfer value. | +| `fee` | decimal | Fee charged for the contract. | +| `fulfilled` | boolean | Whether the contract was fulfilled; blank if unresolved. | +| `defaulted` | boolean | Whether the contract defaulted; blank if unresolved. | ## `server_events.csv` One row per institutional, rule-change, informational, or shock event. -| Column | Type | Description | -| --- | --- | --- | -| `event_id` | string | Internal event identifier. | -| `server_id` | string | Server where the event occurred. | -| `round` | integer | Round associated with the event. | -| `event_type` | enum | Event category, such as `TAX_CHANGE`, `FORMAL_CONTRACT_FEE_CHANGE`, `SHOCK_PROBABILITY_CHANGE`, `RESOURCE_SHOCK`, or `INFO`. | -| `event_value_json` | JSON string | Event payload serialized as JSON. | -| `created_at` | timestamp | Event creation timestamp. | +| Column | Type | Description | +| ------------------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------- | +| `event_id` | string | Internal event identifier. | +| `server_id` | string | Server where the event occurred. | +| `round` | integer | Round associated with the event. | +| `event_type` | enum | Event category, such as `TAX_CHANGE`, `FORMAL_CONTRACT_FEE_CHANGE`, `SHOCK_PROBABILITY_CHANGE`, `RESOURCE_SHOCK`, or `INFO`. | +| `event_value_json` | JSON string | Event payload serialized as JSON. | +| `created_at` | timestamp | Event creation timestamp. | ## `treasury_transactions.csv` One row per public treasury movement. -| Column | Type | Description | -| --- | --- | --- | -| `transaction_id` | string | Internal treasury transaction identifier. | -| `server_id` | string | Server where the transaction occurred. | -| `player_id` | string | Related player, blank for server-level transactions. | -| `round` | integer | Related round, blank if not tied to a round. | -| `type` | enum | Transaction category, such as `CONTRIBUTION`, `TAX`, `FEE`, `FINE`, `PUBLIC_SPENDING`, `PAYOUT`, or `ADJUSTMENT`. | -| `amount` | decimal | Transaction amount. Positive values increase treasury; negative values decrease it. | -| `description` | string | Non-personal transaction note or reason code. | +| Column | Type | Description | +| ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------- | +| `transaction_id` | string | Internal treasury transaction identifier. | +| `server_id` | string | Server where the transaction occurred. | +| `player_id` | string | Related player, blank for server-level transactions. | +| `round` | integer | Related round, blank if not tied to a round. | +| `type` | enum | Transaction category, such as `CONTRIBUTION`, `TAX`, `FEE`, `FINE`, `PUBLIC_SPENDING`, `PAYOUT`, or `ADJUSTMENT`. | +| `amount` | decimal | Transaction amount. Positive values increase treasury; negative values decrease it. | +| `description` | string | Non-personal transaction note or reason code. | ## `round_outcomes.csv` One row per server round with aggregate outcome measures. -| Column | Type | Description | -| --- | --- | --- | -| `server_id` | string | Server identifier. | -| `round` | integer | Round number. | -| `informal_cooperation_rate` | decimal | Informal contracts created divided by formal plus informal contract decisions in the round. | -| `contract_reliability` | decimal | Fulfilled resolved contracts divided by all resolved contracts in the round. | +| Column | Type | Description | +| ----------------------------- | ------- | ------------------------------------------------------------------------------------------------------------ | +| `server_id` | string | Server identifier. | +| `round` | integer | Round number. | +| `informal_cooperation_rate` | decimal | Informal contracts created divided by formal plus informal contract decisions in the round. | +| `contract_reliability` | decimal | Fulfilled resolved contracts divided by all resolved contracts in the round. | | `productive_investment_share` | decimal | Productive-investment spending divided by total investment/public/lobbying/safe-asset spending in the round. | -| `public_contribution_share` | decimal | Public-contribution spending divided by total investment/public/lobbying/safe-asset spending in the round. | -| `exit_rate` | decimal | Share of players exited by the end of the round. | -| `safe_asset_share` | decimal | Safe-asset spending divided by total investment/public/lobbying/safe-asset spending in the round. | -| `lobbying_share` | decimal | Lobbying spending divided by total investment/public/lobbying/safe-asset spending in the round. | -| `treasury` | decimal | Cumulative treasury balance implied by exported treasury transactions through the round. | -| `active_players` | integer | Number of players not exited by the end of the round. | -| `total_output` | decimal | Total production output stored by the round resolver for the round. | +| `public_contribution_share` | decimal | Public-contribution spending divided by total investment/public/lobbying/safe-asset spending in the round. | +| `exit_rate` | decimal | Share of players exited by the end of the round. | +| `safe_asset_share` | decimal | Safe-asset spending divided by total investment/public/lobbying/safe-asset spending in the round. | +| `lobbying_share` | decimal | Lobbying spending divided by total investment/public/lobbying/safe-asset spending in the round. | +| `treasury` | decimal | Cumulative treasury balance implied by exported treasury transactions through the round. | +| `active_players` | integer | Number of players not exited by the end of the round. | +| `total_output` | decimal | Total production output stored by the round resolver for the round. | ## `server_summary.csv` One row per exported server with final treatment and outcome measures. -| Column | Type | Description | -| --- | --- | --- | -| `server_id` | string | Server identifier. | -| `inequality_condition` | enum | Inequality treatment: `LOW` or `HIGH`. | -| `uncertainty_condition` | enum | Uncertainty treatment: `STABLE` or `UNCERTAIN`. | -| `random_seed` | string | Server random seed used for reproducible generation and resolution. | -| `initial_land_gini` | decimal | Gini coefficient of initially assigned parcel quality among players. | -| `final_wealth_gini` | decimal | Gini coefficient of final/export-time wealth plus safe assets among players. | -| `final_exit_rate` | decimal | Share of players exited by export time. | -| `final_contract_reliability` | decimal | Contract reliability from the final exported round, or all resolved contracts when no final round aggregate is available. | -| `final_public_contribution_share` | decimal | Public-contribution spending share from the final exported round. | -| `final_productive_investment_share` | decimal | Productive-investment spending share from the final exported round. | +| Column | Type | Description | +| ----------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------- | +| `server_id` | string | Server identifier. | +| `inequality_condition` | enum | Inequality treatment: `LOW` or `HIGH`. | +| `uncertainty_condition` | enum | Uncertainty treatment: `STABLE` or `UNCERTAIN`. | +| `random_seed` | string | Server random seed used for reproducible generation and resolution. | +| `initial_land_gini` | decimal | Gini coefficient of initially assigned parcel quality among players. | +| `final_wealth_gini` | decimal | Gini coefficient of final/export-time wealth plus safe assets among players. | +| `final_exit_rate` | decimal | Share of players exited by export time. | +| `final_contract_reliability` | decimal | Contract reliability from the final exported round, or all resolved contracts when no final round aggregate is available. | +| `final_public_contribution_share` | decimal | Public-contribution spending share from the final exported round. | +| `final_productive_investment_share` | decimal | Productive-investment spending share from the final exported round. | diff --git a/docs/ethics.md b/docs/ethics.md index de66009..9099f3d 100644 --- a/docs/ethics.md +++ b/docs/ethics.md @@ -1,10 +1,40 @@ # Ethics -Parcel Society should collect only the data required for research analysis. - -- Use anonymous participant identifiers. -- Avoid unnecessary personal data. -- Do not include real-money payout logic in the MVP. -- Do not collect raw chat data; chat is outside MVP scope. -- Export only research-safe data needed for reproducible analysis. -- Document consent, debriefing, and institutional review requirements outside the application when used in real studies. +Parcel Society is research software and should be used with an approved study protocol when human participants are involved. This document is not legal or institutional review advice; it is a practical checklist for keeping the project privacy-preserving and participant-respecting. + +## Principles + +- Collect the minimum data needed for the research question. +- Use anonymous participant identifiers in the application and exports. +- Keep consent, recruitment, compensation, and debriefing materials study-specific and reviewable. +- Avoid deceptive mechanics unless explicitly approved by the relevant review process. +- Prefer transparent, simple rules that participants can understand. +- Do not add chat, social feeds, or direct identifiers without a strong protocol reason. + +## Data minimization + +The application should avoid storing names, raw IP addresses, unnecessary contact details, or free-text participant content. Research exports should contain internal player identifiers and analysis variables only. + +## Consent and debriefing + +Researchers using Parcel Society should provide participant-facing materials that explain: + +- The study purpose at the level approved by the protocol. +- Expected time commitment. +- Risks and benefits. +- Data collected by the application. +- Whether participation is anonymous or confidential. +- Withdrawal and contact procedures. +- Debriefing information after completion when appropriate. + +## Compensation + +The application does not implement real-money payout logic. If compensation or bonuses are used, calculate and administer them through a reviewed external process and avoid storing unnecessary payment identifiers in Parcel Society. + +## Risk management + +Potential risks include misunderstanding the game, frustration from unequal initial conditions, privacy leakage from small groups, and accidental disclosure through exports. Mitigations include clear instructions, comprehension checks, minimal data collection, secure deployment, and careful aggregation in publications. + +## Publication and sharing + +When sharing data, remove direct identifiers, review small-cell disclosure risk, include codebooks, and document all exclusions or transformations. Public releases should favor synthetic demo data unless the study protocol and consent allow broader data sharing. diff --git a/docs/game-mechanics.md b/docs/game-mechanics.md index 720c293..db59733 100644 --- a/docs/game-mechanics.md +++ b/docs/game-mechanics.md @@ -1,38 +1,63 @@ # Game Mechanics -Parcel Society is a research game, not an entertainment game. Mechanics should remain simple, auditable, and reproducible. +Parcel Society is a research game. Mechanics should remain simple, auditable, and directly connected to the study design. -## Season Length +## Core objects -Each experimental season lasts 7 rounds. Rounds create repeated opportunities for investment, cooperation, contracting, rent-seeking, and exit decisions. +- **Server**: one experimental society and treatment assignment. +- **Season**: a repeated interaction session within a server. +- **Round**: one decision and resolution cycle. +- **Player**: an anonymous participant assignment inside a server. +- **Parcel**: one cell on the 10x10 map with a quality value. +- **Treasury**: server-level public balance affected by contributions and events. +- **Contract**: a formal or informal agreement tracked for reliability analysis. -## Action Points +## Default parameters -Each participant receives 3 action points per round. Actions are intentionally limited so choices are interpretable and comparable across treatments. +| Parameter | Default | +| ----------------- | ------------------------------------------------ | +| Map size | 10x10 parcels | +| Season length | 7 rounds | +| Action points | 3 per active player per round | +| Treatment factors | Initial inequality and institutional uncertainty | -## Parcel Map +## Parcel map -Each server uses a 10x10 parcel map. Parcels will later receive quality levels according to the assigned inequality condition. +The map represents spatial opportunity. Each parcel has coordinates and a quality score. Low-inequality servers assign more similar quality values, while high-inequality servers assign more unequal values. The map should be generated from stored configuration and seeds so releases are reproducible. -## Player Actions +## Player actions -The initial action vocabulary is: +The initial action vocabulary is intentionally constrained: -- Produce -- Productive investment -- Safe asset -- Public contribution -- Informal contract -- Formal contract -- Lobbying -- Exit +- **Produce**: convert current opportunities into output. +- **Productive investment**: allocate resources toward future production. +- **Safe asset**: protect resources in a lower-risk option. +- **Public contribution**: contribute to the shared treasury or public good. +- **Informal contract**: cooperate without formal enforcement. +- **Formal contract**: cooperate with a stronger institutional backing. +- **Lobbying**: allocate resources toward rent-seeking or institutional advantage. +- **Exit**: leave the active society. -These are placeholders for the research engine and should not be expanded without a study-design reason. +Do not expand this action list without a clear research-design reason. -## Institutional Conditions +## Round lifecycle -Stable institutions keep the rules and enforcement environment predictable across the season. Uncertain institutions introduce controlled uncertainty about institutional reliability while preserving deterministic seeded randomness for reproducibility. +1. The server exposes the current round state. +2. Active players submit decisions subject to action-point and validation rules. +3. Administrators or automated session control resolve the round. +4. The engine applies production, investment, contracts, shocks, treasury updates, and scoring. +5. The app stores player-round state, decisions, contracts, events, and treasury transactions. +6. Participants see round summaries and continue until the season ends or they exit. -## Inequality Conditions +## Institutions -Low inequality assigns relatively similar parcel opportunities across participants. High inequality assigns more unequal initial parcel opportunities. The exact allocation algorithms will be implemented later in the engine. +Stable institutions keep enforcement and shock rules predictable. Uncertain institutions introduce controlled uncertainty while remaining reproducible through explicit configuration and seeds. + +## Design principles + +- Prefer fewer actions over richer but less interpretable mechanics. +- Keep randomness seeded and inspectable. +- Log every analysis-relevant state transition. +- Preserve anonymous participant identifiers. +- Avoid real-money payout logic in the application core. +- Treat participant-facing text as part of the experimental instrument. diff --git a/docs/images/.gitkeep b/docs/images/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/research-design.md b/docs/research-design.md index b4ec716..df1c5ac 100644 --- a/docs/research-design.md +++ b/docs/research-design.md @@ -1,29 +1,79 @@ # Research Design -Parcel Society is designed for controlled online behavioral experiments. The first scientific version studies how initial spatial inequality and institutional uncertainty shape cooperative behavior and institutional trust. +Parcel Society is designed for controlled online behavioral experiments about cooperation, inequality, and institutional trust. The first public release supports a simple research design that can be audited, reproduced, and extended by researchers before a preregistered study. -## 2x2 Experimental Design +## Research question -Servers are assigned to one of four conditions: +How do initial spatial inequality and institutional uncertainty affect cooperation, investment, public-good contribution, contract reliability, rent-seeking, and exit in a repeated small-society setting? -1. Low inequality + stable institutions -2. Low inequality + uncertain institutions -3. High inequality + stable institutions -4. High inequality + uncertain institutions +## Unit of assignment -Inequality describes the initial distribution of parcel quality across the 10x10 map. Institutional uncertainty describes whether rules, enforcement reliability, or administrative conditions remain predictable across rounds. +The server is the unit of treatment assignment. Participants inside a server share the same parcel map, public treasury, round schedule, institutional condition, and social environment. Assigning treatments at the server level reduces contamination between participants who interact during the same session. -## Primary Outcomes +## Treatment structure -The MVP will eventually measure: +Parcel Society uses a 2x2 design: -- Cooperation and public-good contribution -- Productive investment and saving behavior -- Formal and informal contract creation and reliability -- Lobbying or rent-seeking behavior -- Exit from the virtual society -- Round-level and season-level outcomes suitable for CSV export +| Condition | Initial parcel inequality | Institutional environment | +| ---------------------------------------- | ---------------------------------- | ---------------------------------------------------------------- | +| Low inequality + stable institutions | Low dispersion in parcel quality. | Rules and enforcement are predictable across rounds. | +| Low inequality + uncertain institutions | Low dispersion in parcel quality. | Reliability or shocks vary according to controlled seeded rules. | +| High inequality + stable institutions | High dispersion in parcel quality. | Rules and enforcement are predictable across rounds. | +| High inequality + uncertain institutions | High dispersion in parcel quality. | Reliability or shocks vary according to controlled seeded rules. | -## Why Server-Level Randomization Matters +## Session structure -Participants interact within small societies, so treatment assignment should happen at the server level rather than independently by participant. Server-level randomization prevents participants in different treatment conditions from sharing the same local institution, parcel allocation process, or public treasury. It also keeps analysis aligned with the social unit where spillovers and peer effects occur. +- Participants join an available server. +- Each participant is assigned an anonymous internal player identifier. +- A server runs a seven-round season by default. +- Each round gives every active participant three action points by default. +- Participants allocate decisions across production, investment, public contribution, contracts, lobbying, or exit. +- Rounds are resolved by deterministic engine logic and seeded randomness where the design requires uncertainty. +- Administrators export normalized CSV files after pilots or sessions. + +## Primary outcomes + +Primary outcomes should be summarized at the server or server-round level for confirmatory analysis: + +1. Public-good contribution share. +2. Productive investment share. +3. Contract reliability. +4. Informal versus formal cooperation rate. +5. Lobbying or rent-seeking share. +6. Exit rate. +7. Final wealth and inequality measures. + +## Secondary and diagnostic outcomes + +Secondary outcomes can help explain mechanisms but should be marked exploratory unless included in a preregistration: + +- Safe-asset allocation. +- Total production output. +- Treasury balance. +- Active-player count. +- Initial parcel-quality Gini. +- Final wealth Gini. +- Round completion and missingness indicators. +- Event and shock frequencies. + +## Randomization and reproducibility + +Server configuration should include seeds and explicit treatment labels. A reproduced server should produce the same map and same seeded institutional events when run with the same code and configuration. Randomization records should be retained with exported data and analysis scripts. + +## Exclusions and missingness + +Before real studies, researchers should define: + +- Minimum participation requirements. +- How to handle participants who exit or disconnect. +- Whether incomplete rounds are excluded or carried forward. +- How unresolved contracts enter reliability denominators. +- Whether servers with low participant counts remain in confirmatory analysis. + +## Analysis expectation + +The repository includes a lightweight analysis helper for descriptive treatment contrasts. Confirmatory studies should use a preregistered model, account for clustering within servers, and report uncertainty clearly. + +## Scope boundaries + +Parcel Society intentionally avoids entertainment-game complexity. New mechanics should be added only when they answer a research question and can be explained to participants, logged cleanly, and exported for analysis.