Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
2b5b52a
fix: rebuild bare resume command to include schema defaults (#799)
Apr 22, 2026
53532e2
fix(profiles): add readiness tuning to cursor provider
m1ddl3w4r3 Apr 23, 2026
e78cf8d
fix(sling): refuse dispatch against bead IDs not in the store
Apr 23, 2026
85a3192
Fix sling missing bead validation
julianknutsen Apr 23, 2026
6fa9aa9
Merge pull request #1141 from boylec/fix/sling-verify-bead-exists
julianknutsen Apr 24, 2026
e1be2b2
api: async city lifecycle endpoints
csells Apr 22, 2026
2718f10
Expand GC bead API contract
csells Apr 22, 2026
c5f8eff
api: fix MC bead graph projections
csells Apr 22, 2026
0f600ea
docs: move API architecture guidance into engdocs
csells Apr 22, 2026
99e4198
test: cover GC supervisor city API paths
csells Apr 22, 2026
b128c11
Expose typed event stream envelope schemas
csells Apr 22, 2026
339354a
fix: address PR 1119 review blockers
julianknutsen Apr 23, 2026
99a8504
fix: address follow-up review findings
julianknutsen Apr 23, 2026
3a3b37d
fix: harden cache reconciliation and city rollback paths
julianknutsen Apr 24, 2026
9fc3423
fix: tighten async city lifecycle contracts
julianknutsen Apr 24, 2026
2dd19c8
fix: seal cache and scaffold race regressions
julianknutsen Apr 24, 2026
de3ca66
fix: fully roll back failed city scaffolds
julianknutsen Apr 24, 2026
44be8d4
fix: preserve concurrent edits during scaffold rollback
julianknutsen Apr 24, 2026
4369b2f
Default Codex model to GPT-5.5 (#1171)
julianknutsen Apr 24, 2026
efa5869
test: fix supervisor constructor call after rebase
julianknutsen Apr 24, 2026
5a85a45
test: make isolated city init tests hermetic
julianknutsen Apr 24, 2026
f14e161
Merge pull request #1119 from gastownhall/mc-support-take-2
julianknutsen Apr 24, 2026
32b2a64
fix: atomically materialize system pack files
julianknutsen Apr 24, 2026
241867d
tune dolt-gc-nudge: unconditional GC every 1h (perf evidence) (#1196)
julianknutsen Apr 25, 2026
62e4881
fix: persist supervisor provider env vars
julianknutsen Apr 25, 2026
c3e6f17
fix: avoid no-op system pack rewrites
julianknutsen Apr 24, 2026
4367ec3
fix: secure supervisor service files
julianknutsen Apr 25, 2026
7ed2d38
Merge pull request #1172 from gastownhall/fix/system-pack-atomic-mate…
julianknutsen Apr 25, 2026
584c265
fix: refresh cache from bd hook events
julianknutsen Apr 25, 2026
73f52d5
Merge pull request #1198 from gastownhall/fix/supervisor-env-vars
julianknutsen Apr 25, 2026
0b8196d
fix(dolt-health): exclude rig-local Dolt servers from zombie scan
boylec Apr 24, 2026
3c024cc
ci: publish asset-based Homebrew formula
julianknutsen Apr 25, 2026
07005b5
docs: document gascity core and emergency tap paths
julianknutsen Apr 25, 2026
48a1e9b
managed dolt: disable upstream load-avg auto-GC scheduler (workaround…
julianknutsen Apr 25, 2026
81ab8dd
Fix gc-beads-bd empty GC scheduler override
julianknutsen Apr 25, 2026
167423b
Merge pull request #1200 from gastownhall/dolt-gc-scheduler-disable
julianknutsen Apr 25, 2026
2ea55af
Reduce cmd/gc test runtime under two minutes (#1245)
julianknutsen Apr 25, 2026
72139e9
fix: preserve cmd/gc process coverage and dolt cleanup
julianknutsen Apr 25, 2026
3341b5a
Merge pull request #1246 from gastownhall/fix/cmd-gc-runtime-under-2m…
julianknutsen Apr 25, 2026
4630840
test: cover settings rebuild in API resume regression
julianknutsen Apr 26, 2026
e4891b9
test(profiles): lock cursor readiness hints
julianknutsen Apr 26, 2026
4b578dc
fix(dolt-health): parse quoted rig ports
julianknutsen Apr 26, 2026
811c368
fix: use --use-db in gc-nudge dolt invocation + darwin stat.Dev cast …
itsthatriver Apr 26, 2026
e5783dc
Merge pull request #1125 from quad341/fix/799-control-dispatcher-pool…
julianknutsen Apr 26, 2026
70c6e79
Merge pull request #1133 from m1ddl3w4r3/fix/cursor-agent-readiness-d…
julianknutsen Apr 26, 2026
da057be
Merge pull request #1218 from boylec/fix/dolt-health-exclude-rig-locals
julianknutsen Apr 26, 2026
65404c4
fix(fsys): cast stat.Dev to uint64 for darwin compatibility (#1208)
boylec Apr 26, 2026
0ef7ce4
fix: include protocolVersion in ACP initialize handshake
tesdal Apr 20, 2026
9188803
feat: add ACPCommand/ACPArgs for transport-specific provider commands
tesdal Apr 20, 2026
7c63487
fix: track ACPCommand/ACPArgs in provider provenance
tesdal Apr 20, 2026
b857263
fix: preserve nil-vs-empty ACPArgs in deepCopy and resolvedChainToSpec
tesdal Apr 20, 2026
1adf9df
fix: preserve stored ACP command on session resume
tesdal Apr 20, 2026
fa6454a
fix: wrap supervisor session provider with auto-provider for ACP agents
tesdal Apr 20, 2026
9ee8a1b
fix: send required params in session/new and use correct field in ses…
tesdal Apr 20, 2026
5f4971e
fix: propagate ACP transport through session startup
julianknutsen Apr 21, 2026
de95cc4
fix: propagate ACP MCP session config
julianknutsen Apr 22, 2026
19cc652
fix: fail fast on ACP routing drift
julianknutsen Apr 22, 2026
214f920
fix: tighten ACP wrapper and resume errors
julianknutsen Apr 22, 2026
1a6ed73
fix: tighten ACP transport capability checks
julianknutsen Apr 22, 2026
b3f1f1f
fix: align ACP session startup with transport
julianknutsen Apr 22, 2026
978951d
fix: fail fast for ACP session routing
julianknutsen Apr 22, 2026
48800d5
fix: validate ACP support across entrypoints
julianknutsen Apr 22, 2026
c210ad8
fix: preserve acp transport semantics
julianknutsen Apr 22, 2026
0b49dfc
fix: restore legacy acp runtime inference
julianknutsen Apr 22, 2026
3f6093b
fix: align agent create identity with acp fallback
julianknutsen Apr 22, 2026
8e0d770
fix: preserve resume identity and mcp resilience
julianknutsen Apr 22, 2026
4a034fa
fix: scope acp defaults and mcp hints
julianknutsen Apr 22, 2026
1966893
fix: propagate provider-aware transport resolver
julianknutsen Apr 22, 2026
5a2b671
fix: persist acp session mcp state
julianknutsen Apr 22, 2026
5ba8802
fix: seed mcp snapshots for deferred session create
julianknutsen Apr 22, 2026
d0dada5
fix: infer legacy acp provider routes
julianknutsen Apr 22, 2026
68c1f24
fix: persist cli acp mcp metadata
julianknutsen Apr 22, 2026
3318ef4
fix: default custom provider sessions to acp
julianknutsen Apr 22, 2026
cd2c9d8
fix: default agent sessions to provider acp
julianknutsen Apr 22, 2026
48410dc
fix: infer provider acp defaults for template sessions
julianknutsen Apr 22, 2026
7366b47
fix: align api resume and dashboard schema
julianknutsen Apr 22, 2026
9e280d0
fix: replay template overrides on resume
julianknutsen Apr 22, 2026
8c74c50
fix: recover provider resume contracts
julianknutsen Apr 22, 2026
ce4031d
fix: persist named session mcp metadata
julianknutsen Apr 22, 2026
419a0ec
fix: avoid legacy transport reinterpretation
julianknutsen Apr 22, 2026
2434a4e
fix: restore legacy acp fallback boundaries
julianknutsen Apr 22, 2026
41bd560
fix: scope mcp metadata to acp sessions
julianknutsen Apr 22, 2026
5838810
fix: preserve legacy acp resume inference
julianknutsen Apr 22, 2026
930b8ac
fix: avoid provider default acp reinterpretation
julianknutsen Apr 22, 2026
d89914b
fix: stop inferring acp for stopped sessions
julianknutsen Apr 22, 2026
334edbc
fix: preserve acp proof without leaking mcp secrets
julianknutsen Apr 22, 2026
a286f22
fix: preserve mcp template branch alias
julianknutsen Apr 22, 2026
5d211b5
fix: honor legacy acp resume metadata
julianknutsen Apr 22, 2026
3a4bec3
fix: preserve legacy acp route proofs
julianknutsen Apr 22, 2026
1433b18
fix: scrub stored mcp resume snapshots
julianknutsen Apr 22, 2026
468ebc0
fix: cache runtime mcp snapshots for resume
julianknutsen Apr 22, 2026
50dc7e1
fix: tighten runtime resume fallbacks
julianknutsen Apr 22, 2026
60c49c6
fix: complete provider patch and mcp fallback wiring
julianknutsen Apr 22, 2026
0d2e185
fix: preserve runtime fallback semantics
julianknutsen Apr 26, 2026
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
36 changes: 20 additions & 16 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
set -euo pipefail

staged_go_files=$(git diff --cached --name-only --diff-filter=ACM -- '*.go' || true)
staged_web_src=$(git diff --cached --name-only --diff-filter=ACM -- 'cmd/gc/dashboard/web/src/' 'cmd/gc/dashboard/web/index.html' 'cmd/gc/dashboard/web/public/' 'cmd/gc/dashboard/web/package.json' 'cmd/gc/dashboard/web/vite.config.ts' 'cmd/gc/dashboard/web/tsconfig.json' || true)
staged_web_src=$(git diff --cached --name-only --diff-filter=ACM -- 'cmd/gc/dashboard/web/src/' 'cmd/gc/dashboard/web/index.html' 'cmd/gc/dashboard/web/public/' 'cmd/gc/dashboard/web/package.json' 'cmd/gc/dashboard/web/openapi-ts.config.ts' 'cmd/gc/dashboard/web/vite.config.ts' 'cmd/gc/dashboard/web/tsconfig.json' || true)
staged_docs=$(git diff --cached --name-only --diff-filter=ACM -- '*.md' 'docs/**' 'engdocs/**' 'plans/**' 'specs/**' 'AGENTS.md' 'CONTRIBUTING.md' 'README.md' 'TESTING.md' || true)

if [ -z "$staged_go_files" ] && [ -z "$staged_web_src" ]; then
if [ -z "$staged_go_files" ] && [ -z "$staged_web_src" ] && [ -z "$staged_docs" ]; then
exit 0
fi

Expand All @@ -22,11 +23,22 @@ if [ -n "$staged_go_files" ]; then
go run ./cmd/genspec
git add internal/api/openapi.json docs/schema/openapi.json docs/schema/openapi.txt

go generate ./internal/api/genclient
git add internal/api/genclient/client_gen.go

# Regenerate the config/schema docs derived from Go structs and
# stage every generated artifact so commits do not leave the
# worktree dirty.
go run ./cmd/genschema
git add docs/schema/city-schema.json docs/schema/city-schema.txt docs/reference/config.md docs/reference/cli.md

make lint
make vet
make test
fi

if [ -n "$staged_docs" ]; then
make check-docs
fi

# Dashboard SPA rebuild: whenever the spec changes OR the SPA source
Expand All @@ -36,20 +48,12 @@ fi
if command -v npm >/dev/null 2>&1; then
spec_changed=$(git diff --cached --name-only --diff-filter=ACM -- 'internal/api/openapi.json' || true)
if [ -n "$spec_changed" ] || [ -n "$staged_web_src" ]; then
(
cd cmd/gc/dashboard/web
if [ ! -d node_modules ]; then
npm install --silent
fi
npm run gen --silent
# Typecheck BEFORE build: vite's build transpiles TS to JS and
# silently ignores type errors. Without this step, SPA type
# regressions against the regenerated spec (e.g. a query param
# tightening from string to boolean) ship unnoticed. `tsc
# --noEmit` fails fast and stops the commit.
npm run typecheck --silent
npm run build --silent
)
# Typecheck BEFORE build: vite's build transpiles TS to JS and
# silently ignores type errors. The Makefile target also runs the
# Vitest suite, builds dist/, and smoke-runs the compiled SPA via
# Vite preview so a bundle that builds but won't serve is caught
# before CI.
make dashboard-check dashboard-smoke
git add cmd/gc/dashboard/web/dist
fi
else
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
packs: ${{ steps.filter.outputs.packs }}
worker: ${{ steps.filter.outputs.worker }}
worker_phase2: ${{ steps.filter.outputs.worker_phase2 }}
cmd_gc_process: ${{ steps.filter.outputs.cmd_gc_process }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
Expand Down Expand Up @@ -70,6 +71,14 @@ jobs:
- 'internal/runtime/**'
- 'internal/config/**'
- 'cmd/gc/**'
cmd_gc_process:
- 'go.mod'
- 'go.sum'
- '.github/workflows/**'
- 'Makefile'
- 'cmd/gc/**'
- 'internal/**'
- 'examples/gastown/packs/**'

# Always runs: lint, fmt, vet, unit tests, docs, acceptance, coverage.
check:
Expand Down Expand Up @@ -148,6 +157,27 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true

cmd-gc-process:
name: cmd/gc process suite
needs: changes
if: needs.changes.outputs.cmd_gc_process == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
env:
DOLT_VERSION: "1.86.1"
BD_VERSION: "v1.0.0"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: ./.github/actions/setup-gascity-ubuntu
with:
dolt-version: ${{ env.DOLT_VERSION }}
bd-version: ${{ env.BD_VERSION }}
install-claude-cli: "true"
- name: Install tools
run: make install-tools
- name: Run cmd/gc process suite
run: make test-cmd-gc-process

# Runs always, but remains non-blocking while integration/provider paths are still stabilizing.
integration-shards:
name: Integration / ${{ matrix.shard_name }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/homebrew-tap-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
run: brew uninstall --force gascity || true

- name: Install gascity from the live tap
run: brew install --build-from-source gastownhall/gascity/gascity
run: brew install gastownhall/gascity/gascity

- name: Run formula test block
run: brew test gastownhall/gascity/gascity
Expand Down
136 changes: 136 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ on:
push:
tags:
- "v*"
# Manual dispatch is only for rerunning a release from a v* tag. Publishing
# jobs below are tag-gated and skip branch refs.
workflow_dispatch:

concurrency:
Expand All @@ -16,6 +18,7 @@ permissions:
jobs:
release:
name: Release
if: ${{ github.repository == 'gastownhall/gascity' && startsWith(github.ref, 'refs/tags/v') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
Expand Down Expand Up @@ -48,3 +51,136 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GORELEASER_CURRENT_TAG: ${{ github.ref_name }}

update-homebrew-formula:
name: Update Homebrew formula
if: ${{ github.repository == 'gastownhall/gascity' && startsWith(github.ref, 'refs/tags/v') }}
needs: release
runs-on: ubuntu-latest
env:
HAS_HOMEBREW_APP: ${{ secrets.HOMEBREW_TAP_APP_ID != '' && secrets.HOMEBREW_TAP_APP_PRIVATE_KEY != '' }}
HAS_HOMEBREW_PAT: ${{ secrets.HOMEBREW_TAP_TOKEN != '' }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- name: Extract version from tag
id: version
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"

- name: Mint Homebrew tap token
id: homebrew-token
if: ${{ env.HAS_HOMEBREW_APP == 'true' }}
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.HOMEBREW_TAP_APP_ID }}
private-key: ${{ secrets.HOMEBREW_TAP_APP_PRIVATE_KEY }}
owner: gastownhall
repositories: homebrew-gascity
permission-contents: write

- name: Generate and push Homebrew formula
if: ${{ env.HAS_HOMEBREW_APP == 'true' || env.HAS_HOMEBREW_PAT == 'true' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_TOKEN: ${{ steps.homebrew-token.outputs.token || secrets.HOMEBREW_TAP_TOKEN }}
run: |
version="${{ steps.version.outputs.version }}"
tag="v${version}"
base_url="https://github.com/gastownhall/gascity/releases/download/${tag}"

gh release download "${tag}" --pattern "gascity_${version}_checksums.txt" --dir /tmp
checksums_file="/tmp/gascity_${version}_checksums.txt"

get_sha256() {
local sha
sha=$(grep "$1" "$checksums_file" | awk '{print $1}')
if [ -z "$sha" ]; then
echo "ERROR: missing checksum for $1" >&2
exit 1
fi
echo "$sha"
}

darwin_arm64_sha=$(get_sha256 "gascity_${version}_darwin_arm64.tar.gz")
darwin_amd64_sha=$(get_sha256 "gascity_${version}_darwin_amd64.tar.gz")
linux_amd64_sha=$(get_sha256 "gascity_${version}_linux_amd64.tar.gz")
linux_arm64_sha=$(get_sha256 "gascity_${version}_linux_arm64.tar.gz")

cat > /tmp/gascity.rb <<FORMULA
# typed: false
# frozen_string_literal: true

class Gascity < Formula
desc "Orchestration-builder SDK for multi-agent coding workflows"
homepage "https://github.com/gastownhall/gascity"
version "${version}"
license "MIT"

on_macos do
if Hardware::CPU.arm?
url "${base_url}/gascity_${version}_darwin_arm64.tar.gz"
sha256 "${darwin_arm64_sha}"
else
url "${base_url}/gascity_${version}_darwin_amd64.tar.gz"
sha256 "${darwin_amd64_sha}"
end
end

on_linux do
if Hardware::CPU.arm?
url "${base_url}/gascity_${version}_linux_arm64.tar.gz"
sha256 "${linux_arm64_sha}"
else
url "${base_url}/gascity_${version}_linux_amd64.tar.gz"
sha256 "${linux_amd64_sha}"
end
end

depends_on "beads"
depends_on "jq"
depends_on "tmux"

on_macos do
depends_on "flock"
end

def install
bin.install "gc"
end

def caveats
<<~EOS
Gas City depends on these runtime tools, installed as dependencies:
beads (bd) - issue tracker
dolt - beads storage (via beads)
flock - file locking
jq - JSON processing
tmux - session management

Get started:
gc init <city-path> # create a new city
gc start <city-path> # start an existing city
EOS
end

test do
assert_match version.to_s, shell_output("#{bin}/gc version")
end
end
FORMULA
sed -i 's/^ //' /tmp/gascity.rb

cd /tmp
git clone "https://x-access-token:${HOMEBREW_TAP_TOKEN}@github.com/gastownhall/homebrew-gascity.git"
cp gascity.rb homebrew-gascity/Formula/gascity.rb
cd homebrew-gascity
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/gascity.rb
git commit -m "gascity ${version}" || echo "No changes to commit"
git push

- name: Skip Homebrew formula update
if: ${{ env.HAS_HOMEBREW_APP != 'true' && env.HAS_HOMEBREW_PAT != 'true' }}
run: echo "No Homebrew tap credential configured; skipping tap update."
11 changes: 3 additions & 8 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,9 @@ release:
prerelease: auto
replace_existing_artifacts: true

# Homebrew distribution is handled by a hand-authored, source-built formula
# that lives outside this repo (in `gastownhall/homebrew-gascity` and, once
# merged, `Homebrew/homebrew-core`). Removed the autogenerated binary-install
# `brews:` block because:
# - homebrew-core rejects binary-only formulae; it requires a source build.
# - Keeping both a GoReleaser-stamped tap formula and a hand-authored
# core formula guarantees drift between the two sources of truth.
# See RELEASING.md for the new flow.
# Homebrew tap distribution is generated by .github/workflows/release.yml after
# GoReleaser uploads all release archives. The tap formula installs the release
# assets directly; no source build or Go toolchain is required for users.

changelog:
sort: asc
Expand Down
27 changes: 18 additions & 9 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ becomes one configuration among many.
has `*_test.go` files next to the code. Integration tests that need real
infrastructure (tmux, filesystem) go in `test/` with build tags.

**The spec is a reference, not a blueprint.** When the DX conflicts
with the spec, DX wins. We update the spec to match.
**The architecture docs are a reference, not a blueprint.** When the DX
conflicts with the docs, DX wins. We update the docs to match.

## Architecture

Expand Down Expand Up @@ -89,9 +89,10 @@ Capabilities activate progressively via config presence.
| 7 | Orders |
| 8 | Full orchestration |

## Architecture specs
## Architecture docs

Read **`specs/architecture.md`** before touching:
Read **`engdocs/architecture/api-control-plane.md`** and
**`engdocs/contributors/huma-usage.md`** before touching:

- `internal/api/` (HTTP + SSE API layer)
- `cmd/gc/` (CLI) — especially anything that constructs events,
Expand All @@ -104,7 +105,7 @@ Read **`specs/architecture.md`** before touching:
`cmd/gc/dashboard/web/src/generated/`

Load-bearing invariants enforced by CI (violating any fails the
build; full rationale is in the spec):
build; full rationale is in the architecture docs):

- **Object model at the center.** `internal/{beads, mail, convoy,
formula, agent, events, session, sling, ...}` is the canonical
Expand All @@ -113,9 +114,9 @@ build; full rationale is in the spec):
domain logic.
- **Typed wire.** No hand-written JSON on any HTTP or SSE wire
path; no `map[string]any` or `json.RawMessage` on wire types
(two documented exceptions live in the spec). All endpoints are
Huma-registered; the OpenAPI spec is generated, never
hand-written (`TestOpenAPISpecInSync`).
(documented exceptions live in the API control-plane doc). All
endpoints are Huma-registered; the OpenAPI spec is generated,
never hand-written (`TestOpenAPISpecInSync`).
- **Typed events.** Every constant in `events.KnownEventTypes`
must have a registered payload via
`events.RegisterPayload(constant, sample)`. Use
Expand All @@ -131,7 +132,7 @@ These decisions are final. Do not revisit them.
`city.toml`, `.gc/` runtime state, and `rigs/` infrastructure.
- **Fresh binary, not a Gas Town fork.** We build `gc` from scratch.
- **TOML for config.** `pack.toml` (definition) and `city.toml` (deployment) are the config files.
- **Tutorials win over spec.** When the spec disagrees, we update the spec.
- **Tutorials win over architecture docs.** When the docs disagree, we update the docs.
- **No premature abstraction.** Don't build interfaces until two
implementations exist.
- **Mayor is overseer, not worker.** The mayor plans; coding agents work.
Expand Down Expand Up @@ -218,6 +219,14 @@ Before considering any task complete:

- `go test ./...` passes
- `go vet ./...` clean
- `.githooks/pre-commit` is active locally (`git config core.hooksPath`
prints `.githooks`) and has run for the staged change
- `make dashboard-check` passes for any change touching `internal/api/`,
`internal/api/openapi.json`, `docs/schema/openapi.*`,
`cmd/gc/dashboard/`, or generated dashboard types
- The dashboard starts locally and serves the app for dashboard/API-schema
changes; use `npm run preview -- --host 127.0.0.1 --port <port>` from
`cmd/gc/dashboard/web` after `make dashboard-check`
- Every exported function has a doc comment
- No premature abstractions
- Tests cover happy path AND edge cases
Expand Down
14 changes: 11 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ contributors. Before making changes, read:
auto-formats staged Go files and, when any Go file is staged,
regenerates `internal/api/openapi.json` and `docs/schema/openapi.json`
from the live supervisor. The hook stages both spec copies so the
committed spec never drifts from what the server actually serves.
committed spec never drifts from what the server actually serves. It also
runs the fast CI-equivalent gates for local changes: `make lint`,
`make vet`, and `make test` for Go changes, and `make check-docs` for
Markdown/docs/spec changes.

**Dashboard SPA.** The dashboard at `cmd/gc/dashboard/web/` is a
TypeScript SPA that talks directly to the supervisor's OpenAPI-typed
Expand All @@ -32,9 +35,14 @@ endpoints. When `internal/api/openapi.json` or files under
spec) and rebuilds `cmd/gc/dashboard/web/dist/` (the compiled bundle
that the Go static server embeds via `go:embed`). The hook needs
Node / npm on your PATH; if npm is missing, the hook warns and
skips the rebuild (CI enforces it). Run `make dashboard-dev` to
skips the rebuild (CI enforces it). The hook runs dashboard typecheck,
Vitest, and production build for dashboard/API-schema changes. Run
`make dashboard-dev` to
iterate with Vite HMR, `make dashboard-build` to produce a fresh
bundle, `make dashboard-check` for typecheck + build + test.
bundle, `make dashboard-check` for typecheck + build + test. For
dashboard or API-schema changes, also smoke the built app with
`npm run preview -- --host 127.0.0.1 --port <port>` from
`cmd/gc/dashboard/web/` and load the served page before pushing.

## Development Workflow

Expand Down
Loading
Loading