beads: add atomic ctl operations; replace update_bead.sh
Add to 9p ctl handler: open, defer [until <RFC3339>], reopen, relate, unrelate, config. Add corresponding mcptools scripts. Remove update_bead.sh in favour of atomic operation scripts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5dbd4cf777
commit
e55742d691
|
|
@ -988,8 +988,73 @@ func (b *BeadsFS) executeCtlOnStore(store bd.Storage, cmd string) error {
|
|||
}
|
||||
return store.UpdateIssue(b.ctx, args[0], updates, actor)
|
||||
|
||||
case "open":
|
||||
// Promote a deferred bead to open (ready for scheduling).
|
||||
// Usage: open <bead-id>
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("usage: open <bead-id>")
|
||||
}
|
||||
return store.UpdateIssue(b.ctx, args[0], map[string]any{"status": bd.StatusOpen}, actor)
|
||||
|
||||
case "defer":
|
||||
// Defer a bead, optionally until a specific time (RFC3339).
|
||||
// Usage: defer <bead-id> [until <RFC3339-time>]
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("usage: defer <bead-id> [until <RFC3339-time>]")
|
||||
}
|
||||
updates := map[string]any{"status": bd.StatusDeferred}
|
||||
if len(args) >= 3 && args[1] == "until" {
|
||||
t, err := time.Parse(time.RFC3339, args[2])
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid time %q: expected RFC3339 format", args[2])
|
||||
}
|
||||
updates["defer_until"] = t
|
||||
}
|
||||
return store.UpdateIssue(b.ctx, args[0], updates, actor)
|
||||
|
||||
case "reopen":
|
||||
// Reopen a closed bead (reset to open, clear closed_at).
|
||||
// Usage: reopen <bead-id>
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("usage: reopen <bead-id>")
|
||||
}
|
||||
updates := map[string]any{
|
||||
"status": bd.StatusOpen,
|
||||
"closed_at": (*time.Time)(nil),
|
||||
}
|
||||
return store.UpdateIssue(b.ctx, args[0], updates, actor)
|
||||
|
||||
case "relate":
|
||||
// Add a bidirectional relates-to dependency between two beads.
|
||||
// Usage: relate <bead-id-1> <bead-id-2>
|
||||
if len(args) < 2 {
|
||||
return fmt.Errorf("usage: relate <bead-id-1> <bead-id-2>")
|
||||
}
|
||||
dep := &bd.Dependency{
|
||||
IssueID: args[0],
|
||||
DependsOnID: args[1],
|
||||
Type: bd.DepRelated,
|
||||
}
|
||||
return store.AddDependency(b.ctx, dep, actor)
|
||||
|
||||
case "unrelate":
|
||||
// Remove a relates-to dependency between two beads.
|
||||
// Usage: unrelate <bead-id-1> <bead-id-2>
|
||||
if len(args) < 2 {
|
||||
return fmt.Errorf("usage: unrelate <bead-id-1> <bead-id-2>")
|
||||
}
|
||||
return store.RemoveDependency(b.ctx, args[0], args[1], actor)
|
||||
|
||||
case "config":
|
||||
// Set a beads configuration key.
|
||||
// Usage: config <key> <value>
|
||||
if len(args) < 2 {
|
||||
return fmt.Errorf("usage: config <key> <value>")
|
||||
}
|
||||
return store.SetConfig(b.ctx, args[0], args[1])
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown command: %s (supported: init, new, update, delete, claim, unclaim, complete, fail, dep, undep, pending-approval, pending-review, resume, label, unlabel, set-capability)", command)
|
||||
return fmt.Errorf("unknown command: %s (supported: init, new, update, delete, claim, unclaim, open, defer, reopen, complete, fail, dep, undep, relate, unrelate, pending-approval, pending-review, resume, label, unlabel, set-capability, config)", command)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
# capabilities: beads
|
||||
# description: Set a beads database configuration key
|
||||
# Usage: config_beads.sh <mount> <key> <value>
|
||||
set -euo pipefail
|
||||
|
||||
if cat /etc/shadow >/dev/null 2>&1; then
|
||||
echo "Error: This script must be run via execute_code tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "usage: config_beads.sh <mount> <key> <value>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "config $2 $3" | 9p write anvillm/beads/$1/ctl
|
||||
echo "config $2 = $3"
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#!/bin/bash
|
||||
# capabilities: beads
|
||||
# description: Defer a bead, optionally until a specific time
|
||||
# Usage: defer_bead.sh <mount> <bead-id> [until <RFC3339-time>]
|
||||
set -euo pipefail
|
||||
|
||||
if cat /etc/shadow >/dev/null 2>&1; then
|
||||
echo "Error: This script must be run via execute_code tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "usage: defer_bead.sh <mount> <bead-id> [until <RFC3339-time>]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MOUNT="$1"
|
||||
BEAD_ID="$2"
|
||||
shift 2
|
||||
|
||||
if [ $# -ge 2 ] && [ "$1" = "until" ]; then
|
||||
echo "defer $BEAD_ID until $2" | 9p write anvillm/beads/$MOUNT/ctl
|
||||
echo "deferred $BEAD_ID until $2"
|
||||
else
|
||||
echo "defer $BEAD_ID" | 9p write anvillm/beads/$MOUNT/ctl
|
||||
echo "deferred $BEAD_ID"
|
||||
fi
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
# capabilities: beads
|
||||
# description: Promote a deferred bead to open (ready for scheduling)
|
||||
# Usage: open_bead.sh <mount> <bead-id>
|
||||
set -euo pipefail
|
||||
|
||||
if cat /etc/shadow >/dev/null 2>&1; then
|
||||
echo "Error: This script must be run via execute_code tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "usage: open_bead.sh <mount> <bead-id>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "open $2" | 9p write anvillm/beads/$1/ctl
|
||||
echo "opened $2"
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
# capabilities: beads
|
||||
# description: Add a relates-to link between two beads
|
||||
# Usage: relate_beads.sh <mount> <bead-id-1> <bead-id-2>
|
||||
set -euo pipefail
|
||||
|
||||
if cat /etc/shadow >/dev/null 2>&1; then
|
||||
echo "Error: This script must be run via execute_code tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "usage: relate_beads.sh <mount> <bead-id-1> <bead-id-2>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "relate $2 $3" | 9p write anvillm/beads/$1/ctl
|
||||
echo "related $2 ↔ $3"
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
# capabilities: beads
|
||||
# description: Reopen a closed bead (reset to open)
|
||||
# Usage: reopen_bead.sh <mount> <bead-id>
|
||||
set -euo pipefail
|
||||
|
||||
if cat /etc/shadow >/dev/null 2>&1; then
|
||||
echo "Error: This script must be run via execute_code tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "usage: reopen_bead.sh <mount> <bead-id>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "reopen $2" | 9p write anvillm/beads/$1/ctl
|
||||
echo "reopened $2"
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
# capabilities: beads
|
||||
# description: Remove a relates-to link between two beads
|
||||
# Usage: unrelate_beads.sh <mount> <bead-id-1> <bead-id-2>
|
||||
set -euo pipefail
|
||||
|
||||
if cat /etc/shadow >/dev/null 2>&1; then
|
||||
echo "Error: This script must be run via execute_code tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "usage: unrelate_beads.sh <mount> <bead-id-1> <bead-id-2>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "unrelate $2 $3" | 9p write anvillm/beads/$1/ctl
|
||||
echo "unrelated $2 ↔ $3"
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#!/bin/bash
|
||||
# capabilities: beads
|
||||
# description: Update a bead field
|
||||
# Usage: update_bead.sh <mount> <bead-id> <field> <value>
|
||||
set -euo pipefail
|
||||
|
||||
if cat /etc/shadow >/dev/null 2>&1; then
|
||||
echo "Error: This script must be run via execute_code tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -lt 4 ]; then
|
||||
echo "usage: update_bead.sh <mount> <bead-id> <field> <value>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MOUNT="$1"
|
||||
BEAD_ID="$2"
|
||||
FIELD="$3"
|
||||
shift 3
|
||||
VALUE="$*"
|
||||
|
||||
printf "update %s %s '%s'\n" "$BEAD_ID" "$FIELD" "$VALUE" | 9p write anvillm/beads/$MOUNT/ctl
|
||||
echo "updated $BEAD_ID.$FIELD: $VALUE"
|
||||
Reference in New Issue