Documentation
¶
Overview ¶
Package generator: checksums shim.
The canonical ownership-state type (FileChecksums: disowned paths + the scoped unstampable-format hashes) and the self-certification write helpers live in internal/checksums so that internal/codegen (per-feature emitters) can also import them without an import cycle (generator already imports codegen). Existing call sites in the cli/ and generator/ packages continue to work via the re-exports below.
Package generator orchestrates project scaffolding: it lays down a new project, scaffolds individual services / workers / operators / webhooks / frontends, regenerates infra files on upgrade, and emits the plan-mode entity / proto / ORM / migration files.
The behavioural surface is split into two narrow Services:
- Service — the file-emission orchestrator (every file the scaffolder writes into the user project).
- ConfigService — read / write / mutate forge.yaml on disk.
Data carriers (FileChecksums, Harness, ProjectGenerator, SeedEntity, E2EMethodInfo, UpgradeResult, ServiceInfo, *TemplateData structs) remain plain types — they have no behavioural seam to mock.
Code generated by forge. DO NOT EDIT. forge:hash=98e97e1048ae6c493fcae42242d9101992bc27ce2e8ad1f6676ccd197db1c03b forge-owned: regenerated every run — do not edit (forge disown to take ownership) Source: contract.go in this package.
To customize: edit contract.go (the interface IS the public surface) and re-run "forge generate". This file is regenerated unconditionally.
Package generator — forge/pkg dependency resolution for scaffolded go.mod files.
Generated service projects import github.com/reliant-labs/forge/pkg/* (serverkit, appkit, orm, ...). How a fresh scaffold satisfies that dependency depends on how the running forge binary was built:
RELEASE flow: release builds of forge are stamped (via ldflags, see cmd/forge/main.go PkgVersion) with the published forge/pkg version they were released against — pkg/vX.Y.Z submodule tags created by scripts/release-pkg.sh. The scaffolded go.mod pins `require github.com/reliant-labs/forge/pkg vX.Y.Z` with NO replace; `go mod tidy` resolves it from the module proxy like any other dependency.
DEV flow: dev builds have no published (ldflags-stamped) pkg version. When the new project sits next to a forge checkout (the common `~/src/{forge,myproject}` layout), the scaffolded go.mod gets a host-absolute `replace github.com/reliant-labs/forge/pkg => <sibling>/forge/pkg`; the first `forge generate` then vendors that source into <project>/.forge-pkg/ and rewrites the replace to `./.forge-pkg` so docker builds see the same code (see internal/cli/dev_pkg_replace.go).
With no sibling checkout either (the daemon and any `go install`'d forge), we pin the forge/pkg pseudo-version THIS binary was built against, read from its own build info (buildinfo.PkgModuleVersion) — a real, proxy-resolvable, already-cached version. This is what lets a fresh scaffold's per-module `go mod tidy` (root AND the separate gen/ submodule, which the go.work replace does NOT reach) resolve forge/pkg instead of choking on the unresolvable `v0.0.0` the templates used to hard-code. Only when even the build info carries no usable version (a local go.work build, where forge/pkg shows as "(devel)") is nothing emitted and `go mod tidy` left to resolve a pseudo-version from the proxy — the historical fallback.
The full model is documented in docs/pkg-versioning.md.
Index ¶
- Constants
- func AppendFrontendToConfig(projectRoot, frontendName string, port int) error
- func AppendFrontendToConfigWithKind(projectRoot, frontendName string, port int, kind string) error
- func AppendServiceToConfig(projectRoot, serviceName string, port int) error
- func EnsureCoreComponents(frontendDir string) error
- func ForUpgrade(cfg *config.ProjectConfig, projectDir string) projectTemplateData
- func GenerateBinaryFiles(root, modulePath, binaryName string) error
- func GenerateCRDFiles(in CRDGenInput) error
- func GenerateE2ETests(projectDir, serviceName, modulePath, projectName string, ...) error
- func GenerateEntitySeeds(entities []SeedEntity, outputDir string) error
- func GenerateFrontendFiles(root, modulePath, projectName, frontendName string, apiPort int, kind string) error
- func GenerateFrontendFilesWithOptions(root, modulePath, projectName, frontendName string, apiPort int, kind string, ...) error
- func GenerateGrafanaDashboards(projectName, projectDir string) error
- func GenerateOperatorBinaryOnly(root, modulePath, name, group, version string) error
- func GenerateOperatorFiles(root, modulePath, name, group, version string) error
- func GenerateOperatorFilesWithAPI(root, modulePath, name, group, version, apiPackage, crdType string) error
- func GeneratePlanORM(root, modulePath, serviceName string, entities []config.PlanEntity, ...) error
- func GeneratePlanProtoFile(root, modulePath, serviceName string, rpcs []config.PlanRPC, ...) error
- func GenerateServiceFiles(root, modulePath, serviceName, projectName string, port int) error
- func GenerateServiceFilesWithMode(root, modulePath, serviceName, projectName string, port int, mode ScaffoldMode, ...) error
- func GenerateWebhookFiles(root, modulePath, serviceName, webhookName string) error
- func GenerateWorkerFiles(root, modulePath, workerName, kind, schedule string) error
- func HashContent(content []byte) string
- func ReadProjectConfig(path string) (*config.ProjectConfig, error)
- func RecordFrozenChecksums(projectDir, binary, kind string) error
- func RegenerateInfraFiles(projectDir string, cfg *config.ProjectConfig) error
- func RegenerateInfraFilesTracked(projectDir string, cfg *config.ProjectConfig, cs *FileChecksums) error
- func SaveChecksums(root string, cs *FileChecksums) error
- func Tier2ManagedPaths() map[string]bool
- func UpgradeManagedPaths() map[string]bool
- func WriteFrontendWorkspaceFiles(projectDir, projectName string, workspaces bool) error
- func WriteGeneratedFile(root, relPath string, content []byte, cs *FileChecksums, force bool) (bool, error)
- func WriteGeneratedFileTier1(root, relPath string, content []byte, cs *FileChecksums, force bool) (bool, error)
- func WriteProjectConfigFile(cfg *config.ProjectConfig, path string) error
- func WriteScaffoldIfMissing(root, relPath string, content []byte) (bool, error)
- func WriteUINativePackageFiles(projectDir string, layout FrontendWorkspaceLayout) error
- func WriteUIWebPackageFiles(projectDir, projectName string, workspaces bool) error
- type BinaryBuild
- type CRDGenInput
- type CRDShape
- type ConfigService
- type Deps
- type DisownedEntry
- type E2EMethodInfo
- type E2ETemplateData
- type FileChecksums
- type FrontendGenOptions
- type FrontendWorkspaceLayout
- type Harness
- type MockConfigService
- func (m *MockConfigService) AppendFrontendToConfig(projectRoot string, frontendName string, port int) error
- func (m *MockConfigService) AppendFrontendToConfigWithKind(projectRoot string, frontendName string, port int, kind string) error
- func (m *MockConfigService) AppendServiceToConfig(projectRoot string, serviceName string, port int) error
- func (m *MockConfigService) ReadProjectConfig(path string) (*config.ProjectConfig, error)
- func (m *MockConfigService) WriteProjectConfigFile(cfg *config.ProjectConfig, path string) error
- type MockService
- func (m *MockService) EnsureCoreComponents(frontendDir string) error
- func (m *MockService) GenerateE2ETests(projectDir string, serviceName string, modulePath string, projectName string, ...) error
- func (m *MockService) GenerateEntitySeeds(entities []SeedEntity, outputDir string) error
- func (m *MockService) GenerateFrontendFiles(root string, modulePath string, projectName string, frontendName string, ...) error
- func (m *MockService) GenerateGrafanaDashboards(projectName string, projectDir string) error
- func (m *MockService) GenerateOperatorFiles(root string, modulePath string, name string, group string, version string) error
- func (m *MockService) GeneratePlanORM(root string, modulePath string, serviceName string, ...) error
- func (m *MockService) GeneratePlanProtoFile(root string, modulePath string, serviceName string, rpcs []config.PlanRPC, ...) error
- func (m *MockService) GenerateServiceFiles(root string, modulePath string, serviceName string, projectName string, ...) error
- func (m *MockService) GenerateWebhookFiles(root string, modulePath string, serviceName string, webhookName string) error
- func (m *MockService) GenerateWorkerFiles(root string, modulePath string, workerName string, kind string, ...) error
- func (m *MockService) HashContent(content []byte) string
- func (m *MockService) LoadChecksums(root string) (*FileChecksums, error)
- func (m *MockService) RegenerateInfraFiles(projectDir string, cfg *config.ProjectConfig) error
- func (m *MockService) SaveChecksums(root string, cs *FileChecksums) error
- func (m *MockService) Upgrade(projectDir string, cfg *config.ProjectConfig, force bool, checkOnly bool) ([]UpgradeResult, error)
- func (m *MockService) WriteGeneratedFile(root string, relPath string, content []byte, cs *FileChecksums, force bool) (bool, error)
- type ProjectGenerator
- type ScaffoldMode
- type SeedEntity
- type SeedField
- type SeedFieldType
- type Service
- type ServiceInfo
- type Tier1DriftEntry
- type UpgradeResult
- type UpgradeStatus
Constants ¶
const ( // Tier1 files are always overwritten by forge generate and gitignored. // These are pure infrastructure, 100% derivable from forge.yaml. Tier1 = 1 // Tier2 files are checksum-protected and committed to git. // Overwritten only if the user hasn't modified them. Tier2 = 2 )
File ownership tiers.
Variables ¶
This section is empty.
Functions ¶
func AppendFrontendToConfig ¶
AppendFrontendToConfig reads the project config at the given project root, appends a new frontend entry, and writes it back. It uses yaml.Node round-tripping so that unknown keys, comments, and field ordering added by the user are preserved.
func AppendFrontendToConfigWithKind ¶
AppendFrontendToConfigWithKind is like AppendFrontendToConfig but accepts a kind parameter ("web" or "mobile") to select the frontend type.
func AppendServiceToConfig ¶
AppendServiceToConfig is RETIRED: forge no longer writes a components.json manifest — services are discovered from the proto descriptor. It stays as a no-op because it is part of the ConfigService contract (interface + mock); callers in the add/new flow may still invoke it, but it never touches disk.
func EnsureCoreComponents ¶
EnsureCoreComponents installs any missing core components into an existing frontend directory. Safe to call repeatedly — only writes files that don't already exist.
func ForUpgrade ¶
func ForUpgrade(cfg *config.ProjectConfig, projectDir string) projectTemplateData
ForUpgrade builds the render payload for the upgrade / Tier-1 regeneration lane from a *config.ProjectConfig. It reproduces, verbatim, the derivations the old buildTemplateData performed.
projectDir (when non-empty) is used to read the project's go.mod `go` directive so upgrade doesn't silently retarget the project to the host's Go version, to parse proto/config for the live ConfigFields set, and to detect the dev-mode .forge-pkg/ vendoring state. When projectDir is empty or go.mod can't be parsed, we fall back to the host's detected version.
func GenerateBinaryFiles ¶
GenerateBinaryFiles emits the files that make up a non-server long-running binary scaffold:
- cmd/<package>/main.go thin standalone main (own cmd/<bin>/ tree)
- internal/<package>/<package>.go main loop with Start/Stop/Run lifecycle
- internal/<package>/contract.go Deps, Service interface, New(deps)
- internal/<package>/<package>_test.go basic lifecycle test
The shape is deliberately opinionated: the scaffold solves the boilerplate (signal handling, graceful shutdown, config loading) so the user can hand-write only the binary's actual business logic.
Each binary gets its OWN cmd/<bin>/ tree (devspace idiom): the primary server binary lives under cmd/<server>/ with the full command tree, and each secondary binary added here gets cmd/<package>/main.go — a thin, self-contained main rather than a subcommand of the server. At deploy time KCL emits one Deployment per binary, each running its own image.
CLI/display name (which may contain hyphens) is translated to a Go- package-safe form for the directory and `package` declaration; the hyphenated form is preserved on the cobra `Use:` field.
func GenerateCRDFiles ¶
func GenerateCRDFiles(in CRDGenInput) error
GenerateCRDFiles scaffolds a single CRD into an existing operator:
- api/<version>/<lower-name>_types.go — CRD spec/status types
- internal/operators/<operator>/<lower-name>_controller.go — thin shim
- internal/operators/<operator>/<lower-name>_controller_test.go — fake-client unit test
The operator must already exist; generation is idempotent in the sense that re-running with the same inputs overwrites the three generated files (no merge), but it does NOT rebuild the operator's types.go (placeholder CRD or otherwise).
func GenerateE2ETests ¶
func GenerateE2ETests(projectDir, serviceName, modulePath, projectName string, methods []E2EMethodInfo) error
GenerateE2ETests renders E2E test templates into e2e/<servicePackage>/ under projectDir. It does not overwrite existing files — only creates new ones.
func GenerateEntitySeeds ¶
func GenerateEntitySeeds(entities []SeedEntity, outputDir string) error
GenerateEntitySeeds generates SQL seed files and JSON fixture files for the given entities. SQL files go to <outputDir>/db/seeds/0002_<table>.sql and JSON files go to <outputDir>/db/fixtures/<table>.json.
func GenerateFrontendFiles ¶
func GenerateFrontendFiles(root, modulePath, projectName, frontendName string, apiPort int, kind string) error
GenerateFrontendFiles generates the frontend directory and files. kind selects the template set: "" or "web" for Next.js, "mobile" for React Native. Both the "new" project flow and the "add frontend" flow delegate here so the output is always identical.
This thin shim preserves the original signature for backward compatibility with the Service contract; new call sites should prefer GenerateFrontendFilesWithOptions when they have access to the project-level Frontend config.
func GenerateFrontendFilesWithOptions ¶
func GenerateFrontendFilesWithOptions(root, modulePath, projectName, frontendName string, apiPort int, kind string, opts FrontendGenOptions) error
GenerateFrontendFilesWithOptions is GenerateFrontendFiles with an extra FrontendGenOptions param for project-level toggles (today only Workspaces). The default-zero opts struct produces output byte-identical to GenerateFrontendFiles so existing callers and snapshot tests are unaffected.
func GenerateGrafanaDashboards ¶
GenerateGrafanaDashboards is the standalone entry point callable from both `forge new` (via ProjectGenerator) and `forge generate`. It writes Grafana dashboards and provisioning config into deploy/observability/grafana/.
func GenerateOperatorBinaryOnly ¶
GenerateOperatorBinaryOnly scaffolds an operator package WITHOUT a placeholder CRD. CRDs are added via `forge add crd <name>` instead, which produces per-CRD shims that delegate to forge/pkg/controller.
The generator emits two files:
internal/operators/<package>/doc.go — package documentation that explains the operator's role and points users at `forge add crd`.
internal/operators/<package>/operator.go — the wiring symbols (Controller, Deps, New, AddToScheme) that the bootstrap template expects every operator package to export. The Controller type is a thin holder for the manager-level deps and is not itself a reconciler — per-CRD reconcilers live in <crd>_controller.go and are wired in cmd/<op>/main.go.
The operator's main.go (the cmd binary entrypoint) is generated by the standard project bootstrap step.
func GenerateOperatorFiles ¶
GenerateOperatorFiles generates all files for a single operator:
- internal/operators/<package>/types.go (from operator/types.go.tmpl)
- internal/operators/<package>/controller.go (from operator/controller.go.tmpl)
- internal/operators/<package>/controller_test.go (from operator/controller_test.go.tmpl)
The CLI/display name (which may contain hyphens) is translated to a Go-package-safe form for the directory and `package` declaration.
Both the "new project" and "add operator" flows delegate here so the generated output is always identical.
func GenerateOperatorFilesWithAPI ¶
func GenerateOperatorFilesWithAPI(root, modulePath, name, group, version, apiPackage, crdType string) error
GenerateOperatorFilesWithAPI is GenerateOperatorFiles with explicit overrides for the CRD type's Go package name and type name. This is the path used when the operator name and CRD type diverge — e.g. a `workspace-controller` operator reconciling a `Workspace` CRD. When apiPackage and crdType are both empty this behaves identically to GenerateOperatorFiles.
apiPackage selects the Go-package directory + `package` declaration for the CRD types. When empty, the CRD types live in the operator's own package (the original shape). When set, types are written to api/<version>/<apiPackage>/types.go with `package <apiPackage>`, and the controller imports them from there. crdType selects the Go type name; when empty it defaults to PascalCase(apiPackage) when apiPackage is set, or PascalCase(name) otherwise (preserving original behaviour).
func GeneratePlanORM ¶
func GeneratePlanORM(root, modulePath, serviceName string, entities []config.PlanEntity, cs *FileChecksums) error
GeneratePlanORM writes internal/db/<snake_name>_orm.go for each entity defined in the plan. The generated files provide a Bun-tagged entity struct (a projection of the applied schema) and standalone CRUD functions built on Bun's query builder (reached via orm.Context.Bun()). CRUD is emitted as package-level functions that take an orm.Context, so the same functions run inside or outside a transaction.
cs is the project's checksum tracker: every output is recorded as a Tier-1 manifest entry so `forge disown` can transfer ownership of an ORM file (kalshi fr-4dfef712e9: disown refused on internal/db/*_orm.go because nothing registered them) and `forge audit` doesn't see the files as orphans. A nil cs is tolerated (files written, not tracked).
func GeneratePlanProtoFile ¶
func GeneratePlanProtoFile(root, modulePath, serviceName string, rpcs []config.PlanRPC, entities []config.PlanEntity) error
GeneratePlanProtoFile writes a populated proto file for a service based on plan RPC definitions and entity messages. It overwrites any existing proto stub at proto/services/<name>/v1/<name>.proto.
When entities are provided, their message definitions are emitted inline in the service proto (before the RPC request/response messages) so that CRUD RPCs can reference them by bare name.
When forge.yaml at `root` declares `api.rest: true`, CRUD-prefixed RPCs (Get/List/Create/Update/Delete<Entity>) are emitted with default `google.api.http` annotations so vanguard can transcode REST↔Connect at runtime. Non-CRUD RPCs are left unannotated and need the user to add annotations by hand. The `google/api/annotations.proto` import is added to the proto only when at least one CRUD RPC was annotated.
func GenerateServiceFiles ¶
GenerateServiceFiles generates all files for a single Go service:
- handlers/<servicePackage>/service.go (from service/service.go.tmpl)
- proto/services/<servicePackage>/v1/<servicePackage>.proto (inline stub, skipped if exists)
The display/CLI form of the service name (which may contain hyphens) is translated to a Go-package-safe form ("admin-server" -> "admin_server") for filesystem directories and Go/proto identifiers. Display strings keep the original spelling.
Both the "new project" and "add service" flows delegate here so the generated output is always identical.
handlers.go is intentionally not emitted at scaffold time: with zero RPC methods there is nothing for it to contain. Once RPCs are added to the proto file, `forge generate` produces handlers_gen.go; the user then moves those stubs to handlers.go (or any other file) as they implement them.
func GenerateServiceFilesWithMode ¶
func GenerateServiceFilesWithMode(root, modulePath, serviceName, projectName string, port int, mode ScaffoldMode, progress io.Writer) error
GenerateServiceFilesWithMode is the mode-aware form of GenerateServiceFiles. `mode` controls per-file overwrite/skip behavior so callers can support --resume (recover a partially-applied scaffold) and --force (re-stamp every output file). When non-nil, `progress` receives one human-readable line per scaffolding step so the CLI can render "skipped" / "overwriting" notices without re-implementing the existence check.
func GenerateWebhookFiles ¶
GenerateWebhookFiles generates all files for a webhook endpoint within a service:
- internal/handlers/<service>/webhook_<name>.go (handler + signature verification)
- internal/handlers/<service>/webhook_<name>_test.go (tests)
- internal/handlers/<service>/webhook_store.go (idempotency store, only if not present)
func GenerateWorkerFiles ¶
GenerateWorkerFiles generates all files for a single worker:
- internal/workers/<package>/worker.go (from worker/worker.go.tmpl or worker-cron/worker.go.tmpl)
- internal/workers/<package>/worker_test.go (from worker/worker_test.go.tmpl or worker-cron/worker_test.go.tmpl)
The CLI/display name (which may contain hyphens) is translated to a Go-package-safe form for the directory and `package` declaration so hyphenated worker names like "email-sender" produce a buildable internal/workers/email_sender/ package.
When kind is "cron", the cron-specific templates are used and the schedule is embedded as a constant in the generated code.
Both the "new project" and "add worker" flows delegate here so the generated output is always identical.
func HashContent ¶
HashContent returns the sha256 hex digest of content.
func ReadProjectConfig ¶
func ReadProjectConfig(path string) (*config.ProjectConfig, error)
ReadProjectConfig reads a forge.yaml from the given path with strict validation: unknown keys, missing required fields, and type mismatches are surfaced together via config.ValidationError rather than failing fast on the first issue. The per-component entities are read from the project-root components.json sibling of forge.yaml and the project kind is derived from them (see config.LoadProject). See config.LoadStrict for the full validation semantics.
func RecordFrozenChecksums ¶
RecordFrozenChecksums re-stamps the embedded forge:hash marker on every marker-bearing managed file at projectDir. Exposed publicly so callers outside the scaffold path (e.g. `forge new` after `bootstrapGeneratedCode` runs goimports and reformats files) can re-certify the post-formatting bytes — otherwise the hashes stamped at scaffold time would not match the on-disk content, and the drift guard / `forge upgrade --dry-run` would flag every formatted file as user-modified.
func RegenerateInfraFiles ¶
func RegenerateInfraFiles(projectDir string, cfg *config.ProjectConfig) error
RegenerateInfraFiles regenerates all Tier 1 (always-overwrite) infrastructure files. Called by forge generate to keep infrastructure in sync with templates.
The cmd/<bin>/cmd command tree (root.go, serve.go, server.go, version.go, db.go) is part of this Tier-1 set, keyed off the project name so the per-binary destPaths resolve. cmd/<bin>/main.go is NOT — it is the composition root, owned by the generate pipeline (GenerateCmdGroups), which has the component inventory this path lacks.
func RegenerateInfraFilesTracked ¶
func RegenerateInfraFilesTracked(projectDir string, cfg *config.ProjectConfig, cs *FileChecksums) error
RegenerateInfraFilesTracked is RegenerateInfraFiles routed through the checksums chokepoint. With a non-nil cs every Tier-1 infra write:
- honors disowned entries (the user ran `forge disown`: the write is skipped while the file exists — the raw os.WriteFile path this replaces violated the "forge never regenerates user-owned files" contract for cmd/*.go and friends);
- records the render hash + WrittenThisRun so the stale sweep and the next run's drift guard see an accurate manifest;
- tags the entry Tier-1 (these files ARE regenerated every run).
force=true preserves the historical always-overwrite semantics for forge-owned files: the Tier-1 stomp guard ran earlier in the pipeline, so any surviving drift was already adjudicated (--force / disown).
A nil cs falls back to untracked writes (legacy callers).
func SaveChecksums ¶
func SaveChecksums(root string, cs *FileChecksums) error
SaveChecksums persists the project ownership state. Empty state deletes the files — no bookkeeping churn in the steady state.
func Tier2ManagedPaths ¶
Tier2ManagedPaths returns the set of project-relative paths whose canonical template tier is Tier-2 (scaffold-once, user-owned after the first write). It is the source of truth for `forge generate`'s tier-migration step (generate_tier_migrate.go in internal/cli): a `.forge/checksums.json` entry for one of these paths that still carries tier=1 (or the legacy unset tier=0) predates the template's reclassification and must be flipped to tier=2 so the file stops being drift-guarded and stops surfacing as a "fork".
Two sources:
- The managed-file registry entries tagged Tier2. A destPath's tier is invariant across the (kind, binary) matrix — only the source template varies — so the union over combinations is safe (same posture as UpgradeManagedPaths).
- The one-shot .github scaffolds written once at `forge new` time (project_ci.go) and never re-emitted by `forge generate`. CODEOWNERS even carries the `yours: scaffolded once ... (starter)` banner; recording them as Tier-1 was a historical accident that made hand-editing your own CODEOWNERS trip the Tier-1 stomp guard. (FRICTION 2026-06-05, cp-forge: users worked around the misclassification by hand-flipping `forked: true`.)
Deliberately NOT in this set: .github/workflows/e2e.yml and .github/dependabot.yml — those are re-rendered by `forge generate`'s CI step when enabled, so Tier-1 is their honest tier.
func UpgradeManagedPaths ¶
UpgradeManagedPaths returns the set of project-relative paths that `forge upgrade` (not `forge generate`) is responsible for emitting. Used by `forge generate`'s stale-artifact sweep to exclude these paths from the "stale codegen" candidate list: they're tracked in `.forge/checksums.json` but only re-rendered by upgrade, so seeing them missing from this run's WrittenThisRun set is the expected state, not a stale signal.
The set is the union over every (kind, binary) combination. Forge only ships a small number of these combinations so the union is cheap; computing the union (rather than asking the caller for the project's specific kind/binary) keeps the helper signature simple and means a kind/binary mismatch in detection doesn't accidentally flag a managed file as stale.
FRICTION 2026-06-05 (cp-forge audit-cleanup agent): `forge generate` warned 7 "stale" files — .github/CODEOWNERS, .golangci.yml, cmd/main.go, cmd/db.go, cmd/version.go, .github/workflows/e2e.yml, .github/pull_request_template.md — all of which are managed by `forge upgrade`. The user worked around it by hand-flipping `forked: true` in checksums.json, which silenced the warnings but also disconnected the files from the upgrade pipeline. The right fix is for the stale-sweep to know about the upgrade-managed set.
func WriteFrontendWorkspaceFiles ¶
WriteFrontendWorkspaceFiles emits the workspace-layout scaffolding:
- pnpm-workspace.yaml at the project root
- packages/api/package.json + tsconfig.json + .gitignore
- packages/hooks/package.json + tsconfig.json + use-api-{query,mutation}.ts
- packages/ui-web/package.json + tsconfig.json + src/components/*.tsx
Idempotent: writes files only if they do not already exist, so re- running `forge generate` after the user customizes (e.g.) the packages/api/package.json does not clobber their edits.
Returns nil immediately when workspaces is disabled — callers can invoke unconditionally and let this function decide whether work is needed.
func WriteGeneratedFile ¶
func WriteGeneratedFile(root, relPath string, content []byte, cs *FileChecksums, force bool) (bool, error)
WriteGeneratedFile writes a Tier-1 file through the certification chokepoint. See checksums.WriteGeneratedFile for full semantics.
func WriteGeneratedFileTier1 ¶
func WriteGeneratedFileTier1(root, relPath string, content []byte, cs *FileChecksums, force bool) (bool, error)
WriteGeneratedFileTier1 writes a Tier-1 (regenerated-every-run, self-certifying) file. See checksums.WriteGeneratedFileTier1.
func WriteProjectConfigFile ¶
func WriteProjectConfigFile(cfg *config.ProjectConfig, path string) error
WriteProjectConfig writes a config.ProjectConfig to the given path. The config is normalized first (config.NormalizeForWrite): values that match their shape-derived defaults are dropped so load → mutate → write round-trips keep forge.yaml minimal instead of materializing every derived default back into the file. Explicit overrides (values differing from derivation) always survive.
func WriteScaffoldIfMissing ¶
WriteScaffoldIfMissing writes a scaffold ("yours", user-owned) file only when it does not already exist; once on disk forge never overwrites it. See checksums.WriteScaffoldIfMissing.
func WriteUINativePackageFiles ¶
func WriteUINativePackageFiles(projectDir string, layout FrontendWorkspaceLayout) error
WriteUINativePackageFiles emits the packages/ui-native/ scaffold:
- packages/ui-native/package.json (workspace member)
- packages/ui-native/tsconfig.json (no DOM lib, React JSX)
- packages/ui-native/src/tokens.ts (design tokens)
- packages/ui-native/src/index.ts (re-export barrel)
- packages/ui-native/src/components/<primitive>.tsx (one per primitive)
- packages/ui-native/README.md
Idempotent: write-if-missing throughout. Once a user edits a primitive (or rewrites the tokens), `forge generate` will not clobber the edit — the package is effectively scaffolded once and owned by the project after.
Guarded by the two preconditions documented at the call sites in generate_pipeline.go and add.go:
- `frontend.workspaces: true`
- At least one frontend with `type: react-native`
When either is false this function should not be called (callers gate); calling it directly still works but emits files that have no consumer.
func WriteUIWebPackageFiles ¶
WriteUIWebPackageFiles emits packages/ui-web/ — the shared web-UI component library workspace. Idempotent (write-if-missing); safe to call from `forge generate` cycles after the user customizes the scaffolded files.
No-op when workspaces is false so existing single-frontend projects regenerate byte-identically.
Split from WriteFrontendWorkspaceFiles so callers that want to refresh just the ui-web scaffold (e.g. ensure-step in `forge generate`) don't have to touch the api/hooks packages.
Types ¶
type BinaryBuild ¶
type BinaryBuild struct {
// Dir is the cmd/<Dir>/ leaf — the `go build ./cmd/<Dir>` package path
// segment AND the output binary basename (/app/<Dir>).
Dir string
// Primary marks the server entrypoint (cmd/<projectName>/) that the
// production image runs by default (ENTRYPOINT/CMD). Exactly one binary
// is primary; the rest are run via a per-workload command override.
Primary bool
}
BinaryBuild is one buildable entrypoint: the cmd/<Dir>/ leaf, which is also the output binary name (/app/<Dir>).
type CRDGenInput ¶
type CRDGenInput struct {
Root string // project root
ModulePath string // go module path (e.g. "github.com/example/opt")
OperatorName string // target operator (display form, may have hyphens)
TypeName string // CRD type name (PascalCase, e.g. "Workspace")
Group string // API group (e.g. "reliant.dev")
Version string // API version (e.g. "v1alpha1")
Shape CRDShape // reconciler scaffold style
}
CRDGenInput collects the parameters needed to scaffold a CRD into an existing operator.
type CRDShape ¶
type CRDShape string
CRDShape is the reconciler scaffold style chosen at scaffold time.
state-machine — the CRD has a Spec.State field that drives the reconcile loop through observable phases (Pending → Running → Suspended → Failed). Generated controller carries reconcileRunning / reconcileSuspended / reconcileDeleting helpers and a switch over Spec.State.
config — declarative-only CRD with no observable state. The reconciler's job is to project Spec into a runtime store. Generated controller has a single ReconcileSpec.
composite — the CRD owns a set of sub-resources whose lifetime is coupled to the parent. Generated controller has a ReconcileSpec that's structured as a series of ensure* helpers.
type ConfigService ¶
type ConfigService interface {
ReadProjectConfig(path string) (*config.ProjectConfig, error)
WriteProjectConfigFile(cfg *config.ProjectConfig, path string) error
AppendServiceToConfig(projectRoot, serviceName string, port int) error
AppendFrontendToConfig(projectRoot, frontendName string, port int) error
AppendFrontendToConfigWithKind(projectRoot, frontendName string, port int, kind string) error
}
ConfigService loads, writes, and mutates the on-disk forge.yaml.
func NewConfigService ¶
func NewConfigService(_ Deps) ConfigService
NewConfigService constructs the forge.yaml read/write surface.
type Deps ¶
type Deps struct{}
Deps wires generator's cross-package collaborators. Empty today; the scaffolders use codegen + templates via package-level helpers. When internal/cli is ported, the Deps struct will gain Codegen / Templates fields wired through the New constructor.
type DisownedEntry ¶
type DisownedEntry = checksums.DisownedEntry
DisownedEntry is re-exported as a type alias from internal/checksums.
type E2EMethodInfo ¶
E2EMethodInfo holds method metadata for E2E test template rendering.
func MethodsFromProtoStub ¶
func MethodsFromProtoStub(serviceName string) []E2EMethodInfo
MethodsFromProtoStub returns placeholder E2E method info when no proto methods are available yet (e.g., when creating a brand-new service).
type E2ETemplateData ¶
type E2ETemplateData struct {
Module string
ServiceName string // display form, may contain hyphens
ServicePackage string // Go/proto-package-safe form (snake_case)
ProtoServiceName string // PascalCase service name for Connect client types
ProtoPackage string
ProjectName string
Port int
Methods []E2EMethodInfo
FirstRequestType string // Used to anchor the pb import in helpers
}
E2ETemplateData holds all data needed to render E2E test templates.
type FileChecksums ¶
type FileChecksums = checksums.FileChecksums
FileChecksums is re-exported as a type alias from internal/checksums.
func LoadChecksums ¶
func LoadChecksums(root string) (*FileChecksums, error)
LoadChecksums loads the project ownership state (.forge/disowned.json + .forge/hashes.json).
type FrontendGenOptions ¶
type FrontendGenOptions struct {
// Workspaces opts the frontend into the pnpm-workspace layout —
// its package.json declares "workspace:*" deps on @<scope>/api /
// @<scope>/hooks, and templates render imports of those packages
// instead of relative @/gen / @/hooks paths.
Workspaces bool
// Output selects the Next.js build/runtime shape rendered into
// `next.config.ts`. Valid values: "standalone" (default), "static",
// "server". See config.FrontendConfig.Output for the per-mode
// semantics. Empty string defaults to "standalone" — the only mode
// that both pairs with the shipped Dockerfile and supports the
// dynamic `[id]` CRUD routes forge generates (static export fails
// `next build` on any dynamic segment without generateStaticParams).
//
// Ignored for kind=mobile (react-native) and kind=vite-spa; those
// trees have their own production shapes.
Output string
// BasePath is the URL prefix the frontend is mounted under (e.g.
// "/admin"), mirroring config.FrontendConfig.BasePath. Rendered
// into `next.config.ts` (basePath + assetPrefix defaults) and
// `src/lib/basepath_gen.ts` (BASE_PATH / joinBasePath fallback).
// Empty = served from the host root. Like Output, only the nextjs
// template tree reads it.
BasePath string
}
FrontendGenOptions carries optional project-level settings forwarded to the per-frontend file emitter. Kept distinct from the existing positional GenerateFrontendFiles params so that adding new optional settings (here: Workspaces) doesn't churn every call site.
type FrontendWorkspaceLayout ¶
type FrontendWorkspaceLayout struct {
// Scope is the npm scope without the leading `@`. Derived from
// the project name; sanitized to a valid npm scope segment.
Scope string
// ApiPackage is the fully-qualified npm package name for the API
// workspace (e.g. "@myapp/api").
ApiPackage string
// HooksPackage is the fully-qualified npm package name for the
// hooks workspace (e.g. "@myapp/hooks").
HooksPackage string
// UIWebPackage is the fully-qualified npm package name for the
// shared web-UI component workspace (e.g. "@myapp/ui-web"). It
// holds the React/Tailwind component library that all browser-
// targeted frontends import from instead of duplicating per-
// frontend copies under src/components/.
UIWebPackage string
// UINativePackage is the fully-qualified npm package name for the
// React Native primitives workspace (e.g. "@myapp/ui-native").
// Only emitted when the project has at least one RN frontend AND
// workspaces are enabled — empty otherwise.
UINativePackage string
}
FrontendWorkspaceLayout describes the workspace package names + paths derived from a project. It is the single source of truth that hooks generation, buf TS generation, and frontend templates consult.
func NewFrontendWorkspaceLayout ¶
func NewFrontendWorkspaceLayout(projectName string) FrontendWorkspaceLayout
NewFrontendWorkspaceLayout builds the canonical layout from a raw project name. Falls back to "@app/api" / "@app/hooks" / "@app/ui-web" when the project name doesn't produce a valid npm scope segment.
type Harness ¶
type Harness string
Harness identifies which AI tool's conventions to scaffold for at project creation time: the top-level memory file's path, and (for harnesses that have a native skills concept) the on-disk directory where forge skills should be emitted. The default is "reliant".
func ParseHarness ¶
ParseHarness validates and normalises a user-supplied string.
func ValidHarnesses ¶
func ValidHarnesses() []Harness
ValidHarnesses lists all accepted --harness values. Returned as a getter to satisfy the no-exported-vars rule; callers should treat the returned slice as read-only (it is rebuilt on each call).
func (Harness) MemoryFilePath ¶
MemoryFilePath returns the project-root-relative path for the top-level memory file corresponding to the given harness.
func (Harness) SkillsDir ¶
SkillsDir returns the project-root-relative directory where forge skills should be written on `forge new` for this harness, or "" when the harness has no native skills concept. Reliant returns "" because the reliant CLI auto-discovers forge skills via the project's forge.yaml (no on-disk emission needed); copilot/codex return "" because they have no native skills mechanism.
type MockConfigService ¶
type MockConfigService struct {
contractkit.Recorder
ReadProjectConfigFunc func(string) (*config.ProjectConfig, error)
WriteProjectConfigFileFunc func(*config.ProjectConfig, string) error
AppendServiceToConfigFunc func(string, string, int) error
AppendFrontendToConfigFunc func(string, string, int) error
AppendFrontendToConfigWithKindFunc func(string, string, int, string) error
}
MockConfigService is a test mock for the ConfigService interface.
The embedded contractkit.Recorder records every call so tests can assert call counts and captured arguments. Set XxxFunc fields to override per-method behaviour; unset methods return the canonical "MockConfigService.<Method>Func not set" error.
func (*MockConfigService) AppendFrontendToConfig ¶
func (m *MockConfigService) AppendFrontendToConfig(projectRoot string, frontendName string, port int) error
func (*MockConfigService) AppendFrontendToConfigWithKind ¶
func (*MockConfigService) AppendServiceToConfig ¶
func (m *MockConfigService) AppendServiceToConfig(projectRoot string, serviceName string, port int) error
func (*MockConfigService) ReadProjectConfig ¶
func (m *MockConfigService) ReadProjectConfig(path string) (*config.ProjectConfig, error)
func (*MockConfigService) WriteProjectConfigFile ¶
func (m *MockConfigService) WriteProjectConfigFile(cfg *config.ProjectConfig, path string) error
type MockService ¶
type MockService struct {
contractkit.Recorder
GeneratePlanORMFunc func(string, string, string, []config.PlanEntity, *FileChecksums) error
GeneratePlanProtoFileFunc func(string, string, string, []config.PlanRPC, []config.PlanEntity) error
GenerateServiceFilesFunc func(string, string, string, string, int) error
GenerateWorkerFilesFunc func(string, string, string, string, string) error
GenerateOperatorFilesFunc func(string, string, string, string, string) error
GenerateWebhookFilesFunc func(string, string, string, string) error
GenerateFrontendFilesFunc func(string, string, string, string, int, string) error
EnsureCoreComponentsFunc func(string) error
GenerateE2ETestsFunc func(string, string, string, string, []E2EMethodInfo) error
GenerateEntitySeedsFunc func([]SeedEntity, string) error
GenerateGrafanaDashboardsFunc func(string, string) error
RegenerateInfraFilesFunc func(string, *config.ProjectConfig) error
UpgradeFunc func(string, *config.ProjectConfig, bool, bool) ([]UpgradeResult, error)
WriteGeneratedFileFunc func(string, string, []byte, *FileChecksums, bool) (bool, error)
HashContentFunc func([]byte) string
LoadChecksumsFunc func(string) (*FileChecksums, error)
SaveChecksumsFunc func(string, *FileChecksums) error
}
MockService is a test mock for the Service interface.
The embedded contractkit.Recorder records every call so tests can assert call counts and captured arguments. Set XxxFunc fields to override per-method behaviour; unset methods return the canonical "MockService.<Method>Func not set" error.
func (*MockService) EnsureCoreComponents ¶
func (m *MockService) EnsureCoreComponents(frontendDir string) error
func (*MockService) GenerateE2ETests ¶
func (m *MockService) GenerateE2ETests(projectDir string, serviceName string, modulePath string, projectName string, methods []E2EMethodInfo) error
func (*MockService) GenerateEntitySeeds ¶
func (m *MockService) GenerateEntitySeeds(entities []SeedEntity, outputDir string) error
func (*MockService) GenerateFrontendFiles ¶
func (*MockService) GenerateGrafanaDashboards ¶
func (m *MockService) GenerateGrafanaDashboards(projectName string, projectDir string) error
func (*MockService) GenerateOperatorFiles ¶
func (*MockService) GeneratePlanORM ¶
func (m *MockService) GeneratePlanORM(root string, modulePath string, serviceName string, entities []config.PlanEntity, cs *FileChecksums) error
func (*MockService) GeneratePlanProtoFile ¶
func (m *MockService) GeneratePlanProtoFile(root string, modulePath string, serviceName string, rpcs []config.PlanRPC, entities []config.PlanEntity) error
func (*MockService) GenerateServiceFiles ¶
func (*MockService) GenerateWebhookFiles ¶
func (*MockService) GenerateWorkerFiles ¶
func (*MockService) HashContent ¶
func (m *MockService) HashContent(content []byte) string
func (*MockService) LoadChecksums ¶
func (m *MockService) LoadChecksums(root string) (*FileChecksums, error)
func (*MockService) RegenerateInfraFiles ¶
func (m *MockService) RegenerateInfraFiles(projectDir string, cfg *config.ProjectConfig) error
func (*MockService) SaveChecksums ¶
func (m *MockService) SaveChecksums(root string, cs *FileChecksums) error
func (*MockService) Upgrade ¶
func (m *MockService) Upgrade(projectDir string, cfg *config.ProjectConfig, force bool, checkOnly bool) ([]UpgradeResult, error)
func (*MockService) WriteGeneratedFile ¶
func (m *MockService) WriteGeneratedFile(root string, relPath string, content []byte, cs *FileChecksums, force bool) (bool, error)
type ProjectGenerator ¶
type ProjectGenerator struct {
Name string
Path string
ModulePath string
Kind string // project kind: "service" (default), "cli", "library"
Binary string // binary mode: "per-service" (default), "shared" — emit one Go binary with cobra subcommand per service when shared
ServiceName string // initial service name (empty if none specified)
AdditionalServices []string // additional service names beyond ServiceName — only consumed by binary=shared scaffolds; per-service mode adds these post-scaffold
ServicePort int // initial service port (default: 8080)
FrontendName string // optional initial Next.js frontend name
FrontendPort int // frontend port (default: 3000)
// FrontendWorkspaces opts the project into the pnpm-workspaces
// layout: emit a root pnpm-workspace.yaml + packages/api +
// packages/hooks, frontends consume @<scope>/api / @<scope>/hooks
// via "workspace:*" deps. Off by default — single-frontend
// projects keep the historic per-frontend layout unchanged.
FrontendWorkspaces bool
GoVersionOverride string // if set, use this Go version instead of detecting
Features config.FeaturesConfig // feature flags for generation
Harness Harness // AI harness (default: reliant) — controls memory file path and skill emission
// BuildVersionVar mirrors forge.yaml build.version_var: an additional
// `-ldflags -X` target the Dockerfile stamps with the build version.
// Empty at scaffold time (a fresh forge.yaml has no build: block), so
// the Dockerfile's `{{if .VersionVar}}` renders nothing — preserving
// the historical main.version-only stamping. `forge generate` /
// upgrade re-render with the live forge.yaml value.
BuildVersionVar string
}
ProjectGenerator generates new project structure
func NewProjectGenerator ¶
func NewProjectGenerator(name, path, modulePath string) *ProjectGenerator
NewProjectGenerator creates a new project generator
func (*ProjectGenerator) ApplyKindFeatureDefaults ¶
func (g *ProjectGenerator) ApplyKindFeatureDefaults(kind string)
ApplyKindFeatureDefaults is the public entry point invoked by `forge new` after parsing the --kind flag. It delegates to the private applyKindFeatureDefaults helper so the scaffold-time matrix lives in one place. Exposed publicly so other callers (tests, sibling tools) can derive the same defaults from a kind string without duplicating the per-feature decisions.
func (*ProjectGenerator) ForScaffold ¶
func (g *ProjectGenerator) ForScaffold() projectTemplateData
ForScaffold builds the render payload for the `forge new` scaffold lane from a *ProjectGenerator. It reproduces, verbatim, the derivations the old inline anonymous struct performed (protoName via hyphen→underscore, servicePackage via naming.ServicePackage, the goVersion family, the forge/pkg dep resolution and its LocalForgePkgVendored gate).
func (*ProjectGenerator) Generate ¶
func (g *ProjectGenerator) Generate() error
Generate creates the project structure.
type ScaffoldMode ¶
type ScaffoldMode int
ScaffoldMode controls how scaffolding functions handle pre-existing output files. It exists so `forge add service --resume / --force` can re-run a partial scaffold without forcing the user to rm -rf and start over.
const ( // ScaffoldFail is the default: writes unconditionally. Callers are // expected to have done their own up-front "does this name conflict" // check (forge.yaml services: list). Equivalent to pre-resume behavior. ScaffoldFail ScaffoldMode = iota // ScaffoldResume skips any output file that already exists on disk. // Use this to recover from a partial scaffold where buf generate (or a // later pipeline step) failed mid-flight and left some files written. ScaffoldResume // ScaffoldForce overwrites every output file, even when present. The // proto file is included — the only file the default codepath // historically preserved — so users can fully re-stamp a scaffold. ScaffoldForce )
type SeedEntity ¶
SeedEntity describes a database entity for seed-data generation.
func EntityDefsToSeedEntities ¶
func EntityDefsToSeedEntities(defs []codegen.EntityDef) []SeedEntity
EntityDefsToSeedEntities converts codegen.EntityDef slices into SeedEntity slices suitable for seed-data generation. Seeds INSERT into real columns, so the source is the entity's introspected COLUMNS (the applied schema) — never the wire message.
type SeedField ¶
type SeedField struct {
ColumnName string
FieldType SeedFieldType
IsPK bool
NotNull bool
IsTimestamp bool
AutoIncrement bool
References string // FK reference in "table.column" format
}
SeedField describes a single column for seed-data generation.
type SeedFieldType ¶
type SeedFieldType int
SeedFieldType represents the SQL column type for seed generation.
const ( SeedFieldText SeedFieldType = iota SeedFieldUUID SeedFieldInteger SeedFieldBigInt SeedFieldBoolean SeedFieldTimestamp SeedFieldFloat SeedFieldBytes // JSON array columns (repeated scalar entity fields). SeedFieldJSONStrings SeedFieldJSONNumbers )
type Service ¶
type Service interface {
// Plan-mode generators.
GeneratePlanORM(root, modulePath, serviceName string, entities []config.PlanEntity, cs *FileChecksums) error
GeneratePlanProtoFile(root, modulePath, serviceName string, rpcs []config.PlanRPC, entities []config.PlanEntity) error
// Component scaffolders.
GenerateServiceFiles(root, modulePath, serviceName, projectName string, port int) error
GenerateWorkerFiles(root, modulePath, workerName, kind, schedule string) error
GenerateOperatorFiles(root, modulePath, name, group, version string) error
GenerateWebhookFiles(root, modulePath, serviceName, webhookName string) error
GenerateFrontendFiles(root, modulePath, projectName, frontendName string, apiPort int, kind string) error
EnsureCoreComponents(frontendDir string) error
GenerateE2ETests(projectDir, serviceName, modulePath, projectName string, methods []E2EMethodInfo) error
GenerateEntitySeeds(entities []SeedEntity, outputDir string) error
GenerateGrafanaDashboards(projectName, projectDir string) error
// Project-level upgrade / regeneration.
RegenerateInfraFiles(projectDir string, cfg *config.ProjectConfig) error
Upgrade(projectDir string, cfg *config.ProjectConfig, force bool, checkOnly bool) ([]UpgradeResult, error)
// Checksum-aware file writes (used by the bootstrap orchestrator).
WriteGeneratedFile(root, relPath string, content []byte, cs *FileChecksums, force bool) (bool, error)
HashContent(content []byte) string
LoadChecksums(root string) (*FileChecksums, error)
SaveChecksums(root string, cs *FileChecksums) error
}
Service is the file-emission surface of the generator package. Methods write into the user-project working directory; callers wanting finer-grained mocking can stub one method at a time.
type ServiceInfo ¶
ServiceInfo holds the name and port of a service for template rendering.
type Tier1DriftEntry ¶
type Tier1DriftEntry = checksums.Tier1DriftEntry
Tier1DriftEntry is re-exported as a type alias from internal/checksums.
type UpgradeResult ¶
type UpgradeResult struct {
Path string // relative path in project (e.g. "cmd/server.go")
Status UpgradeStatus // what happened
Diff string // unified-style diff when file changed
}
UpgradeResult holds the outcome for a single managed file.
func Upgrade ¶
func Upgrade(projectDir string, cfg *config.ProjectConfig, force bool, checkOnly bool) ([]UpgradeResult, error)
Upgrade checks all managed (frozen) files against the current templates and optionally applies updates.
When checkOnly is true, no files are written — it only reports what would change. When force is true, user-modified files are overwritten without prompting.
type UpgradeStatus ¶
type UpgradeStatus string
UpgradeStatus describes the outcome for each managed file.
const ( UpgradeUpToDate UpgradeStatus = "up-to-date" UpgradeUpdated UpgradeStatus = "updated" UpgradeUserModified UpgradeStatus = "user-modified" UpgradeSkipped UpgradeStatus = "skipped" )
Source Files
¶
- binary_gen.go
- checksums.go
- contract.go
- contract_methods.go
- crd_gen.go
- dx_files.go
- e2e.go
- frontend_gen.go
- frontend_workspaces.go
- grafana_dashboards.go
- harness.go
- mock_gen.go
- operator_binary_gen.go
- operator_gen.go
- plan_orm_gen.go
- plan_proto_gen.go
- project.go
- project_bootstrap.go
- project_ci.go
- project_config.go
- project_deploy.go
- project_goversion.go
- project_helpers.go
- project_metadata.go
- project_pkgdep.go
- project_template_data.go
- seed_gen.go
- service_gen.go
- upgrade.go
- webhook_gen.go
- worker_gen.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package contract drives the four *_gen.go files (mock, middleware, tracing, metrics) emitted from a single hand-written contract.go.
|
Package contract drives the four *_gen.go files (mock, middleware, tracing, metrics) emitted from a single hand-written contract.go. |