[agent/codex:gpt-5.3-codex-spark] Read .core/reference/RFC-CORE-008-AGENT-EXPERIENCE.md (the A... #8

Merged
Virgil merged 1 commit from agent/create-an-upgrade-plan-for-this-package into dev 2026-03-29 15:20:38 +00:00
7 changed files with 33 additions and 27 deletions

View file

@ -98,8 +98,8 @@ func runContainer(image, name string, detach bool, memory, cpus, sshPort int) er
core.Print(nil, "%s %s", successStyle.Render(i18n.Label("started")), c.ID)
core.Print(nil, "%s %d", dimStyle.Render(i18n.T("cmd.vm.label.pid")), c.PID)
core.Println()
core.Println(i18n.T("cmd.vm.hint.view_logs", map[string]any{"ID": c.ID[:8]}))
core.Println(i18n.T("cmd.vm.hint.stop", map[string]any{"ID": c.ID[:8]}))
core.Println(i18n.T("cmd.vm.hint.view_logs", map[string]any{"ID": shortContainerID(c.ID)}))
core.Println(i18n.T("cmd.vm.hint.stop", map[string]any{"ID": shortContainerID(c.ID)}))
} else {
core.Println()
core.Print(nil, "%s %s", dimStyle.Render(i18n.T("cmd.vm.label.container_stopped")), c.ID)
@ -184,13 +184,23 @@ func listContainers(all bool) error {
}
core.Print(w, "%s\t%s\t%s\t%s\t%s\t%d",
c.ID[:8], c.Name, imageName, status, duration, c.PID)
shortContainerID(c.ID), c.Name, imageName, status, duration, c.PID)
}
if err := w.Flush(); err != nil {
return coreerr.E("listContainers", "flush output", err)
}
_ = w.Flush()
return nil
}
func shortContainerID(id string) string {
if len(id) <= 8 {
return id
}
return id[:8]
}
func formatDuration(d time.Duration) string {
if d < time.Minute {
return core.Sprintf("%ds", int(d.Seconds()))
@ -233,7 +243,7 @@ func stopContainer(id string) error {
return err
}
core.Print(nil, "%s %s", dimStyle.Render(i18n.T("cmd.vm.stop.stopping")), fullID[:8])
core.Print(nil, "%s %s", dimStyle.Render(i18n.T("cmd.vm.stop.stopping")), shortContainerID(fullID))
ctx := context.Background()
if err := manager.Stop(ctx, fullID); err != nil {

View file

@ -88,7 +88,9 @@ func listTemplates() error {
}
core.Print(w, "%s\t%s", repoNameStyle.Render(tmpl.Name), desc)
}
_ = w.Flush()
if err := w.Flush(); err != nil {
return coreerr.E("listTemplates", "flush output", err)
}
core.Println()
core.Print(nil, "%s %s", i18n.T("cmd.vm.templates.hint.show"), dimStyle.Render("core vm templates show <name>"))
@ -209,8 +211,8 @@ func RunFromTemplate(templateName string, vars map[string]string, runOpts contai
core.Print(nil, "%s %s", successStyle.Render(i18n.T("common.label.started")), c.ID)
core.Print(nil, "%s %d", dimStyle.Render(i18n.T("cmd.vm.label.pid")), c.PID)
core.Println()
core.Println(i18n.T("cmd.vm.hint.view_logs", map[string]any{"ID": c.ID[:8]}))
core.Println(i18n.T("cmd.vm.hint.stop", map[string]any{"ID": c.ID[:8]}))
core.Println(i18n.T("cmd.vm.hint.view_logs", map[string]any{"ID": shortContainerID(c.ID)}))
core.Println(i18n.T("cmd.vm.hint.stop", map[string]any{"ID": shortContainerID(c.ID)}))
} else {
core.Println()
core.Print(nil, "%s %s", dimStyle.Render(i18n.T("cmd.vm.label.container_stopped")), c.ID)

View file

@ -43,7 +43,7 @@ func New(m io.Medium) (*DevOps, error) {
return nil, coreerr.E("devops.New", "failed to create image manager", err)
}
mgr, err := container.NewLinuxKitManager(io.Local)
mgr, err := container.NewLinuxKitManager(m)
if err != nil {
return nil, coreerr.E("devops.New", "failed to create container manager", err)
}

View file

@ -16,7 +16,6 @@ import (
// ImageManager handles image downloads and updates.
type ImageManager struct {
medium io.Medium
config *Config
manifest *Manifest
sources []sources.ImageSource
}
@ -83,7 +82,6 @@ func NewImageManager(m io.Medium, cfg *Config) (*ImageManager, error) {
return &ImageManager{
medium: m,
config: cfg,
manifest: manifest,
sources: srcs,
}, nil

View file

@ -240,7 +240,6 @@ func TestImageManager_InstallNoSourceAvailable_Bad(t *testing.T) {
// Create manager with empty sources
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{medium: io.Local, Images: make(map[string]ImageInfo), path: coreutil.JoinPath(tmpDir, "manifest.json")},
sources: nil, // no sources
}
@ -301,7 +300,6 @@ func TestImageManager_InstallWithMockSource_Good(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{medium: io.Local, Images: make(map[string]ImageInfo), path: coreutil.JoinPath(tmpDir, "manifest.json")},
sources: []sources.ImageSource{mock},
}
@ -330,7 +328,6 @@ func TestImageManager_InstallDownloadError_Bad(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{medium: io.Local, Images: make(map[string]ImageInfo), path: coreutil.JoinPath(tmpDir, "manifest.json")},
sources: []sources.ImageSource{mock},
}
@ -351,7 +348,6 @@ func TestImageManager_InstallVersionError_Bad(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{medium: io.Local, Images: make(map[string]ImageInfo), path: coreutil.JoinPath(tmpDir, "manifest.json")},
sources: []sources.ImageSource{mock},
}
@ -377,7 +373,6 @@ func TestImageManager_InstallSkipsUnavailableSource_Good(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{medium: io.Local, Images: make(map[string]ImageInfo), path: coreutil.JoinPath(tmpDir, "manifest.json")},
sources: []sources.ImageSource{unavailableMock, availableMock},
}
@ -402,7 +397,6 @@ func TestImageManager_CheckUpdateWithMockSource_Good(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{
medium: io.Local,
Images: map[string]ImageInfo{
@ -432,7 +426,6 @@ func TestImageManager_CheckUpdateNoUpdate_Good(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{
medium: io.Local,
Images: map[string]ImageInfo{
@ -461,7 +454,6 @@ func TestImageManager_CheckUpdateNoSource_Bad(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{
medium: io.Local,
Images: map[string]ImageInfo{
@ -489,7 +481,6 @@ func TestImageManager_CheckUpdateVersionError_Bad(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{
medium: io.Local,
Images: map[string]ImageInfo{
@ -511,7 +502,6 @@ func TestImageManager_InstallEmptySources_Bad(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{medium: io.Local, Images: make(map[string]ImageInfo), path: coreutil.JoinPath(tmpDir, "manifest.json")},
sources: []sources.ImageSource{}, // Empty slice, not nil
}
@ -530,7 +520,6 @@ func TestImageManager_InstallAllUnavailable_Bad(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{medium: io.Local, Images: make(map[string]ImageInfo), path: coreutil.JoinPath(tmpDir, "manifest.json")},
sources: []sources.ImageSource{mock1, mock2},
}
@ -549,7 +538,6 @@ func TestImageManager_CheckUpdateFirstSourceUnavailable_Good(t *testing.T) {
mgr := &ImageManager{
medium: io.Local,
config: DefaultConfig(),
manifest: &Manifest{
medium: io.Local,
Images: map[string]ImageInfo{

View file

@ -351,11 +351,13 @@ type followReader struct {
ctx context.Context
cancel context.CancelFunc
reader *bufio.Reader
medium io.Medium
path string
}
func newFollowReader(ctx context.Context, m io.Medium, path string) (*followReader, error) {
if ctx == nil {
ctx = context.Background()
}
file, err := m.Open(path)
if err != nil {
return nil, err
@ -370,8 +372,6 @@ func newFollowReader(ctx context.Context, m io.Medium, path string) (*followRead
ctx: ctx,
cancel: cancel,
reader: bufio.NewReader(file),
medium: m,
path: path,
}, nil
}

View file

@ -116,6 +116,10 @@ func (s *State) SaveState() error {
// Add adds a container to the state and persists it.
func (s *State) Add(c *Container) error {
if c == nil {
return core.E("State.Add", "container cannot be nil", nil)
}
s.mu.Lock()
s.Containers[c.ID] = c
s.mu.Unlock()
@ -140,6 +144,10 @@ func (s *State) Get(id string) (*Container, bool) {
// Update updates a container in the state and persists it.
func (s *State) Update(c *Container) error {
if c == nil {
return core.E("State.Update", "container cannot be nil", nil)
}
s.mu.Lock()
s.Containers[c.ID] = c
s.mu.Unlock()