Skip to content

Add a go-service policy to the policy registry #112

Description

@bkd-dotcom

What this is

signetry-core ships a policy registry: a directory of YAML files, one per repository
shape, that says which paths an AI agent may touch for a given task and which it may not.
Six ship today (signetry_core/policies/):
python-library, node-service, monorepo-service, docs-only, dependency-bump,
ci-workflow-fix. A Go service is missing.

This is the highest-leverage thing you can contribute without touching the kernel: one new
file, no Python, and no test to writetests/test_policy_registry.py is parametrized
over every file in that directory, so your policy is validated the moment it exists.

The deliverable

One file: signetry_core/policies/go-service.yaml. Copy
python-library.yaml
as your starting shape — the # @policy header comments are load-bearing metadata, not
decoration.

A starting point, not a spec to type in verbatim — argue with it, the reasoning is the
contribution:

# @policy id: go-service
# @policy title: Go service (cmd/internal layout, go test)
# @policy summary: A Go service laid out as cmd/ + internal/. The agent may change handlers, business
#   logic and tests, and must keep `go test ./...` and `go vet` green. Generated code,
#   migrations, the container image and CI stay off-limits.
# @policy stack: go, go-modules, gotest
# @policy author: your-github-handle
# @policy blocks: internal/db/migrations/0007_add_index.sql, internal/api/api.gen.go, Dockerfile, .github/workflows/release.yml, deploy/k8s/prod.yaml
# @policy allows: cmd/server/main.go, internal/handler/checkout.go, internal/handler/checkout_test.go, go.mod, README.md
version: 2
task_type: feature-work

allowed_paths:
  - "cmd/**"
  - "internal/**"
  - "pkg/**"
  - "go.mod"
  - "go.sum"
  - "README.md"
  - "CHANGELOG.md"

forbidden_paths:
  # A file ending .gen.go / .pb.go is the OUTPUT of a generator. Hand-editing it
  # makes the checked-in code disagree with the source it was generated from, and
  # the next `go generate` silently reverts the fix.
  - "**/*.gen.go"
  - "**/*.pb.go"
  - "**/zz_generated*.go"
  # Inside internal/** which is otherwise allowed: a migration is applied once and
  # unapplied by hand at 3am. Schema change is a human decision, not agent scope.
  - "internal/db/migrations/**"
  - "**/migrations/**"
  - ".github/**"
  - "Dockerfile*"
  - "deploy/**"
  - "**/.env*"
  - "**/*secret*"

max_files_changed: 15
required_checks:
  - "go build ./..."
  - "go vet ./..."
  - "go test ./..."

policy_owner: your-team
policy_version: "1.0"

The part people get wrong

Your blocks list must include at least one path that sits inside your own
allowed_paths
. Carving an exception out of a directory you otherwise own is the whole
skill. For a Go service that exception is:

internal/db/migrations/**internal/** is allowed wholesale because that's
where the service actually lives, but a migration is applied once and rolled back by hand
under pressure. Schema change is a human decision.

The Go trap worth a comment in the file

go.sum changing while go.mod doesn't is a dependency swap wearing a checksum
update's clothing, and //go:embed pulls a file into the binary without that file
looking dangerous — an embedded template or cert bundle ships in the artifact. Decide
deliberately whether go.sum belongs in your allowlist and say why in a comment.

Acceptance criteria

  • signetry_core/policies/go-service.yaml exists; filename matches @policy id.
  • blocks and allows each list 3–4 realistic paths for this stack, and don't overlap.
  • At least one blocks entry is inside allowed_paths.
  • Every forbidden_paths entry that isn't self-evident carries a comment saying why,
    not just that it is. python-library forbids conftest.py at any depth and the comment
    explains it executes at collection time on every developer machine — that is the bar.
  • pytest tests/test_policy_registry.py is green. The suite proves each claimed block is
    actually refused by the real evaluate_contract, so a policy that misleads adopters
    fails CI rather than shipping.
  • If the policy permits something risky, it says so in a caution:signetry init
    prints it at adoption time. A risky policy with no caution gets sent back; a risky
    policy that's honest is fine.

Getting started

The full numbered walkthrough, including what makes a policy worth merging, is in
docs/site/policy-registry.md → "Contributing a policy".

git clone https://github.com/Signetry/core && cd core
uv sync
uv run pytest tests/test_policy_registry.py -q
uv run signetry policies          # your entry should appear here once the file exists

Comment to claim it — one policy per contributor so nobody's work gets duplicated. Happy to
review a half-finished scope list; the reasoning matters more than the YAML.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions