Imported from misty-step/landmark (
AGENTS.md). Install upstream withnpx skills add misty-step/landmark. Copyright stays with the author.
Landmark Agent Contract
Landmark combines automated versioning with LLM synthesis of commits, diffs, and product context into coherent, user-friendly changelogs and release notes. Explain what changed and why users should care. The portable Rust CLI owns this behavior; the GitHub Action is an integration layer. Deterministic local previews complement, rather than replace, the model-assisted product.
Product Boundary
Landmark is a portable release-intelligence runtime. The GitHub Action is one packaging layer, not the product boundary. Keep release analysis, synthesis, artifact planning, artifact writing, feed generation, notifications, evidence, and provider policy in the Rust CLI. Keep GitHub-specific behavior behind explicit adapter seams.
Landmark's target boundary owns release truth, audience/importance
classification, release-kit plans, provenance, approval state, public release
mutation, reconciliation, and the completed release receipt. Release judgment
and mutation are one deep module: inspect before writing, make retries
idempotent, finish compatible partial state, and fail closed on contradictions.
release-transaction prepare|bind|commit emits that receipt for artifact-bound
releases. The self-release pipeline shares the same reconciliation core but is
not yet artifact-bound — its publication carries no OCI/Sigstore identity and
emits no completed receipt; revisit when product builds supply one. Until then,
do not infer receipt authority from tags, events, or synthesis-status outputs.
Product build pipelines own construction, signing, and publication of their executable artifacts. Landmark validates supplied artifact manifests and binds immutable artifact identities into release truth; it does not rebuild product containers, packages, or binaries. Deployment systems consume completed release receipts and own environment-specific promotion, verification, rollback, and convergence. Forge events are wake-up signals, not release authority, and Landmark does not deploy.
Landmark also does not own bespoke media production, brand design, CMS
publishing, or long-running creative pipelines. Demo videos, GIFs, images, blog
posts, essays, and docs updates should be represented as typed
planned/produced artifacts and delegated to explicit local, browser, service,
harness, or human producer adapters. See
docs/adr/0004-release-transaction-authority.md for the boundary decision.
Use the README, accepted ADRs, and versioned schemas when changing release
boundaries, adoption modes, agent-native contracts, or producer responsibilities.
VISION.md is optional rationale, not a mandatory workflow or higher authority.
Architecture
Runtime Structure
crates/landmark/src/main.rsis the Rust binary facade: parse CLI, dispatch, and render top-level errors. Runtime responsibilities should live in focused modules undercrates/landmark/src/.bin/check-architectureratchets the facade and extracted module sizes; if a module needs to grow past its current budget, split ownership first or update the ratchet with an explicit architecture reason.action.ymlis a composite GitHub Action wrapper around a bootstrap- downloaded Landmark release binary plussemantic-releasefor full GitHub release mode. The bootstrap step downloads and checksum-verifies the release binary matching the runner's OS/arch from the GitHub Release for the action's own pinned version; there is no checked-in binary.- Release binaries are built for
x86_64-unknown-linux-musl,aarch64-unknown-linux-musl,aarch64-apple-darwin, andx86_64-apple-darwinand published withchecksums.txtas GitHub Release assets by.github/workflows/release.yml. For local development usecargo run --locked -p landmark -- ...or a locally builttarget/debug/landmark. - Node is only for
semantic-releasein full mode. Do not add new Node or shell orchestration unless the platform boundary requires it. - Python is not part of the active runtime. Do not reintroduce Python scripts for release behavior.
Pipeline Steps
Composite GitHub Action with these steps:
semantic-releasehandles steps 1-4 (analyze commits, generate changelog, push version bump + changelog, create GitHub Release) — proven, battle-tested.- A bootstrap-downloaded Rust runtime handles step 5-6 (LLM-synthesize user-facing release notes, update the GitHub Release body) plus policy, artifacts, notifications, and replay.
Key Design Decisions
- Unix philosophy: This does ONE thing — releases. Not code review, monitoring, artifact construction, or deployment.
- Wraps semantic-release: Don't reinvent the wheel. Extend it.
- LLM synthesis is the value-add: Technical changelogs exist. User-facing notes don't.
- OpenRouter by default: Supports provider choice and model fallback chains.
- Reusable Action: Any repo can opt in with a simple workflow file.
Portability Direction
- A non-GitHub caller must be able to drive Landmark through CLI commands, manifest files, JSON artifacts, and local git state.
synthesis-only,backfill --mode artifacts-only,write-artifacts,update-feed, and webhook/Slack notification paths are the portable core.release-kitartifacts are the planning/evidence boundary for richer final-mile output; prefer extending the typed kit contract over embedding a producer in the core runtime.- GitHub operations such as release-body mutation, PR extraction, issue lifecycle, fleet scan, and Action outputs must be treated as adapter-specific.
- Cross-system release mutations must share one transaction model and receipt; adapters do not get to define independent meanings of "published."
- Prefer adding a provider interface or local artifact sink over broadening GitHub assumptions.
Repo Gates
- Run
bin/gatebefore closeout for code or contract changes. bin/gateincludesbin/check-architecture; do not weaken the ratchet to land feature work.- For action contract changes, also ensure
check-action-contractcoverage remains green through the gate. - Use
bin/replay-actionwhen touching release orchestration, synthesis, artifact outputs, release-body mutation, notifications, feeds, or failure lifecycle behavior.
action.yml Safety Patterns
- Never interpolate an
inputs.*orsecrets.*value directly into arun:shell block; pass it through anenv:block and reference the shell variable instead. Direct interpolation is a shell-injection vector (a repo name, commit subject, or synthesized note containing shell metacharacters becomes code). Everyrun:step inaction.ymlfollows this today; keep it that way when adding steps. - Non-blocking pipeline stages (synthesis, artifact writes, RSS/webhook/Slack
notifications) must
exit 0on failure and recordsucceeded/failure_stage/failure_messageoutputs instead. A release must still publish when a best-effort stage fails; onlysynthesis-required: "true"turns a synthesis/publication failure into a hard blocker (see "Enforce synthesis required" inaction.yml).
File Structure
landmark/
├── action.yml # Reusable GitHub Action (called by repos)
├── crates/
│ └── landmark/ # Rust runtime
├── templates/
│ └── synthesis-prompt.md # Prompt template for LLM
├── configs/
│ └── .releaserc.json # Default semantic-release config
├── README.md
├── AGENTS.md # Canonical agent contract (CLAUDE.md is a symlink to this file)
└── package.json # For semantic-release deps
How Repos Use It
name: Release
on:
push:
branches: [master, main]
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/create-github-app-token@v2
id: release-token
with:
app-id: ${{ secrets.LANDMARK_RELEASER_APP_ID }}
private-key: ${{ secrets.LANDMARK_RELEASER_PRIVATE_KEY }}
- uses: misty-step/landmark@v0
with:
github-token: ${{ steps.release-token.outputs.token }}
llm-api-key: ${{ secrets.OPENROUTER_API_KEY }}
# Optional:
# llm-model: deepseek/deepseek-v4-flash-0731
# llm-fallback-models: "google/gemini-3.7-flash,deepseek/deepseek-v4-pro-0813"
Requirements
- Node.js 22+
- Rust stable
- A GitHub App installed on the repo with Contents: read/write, and its App
ID + private key as
LANDMARK_RELEASER_APP_ID/LANDMARK_RELEASER_PRIVATE_KEYsecrets (see README's "Why a GitHub App, not a PAT"). The default${{ github.token }}covers landmark's own action invocation but its tags and releases do not trigger further workflow runs the way an App installation token does — use the App when downstream automation depends on that trigger. OPENROUTER_API_KEYsecret (or another compatible provider API key)
Work And Docs
- Work from the operator's current request. Check current code and overlapping work, then report the result and verification evidence in the session or PR. Historical tickets are context; do not maintain a replacement backlog.
- Track selected work in the Landmark Linear project; do not create a second backlog or automatically select historical work.
- Dated
.groom/anddocs/dogfood/reports are historical evidence, not live plans. Return selected unresolved findings with sources and proposal status; do not automatically import old reports as issues. - Keep README,
action.yml, examples, and this file aligned. Stale agent-facing prose is a release risk because agents use it as an operating contract. - Keep runner scheduling, generic agent roles, and coordination protocols in
the owning harness, not vendored into this repository. Repository checks
remain executable through
bin/gate.
Git
Prefer jj for local status and commits when it is available; fall back to
non-destructive git commands when an agent environment does not provide it.
Preserve user changes and avoid destructive git commands.