From de6ff3da29ec74bc5499bf861a505608f08e5c10 Mon Sep 17 00:00:00 2001 From: damocles Date: Fri, 22 May 2026 00:18:45 +0200 Subject: [PATCH] hive-forge: add milestone verb (list/create/close), closes #226 --- hive-ag3nt/prompts/agent.md | 2 +- hive-ag3nt/prompts/manager.md | 2 +- nix/packages/hive-forge-tools.nix | 54 +++++++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/hive-ag3nt/prompts/agent.md b/hive-ag3nt/prompts/agent.md index c853e64..89a3735 100644 --- a/hive-ag3nt/prompts/agent.md +++ b/hive-ag3nt/prompts/agent.md @@ -24,7 +24,7 @@ Claude session (OAuth credentials) lives at `/root/.claude/` and persists across **Code forge**: a private Forgejo at `http://localhost:3000` is available when `/agents/{label}/state/forge-token` exists. You have your own user account (named `{label}`); credentials for the `tea` CLI are pre-configured at boot. Use `tea repos create`, `tea pulls create --base main --head `, `tea pulls list`, `tea issues create`, etc. for any persistent code work — git repos that should outlive a single turn, code you want a peer or the operator to review, anything you'd otherwise jam into `/shared`. Falls back to plain `git`/`curl` if `tea` doesn't fit; the REST API is at `http://localhost:3000/api/v1/` with the same token (`Authorization: token $(cat /agents/{label}/state/forge-token)`). -The `hive-forge` CLI helper wraps common Forgejo API operations: `view`, `issue`, `issue-create`, `issue-edit`, `pr`, `pr-create`, `comment`, `assign`, `close`, `labels`, `pr-reviews`, `branches`, `tree-sha`, `diff`, `subscription`. To create a PR: `hive-forge pr-create --title "..." --head [--base main] [--body "..."] [--draft] [repo]` — prints the PR URL. To create an issue: `hive-forge issue-create --title "..." [--body "..."] [--assignee ] [repo]`. To attach a file to an issue or comment use `hive-forge attach-issue [repo]` or `hive-forge attach-comment [repo]` — both print the `browser_download_url` of the uploaded attachment. Key ops: `hive-forge diff [repo]` prints the unified diff; `hive-forge subscription [--watch|--ignore|--unwatch] [repo]` manages repo watch state. Note: forge notifications are delivered via the internal message daemon. +The `hive-forge` CLI helper wraps common Forgejo API operations: `view`, `issue`, `issue-create`, `issue-edit`, `pr`, `pr-create`, `comment`, `assign`, `close`, `labels`, `milestone`, `pr-reviews`, `branches`, `tree-sha`, `diff`, `subscription`. To create a PR: `hive-forge pr-create --title "..." --head [--base main] [--body "..."] [--draft] [repo]` — prints the PR URL. To create an issue: `hive-forge issue-create --title "..." [--body "..."] [--assignee ] [repo]`. To attach a file to an issue or comment use `hive-forge attach-issue [repo]` or `hive-forge attach-comment [repo]` — both print the `browser_download_url` of the uploaded attachment. Key ops: `hive-forge diff [repo]` prints the unified diff; `hive-forge subscription [--watch|--ignore|--unwatch] [repo]` manages repo watch state. Note: forge notifications are delivered via the internal message daemon. Keep messages short — a few sentences each. For anything big (file listings, long diffs, transcripts, analysis): write the payload to `/agents/{label}/state/` and `send` a short pointer ("dropped the cluster audit in /agents/{label}/state/cluster-audit-2026-05.md, headline: 3 nodes over 80% mem"). The manager + operator can read your state from the host as `/agents/{label}/state/`. Sub-agent peers can't read each other's state directly — go through the manager if a payload needs to reach another sub-agent. diff --git a/hive-ag3nt/prompts/manager.md b/hive-ag3nt/prompts/manager.md index bbb5c0b..a50e10a 100644 --- a/hive-ag3nt/prompts/manager.md +++ b/hive-ag3nt/prompts/manager.md @@ -91,7 +91,7 @@ Keep messages short — a few sentences each. For anything big (digests, agent r - To the operator: write to your own `/state/` (host path `/var/lib/hyperhive/agents/hm1nd/state/`) and tell them where to look. - For shared artifacts (coordination, common reference data): write to `/shared/`. Only put things here you're willing to lose — other agents may delete them. -**Code forge**: a private Forgejo at `http://localhost:3000` is available when `/state/forge-token` exists. You have your own user (`hm1nd`) and so does every sub-agent (one per name). The `tea` CLI is pre-configured at boot. Use it for code work that should survive a turn — a proposed refactor across sub-agents, scratch repos, PRs you want a sub-agent or the operator to review (`tea pulls create --base main --head `, `tea pulls list`, `tea issues create`). REST API at `http://localhost:3000/api/v1/` with `Authorization: token $(cat /state/forge-token)` for anything `tea` can't express. The `hive-forge` CLI helper wraps common operations: `view`, `issue`, `issue-create`, `issue-edit`, `pr`, `pr-create`, `comment`, `assign`, `close`, `labels`, `pr-reviews`, `branches`, `tree-sha`, `diff`, `subscription`, `attach-issue`, `attach-comment`. Use `hive-forge pr-create --title "..." --head [--base main] [--body "..."] [--draft]` to open a PR; `hive-forge issue-create --title "..." [--body "..."] [--assignee ]` to file an issue; `diff ` prints unified diff; `subscription [--watch|--ignore|--unwatch] [repo]` manages watch state. Forge notifications arrive via the internal message daemon. +**Code forge**: a private Forgejo at `http://localhost:3000` is available when `/state/forge-token` exists. You have your own user (`hm1nd`) and so does every sub-agent (one per name). The `tea` CLI is pre-configured at boot. Use it for code work that should survive a turn — a proposed refactor across sub-agents, scratch repos, PRs you want a sub-agent or the operator to review (`tea pulls create --base main --head `, `tea pulls list`, `tea issues create`). REST API at `http://localhost:3000/api/v1/` with `Authorization: token $(cat /state/forge-token)` for anything `tea` can't express. The `hive-forge` CLI helper wraps common operations: `view`, `issue`, `issue-create`, `issue-edit`, `pr`, `pr-create`, `comment`, `assign`, `close`, `labels`, `milestone`, `pr-reviews`, `branches`, `tree-sha`, `diff`, `subscription`, `attach-issue`, `attach-comment`. Use `hive-forge pr-create --title "..." --head [--base main] [--body "..."] [--draft]` to open a PR; `hive-forge issue-create --title "..." [--body "..."] [--assignee ]` to file an issue; `diff ` prints unified diff; `subscription [--watch|--ignore|--unwatch] [repo]` manages watch state. Forge notifications arrive via the internal message daemon. A one-line headline + the file path beats a wall-of-text every time — it survives context compaction and the operator can read it in their own time. diff --git a/nix/packages/hive-forge-tools.nix b/nix/packages/hive-forge-tools.nix index 5ddffc1..421844a 100644 --- a/nix/packages/hive-forge-tools.nix +++ b/nix/packages/hive-forge-tools.nix @@ -371,11 +371,60 @@ pkgs.writeShellApplication { fi } + cmd_milestone() { + # milestone [list|create|close] [args...] [repo] + # Manage milestones. Default action: list. + # list [repo] -- list open milestones as JSON + # create --title [--desc <desc>] [--due YYYY-MM-DD] [repo] -- create milestone, print id+title + # close <id> [repo] -- close a milestone + local _action="''${1:-list}" + shift || true + local _repo="$HIVE_FORGE_REPO" + case "$_action" in + list) + if [ $# -gt 0 ] && [[ "$1" != --* ]]; then _repo="$1"; shift; fi + forge_get "$FORGE_API/repos/$_repo/milestones?state=open&limit=50" \ + | jq '[.[] | {id,title,open_issues,closed_issues,due_on,description}]' + ;; + create) + local _title="" _desc="" _due="" + while [ $# -gt 0 ]; do + case "$1" in + --title) _title="$2"; shift 2 ;; + --desc) _desc="$2"; shift 2 ;; + --due) _due="$2"; shift 2 ;; + *) _repo="$1"; shift ;; + esac + done + if [ -z "$_title" ]; then + echo "usage: hive-forge milestone create --title <title> [--desc <desc>] [--due YYYY-MM-DD] [repo]" >&2; exit 1 + fi + local _payload + _payload=$(jq -n --arg t "$_title" --arg d "$_desc" --arg due "$_due" \ + '{title:$t} | + if $d != "" then . + {description:$d} else . end | + if $due != "" then . + {due_on:($due+"T00:00:00Z")} else . end') + forge_post "$FORGE_API/repos/$_repo/milestones" "$_payload" \ + | jq '{id,title}' + ;; + close) + if [ $# -lt 1 ]; then echo "usage: hive-forge milestone close <id> [repo]" >&2; exit 1; fi + local _id="$1"; shift + if [ $# -gt 0 ]; then _repo="$1"; fi + forge_patch "$FORGE_API/repos/$_repo/milestones/$_id" '{"state":"closed"}' \ + | jq '{id,title,state}' + ;; + *) + echo "unknown milestone action: $_action (use list, create, close)" >&2; exit 1 + ;; + esac + } + VERB="''${1:-}" if [ -z "$VERB" ]; then echo "usage: hive-forge <verb> [args...]" >&2 echo "verbs: view, issue, issue-create, issue-edit, pr, pr-create, comment, assign, close," >&2 - echo " labels, pr-reviews, branches, tree-sha, diff, subscription," >&2 + echo " labels, milestone, pr-reviews, branches, tree-sha, diff, subscription," >&2 echo " attach-issue, attach-comment" >&2 exit 1 fi @@ -392,6 +441,7 @@ pkgs.writeShellApplication { assign) cmd_assign "$@" ;; close) cmd_close "$@" ;; labels) cmd_labels "$@" ;; + milestone) cmd_milestone "$@" ;; pr-reviews) cmd_pr_reviews "$@" ;; branches) cmd_branches "$@" ;; tree-sha) cmd_tree_sha "$@" ;; @@ -402,7 +452,7 @@ pkgs.writeShellApplication { *) echo "hive-forge: unknown verb '$VERB'" >&2 echo "verbs: view, issue, issue-create, issue-edit, pr, pr-create, comment, assign, close," >&2 - echo " labels, pr-reviews, branches, tree-sha, diff, subscription," >&2 + echo " labels, milestone, pr-reviews, branches, tree-sha, diff, subscription," >&2 echo " attach-issue, attach-comment" >&2 exit 1 ;;