Skip to content

feat(GH-63): machine-enforceable decision-record quality (schemas, validator, index, CI gate)#76

Open
juliusz-cwiakalski wants to merge 20 commits into
mainfrom
feat/GH-63/machine-enforceable-decision-records
Open

feat(GH-63): machine-enforceable decision-record quality (schemas, validator, index, CI gate)#76
juliusz-cwiakalski wants to merge 20 commits into
mainfrom
feat/GH-63/machine-enforceable-decision-records

Conversation

@juliusz-cwiakalski

Copy link
Copy Markdown
Owner

Summary

Makes the decision-record quality invariants GH-46 established (single source of truth for body structure, rigor-aware required fields, lifecycle validity, constraint/driver discipline) machine-enforceable instead of prompt-only, and turns them into a CI gate. Adds a generated, auditable decision index with a health view. Closes #63.

What lands

  • schemas/decision-record-frontmatter.schema.json + decision-planning-summary.schema.json (JSON Schema draft 2020-12), modeling the landed Decision-making refactor: unify agent, process-first guide, type-aware practice #46 nested front matter (classification/governance/ai_assistance/links), validated against the ADR-0001 dogfood record + template.
  • tools/validate-decision-record — stdlib-only CLI (bash + python3/jq; no jsonschema pip dep, no network) enforcing rigor-aware required fields, lifecycle transitions, and the §28.3 negative cases expressible against landed artifacts, with actionable errors. --coverage proves schema↔validator parity by running the validator on each negative fixture.
  • tools/generate-decision-index — deterministic index generator; doc/decisions/00-index.md becomes generated (replaces hand-maintenance). Committed health = time-independent (missing deciders, missing metrics, future-field waivers); overdue reviews are stdout-only so calendar time can't trip CI.
  • /decision-index command (read-only w.r.t. records) + regenerated .ados-claude/.
  • CI gate — new verify-decision-records job alongside the preserved verify-claude-build; path-filtered on doc/decisions/, schemas/, the template/spec, and the tools; runs the validator + schema self-validity + index-drift check + the suites. Failures block merge.
  • PDR-0001 — formalizes the §28.3 scope interpretation (see sign-off below).
  • Docs reconciled: feature-decision-records.md, decision-records-management.md, doc/decisions/README.md, AGENTS.md, doc/tools/*.md.

⚠️ Needs your decision — PDR-0001 (Proposed, R3)

The ticket AC says the validator must "fail each negative case from §28.3." 4 of 14 cases require machinery this ticket lists as non-goals, so they are deferred to siblings with documented ownership (not silently dropped):

PDR-0001 (doc/decisions/PDR-0001-decision-record-validator-scope.md) records this. If you'd rather land all 14 here, say so before merge and I'll expand scope. Otherwise, accepting the PR accepts the PDR.

Review / quality gates (two red-team rounds + one reviewer iteration)

  • RT1 (artifacts, pre-delivery): GO-WITH-CONDITIONS → all conditions addressed (an AC self-contradiction on warn-vs-fail; a CI-drift time-bomb from a time-dependent index dimension; a network/version-check vs 0-network-calls conflict; a coverage-check tautology).
  • @Reviewer iter-1: FAIL → fixed in Phase 10 (a links: {} flow-map parser crash; decision_date pattern not enforced; dead code; mockability) → iter-2: PASS.
  • RT2 (delivered change): SHIP-WITH-CONDITIONS → all conditions addressed in Phase 11 (implemented the ticket's "missing metrics" dimension; missing-fence cascade error; id/filename prefix collision; calendar-invalid dates; LC_ALL=C determinism pin; DM-4 default-rigor explanation).
  • Independent verification (CI-gate exit codes): caught and fixed a CI-breaking bug — the test suites returned exit 1 on all-pass (would have made the gate always red). Fixed (8c72277).

Testing (all green, correct exit codes)

  • tools/.tests/test-validate-decision-record.sh39/39 (exit 0)
  • tools/.tests/test-generate-decision-index.sh14/14 (exit 0)
  • scripts/test-all.sh → 5/5 (exit 0)
  • validate-decision-record --coverage0 uncovered, 18 pattern/enum rules enforcement-proven
  • ADR-0001 and PDR-0001 validate clean (dogfooding); 00-index.md in sync + byte-deterministic across locales; .ados-claude/ regen is a no-op; 0 forbidden deps / network calls; headers via scripts/add-header-location.sh only.

Non-goals (sibling tickets)

Domain catalogs (GH-66), structured evidence ledger + R3 source verification (GH-65), and the verification/retrospective lifecycle agents (GH-64) reuse this schema/index foundation and own the 4 deferred §28.3 cases.

Refs: GH-63

Add planning artifacts for "Machine-enforceable decision-record quality (JSON schemas, validator, index tool, CI gate)": spec, test plan, implementation plan, and PM notes for GH-63 (no implementation yet).

Ticket: #63

Refs: GH-63
Incorporates pre-delivery red-team (#1) review of change artifacts — resolving
AC-GH63-5↔DEC-13 contradiction (C1: non-negotiable-violation reclassified as
non-blocking warning per AC-GH63-6/DEC-13), time-dependent index-determinism
issue (M1→DEC-15: committed index=time-independent only; overdue reviews to
stdout), version-check↔NFR-1 conflict (M3→DEC-14: repo-internal tools omit network
version-check), plus adding decision-record template to CI path filter (M4),
schema-driven coverage check (M5), minor reconciliations (DEC-12/16, lifecycle
matrix DM-5, flags), and PDR-0001 formalizing §28.3 scope interpretation (SD-2)
for human sign-off at PR review.

Refs: GH-63

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes the decision-record standards introduced in GH-46 machine-enforceable by adding JSON Schemas, a stdlib-only validator, a deterministic index generator, and a path-filtered CI gate that blocks malformed decision records and stale indexes.

Changes:

  • Add JSON Schemas for decision-record front matter and decision planning summaries, plus fixtures and tests to keep schema and validator behavior aligned.
  • Introduce tools/validate-decision-record (front matter + cross-field rules, plus non-blocking heuristics) and tools/generate-decision-index (generated doc/decisions/00-index.md + health view).
  • Add a verify-decision-records GitHub Actions job that validates records, checks index drift, and runs the tool test suites when relevant paths change.

Reviewed changes

Copilot reviewed 54 out of 54 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tools/validate-decision-record New validator CLI (front matter + cross-field rules, --summary mode, --coverage coupling)
tools/test-all.sh Adds license header metadata
tools/generate-decision-index New deterministic index generator with committed vs advisory health split
tools/.tests/test-zclaude-unit Adds license header metadata
tools/.tests/test-validate-decision-record.sh New validator test suite (fixtures, coverage, regression guards)
tools/.tests/test-generate-decision-index.sh New generator test suite (determinism, health signals, flags)
tools/.tests/fixtures/positive/ADR-9005-empty-links-flow-map.md Positive fixture covering links: {} parsing regression
tools/.tests/fixtures/positive/ADR-9004-unclassified-r2.md Positive fixture for default-rigor behavior
tools/.tests/fixtures/positive/ADR-9003-accepted-r3-with-reviewers.md Positive fixture for Accepted R3 reviewers requirement
tools/.tests/fixtures/positive/ADR-9002-accepted-r2-with-decider.md Positive fixture for Accepted R2 decider requirement
tools/.tests/fixtures/positive/ADR-9001-template-instantiated-r2.md Positive fixture covering many schema enum fields
tools/.tests/fixtures/positive/ADR-0001-snapshot.md Snapshot fixture of ADR-0001 for dogfooding validation
tools/.tests/fixtures/planning-summary/legacy-alias-summary.json Planning-summary fixture for legacy adr.* alias normalization
tools/.tests/fixtures/planning-summary/generic-summary.json Planning-summary fixture for canonical shape
tools/.tests/fixtures/negative/summary-non-negotiable-violation.json Negative fixture for heuristic warning (non-blocking)
tools/.tests/fixtures/negative/summary-constraint-driver-overlap.json Negative fixture for hard-fail constraint/driver overlap
tools/.tests/fixtures/negative/ADR-9027-accepted-unclassified-missing-decider.md Negative fixture for default-R2 Accepted decider requirement
tools/.tests/fixtures/negative/ADR-9026-invalid-calendar-date.md Negative fixture for semantic date validation
tools/.tests/fixtures/negative/ADR-9022-invalid-rigor.md Negative fixture for invalid nested rigor enum
tools/.tests/fixtures/negative/ADR-9021-malformed-id.md Negative fixture for id pattern enforcement
tools/.tests/fixtures/negative/ADR-9020-malformed-dates.md Negative fixture for date pattern enforcement (multiple fields)
tools/.tests/fixtures/negative/ADR-9019-malformed-decision-date.md Negative fixture for decision_date pattern enforcement
tools/.tests/fixtures/negative/ADR-9018-accepted-missing-verification-criteria.md Negative fixture for Accepted VC heuristic warning (non-blocking)
tools/.tests/fixtures/negative/ADR-9017-accepted-r3-missing-reviewers.md Negative fixture for Accepted R3 reviewers hard-fail
tools/.tests/fixtures/negative/ADR-9016-accepted-missing-decision-date.md Negative fixture for Accepted decision_date non-null hard-fail
tools/.tests/fixtures/negative/ADR-9015-accepted-r2-missing-decider.md Negative fixture for Accepted R2 decider hard-fail
tools/.tests/fixtures/negative/ADR-9014-missing-owners.md Negative fixture for owners minItems violation
tools/.tests/fixtures/negative/ADR-9013-supersedes-mismatch.md Negative fixture for Superseded lifecycle consistency
tools/.tests/fixtures/negative/ADR-9012-impossible-transition.md Negative fixture for impossible lifecycle state
tools/.tests/fixtures/negative/ADR-9011-invalid-status.md Negative fixture for invalid status enum
tools/.tests/fixtures/negative/ADR-9010-invalid-decision-type.md Negative fixture for invalid decision_type enum
tools/.tests/fixtures/negative/ADR-00010-filename-prefix-collision.md Negative fixture for id/filename boundary matching
tools/.tests/fixtures/coverage-map.json Schema-rule to fixture mapping used by --coverage
tools/.lib/frontmatter.sh Shared stdlib-only front-matter parser used by validator + index generator
schemas/decision-record-frontmatter.schema.json JSON Schema for decision-record front matter + x-coverage rules
schemas/decision-planning-summary.schema.json JSON Schema for planning-summary artifacts + x-coverage rules
doc/tools/validate-decision-record.md User guide for the validator CLI
doc/tools/generate-decision-index.md User guide for the index generator + DEC-15 split
doc/spec/features/feature-decision-records.md Spec updates documenting generated index + machine-enforceable gate
doc/guides/decision-records-management.md Guide updates: generated index workflow + validator/index usage
doc/decisions/README.md README updates: index generation + validation pointers
doc/decisions/PDR-0001-decision-record-validator-scope.md New PDR documenting validator negative-case scope interpretation
doc/decisions/00-index.md Updated generated index content (table + health section)
doc/changes/2026-06/2026-06-25--GH-63--machine-enforceable-decision-records/code-review/review-iter-2.md Review artifact documenting iteration-2 PASS
doc/changes/2026-06/2026-06-25--GH-63--machine-enforceable-decision-records/code-review/findings-iter-2.json Structured record of iteration-2 findings
doc/changes/2026-06/2026-06-25--GH-63--machine-enforceable-decision-records/chg-GH-63-pm-notes.yaml PM notes capturing scope decisions + phase results
AGENTS.md Documents the new /decision-index command
.opencode/README.md Adds /decision-index to the command inventory
.opencode/command/decision-index.md New command definition wrapping tools/generate-decision-index
.github/workflows/ci.yml Adds verify-decision-records job (schema validity, validator, drift check, tests)
.ados-claude/skills/decision-index/SKILL.md Generated Claude plugin artifact for /decision-index

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tools/.lib/frontmatter.sh
Comment on lines +203 to +206
except Exception as exc:
sys.stderr.write("frontmatter parse error: %s\n" % exc)
print(json.dumps({}))
sys.exit(0)
Comment on lines +165 to +170
# owners: required + minItems 1
if [[ "$(_jq -r 'has("owners")' <<<"$json")" == "false" ]]; then
VALIDATION_ERRORS+=("[ERROR] ${LOG_TAG} ${fname} (id ${id:-<missing>}): required field 'owners' is missing (minItems: 1).")
elif [[ "$(_jq -r '.owners | length' <<<"$json")" -lt 1 ]]; then
VALIDATION_ERRORS+=("[ERROR] ${LOG_TAG} ${fname} (id ${id:-<missing>}): field 'owners' must have at least one entry (minItems: 1).")
fi
Comment on lines +349 to +354
for rf in decision_id decision_type title hard_requirements decision_drivers alternatives; do
if [[ "$(_jq -r --arg k "$rf" 'has($k)' <<<"$json")" == "false" ]]; then
VALIDATION_ERRORS+=("[ERROR] ${LOG_TAG} ${fname}: planning-summary required field '${rf}' is missing.")
fi
done

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Machine-enforceable decision-record quality (JSON schemas, validator, index tool, CI gate)

2 participants