d2f706a16c
- agents/course-hand.md:管 inkstone/ax-courses、course_gen、llm-wiki-template(c7358 leo「你可以製作一個」) 假設:llm-wiki-template 也歸課程工人(同為課程素材),總管不同意就把它拆出去 - hooks/lib/roster.py:`負責 repo` 可列多個(、或逗號),新增 which()/uncovered();find() 與閘本身未動 - scripts/roster which 改走 roster.which - scripts/isep-nag 第④類:org 裡有開著的票、名單上卻沒人負責的 repo,只進開場長版、不進 Telegram - 測試:roster-guard 25→31、overdue-nag 36→43;兩種突變(拿掉票數條件/只認第一個 repo)都會紅 - 文件:worker-roster.md 回答「新 repo 的工人誰在什麼時候加」;README/plugin.json 工人 8、scripts 65(樹上實數) 待總管定版(改了 agents/scripts,要升版才裝得上)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
95 lines
3.3 KiB
Python
Executable File
95 lines
3.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""roster — 工人名單(inkstone/ISEP#86)
|
||
|
||
python3 scripts/roster list 名單:有哪幾個工人、各自管什麼
|
||
python3 scripts/roster show <名字> 一個工人的全文(它開工時會讀到的東西)
|
||
python3 scripts/roster names 只印名字,一行一個(給腳本用)
|
||
python3 scripts/roster which <owner/repo> 這個 repo 該派給誰
|
||
|
||
leo(ISEP#86):「身為派工的人,我要工人有名字,我才知道票上這件事到底是誰做的。」
|
||
|
||
名單是**資料**(`agents/*.md`),不是程式:加一個工人=加一個檔,不改任何 hook。
|
||
派工時把名字放進 `Task` 的 `subagent_type`;名字不在名單上,
|
||
`hooks/roster-guard.sh` 會擋下來並說「沒有這個人」。
|
||
"""
|
||
import os
|
||
import sys
|
||
|
||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "hooks", "lib"))
|
||
try:
|
||
import roster as R
|
||
except Exception as e: # pragma: no cover
|
||
print("🔴 讀不到 hooks/lib/roster.py:%s" % e, file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
|
||
def cmd_list():
|
||
ws = R.load()
|
||
if not ws:
|
||
print("🔴 名單是空的(找不到 %s 底下任何工人檔)" % R.roster_dir(), file=sys.stderr)
|
||
return 1
|
||
print("工人名單(%d 位) 來源:%s\n" % (len(ws), R.roster_dir()))
|
||
print(" %-18s %-26s %s" % ("名字", "負責 repo", "它是誰"))
|
||
print(" " + "─" * 100)
|
||
for w in ws:
|
||
print(" " + R.one_liner(w))
|
||
print("\n派工:把「名字」放進 Task 的 subagent_type;派工單本身仍然只有一行【工單】。")
|
||
print("看某一位的全文:python3 scripts/roster show <名字>")
|
||
return 0
|
||
|
||
|
||
def cmd_show(name):
|
||
w = R.find(name)
|
||
if not w:
|
||
print("🚫 名單上沒有「%s」這個人。現有的是:\n %s"
|
||
% (name, "\n ".join(R.names()) or "(空)"), file=sys.stderr)
|
||
return 2
|
||
print("# %s\n" % w["name"])
|
||
print("負責 repo:%s" % (w["repo"] or "(跨 repo)"))
|
||
print("一句話 :%s" % w["description"])
|
||
print("檔案 :%s\n" % w["path"])
|
||
print(w["body"])
|
||
return 0
|
||
|
||
|
||
def cmd_which(repo):
|
||
hits = R.which(repo) # 一個工人可以管好幾個 repo(inkstone/ISEP#118)
|
||
if not hits:
|
||
print("🚫 名單上沒有負責「%s」的人。現有的是:" % repo, file=sys.stderr)
|
||
for w in R.load():
|
||
print(" " + R.one_liner(w), file=sys.stderr)
|
||
return 2
|
||
for w in hits:
|
||
print(w["name"])
|
||
return 0
|
||
|
||
|
||
def main():
|
||
argv = sys.argv[1:]
|
||
if not argv or argv[0] in ("-h", "--help", "help"):
|
||
print(__doc__)
|
||
return 0
|
||
verb, rest = argv[0], argv[1:]
|
||
if verb == "list":
|
||
return cmd_list()
|
||
if verb == "names":
|
||
for n in R.names():
|
||
print(n)
|
||
return 0
|
||
if verb == "show":
|
||
if not rest:
|
||
print("用法:scripts/roster show <名字>", file=sys.stderr)
|
||
return 1
|
||
return cmd_show(rest[0])
|
||
if verb == "which":
|
||
if not rest:
|
||
print("用法:scripts/roster which <owner/repo>", file=sys.stderr)
|
||
return 1
|
||
return cmd_which(rest[0])
|
||
print("不認得的動詞「%s」。\n%s" % (verb, __doc__), file=sys.stderr)
|
||
return 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|