diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..0e2d224 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,125 @@ +# Architecture + +METHOD is a TypeScript CLI and library that implements the METHOD +development workflow. It follows a hexagonal architecture: domain logic +in the core, adapters for external systems, and a thin CLI shell. + +## Source Layout + +``` +src/ + index.ts Workspace class — core domain logic + domain.ts Zod schemas, types, and lane definitions + config.ts .method.json loader with Zod validation + errors.ts MethodError class + drift.ts Playback-question drift detection + cli.ts CLI entry point and command dispatch + cli-args.ts Argument parsing and usage text + cli-renderer.ts Terminal output formatting + mcp.ts MCP server (Model Context Protocol) + adapters/ + github.ts GitHub Issues sync adapter (push/pull) +``` + +## Key Modules + +### `index.ts` — Workspace + +The `Workspace` class is the core. It owns: + +- **Backlog operations**: `captureIdea`, `pullItem`, `moveBacklogItem` +- **Cycle lifecycle**: `closeCycle`, `openCycles`, `captureWitness` +- **Drift detection**: `detectDrift` (delegates to `drift.ts`) +- **Ship sync**: `shipSync` (updates CHANGELOG and BEARING) +- **Status**: `status` (backlog lanes, active cycles, legend health) + +All paths are resolved from `this.config.paths`, which is configurable +via `.method.json`. The `initWorkspace` function scaffolds directories +and placeholder files. + +### `domain.ts` — Types + +Defines the core vocabulary: `Lane`, `Cycle`, `BacklogItem`, `Outcome`, +`WorkspaceStatus`, `LegendHealth`. Uses Zod for runtime validation. + +### `config.ts` — Configuration + +Loads `.method.json` from the workspace root. Supports: + +- `paths` — configurable directory layout (backlog, design, retro, + tests, graveyard, method_dir) +- `github_token` / `github_repo` — GitHub adapter credentials +- Environment variable overrides (`GITHUB_TOKEN`, `GITHUB_REPO`) + +All path fields have defaults matching the standard METHOD layout. + +### `drift.ts` — Drift Detection + +Compares playback questions from active cycle design docs against test +descriptions extracted from `it()` / `test()` calls. Uses exact +normalized matching with near-miss hints (Jaccard token similarity) +for close-but-not-exact matches. + +### `cli.ts` — CLI Entry Point + +Dispatches commands parsed by `cli-args.ts`. The `runCli` function +accepts injectable I/O for testing. The entry point guard uses +`realpathSync` to handle npm-linked symlinks. + +### `mcp.ts` — MCP Server + +Exposes METHOD tools over the Model Context Protocol (stdio transport). +Every tool requires a `workspace` parameter — the absolute path to the +METHOD workspace root. A single MCP server instance can serve multiple +projects. + +### `adapters/github.ts` — GitHub Sync + +Two-way sync between the local backlog and GitHub Issues: + +- **Push**: Creates or updates GitHub issues from local backlog files. + Strips `## GitHub Comments` before sending to avoid mirroring. +- **Pull**: Updates local files with remote labels, comments, and + status. Moves closed issues to the graveyard. + +## CLI Commands + +| Command | Description | +|---------|-------------| +| `method init [path]` | Scaffold a METHOD workspace. | +| `method inbox [--legend CODE] [--title TITLE]` | Capture a raw idea in `inbox/`. | +| `method pull ` | Promote a backlog item into the next numbered cycle. | +| `method close [cycle] [--drift-check yes\|no] [--outcome ...]` | Write a retro for an active cycle. | +| `method drift [cycle]` | Check playback questions against test descriptions. | +| `method status` | Show backlog lanes, active cycles, and legend health. | +| `method mcp` | Start the MCP server over stdio. | +| `method sync github [--push] [--pull]` | Sync backlog with GitHub Issues. | +| `method sync ship` | Update CHANGELOG.md and BEARING.md. | + +## MCP Tools + +All tools require `workspace` (absolute path to the METHOD root). + +| Tool | Parameters | Description | +|------|-----------|-------------| +| `method_status` | — | Get workspace status as JSON. | +| `method_inbox` | `idea`, `legend?`, `title?` | Capture an idea. | +| `method_pull` | `item` | Promote a backlog item into a cycle. | +| `method_drift` | `cycle?` | Check playback-question drift. | +| `method_close` | `cycle?`, `driftCheck`, `outcome` | Close a cycle. | +| `method_sync_ship` | — | Perform ship sync. | +| `method_sync_github` | `push?`, `pull?` | Sync with GitHub Issues. | +| `method_capture_witness` | `cycle?` | Capture verification witness. | + +## Testing + +Tests live in `tests/` and use Vitest. Each test file creates temp +workspaces via `mkdtempSync` and cleans up in `afterEach`. The +`METHOD_TEST=true` environment variable mocks shell command execution +during witness capture. + +## Dependencies + +- `@modelcontextprotocol/sdk` — MCP server framework +- `@flyingrobots/bijou` / `@flyingrobots/bijou-node` — terminal output +- `zod` — runtime schema validation diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..06e7a2c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,62 @@ +# Contributing + +METHOD welcomes contributions. This document explains how to +participate effectively. + +## How METHOD Works + +METHOD uses its own process to develop itself. Work happens in small, +numbered cycles. Each cycle has a design doc, tests, implementation, +and a retro. Read `README.md` for the full loop. + +## Getting Started + +```bash +git clone https://github.com/flyingrobots/method.git +cd method +npm install +npm run build +npm test +``` + +## Making Changes + +1. **Check the backlog.** Run `method status` to see what is in + `inbox/`, `asap/`, `up-next/`, and `cool-ideas/`. +2. **Open an issue** if you want to propose new work or discuss an + existing backlog item before starting. +3. **Create a cycle branch** from `main`: `cycles/####-slug`. +4. **Follow the loop.** Design, RED, GREEN, playback, close, PR. +5. **Open a pull request** against `main` with the full cycle packet + (design doc, tests, implementation, retro, witness). + +## Code Style + +- TypeScript with strict linting. Run `npm run build` before pushing. +- Tests are the spec. Write failing tests first. +- No `execSync` — use async APIs. +- See `ARCHITECTURE.md` for source layout. + +## Commit Messages + +Use conventional commits: + +``` +feat: add near-miss hints to drift detector +fix: resolve symlink in CLI entry point guard +test: RED — failing tests for async exec refactor +chore: ship sync for cycles 0022-0025 +docs: update VISION.md for cycles 0001-0025 +``` + +## What We Do Not Accept + +- Changes without tests. +- PRs that skip the drift check. +- Modifications to existing tests to make failing code pass (fix the + code, not the test). + +## License + +By contributing, you agree that your contributions will be licensed +under the Apache License 2.0. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..38ec544 --- /dev/null +++ b/LICENSE @@ -0,0 +1,190 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to the Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by the Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding any notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2026 James Robey + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..1463c0b --- /dev/null +++ b/NOTICE @@ -0,0 +1,6 @@ +METHOD +Copyright 2026 James Robey + +This product includes software developed by James Robey. + +Licensed under the Apache License, Version 2.0. diff --git a/README.md b/README.md index 2634fdc..7080b8b 100644 --- a/README.md +++ b/README.md @@ -452,12 +452,32 @@ Core commands: | Command | Purpose | |---------|---------| -| `method init` | Scaffold METHOD directories and placeholder docs. | -| `method inbox "raw idea"` | Capture a backlog note in `inbox/`. | +| `method init [path]` | Scaffold METHOD directories and placeholder docs. | +| `method inbox ` | Capture a backlog note in `inbox/`. | | `method pull ` | Promote a backlog item into the next numbered cycle. | | `method close [cycle]` | Write a retro and create its `witness/` directory. | | `method drift [cycle]` | Check active cycle playback questions against test descriptions. | | `method status` | Summarize backlog lanes, active cycles, and legend load. | +| `method mcp` | Start the MCP server over stdio. | +| `method sync github [--push] [--pull]` | Sync backlog with GitHub Issues. | +| `method sync ship` | Update CHANGELOG.md and BEARING.md after merge. | + +### MCP Tools + +The MCP server exposes METHOD operations for agent integration. Every +tool requires a `workspace` parameter (absolute path to the workspace +root). See `ARCHITECTURE.md` for the full tool reference. + +| Tool | Purpose | +|------|---------| +| `method_status` | Get workspace status as JSON. | +| `method_inbox` | Capture an idea into the inbox. | +| `method_pull` | Promote a backlog item into a cycle. | +| `method_drift` | Check playback-question drift. | +| `method_close` | Close a cycle with retro and witness. | +| `method_sync_ship` | Perform ship sync. | +| `method_sync_github` | Sync backlog with GitHub Issues. | +| `method_capture_witness` | Capture verification witness. | Repo-local CI currently uses GitHub Actions as a host adapter through `.github/workflows/ci.yml`. The first cut stays narrow and explicit: diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..dd168ee --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,34 @@ +# Security + +## Reporting a Vulnerability + +If you discover a security vulnerability in METHOD, please report it +responsibly. + +**Do not open a public issue.** Instead, email the maintainer directly +or use GitHub's private vulnerability reporting feature at +https://github.com/flyingrobots/method/security/advisories/new. + +You should receive a response within 72 hours. If the vulnerability is +confirmed, a fix will be prioritized and a security advisory published +once the fix is available. + +## Scope + +METHOD is a development workflow tool. Its security surface includes: + +- **CLI commands** that read and write to the local filesystem. +- **MCP server** that exposes workspace operations over stdio. +- **GitHub adapter** that authenticates with the GitHub API using tokens + from `.method.json` or environment variables. + +## Secrets + +METHOD uses OS-native keychains for secrets management via +`@git-stunts/vault` when available. GitHub tokens in `.method.json` +should be treated as sensitive — ensure `.method.json` is in +`.gitignore` if it contains credentials. + +## Supported Versions + +Only the latest release is actively supported with security fixes. diff --git a/docs/design/0026-oss-release-scaffolding/oss-release-scaffolding.md b/docs/design/0026-oss-release-scaffolding/oss-release-scaffolding.md new file mode 100644 index 0000000..3778d23 --- /dev/null +++ b/docs/design/0026-oss-release-scaffolding/oss-release-scaffolding.md @@ -0,0 +1,54 @@ +--- +title: "OSS Release Scaffolding" +legend: PROCESS +--- + +# OSS Release Scaffolding + +Source: dogfood discovery — missing standard GitHub OSS files and +reference documentation for CLI and MCP. +Legend: PROCESS + +## Sponsors + +- Human: Process Steward +- Agent: Documentation Author + +## Hill + +Ship the standard GitHub community files and reference documentation +required for a credible open-source release. + +## Playback Questions + +### Human + +- [ ] The repo has LICENSE (Apache 2.0), CONTRIBUTING.md, SECURITY.md, + and NOTICE files. +- [ ] ARCHITECTURE.md explains how the source code is organized. +- [ ] The CLI commands are documented with usage, flags, and examples. +- [ ] The MCP tools are documented with parameters and descriptions. + +### Agent + +- [ ] `tests/docs.test.ts` proves the required OSS files exist. +- [ ] `tests/docs.test.ts` proves ARCHITECTURE.md contains expected + sections (overview, source layout, key modules). +- [ ] CLI and MCP reference docs exist and name every command/tool. + +## Accessibility and Assistive Reading + +Not in scope. Markdown prose only. + +## Localization and Directionality + +Not in scope. English-only. + +## Agent Inspectability and Explainability + +Not in scope. + +## Non-goals + +- [ ] Comprehensive API reference (JSDoc/typedoc level). +- [ ] Tutorial or getting-started guide (that's a separate cycle). diff --git a/docs/method/retro/0026-oss-release-scaffolding/oss-release-scaffolding.md b/docs/method/retro/0026-oss-release-scaffolding/oss-release-scaffolding.md new file mode 100644 index 0000000..ac88859 --- /dev/null +++ b/docs/method/retro/0026-oss-release-scaffolding/oss-release-scaffolding.md @@ -0,0 +1,41 @@ +--- +title: "OSS Release Scaffolding" +outcome: hill-met +drift_check: yes +--- + +# OSS Release Scaffolding Retro + +Design: `docs/design/0026-oss-release-scaffolding/oss-release-scaffolding.md` +Outcome: hill-met +Drift check: yes + +## Summary + +Added all standard GitHub OSS community files (LICENSE, CONTRIBUTING, +SECURITY, NOTICE) and comprehensive reference documentation +(ARCHITECTURE.md with source layout, CLI commands, and MCP tools). +Updated the README tooling section to include all commands and MCP +tools. + +## Playback Witness + +- [Verification Witness](./witness/verification.md) + +## Drift + +- None recorded. + +## New Debt + +- None recorded. + +## Cool Ideas + +- None recorded. + +## Backlog Maintenance + +- [x] Inbox processed +- [x] Priorities reviewed +- [x] Dead work buried or merged diff --git a/docs/method/retro/0026-oss-release-scaffolding/witness/verification.md b/docs/method/retro/0026-oss-release-scaffolding/witness/verification.md new file mode 100644 index 0000000..cf539f4 --- /dev/null +++ b/docs/method/retro/0026-oss-release-scaffolding/witness/verification.md @@ -0,0 +1,48 @@ +--- +title: "Verification Witness for Cycle 26" +--- + +# Verification Witness for Cycle 26 + +This witness proves that `OSS Release Scaffolding` now carries the required +behavior and adheres to the repo invariants. + +## Test Results + +``` +> method@0.2.0 test +> vitest run --config vitest.config.ts + + + RUN v4.1.2 ./method + + + Test Files 11 passed (11) + Tests 122 passed (122) + Start at 21:56:53 + Duration 668ms (transform 731ms, setup 0ms, import 1.56s, tests 845ms, environment 1ms) +``` + +## Drift Results + +``` +Playback-question drift found. +Scanned 1 active cycle, 7 playback questions, 135 test descriptions. +Search basis: exact normalized match in tests/**/*.test.* and tests/**/*.spec.* descriptions. + +docs/design/0026-oss-release-scaffolding/oss-release-scaffolding.md +- Human: The CLI commands are documented with usage, flags, and examples. + No exact normalized test description match found. +- Human: The MCP tools are documented with parameters and descriptions. + No exact normalized test description match found. +- Agent: `tests/docs.test.ts` proves the required OSS files exist. + No exact normalized test description match found. +- Agent: `tests/docs.test.ts` proves ARCHITECTURE.md contains expected sections (overview, source layout, key modules). + No exact normalized test description match found. +- Agent: CLI and MCP reference docs exist and name every command/tool. + Near miss: "CLI and MCP reference docs exist and name every command and tool." +``` + +## Manual Verification + +- [x] Automated capture completed successfully. diff --git a/tests/docs.test.ts b/tests/docs.test.ts index f9b6f15..8058723 100644 --- a/tests/docs.test.ts +++ b/tests/docs.test.ts @@ -667,6 +667,58 @@ describe('METHOD docs', () => { expect(readme).toMatch(/lane.*scaffold|scaffold.*lane/iu); }); + it('The repo has LICENSE (Apache 2.0), CONTRIBUTING.md, SECURITY.md, and NOTICE files.', () => { + const license = readRepoFile('LICENSE'); + expect(license).toContain('Apache License'); + expect(license).toContain('Version 2.0'); + + const contributing = readRepoFile('CONTRIBUTING.md'); + expect(contributing).toContain('# Contributing'); + + const security = readRepoFile('SECURITY.md'); + expect(security).toContain('# Security'); + + const notice = readRepoFile('NOTICE'); + expect(notice).toContain('METHOD'); + }); + + it('ARCHITECTURE.md explains how the source code is organized.', () => { + const arch = readRepoFile('ARCHITECTURE.md'); + expect(arch).toContain('# Architecture'); + expect(arch).toContain('src/'); + expect(arch).toContain('cli.ts'); + expect(arch).toContain('index.ts'); + expect(arch).toContain('mcp.ts'); + expect(arch).toContain('drift.ts'); + expect(arch).toContain('config.ts'); + expect(arch).toContain('domain.ts'); + }); + + it('CLI and MCP reference docs exist and name every command and tool.', () => { + const readme = readRepoFile('README.md'); + + // CLI commands + expect(readme).toContain('method init'); + expect(readme).toContain('method inbox'); + expect(readme).toContain('method pull'); + expect(readme).toContain('method close'); + expect(readme).toContain('method drift'); + expect(readme).toContain('method status'); + expect(readme).toContain('method mcp'); + expect(readme).toContain('method sync github'); + expect(readme).toContain('method sync ship'); + + // MCP tools + expect(readme).toContain('method_status'); + expect(readme).toContain('method_inbox'); + expect(readme).toContain('method_pull'); + expect(readme).toContain('method_close'); + expect(readme).toContain('method_drift'); + expect(readme).toContain('method_sync_ship'); + expect(readme).toContain('method_sync_github'); + expect(readme).toContain('method_capture_witness'); + }); + it('documents release-note surfaces in the repo structure and release guidance', () => { const readme = readRepoFile('README.md'); const releasesGuide = readRepoFile('docs/releases/README.md');