Verification is optional and the agent's job; the form stays open with a receipt; panes fall back to a shell

This commit is contained in:
Sam
2026-11-11 11:28:11 +11:00
parent c9e027d0e3
commit 678c497064
8 changed files with 329 additions and 18 deletions

View File

@@ -52,12 +52,12 @@ const (
fieldCount
)
var fieldNames = []string{"Title", "What it must do", "Must finish first", "Proves it is done", "Assign to an agent"}
var fieldNames = []string{"Title", "What it must do", "Must finish first", "A command that proves it (optional)", "Assign to an agent"}
var fieldHints = []string{
"one line, the thing to be done",
"details the agent needs: files, behaviour, limits",
"identifier of a task that must finish first, or empty",
"a command that succeeds only when the work is right, or empty",
"leave empty and the agent decides how to check its own work",
"yes, to hand it to the configured agent after the blocker is set",
}
@@ -76,6 +76,9 @@ func newTaskForm(c *paperclip.Client, proj paperclip.Project, agentID string) ne
func (m newTaskModel) Init() tea.Cmd { return textinput.Blink }
// fieldTitle is index 0; kept as a method so the intent is readable above.
func (m newTaskModel) fieldTitle() int { return fieldTitle }
func (m newTaskModel) submit() tea.Cmd {
title := strings.TrimSpace(m.inputs[fieldTitle].Value())
body := strings.TrimSpace(m.inputs[fieldBody].Value())
@@ -177,14 +180,22 @@ func (m newTaskModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.err = msg.err
return m, nil
}
// Stay open with a receipt and empty fields. A pane that quits on
// success leaves nothing behind, which reads like a crash.
m.result = "created " + msg.issue.Identifier
if msg.blocked != "" {
m.result += ", waiting on " + msg.blocked
}
if msg.assigned {
m.result += ", handed to an agent"
m.result += ", handed to an agent which will start on its own"
}
return m, tea.Quit
for i := range m.inputs {
m.inputs[i].SetValue("")
}
m.focus = fieldTitle
m.inputs[m.fieldTitle()].Focus()
m.tab = 0
return m, nil
}
var cmd tea.Cmd
@@ -242,8 +253,8 @@ func (m newTaskModel) guidanceLines(width int) []string {
"Create CHANGELOG.md at the repository root. One section titled Unreleased with three bullets. Change no other file. Commit it.")
add("Must finish first", "The identifier of another task, for example AUD-171. Paperclip then records a real blocker edge and will not let this task run before that one is done. Leave it empty when nothing must come first.",
"AUD-171")
add("Proves it is done", "A shell command that exits 0 only when the work is right. It runs in the task's own copy of the code. Leave it empty and the task will be accepted on the agent's word, which is a weaker test.",
"test -s CHANGELOG.md or make test")
add("A command that proves it", "Optional. Most tasks need nothing here: the agent does the work, runs the project's own tests, and says what it did. Fill this in only when you want a hard gate that no agent can talk its way past.",
"make test or go test ./...")
add("Assign to", "yes, or empty. yes hands the task to the configured agent as soon as it is created; empty leaves it for a person to assign on the board.",
"yes")
@@ -316,6 +327,10 @@ func (m newTaskModel) View() string {
func (m newTaskModel) formLines(width int) []string {
var body []string
body = append(body, "")
if m.result != "" {
body = append(body, " "+lipgloss.NewStyle().Foreground(lipgloss.Color(active.Success)).Bold(true).Render(m.result))
body = append(body, "")
}
for i, in := range m.inputs {
label := fieldNames[i]
if i == fieldTitle {