Files
settled-reach/governance
jpmschweitzerandClaude Opus 5 5cdb3e9327 feat(config): T-1262 — parity is facts and exit codes, not bytes
schemas.py becomes pydantic, so the reference domain is the normal pattern
rather than an exception carrying a footnote. Frozen: a result is a statement
about what was found, and nothing downstream should edit the finding on its way
to being reported. pydantic stays off the --help path — test_lazy_domains still
passes, which is precisely the assertion that it loads with the domain and not
with the CLI.

The acceptance criterion could not be met as written, and that is the finding
worth keeping. It asked for byte-for-byte parity with the old script; D-263 was
amended after this ticket to give reach a streaming model that puts the verdict
on stderr, while the old script writes its success line to stdout. Measured:
the text is byte-identical in text mode, only the stream differs. Matching both
would mean abandoning streaming or special-casing every ported gate.

So parity is redefined, and it is stronger than bytes where it counts: exit
codes match exactly, no fact the old message carried is lost, and failures name
a remedy as a structured field. That governs every port in T-1251, not just
this one, so it is in D-263 rather than only here.

test_check_parity.py runs three paths — ok, drift, missing file — through both
implementations and compares. It builds a throwaway fixture repo and copies the
OLD script into it, because that script resolves its root from __file__ and has
no override; the new command just takes SR_REPO_ROOT. That asymmetry is part of
why the port earns its keep. It also asserts the failing paths actually exit
non-zero, without which "the exit codes matched" would be vacuous for two
checks that both silently pass.

Proven to fail twice before being trusted. Once by accident: the first version
asserted the yaml version appears on every failing path, which the old script
does not report when the client file is missing — the test was wrong, not the
code, and it now derives expected facts from what the old output actually
contains. Once on purpose: mutating the router to drop a version made it fail
and name the missing fact.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 13:45:39 +02:00
..

Governance — Decisions, Questions, Rejected

Structured planning records for The Settled Reach. pql decisions sync parses these into .pql/pql.db; query them with pql decisions ….

Layout

Records live in three per-type subdirectories, split by domain:

governance/
  decisions/<domain>.md   # D-NNN — confirmed design decisions
  questions/<domain>.md    # Q-NNN — open questions (may resolve into a D or R)
  rejected/<domain>.md     # R-NNN — rejected alternatives (kept for the audit trail)

The parser infers record type from the parent subdirectory and domain from the filename stem. A ### D-NNN: Title (or Q-/R-) heading begins each record; - **Field:** value lines and inline [D-NNN](…#anchor) links carry the metadata and cross-references pql indexes.

Current domains: architecture, content, economics, perception, process, scope. Create a new <domain>.md in the relevant subdir when records land in a new domain.

Domain guide

When in doubt where a record belongs:

  • architecture — constrains how we build (engine, protocols, data structures, performance).
  • scope — defines what we build (game concept, feature scope, prototype shape).
  • perception — defines what the player observes or knows (camera, fog, LOS, audio).
  • content — defines narrative, NPCs, dialogue, setting, templates.
  • economics — the economics layer (currencies, commodities, corporations, simulation).
  • process — defines how the team works (workflow, commits, branches, reviews).

Cross-domain records live in one file with [D-NNN](../<subdir>/<domain>.md#…) links to the related domain.

Querying

pql decisions list                              # every record
pql decisions list --type confirmed --domain architecture
pql decisions show D-010 --with-tickets         # a record + its implementing tickets
pql decisions read D-238                         # full markdown body
pql decisions refs D-010                          # cross-references in/out
pql decisions coverage                            # decisions ↔ ticket coverage

Adding a record

  1. Claim an ID (no side effects): pql decisions claim D <domain> "title" (use Q for a question, R for a rejected alternative).
  2. Edit the appropriate file (decisions/<domain>.md, questions/<domain>.md, or rejected/<domain>.md). Follow the existing ### D-NNN: Title format.
  3. Commit. The pre-commit hook runs pql decisions validate (malformed-record gate) and stages the planning changelog.
  4. Update relevant agent briefings if needed.

When a question resolves, set its - **Status:** Resolved → [D-NNN](../decisions/<domain>.md#…) line in place — keep the Q-record for the audit trail rather than deleting it.

Maintained by Qatux.

Decisions

Open questions

Resolved questions

Rejected