version: '3' vars: PROJECT_NAME: hyperguild VERSION: sh: git describe --tags --always --dirty 2>/dev/null || echo "dev" SHORT_SHA: sh: git rev-parse --short HEAD tasks: context:sync: desc: Regenerate all harness-specific context files cmds: - bash scripts/context-sync.sh context:sync:claude: cmds: [bash scripts/context-sync.sh claude] context:sync:agents: cmds: [bash scripts/context-sync.sh agents] # ── Development ──────────────────────────────────────────────────────────── start: desc: Start ingestion (requires goreman — go install github.com/mattn/goreman@latest) cmds: - goreman start stop: desc: Stop all hyperguild processes (Ctrl-C in the goreman terminal, or kill by port) cmds: - lsof -ti:3300 | xargs kill -9 2>/dev/null || true - lsof -ti:3200 | xargs kill -9 2>/dev/null || true - echo "hyperguild stopped" hyperguild:dev: desc: Run hyperguild CLI from source (e.g. task hyperguild:dev -- tier) cmds: - go run ./cmd/hyperguild {{.CLI_ARGS}} hyperguild:build: desc: Build the hyperguild binary into ./bin/hyperguild cmds: - mkdir -p bin - go build -o bin/hyperguild ./cmd/hyperguild hyperguild:install: desc: Install hyperguild into $GOBIN cmds: - go install ./cmd/hyperguild ingestion:dev: desc: Run ingestion server in development mode dir: ingestion env: INGEST_BRAIN_DIR: "{{.ROOT_DIR}}/brain" INGEST_PORT: "3300" cmds: - go run ./cmd/server # ── Build ────────────────────────────────────────────────────────────────── build: desc: Build all binaries cmds: - task: hyperguild:build - task: ingestion:build ingestion:build: desc: Build ingestion server binary dir: ingestion cmds: - go build -trimpath -ldflags="-s -w" -o ../bin/ingestion-server ./cmd/server # ── Quality ──────────────────────────────────────────────────────────────── check: desc: Run all checks (context freshness + lint + test + vet + build) across all modules cmds: # Context sync is skipped under CI, matching dma-cli, gitea-mcp, and the # rest of the estate. It is not a preference: context-sync.sh walks UP # the tree for the canonical .context/AGENT.md, which lives in local-dev # and does not exist on a CI runner. Without this guard, the script # silently falls back to "project context only" and regenerates AGENTS.md # and .context/system-prompt.txt shorter than their committed, correct # versions -- so the drift assertion fails every CI run for a purely # environmental reason, not real drift. Verified, not assumed: this is # exactly what was happening here (AGENTS.md 430 lines committed vs. an # 82-line regeneration on the runner). # # The cost is real and worth stating: drift is therefore only ever caught # on a developer machine, or by infra's estate-wide context-sync-drift # CronJob (ADR-0019), which does have canonical access and is the actual # enforcement mechanism now. - cmd: | if [ -n "${CI:-}" ]; then echo "✓ context sync: skipped in CI (no canonical AGENT.md on the runner)" else bash scripts/context-sync.sh drift=$(git status --porcelain -- AGENTS.md CLAUDE.md .context/system-prompt.txt 2>/dev/null) if [ -n "$drift" ]; then echo "ERROR: derived adapters drifted from canonical context." >&2 echo "$drift" >&2 echo "" >&2 echo "Run: git add AGENTS.md CLAUDE.md .context/system-prompt.txt" >&2 echo " git commit -m 'chore: re-sync context adapters'" >&2 exit 1 fi echo "✓ context: canonical and adapters are in sync" fi - task: lint - task: test - task: vet # `build` is in the gate deliberately (hyperguild#120). vet and test walk # ./... , which enumerates the packages that EXIST — so a build target # naming a DELETED package is invisible to both. `task build` pointed at # ./cmd/supervisor for months after that directory was removed, and CI # stayed green the whole time because nothing in check ever built. - task: build - task: security:gitleaks # ── Security ───────────────────────────────────────────── security:gitleaks: desc: Scan the working tree for secrets (gitleaks, fail-closed; skipped if gitleaks absent) dir: '{{.ROOT_DIR}}' cmds: - | GL="$(command -v gitleaks || true)" [ -z "$GL" ] && [ -x "$(go env GOPATH 2>/dev/null)/bin/gitleaks" ] && GL="$(go env GOPATH)/bin/gitleaks" if [ -z "$GL" ]; then echo "⚠ gitleaks not installed — skipping secret scan (CI enforces it)." echo " Install: go install github.com/zricethezav/gitleaks/v8@latest" exit 0 fi "$GL" detect --no-git --redact --config .gitleaks.toml --source . security:gitleaks:history: desc: "One-time FULL-HISTORY secret audit (infra#39 rotation pass; not a per-push gate)" dir: '{{.ROOT_DIR}}' cmds: - | GL="$(command -v gitleaks || true)" [ -z "$GL" ] && [ -x "$(go env GOPATH 2>/dev/null)/bin/gitleaks" ] && GL="$(go env GOPATH)/bin/gitleaks" if [ -z "$GL" ]; then echo "gitleaks not installed: go install github.com/zricethezav/gitleaks/v8@latest" >&2 exit 2 fi echo "Scanning FULL git history (redacted). Known historical leaks are expected" echo "until the infra#39 rotation pass completes — triage against the rotation list." "$GL" detect --redact --config .gitleaks.toml lint: cmds: - golangci-lint run ./... - cd ingestion && golangci-lint run ./... lint:frontmatter: desc: Report brain notes whose YAML frontmatter does not parse (BRAIN=path, FIX=1 repairs in place) cmds: - cd ingestion && go run ./cmd/frontmatterlint {{if .FIX}}-fix{{end}} {{.BRAIN | default "../../brain"}} test: cmds: - go test -race -count=1 ./... - cd ingestion && go test -race -count=1 ./... vet: cmds: - go vet ./... - govulncheck ./... || true - cd ingestion && go vet ./... # ── Git / Release ────────────────────────────────────────────────────────── tag: desc: Create and push a semver tag (usage — task tag version=v1.2.3) preconditions: - sh: '[[ "{{.version}}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]' msg: "version must be semver, e.g. v1.2.3 or v1.2.3-rc.1" - sh: "git diff --quiet && git diff --cached --quiet" msg: "working tree must be clean before tagging" cmds: - git tag -a {{.version}} -m "Release {{.version}}" - git push origin {{.version}} push: desc: Push current branch and tags to origin vars: BRANCH: sh: git rev-parse --abbrev-ref HEAD cmds: - git push origin {{.BRANCH}} --tags