Skip to content

Deepen Facts internal contracts#21

Merged
ncode merged 12 commits into
mainfrom
juliano/deepening
Jun 22, 2026
Merged

Deepen Facts internal contracts#21
ncode merged 12 commits into
mainfrom
juliano/deepening

Conversation

@ncode

@ncode ncode commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Summary

Deepens four shallow internal contracts in Facts that had started to cost real time: schema interpretation was duplicated, platform vocabulary was repeated across tests/docs/build tooling, CLI option metadata had already drifted, and host probe behaviour still leaked through category modules.

No public Facts library API change, no new runtime dependency, and the canonical structured fact tree is unchanged. User-visible output is stable except for corrected help/man docs and stricter failures for undocumented or overclaimed schema entries.

Tracked as OpenSpec change deepen-facts-internal-contracts (proposal, design, specs, and tasks included under openspec/changes/).

Why

Four internal contracts were doing more work than their code shape admitted:

  • Schema semantics lived in both schema_test.go and tools/supportedfacts.
  • CLI option metadata lived across validation, app runtime, help/man text, and installed docs — and had drifted (--force-dot-resolution was accepted but undocumented).
  • Platform target vocabulary lived across schema, docs generation, Makefile targets, CI, and category policy.
  • Session owned run-scoped discovery state, but category modules still reached around it to call host/runtime APIs directly.

What changed

1. Schema contract (internal/schema)

  • New internal package owns loading docs/schema/facts.yaml, validating entries, flattening fact trees, platform vocabulary, and schema-path matching.
  • schema_test.go (−211 lines) and tools/supportedfacts (−88 lines) become thin adapters over it instead of each re-implementing parsing and matching.
  • Stricter matching: dynamic keyed maps (disks.*, mountpoints.*) no longer act as blanket approval for arbitrary descendants. Open provider-shaped subtrees stay open only when explicitly marked. Undocumented emitted leaves now fail conformance.

2. CLI option contract (internal/cli/options.go)

  • One internal source of option metadata: canonical names, aliases, arity, repeatability, task flags, conflicts, and documentation rows.
  • Validation, argument helpers, and app helper paths (config-path discovery, external-dir discovery, group-list value handling) all read from it instead of inspecting raw args ad hoc.
  • flag.FlagSet and app execution stay in place — this is shared vocabulary, not a new CLI framework.
  • Fixed documentation drift: --force-dot-resolution added to help/man surfaces while it remains accepted. Drift tests prove every accepted non-hidden option appears in help/man output and the installed man page.
  • Valueless options now reject inline values.

3. Platform target profile (internal/platform/profile.go)

  • One internal profile table keyed by GOOS: target ID, label, support tier, schema visibility, compile/distribution target membership, gate metadata, and coarse capability policy.
  • Replaces duplicated schema/docs platform vocabulary and low-risk OS identity helpers (os/kernel/release facts preserved).
  • Wires low-risk capability gates (filesystems, ZFS, Plan 9 intentionally-absent release facts).
  • Policy-only by design: category modules still own resolver implementation and parsing — no resolver registry, no GOOS-suffixed resolver split (ADR-0010 category organization stays).

4. Session host probe seam (internal/engine/session.go, disks.go, os.go)

  • Extends the Session host seam only where category modules reached around it. Disk, partition, and mountpoint resolution now route through injectable host operations: platform identity, directory reads, globbing, command output, file reads, and stat data.
  • Existing command timeout, context cancellation, logging, and sanitized-environment behaviour preserved.
  • Fake-host tests prove disk/partition/mountpoint facts no longer read the developer host directly; regression tests prove canonical output is unchanged.

Testing

  • gofmt -w on edited files, go test ./..., go vet ./....
  • New/expanded tests: schema contract matching (exact paths, one-segment *, documented vs unknown dynamic children, explicit open subtrees), CLI option drift, platform profile (target IDs, target-set separation, excluded solaris/aix, OS identity, vocabulary alignment), and fake-host disk/partition/mountpoint probes.
  • facts-lab native gates exercised only for slices that change platform probe behaviour or target policy.

Notes

  • Net +2556 / −604 across 33 files; much of the addition is tests and the OpenSpec change docs, offset by deduplication in schema_test.go and tools/supportedfacts.
  • Stricter schema matching is intentional: a failure means an emitted leaf is undocumented or a schema entry is overclaimed — treat it as a contract signal and update schema or resolver output deliberately.

@ncode ncode merged commit 1609798 into main Jun 22, 2026
37 checks passed
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.

1 participant