Skip to content

refactor: naming-standard hard cut — tfpfgen, noun-group CLI, one glossary - #101

Merged
ShocOne merged 6 commits into
mainfrom
refactor/naming-standard
Aug 4, 2026
Merged

refactor: naming-standard hard cut — tfpfgen, noun-group CLI, one glossary#101
ShocOne merged 6 commits into
mainfrom
refactor/naming-standard

Conversation

@ShocOne

@ShocOne ShocOne commented Aug 4, 2026

Copy link
Copy Markdown
Member

Why

The project's naming grew organically under LLM-driven development and drifted into inconsistency: mixed noun/verb commands, two global flags that were registered but never read, -only with four different meanings, plan carrying five senses (colliding with terraform plan), snapshot/gate/fixture/archetype/promote each meaning two or three things, Kind typed five ways with colliding constants, the pipeline documented five conflicting ways, and the tool itself named five different ways.

This PR is the approved hard cut: HashiCorp/industry-aligned vocabulary, noun-group CLI grammar, the tfpfgen stem, no deprecation aliases. The complete old→new mapping table is in the CHANGELOG; the normative term inventory is the new docs/glossary.md.

What changed

Tool name — binary tfpluginframeworkgentfpfgen (the stem the TFPFGEN_ env prefix and tfpfgen-probe object prefix already used); dot-dir .tfpfgen/. Repo/module name unchanged.

CLI grammar — every command is tfpfgen <noun> <verb>, generalising the verb-table pattern interop introduced:

Old New
specs openapi fetch
ingest blueprint draft
merge blueprint merge
probe -mode record|replay|verify|sweep, -list probe record|replay|verify|sweep|list (bare probe still = replay)
emit provider generate
verify provider generate -check
bindings (+-facts-out/-facts-check) bindings check + bindings facts -out [-check]
interop export|import spec export|import

One flag lexicon-out for the primary output everywhere; selection flags named for the noun they select (-resource, -tag, -probe); -dry-run as the single preview idiom; -check as the single drift-check idiom; -allow-*/-skip-* booleans; -scenario/-recording; vendor-neutral -summary; -chdir with -C shorthand; single-dash everywhere. The dead -v and -config globals are deleted outright — they were never read.

Vocabulary (one word, one meaning): probe worksheet → scenario (<key>.scenario.json); probe evidence → recording (recordings/); CI job → check (docs/checks.md); sandbox admission → guard; the generation stage → generate (emit deleted, render = internal template execution only); protocol→probe, wave→batch, archetype→scaffold template. "spec" always means HashiCorp's Provider Code Specification; the upstream document is "the OpenAPI document".

Go surface — packages internal/generate (ex render+emit), internal/openapi, internal/snapshot, internal/spec; enum constants carry their type names (ConfidenceObserved, BlockKindResource, ProbeKindRead, …), dissolving the five-way Kind collision; conceptually colliding generics split (probe.FactSet, cassette.Leak, openapi.Caveat, spec.Loss); cassette.Record vs snapshot.Pin; generated code registers through one TypeName constant with one import-alias scheme.

Data — committed trees renamed (openapi/, recordings/, specs/); blueprint key fixes alerts_rulealert_rule, dashboards_filterdashboard_filter, TestsDnssecTestsDNSSEC; the pilot fully regenerated. SDK-owned spellings (dashboards_filters, DashboardsFilters, AlertRules) and HashiCorp's own (planModifiers, TestStep.ResourceName) are deliberately untouched.

Docs & CI — one canonical pipeline statement, drawn as Mermaid in README/architecture/cli.md; docs/cli.md rewritten and held to the binary by a new unit test (TestUnit_CLI_DocsMatchTheBinary) that fails on missing flags/verbs and retired spellings; probing.md sheds its phantom pagination probe and cassette.json and gains the four confidence levels; all workflows, linter configs and CODEOWNERS updated; dependancy-review.ymldependency-review.yml.

Breaking changes

  • Every CLI spelling above; no aliases were kept.
  • Terraform types thousandeyes_alerts_rulethousandeyes_alert_rule and thousandeyes_dashboards_filterthousandeyes_dashboard_filter — existing state referencing the pilot provider's old types must migrate.

Verification

  • go build ./... && go test ./... clean in both modules (root + pilot), every commit.
  • tfpfgen provider generate -check passes against the regenerated pilot; generation is idempotent.
  • tfpfgen probe verify re-derives identical facts from the renamed recordings, offline.
  • tfpfgen spec export is stable against the committed Provider Code Specification.
  • The cli.md drift test proves the reference matches the binary's registered flag sets.

🤖 Generated with Claude Code

ShocOne and others added 6 commits August 4, 2026 11:35
…it colliding generic types

Every enum constant now carries its full type name (ProbeKind*, EntryKind*,
Confidence*, Outcome*, Source*, BlockKind*, CandidateKind*, RegistryKind*),
dissolving the five-way Kind collision and the bare Observed/Absent/
ServerDefault constants. Conceptually colliding generics diverge:
probe.Findings -> FactSet, cassette.Finding -> Leak, openapi.Note -> Caveat,
interop.Note -> Loss. quirkserver now consumes apierr's Envelope enum instead
of duplicating it. GateOptions -> GuardOptions ahead of the gate -> guard
vocabulary split. UpdateMergePatch -> UpdatePatchMerge so constant and value
agree on word order. naming gains the DNSSEC initialism, and the previously
dead AccTestName helper becomes the single source for generated acceptance
test names, called from all five render sites.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ecstore, interop and ingest/openapi packages

One package per pipeline stage, named for its command: internal/render and
internal/emit collapse into internal/generate (render survives as the internal
template-execution verb only), internal/specstore becomes internal/snapshot
(it stores pinned OpenAPI snapshots -- 'spec' is reserved for HashiCorp's
Provider Code Specification), internal/interop becomes internal/spec to match,
and the empty internal/ingest shell around internal/ingest/openapi is gone.
cassette.Record replaces cassette.Write, de-twinning it from snapshot.Pin.
HashiCorp's own spec package is imported as hcspec wherever both meet.
emit.Options -> generate.BuildOptions and emit.Plan -> generate.Fileset,
retiring the last in-repo sense of the word 'plan' from the emit side.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The binary is now tfpfgen -- the stem the env prefix (TFPFGEN_) and probe
object prefix already used -- and the dot-dir follows as .tfpfgen/. Every
command is <noun> <verb>, generalising the verb-table pattern interop
introduced: specs -> openapi fetch, ingest -> blueprint draft, merge ->
blueprint merge, emit -> provider generate, verify -> provider generate
-check, bindings -> bindings check + bindings facts, interop -> spec
export/import, probe -mode X -> probe record|replay|verify|sweep|list with
bare probe still defaulting to the safe replay verb.

Flags now follow one lexicon: -out for the primary output everywhere
(kills -output-dir, -facts-out), selection flags named for the noun they
select (-resource, -tag, -probe; kills the four-way -only), -dry-run as
the single preview idiom (kills -list-as-flag), -check as the single
drift-check idiom (absorbs the verify command and -facts-check),
-allow-conflicts and -skip-rehearsal for opt-in/opt-out booleans,
-recording for the evidence marker (was -snapshot-id), -scenario/
-scenario-dir for probe worksheets (was -plan/-plan-dir), -adopt-scenarios
(was -promote-plans), and vendor-neutral -summary (was -github-summary).
The dead -v and -config globals are deleted outright -- they were
registered but never read -- and -chdir arrives with -C as its shorthand.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rint key fixes

The probe worksheet is now a scenario: probe.Plan -> probe.Scenario,
KEY.probe.plan.json -> KEY.scenario.json (drafts keep the load-bearing
.draft. infix), and the frozen copy inside a recording is scenario.json.
merge's evidence marker is RecordingID. The committed artefact trees are
renamed to match the glossary: openapi-specs/ -> openapi/, probe-evidence/
-> recordings/, interop-specs/ -> specs/, and the tool dot-dir is .tfpfgen/
everywhere including the pilot's committed manifest. The sandbox admission
test keys move from GATE to GUARD wording, and BlockKindDataSource's value
joins the camelCase enum rule as "dataSource".

Blueprint data fixes: alerts_rule -> alert_rule and dashboards_filter ->
dashboard_filter (keys, names, Go identifiers and recordings; the SDK's own
package and service spellings -- dashboards_filters, DashboardsFilters --
are theirs and stay), and TestsDnssec -> TestsDNSSEC. The committed
provider-code-spec.json is re-exported; probe verify re-derives identical
facts from the renamed recordings and bindings still resolve against the
pinned SDK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…es and corrected keys

Every generated block kind now registers through one constant name,
TypeName, instead of four per-kind spellings, and import aliases follow one
prefix scheme (v7AlertRule, v7TagData, v7CredentialEph -- the ephemeral's
ephV7Credential inversion is gone). The regenerated tree picks up the
alert_rule and dashboard_filter keys, the TestsDNSSEC initialism casing,
and the .tfpfgen manifest location. terraform-plugin-testing's own
TestStep.ResourceName field keeps HashiCorp's spelling. provider generate
-check passes against the regenerated tree and the pilot module builds and
tests clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e, CI grammar

One canonical pipeline statement -- openapi fetch -> blueprint draft ->
[probe record -> blueprint merge] -> provider generate -- replaces the five
conflicting versions, drawn as a Mermaid diagram in the README,
architecture.md and cli.md. docs/cli.md is rewritten against the binary and
held there by a unit test that asserts every command, verb, verbatim usage
line and registered flag appears on the page and that no retired spelling
does. New docs/glossary.md is the normative term inventory (one meaning per
term); blueprint.md's terminology section stays as the doctrine and points
at it. gates.md becomes checks.md (CI jobs are checks; the sandbox
admission is the guard), probing.md sheds its phantom pagination probe and
cassette.json, documents report.json and the four confidence levels, and
every doc, workflow, linter config and CODEOWNERS entry speaks the new
grammar and paths. dependancy-review.yml is finally dependency-review.yml.
The CHANGELOG carries the complete old->new mapping table for the hard cut.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ShocOne
ShocOne merged commit b5030b4 into main Aug 4, 2026
8 of 11 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