Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
name: release

on:
push:
tags: ["v*"]
tags:
- "v*"

permissions:
contents: write
Expand All @@ -10,15 +12,26 @@ jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-go@v5

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- uses: goreleaser/goreleaser-action@v6
cache: true

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
with:
distribution: goreleaser
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}
# PAT with `contents: write` on sirrobot01/homebrew-tap, so GoReleaser
# can commit the generated cask there. GITHUB_TOKEN is scoped to this
# repo only and cannot push to the tap.
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
45 changes: 33 additions & 12 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ version: 2
project_name: writ

builds:
- main: ./cmd/writ
- id: writ
main: ./cmd/writ
binary: writ
# modernc.org/sqlite is pure Go, so every target cross-compiles.
env:
Expand All @@ -24,7 +25,11 @@ builds:
mod_timestamp: "{{ .CommitTimestamp }}"

archives:
- name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
# id is what homebrew_casks.ids matches on, not the build id.
- id: writ
ids:
- writ
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
formats: [tar.gz]
format_overrides:
- goos: windows
Expand All @@ -48,25 +53,41 @@ changelog:
exclude:
- "^docs"

brews:
homebrew_casks:
- name: writ
homepage: https://writ.build
description: Agent orchestration as contract enforcement
license: Apache-2.0
directory: Formula
# Publishing to the tap needs a token with write access to this
# repository, provided as TAP_GITHUB_TOKEN in the release workflow.
ids:
- writ
# Publishing to the tap needs a token with write access to that
# repository, provided as HOMEBREW_TAP_GITHUB_TOKEN in the release
# workflow. GITHUB_TOKEN is scoped to this repo and cannot push to it.
repository:
owner: sirrobot01
name: homebrew-tap
token: "{{ .Env.TAP_GITHUB_TOKEN }}"
test: |
system "#{bin}/writ --version"
token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
directory: Casks
homepage: "https://docs.writ.build"
description: "Agent orchestration as contract enforcement"
license: "Apache-2.0"
commit_author:
name: goreleaser-bot
email: goreleaser-bot@users.noreply.github.com
# Only publish the cask for stable releases, never prereleases.
skip_upload: auto
caveats: |
Run `writ configure` to create the engagement configuration, then
`writ init <name>` to write your first writ.
# Strip the quarantine xattr so the downloaded binary runs without a
# Gatekeeper prompt.
hooks:
post:
install: |
if OS.mac?
system_command "/usr/bin/xattr",
args: ["-dr", "com.apple.quarantine", "#{staged_path}/writ"]
end

release:
prerelease: auto
footer: |
The record is the product. Issue a writ, read the record, add a clause
when it shows a behavior you want to stop.
14 changes: 14 additions & 0 deletions blog/wrangler.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "writ-blog",
"compatibility_date": "2026-07-25",
"observability": {
"enabled": true
},
"assets": {
"directory": "."
},
"compatibility_flags": [
"nodejs_compat"
]
}
6 changes: 6 additions & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ pnpm-debug.log*

# macOS-specific files
.DS_Store

# wrangler files
.wrangler
.dev.vars*
!.dev.vars.example
!.env.example
187 changes: 96 additions & 91 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,97 +2,102 @@
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';

import cloudflare from '@astrojs/cloudflare';

// https://astro.build/config
export default defineConfig({
site: 'https://docs.writ.build',
integrations: [
starlight({
title: 'writ',
description:
'Writ is a language and a runtime for bounded agent authority. You write the terms. The registrar enforces them.',
favicon: '/writ-favicon-64.png',
customCss: ['./src/styles/writ.css'],
components: {
// The wordmark is the mark: wr, a blinking caret, then t.
SiteTitle: './src/components/SiteTitle.astro',
},
head: [
{ tag: 'link', attrs: { rel: 'preconnect', href: 'https://fonts.googleapis.com' } },
{
tag: 'link',
attrs: { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
},
{
tag: 'link',
attrs: {
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Instrument+Sans:wght@400;500;600;700&display=swap',
},
},
{ tag: 'link', attrs: { rel: 'apple-touch-icon', href: '/writ-appicon-180.png' } },
{ tag: 'meta', attrs: { name: 'theme-color', content: '#10141c' } },
{
tag: 'meta',
attrs: { property: 'og:image', content: 'https://docs.writ.build/writ-og.png' },
},
{ tag: 'meta', attrs: { name: 'twitter:card', content: 'summary_large_image' } },
],
social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/sirrobot01/writ' }],
editLink: { baseUrl: 'https://github.com/sirrobot01/writ/edit/main/docs/' },
lastUpdated: true,
sidebar: [
{
label: 'Start',
items: [
{ label: 'What Writ does', slug: 'start/what-writ-does' },
{ label: 'Install Writ', slug: 'start/install' },
{ label: 'Write your first writ', slug: 'start/first-writ' },
{ label: 'Configure the engagement', slug: 'start/configure' },
],
},
{
label: 'The writ file',
items: [
{ label: 'Structure', slug: 'writ-file/structure' },
{ label: 'Mandate', slug: 'writ-file/mandate' },
{ label: 'Grants', slug: 'writ-file/grants' },
{ label: 'Bounds', slug: 'writ-file/bounds' },
{ label: 'Invariants', slug: 'writ-file/invariants' },
{ label: 'Satisfaction', slug: 'writ-file/satisfaction' },
{ label: 'Obligations', slug: 'writ-file/obligations' },
{ label: 'Remedies', slug: 'writ-file/remedies' },
{ label: 'Placeholders', slug: 'writ-file/placeholders' },
],
},
{
label: 'Concepts',
items: [
{ label: 'The three check layers', slug: 'concepts/layers' },
{ label: 'The registrar', slug: 'concepts/registrar' },
{ label: 'The record', slug: 'concepts/record' },
],
},
{
label: 'Commands',
items: [
{ label: 'writ init', slug: 'cli/init' },
{ label: 'writ check', slug: 'cli/check' },
{ label: 'writ issue', slug: 'cli/issue' },
{ label: 'writ record', slug: 'cli/record' },
{ label: 'writ amend', slug: 'cli/amend' },
{ label: 'writ gate', slug: 'cli/gate' },
{ label: 'writ proxy', slug: 'cli/proxy' },
{ label: 'writ configure', slug: 'cli/configure' },
],
},
{
label: 'Reference',
items: [
{ label: 'Terms', slug: 'reference/terms' },
{ label: 'Exit codes', slug: 'reference/exit-codes' },
],
},
],
}),
site: 'https://docs.writ.build',

integrations: [
starlight({
title: 'writ',
description:
'Writ is a language and a runtime for bounded agent authority. You write the terms. The registrar enforces them.',
favicon: '/writ-favicon-64.png',
customCss: ['./src/styles/writ.css'],
components: {
// The wordmark is the mark: wr, a blinking caret, then t.
SiteTitle: './src/components/SiteTitle.astro',
},
head: [
{ tag: 'link', attrs: { rel: 'preconnect', href: 'https://fonts.googleapis.com' } },
{
tag: 'link',
attrs: { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
},
{
tag: 'link',
attrs: {
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Instrument+Sans:wght@400;500;600;700&display=swap',
},
},
{ tag: 'link', attrs: { rel: 'apple-touch-icon', href: '/writ-appicon-180.png' } },
{ tag: 'meta', attrs: { name: 'theme-color', content: '#10141c' } },
{
tag: 'meta',
attrs: { property: 'og:image', content: 'https://docs.writ.build/writ-og.png' },
},
{ tag: 'meta', attrs: { name: 'twitter:card', content: 'summary_large_image' } },
],
social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/sirrobot01/writ' }],
editLink: { baseUrl: 'https://github.com/sirrobot01/writ/edit/main/docs/' },
lastUpdated: true,
sidebar: [
{
label: 'Start',
items: [
{ label: 'What Writ does', slug: 'start/what-writ-does' },
{ label: 'Install Writ', slug: 'start/install' },
{ label: 'Write your first writ', slug: 'start/first-writ' },
{ label: 'Configure the engagement', slug: 'start/configure' },
],
},
{
label: 'The writ file',
items: [
{ label: 'Structure', slug: 'writ-file/structure' },
{ label: 'Mandate', slug: 'writ-file/mandate' },
{ label: 'Grants', slug: 'writ-file/grants' },
{ label: 'Bounds', slug: 'writ-file/bounds' },
{ label: 'Invariants', slug: 'writ-file/invariants' },
{ label: 'Satisfaction', slug: 'writ-file/satisfaction' },
{ label: 'Obligations', slug: 'writ-file/obligations' },
{ label: 'Remedies', slug: 'writ-file/remedies' },
{ label: 'Placeholders', slug: 'writ-file/placeholders' },
],
},
{
label: 'Concepts',
items: [
{ label: 'The three check layers', slug: 'concepts/layers' },
{ label: 'The registrar', slug: 'concepts/registrar' },
{ label: 'The record', slug: 'concepts/record' },
],
},
{
label: 'Commands',
items: [
{ label: 'writ init', slug: 'cli/init' },
{ label: 'writ check', slug: 'cli/check' },
{ label: 'writ issue', slug: 'cli/issue' },
{ label: 'writ record', slug: 'cli/record' },
{ label: 'writ amend', slug: 'cli/amend' },
{ label: 'writ gate', slug: 'cli/gate' },
{ label: 'writ proxy', slug: 'cli/proxy' },
{ label: 'writ configure', slug: 'cli/configure' },
],
},
{
label: 'Reference',
items: [
{ label: 'Terms', slug: 'reference/terms' },
{ label: 'Exit codes', slug: 'reference/exit-codes' },
],
},
],
}),
],
});

adapter: cloudflare(),
});
Loading
Loading