-
Notifications
You must be signed in to change notification settings - Fork 5
refactor(codegen): generated app foundation and module mount safety #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+310
−57
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| # Machine Contracts | ||
|
|
||
| Lathe's durable value is a small set of versioned, machine-readable contracts. | ||
| Generated CLIs, agents, and sibling tooling (installers, verifiers, registries) | ||
| integrate through these contracts, not through Lathe internals. Any new tool or | ||
| capability should answer one question first: which contract does it consume or | ||
| produce, and how is that contract versioned? | ||
|
|
||
| Code is the source of truth. Each section below points at the defining source | ||
| file; when this page and the code disagree, trust the code and fix this page. | ||
|
|
||
| ## Generated code schema | ||
|
|
||
| - Version constant: `runtime.SchemaVersion` in `pkg/runtime/spec.go`. | ||
| - Couples generated `[]runtime.CommandSpec` literals | ||
| (`internal/generated/<module>/<module>_gen.go` in downstream repos) to the | ||
| runtime that executes them. | ||
| - Enforced by `runtime.AssertSchema` at mount time: a mismatch fails fast at | ||
| startup with an instruction to re-run codegen. | ||
| - Bump the constant whenever `CommandSpec` semantics or the generated mount | ||
| contract change in a way that requires regeneration. | ||
|
|
||
| ## Command catalog | ||
|
|
||
| - Version field: `catalog_schema_version`, constant | ||
| `runtime.CatalogSchemaVersion` in `pkg/runtime/catalog.go`. | ||
| - Served by `<cli> commands --json`, `commands show <path...> --json`, | ||
| `search "<intent>" --json`, and `commands schema --json`. | ||
| - This is the agent-facing discovery contract and the source of truth for | ||
| generated operation details: HTTP method and path template, auth | ||
| requirements, flags, body schema, output and pagination hints. | ||
| - Only generated API operation commands carry catalog entries. Framework | ||
| commands (`auth`, `commands`, `search`, `update`, `__lathe`) are discovered | ||
| through `--help`, not the catalog. | ||
| - Consumers: agents following the documented loop (search, then | ||
| `commands show`, then `auth status`, then execute), generated Skill files | ||
| (guidance and indexes only, never execution authority), and external | ||
| conformance tooling. | ||
|
|
||
| ## Verify report | ||
|
|
||
| - Emitted by `<cli> __lathe verify --json`; implemented in | ||
| `pkg/lathe/verify.go`. | ||
| - Shape: `{"ok": bool, "checks": [{"name": string, "ok": bool, "error": | ||
| string}]}`. The process exits non-zero when any check fails. | ||
| - This is the generated CLI's self-evidence: root help contract, catalog | ||
| schema and JSON round-trip, per-command flag consistency, and an isolated | ||
| unauthenticated `auth status` probe. | ||
| - The report is not independently versioned today; treat any change to its | ||
| shape or check names as a contract change and document it here. | ||
|
|
||
| ## Structured errors and exit codes | ||
|
|
||
| - Defined in `pkg/runtime/errors.go`. | ||
| - Error codes: `general`, `usage`, `api_error`, `not_authenticated`. | ||
| - Exit codes: `0` OK, `1` general, `2` usage, `3` API error, | ||
| `4` not authenticated. | ||
| - Consumers: agents and scripts that branch on failure classes instead of | ||
| parsing prose. | ||
|
|
||
| ## Durable inputs | ||
|
|
||
| - `cli.yaml`, parsed by `pkg/config.Load`, plus codegen-only keys | ||
| (`skill.root`, `skill.include`) parsed in `internal/lathecmd`. | ||
| - `specs/sources.yaml`, parsed by `internal/sourceconfig`, pinning upstream | ||
| spec refs per module. | ||
| - Optional overlay files, parsed by `internal/overlay`, merged at codegen time | ||
| only. | ||
| - Together these are the reproducibility contract: generated output must be | ||
| reproducible from these pinned inputs. Overlay concepts never reach the | ||
| runtime. | ||
|
|
||
| ## Rules | ||
|
|
||
| - The runtime catalog is authoritative for operation details; generated Skill | ||
| files are guidance. | ||
| - Search results are discovery only; agents must inspect a command via | ||
| `commands show` before executing it. | ||
| - A change to any surface above is product behavior: prove it with focused | ||
| tests and treat the version fields as the compatibility gate. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| // Package app models the generated CLI application that one codegen run is | ||
| // about to emit. Outputs are collected into an App first and written together, | ||
| // so a failing input never leaves partially generated output behind. The model | ||
| // is internal to codegen; it is not a stable extension API. | ||
| package app | ||
|
|
||
| import ( | ||
| "github.com/lathe-cli/lathe/internal/codegen/render" | ||
| "github.com/lathe-cli/lathe/pkg/config" | ||
| "github.com/lathe-cli/lathe/pkg/runtime" | ||
| ) | ||
|
|
||
| // App is the complete set of generated outputs for one codegen run. | ||
| type App struct { | ||
| Manifest *config.Manifest | ||
| Modules []Module | ||
| Skill *Skill | ||
| } | ||
|
|
||
| // Module is one generated command module and how it mounts on the root command. | ||
| type Module struct { | ||
| Source string | ||
| CLIName string | ||
| Flat bool | ||
| Specs []runtime.CommandSpec | ||
| } | ||
|
|
||
| // Skill is the optional generated Skill directory output. | ||
| type Skill struct { | ||
| Dir string | ||
| Include render.SkillInclude | ||
| Modules []render.SkillModule | ||
| } | ||
|
|
||
| // Validate rejects app compositions that would produce a conflicting root | ||
| // command tree. Flat modules are skipped: their module name is never mounted, | ||
| // and flat root conflicts are rejected by ResolveFlatCommandPath. | ||
| func (a *App) Validate() error { | ||
| names := make([]string, 0, len(a.Modules)) | ||
| for _, m := range a.Modules { | ||
| if m.Flat { | ||
| continue | ||
| } | ||
| names = append(names, m.CLIName) | ||
| } | ||
| return render.ValidateModuleNames(names) | ||
| } | ||
|
|
||
| // Write renders every collected output. | ||
| func (a *App) Write() error { | ||
| mounts := make([]render.ModuleMount, 0, len(a.Modules)) | ||
| for _, m := range a.Modules { | ||
| if err := render.RenderModule(m.Source, m.CLIName, m.Specs, nil); err != nil { | ||
| return err | ||
| } | ||
| mounts = append(mounts, render.ModuleMount{Name: m.Source, Flat: m.Flat}) | ||
| } | ||
| if err := render.RenderModulesGen(mounts); err != nil { | ||
| return err | ||
| } | ||
| if a.Skill == nil { | ||
| return nil | ||
| } | ||
| return render.RenderSkillDirectoryWithInclude(a.Skill.Dir, a.Manifest, a.Skill.Modules, a.Skill.Include) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.