fix(rfc-025): pass 2 — stale examples, self-contradiction, missing entitlement pattern

- Principle 2: NewPrep/SetCore examples → actual Core comment style
- Principle 3: proc.go (deleted) → handlers.go, added docs/RFC.md
- Principle 5: fmt.Errorf → core.E() (was contradicting Principle 9)
- Principle 6: Service Registration → ServiceRuntime pattern
- Error Handling: SetCore manual pattern → ServiceRuntime
- Added: Permission Gating example (AX vs scattered if-statements)

The RFC now practices what it preaches — no example contradicts a rule.

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
user.email 2026-03-25 17:45:51 +00:00
parent 49584e8b4c
commit 297d920fed

View file

@ -59,19 +59,20 @@ Options not Opts
The function signature tells WHAT. The comment shows HOW with real values.
```go
// NewPrep creates an agentic subsystem.
// Entitled checks if an action is permitted.
//
// sub := agentic.NewPrep()
// sub.SetCore(c)
// sub.RegisterTools(server)
// e := c.Entitled("process.run")
// e := c.Entitled("social.accounts", 3)
// if e.Allowed { proceed() }
// Detect the project type from files present.
// WriteAtomic writes via temp file then rename (safe for concurrent readers).
//
// projType := setup.Detect("./repo")
// r := fs.WriteAtomic("/status.json", data)
// Set up a workspace with auto-detected template.
// Action registers or invokes a named callable.
//
// err := setup.Run(setup.Options{Path: ".", Template: "auto"})
// c.Action("git.log", handler) // register
// c.Action("git.log").Run(ctx, opts) // invoke
```
**Rule:** If a comment restates what the type signature already says, delete it. If a comment shows a concrete usage with realistic values, keep it.
@ -84,11 +85,12 @@ File and directory paths should be self-describing. An agent navigating the file
```
pkg/agentic/dispatch.go — agent dispatch logic
pkg/agentic/proc.go — process execution helpers
pkg/agentic/handlers.go — IPC event handlers
pkg/lib/task/bug-fix.yaml — bug fix plan template
pkg/lib/persona/engineering/ — engineering personas
flow/deploy/to/homelab.yaml — deploy TO the homelab
template/dir/workspace/default/ — default workspace scaffold
docs/RFC.md — authoritative API contract
```
**Rule:** If an agent needs to read a file to understand what a directory contains, the directory naming has failed.
@ -137,7 +139,7 @@ steps:
cmd := exec.Command("docker", "build", "--platform", "linux/amd64", "-t", imageName, ".")
cmd.Dir = appDir
if err := cmd.Run(); err != nil {
return fmt.Errorf("docker build: %w", err)
return core.E("build", "docker build failed", err)
}
```
@ -168,10 +170,10 @@ c.Run() // or: if err := c.RunE(); err != nil { ... }
```go
// Service factory — receives Core, returns Result
func Register(c *core.Core) core.Result {
sub := NewPrep()
sub.SetCore(c)
RegisterHandlers(c, sub)
return core.Result{Value: sub, OK: true}
svc := &MyService{
ServiceRuntime: core.NewServiceRuntime(c, MyOptions{}),
}
return core.Result{Value: svc, OK: true}
}
```
@ -404,18 +406,17 @@ src/
```go
// AX-native: errors flow through Result, not call sites
func Register(c *core.Core) core.Result {
sub := NewPrep()
sub.SetCore(c)
return core.Result{Value: sub, OK: true}
svc := &MyService{ServiceRuntime: core.NewServiceRuntime(c, MyOpts{})}
return core.Result{Value: svc, OK: true}
}
// Not AX: errors dominate the code
func Register(c *core.Core) (*PrepSubsystem, error) {
sub := NewPrep()
if err := sub.SetCore(c); err != nil {
return nil, fmt.Errorf("set core: %w", err)
func Register(c *core.Core) (*MyService, error) {
svc, err := NewMyService(c)
if err != nil {
return nil, fmt.Errorf("create service: %w", err)
}
return sub, nil
return svc, nil
}
```
@ -462,6 +463,25 @@ func (s *PrepSubsystem) getGitLog(repoPath string) string {
}
```
### Permission Gating
```go
// AX-native: entitlement checked by framework, not by business logic
c.Action("agentic.dispatch", func(ctx context.Context, opts core.Options) core.Result {
// Action.Run() already checked c.Entitled("agentic.dispatch")
// If we're here, we're allowed. Just do the work.
return dispatch(ctx, opts)
})
// Not AX: permission logic scattered through business code
func handleDispatch(ctx context.Context, opts core.Options) core.Result {
if !isAdmin(ctx) && !hasPlan(ctx, "pro") {
return core.Result{Value: core.E("dispatch", "upgrade required", nil), OK: false}
}
// duplicate permission check in every handler
}
```
## Compatibility
AX conventions are valid, idiomatic Go/PHP/TS. They do not require language extensions, code generation, or non-standard tooling. An AX-designed codebase compiles, tests, and deploys with standard toolchains.