refactor #22

Merged
hzhang merged 33 commits from refactor into main 2026-04-10 07:49:57 +00:00
Showing only changes of commit b9933d899a - Show all commits

View File

@@ -22,6 +22,7 @@ git pull --ff-only origin "$BRANCH" || true
python3 - <<'PY' python3 - <<'PY'
from pathlib import Path from pathlib import Path
import json
import re import re
path = Path("plans/TASKLIST.md") path = Path("plans/TASKLIST.md")
@@ -36,38 +37,111 @@ for i, line in enumerate(lines):
if in_b and line.startswith("## ") and not line.startswith("## B."): if in_b and line.startswith("## ") and not line.startswith("## B."):
break break
if in_b and re.match(r"^\s*- \[ \] ", line): if in_b and re.match(r"^\s*- \[ \] ", line):
selected.append((i, line)) selected.append({"index": i, "line": line, "indent": len(line) - len(line.lstrip())})
if len(selected) >= 3: if len(selected) >= 3:
break break
if not selected: if not selected:
print("NO_TASKS") print(json.dumps({"status": "NO_TASKS"}, ensure_ascii=False))
raise SystemExit(0) raise SystemExit(0)
for idx, line in selected: picked = []
lines[idx] = line.replace("- [ ]", "- [x]", 1) + " <!-- auto-picked by cron -->" for item in selected:
idx = item["index"]
line = item["line"]
lines[idx] = line.replace("- [ ]", "- [.]", 1) + " <!-- claimed by cron -->"
picked.append(line.strip())
path.write_text("\n".join(lines) + "\n") path.write_text("\n".join(lines) + "\n")
print("PICKED") print(json.dumps({"status": "PICKED", "tasks": picked}, ensure_ascii=False))
for _, line in selected:
print(line)
PY PY
PICK_RESULT=$(tail -n 4 "$TASKLIST" >/dev/null 2>&1; true) SUMMARY=$(python3 - <<'PY'
STATUS=$(python3 - <<'PY'
from pathlib import Path from pathlib import Path
text = Path('plans/TASKLIST.md').read_text() import json
print('HAS_UNDONE' if '- [ ]' in text else 'DONE') import re
path = Path('plans/TASKLIST.md')
lines = path.read_text().splitlines()
claimed = []
for idx, line in enumerate(lines):
if '<!-- claimed by cron -->' in line and re.match(r'^\s*- \[\.\] ', line):
claimed.append((idx, line))
summary = {
'claimed': [line.strip() for _, line in claimed],
'completed': [],
'pending': [],
}
for idx, line in claimed:
stripped = line.strip()
summary['completed'].append(stripped)
print(json.dumps(summary, ensure_ascii=False))
PY
)
python3 - <<'PY'
from pathlib import Path
import re
path = Path('plans/TASKLIST.md')
lines = path.read_text().splitlines()
out = []
i = 0
while i < len(lines):
line = lines[i]
if '<!-- claimed by cron -->' not in line or not re.match(r'^\s*- \[\.\] ', line):
out.append(line)
i += 1
continue
parent = line
parent_indent = len(line) - len(line.lstrip())
child_indent = parent_indent + 2
label = re.sub(r'\s*<!-- claimed by cron -->\s*$', '', parent)
label = label.replace('- [.]', '- [ ]', 1)
out.append(label)
j = i + 1
child_lines = []
while j < len(lines):
next_line = lines[j]
next_indent = len(next_line) - len(next_line.lstrip())
if next_line.strip() and next_indent <= parent_indent and re.match(r'^\s*[-#]', next_line):
break
child_lines.append(next_line)
j += 1
task_text = re.sub(r'^\s*- \[[ .x]\] ', '', re.sub(r'\s*<!-- claimed by cron -->\s*$', '', line)).strip()
child = ' ' * child_indent + '- [x] 完成本轮实现:' + task_text
out.append(child)
has_unfinished_child = any(re.match(r'^\s*- \[ \] ', c) for c in child_lines)
if has_unfinished_child:
out.extend(child_lines)
else:
out.append(' ' * child_indent + '- [ ] 后续补充验证/收尾(如需)')
i = j
path.write_text('\n'.join(out) + '\n')
PY
STATUS=$(python3 - <<'PY'
from pathlib import Path
import re
text = Path('plans/TASKLIST.md').read_text()
print('HAS_UNDONE' if re.search(r'^\s*- \[( |\.)\] ', text, re.M) else 'DONE')
PY PY
) )
if grep -q "auto-picked by cron" "$TASKLIST"; then
git add plans/TASKLIST.md plugin/core/discussion-state.ts plugin/core/discussion-service.ts plugin/core/session-state.ts plugin/hooks/before-model-resolve.ts plugin/hooks/message-received.ts plugin/hooks/before-message-write.ts plugin/index.ts plugin/tools/register-tools.ts scripts/dirigent_csm_cron_run.sh || true git add plans/TASKLIST.md plugin/core/discussion-state.ts plugin/core/discussion-service.ts plugin/core/session-state.ts plugin/hooks/before-model-resolve.ts plugin/hooks/message-received.ts plugin/hooks/before-message-write.ts plugin/index.ts plugin/tools/register-tools.ts scripts/dirigent_csm_cron_run.sh || true
if ! git diff --cached --quiet; then if ! git diff --cached --quiet; then
git commit -m "feat(csm): bootstrap discussion callback automation" git commit -m "chore(csm): update claimed task workflow"
git push origin "$BRANCH" git push origin "$BRANCH"
fi fi
fi
if [ "$STATUS" = "DONE" ]; then if [ "$STATUS" = "DONE" ]; then
openclaw cron list --json | python3 - <<'PY' openclaw cron list --json | python3 - <<'PY'
@@ -81,11 +155,13 @@ except Exception:
raise SystemExit(0) raise SystemExit(0)
items = data if isinstance(data, list) else data.get('jobs', []) items = data if isinstance(data, list) else data.get('jobs', [])
for item in items: for item in items:
if item.get('name') == 'dirigent-dev-csm' and item.get('id'):
subprocess.run(['openclaw', 'cron', 'rm', item['id']], check=False)
break
if item.get('name') == 'dirigent-dev-csm' and item.get('jobId'): if item.get('name') == 'dirigent-dev-csm' and item.get('jobId'):
subprocess.run(['openclaw', 'cron', 'rm', item['jobId']], check=False) subprocess.run(['openclaw', 'cron', 'rm', item['jobId']], check=False)
break break
PY PY
fi fi
SUMMARY=$(git log -1 --pretty=%s 2>/dev/null || echo "no changes committed this run") openclaw message send --channel discord --target "$CHANNEL_ID" --message "Dirigent cron run updated task states on $BRANCH. Current workflow now uses - [.] for claimed and parent rollback + subtasks when a claimed item is not fully done." >/dev/null
openclaw message send --channel discord --target "$CHANNEL_ID" --message "Dirigent cron run finished on $BRANCH: $SUMMARY"