Codex-authored docs covering primitives, commands, messaging, lifecycle, subsystems, and getting started — all using the current DTO/Options/Result API with concrete usage examples. Co-Authored-By: Virgil <virgil@lethean.io>
3 KiB
AX Package Standards
This page describes how to build packages on top of CoreGO in the style described by RFC-025.
1. Prefer Predictable Names
Use names that tell an agent what the thing is without translation.
Good:
RepositoryServiceRepositoryServiceOptionsWorkspaceCountQuerySyncRepositoryTask
Avoid shortening names unless the abbreviation is already universal.
2. Put Real Usage in Comments
Write comments that show a real call with realistic values.
Good:
// Sync a repository into the local workspace cache.
// svc.SyncRepository("core-go", "/srv/repos/core-go")
Avoid comments that only repeat the signature.
3. Keep Paths Semantic
If a command or template lives at a path, let the path explain the intent.
Good:
deploy/to/homelab
workspace/create
template/workspace/go
That keeps the CLI, tests, docs, and message vocabulary aligned.
4. Reuse CoreGO Primitives
At Core boundaries, prefer the shared shapes:
core.Optionsfor lightweight inputcore.Resultfor outputcore.Servicefor lifecycle registrationcore.Message,core.Query,core.Taskfor bus protocols
Inside your package, typed structs are still good. Use ServiceRuntime[T] when you want typed package options plus a Core reference.
type repositoryServiceOptions struct {
BaseDirectory string
}
type repositoryService struct {
*core.ServiceRuntime[repositoryServiceOptions]
}
5. Prefer Explicit Registration
Register services and commands with names and paths that stay readable in grep results.
c.Service("repository", core.Service{...})
c.Command("repository/sync", core.Command{...})
6. Use the Bus for Decoupling
When one package needs another package’s behavior, prefer queries and tasks over tight package coupling.
type repositoryCountQuery struct{}
type syncRepositoryTask struct {
Name string
}
That keeps the protocol visible in code and easy for agents to follow.
7. Use Structured Errors
Use core.E, core.Wrap, and core.WrapCode.
return core.Result{
Value: core.E("repository.Sync", "git fetch failed", err),
OK: false,
}
Do not introduce free-form fmt.Errorf chains in framework code.
8. Keep Testing Names Predictable
Follow the repository pattern:
_Good_Bad_Ugly
Example:
func TestRepositorySync_Good(t *testing.T) {}
func TestRepositorySync_Bad(t *testing.T) {}
func TestRepositorySync_Ugly(t *testing.T) {}
9. Prefer Stable Shapes Over Clever APIs
For package APIs, avoid patterns that force an agent to infer too much hidden control flow.
Prefer:
- clear structs
- explicit names
- path-based commands
- visible message types
Avoid:
- implicit global state unless it is truly a default service
- panic-hiding constructors
- dense option chains when a small explicit struct would do
10. Document the Current Reality
If the implementation is in transition, document what the code does now, not the API shape you plan to have later.
That keeps agents correct on first pass, which is the real AX metric.