@aipper/aiws-spec 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/spec-contract.md +5 -4
- package/package.json +1 -1
- package/templates/workspace/.agents/skills/{aiws-change-archive → p-aiws-change-archive}/SKILL.md +3 -2
- package/templates/workspace/.agents/skills/{aiws-change-finish → p-aiws-change-finish}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-change-list → p-aiws-change-list}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-change-new → p-aiws-change-new}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-change-next → p-aiws-change-next}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-change-start → p-aiws-change-start}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-change-status → p-aiws-change-status}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-change-sync → p-aiws-change-sync}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-change-templates-init → p-aiws-change-templates-init}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-change-templates-which → p-aiws-change-templates-which}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-change-validate → p-aiws-change-validate}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-hooks-install → p-aiws-hooks-install}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-hooks-status → p-aiws-hooks-status}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-init → p-aiws-init}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-rollback → p-aiws-rollback}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-update → p-aiws-update}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/{aiws-validate → p-aiws-validate}/SKILL.md +2 -2
- package/templates/workspace/.agents/skills/p-tasks-plan/SKILL.md +37 -0
- package/templates/workspace/.agents/skills/ws-commit/SKILL.md +21 -6
- package/templates/workspace/.agents/skills/ws-deliver/SKILL.md +38 -9
- package/templates/workspace/.agents/skills/ws-dev/SKILL.md +61 -2
- package/templates/workspace/.agents/skills/ws-finish/SKILL.md +39 -25
- package/templates/workspace/.agents/skills/ws-handoff/SKILL.md +31 -0
- package/templates/workspace/.agents/skills/ws-plan/SKILL.md +32 -0
- package/templates/workspace/.agents/skills/ws-push/SKILL.md +17 -12
- package/templates/workspace/.claude/commands/{aiws-change-archive.md → p-aiws-change-archive.md} +3 -1
- package/templates/workspace/.claude/commands/{aiws-change-finish.md → p-aiws-change-finish.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-change-list.md → p-aiws-change-list.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-change-new.md → p-aiws-change-new.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-change-next.md → p-aiws-change-next.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-change-start.md → p-aiws-change-start.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-change-status.md → p-aiws-change-status.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-change-sync.md → p-aiws-change-sync.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-change-templates-init.md → p-aiws-change-templates-init.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-change-templates-which.md → p-aiws-change-templates-which.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-change-validate.md → p-aiws-change-validate.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-hooks-install.md → p-aiws-hooks-install.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-hooks-status.md → p-aiws-hooks-status.md} +2 -0
- package/templates/workspace/.claude/commands/{aiws-init.md → p-aiws-init.md} +2 -1
- package/templates/workspace/.claude/commands/{aiws-rollback.md → p-aiws-rollback.md} +2 -1
- package/templates/workspace/.claude/commands/{aiws-update.md → p-aiws-update.md} +2 -1
- package/templates/workspace/.claude/commands/{aiws-validate.md → p-aiws-validate.md} +2 -1
- package/templates/workspace/.claude/commands/ws-dev.md +4 -1
- package/templates/workspace/.claude/commands/ws-handoff.md +22 -0
- package/templates/workspace/.opencode/command/{aiws-change-archive.md → p-aiws-change-archive.md} +4 -2
- package/templates/workspace/.opencode/command/{aiws-change-finish.md → p-aiws-change-finish.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-change-list.md → p-aiws-change-list.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-change-new.md → p-aiws-change-new.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-change-next.md → p-aiws-change-next.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-change-start.md → p-aiws-change-start.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-change-status.md → p-aiws-change-status.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-change-sync.md → p-aiws-change-sync.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-change-templates-init.md → p-aiws-change-templates-init.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-change-templates-which.md → p-aiws-change-templates-which.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-change-validate.md → p-aiws-change-validate.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-hooks-install.md → p-aiws-hooks-install.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-hooks-status.md → p-aiws-hooks-status.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-init.md → p-aiws-init.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-rollback.md → p-aiws-rollback.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-update.md → p-aiws-update.md} +3 -1
- package/templates/workspace/.opencode/command/{aiws-validate.md → p-aiws-validate.md} +3 -1
- package/templates/workspace/.opencode/command/ws-commit.md +1 -1
- package/templates/workspace/.opencode/command/ws-dev.md +4 -1
- package/templates/workspace/.opencode/command/ws-handoff.md +25 -0
- package/templates/workspace/.opencode/command/ws-review.md +1 -1
- package/templates/workspace/AGENTS.md +7 -4
- package/templates/workspace/manifest.json +171 -103
- package/templates/workspace/tools/ws_change_check.py +99 -0
- package/templates/workspace/tools/ws_resolve_sub_target.sh +46 -0
- package/templates/workspace/tools/ws_tasks_plan.py +137 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Generate an update_plan JSON payload from changes/<id>/tasks.md checkbox tasks.
|
|
4
|
+
|
|
5
|
+
This script is intended to be used by the `p-tasks-plan` Codex skill.
|
|
6
|
+
It reads tasks.md only and does not modify it.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import json
|
|
13
|
+
import re
|
|
14
|
+
import sys
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
_TASK_RE = re.compile(r"^\s*[-*]\s+\[([ xX])\]\s+(.*\S)\s*$")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True)
|
|
23
|
+
class Task:
|
|
24
|
+
text: str
|
|
25
|
+
done: bool
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _read_tasks_md(path: Path) -> str:
|
|
29
|
+
if not path.exists():
|
|
30
|
+
raise FileNotFoundError(str(path))
|
|
31
|
+
return path.read_text(encoding="utf-8")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _extract_tasks(markdown: str) -> list[Task]:
|
|
35
|
+
tasks: list[Task] = []
|
|
36
|
+
in_code_block = False
|
|
37
|
+
for raw_line in markdown.splitlines():
|
|
38
|
+
line = raw_line.rstrip("\n")
|
|
39
|
+
if line.lstrip().startswith("```"):
|
|
40
|
+
in_code_block = not in_code_block
|
|
41
|
+
continue
|
|
42
|
+
if in_code_block:
|
|
43
|
+
continue
|
|
44
|
+
m = _TASK_RE.match(line)
|
|
45
|
+
if not m:
|
|
46
|
+
continue
|
|
47
|
+
mark = m.group(1)
|
|
48
|
+
text = m.group(2).strip()
|
|
49
|
+
if not text:
|
|
50
|
+
continue
|
|
51
|
+
tasks.append(Task(text=text, done=(mark.lower() == "x")))
|
|
52
|
+
return tasks
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _plan_statuses(tasks: list[Task]) -> list[str]:
|
|
56
|
+
first_todo_idx = next((i for i, t in enumerate(tasks) if not t.done), None)
|
|
57
|
+
statuses: list[str] = []
|
|
58
|
+
for i, t in enumerate(tasks):
|
|
59
|
+
if t.done:
|
|
60
|
+
statuses.append("completed")
|
|
61
|
+
elif first_todo_idx is not None and i == first_todo_idx:
|
|
62
|
+
statuses.append("in_progress")
|
|
63
|
+
else:
|
|
64
|
+
statuses.append("pending")
|
|
65
|
+
return statuses
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def cmd_status(args: argparse.Namespace) -> int:
|
|
69
|
+
path = Path(args.file).resolve()
|
|
70
|
+
try:
|
|
71
|
+
tasks = _extract_tasks(_read_tasks_md(path))
|
|
72
|
+
except FileNotFoundError:
|
|
73
|
+
print(f"tasks.md not found: {path}", file=sys.stderr)
|
|
74
|
+
return 2
|
|
75
|
+
|
|
76
|
+
if not tasks:
|
|
77
|
+
print(f"No checkbox tasks found in: {path}", file=sys.stderr)
|
|
78
|
+
return 2
|
|
79
|
+
|
|
80
|
+
total = len(tasks)
|
|
81
|
+
done = sum(1 for t in tasks if t.done)
|
|
82
|
+
first_todo_idx = next((i for i, t in enumerate(tasks) if not t.done), None)
|
|
83
|
+
suffix = f" (IN_PROGRESS: {first_todo_idx + 1})" if first_todo_idx is not None else ""
|
|
84
|
+
print(f"{done}/{total} DONE{suffix}")
|
|
85
|
+
return 0
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def cmd_plan(args: argparse.Namespace) -> int:
|
|
89
|
+
path = Path(args.file).resolve()
|
|
90
|
+
try:
|
|
91
|
+
tasks = _extract_tasks(_read_tasks_md(path))
|
|
92
|
+
except FileNotFoundError:
|
|
93
|
+
print(f"tasks.md not found: {path}", file=sys.stderr)
|
|
94
|
+
return 2
|
|
95
|
+
|
|
96
|
+
if not tasks:
|
|
97
|
+
print(f"No checkbox tasks found in: {path}", file=sys.stderr)
|
|
98
|
+
return 2
|
|
99
|
+
|
|
100
|
+
statuses = _plan_statuses(tasks)
|
|
101
|
+
if len(tasks) != len(statuses):
|
|
102
|
+
print("Internal error: tasks/statuses length mismatch", file=sys.stderr)
|
|
103
|
+
return 2
|
|
104
|
+
|
|
105
|
+
payload = {
|
|
106
|
+
"explanation": args.explanation or "",
|
|
107
|
+
"plan": [{"step": t.text, "status": s} for t, s in zip(tasks, statuses)],
|
|
108
|
+
}
|
|
109
|
+
json.dump(payload, sys.stdout, ensure_ascii=False, indent=2)
|
|
110
|
+
sys.stdout.write("\n")
|
|
111
|
+
return 0
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
115
|
+
p = argparse.ArgumentParser(prog="ws_tasks_plan.py")
|
|
116
|
+
sub = p.add_subparsers(dest="cmd", required=True)
|
|
117
|
+
|
|
118
|
+
p_status = sub.add_parser("status", help="Print progress summary from tasks.md")
|
|
119
|
+
p_status.add_argument("--file", required=True, help="Path to changes/<id>/tasks.md")
|
|
120
|
+
p_status.set_defaults(fn=cmd_status)
|
|
121
|
+
|
|
122
|
+
p_plan = sub.add_parser("plan", help="Generate update_plan JSON payload from tasks.md")
|
|
123
|
+
p_plan.add_argument("--file", required=True, help="Path to changes/<id>/tasks.md")
|
|
124
|
+
p_plan.add_argument("--explanation", default="", help="Explanation for update_plan payload")
|
|
125
|
+
p_plan.set_defaults(fn=cmd_plan)
|
|
126
|
+
|
|
127
|
+
return p
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def main(argv: list[str]) -> int:
|
|
131
|
+
parser = build_parser()
|
|
132
|
+
args = parser.parse_args(argv)
|
|
133
|
+
return int(args.fn(args))
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
if __name__ == "__main__":
|
|
137
|
+
raise SystemExit(main(sys.argv[1:]))
|