feat(agent): gpt-5.4-mini/mature pass 2

- `git add` / `git commit` fail with `Operation not permitted` on `.git/index.lock`
  - even a plain `touch .git/...` is blocked

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Snider 2026-04-18 08:34:52 +01:00
parent 651783e1f5
commit 60f4cb6fdb
4 changed files with 27 additions and 11 deletions

View file

@ -1,2 +0,0 @@
- @bug pkg/agentic/deps.go:59 — `go.work` is written without checking the result, so dependency cloning can fail silently.
- @bug pkg/agentic/prep.go:835 — the PHP-specific `CODEX.md` overwrite ignores write failures, leaving prep to continue with a partial workspace.

View file

@ -9,18 +9,18 @@ import (
)
// s.cloneWorkspaceDeps(ctx, workspaceDir, repoDir, "core")
func (s *PrepSubsystem) cloneWorkspaceDeps(ctx context.Context, workspaceDir, repoDir, org string) {
func (s *PrepSubsystem) cloneWorkspaceDeps(ctx context.Context, workspaceDir, repoDir, org string) error {
goModPath := core.JoinPath(repoDir, "go.mod")
r := fs.Read(goModPath)
if !r.OK {
return
return nil
}
deps := parseCoreDeps(r.Value.(string))
if len(deps) == 0 {
return
return nil
}
if s.ServiceRuntime == nil {
return
return nil
}
process := s.Core().Process()
@ -56,8 +56,15 @@ func (s *PrepSubsystem) cloneWorkspaceDeps(ctx context.Context, workspaceDir, re
b.WriteString(core.Concat("\t./", dir, "\n"))
}
b.WriteString(")\n")
fs.Write(core.JoinPath(workspaceDir, "go.work"), b.String())
if r := fs.WriteAtomic(core.JoinPath(workspaceDir, "go.work"), b.String()); !r.OK {
if err, ok := r.Value.(error); ok {
return core.E("cloneWorkspaceDeps", "write go.work", err)
}
return core.E("cloneWorkspaceDeps", "write go.work", nil)
}
}
return nil
}
// dep := coreDep{module: "dappco.re/go/core", repo: "go", dir: "core-go"}

View file

@ -70,7 +70,9 @@ func TestDeps_CloneWorkspaceDeps_Bad_NoGoMod(t *testing.T) {
}
subsystem := &PrepSubsystem{}
subsystem.cloneWorkspaceDeps(context.Background(), wsDir, repoDir, "core")
if err := subsystem.cloneWorkspaceDeps(context.Background(), wsDir, repoDir, "core"); err != nil {
t.Fatalf("clone workspace deps: %v", err)
}
assert.False(t, fs.IsFile(core.JoinPath(wsDir, "go.work")))
}
@ -95,7 +97,9 @@ require (
}
subsystem := &PrepSubsystem{}
subsystem.cloneWorkspaceDeps(context.Background(), wsDir, repoDir, "core")
if err := subsystem.cloneWorkspaceDeps(context.Background(), wsDir, repoDir, "core"); err != nil {
t.Fatalf("clone workspace deps: %v", err)
}
assert.False(t, fs.IsFile(core.JoinPath(wsDir, "go.work")))
}

View file

@ -832,11 +832,18 @@ func (s *PrepSubsystem) prepWorkspace(ctx context.Context, _ *mcp.CallToolReques
if lang == "php" {
if r := lib.WorkspaceFile("default", "CODEX-PHP.md.tmpl"); r.OK {
codexPath := core.JoinPath(workspaceDir, "CODEX.md")
fs.Write(codexPath, r.Value.(string))
if writeResult := fs.WriteAtomic(codexPath, r.Value.(string)); !writeResult.OK {
if err, ok := writeResult.Value.(error); ok {
return nil, PrepOutput{}, core.E("prepWorkspace", "write CODEX.md", err)
}
return nil, PrepOutput{}, core.E("prepWorkspace", "write CODEX.md", nil)
}
}
}
s.cloneWorkspaceDeps(ctx, workspaceDir, repoDir, input.Org)
if err := s.cloneWorkspaceDeps(ctx, workspaceDir, repoDir, input.Org); err != nil {
return nil, PrepOutput{}, err
}
if err := s.runWorkspaceLanguagePrep(ctx, workspaceDir, repoDir); err != nil {
return nil, PrepOutput{}, err
}