chore(hq): daily sync 2026-02-17
This commit is contained in:
0
hq/workspaces/shared/.taskboard.lock
Normal file
0
hq/workspaces/shared/.taskboard.lock
Normal file
48
hq/workspaces/shared/CHANNELS.md
Normal file
48
hq/workspaces/shared/CHANNELS.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Atomizer HQ — Discord Channel Guide
|
||||
|
||||
## How It Works
|
||||
- **Shared channels:** Agents only respond when `@mentioned` by name
|
||||
- **Direct messages (`#dm-{agent}`):** No mention needed — that agent always listens
|
||||
- **New project?** Start exploring in `#rnd`. When it's serious → Manager creates a `#proj-*` channel.
|
||||
|
||||
## Standing Channels (📋 HQ)
|
||||
|
||||
| Channel | Purpose | Who to @mention |
|
||||
|---------|---------|-----------------|
|
||||
| **#hq** | CEO directives & general command | Manager listens automatically; @mention others |
|
||||
| **#feed** | Activity feed — what's happening across the org | Any agent (they post updates here) |
|
||||
| **#technical** | Engineering discussion | @Tech Lead, @Optimizer, @NX Expert |
|
||||
| **#rnd** | R&D, ideas, experiments — before they earn a project | Any agent |
|
||||
| **#lessons-learned** | Permanent post-mortems. Survives project archival. | @Auditor enforces |
|
||||
| **#knowledge-base** | Curated reference material (not discussion) | Any agent to query |
|
||||
| **#it** | Infrastructure & ops | @Webster |
|
||||
|
||||
## Project Channels (🏗️ PROJECTS)
|
||||
Dynamic — Manager creates `#proj-*` channels as needed.
|
||||
|
||||
| Channel | Project |
|
||||
|---------|---------|
|
||||
| **#proj-hydrotech-beam** | Hydrotech Beam |
|
||||
|
||||
## Direct Messages (📨 DIRECT LINES)
|
||||
No @mention needed — the agent always listens in their DM channel.
|
||||
|
||||
| Channel | Agent |
|
||||
|---------|-------|
|
||||
| `#dm-manager` | Manager |
|
||||
| `#dm-tech-lead` | Tech Lead |
|
||||
| `#dm-secretary` | Secretary |
|
||||
| `#dm-auditor` | Auditor |
|
||||
| `#dm-optimizer` | Optimizer |
|
||||
| `#dm-study-builder` | Study Builder |
|
||||
| `#dm-nx-expert` | NX Expert |
|
||||
| `#dm-webster` | Webster |
|
||||
|
||||
## What's Different From Before
|
||||
- **#feed** is the game-changer — no more guessing what's happening
|
||||
- **#lessons-learned** is permanent — survives project archival, Auditor enforces post-mortems
|
||||
- **#knowledge-base** stays as curated reference (not discussion — use #rnd or #technical)
|
||||
- **#rnd** gives ideas a place to live before they earn a project channel
|
||||
- **#it** separates infra noise from real work
|
||||
- Direct lines renamed `#dm-*` for clarity
|
||||
- 6 standing + 8 direct lines + dynamic project channels = clean but powerful
|
||||
42
hq/workspaces/shared/DISCORD_CHANNELS.md
Normal file
42
hq/workspaces/shared/DISCORD_CHANNELS.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Discord Channel Reference — Atomizer HQ
|
||||
|
||||
When posting to Discord, ALWAYS use the message tool with:
|
||||
- `channel: "discord"`
|
||||
- `target: "channel:<channel-name>"`
|
||||
|
||||
⚠️ NEVER use raw numeric IDs without the `channel:` or `user:` prefix. OpenClaw requires this to disambiguate.
|
||||
|
||||
## Key Channels
|
||||
| Channel | Use for |
|
||||
|---------|---------|
|
||||
| `channel:reports` | Secretary condensation summaries, orchestration distillates |
|
||||
| `channel:feed` | Kanban snapshots, orchestration plans, status updates |
|
||||
| `channel:hq` | Company-wide coordination, task discussion |
|
||||
| `channel:technical` | Technical deliverables, analysis results, code |
|
||||
| `channel:knowledge-base` | New KB entries, reference data, material properties |
|
||||
| `channel:rnd` | R&D discussions |
|
||||
| `channel:lessons-learned` | Lessons learned, post-mortems |
|
||||
| `channel:it` | Infrastructure, tooling |
|
||||
|
||||
## Deliverable Routing (from taskboard)
|
||||
| Deliverable Type | Default Channel |
|
||||
|-----------------|-----------------|
|
||||
| document | `channel:reports` |
|
||||
| code | `channel:technical` |
|
||||
| analysis | `channel:technical` |
|
||||
| recommendation | `channel:reports` |
|
||||
| review | `channel:reports` |
|
||||
| data | `channel:knowledge-base` |
|
||||
|
||||
## Antoine's DM
|
||||
To DM Antoine: `target: "user:719982779793932419"`
|
||||
|
||||
## Example (message tool)
|
||||
```json
|
||||
{
|
||||
"action": "send",
|
||||
"channel": "discord",
|
||||
"target": "channel:reports",
|
||||
"message": "📋 **Report Title**\n\nContent here..."
|
||||
}
|
||||
```
|
||||
28
hq/workspaces/shared/orchestration-log.md
Normal file
28
hq/workspaces/shared/orchestration-log.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Orchestration Log
|
||||
|
||||
_Append-only. Manager posts orchestration plans here before delegating work._
|
||||
|
||||
---
|
||||
|
||||
## [2026-02-17 01:42] Orchestration: System Test — Taskboard Validation
|
||||
|
||||
**Objective:** Validate the new taskboard orchestration workflow end-to-end
|
||||
**Tasks created:** TASK-001, TASK-002
|
||||
**Agent assignments:**
|
||||
- Webster → Quick research task (TASK-001)
|
||||
- Secretary → Summarize results and post to #reports (TASK-002, after TASK-001)
|
||||
|
||||
**Dependencies:** TASK-002 waits on TASK-001
|
||||
**Expected output:** Webster posts to #technical, Secretary posts distillate to #reports
|
||||
**ETA:** ~15 minutes
|
||||
|
||||
---
|
||||
## [2026-02-17 02:04] Orchestration: M2 Mirror Material Trade Study
|
||||
**Objective:** Compare Zerodur Class 0 and Clearceram-Z HS for the M2 mirror application and provide a final recommendation.
|
||||
**Tasks created:** TASK-001, TASK-002, TASK-003 (will be created by the workflow)
|
||||
**Agent assignments:**
|
||||
- Webster: Research thermal and mechanical properties.
|
||||
- Tech Lead: Assess materials against thermal stability requirements.
|
||||
- Secretary: Summarize findings into a recommendation report.
|
||||
**Dependencies:** Tech Lead's work depends on Webster's output. Secretary's work depends on the Tech Lead's output.
|
||||
**Expected output:** A final recommendation report posted by the Secretary.
|
||||
@@ -5,3 +5,24 @@
|
||||
[2026-02-15 18:30] Webster: Completed — Logged new material property (Invar 36 Young's modulus) to memory.
|
||||
[2026-02-15 18:30] Webster: Completed — Received duplicate material property for Invar 36. No action taken as data is already in memory.
|
||||
[2026-02-16 03:03] webster: Completed — Research on thermal conductivity of SiC and comparison with ULE and Zerodur.
|
||||
[2026-02-16 14:05] Auditor: Completed — Challenged the Technical Lead on the 'P-Adaptive-Isogrid vs State-of-the-Art' review in the #technical channel.
|
||||
[2026-02-16 15:35] Auditor: Completed — Sent a direct message to the Tech Lead to follow up on the 'P-Adaptive-Isogrid vs State-of-the-Art' review.
|
||||
[2026-02-16 17:12] Auditor: Completed — Notified the Manager that I am blocked on the 'P-Adaptive-Isogrid vs State-of-the-Art' review pending a response from the Tech Lead.
|
||||
[2026-02-16 12:56] Webster: Completed — Logged CEO decision to prioritize structural performance for the lightweight bracket, selecting 7075-T6.
|
||||
[2026-02-17 01:41] [manager] TASK-001: Created — Research: What is the melting point of Invar 36? (assigned to webster)
|
||||
[2026-02-17 01:41] [manager] TASK-002: Created — Summarize system test orchestration (assigned to secretary)
|
||||
[2026-02-17 01:42] [webster] TASK-001: Status → in-progress — Started research
|
||||
[2026-02-17 01:42] [webster] TASK-001: Status → review — Posted to #technical
|
||||
[2026-02-16 20:42] webster: Completed — Researched melting point of Invar 36 (TASK-001)
|
||||
[2026-02-17 01:42] [manager] TASK-001: Completed — Deliverable accepted — melting point data posted to #technical
|
||||
[2026-02-17 01:43] [secretary] TASK-002: Status → in-progress — Starting condensation
|
||||
[2026-02-17 01:43] [secretary] TASK-002: Status → review — Distillate composed, but failed to post to #reports due to tool error.
|
||||
[2026-02-17 03:05] [manager] TASK-002: Status → in-progress — Manager: Tool error prevented report delivery. Please provide the summary directly to me in the #hq channel.
|
||||
[2026-02-17 04:06] [manager] TASK-003: Created — Resolve blocked task: Clearceram-Z HS data (assigned to manager)
|
||||
[2026-02-16 23:21] Webster: Completed — Verified CTE and Density for Clearceram-Z HS.
|
||||
[2026-02-16 23:55] Webster: Reviewed state-of-the-art for isogrid design optimization in aerospace, focusing on mass-strength trade-offs and novel geometries. Found no external or internal references to 'P-Adaptive-Isogrid.' Ready to contribute to the review once pointed to the relevant internal documents or discussions.
|
||||
[2026-02-17 06:35] [manager] TASK-003: Completed — Webster reported completing the data verification in the project log, unblocking the original task. Closing this resolution task.
|
||||
[2026-02-17 07:05] [manager] TASK-002: Status → in-progress — Checking in on status, since original delivery was blocked by a tool error.
|
||||
[2026-02-17 09:05] [manager] TASK-002: Cancelled — Secretary appears to be stuck; tool error on deliverable. Re-creating as TASK-004 assigned to manager to unblock.
|
||||
[2026-02-17 09:05] [manager] TASK-004: Created — Summarize system test orchestration (replaces TASK-002) (assigned to manager)
|
||||
[2026-02-17 09:05] [manager] TASK-004: Completed — Summary posted to #reports channel.
|
||||
|
||||
@@ -159,11 +159,16 @@ Write the file BEFORE posting to Discord. The orchestrator is waiting for it."""
|
||||
if context:
|
||||
message = f"CONTEXT:\n{context}\n\n{message}"
|
||||
|
||||
# Map agent to their Discord delivery channel (dl-<agent>)
|
||||
discord_channel = f"channel:dl-{agent}"
|
||||
|
||||
payload = {
|
||||
"message": message,
|
||||
"name": f"orchestrate:{run_id}",
|
||||
"sessionKey": f"hook:orchestrate:{run_id}:{attempt}",
|
||||
"deliver": not no_deliver,
|
||||
"channel": "discord",
|
||||
"to": discord_channel,
|
||||
"wakeMode": "now",
|
||||
"timeoutSeconds": 600,
|
||||
}
|
||||
|
||||
72
hq/workspaces/shared/skills/taskboard/SKILL.md
Normal file
72
hq/workspaces/shared/skills/taskboard/SKILL.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Taskboard — Kanban Task Management
|
||||
|
||||
Central orchestration tool for Atomizer HQ. All agents interact with the shared taskboard.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```bash
|
||||
TB="/home/papa/atomizer/workspaces/shared/skills/taskboard/taskboard.sh"
|
||||
|
||||
# List your tasks
|
||||
CALLER=my-agent-name bash "$TB" list --agent my-agent-name
|
||||
|
||||
# List by status or project
|
||||
bash "$TB" list --status in-progress
|
||||
bash "$TB" list --project gigabit-m2
|
||||
|
||||
# View task details
|
||||
bash "$TB" view TASK-001
|
||||
|
||||
# Update task status (any agent can update their own tasks)
|
||||
CALLER=my-agent-name bash "$TB" update TASK-001 --status in-progress --note "Started research"
|
||||
CALLER=my-agent-name bash "$TB" update TASK-001 --status review --note "Draft posted to #technical"
|
||||
|
||||
# Kanban summary (counts per column)
|
||||
bash "$TB" summary
|
||||
|
||||
# Kanban snapshot (markdown for Discord)
|
||||
bash "$TB" snapshot
|
||||
```
|
||||
|
||||
## Manager-Only Commands
|
||||
|
||||
```bash
|
||||
# Create a task
|
||||
CALLER=manager bash "$TB" create \
|
||||
--title "Research CCZ thermal properties" \
|
||||
--assignee webster \
|
||||
--priority high \
|
||||
--project gigabit-m2 \
|
||||
--description "Full thermal comparison: CTE, conductivity for CCZ HS vs Zerodur" \
|
||||
--deliverable-type analysis \
|
||||
--deliverable-channel technical
|
||||
|
||||
# Complete a task
|
||||
CALLER=manager bash "$TB" complete TASK-001 --note "Deliverable accepted"
|
||||
|
||||
# Cancel a task
|
||||
CALLER=manager bash "$TB" cancel TASK-002 --reason "Superseded by new approach"
|
||||
```
|
||||
|
||||
## Status Flow
|
||||
|
||||
```
|
||||
backlog → todo → in-progress → review → done
|
||||
↓
|
||||
cancelled
|
||||
```
|
||||
|
||||
## For Executor Agents (non-Manager)
|
||||
|
||||
On every session start:
|
||||
1. Check your tasks: `CALLER=<you> bash "$TB" list --agent <you>`
|
||||
2. If you have `todo` tasks: update to `in-progress` and start working
|
||||
3. When work is done: update to `review` and post deliverable to the target Discord channel
|
||||
4. Append progress to `shared/project_log.md`
|
||||
|
||||
## Important
|
||||
|
||||
- **taskboard.json is the single source of truth** — never edit it directly
|
||||
- **Only Manager creates/completes/cancels tasks** — other agents update status
|
||||
- **All writes are atomic** (tmp file + mv) with flock locking
|
||||
- **Set CALLER env var** so your name appears in logs and notes
|
||||
380
hq/workspaces/shared/skills/taskboard/taskboard.sh
Executable file
380
hq/workspaces/shared/skills/taskboard/taskboard.sh
Executable file
@@ -0,0 +1,380 @@
|
||||
#!/usr/bin/env bash
|
||||
# taskboard.sh — Kanban task management for Atomizer HQ
|
||||
# Usage: taskboard.sh <command> [options]
|
||||
#
|
||||
# Commands:
|
||||
# list [--agent <name>] [--status <s>] [--project <tag>]
|
||||
# create --title '...' --assignee <agent> --priority <p> --project <tag> --description '...' [--deliverable-type <type>] [--deliverable-channel <ch>] [--due <iso>]
|
||||
# update <task-id> --status <new> [--note '...']
|
||||
# complete <task-id> [--note '...']
|
||||
# cancel <task-id> --reason '...'
|
||||
# view <task-id>
|
||||
# summary
|
||||
# snapshot
|
||||
#
|
||||
# Environment:
|
||||
# CALLER — agent name (used for logging, optional)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
TASKBOARD="/home/papa/atomizer/workspaces/shared/taskboard.json"
|
||||
LOCKFILE="/home/papa/atomizer/workspaces/shared/.taskboard.lock"
|
||||
PROJECT_LOG="/home/papa/atomizer/workspaces/shared/project_log.md"
|
||||
CALLER="${CALLER:-unknown}"
|
||||
NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
NOW_LOG=$(date -u +"%Y-%m-%d %H:%M")
|
||||
|
||||
# --- Helpers ---
|
||||
|
||||
die() { echo "❌ $*" >&2; exit 1; }
|
||||
|
||||
# Atomic write: write to tmp, then mv
|
||||
atomic_write() {
|
||||
local tmp="${TASKBOARD}.tmp.$$"
|
||||
cat > "$tmp"
|
||||
mv -f "$tmp" "$TASKBOARD"
|
||||
}
|
||||
|
||||
# Write lock (flock on fd 9)
|
||||
lock_write() {
|
||||
exec 9>"$LOCKFILE"
|
||||
flock -w 5 9 || die "Could not acquire lock"
|
||||
}
|
||||
|
||||
unlock_write() {
|
||||
flock -u 9 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Append to project log
|
||||
log_entry() {
|
||||
echo "[$NOW_LOG] [$CALLER] $*" >> "$PROJECT_LOG"
|
||||
}
|
||||
|
||||
# Get next task ID
|
||||
next_id() {
|
||||
local max
|
||||
max=$(jq -r '[.tasks[].id | ltrimstr("TASK-") | tonumber] | max // 0' "$TASKBOARD")
|
||||
printf "TASK-%03d" $(( max + 1 ))
|
||||
}
|
||||
|
||||
# --- Commands ---
|
||||
|
||||
cmd_list() {
|
||||
local agent="" status="" project=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--agent) agent="$2"; shift 2 ;;
|
||||
--status) status="$2"; shift 2 ;;
|
||||
--project) project="$2"; shift 2 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
local filter=".tasks"
|
||||
[[ -n "$agent" ]] && filter="$filter | map(select(.assignee == \"$agent\"))"
|
||||
[[ -n "$status" ]] && filter="$filter | map(select(.status == \"$status\"))"
|
||||
[[ -n "$project" ]] && filter="$filter | map(select(.project == \"$project\"))"
|
||||
|
||||
local result
|
||||
result=$(jq -r "$filter | .[] | \"[\(.status | ascii_upcase)] \(.id) [\(.priority)] \(.title) → \(.assignee)\"" "$TASKBOARD")
|
||||
|
||||
if [[ -z "$result" ]]; then
|
||||
echo "No tasks found."
|
||||
else
|
||||
echo "$result"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_create() {
|
||||
local title="" assignee="" priority="medium" project="" description=""
|
||||
local del_type="" del_channel="" due="null"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--title) title="$2"; shift 2 ;;
|
||||
--assignee) assignee="$2"; shift 2 ;;
|
||||
--priority) priority="$2"; shift 2 ;;
|
||||
--project) project="$2"; shift 2 ;;
|
||||
--description) description="$2"; shift 2 ;;
|
||||
--deliverable-type) del_type="$2"; shift 2 ;;
|
||||
--deliverable-channel) del_channel="$2"; shift 2 ;;
|
||||
--due) due="\"$2\""; shift 2 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -z "$title" ]] && die "Missing --title"
|
||||
[[ -z "$assignee" ]] && die "Missing --assignee"
|
||||
[[ -z "$project" ]] && die "Missing --project"
|
||||
|
||||
lock_write
|
||||
|
||||
local id
|
||||
id=$(next_id)
|
||||
|
||||
# Build deliverable object
|
||||
local deliverable="null"
|
||||
if [[ -n "$del_type" || -n "$del_channel" ]]; then
|
||||
deliverable=$(jq -n \
|
||||
--arg t "${del_type:-document}" \
|
||||
--arg c "${del_channel:-reports}" \
|
||||
'{type: $t, targetChannel: $c, format: ""}')
|
||||
fi
|
||||
|
||||
# Add task
|
||||
jq --arg id "$id" \
|
||||
--arg title "$title" \
|
||||
--arg desc "$description" \
|
||||
--arg status "todo" \
|
||||
--arg priority "$priority" \
|
||||
--arg assignee "$assignee" \
|
||||
--arg requestedBy "$CALLER" \
|
||||
--arg project "$project" \
|
||||
--argjson deliverable "$deliverable" \
|
||||
--arg created "$NOW" \
|
||||
--arg updated "$NOW" \
|
||||
--argjson dueBy "$due" \
|
||||
'.tasks += [{
|
||||
id: $id,
|
||||
title: $title,
|
||||
description: $desc,
|
||||
status: $status,
|
||||
priority: $priority,
|
||||
assignee: $assignee,
|
||||
requestedBy: $requestedBy,
|
||||
project: $project,
|
||||
deliverable: $deliverable,
|
||||
created: $created,
|
||||
updated: $updated,
|
||||
dueBy: $dueBy,
|
||||
notes: [],
|
||||
completedAt: null
|
||||
}] | .lastUpdated = $created | .updatedBy = $requestedBy' \
|
||||
"$TASKBOARD" | atomic_write
|
||||
|
||||
unlock_write
|
||||
log_entry "$id: Created — $title (assigned to $assignee)"
|
||||
echo "✅ Created $id: $title → $assignee"
|
||||
}
|
||||
|
||||
cmd_update() {
|
||||
local task_id="${1:-}"; shift || die "Usage: update <task-id> --status <s> [--note '...']"
|
||||
local status="" note=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--status) status="$2"; shift 2 ;;
|
||||
--note) note="$2"; shift 2 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -z "$status" ]] && die "Missing --status"
|
||||
|
||||
# Validate status
|
||||
case "$status" in
|
||||
backlog|todo|in-progress|review|done|cancelled) ;;
|
||||
*) die "Invalid status: $status (must be backlog|todo|in-progress|review|done|cancelled)" ;;
|
||||
esac
|
||||
|
||||
lock_write
|
||||
|
||||
# Check task exists
|
||||
local exists
|
||||
exists=$(jq -r --arg id "$task_id" '.tasks | map(select(.id == $id)) | length' "$TASKBOARD")
|
||||
[[ "$exists" -eq 0 ]] && { unlock_write; die "Task $task_id not found"; }
|
||||
|
||||
local note_entry=""
|
||||
[[ -n "$note" ]] && note_entry="[$NOW_LOG] [$CALLER] $note"
|
||||
|
||||
jq --arg id "$task_id" \
|
||||
--arg status "$status" \
|
||||
--arg updated "$NOW" \
|
||||
--arg updatedBy "$CALLER" \
|
||||
--arg note "$note_entry" \
|
||||
'(.tasks[] | select(.id == $id)) |= (
|
||||
.status = $status |
|
||||
.updated = $updated |
|
||||
if $note != "" then .notes += [$note] else . end
|
||||
) | .lastUpdated = $updated | .updatedBy = $updatedBy' \
|
||||
"$TASKBOARD" | atomic_write
|
||||
|
||||
unlock_write
|
||||
log_entry "$task_id: Status → $status${note:+ — $note}"
|
||||
echo "✅ $task_id → $status"
|
||||
}
|
||||
|
||||
cmd_complete() {
|
||||
local task_id="${1:-}"; shift || die "Usage: complete <task-id> [--note '...']"
|
||||
local note=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--note) note="$2"; shift 2 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
lock_write
|
||||
|
||||
local exists
|
||||
exists=$(jq -r --arg id "$task_id" '.tasks | map(select(.id == $id)) | length' "$TASKBOARD")
|
||||
[[ "$exists" -eq 0 ]] && { unlock_write; die "Task $task_id not found"; }
|
||||
|
||||
local note_entry=""
|
||||
[[ -n "$note" ]] && note_entry="[$NOW_LOG] [$CALLER] $note"
|
||||
|
||||
jq --arg id "$task_id" \
|
||||
--arg updated "$NOW" \
|
||||
--arg updatedBy "$CALLER" \
|
||||
--arg note "$note_entry" \
|
||||
'(.tasks[] | select(.id == $id)) |= (
|
||||
.status = "done" |
|
||||
.updated = $updated |
|
||||
.completedAt = $updated |
|
||||
if $note != "" then .notes += [$note] else . end
|
||||
) | .lastUpdated = $updated | .updatedBy = $updatedBy' \
|
||||
"$TASKBOARD" | atomic_write
|
||||
|
||||
unlock_write
|
||||
log_entry "$task_id: Completed${note:+ — $note}"
|
||||
echo "✅ $task_id → done"
|
||||
}
|
||||
|
||||
cmd_cancel() {
|
||||
local task_id="${1:-}"; shift || die "Usage: cancel <task-id> --reason '...'"
|
||||
local reason=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--reason) reason="$2"; shift 2 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -z "$reason" ]] && die "Missing --reason"
|
||||
|
||||
lock_write
|
||||
|
||||
local exists
|
||||
exists=$(jq -r --arg id "$task_id" '.tasks | map(select(.id == $id)) | length' "$TASKBOARD")
|
||||
[[ "$exists" -eq 0 ]] && { unlock_write; die "Task $task_id not found"; }
|
||||
|
||||
local note_entry="[$NOW_LOG] [$CALLER] Cancelled: $reason"
|
||||
|
||||
jq --arg id "$task_id" \
|
||||
--arg updated "$NOW" \
|
||||
--arg updatedBy "$CALLER" \
|
||||
--arg note "$note_entry" \
|
||||
'(.tasks[] | select(.id == $id)) |= (
|
||||
.status = "cancelled" |
|
||||
.updated = $updated |
|
||||
.notes += [$note]
|
||||
) | .lastUpdated = $updated | .updatedBy = $updatedBy' \
|
||||
"$TASKBOARD" | atomic_write
|
||||
|
||||
unlock_write
|
||||
log_entry "$task_id: Cancelled — $reason"
|
||||
echo "✅ $task_id → cancelled"
|
||||
}
|
||||
|
||||
cmd_view() {
|
||||
local task_id="${1:-}"; [[ -z "$task_id" ]] && die "Usage: view <task-id>"
|
||||
|
||||
local task
|
||||
task=$(jq -r --arg id "$task_id" '.tasks[] | select(.id == $id)' "$TASKBOARD")
|
||||
[[ -z "$task" ]] && die "Task $task_id not found"
|
||||
|
||||
echo "$task" | jq -r '
|
||||
"═══════════════════════════════════════",
|
||||
" \(.id) — \(.title)",
|
||||
"═══════════════════════════════════════",
|
||||
" Status: \(.status)",
|
||||
" Priority: \(.priority)",
|
||||
" Assignee: \(.assignee)",
|
||||
" Requested by: \(.requestedBy)",
|
||||
" Project: \(.project)",
|
||||
" Created: \(.created)",
|
||||
" Updated: \(.updated)",
|
||||
" Due: \(.dueBy // "none")",
|
||||
" Completed: \(.completedAt // "—")",
|
||||
"",
|
||||
" Description:",
|
||||
" \(.description)",
|
||||
"",
|
||||
if (.deliverable != null) then
|
||||
" Deliverable:",
|
||||
" Type: \(.deliverable.type)",
|
||||
" Channel: #\(.deliverable.targetChannel)",
|
||||
""
|
||||
else "" end,
|
||||
if ((.notes | length) > 0) then
|
||||
" Notes:",
|
||||
(.notes[] | " • \(.)")
|
||||
else " Notes: (none)" end
|
||||
'
|
||||
}
|
||||
|
||||
cmd_summary() {
|
||||
echo "📋 Taskboard Summary"
|
||||
echo "════════════════════"
|
||||
jq -r '
|
||||
.tasks | group_by(.status) | map({
|
||||
status: .[0].status,
|
||||
count: length
|
||||
}) | sort_by(.status) | .[] |
|
||||
" \(.status | ascii_upcase): \(.count)"
|
||||
' "$TASKBOARD"
|
||||
|
||||
local total
|
||||
total=$(jq '.tasks | length' "$TASKBOARD")
|
||||
echo "────────────────────"
|
||||
echo " TOTAL: $total"
|
||||
}
|
||||
|
||||
cmd_snapshot() {
|
||||
# Markdown kanban for Discord posting
|
||||
echo "# 📋 Taskboard Snapshot"
|
||||
echo "_Updated: $(date -u +"%Y-%m-%d %H:%M UTC")_"
|
||||
echo ""
|
||||
|
||||
for status in backlog todo in-progress review done; do
|
||||
local label
|
||||
case "$status" in
|
||||
backlog) label="📥 Backlog" ;;
|
||||
todo) label="📌 To Do" ;;
|
||||
in-progress) label="🔄 In Progress" ;;
|
||||
review) label="🔍 Review" ;;
|
||||
done) label="✅ Done" ;;
|
||||
esac
|
||||
|
||||
local tasks
|
||||
tasks=$(jq -r --arg s "$status" '
|
||||
.tasks | map(select(.status == $s)) |
|
||||
if length == 0 then "_(empty)_"
|
||||
else .[] | "- **\(.id)** \(.title) → `\(.assignee)` [\(.priority)]"
|
||||
end
|
||||
' "$TASKBOARD")
|
||||
|
||||
echo "## $label"
|
||||
echo "$tasks"
|
||||
echo ""
|
||||
done
|
||||
}
|
||||
|
||||
# --- Main ---
|
||||
|
||||
cmd="${1:-}"; shift || die "Usage: taskboard.sh <command> [options]
|
||||
Commands: list, create, update, complete, cancel, view, summary, snapshot"
|
||||
|
||||
case "$cmd" in
|
||||
list) cmd_list "$@" ;;
|
||||
create) cmd_create "$@" ;;
|
||||
update) cmd_update "$@" ;;
|
||||
complete) cmd_complete "$@" ;;
|
||||
cancel) cmd_cancel "$@" ;;
|
||||
view) cmd_view "$@" ;;
|
||||
summary) cmd_summary ;;
|
||||
snapshot) cmd_snapshot ;;
|
||||
*) die "Unknown command: $cmd" ;;
|
||||
esac
|
||||
97
hq/workspaces/shared/taskboard.json
Normal file
97
hq/workspaces/shared/taskboard.json
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"version": 1,
|
||||
"lastUpdated": "2026-02-17T09:05:27Z",
|
||||
"updatedBy": "manager",
|
||||
"tasks": [
|
||||
{
|
||||
"id": "TASK-001",
|
||||
"title": "Research: What is the melting point of Invar 36?",
|
||||
"description": "Quick validation task. Research the melting point of Invar 36 and post findings to #technical. Then update your task status to review.",
|
||||
"status": "done",
|
||||
"priority": "medium",
|
||||
"assignee": "webster",
|
||||
"requestedBy": "manager",
|
||||
"project": "system-test",
|
||||
"deliverable": {
|
||||
"type": "data",
|
||||
"targetChannel": "technical",
|
||||
"format": ""
|
||||
},
|
||||
"created": "2026-02-17T01:41:59Z",
|
||||
"updated": "2026-02-17T01:42:54Z",
|
||||
"dueBy": null,
|
||||
"notes": [
|
||||
"[2026-02-17 01:42] [webster] Started research",
|
||||
"[2026-02-17 01:42] [webster] Posted to #technical",
|
||||
"[2026-02-17 01:42] [manager] Deliverable accepted — melting point data posted to #technical"
|
||||
],
|
||||
"completedAt": "2026-02-17T01:42:54Z"
|
||||
},
|
||||
{
|
||||
"id": "TASK-002",
|
||||
"title": "Summarize system test orchestration",
|
||||
"description": "After TASK-001 is done, read the taskboard and orchestration log, produce a short summary of this test orchestration, and post to #reports.",
|
||||
"status": "cancelled",
|
||||
"priority": "medium",
|
||||
"assignee": "secretary",
|
||||
"requestedBy": "manager",
|
||||
"project": "system-test",
|
||||
"deliverable": {
|
||||
"type": "document",
|
||||
"targetChannel": "reports",
|
||||
"format": ""
|
||||
},
|
||||
"created": "2026-02-17T01:41:59Z",
|
||||
"updated": "2026-02-17T09:05:04Z",
|
||||
"dueBy": null,
|
||||
"notes": [
|
||||
"[2026-02-17 01:43] [secretary] Starting condensation",
|
||||
"[2026-02-17 01:43] [secretary] Distillate composed, but failed to post to #reports due to tool error.",
|
||||
"[2026-02-17 03:05] [manager] Manager: Tool error prevented report delivery. Please provide the summary directly to me in the #hq channel.",
|
||||
"[2026-02-17 07:05] [manager] Checking in on status, since original delivery was blocked by a tool error.",
|
||||
"[2026-02-17 09:05] [manager] Cancelled: Secretary appears to be stuck; tool error on deliverable. Re-creating as TASK-004 assigned to manager to unblock."
|
||||
],
|
||||
"completedAt": null
|
||||
},
|
||||
{
|
||||
"id": "TASK-003",
|
||||
"title": "Resolve blocked task: Clearceram-Z HS data",
|
||||
"description": "Task orch-1771176838-52dc0c1b.json (webster) is blocked because the required data for Clearceram-Z HS is only available in a PDF, and no tool is available to parse it. The web_search tool is also unavailable due to a missing API key. Needs manual intervention or a new tool/skill.",
|
||||
"status": "done",
|
||||
"priority": "high",
|
||||
"assignee": "manager",
|
||||
"requestedBy": "manager",
|
||||
"project": "atomizer-ops",
|
||||
"deliverable": null,
|
||||
"created": "2026-02-17T04:06:25Z",
|
||||
"updated": "2026-02-17T06:35:08Z",
|
||||
"dueBy": null,
|
||||
"notes": [
|
||||
"[2026-02-17 06:35] [manager] Webster reported completing the data verification in the project log, unblocking the original task. Closing this resolution task."
|
||||
],
|
||||
"completedAt": "2026-02-17T06:35:08Z"
|
||||
},
|
||||
{
|
||||
"id": "TASK-004",
|
||||
"title": "Summarize system test orchestration (replaces TASK-002)",
|
||||
"description": "Original task was assigned to secretary, who encountered a tool error. This task is to complete the summary of the test orchestration based on the taskboard and orchestration log, and post to the #reports channel.",
|
||||
"status": "done",
|
||||
"priority": "high",
|
||||
"assignee": "manager",
|
||||
"requestedBy": "manager",
|
||||
"project": "system-test",
|
||||
"deliverable": {
|
||||
"type": "document",
|
||||
"targetChannel": "reports",
|
||||
"format": ""
|
||||
},
|
||||
"created": "2026-02-17T09:05:07Z",
|
||||
"updated": "2026-02-17T09:05:27Z",
|
||||
"dueBy": null,
|
||||
"notes": [
|
||||
"[2026-02-17 09:05] [manager] Summary posted to #reports channel."
|
||||
],
|
||||
"completedAt": "2026-02-17T09:05:27Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user