Task Workflow
ikarenkov/Modo
Spec-driven workflow for non-trivial work. An agent skill from ikarenkov/Modo.
Extract knowledge, guidelines, and ADRs from one or more completed spec directories into the project documentation system.
$ npx skills add opsmill/infrahub --skill speckit-opsmill-extract -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install opsmill/infrahub speckit-opsmill-extract --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/opsmill/infrahub.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/speckit-opsmill-extract .claude/skills/speckit-opsmill-extract && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "speckit-opsmill-extract" agent skill from https://github.com/opsmill/infrahub/tree/stable/.agents/skills/speckit-opsmill-extract into .claude/skills/speckit-opsmill-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "speckit-opsmill-extract", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/opsmill/infrahub/tree/stable/.agents/skills/speckit-opsmill-extractType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add opsmill/infrahub --skill speckit-opsmill-extract -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install opsmill/infrahub speckit-opsmill-extract --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/opsmill/infrahub.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/speckit-opsmill-extract .agents/skills/speckit-opsmill-extract && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "speckit-opsmill-extract" agent skill from https://github.com/opsmill/infrahub/tree/stable/.agents/skills/speckit-opsmill-extract into .agents/skills/speckit-opsmill-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "speckit-opsmill-extract", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add opsmill/infrahub --skill speckit-opsmill-extract -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install opsmill/infrahub speckit-opsmill-extract --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/opsmill/infrahub.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/speckit-opsmill-extract .cursor/skills/speckit-opsmill-extract && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "speckit-opsmill-extract" agent skill from https://github.com/opsmill/infrahub/tree/stable/.agents/skills/speckit-opsmill-extract into .cursor/skills/speckit-opsmill-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "speckit-opsmill-extract", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/opsmill/infrahub.git --path .agents/skills/speckit-opsmill-extract--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add opsmill/infrahub --skill speckit-opsmill-extract -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install opsmill/infrahub speckit-opsmill-extract --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/opsmill/infrahub.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/speckit-opsmill-extract .gemini/skills/speckit-opsmill-extract && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "speckit-opsmill-extract" agent skill from https://github.com/opsmill/infrahub/tree/stable/.agents/skills/speckit-opsmill-extract into .gemini/skills/speckit-opsmill-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "speckit-opsmill-extract", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install opsmill/infrahub speckit-opsmill-extractInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add opsmill/infrahub --skill speckit-opsmill-extract -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/opsmill/infrahub.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/speckit-opsmill-extract .github/skills/speckit-opsmill-extract && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "speckit-opsmill-extract" agent skill from https://github.com/opsmill/infrahub/tree/stable/.agents/skills/speckit-opsmill-extract into .github/skills/speckit-opsmill-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "speckit-opsmill-extract", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add opsmill/infrahub --skill speckit-opsmill-extract -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install opsmill/infrahub speckit-opsmill-extract --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/opsmill/infrahub.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/speckit-opsmill-extract .opencode/skills/speckit-opsmill-extract && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "speckit-opsmill-extract" agent skill from https://github.com/opsmill/infrahub/tree/stable/.agents/skills/speckit-opsmill-extract into .opencode/skills/speckit-opsmill-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "speckit-opsmill-extract", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
speckit-opsmill-extractExtract knowledge, guidelines, and ADRs from one or more completed spec directories into the project documentation system.
Speckit Opsmill Extract is an agent skill from opsmill/infrahub. Extract knowledge, guidelines, and ADRs from one or more completed spec directories into the project documentation system.
Its SKILL.md is about 3.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts. Compatibility notes: Requires spec-kit project structure with .specify/ directory
It sits in Development, covering Architecture decision records and Spec-driven development. The repository describes itself as: Infrahub is a graph-based data management platform with built-in version control, CI workflows, peer review, and API access. It’s purpose-built to power reliable infrastructure… The licence is Apache-2.0.
5 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 460d724. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are markdown and bash).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Requires spec-kit project structure with .specify/ directory
From compatibility in the SKILL.md frontmatter.
Speckit Opsmill Extract loads about 3.4k tokens when it runs. Until then it costs about 37 tokens; SKILL.md has 1,403 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from opsmill/infrahub at commit 460d724, republished under its Apache-2.0 licence (© opsmill). 1,403 words, ~3,449 tokens.
.claude/skills/speckit-opsmill-extract/SKILL.md (or your agent's skills folder).$ARGUMENTSYou MUST consider the user input before proceeding (if not empty).
Goal: Analyze one or more completed spec directories and extract durable knowledge into the project's documentation system (dev/knowledge/, dev/guidelines/, dev/adr/), then mark each spec as extracted.
This command accepts multiple specs as input (space-separated) and processes them sequentially. It operationalizes the documentation lifecycle: specs/ → knowledge/ or guidelines/ (see dev/guidelines/markdown.md).
<thinking>
First, resolve all spec directories from the user's arguments and validate each one contains the expected artifacts.
</thinking>
Parse arguments — split $ARGUMENTS into individual spec identifiers (space-separated). If $ARGUMENTS is empty, list available spec directories and ask the user to pick one or more.
Resolve each spec directory:
specs/NNN-* or NNN-*, resolve to REPO_ROOT/specs/NNN-*graphql-name-lookup, search specs/ for a matching directoryValidate each resolved spec:
spec.md MUST exist — skip that spec with an error if missingresearch.md SHOULD exist — warn if missing ("No ADRs can be extracted without research.md") but continueCheck extraction status for each spec:
EXTRACTED.md exists in the spec directory, warn the user that this spec was previously extractedspecs/archive/ — if so, it was previously extracted and archivedSummarize resolved specs — before proceeding, print the list of specs that will be processed:
Processing N spec(s):
1. specs/<spec-name-1>
2. specs/<spec-name-2>
...Load existing documentation index (once, shared across all specs):
dev/knowledge/ (recursively)dev/guidelines/ (recursively)dev/adr/ to determine the next ADR numberLoad spec artifacts — for each spec, read all available files from its directory:
research.md (primary source for ADRs)spec.md (context, scope decisions)data-model.md (schema changes, new methods — if exists)contracts/ (API changes — if exists)plan.md (architectural context — if exists)<thinking>
For each spec, I need to parse each source and classify content into three buckets: ADR, Knowledge, Guideline. I should also identify content to skip with a clear reason. I'll process specs sequentially and tag each finding with its source spec.
</thinking>
Repeat the following steps for each resolved spec directory. Tag every finding with the source spec name so the extraction plan in Phase 2 groups items by spec.
Parse each ## R# section in research.md. For each entry:
Also scan spec.md for scope decisions or trade-offs in the Clarifications or Assumptions sections that represent architectural choices worth recording.
Scan for content that describes how the system works after the feature:
| Source | What to look for | Target file |
|---|---|---|
data-model.md | New entities, fields, relationships, constraints | dev/knowledge/backend/data-models.md |
contracts/ | New or changed GraphQL queries, mutations, types | dev/knowledge/backend/api.md |
research.md | New service patterns, architectural patterns | dev/knowledge/backend/services.md or relevant file |
spec.md | New concepts or domain terminology | dev/knowledge/backend/overview.md or relevant file |
For each finding, map it to a specific existing knowledge file and section. If no existing file fits, propose a new file with a name following kebab-case.md convention.
Scan research.md for implementation patterns that establish repeatable, prescriptive conventions for future code:
dev/guidelines/backend/python.md or dev/guidelines/cyclopts.mddev/guidelines/backend/exceptions.mddev/guidelines/backend/graphql.md (create if needed)These targets are routing examples, not a fixed map — content moves as files split, so confirm the section still lives in the named file before writing to it.
Only extract patterns that are prescriptive (should be followed in future code). Do NOT extract patterns that are merely descriptive of how this specific feature works — those belong in knowledge.
For each piece of spec content not classified above, note it with a reason:
plan.md, quickstart.md) — no durable knowledgePresent findings in a structured extraction plan. When processing multiple specs, group the plan by spec. Use a global numbering scheme across all specs so that item numbers are unique (e.g., spec 1 items are 1–4, spec 2 items are 5–8).
Use this format:
## Extraction Plan
### specs/<spec-name-1>
#### ADRs to Create (<count>)
| # | Source | Title | Target File |
|---|--------|-------|-------------|
| 1 | R1 | <title> | dev/adr/nnnn-<slug>.md |
| 2 | R2 | <title> | dev/adr/nnnn-<slug>.md |
#### Knowledge Updates (<count>)
| # | Target File | Section | Change | Summary |
|---|-------------|---------|--------|---------|
| 3 | dev/knowledge/backend/api.md | Queries | UPDATE | <what changes> |
#### Guidelines Updates (<count>)
| # | Target File | Section | Change | Summary |
|---|-------------|---------|--------|---------|
| 4 | dev/guidelines/backend/exceptions.md | Error Handling | UPDATE | <what changes> |
#### Skipped (with reasons)
| Source | Reason |
|--------|--------|
| plan.md | Execution artifact — no durable knowledge |
---
### specs/<spec-name-2>
#### ADRs to Create (<count>)
| # | Source | Title | Target File |
|---|--------|-------|-------------|
| 5 | R1 | <title> | dev/adr/nnnn-<slug>.md |
...When processing a single spec, omit the per-spec grouping headers and use the simpler flat format (same as the multi-spec table structure but without the ### specs/<name> wrapper).
After presenting, tell the user:
Actions:
approve all— proceed with all extractions across all specsapprove spec <name>— approve all items for a specific specapprove adrs/approve knowledge/approve guidelines— approve by category (across all specs)skip N— skip a specific numbered itemedit N— modify a specific item before writinggroup N,M— merge multiple ADR items into a single ADR
Wait for user response before proceeding. Do NOT write any files until the user approves.
For each approved item across all specs, write the content. ADR numbering is sequential across all specs (i.e., if spec 1 creates 0005 and 0006, spec 2 starts at 0007).
Create new files in dev/adr/ using this format:
# N. <Title>
**Status**: Accepted
**Date**: <today's date YYYY-MM-DD>
**Source**: specs/archive/<spec-name>/research.md (R#)
## Context
<What is the issue that motivates this decision? Derive from the feature context in spec.md and the specific problem the R# entry addresses.>
## Decision
<What was decided. Taken from the Decision field of the R# entry.>
## Consequences
<What becomes easier or harder as a result. Synthesize from the Rationale and any implementation notes.>
## Alternatives Considered
<What other options were evaluated and why they were rejected. Taken from the Alternatives considered field.>Numbering: Read existing files in dev/adr/ to find the highest existing ADR number. Start new ADRs at the next sequential number. Zero-pad the filename sequence to 4 digits (e.g., 0001, 0012); the H1 heading uses the un-padded number (e.g., # 1., # 12.).
File naming: canonical MADR nnnn-kebab-case-short-title.md — 4-digit zero-padded sequence, lowercase kebab title, no adr-/ADR- prefix (e.g., 0001-schema-changes-without-migrations.md).
For each knowledge update:
<!-- Extracted from specs/<spec-name> on YYYY-MM-DD -->Same approach as knowledge updates:
<!-- Extracted from specs/<spec-name> on YYYY-MM-DD -->If creating a new guidelines file, follow the standard structure:
# <Topic> Guidelines
## Overview
<Brief description of what this document covers.>
## <Sections...>Perform the following steps for each spec that had approved extractions.
Write EXTRACTED.md in each spec directory:
# Extraction Record
**Extracted on**: <YYYY-MM-DD>
**Extracted by**: speckit.opsmill.extract
## ADRs Created
- <path to ADR file> (from R#)
- ...
## Knowledge Updated
- <path to knowledge file> (<section name>)
- ...
## Guidelines Updated
- <path to guidelines file> (<section name>)
- ...
## Archive
Spec directory moved to `specs/archive/<spec-name>/` as a historical record.For each spec:
spec.md, update or add the status field to: **Status**: Extractedspecs/archive/:mkdir -p specs/archive
mv specs/<spec-name> specs/archive/<spec-name>After all specs have been processed, update dev/README.md once with all new files:
dev/knowledge/, dev/guidelines/, or dev/adr/:dev/README.md- [filename.md](path/to/filename.md) - Brief descriptiondev/adr/ now has content and there is no "Current ADRs" section in the README, create one following the pattern of the existing sections.Print a combined summary covering all processed specs:
## Extraction Complete
**Date**: YYYY-MM-DD
**Specs processed**: N
### Per-Spec Summary
| Spec | ADRs | Knowledge | Guidelines | Status |
|------|------|-----------|------------|--------|
| specs/<spec-name-1> | N | N | N | archived |
| specs/<spec-name-2> | N | N | N | archived |
### Totals
- N ADR(s) created in dev/adr/
- N knowledge file(s) updated
- N guideline file(s) updated
### Archived
- specs/<spec-name-1> → specs/archive/<spec-name-1>
- specs/<spec-name-2> → specs/archive/<spec-name-2>
### Files Created/Modified
- <list each file path>
### Next Steps
- Review the created ADRs for accuracy
- Verify knowledge and guideline updates read well in contextspecs/archive/ before moving if it does not existSource paths must reference the archive location (specs/archive/<spec-name>/) since the spec will be moved there'I'\''m Groot' (or double-quote if possible: "I'm Groot")© opsmill, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/speckit-opsmill-extract of opsmill/infrahub.
Open the folder on GitHubat commit 460d724
Speckit Opsmill Extract next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Speckit Opsmill Extract this skillopsmill/infrahub | 531 | — | ~3.4k | Automated safety check: Pass | Apache-2.0 | |
| Task Workflowikarenkov/Modo | 343 | — | ~2.4k | Automated safety check: Pass | None | |
| Architecture Reviewowainlewis/blueprint | 412 | — | ~1.2k | Automated safety check: Pass | MIT | |
| Architect Build Specsjsmastery-pro/skills | 1.4k | — | ~7k | Automated safety check: Notes | MIT | |
| OpenSpec Bulk Change ArchiverFission-AI/OpenSpec | 71k | 3 repos | ~5.6k | Automated safety check: Pass | MIT | |
| PR Design DocOpenHands/OpenHands | 90k | — | ~2.4k | Automated safety check: Pass | MIT |
ikarenkov/Modo
Spec-driven workflow for non-trivial work. An agent skill from ikarenkov/Modo.
owainlewis/blueprint
Reviews a technical proposal before implementation through an independent subagent, returning findings, open questions and a verdict without rewriting it.
jsmastery-pro/skills
Runs a structured design conversation on a feature, tech stack or enhancement, recommends an answer and records it as a build spec in docs/specs.
Fission-AI/OpenSpec
Archives several completed OpenSpec changes in one operation, checking the codebase to resolve spec conflicts rather than archiving blindly.
OpenHands/OpenHands
For a non-trivial pull request, write a self-contained HTML design doc under the temporary .pr/ directory and link a visibility-appropriate preview in the PR description, so maintainers grasp the…
WeihanLi/WeihanLi.Common
Create or update the project constitution from interactive or provided principle inputs, ensuring all dependent templates stay in sync.
opsmill/infrahub
Analyzes recent CI failures on pull requests to identify flaky tests, using retry outcomes (failed attempt → green re-run) and cross-PR recurrence as evidence, and maintains a local longitudinal…
opsmill/infrahub
Audits internal (dev/) and external (docs/) documentation completeness for a feature, subject, or set of existing docs, maps changes indicated by the user, across Infrahub's documentation layers…
opsmill/infrahub
Stages and commits the current changes onto a safe working branch, enforcing branch discipline and optionally pushing upstream.
opsmill/infrahub
A skill your agent uses when you've fixed a bug, added a feature, or made any user-facing change in a project that uses Towncrier and need to record it for the changelog — before committing or…
opsmill/infrahub
Turns a single feature idea, improvement, or bug into ONE well-structured GitHub issue.
opsmill/infrahub
Synthesises the current conversation context into a Product Requirements Document and publishes it to GitHub (as a comment on a referenced issue, or a new issue).
Categories
Extract knowledge, guidelines, and ADRs from one or more completed spec directories into the project documentation system. Speckit Opsmill Extract is an agent skill from opsmill/infrahub. Extract knowledge, guidelines, and ADRs from one or more completed spec directories into the project documentation system.
Speckit Opsmill Extract fits situations like: tasks that involve Architecture decision records; tasks that involve Spec-driven development.
Run `npx skills add opsmill/infrahub --skill speckit-opsmill-extract -a claude-code`. Or copy the skill folder (.agents/skills/speckit-opsmill-extract in opsmill/infrahub) into .claude/skills/speckit-opsmill-extract in your project. Claude Code loads it when a task matches its description.
Run `npx skills add opsmill/infrahub --skill speckit-opsmill-extract -a codex`. Or copy the skill folder (.agents/skills/speckit-opsmill-extract in opsmill/infrahub) into .agents/skills/speckit-opsmill-extract in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add opsmill/infrahub --skill speckit-opsmill-extract -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/speckit-opsmill-extract, .gemini/skills/speckit-opsmill-extract, .github/skills/speckit-opsmill-extract and .opencode/skills/speckit-opsmill-extract in your project.
SKILL.md names no scripts, command-line tools or credentials: Speckit Opsmill Extract is instructions for the agent only. Compatibility (from SKILL.md): Requires spec-kit project structure with .specify/ directory.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Speckit Opsmill Extract is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.4k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Speckit Opsmill Extract: Task Workflow (ikarenkov/Modo, 343 stars), Architecture Review (owainlewis/blueprint, 412 stars), Architect Build Specs (jsmastery-pro/skills, 1.4k stars) and OpenSpec Bulk Change Archiver (Fission-AI/OpenSpec, 71k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
opsmill (a GitHub organization) maintains it in opsmill/infrahub, which has 531 GitHub stars. The repository holds 32 skills in this directory. The repository was last updated on October 8, 2026.
Source: opsmill/infrahub on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.