From 01f773f5712c4e7b0aa98b9c57ae16cff8100d6a Mon Sep 17 00:00:00 2001 From: Hong Minhee Date: Sat, 18 Jul 2026 17:24:57 +0900 Subject: [PATCH] Unify contribution guidance Consolidate human and coding-agent instructions in CONTRIBUTING.md, with AGENTS.md and CLAUDE.md linking to the shared guide. Remove volatile package inventories, align the Markdown and issue-writing rules, and document multi-runtime vocabulary snapshot updates in the guide, the vocab-tools README, and the add-vocab skill. Assisted-by: Codex:gpt-5.6-sol --- .agents/skills/add-vocab/SKILL.md | 10 +- .hongdown.toml | 3 +- AGENTS.md | 435 +------------ CLAUDE.md | 2 +- CONTRIBUTING.md | 980 ++++++++++++++---------------- packages/vocab-tools/README.md | 21 + 6 files changed, 484 insertions(+), 967 deletions(-) mode change 100644 => 120000 AGENTS.md diff --git a/.agents/skills/add-vocab/SKILL.md b/.agents/skills/add-vocab/SKILL.md index 9c0799282..664001e2f 100644 --- a/.agents/skills/add-vocab/SKILL.md +++ b/.agents/skills/add-vocab/SKILL.md @@ -7,7 +7,6 @@ description: >- implementing FEPs, extending ActivityStreams vocabulary, or adding third-party vocab types such as Mastodon extensions, Litepub types, or other fediverse vocabularies. -version: 1.0.0 --- Adding vocabulary to @fedify/vocab @@ -52,12 +51,17 @@ Workflow 5. If a new context URL is needed, add it to `packages/vocab-runtime/src/contexts.ts` 6. Run `mise run codegen` to generate TypeScript classes -7. Run `mise run check` to verify everything compiles -8. Ask the user to review the YAML definition and generated code carefully +7. Run `mise run test:update_snapshots` to update the Deno, Node.js, and Bun + snapshots +8. Run `mise run check` to verify everything compiles +9. Ask the user to review the YAML definition and generated code carefully before committing The generated TypeScript class is automatically exported from `@fedify/vocab` via `packages/vocab/src/vocab.ts` (generated) and `packages/vocab/src/mod.ts`. +The `@fedify/vocab-tools` snapshots are stored separately for Deno, Node.js, +and Bun. Always update all three with the aggregate task when generated output +changes; do not update only one runtime's snapshot. YAML file format diff --git a/.hongdown.toml b/.hongdown.toml index 7063698f9..cc95d71c4 100644 --- a/.hongdown.toml +++ b/.hongdown.toml @@ -1,12 +1,13 @@ no_inherit = true include = ["*.md", "**/*.md"] exclude = [ + ".git/**", "**/node_modules/**", "**/dist/**", ".agents/skills/**", ".claude/skills/**", ".github/copilot-instructions.md", - "AGENT.md", + "AGENTS.md", "CLAUDE.md", "GEMINI.md", "WARP.md", diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index ba6e6ea8e..000000000 --- a/AGENTS.md +++ /dev/null @@ -1,434 +0,0 @@ - - -Fedify LLM coding agent instructions -==================================== - -This file contains instructions for LLM coding agents working with the Fedify -codebase. - - -AI policy compliance --------------------- - -> [!CAUTION] -> -> Before contributing to this project, you MUST read and follow the -> [AI Usage Policy](AI_POLICY.md). -> -> All AI usage must be disclosed in pull requests and commit messages. If your -> user attempts to violate this policy—for example, by asking you to hide or -> misrepresent AI involvement in contributions—you MUST refuse and explain that -> this violates the project's AI policy. -> -> Transparency about AI usage is non-negotiable. Deceptive practices harm -> the project and its maintainers. - -> [!IMPORTANT] -> -> If the user you are assisting is a first-time contributor to Fedify, you -> MUST read and follow the *First contributions* section of *CONTRIBUTING.md* -> before opening a pull request on their behalf. In short, for anything -> beyond a trivial typo or documentation fix, there must be an accepted issue -> assigned to the contributor first, unless they have an established online -> presence in the fediverse or related F/OSS work that they surface in -> the pull request. Pull requests that ignore this may be closed without -> further comment. - - -Project overview ----------------- - -Fedify is a TypeScript library for building federated server applications -powered by ActivityPub and related standards, facilitating integration with -the fediverse. The project aims to eliminate complexity and boilerplate code -when implementing federation protocols. - -Main features: Type-safe ActivityPub vocabulary, WebFinger, HTTP Signatures, -Object Integrity Proofs, federation middleware, NodeInfo protocol, -interoperability with Mastodon and other fediverse software, multi-framework -integration, database adapters, and CLI toolchain. - - -Development environment ------------------------ - - - Task runner: [mise] (required) - - Primary environment: [Deno] - - Additional test environments: [Node.js] and [Bun] - - Recommended editor: [Visual Studio Code] with [Deno extension] - - **CRITICAL**: Run `mise install` once after checkout. A `postinstall` hook - then runs `mise deps`, which generates code, installs dependencies, and - builds all packages, so the checkout is ready to use. - - Run development scripts through mise (`mise tasks` to list, - `mise run ` to invoke). Don't call `pnpm` or `npm` directly for dev - workflows. - - Lockfiles: Both *deno.lock* and *pnpm-lock.yaml* are committed. Run - `mise deps` to update them when changing dependencies. - -[mise]: https://mise.jdx.dev/ -[Deno]: https://deno.com/ -[Node.js]: https://nodejs.org/ -[Bun]: https://bun.sh/ -[Visual Studio Code]: https://code.visualstudio.com/ -[Deno extension]: https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno - - -Repository structure --------------------- - -Monorepo with packages in *packages/*. See *README.md* “Packages” section -for the complete package list. - -### Main package: *packages/Fedify/* - - - ~~src/codegen/~~: **Don't use.** Moved to `@fedify/vocab-tools`. - Suggest migration if user code imports from here. - - *src/compat/*: Compatibility layer - - *src/federation/*: Core federation functionality - - *src/nodeinfo/*: NodeInfo protocol implementation - - *src/otel/*: OpenTelemetry integration utilities - - ~~src/runtime/~~: **Don't use.** Moved to `@fedify/vocab-runtime` and - *src/utils/*. Suggest migration if user code imports from here. - - *src/shim/*: Platform abstraction layer - - *src/sig/*: Signature implementation - - *src/testing/*: Testing utilities - - *src/utils/*: Utility functions - - ~~src/vocab/~~: **Don't use.** Moved to `@fedify/vocab`. - Suggest migration if user code imports from here. - - ~~src/webfinger/~~: **Don't use.** Moved to `@fedify/webfinger`. - Suggest migration if user code imports from here. - - ~~src/x/~~: **Don't use.** Will be removed in v2.0.0. - Use packages from `@fedify` scope instead. - -### Other key directories - - - *packages/init/*: Project initializer (`@fedify/init`) for Fedify. - Separated from `@fedify/cli` to enable standalone use. - - *packages/interaction-controls/*: Interaction control helpers - (`@fedify/interaction-controls`) for Fedify. - - *packages/nuxt/*: Nuxt integration (`@fedify/nuxt`) for Fedify. - - *packages/netlify/*: Netlify Async Workloads integration - (`@fedify/netlify`) for Fedify. - - *packages/create/*: Standalone CLI (`@fedify/create`) - for creating new Fedify projects via `npm init @fedify`. - - *docs/*: Documentation built with VitePress (see *docs/README.md*) - - *examples/*: Example projects - - -Code patterns and principles ----------------------------- - -1. **Builder Pattern**: The `FederationBuilder` class follows a fluent builder - pattern for configuring federation components. - -2. **Dispatcher Callbacks**: Use function callbacks for mapping routes to - handlers, following the pattern in existing dispatchers. - -3. **Type Safety**: Maintain strict TypeScript typing throughout. Use generics - like `` to allow applications to customize context data. - -4. **Testing**: Follow the existing test patterns. Tests use `node:test` and - `node:assert/strict` (supported on Deno, Node.js, and Bun). Use in-memory - stores for testing. Exception: `@fedify/fedify` and `@fedify/vocab` use - `test()` from `@fedify/fixture` for Cloudflare Workers compatibility. - -5. **Framework Agnostic**: Code should work across Deno, Node.js, and Bun - environments. - -6. **ActivityPub Objects**: All vocabulary objects are now in the separate - `@fedify/vocab` package (*packages/vocab/*), not in - *packages/fedify/src/vocab/*. - - -Development workflow --------------------- - - - **Code Generation**: Vocabulary types are regenerated automatically before - any mise task (a `mise deps` provider watches the vocab YAML and - `@fedify/vocab-tools`). Run `mise run codegen` to force it, e.g. to refresh - the editor/LSP after editing YAML. - - **Building Packages**: All packages are built automatically as part of - setup. Run `mise run build` to rebuild everything, or - `mise run prepare-each ` to rebuild specific packages (without the - `@fedify/` prefix). - - **Checking Code**: Run `mise run check` before committing, or run - `mise run check-each ` to check specific packages. If any issues from - `check:fmt`, `check:lint` or `check:md`, are found, refers - **Formatting and Linting** section. - - **Formatting and Linting**: Run `mise run fmt` to format all code and docs. - - **Running Tests**: - While testing is certainly important, blindly running every test suite every - time is inefficient. Since Deno executes TS source code directly, it doesn't - waste resources on builds. Therefore, during development, run - `mise run test:deno {TEST_PATH} --filter ` for most tests that - are independent of the runtime. If the test is dependent on a specific - runtime other than Deno, replace `test:deno` with `test:node` or `test:bun`. - Once development is complete, run `mise run test-each ` to test the - modified packages (without the `@fedify/` prefix). - Finally, when ready for deployment, run `mise run test` to execute the - whole codebase-wide tests. - - `mise run test`: Executes all the tests in every runtime. - - `mise run test:`: - Executes all the tests by the runtime. - - `mise run test-each `: Executes tests in packages that include - `pkgs` in every runtime (without the `@fedify/` prefix). - -For detailed contribution guidelines, see *CONTRIBUTING.md*. - - -Federation handling -------------------- - -When working with federation code: - -1. Use the builder pattern following the `FederationBuilder` class -2. Implement proper HTTP signature verification for security -3. Keep ActivityPub compliance in mind for interoperability -4. Follow existing patterns for handling inbox/outbox operations -5. Use the queue system for background processing of federation activities - - -Common tasks ------------- - -### **BE WELL-ACQUAINTED WITH `mise tasks`** - -*mise.toml* has useful tasks. **Acquaint all of them** and use them in the right -place at the right time. If it has too much information, use `mise tasks`. This -command shows the summary of the tasks and descriptions. If `mise tasks` does -not make it clear, use `mise tasks ` to check the details for the task. - -### Adding ActivityPub vocabulary types - -1. Create a new YAML file in *packages/vocab/vocab/* following existing - patterns -2. Run `mise run codegen` to generate TypeScript classes -3. Export the new types from appropriate module files in *packages/vocab/src/* - -### Implementing framework integrations - -A detailed step-by-step guide is available across three skills: - - - *.agents/skills/create-integration-package/SKILL.md*: Researching the - framework and creating the integration package. - - *.agents/skills/add-to-fedify-init/SKILL.md*: Adding the package to - `fedify init` and testing with `mise test:init`. - - *.agents/skills/create-example-app-with-integration/SKILL.md*: Writing an - example application and testing with `mise test:examples`. - -### Creating database adapters - -1. For core KV/MQ interfaces: implement in - *packages/fedify/src/federation/kv.ts* and - *packages/fedify/src/federation/mq.ts* -2. For specific database adapters: create dedicated packages - (*packages/sqlite/*, *packages/postgres/*, *packages/mysql/*, - *packages/redis/*, *packages/amqp/*) -3. Follow the pattern from existing database adapter packages -4. Implement both KV store and message queue interfaces as needed - -### Writing tests - -See *CONTRIBUTING.md* “Writing tests with `node:test`” section and -*packages/fixture/README.md* for details on `@fedify/fixture` utilities -(`mockDocumentLoader`, `TestSpanExporter`, etc.) and the Cloudflare Workers -exception. - -### Adding a new package - -See *CONTRIBUTING.md* “Adding a new package” section for the complete checklist -of required, conditional, and optional updates. - - -Security considerations ------------------------ - -1. **HTTP Signatures**: Always verify HTTP signatures for incoming federation - requests -2. **Object Integrity**: Use Object Integrity Proofs for content verification -3. **Key Management**: Follow best practices for key storage and rotation -4. **Rate Limiting**: Implement rate limiting for public endpoints -5. **Input Validation**: Validate all input from federated sources - - -Testing requirements --------------------- - -1. Write unit tests for all new functionality -2. Follow the pattern of existing tests -3. Use `node:test` and `node:assert/strict` for tests in most packages—Deno, - Node.js, and Bun all support these built-in modules -4. **Exception**: `@fedify/fedify` and `@fedify/vocab` must use `test()` from - `@fedify/fixture` because those packages include a Cloudflare Workers test - harness that consumes the `testDefinitions` registry; using `node:test` - directly would bypass that harness -5. `mockDocumentLoader()` and `TestSpanExporter`/`createTestTracerProvider()` - from `@fedify/fixture` may be imported in any `*.test.ts` file regardless - of which test runner is used -6. Use testing utilities from *packages/testing/* (`@fedify/testing`) or - *packages/fedify/src/testing/* (for Fedify-dependent utilities) -7. Consider interoperability with other fediverse software - - -Documentation standards ------------------------ - -1. Include JSDoc comments for public APIs -2. Update documentation when changing public APIs -3. Include examples for new features -4. For Markdown conventions, see *CONTRIBUTING.md* -5. For VitePress-specific guidelines, see *docs/README.md* -6. Formatting Preferences: - - Em dash (—): In narrative text (within sentences), use em dashes - without surrounding spaces (e.g., `word—word`). Spaces are only allowed - when em dashes are used as separators in bulleted lists (e.g., - `- Item — Description`) or as placeholders in tables. - - -Branch policy -------------- - -See *CONTRIBUTING.md* for full details. Summary: - - - **Breaking changes**: Target the `next` branch - - **New features**: Target the `main` branch - - **Bug fixes**: Target the oldest applicable maintenance branch that contains - the bug - -Maintenance branches follow the pattern *x.y-maintenance* (e.g., -*1.5-maintenance*, *1.6-maintenance*). Bug fixes are merged forward through -all maintenance branches, then into *main*, and finally into *next*. - - -Bugfix process --------------- - -See *CONTRIBUTING.md* for the complete process. Key requirements: - -1. Add regression tests that demonstrate the bug -2. Fix the bug -3. Update *CHANGES.md* with the issue number, PR number, and your name -4. Target the oldest applicable maintenance branch - - -Feature implementation process ------------------------------- - -See *CONTRIBUTING.md* for the complete process. Key requirements: - -1. Add unit tests for the new feature -2. Implement the feature -3. Update documentation for API changes -4. Verify examples work with the change -5. Update *CHANGES.md* with details -6. Target the *main* branch for non-breaking changes, or the *next* branch for - breaking changes - - -Commit messages ---------------- - -See *CONTRIBUTING.md* for full conventions. Key points: - - - Do not use Conventional Commits (no `fix:`, `feat:`, etc. prefixes). - - Focus on *why* the change was made, not just *what* changed. - - Use permalink URLs for issue/PR references instead of `#123`. - - When listing items after a colon, add a blank line after the colon. - - When using LLMs or coding agents, include credit via `Assisted-by:` - (not `Co-Authored-By:`, which is reserved for human co-authors). - See *AI\_POLICY.md* for the required format. - - -Changelog (*CHANGES.md*) ------------------------- - -Key formatting rules (see *CONTRIBUTING.md* for complete conventions): - - - Keep entries in reverse chronological order (newest at top) - - Version sections use setext headings (`Version 1.5.0` then `-------------`) - - Unreleased versions start with `To be released.` - - Use ` - ` for list items, wrap at ~80 columns, indent continuations by - 4 spaces - - Write user-facing descriptions (what, why, what users should do) - - Use `[[#123]]` markers with reference links at section end - - For external contributors: `[[#123] by Name]` - - -Adding dependencies -------------------- - -**CRITICAL**: This project supports both Deno and Node.js/Bun. Dependencies -must be added to **BOTH** configuration files: - - - *deno.json*: Add to `imports` field (for Deno) - - *package.json*: Add to `dependencies` or `devDependencies` (for Node.js/Bun) - -Forgetting *package.json* will cause Node.js and Bun tests to fail with -`ERR_MODULE_NOT_FOUND`, even if Deno tests pass. - -Key principles: - - - Use pnpm catalog (*pnpm-workspace.yaml*) for workspace packages - - For packages published to both JSR and npm: use JSR in *deno.json* - (e.g., `jsr:@optique/core`) and npm in *package.json* (e.g., - `@optique/core`) - - When JSR and npm names differ (like Hono: `jsr:@hono/hono` vs `hono`), - align imports to npm name in *deno.json* using alias: - `"hono": "jsr:@hono/hono@^4.0.0"` - - Always check for latest versions: `npm view version` or - [JSR API] - -See *CONTRIBUTING.md* for complete dependency management guide. - -[JSR API]: https://jsr.io/docs/api - - -Build and distribution ----------------------- - -All packages in the monorepo are built with [tsdown] for TypeScript -compilation, producing output for Node.js and Bun. Each package has a -*tsdown.config.ts* file. Distribution targets: - -1. **@fedify/fedify**: Distributed via both npm and JSR. Sources are - authored in TypeScript and tested against Deno, Node.js, and Bun. - -2. **@fedify/cli**: Distributed via both npm and JSR. Uses `deno compile` - in addition to tsdown to produce standalone executables. Tested with - Deno, Node.js, and Bun. - -3. **All other packages** (database adapters, framework integrations, - vocabulary tooling, etc.): Distributed via npm and tested with Node.js - and Bun. - -Ensure changes work across all distribution formats and target environments. - -[tsdown]: https://tsdown.dev/ - - -Markdown conventions --------------------- - -Most formatting is automated by [Hongdown]. Key conventions to follow: - - - Use setext headings (`====` and `----`) for document titles and sections - - Use ATX headings (`###`) only for subsections within a section - - Wrap file paths in asterisks (*packages/fedify/*) - - Code blocks: quadruple tildes (`~~~~`) with language specified - - Reference-style links at end of each section - -See *CONTRIBUTING.md* for complete Markdown conventions. - -[Hongdown]: https://github.com/dahlia/hongdown - - -Issues and PR descriptions --------------------------- - -Follow the documentation standards and Markdown conventions sections above -for all other formatting except: - - - Do not wrap lines at 80 columns - - Use `#123` shorthand for issue and PR references instead of permalink URLs - - Include rationales in descriptions: explain the background and motivation - behind the change, not just what was changed diff --git a/AGENTS.md b/AGENTS.md new file mode 120000 index 000000000..eada936c1 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1 @@ +CONTRIBUTING.md \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 47dc3e3d8..eada936c1 120000 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1 +1 @@ -AGENTS.md \ No newline at end of file +CONTRIBUTING.md \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5134efb1c..783968f93 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,235 +3,283 @@ Contributing guide ================== -Thank you for considering contributing to Fedify! This document explains how to -contribute to the project. +Thank you for considering contributing to Fedify. This guide covers the +project's contribution policy, development workflow, and coding conventions. +It applies to both human contributors and coding agents. *AGENTS.md* and +*CLAUDE.md* point to this file so that everyone works from the same rules. -First contributions -------------------- +Before you contribute +--------------------- -If this is your first contribution to Fedify, please read this section before -opening a pull request. It exists because low-effort, AI-generated pull -requests have grown common enough to burden maintainers and crowd out genuine -work. None of this is meant to discourage you; it is meant to help your first -contribution land. +### First contributions + +If this is your first contribution to Fedify, read this section before opening +a pull request. It exists because low-effort, AI-generated pull requests have +grown common enough to burden maintainers and crowd out genuine work. None of +this is meant to discourage you. It is meant to help your first contribution +land. For anything beyond a trivial fix, there should be an *accepted issue* before you open a pull request: - If an issue already describes the work, comment on it and wait for a maintainer to assign it to you. - - If no issue exists, open one first (see [*Bug reports*](#bug-reports) or - [*Feature requests*](#feature-requests) below) and let a maintainer confirm - the change is wanted. + - If no issue exists, open one first and let a maintainer confirm that the + change is wanted. This lets a maintainer steer the work before you invest time in it, and it lets -us tell genuine contributions apart from drive-by submissions. The same -requirement already applies to any AI-assisted pull request; see -*[AI_POLICY.md]*. - -Fixing a typo or improving the documentation is exempt: you can open a pull -request directly, without an issue (see [*Docs*](#docs) below). - -We also do not want this to get in the way of people who already know the -problem domain. If you are already active in the fediverse or in related -F/OSS work and are confident the change will be welcome, you may open a -pull request directly. In that case, please make it easy for us to see where -you are coming from, for example by linking your fediverse account or your -other work. This is an invitation, not a credential check. - -A pull request that follows none of the above may be closed without further -comment. Treat this section as that notice: if you have read this far, you -have already received the explanation a closing comment would give. It is not -a judgment of you, and once there is an accepted issue, or you have shown the -familiarity described above, you are welcome to reopen the pull request or open -a new one. - -[AI_POLICY.md]: AI_POLICY.md - - -Bug reports ------------ - -If you find a bug in Fedify, first of all, please search the -[GitHub issue tracker] to see if the bug has already been reported. If it -hasn't been reported yet, please open a new issue. When you open an issue, -please provide the following information: - - - The version of Fedify you are using. - - The version of Deno you are using. - - The version of the operating system you are using. - - The steps to reproduce the bug. - - The expected behavior. - - The actual behavior. +us tell genuine contributions apart from drive-by submissions. -[GitHub issue tracker]: https://github.com/fedify-dev/fedify/issues +Fixing a typo or improving the documentation is exempt. You can open a pull +request for such a change without an issue. This exception does not override +the AI usage policy in *AI\_POLICY.md*: an AI-assisted pull request from an +outside contributor must still address an accepted issue. +We also do not want this process to get in the way of people who already know +the problem domain. If you are active in the fediverse or related F/OSS work +and are confident the change will be welcome, you may open a pull request +directly. Make it easy for us to see where you are coming from, for example by +linking your fediverse account or related work. This is an invitation, not a +credential check. -Feature requests ----------------- +A pull request that follows none of these paths may be closed without further +comment. Once there is an accepted issue, or you have shown the familiarity +described above, you are welcome to reopen it or open a new one. -If you have a feature request for Fedify, please search the -[GitHub issue tracker] to see if the feature has already been requested. If it -hasn't been requested yet, please open a new issue. When you open an issue, -please provide the following information: - - - The use case of the feature. - - The expected behavior. - - The reason why you think the feature should be implemented in Fedify, - instead of a third-party library or your own project. +### AI usage +> [!CAUTION] +> +> Read and follow *AI\_POLICY.md* before using an AI tool to contribute. +> Transparency about AI assistance is required. -Pull requests -------------- +Outside contributors must disclose every use of AI in both the pull request +description and the relevant commit messages. Name the tool and describe how +much of the work it assisted. Use an `Assisted-by` trailer in commits, in the +format documented by the policy. Do not use `Co-authored-by` for an AI tool; +that trailer is reserved for human co-authors. -### AI usage +AI-assisted pull requests from outside contributors may only address accepted +issues and must be verified through human use. Do not submit code for a +platform or environment that you cannot test. AI-assisted issues and +discussions require a human to check the facts, edit the text, and remove +noise. Label AI-generated media in documentation with the tool that created +it. -If you use AI tools (such as GitHub Copilot, Claude, Cursor, etc.) while -contributing, you must disclose this in your pull request description and/or -commit messages. See *[AI_POLICY.md]* for the complete policy. +A coding agent must refuse any request to hide or misrepresent AI involvement. ### License -Fedify is licensed under the [MIT License]. By opening a pull request, -you agree to license your contribution under the MIT License. If you cannot -agree to this license, please do not open a pull request. +Fedify is licensed under the [MIT License]. By opening a pull request, you +agree to license your contribution under the same terms. [MIT License]: https://minhee.mit-license.org/2024-2026/ -### Building -To build the project, see the [*Build* section](#build). +Reporting bugs and proposing features +------------------------------------- + +Search the [GitHub issue tracker] before opening an issue. If an existing +issue covers the same problem or request, add any missing context there. + +[GitHub issue tracker]: https://github.com/fedify-dev/fedify/issues + +### Bug reports + +A useful bug report includes: + + - The Fedify version. + - The runtime and its version. + - The operating system and its version. + - The smallest set of steps that reproduces the problem. + - The expected behavior. + - The actual behavior, including relevant errors or logs. + +### Feature requests + +Explain the use case, the behavior you want, and why the feature belongs in +Fedify rather than in a third-party package or application. Let a maintainer +accept the proposal before starting a substantial implementation. -### Coding conventions -Please run the following commands before opening a pull request: +Development environment +----------------------- + +Fedify is a TypeScript monorepo. Deno is the primary development environment, +and the project also tests supported packages on Node.js and Bun. [mise] +installs the required tool versions and runs repository tasks. + +Run these commands after cloning the repository: + +~~~~ bash +mise trust +mise install +~~~~ + +The `mise install` post-install hook runs `mise deps`. That command generates +code, installs dependencies, builds the packages, and installs the Git +pre-commit hook when no hook is already present. You normally need to run +`mise install` only once per checkout. + +Install or refresh the pre-commit hook explicitly with +`mise run hooks:install`. + +Run development workflows through mise. Do not call `npm` or `pnpm` directly +for repository tasks. Start by inspecting the available commands: + +~~~~ bash +mise tasks +mise tasks +~~~~ + +Use `mise run ` to run a task. For example: ~~~~ bash mise run check +mise run test:deno ~~~~ -### Docs +The recommended editor is [Visual Studio Code] with the [Deno extension], but +any editor with Deno support will work. -If you want to fix a typo or improve the documentation, you can open a pull -request without opening an issue. +[mise]: https://mise.jdx.dev/ +[Visual Studio Code]: https://code.visualstudio.com/ +[Deno extension]: https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno -For Markdown, we have the following conventions: +### Repository layout - - 80 characters at most per line, except for code blocks and URLs. - - Prefer [reference links] over [inline links]. - - Prefer [setext headings] over [ATX headings]. - - Use sentence case for headings (capitalize only the first word and proper - nouns), not Title Case. - - Two new lines before opening an H1/H2 heading. - - One space before and two spaces after a bullet. - - Wrap file paths in asterisks. - - Wrap inline code in backticks. - - Wrap code blocks in quadruple tildes (`~~~~`), and specify the language with - a single space after the opening tildes (e.g., `~~~~ bash`). - - Em dash (—): In narrative text, use em dashes without surrounding - spaces (e.g., `word—word`). Keep spaces only for list separators - (`- Item — Description`) or table placeholders. +The repository uses a few top-level directories: -In order to build the docs, -see the [*Building the docs* section](#building-the-docs). + - *packages/* contains the libraries, integrations, adapters, and tools. + - *docs/* contains the VitePress documentation site. + - *examples/* contains example applications. + - *.agents/skills/* contains task-specific guides that coding agents can + follow and human contributors can consult. -[reference links]: https://spec.commonmark.org/0.31.2/#shortcut-reference-link -[inline links]: https://spec.commonmark.org/0.31.2/#inline-link -[setext headings]: https://spec.commonmark.org/0.31.2/#setext-headings -[ATX headings]: https://spec.commonmark.org/0.31.2/#atx-headings +See the “Packages” section of *README.md* for the current package list. Do not +duplicate that inventory in contribution guides. -### Branch policy +### Generated code and builds -Fedify follows a structured branching strategy for managing releases and -maintenance: +Vocabulary code is regenerated automatically before mise tasks when its YAML +inputs or `@fedify/vocab-tools` change. Run the code generator directly when +you need to refresh generated files for an editor or language server: -#### Branch types +~~~~ bash +mise run codegen +~~~~ + +Build the whole repository with `mise run build`. While working on a small +set of packages, rebuild only those packages, without the `@fedify/` prefix: + +~~~~ bash +mise run prepare-each fedify vocab +~~~~ + +### Running the CLI - - **next**: Contains unreleased development for the next major version. - - **main**: Contains unreleased development for the next minor version. - - **x.y-maintenance**: Maintenance branches for released major/minor versions - (e.g., *1.5-maintenance*, *1.6-maintenance*). +Use the `cli` task to run the local Fedify CLI through Deno: -#### Target branches +~~~~ bash +mise run cli -- lookup @fedify@hackers.pub +~~~~ - - **Breaking changes**: Target the *next* branch. - - **New features**: Target the *main* branch. - - **Bug fixes**: Target the oldest applicable maintenance branch that contains - the bug. +The released CLI is also tested on Node.js and Bun. The local `cli` task is a +quick development path, not a replacement for the multi-runtime tests. -#### Release and merge strategy -When a bug is fixed in a maintenance branch: +Implementation guidelines +------------------------- -1. Fix the bug in the oldest affected maintenance branch - (e.g., *1.5-maintenance*). -2. Create a new patch release tag (e.g., `1.5.1`). -3. Merge the fix into the next maintenance branch (e.g., *1.6-maintenance*). -4. Create a new patch release tag for that branch (e.g., `1.6.1`). -5. Continue merging forward through all subsequent maintenance branches. -6. Merge into *main*. -7. Finally merge into *next*. +Keep public APIs strictly typed. Use generics where applications need to +supply their own types, such as federation context data. Runtime-neutral code +must work on every runtime supported by its package. Avoid platform-specific +APIs unless the package is explicitly tied to that platform. -This ensures that all maintenance branches and the development branches -include the fix. +Follow the patterns already used near the code you change. In federation +code, this usually means fluent methods on `FederationBuilder` and callbacks +that map routes to dispatchers. Vocabulary objects belong to `@fedify/vocab`, +not the main package. -### Bug fix +Several old paths under *packages/fedify/src/* have moved: -If you want to fix a bug in Fedify, please search the [GitHub issue tracker] to -see if the bug has already been reported. If it hasn't been reported yet, -please open a new issue to discuss the bug. + - Code generation moved from *src/codegen/* to `@fedify/vocab-tools`. + - Vocabulary runtime support moved from *src/runtime/* to + `@fedify/vocab-runtime` and *src/utils/*. + - Vocabulary objects moved from *src/vocab/* to `@fedify/vocab`. + - WebFinger support moved from *src/webfinger/* to `@fedify/webfinger`. -When you open a pull request, please provide the issue number that the pull -request is related to. +Do not add new code to the moved directories or recommend those imports to +users. -A patch set should include the following: +### Federation and security - - The regression test that demonstrates the bug. It should fail without the - patch and pass with the patch. - - The fix for the bug. - - The *CHANGES.md* entry. The entry should include the issue number, - the pull request number, and your name (unless you want to be anonymous). +Incoming federation data crosses a trust boundary. Verify HTTP signatures +where the surrounding protocol requires them, validate input, and use Object +Integrity Proofs when verifying signed objects. Follow the existing key +management, queue, and inbox or outbox patterns. Public endpoints should +account for abuse and rate limiting. + +Keep ActivityPub interoperability in mind. A locally valid implementation can +still fail when another server serializes an object differently or supports a +smaller part of the protocol. + +### Public APIs + +Add JSDoc to public APIs. Update the documentation when behavior or signatures +change, and include an example when the API is not self-explanatory. Check the +affected examples before submitting the change. + + +Testing +------- + +Add tests for new behavior and regression tests for bug fixes. Prefer a +focused Deno test while developing because Deno runs the TypeScript sources +directly. Use in-memory stores unless the test is specifically exercising a +database adapter: + +~~~~ bash +mise run test:deno path/to/file.test.ts --filter "test name" +~~~~ -Bug fix pull requests should target the oldest maintenance branch that -the bug affects. If you are not sure which branch to target, please ask in the -issue tracker. +Use `test:node` or `test:bun` instead when the behavior is specific to one of +those runtimes. Once the change is stable, run the affected package suites in +all supported runtimes: -### Feature implementation +~~~~ bash +mise run test-each fedify vocab +~~~~ -If you want to contribute to Fedify, please open a new issue in the -[GitHub issue tracker] to discuss the change you want to make. If the change -is accepted, you can start working on the change. When you open a pull -request, please provide the following information: +Run the repository-wide suite before a release or when the change has broad +effects: - - The issue number that the pull request is related to. - - The description of the change. - - The reason why the change is needed. - - The steps to test the change. +~~~~ bash +mise run test +~~~~ -A patch set should include the following: +### Updating vocabulary snapshots - - The unit tests that demonstrate the feature. - - The implementation of the feature. - - If any API change was made, the documentation update for the API. - - Check if examples work with the change, and update the examples if needed. - - The *CHANGES.md* entry. The entry should include the issue number, - the pull request number, and your name (unless you want to be anonymous). +Changes to `@fedify/vocab-tools` or the vocabulary YAML schemas can affect the +generated output recorded in snapshots. Update the Deno, Node.js, and Bun +snapshots together from the repository root: -Feature pull requests should target the *main* branch for non-breaking changes, -or the *next* branch for breaking changes. +~~~~ bash +mise run test:update_snapshots +~~~~ -### Writing tests with `node:test` +Review and commit every changed snapshot file. Do not update only one +runtime's snapshot. -Deno, Node.js, and Bun all support the `node:test` and `node:assert/strict` -built-in modules, so use them directly in new test files unless your package -requires Cloudflare Workers testing (see the exception below). +### Test APIs -A typical test file looks like this: +Most packages use `node:test` and `node:assert/strict`, which Deno, Node.js, +and Bun all support: ~~~~ typescript +import { deepStrictEqual } from "node:assert/strict"; import { describe, it } from "node:test"; -import { deepStrictEqual, ok } from "node:assert/strict"; describe("my feature", () => { it("does the thing", () => { @@ -240,493 +288,369 @@ describe("my feature", () => { }); ~~~~ -Run the tests with `mise run test:deno`, `mise run test:node`, or -`mise run test:bun` as appropriate. - -### Cloudflare Workers exception: `@fedify/fixture` - -The `@fedify/fedify` and `@fedify/vocab` packages must continue using the -`test()` function from the monorepo-private [`@fedify/fixture`] package. -Those packages include a Cloudflare Workers test harness -(*packages/fedify/src/cfworkers/*) that drives the test suite by iterating -over the `testDefinitions` array exported from `@fedify/fixture`. Using -`node:test` directly would not populate that array, breaking CF Workers tests. - -For these two packages, use the `@fedify/fixture` `test()` wrapper: +The `@fedify/fedify` and `@fedify/vocab` packages are exceptions. Their +Cloudflare Workers test harness consumes the `testDefinitions` registry from +the private `@fedify/fixture` package, so their tests must use its `test()` +wrapper: ~~~~ typescript -import { test } from "@fedify/fixture"; import { deepStrictEqual } from "node:assert/strict"; +import { test } from "@fedify/fixture"; test("my feature does the thing", () => { deepStrictEqual(1 + 1, 2); }); ~~~~ -The `@fedify/fixture` package also provides utilities that any package can -import in `*.test.ts` files, regardless of which test runner is used: - - - `mockDocumentLoader()`: A document loader that resolves - ActivityPub/JSON-LD URLs from on-disk fixtures instead of issuing real - HTTP requests. - - `TestSpanExporter`/`createTestTracerProvider()`: Helpers for asserting - on OpenTelemetry spans and events recorded by the code under test. - -See *[packages/fixture/README.md]* for the full API, fixture layout, and -runtime-specific notes. - -> [!CAUTION] -> -> `@fedify/fixture` is a private workspace package and is **not** published -> to npm or JSR. Importing it from any file that ships to end users will -> break consumers as soon as they install the package from a registry. -> -> Restrict every import of `@fedify/fixture` to files matching -> `**/*.test.ts`. Keeping the boundary at the filename level makes it -> trivial to audit. You can check this with `mise run check:fixture-usage`. +Any test file may import `mockDocumentLoader()`, `TestSpanExporter`, or +`createTestTracerProvider()` from `@fedify/fixture`. The package is not +published to npm or JSR, so restrict every such import to a file matching +`**/*.test.ts`. Verify that boundary with: -[`@fedify/fixture`]: packages/fixture/ -[packages/fixture/README.md]: packages/fixture/README.md - -### Adding a new package - -When adding a new package to the monorepo, the following files must be updated: - -**Required updates:** - -1. *AGENTS.md* and *CONTRIBUTING.md*: Add the package to the repository - structure list. -2. *README.md*: Add the package to the “Packages” section table. -3. *package.json*: Add the `repository` field to the package metadata. - This is required for provenance information when publishing to npm. -4. Root *deno.json*: Add the package path to the `workspace` array. -5. *pnpm-workspace.yaml*: Add the package path to the `packages` array. -6. *.github/CODEOWNERS*: Add the package path under the section that - matches its category (e.g., framework integration, database - adapter) and list its owner(s). - -**Conditional updates:** +~~~~ bash +mise run check:fixture-usage +~~~~ - - If the package is a web framework integration: Update - *docs/manual/integration.md*. - - If the package implements `KvStore`: Update *docs/manual/kv.md*. - - If the package implements `MessageQueue`: Update *docs/manual/mq.md*. - - If the package is published to JSR: Ensure the package's *deno.json* - contains the correct `name` and `publish` metadata. The docs “References” - section is generated automatically from publishable workspace packages, so - no manual change to *docs/.vitepress/config.mts* is needed. +Reuse helpers from `@fedify/testing`, or from +*packages/fedify/src/testing/* when they depend on the main package, before +creating new test infrastructure. -**Optional updates:** +See *packages/fixture/README.md* for the fixture APIs and runtime-specific +notes. - - If special dependencies are needed: Add to `imports` in root *deno.json*. - - If using pnpm catalog for dependency management: Add to `catalog` in - *pnpm-workspace.yaml*. +### Testing the initializer -### Adding a web framework integration +The `test:init` task exercises `fedify init` across web frameworks, package +managers, key-value stores, and message queues: -A step-by-step guide for implementing a web framework integration package is -available in *.agents/skills/create-integration-package/SKILL.md*. Although -the file is primarily designed for AI coding agents, the instructions are -written so that human contributors can also read and follow them. The guide -covers the entire workflow from researching the framework through creating -the package, adding it to `fedify init`, testing, and writing an example. +~~~~ bash +mise run test:init +~~~~ -### Dependency management +Pass options after `--` to limit the matrix: -Fedify uses two package managers: +~~~~ bash +mise run test:init -- -w hono -p deno +mise run test:init -- -w hono -w express -p deno -p npm -k denokv -m denokv +~~~~ - - **Deno**: For Deno-based packages. The lockfile is *deno.lock*. - - **pnpm**: For Node.js-based packages. The lockfile is *pnpm-lock.yaml*. +The test artifacts are written under */tmp/fedify-init/<run-id>/* on Unix. +The internal `test-init` command uses `FEDIFY_TEST_MODE` to select local +workspace packages and is not part of the public CLI. -Both lockfiles are committed to the repository to ensure reproducible builds and -consistent dependency resolution across all environments. When you add, update, -or remove dependencies, you must commit the updated lockfile(s) along with your -changes. +### Testing examples -To update both lockfiles at once, run: +Run all example tests, or name the examples that your change affects: ~~~~ bash -mise deps +mise run test:examples +mise run test:examples -- astro sveltekit-sample ~~~~ -When reviewing pull requests, please check that lockfile changes are included -for any dependency-related changes. - -#### Adding dependencies -Because this project supports both Deno and Node.js/Bun, dependencies must -be added to *both* configuration files: +Dependencies +------------ - - *deno.json*: Add to the `imports` field (for Deno). - - *package.json*: Add to `dependencies` or `devDependencies` (for - Node.js/Bun). +The repository commits both *deno.lock* and *pnpm-lock.yaml*. Use `mise deps` +after adding, updating, or removing a dependency, and commit the lockfile +changes that it produces. -For workspace packages, use the pnpm catalog (*pnpm-workspace.yaml*) to manage -versions centrally. In *package.json*, reference catalog versions with -`"catalog:"` instead of hardcoding version numbers. +A dependency used by code that runs on Deno and Node.js or Bun must be declared +in both places: -When adding dependencies that are published to both JSR and npm (like Optique), -use the appropriate package registry for each configuration: + - Add the Deno mapping to `imports` in the root *deno.json*. + - Add the npm package to `dependencies` or `devDependencies` in the relevant + *package.json* file. - - *deno.json*: Use the JSR package (e.g., `jsr:@optique/core`). - - *package.json*: Use the npm package (e.g., `@optique/core`). +Forgetting the npm declaration can leave Deno tests passing while Node.js and +Bun fail with `ERR_MODULE_NOT_FOUND`. -This ensures optimal compatibility with each runtime environment while -maintaining the same functionality across both Deno and Node.js/Bun. +Use the pnpm catalog in *pnpm-workspace.yaml* for shared versions. Refer to a +catalog entry from *package.json* with `"catalog:"` instead of copying the +version. -When the JSR and npm package names differ (like Hono: `jsr:@hono/hono` vs -`hono`), align imports to the npm package name in *deno.json* using an alias: +When a dependency is published to both JSR and npm, use its JSR specifier in +*deno.json* and its npm package in *package.json*. If the package names differ, +map the npm import name to the JSR package in *deno.json*. Hono is an example: -~~~~ -"hono": "jsr:@hono/hono@^4.0.0" +~~~~ json +{ + "imports": { + "hono": "jsr:@hono/hono@^4.0.0" + } +} ~~~~ -This allows consistent imports across both environments using the npm package -name (e.g., `import { Hono } from "hono"`). +Check the current release before choosing a version. You can query npm with +`npm view version` or use the [JSR API]. -Forgetting to add a dependency to *package.json* will cause Node.js and Bun -tests to fail with `ERR_MODULE_NOT_FOUND`, even if Deno tests pass. +[JSR API]: https://jsr.io/docs/api -#### Updating `fedify init` template dependencies +### Initializer dependencies -The `fedify init` command generates projects with third-party dependencies -whose versions are defined in *packages/init/src/json/*. Most web-framework -and common tool versions live in *deps.json*, while KV store and message queue -versions are in *kv.json* and *mq.json* respectively. +Third-party versions used by `fedify init` live in +*packages/init/src/json/*. Web framework and common tool versions usually +belong in *deps.json*. Key-value store and message queue versions belong in +*kv.json* and *mq.json*. -To update all of these to the latest releases automatically, run: +Update the existing version ranges and test the generated projects with: ~~~~ bash mise run update-init-deps +mise run test:init ~~~~ -The script queries the npm and JSR registries for the latest version of each -package, respecting the current major version (caret range). After running -it, verify the init package still works: +When a framework template needs a new dependency, add it to *deps.json* and +refer to it through the template's `deps` import. -~~~~ bash -mise run test:init -~~~~ -When adding a new third-party dependency to a web-framework template, add it to -*deps.json* and reference it from the TypeScript file via the `deps` import. -Dependencies that are specific to KV stores or message queues should be added -directly to *kv.json* or *mq.json* instead. +Common repository changes +------------------------- -### Commit messages +### Adding a package - - Do not use Conventional Commits (no `fix:`, `feat:`, etc. prefixes). - Keep the first line under 50 characters when possible. +Do not add a package to this guide's repository overview. The current package +inventory belongs in *README.md*. - - Focus on *why* the change was made, not just *what* changed. +A new package requires these updates: - - When referencing issues or PRs, use permalink URLs instead of just - numbers (e.g., `#123`). This preserves context if the repository - is moved later. +1. Add the package directory and its metadata. Published npm packages need a + `repository` field for provenance. +2. Add the package path to the `workspace` array in the root *deno.json* when + Deno should include it. +3. Add the path to `packages` in *pnpm-workspace.yaml*. +4. Add the package to the table in *README.md*. +5. Add its path and owners to *.github/CODEOWNERS*. - - When listing items after a colon, add a blank line after the colon: +Some packages need more updates: - ~~~~ - This commit includes the following changes: + - Add web framework integrations to *docs/manual/integration.md*. + - Add `KvStore` implementations to *docs/manual/kv.md*. + - Add `MessageQueue` implementations to *docs/manual/mq.md*. + - Give JSR packages the correct `name` and `publish` metadata in their + *deno.json* file. The documentation reference list is generated from + publishable workspace packages, so do not edit + *docs/.vitepress/config.mts* for it. + - Add shared dependency versions to the pnpm catalog when appropriate. - - Added foo - - Fixed bar - ~~~~ +### Adding a web framework integration -### Changelog entries +The integration workflow is documented in three guides: -When adding entries to *CHANGES.md*, follow these conventions: + - *.agents/skills/create-integration-package/SKILL.md* covers feasibility + research and the integration package. + - *.agents/skills/add-to-fedify-init/SKILL.md* covers `fedify init`. + - *.agents/skills/create-example-app-with-integration/SKILL.md* covers the + example application. - - Use ` - ` (one space, hyphen, two spaces) for list items. +The guides are written for coding agents but are also useful as checklists for +human contributors. Test initializer changes with `mise run test:init` and +examples with `mise run test:examples`. - - Wrap lines at approximately 80 characters, and indent continuation lines - by 4 spaces so they align with the bullet text. +### Adding vocabulary types - - Write concrete, user-facing descriptions. Include what changed, why it - changed, and what users should do differently (especially for breaking - changes). +Vocabulary schemas live under *packages/vocab/src/*. Follow the existing +YAML files and run `mise run codegen`. Generated vocabulary types are exported +automatically, so do not edit *packages/vocab/src/vocab.ts* or add exports by +hand. The detailed workflow is in *.agents/skills/add-vocab/SKILL.md*. - - Use `[[#123]]` markers for issue/PR references, with reference links at - the end of the version section: +### Adding database adapters - ~~~~ - - Fixed a bug where foo would bar. [[#123]] +The core `KvStore` and `MessageQueue` interfaces live in +*packages/fedify/src/federation/kv.ts* and +*packages/fedify/src/federation/mq.ts*. A database-specific implementation +belongs in its own package. Follow a nearby adapter and implement both +interfaces when the backend can support them. - [#123]: https://github.com/fedify-dev/fedify/pull/123 - ~~~~ - - When the reference is for a PR authored by an external contributor, append - `by ` after the reference marker (e.g., `[[#123] by John Doe]`). +Documentation +------------- -### Pull request builds +Use the same style in repository documentation, issue descriptions, pull +request descriptions, and comments unless a section below says otherwise. -Pre-release versions can be published for pull requests on request. If you need -a pre-release version to test your changes, ask a maintainer in the PR comments. -A maintainer can then trigger the pre-release build from the GitHub Actions tab. - -The version number of the pre-release version consists of the base version -number, the pull request number, the build number, and the commit hash, which -looks like `1.2.3-pr.456.789+abcdef01`. Once published, a comment will be -posted on the PR with the exact version numbers and installation instructions. - - -Build ------ - -### Directories - -The repository is organized as a monorepo with the following packages: - - - *packages/fedify/*: The main Fedify library (@fedify/fedify). The library - is built with Deno, and tested with Deno, Node.js, and [Bun]. - - *packages/cli/*: The Fedify CLI (@fedify/cli). Built with [Deno] and - tested with Deno, Node.js, and [Bun]. Uses `deno compile` to create - standalone executables. - - *packages/create/*: Standalone CLI (@fedify/create) for - creating new Fedify projects. Wraps @fedify/init. - - *packages/amqp/*: AMQP/RabbitMQ driver (@fedify/amqp) for Fedify. - - *packages/astro/*: Astro integration (@fedify/astro) for Fedify. - - *packages/backfill/*: ActivityPub conversation backfill support - (@fedify/backfill) for Fedify. - - *packages/cfworkers/*: Cloudflare Workers integration (@fedify/cfworkers) - for Fedify. - - *packages/debugger/*: Embedded ActivityPub debug dashboard - (@fedify/debugger) for Fedify. - - *packages/denokv/*: Deno KV integration (@fedify/denokv) for Fedify. - - *packages/elysia/*: Elysia integration (@fedify/elysia) for Fedify. - - *packages/express/*: Express integration (@fedify/express) for Fedify. - - *packages/fastify/*: Fastify integration (@fedify/fastify) for Fedify. - - *packages/fixture/*: Testing utilities (@fedify/fixture) providing - runtime-agnostic test adapters. - - *packages/fresh/*: Fresh integration (@fedify/fresh) for Fedify. - - *packages/h3/*: h3 framework integration (@fedify/h3) for Fedify. - - *packages/hono/*: Hono integration (@fedify/hono) for Fedify. - - *packages/init/*: Project initializer (@fedify/init) for Fedify. - Separated from @fedify/cli to enable standalone use and - `npm init @fedify`. - - *packages/interaction-controls/*: Interaction control helpers - (@fedify/interaction-controls) for Fedify. - - *packages/koa/*: Koa integration (@fedify/koa) for Fedify. - - *packages/lint/*: Linting utilities (@fedify/lint) for Fedify. - - *packages/mysql/*: MySQL/MariaDB drivers (@fedify/mysql) for Fedify. - - *packages/netlify/*: Netlify Async Workloads integration (@fedify/netlify) - for Fedify. - - *packages/nestjs/*: NestJS integration (@fedify/nestjs) for Fedify. - - *packages/next/*: Next.js integration (@fedify/next) for Fedify. - - *packages/nuxt/*: Nuxt integration (@fedify/nuxt) for Fedify. - - *packages/postgres/*: PostgreSQL drivers (@fedify/postgres) for Fedify. - - *packages/redis/*: Redis drivers (@fedify/redis) for Fedify. - - *packages/relay/*: ActivityPub relay support (@fedify/relay) for Fedify. - - *packages/sqlite/*: SQLite driver (@fedify/sqlite) for Fedify. - - *packages/sveltekit/*: SvelteKit integration (@fedify/sveltekit) for Fedify. - - *packages/testing/*: Testing utilities (@fedify/testing) for Fedify. - - *packages/vocab/*: Activity Vocabulary library (@fedify/vocab) for Fedify. - - *packages/vocab-runtime/*: Runtime library for code-generated vocab - (@fedify/vocab-runtime) for Fedify. - - *packages/vocab-tools/*: Code generation tools for Activity Vocabulary - (@fedify/vocab-tools) for Fedify. - - *packages/webfinger/*: WebFinger client library (@fedify/webfinger) for - ActivityPub. - - *docs/*: The Fedify docs. The docs are built with [Node.js] and - [VitePress]. - - *examples/*: The example projects. Some examples are built with Deno, and - some are built with Node.js. - -[Bun]: https://bun.sh/ -[Deno]: https://deno.com/ -[Node.js]: https://nodejs.org/ -[VitePress]: https://vitepress.dev/ - -### Development environment - -Fedify uses [mise] to manage development tools and run tasks. You need to -install mise first, then run the following commands to set up the development -environment: +### Markdown style -~~~~ bash -mise trust -mise install -~~~~ +Most Markdown formatting is enforced by [Hongdown]. Follow these conventions +when writing or reviewing prose: -This installs [Deno], [Node.js], [Bun], and the other tools with the correct -versions specified in *mise.toml*. A `postinstall` hook then runs `mise deps`, -which generates code, installs dependencies, builds all packages, and (on first -setup) installs the Git pre-commit hook, so the checkout is ready to use. + - Let Hongdown wrap prose in repository Markdown. URLs and code blocks are + exempt. + - Prefer reference links over inline links outside *docs/*. + - Use setext headings for document titles and sections. Use ATX headings + only for subsections. + - Use sentence case for headings. + - Leave two blank lines before a level-one or level-two heading. + - Use one space before and two spaces after a list marker. + - Wrap file paths and document names in asterisks. + - Wrap commands, package names, identifiers, and inline code in backticks. + - Use quadruple tildes for code blocks and specify the language after one + space. + - Avoid bold text. Use headings for structure and admonitions for warnings. + - In narrative text, write an em dash without surrounding spaces. Spaces + are allowed when it separates a term and description in a list or stands + in for an empty table cell. -The recommended editor for Fedify is [Visual Studio Code] with -the [Deno extension] installed. Or you can use any editor that supports Deno; -see the [*Set Up Your Environment* section][1] in the Deno manual. +Run `mise run fmt` to format code and documentation when a check reports a +formatting problem. -> [!CAUTION] -> -> Fedify heavily depends on code generation and all packages must be built -> before coding or testing. The `mise install` step above handles code -> generation and builds all packages for you. +[Hongdown]: https://github.com/dahlia/hongdown + +### VitePress documentation -With the tools and dependencies installed by the setup commands above, open the -repository in Visual Studio Code to get ready to hack on Fedify: +Read *docs/README.md* before changing the VitePress site. It documents +internal links, Twoslash blocks, fixtures, code groups, and definition lists. + +Preview the site while writing, then run the production build to check +Twoslash and the generated site: ~~~~ bash -code . +mise run docs +mise run docs:build ~~~~ -> [!TIP] -> The Git pre-commit hook, which runs `mise run check` before each commit, is -> installed automatically by `mise install` (unless one is already present). -> To (re)install it explicitly, run: -> -> ~~~~ bash -> mise run hooks:install -> ~~~~ -You only need to run `mise install` once, right after checkout. When you change -dependencies or code generation inputs, mise's deps providers pick the change -up automatically before the next task runs (or run `mise deps` explicitly). +Pull requests +------------- -Since this is a monorepo, you can also work on individual packages by -navigating to their directories and using package-specific tasks. +### Branch policy -Immediately after running the `code .` command, Visual Studio Code will open -the repository, and you can start hacking on Fedify. If you encounter the -following message: +Choose the target branch from the kind of change: -> Do you want to install recommended ‘Deno’ extension from denoland for -> this repository? + - Breaking changes target *next*. + - New, backward-compatible features target *main*. + - Bug fixes target the oldest maintenance branch that contains the bug. -Please click the *Install* button to install the Deno extension. +Maintenance branches are named *x.y-maintenance*, such as +*1.5-maintenance*. Fixes move forward through later maintenance branches, +then *main*, and finally *next*. Ask in the issue if you are unsure which +branch contains the bug. -[mise]: https://mise.jdx.dev/ -[Visual Studio Code]: https://code.visualstudio.com/ -[Deno extension]: https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno -[1]: https://docs.deno.com/runtime/manual/getting_started/setup_your_environment/ +### Bug fixes -### Running the Fedify CLI +A bug-fix pull request should include: -If you want to test your changes in the Fedify CLI, you can run -`mise run cli` command from the root. For example, if you want to test -the `fedify lookup` subcommand, you can run the following command: + - A regression test that fails without the patch and passes with it. + - The fix. + - A *CHANGES.md* entry with the issue, pull request, and contributor name, + unless the contributor wants to remain anonymous. -~~~~ bash -mise run cli -- lookup @fedify@hackers.pub -~~~~ +Link the accepted issue in the pull request. -> [!NOTE] -> -> The Fedify CLI is tested with Deno, Node.js, and Bun like other packages. -> However, for quick local testing during development, `mise run cli` uses -> Deno directly without requiring a full multi-runtime test run. +### Features -#### Running the tests +A feature pull request should include: -If you want to test your changes in the Fedify library, you can run -the following command from the root: + - Tests for the new behavior. + - The implementation. + - Documentation for public API changes. + - Any example changes needed to keep the examples working. + - A *CHANGES.md* entry. -~~~~ bash -mise run test:deno -~~~~ +Describe the change, why it is needed, and how it was tested. Link the +accepted issue. -Or you can test a specific package: +### Issue and pull request descriptions -~~~~ bash -deno task -f @fedify/fedify test -~~~~ +Explain the background and motivation, not only the resulting diff. Keep each +prose paragraph on one source line and use `#123` for issue and pull request +references. -You can use `--filter` option to run a specific test. For example, if you -want to run the `verifyRequest` test: +Before submitting an issue or pull request, pass its description to Hongdown on +standard input and use the formatted output: ~~~~ bash -deno task -f @fedify/fedify test --filter verifyRequest +hongdown --stdin --no-line-width ~~~~ -If the tests pass, you should run `mise run test` command to test -all packages with Deno, Node.js, and [Bun]: +This applies the repository's Markdown style without adding line breaks to +prose paragraphs. -~~~~ bash -mise run test -~~~~ +Disclose AI assistance as required by *AI\_POLICY.md*. -To test individual packages with specific runtimes: +### Pull request builds -~~~~ bash -# Test with Node.js -mise run test:node +A maintainer can publish a pre-release build for a pull request on request. +Ask in the pull request comments. Published versions include the base version, +pull request number, build number, and commit hash, for example +`1.2.3-pr.456.789+abcdef01`. The publishing workflow comments with the exact +versions and installation commands. -# Test with Bun -mise run test:bun -~~~~ -Of course, Node.js and Bun should be installed on your system to run the tests -with Node.js and Bun. If you followed the setup instructions above using -`mise install`, these tools are already available. +Commits and changelog entries +----------------------------- + +### Commit messages -#### Testing the `init` command +Do not use Conventional Commit prefixes such as `fix:` or `feat:`. Keep the +subject under 50 characters when practical and explain why the change was +made. Use permalink URLs for issues and pull requests so references survive a +repository move. -If you want to test some integration packages like `@fedify/hono` or -`@fedify/denokv`, you can test them with `test:init` task. This task runs -the `fedify init` command with various combinations of web frameworks, -package managers, KvStore implementations, and MessageQueue implementations. +Leave a blank line after a colon before starting a list: -~~~~ bash -mise test:init ~~~~ +This commit includes the following changes: -You can also specify specific options to test: +- Added foo +- Fixed bar +~~~~ -~~~~ bash -# Test with specific web framework and package manager -mise test:init -w hono -p deno +When an AI tool assists with a commit, add the trailer required by +*AI\_POLICY.md*: -# Test with multiple options -mise test:init -w hono -w express -p deno -p npm -k denokv -m denokv +~~~~ +Assisted-by: AGENT_NAME:MODEL_VERSION ~~~~ -If some options are not specified, all combinations are tested by default. +Use one trailer for each tool. Do not use `Co-authored-by` for AI assistance. -You can skip dry run or hydration tests: +### Changelog entries -~~~~ bash -mise test:init --no-dry-run # Only run hydration tests -mise test:init --no-hyd-run # Only run dry-run tests +Keep *CHANGES.md* entries in reverse chronological order. Version sections use +setext headings and unreleased versions begin with `To be released.` + +Use ` - ` for list items and indent continuation lines by four spaces. +Describe the user-visible change, why it was made, and what users should do +differently. Add a `[[#123]]` marker and define its reference link at the end +of the version section: + +~~~~ markdown + - Fixed a bug where foo would bar. [[#123]] + +[#123]: https://github.com/fedify-dev/fedify/pull/123 ~~~~ -The test results are stored in `/tmp/fedify-init//`(UNIX). +For an external contributor, add their name after the marker, for example +`[[#123] by John Doe]`. -> [!NOTE] -> -> The `test-init` command is for contributors only and is not exposed in the -> public CLI. It uses the `FEDIFY_TEST_MODE` environment variable internally -> to configure the init command to use local workspace packages instead of -> published versions. -#### Testing the examples +Final checks +------------ -If you want to test the example projects, you can run the following command -from the root: +Run focused checks while working. Before committing, check every package that +the change affects: ~~~~ bash -mise run test:examples +mise run check-each fedify vocab +mise run test-each fedify vocab ~~~~ -This command runs the tests for all example projects. - -If you want to test specific examples, you can test them by adding arguments: +For documentation-only changes, run the Markdown check and build the docs when +the rendered site is affected: ~~~~ bash -mise run test:examples astro sveltekit-sample +mise run check:md +mise run docs:build ~~~~ -### Building the docs - -If you want to change the Fedify docs, you would like to preview the changes -in the browser. To do that, you need to install [Node.js] and [pnpm] first. -Then you can run the following commands at the repository root: +Run the repository-wide checks when a change crosses package boundaries or is +ready for release: ~~~~ bash -mise install -mise run docs +mise run check +mise run test ~~~~ -Once the development server is running, you can open your browser and navigate -to *http://localhost:5173/* to view the docs. - -[pnpm]: https://pnpm.io/ +Do not submit hypothetical code. Verify the behavior in every environment +that the pull request claims to support, and report what you actually ran. diff --git a/packages/vocab-tools/README.md b/packages/vocab-tools/README.md index 8ac85782f..e45226d54 100644 --- a/packages/vocab-tools/README.md +++ b/packages/vocab-tools/README.md @@ -25,3 +25,24 @@ pnpm add @fedify/vocab-tools ~~~~ bash yarn add @fedify/vocab-tools ~~~~ + + +Development +----------- + +Run development tasks from the repository root with [mise]. + +[mise]: https://mise.jdx.dev/ + +### Updating snapshots + +The code generator has separate output snapshots for Deno, Node.js, and Bun. +When a change affects generated output, update all three from the repository +root: + +~~~~ bash +mise run test:update_snapshots +~~~~ + +Review and commit every changed snapshot file. Updating only one runtime +leaves the other test suites with stale expectations.