@warnyin/agents 0.9.0 → 0.10.0

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.
Files changed (78) hide show
  1. package/CHANGELOG.md +110 -99
  2. package/README.md +148 -148
  3. package/package.json +38 -38
  4. package/src/.claude/agents/warnyin-infra.md +13 -13
  5. package/src/.claude/agents/warnyin-qa.md +13 -13
  6. package/src/.claude/agents/warnyin-sa.md +13 -13
  7. package/src/.claude/agents/warnyin-security.md +13 -13
  8. package/src/.claude/agents/warnyin-tech-lead.md +13 -13
  9. package/src/.claude/commands/warnyin/build.md +30 -30
  10. package/src/.claude/commands/warnyin/design.md +26 -26
  11. package/src/.claude/commands/warnyin/discovery.md +17 -17
  12. package/src/.claude/commands/warnyin/explore.md +14 -14
  13. package/src/.claude/commands/warnyin/init.md +12 -12
  14. package/src/.claude/commands/warnyin/install-skill.md +14 -14
  15. package/src/.claude/commands/warnyin/next.md +17 -17
  16. package/src/.claude/commands/warnyin/ship.md +28 -28
  17. package/src/.claude/commands/warnyin/update-codemaps.md +12 -12
  18. package/src/.claude/commands/warnyin/verify.md +20 -20
  19. package/src/.claude/skills/explore/SKILL.md +8 -8
  20. package/src/.claude/skills/next/SKILL.md +8 -8
  21. package/src/.claude/skills/update-codemaps/SKILL.md +8 -8
  22. package/src/.warnyin/installer/templates/CLAUDE.md +29 -29
  23. package/src/.warnyin/template/docs/codemap/index.md +18 -18
  24. package/src/.warnyin/template/docs/features/[feature-name]/business.md +5 -5
  25. package/src/.warnyin/template/docs/features/[feature-name]/feature.md +5 -5
  26. package/src/.warnyin/template/docs/features/[feature-name]/spec.md +16 -16
  27. package/src/.warnyin/template/docs/infra.md +16 -16
  28. package/src/.warnyin/template/docs/project.md +18 -18
  29. package/src/.warnyin/template/docs/rule.md +7 -7
  30. package/src/.warnyin/template/docs/techstack/[component]/about.md +6 -6
  31. package/src/.warnyin/template/docs/techstack/[component]/rule.md +6 -6
  32. package/src/.warnyin/template/docs/techstack/[component]/standard.md +6 -6
  33. package/src/.warnyin/template/docs/techstack/[component]/structure.md +7 -7
  34. package/src/.warnyin/template/docs/techstack/[component]/test.md +7 -7
  35. package/src/.warnyin/template/docs/troubleshooting.md +32 -32
  36. package/src/.warnyin/template/stages/[topic]/build.md +58 -58
  37. package/src/.warnyin/template/stages/[topic]/business.md +21 -21
  38. package/src/.warnyin/template/stages/[topic]/design.md +57 -57
  39. package/src/.warnyin/template/stages/[topic]/discovery.md +69 -69
  40. package/src/.warnyin/template/stages/[topic]/proposal.md +43 -43
  41. package/src/.warnyin/template/stages/[topic]/research.md +49 -49
  42. package/src/.warnyin/template/stages/[topic]/ship.md +32 -32
  43. package/src/.warnyin/template/stages/[topic]/tasks/[task-name]/issue.md +19 -19
  44. package/src/.warnyin/template/stages/[topic]/tasks/[task-name]/rule.md +13 -13
  45. package/src/.warnyin/template/stages/[topic]/tasks/[task-name]/spec.md +36 -36
  46. package/src/.warnyin/template/stages/[topic]/tasks/[task-name]/standard.md +21 -21
  47. package/src/.warnyin/template/stages/[topic]/tasks/[task-name]/task.md +39 -39
  48. package/src/.warnyin/template/stages/[topic]/test.md +46 -46
  49. package/src/.warnyin/template/stages/[topic]/troubleshooting.md +34 -34
  50. package/src/.warnyin/template/stages/[topic]/verify.md +44 -44
  51. package/src/.warnyin/workflow/README.md +101 -100
  52. package/src/.warnyin/workflow/api-doc.md +93 -0
  53. package/src/.warnyin/workflow/codemap.md +91 -91
  54. package/src/.warnyin/workflow/contexts/README.md +49 -49
  55. package/src/.warnyin/workflow/contexts/build.md +25 -25
  56. package/src/.warnyin/workflow/contexts/research.md +25 -25
  57. package/src/.warnyin/workflow/contexts/review.md +25 -25
  58. package/src/.warnyin/workflow/explore.md +32 -32
  59. package/src/.warnyin/workflow/init.md +125 -125
  60. package/src/.warnyin/workflow/next.md +48 -48
  61. package/src/.warnyin/workflow/roles/README.md +47 -46
  62. package/src/.warnyin/workflow/roles/ba.md +25 -25
  63. package/src/.warnyin/workflow/roles/developer.md +30 -30
  64. package/src/.warnyin/workflow/roles/infra.md +24 -24
  65. package/src/.warnyin/workflow/roles/po.md +28 -28
  66. package/src/.warnyin/workflow/roles/qa.md +35 -35
  67. package/src/.warnyin/workflow/roles/sa.md +28 -28
  68. package/src/.warnyin/workflow/roles/security.md +39 -39
  69. package/src/.warnyin/workflow/roles/tech-lead.md +28 -28
  70. package/src/.warnyin/workflow/scripts/build-wave.mjs +125 -109
  71. package/src/.warnyin/workflow/scripts/validate-topic.mjs +378 -378
  72. package/src/.warnyin/workflow/stages/build.md +98 -97
  73. package/src/.warnyin/workflow/stages/design.md +122 -119
  74. package/src/.warnyin/workflow/stages/discovery.md +78 -78
  75. package/src/.warnyin/workflow/stages/ship.md +92 -90
  76. package/src/.warnyin/workflow/stages/verify.md +80 -77
  77. package/src/AGENTS.md +48 -48
  78. package/src/bin/cli.mjs +193 -193
@@ -1,109 +1,125 @@
1
- // build-wave — fan-out หนึ่ง sub-agent ต่อหนึ่ง task ใน "หนึ่ง wave" (task ที่ independent กัน)
2
- // main loop (BUILD command) เรียก script นี้ทีละ wave ตาม dependency แล้ว integrate ระหว่าง wave
3
- //
4
- // args = {
5
- // slug: string, // ชื่อ topic เช่น "billing-redesign"
6
- // tasks: string[], // ชื่อ task ใน wave นี้ (โฟลเดอร์ docs/stages/<slug>/tasks/<task>)
7
- // isolate?: boolean, // true = worktree ต่อ task (ดีฟอลต์), false = shared tree (sequential)
8
- // }
9
-
10
- export const meta = {
11
- name: 'build-wave',
12
- description: 'BUILD: fan-out sub-agent ต่อ task ใน wave เดียว — implement + test/lint + commit แล้วรายงานผล',
13
- phases: [{ title: 'Build wave', detail: 'parallel agent, หนึ่งตัวต่อหนึ่ง task (worktree isolation)' }],
14
- }
15
-
16
- // บาง harness ส่ง args ของ Workflow เป็น string (JSON text) ไม่ใช่ object — รับทั้งสองแบบ
17
- const A = typeof args === 'string' ? JSON.parse(args) : (args || {})
18
- const slug = A.slug
19
- const tasks = A.tasks || []
20
- const isolate = !(A.isolate === false)
21
-
22
- if (!slug || tasks.length === 0) {
23
- log('ไม่มี slug หรือ tasks — ไม่มีอะไรให้ build')
24
- return { slug: slug || null, results: [], failed: [] }
25
- }
26
-
27
- phase('Build wave')
28
- log(`Build ${tasks.length} task ของ "${slug}"${isolate ? ' · worktree isolation' : ' · shared tree'}`)
29
-
30
- const RESULT_SCHEMA = {
31
- type: 'object',
32
- additionalProperties: false,
33
- required: ['task', 'status', 'summary'],
34
- properties: {
35
- task: { type: 'string', description: 'ชื่อ task' },
36
- status: { enum: ['passed', 'failed'], description: 'passed ก็ต่อเมื่อ test/lint เขียวจริง' },
37
- summary: { type: 'string', description: 'สรุปสั้นๆ ว่าทำอะไร' },
38
- branch: { type: 'string', description: 'ชื่อ git branch ของ worktree (ถ้า isolate) ให้ main loop merge' },
39
- filesChanged: { type: 'array', items: { type: 'string' } },
40
- testResult: { type: 'string', description: 'ผล test-flow + build/lint' },
41
- notes: { type: 'string', description: 'conflict/ข้อควรระวัง/ rule ใหม่ที่ note ไว้' },
42
- troubleshooting: {
43
- type: 'array',
44
- description: 'ปัญหายาก/เจอซ้ำที่แก้สำเร็จ — main loop จะเขียนรวมลง topic troubleshooting.md',
45
- items: {
46
- type: 'object',
47
- additionalProperties: false,
48
- required: ['title', 'rootCause', 'solution'],
49
- properties: {
50
- title: { type: 'string' },
51
- symptom: { type: 'string', description: 'อาการ/error message' },
52
- rootCause: { type: 'string' },
53
- solution: { type: 'string' },
54
- prevention: { type: 'string', description: 'วิธีป้องกันไม่ให้เกิดซ้ำ' },
55
- },
56
- },
57
- },
58
- },
59
- }
60
-
61
- function prompt(task) {
62
- const dir = `docs/stages/${slug}/tasks/${task}`
63
- const lines = [
64
- `คุณคือ build sub-agent ของ task "${task}" (vertical slice) ทำตาม playbook .warnyin/workflow/stages/build.md`,
65
- ``,
66
- `1. อ่านให้ครบก่อนเขียนโค้ด:`,
67
- ` - .warnyin/workflow/roles/developer.md (role card: lens + checklist ก่อนส่งงาน — ทำตามทุกข้อ)`,
68
- ` - ${dir}/task.md (เป้าหมาย + sub-tasks + dependency + acceptance)`,
69
- ` - ${dir}/spec.md (API/UXUI/data-flow/user-flow/persona/test-flow)`,
70
- ` - ${dir}/standard.md (pattern โค้ด, shared component reuse ห้ามเขียนซ้ำ)`,
71
- ` - ${dir}/rule.md (กฎที่ต้อง follow)`,
72
- ` - ภาพรวม: docs/stages/${slug}/design.md, proposal.md`,
73
- ` - rule/standard กลางที่อ้างถึงใน docs/techstack/<component>/`,
74
- `2. Implement ให้ครบทุก sub-task แบบ vertical slice (end-to-end) ทำตาม standard.md + rule.md เคร่งครัด`,
75
- `3. รัน test-flow ใน spec.md + build/lint ของ component นั้น`,
76
- `4. ถ้าเจอ error/ติดปัญหา อ่าน docs/troubleshooting.md ก่อน เผื่อเคยแก้แล้ว`,
77
- `5. รายงาน status=passed เฉพาะเมื่อ test/build เขียวจริง; ถ้าแก้ไม่ได้ status=failed พร้อมเหตุผล`,
78
- ` ห้ามรายงานผ่านทั้งที่ยังแดง`,
79
- `6. ห้ามแก้ไฟล์ rule/standard กลางใน docs/ (rule ใหม่ note ไว้ใน ${dir}/rule.md อยู่แล้ว รอ SHIP)`,
80
- `7. อัปเดตสถานะ + acceptance ที่ผ่านใน ${dir}/task.md`,
81
- `8. ปัญหาที่ "ยาก/เจอซ้ำ" และแก้สำเร็จ ใส่ในฟิลด์ troubleshooting (main loop จะรวมลง topic troubleshooting.md)`,
82
- ]
83
- if (isolate) {
84
- lines.push(
85
- `9. คุณอยู่ใน git worktree แยก: เมื่อเสร็จและเขียวแล้ว ให้ commit งาน (git add -A && git commit -m "build(${task}): ...")`,
86
- ` แล้วรายงานชื่อ branch (git rev-parse --abbrev-ref HEAD) ในฟิลด์ branch เพื่อให้ main loop merge`,
87
- )
88
- } else {
89
- lines.push(`9. (shared tree) อย่า commit เอง main loop จะ commit ให้หลังตรวจ`)
90
- }
91
- lines.push(``, `คืนผลตาม schema.`)
92
- return lines.join('\n')
93
- }
94
-
95
- const results = await parallel(
96
- tasks.map((task) => () =>
97
- agent(prompt(task), isolate
98
- ? { label: `build:${task}`, schema: RESULT_SCHEMA, isolation: 'worktree' }
99
- : { label: `build:${task}`, schema: RESULT_SCHEMA })
100
- )
101
- )
102
-
103
- const clean = results.filter(Boolean)
104
- const failed = clean.filter((r) => r.status === 'failed').map((r) => r.task)
105
- const skipped = tasks.filter((t) => !clean.some((r) => r.task === t))
106
-
107
- log(`เสร็จ ${clean.length}/${tasks.length} · ผ่าน ${clean.length - failed.length} · ล้ม ${failed.length}${skipped.length ? ` · ข้าม ${skipped.length}` : ''}`)
108
-
109
- return { slug, results: clean, failed, skipped }
1
+ // build-wave — fan-out หนึ่ง sub-agent ต่อหนึ่ง task ใน "หนึ่ง wave" (task ที่ independent กัน)
2
+ // main loop (BUILD command) เรียก script นี้ทีละ wave ตาม dependency แล้ว integrate ระหว่าง wave
3
+ //
4
+ // args = {
5
+ // slug: string, // ชื่อ topic เช่น "billing-redesign"
6
+ // tasks: string[], // ชื่อ task ใน wave นี้ (โฟลเดอร์ docs/stages/<slug>/tasks/<task>)
7
+ // isolate?: boolean, // true = worktree ต่อ task (ดีฟอลต์), false = shared tree (sequential)
8
+ // baseRef?: string, // ชื่อ build branch เช่น "build/my-topic"; ไม่ส่ง = ไม่ sync (backward compat)
9
+ // }
10
+
11
+ export const meta = {
12
+ name: 'build-wave',
13
+ description: 'BUILD: fan-out sub-agent ต่อ task ใน wave เดียว implement + test/lint + commit แล้วรายงานผล',
14
+ phases: [{ title: 'Build wave', detail: 'parallel agent, หนึ่งตัวต่อหนึ่ง task (worktree isolation)' }],
15
+ }
16
+
17
+ // บาง harness ส่ง args ของ Workflow เป็น string (JSON text) ไม่ใช่ object รับทั้งสองแบบ
18
+ const A = typeof args === 'string' ? JSON.parse(args) : (args || {})
19
+ const slug = A.slug
20
+ const tasks = A.tasks || []
21
+ const isolate = !(A.isolate === false)
22
+ const baseRef = A.baseRef || null // ชื่อ build branch เช่น "build/my-topic"; ไม่ส่ง = ไม่ sync (backward compat)
23
+
24
+ if (!slug || tasks.length === 0) {
25
+ log('ไม่มี slug หรือ tasks — ไม่มีอะไรให้ build')
26
+ return { slug: slug || null, results: [], failed: [] }
27
+ }
28
+
29
+ phase('Build wave')
30
+ log(`Build ${tasks.length} task ของ "${slug}"${isolate ? ' · worktree isolation' : ' · shared tree'}`)
31
+
32
+ const RESULT_SCHEMA = {
33
+ type: 'object',
34
+ additionalProperties: false,
35
+ required: ['task', 'status', 'summary'],
36
+ properties: {
37
+ task: { type: 'string', description: 'ชื่อ task' },
38
+ status: { enum: ['passed', 'failed'], description: 'passed ก็ต่อเมื่อ test/lint เขียวจริง' },
39
+ summary: { type: 'string', description: 'สรุปสั้นๆ ว่าทำอะไร' },
40
+ branch: { type: 'string', description: 'ชื่อ git branch ของ worktree (ถ้า isolate) ให้ main loop merge' },
41
+ filesChanged: { type: 'array', items: { type: 'string' } },
42
+ testResult: { type: 'string', description: 'ผล test-flow + build/lint' },
43
+ notes: { type: 'string', description: 'conflict/ข้อควรระวัง/ rule ใหม่ที่ note ไว้' },
44
+ troubleshooting: {
45
+ type: 'array',
46
+ description: 'ปัญหายาก/เจอซ้ำที่แก้สำเร็จ — main loop จะเขียนรวมลง topic troubleshooting.md',
47
+ items: {
48
+ type: 'object',
49
+ additionalProperties: false,
50
+ required: ['title', 'rootCause', 'solution'],
51
+ properties: {
52
+ title: { type: 'string' },
53
+ symptom: { type: 'string', description: 'อาการ/error message' },
54
+ rootCause: { type: 'string' },
55
+ solution: { type: 'string' },
56
+ prevention: { type: 'string', description: 'วิธีป้องกันไม่ให้เกิดซ้ำ' },
57
+ },
58
+ },
59
+ },
60
+ },
61
+ }
62
+
63
+ function prompt(task) {
64
+ const dir = `docs/stages/${slug}/tasks/${task}`
65
+ const lines = [
66
+ `คุณคือ build sub-agent ของ task "${task}" (vertical slice) ทำตาม playbook .warnyin/workflow/stages/build.md`,
67
+ ``,
68
+ `1. อ่านให้ครบก่อนเขียนโค้ด:`,
69
+ ` - .warnyin/workflow/roles/developer.md (role card: lens + checklist ก่อนส่งงาน — ทำตามทุกข้อ)`,
70
+ ` - ${dir}/task.md (เป้าหมาย + sub-tasks + dependency + acceptance)`,
71
+ ` - ${dir}/spec.md (API/UXUI/data-flow/user-flow/persona/test-flow)`,
72
+ ` - ${dir}/standard.md (pattern โค้ด, shared component — reuse ห้ามเขียนซ้ำ)`,
73
+ ` - ${dir}/rule.md (กฎที่ต้อง follow)`,
74
+ ` - ภาพรวม: docs/stages/${slug}/design.md, proposal.md`,
75
+ ` - rule/standard กลางที่อ้างถึงใน docs/techstack/<component>/`,
76
+ `2. Implement ให้ครบทุก sub-task แบบ vertical slice (end-to-end) ทำตาม standard.md + rule.md เคร่งครัด`,
77
+ `3. รัน test-flow ใน spec.md + build/lint ของ component นั้น`,
78
+ `4. ถ้าเจอ error/ติดปัญหา → อ่าน docs/troubleshooting.md ก่อน เผื่อเคยแก้แล้ว`,
79
+ `5. รายงาน status=passed เฉพาะเมื่อ test/build เขียวจริง; ถ้าแก้ไม่ได้ status=failed พร้อมเหตุผล`,
80
+ ` ห้ามรายงานผ่านทั้งที่ยังแดง`,
81
+ `6. ห้ามแก้ไฟล์ rule/standard กลางใน docs/ (rule ใหม่ note ไว้ใน ${dir}/rule.md อยู่แล้ว รอ SHIP)`,
82
+ `7. อัปเดตสถานะ + acceptance ที่ผ่านใน ${dir}/task.md`,
83
+ `8. ปัญหาที่ "ยาก/เจอซ้ำ" และแก้สำเร็จ → ใส่ในฟิลด์ troubleshooting (main loop จะรวมลง topic troubleshooting.md)`,
84
+ ]
85
+ // worktree fork จาก main (คุมไม่ได้) ให้ agent sync build branch เข้า worktree เองก่อนทำงาน
86
+ // แทรกเป็น step "0." ก่อน "1. อ่านให้ครบ" เฉพาะ isolate && baseRef (ไม่ renumber step 1-9; !baseRef = พฤติกรรมเดิม)
87
+ if (isolate && baseRef) {
88
+ lines.splice(2, 0,
89
+ `0. **★ Sync build branch เข้า worktree ก่อน (ทำก่อน Read ไฟล์ใดๆ):** รัน`,
90
+ ` \`git merge ${baseRef} --no-edit || (git merge --abort; <รายงาน failed>)\``,
91
+ ` (worktree fork จาก main — ต้อง merge build branch เพื่อให้เห็น docs/stages/${slug}/ + output ของ wave ก่อนหน้า)`,
92
+ ` - ปกติเป็น fast-forward (main มักเป็น ancestor ของ build branch); ถ้าเป็น 3-way แล้ว conflict → **abort + รายงาน failed** (ห้ามทิ้ง worktree ค้าง MERGE state — step commit ท้ายจะพัง)`,
93
+ ` - ถ้าล้มด้วย lock error ชั่วคราว (transient \`index.lock\`/\`packed-refs\`) → **retry 1 ครั้ง** ก่อนรายงาน failed`,
94
+ ` - **★ hard-stop กัน improvise (panel B2):** หลัง merge ถ้าไฟล์ \`${dir}/task.md\` **ยังไม่ปรากฏ** → **STOP รายงาน failed ทันที ห้าม improvise/git reset เอง** (กันวนรอย KB#14)`,
95
+ ` - บันทึกผล merge ลงฟิลด์ \`notes\` (เช่น "merged ${baseRef}: fast-forward to <sha>") เพื่อ main loop verify ว่า sync เกิดจริง (Infra-S5)`,
96
+ ``,
97
+ )
98
+ }
99
+ if (isolate) {
100
+ lines.push(
101
+ `9. คุณอยู่ใน git worktree แยก: เมื่อเสร็จและเขียวแล้ว ให้ commit งาน (git add -A && git commit -m "build(${task}): ...")`,
102
+ ` แล้วรายงานชื่อ branch (git rev-parse --abbrev-ref HEAD) ในฟิลด์ branch เพื่อให้ main loop merge`,
103
+ )
104
+ } else {
105
+ lines.push(`9. (shared tree) อย่า commit เอง main loop จะ commit ให้หลังตรวจ`)
106
+ }
107
+ lines.push(``, `คืนผลตาม schema.`)
108
+ return lines.join('\n')
109
+ }
110
+
111
+ const results = await parallel(
112
+ tasks.map((task) => () =>
113
+ agent(prompt(task), isolate
114
+ ? { label: `build:${task}`, schema: RESULT_SCHEMA, isolation: 'worktree' }
115
+ : { label: `build:${task}`, schema: RESULT_SCHEMA })
116
+ )
117
+ )
118
+
119
+ const clean = results.filter(Boolean)
120
+ const failed = clean.filter((r) => r.status === 'failed').map((r) => r.task)
121
+ const skipped = tasks.filter((t) => !clean.some((r) => r.task === t))
122
+
123
+ log(`เสร็จ ${clean.length}/${tasks.length} · ผ่าน ${clean.length - failed.length} · ล้ม ${failed.length}${skipped.length ? ` · ข้าม ${skipped.length}` : ''}`)
124
+
125
+ return { slug, results: clean, failed, skipped }