makdoong2-team 1.3.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 (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +193 -0
  3. package/agents/makdoong2-analyzer.md +135 -0
  4. package/agents/makdoong2-engineer.md +165 -0
  5. package/agents/makdoong2-planner.md +267 -0
  6. package/agents/makdoong2-publisher.md +481 -0
  7. package/agents/makdoong2-team-leader.md +249 -0
  8. package/agents/makdoong2-verifier.md +353 -0
  9. package/assets/makdoong2-team.default.json +46 -0
  10. package/assets/makdoong2-team.schema.json +357 -0
  11. package/bin/cli.js +404 -0
  12. package/dist/agent-stage-config.d.ts +15 -0
  13. package/dist/agent-stage-config.js +119 -0
  14. package/dist/config.d.ts +79 -0
  15. package/dist/config.js +96 -0
  16. package/dist/logger.d.ts +14 -0
  17. package/dist/logger.js +131 -0
  18. package/dist/mcp-secret-injector.d.ts +56 -0
  19. package/dist/mcp-secret-injector.js +89 -0
  20. package/dist/model-chain-cli.d.ts +1 -0
  21. package/dist/model-chain-cli.js +21 -0
  22. package/dist/model-fallback-policy.d.ts +69 -0
  23. package/dist/model-fallback-policy.js +211 -0
  24. package/dist/opencode-plugin.d.ts +8 -0
  25. package/dist/opencode-plugin.js +2457 -0
  26. package/dist/poll-sub-session.d.ts +139 -0
  27. package/dist/poll-sub-session.js +494 -0
  28. package/dist/redact-secrets.d.ts +3 -0
  29. package/dist/redact-secrets.js +68 -0
  30. package/dist/session-index.d.ts +11 -0
  31. package/dist/session-index.js +71 -0
  32. package/dist/skill-mcp-registry.d.ts +59 -0
  33. package/dist/skill-mcp-registry.js +178 -0
  34. package/dist/stall-escalation.d.ts +1 -0
  35. package/dist/stall-escalation.js +22 -0
  36. package/dist/tmux-monitor.d.ts +193 -0
  37. package/dist/tmux-monitor.js +694 -0
  38. package/dist/verdict-hash.d.ts +1 -0
  39. package/dist/verdict-hash.js +62 -0
  40. package/gates/stage-analysis-verify.sh +84 -0
  41. package/gates/stage2-requirements-verify.sh +13 -0
  42. package/gates/stage3-scope-verify.sh +45 -0
  43. package/gates/stage4-dev-post-verify.sh +64 -0
  44. package/gates/stage4-dev-verify.sh +36 -0
  45. package/gates/stage5-coverage-verify.sh +36 -0
  46. package/gates/stage5-test-verify.sh +24 -0
  47. package/gates/stage6-commit-verify.sh +41 -0
  48. package/gates/stage6-post-commit-verify.sh +131 -0
  49. package/gates/stage7-post-pr-verify.sh +53 -0
  50. package/gates/stage7-pr-verify.sh +48 -0
  51. package/gates/stage8-post-review-verify.sh +84 -0
  52. package/gates/stage8-review-verify.sh +45 -0
  53. package/gates/verify.sh +44 -0
  54. package/opencode.json.example +40 -0
  55. package/package.json +84 -0
  56. package/postinstall.mjs +56 -0
  57. package/references/commit-convention.md +130 -0
  58. package/references/jira-issue-templates.md +203 -0
  59. package/references/pr-template.md +381 -0
  60. package/scripts/config.sh +46 -0
  61. package/scripts/coverage-record.sh +67 -0
  62. package/scripts/gate-policy-test.sh +152 -0
  63. package/scripts/install-lib.mjs +1029 -0
  64. package/scripts/lint-agent-prompts.sh +74 -0
  65. package/scripts/log-event.sh +44 -0
  66. package/scripts/model-policy.mjs +183 -0
  67. package/scripts/publish-if-changed.sh +207 -0
  68. package/scripts/release.sh +276 -0
  69. package/scripts/rollback-commits.sh +35 -0
  70. package/scripts/smoke-test.mjs +194 -0
  71. package/scripts/state.sh +192 -0
  72. package/scripts/test-postinstall.mjs +141 -0
  73. package/scripts/with-fallback.sh +56 -0
  74. package/scripts/wt-sync-ignored.sh +193 -0
  75. package/skills/_lib/load-secret.sh +149 -0
  76. package/skills/bamboo-ci/SKILL.md +81 -0
  77. package/skills/bamboo-ci/run-bamboo.sh +23 -0
  78. package/skills/bitbucket-research/SKILL.md +87 -0
  79. package/skills/bitbucket-research/run-repos.sh +23 -0
  80. package/skills/confluence-research/SKILL.md +75 -0
  81. package/skills/confluence-research/run-docs.sh +23 -0
  82. package/skills/github-oss-research/SKILL.md +59 -0
  83. package/skills/jira-research/SKILL.md +75 -0
  84. package/skills/jira-research/run-works.sh +23 -0
  85. package/src/hooks/guard-bash.sh +67 -0
  86. package/src/hooks/session-start.sh +96 -0
  87. package/src/hooks/sync-state.sh +47 -0
  88. package/stages/01-jira.md +43 -0
  89. package/stages/01-planning.md +229 -0
  90. package/stages/02-requirements.md +298 -0
  91. package/stages/03-scope.md +81 -0
  92. package/stages/04-analysis.md +281 -0
  93. package/stages/05-worktree-dev.md +124 -0
  94. package/stages/06-test.md +161 -0
  95. package/stages/07-commit.md +229 -0
  96. package/stages/08-pr.md +177 -0
  97. package/stages/09-review-comments.md +277 -0
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env bash
2
+ # coverage-record.sh <issue> <pct> [attempt]
3
+ #
4
+ # makdoong2-team.json 의 coverage.threshold 를 읽어 pct 와 숫자 비교 후
5
+ # state.json 에 pass/fail 을 결정론적으로 기록한다.
6
+ #
7
+ # LLM 이 임계값을 해석하거나 판단하지 않도록 비교 로직을 shell 로 위임.
8
+ # engineer 는 커버리지 숫자만 추출해서 이 스크립트에 넘기면 된다.
9
+ #
10
+ # 사용:
11
+ # bash <SCRIPTS_DIR>/coverage-record.sh <이슈키> <pct> [attempt]
12
+ #
13
+ # 인수:
14
+ # <이슈키> — 예: PROJ-12345
15
+ # <pct> — 측정된 커버리지 퍼센트 (정수 또는 소수, 예: 87 / 87.3)
16
+ # [attempt] — 라운드 번호. 미지정 시 state.json 의 기존 coverage_attempt+1 로
17
+ # 자동 증가한다 (초회 호출은 1). engineer 가 3회 재시도 흐름에서
18
+ # 라운드를 수동으로 관리하지 않도록 하는 안전장치.
19
+ #
20
+ # 종료코드:
21
+ # 0 → pass (pct >= threshold)
22
+ # 1 → fail (pct < threshold)
23
+ #
24
+ # 의존: awk, jq (config.sh 경유), state.sh
25
+ set -euo pipefail
26
+
27
+ HERE="$(cd "$(dirname "$0")" && pwd)"
28
+
29
+ ISSUE="${1:?usage: coverage-record.sh <issue> <pct> [attempt]}"
30
+ PCT="${2:?usage: coverage-record.sh <issue> <pct> [attempt]}"
31
+
32
+ if [[ $# -ge 3 && -n "$3" ]]; then
33
+ ATTEMPT="$3"
34
+ else
35
+ PREV_ATTEMPT="$("$HERE/state.sh" get "$ISSUE" \
36
+ '.stages."2_implementation".substages."test".coverage_attempt' 2>/dev/null || echo "null")"
37
+ case "$PREV_ATTEMPT" in
38
+ ''|null|None) ATTEMPT=1 ;;
39
+ *)
40
+ if [[ "$PREV_ATTEMPT" =~ ^[0-9]+$ ]]; then
41
+ ATTEMPT=$((PREV_ATTEMPT + 1))
42
+ else
43
+ ATTEMPT=1
44
+ fi
45
+ ;;
46
+ esac
47
+ fi
48
+
49
+ THRESHOLD="$("$HERE/config.sh" get coverage.threshold 95)"
50
+
51
+ "$HERE/state.sh" set "$ISSUE" \
52
+ '.stages."2_implementation".substages."test".coverage_pct' "$PCT"
53
+ "$HERE/state.sh" set "$ISSUE" \
54
+ '.stages."2_implementation".substages."test".coverage_attempt' "$ATTEMPT"
55
+
56
+ # awk: shell 산술은 정수 전용이므로 소수점 비교는 awk 에 위임
57
+ if awk "BEGIN{exit !($PCT + 0 >= $THRESHOLD + 0)}"; then
58
+ "$HERE/state.sh" set "$ISSUE" \
59
+ '.stages."2_implementation".substages."test".coverage' '"pass"'
60
+ echo "COVERAGE PASS: ${PCT}% >= ${THRESHOLD}% (라운드 ${ATTEMPT})"
61
+ exit 0
62
+ else
63
+ "$HERE/state.sh" set "$ISSUE" \
64
+ '.stages."2_implementation".substages."test".coverage' '"fail"'
65
+ echo "COVERAGE FAIL: ${PCT}% < ${THRESHOLD}% (라운드 ${ATTEMPT})"
66
+ exit 1
67
+ fi
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env bash
2
+ # gate-policy-test.sh — 작업 범주화(.policy) 기반 조건부 auto-approve 게이트 단위 테스트.
3
+ #
4
+ # 2단계에서 결정한 `.policy.auto_approve.<stage>` 마커가 stage3/4/6/8 진입 게이트의
5
+ # 사람-승인 분기를 올바르게 제어하는지 임시 git repo + state.json 픽스처로 검증한다.
6
+ # - minor (기본) → 모든 게이트 무인 통과
7
+ # - major (기본) → 모든 게이트 무인 통과 (category 는 위험도 라벨/opt-in 훅용)
8
+ # - HITL opt-in (auto_approve="false") → 해당 substage 만 변경 보고서 + 승인 요구
9
+ # - 구형 state (.policy 미설정) → 기존 사람-승인 동작 보존 (backward-compat)
10
+ #
11
+ # 의존: jq, git, bash. 실행: bash scripts/gate-policy-test.sh (exit 0=all pass / 1=fail)
12
+ set -uo pipefail
13
+
14
+ REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
15
+ GATES="$REPO_ROOT/gates"
16
+ ISSUE="TEST-1"
17
+
18
+ pass=0; fail=0
19
+
20
+ TMP="$(mktemp -d)"
21
+ cleanup(){ rm -rf "$TMP"; }
22
+ trap cleanup EXIT
23
+
24
+ git init -q "$TMP"
25
+ ROOT="$(cd "$TMP" && git rev-parse --show-toplevel)"
26
+ SDIR="$ROOT/.makdoong2-team/$ISSUE"
27
+ mkdir -p "$SDIR"
28
+ STATE="$SDIR/state.json"
29
+ REPORT="$SDIR/change-report.md"
30
+
31
+ # 격리된 설정 디렉토리 — config.sh(coverage.threshold)가 결정론적으로 읽도록 XDG를 고정.
32
+ XDGHOME="$TMP/xdg"; mkdir -p "$XDGHOME/opencode"
33
+ printf '{"coverage":{"threshold":95}}\n' > "$XDGHOME/opencode/makdoong2-team.json"
34
+
35
+ # 기준 state.json에 jq 필터를 적용해 시나리오별 픽스처 작성 (신 hierarchical 구조).
36
+ BASE='{"issue":"TEST-1","worktree":"'"$ROOT"'","stages":{"1_planning":{"done":false,"substages":{"jira":{"done":true,"validation_passed":true},"requirements":{"done":false},"scope":{"done":false}}},"2_implementation":{"done":false,"substages":{"dev":{"done":false},"test":{"unit":"none","integration":"none","coverage":"none"}}},"3_delivery":{"done":false,"substages":{"commit":{"done":false},"pr":{"draft_url":null},"review":{"comments":0}}}},"policy":null}'
37
+ mk(){ echo "$BASE" | jq "$1" > "$STATE"; }
38
+
39
+ # expect <name> <want: pass|block> <gate-script>
40
+ expect(){
41
+ local name="$1" want="$2" script="$3" out rc got
42
+ out="$(cd "$ROOT" && XDG_CONFIG_HOME="$XDGHOME" bash "$GATES/$script" "$ISSUE" 2>&1)"; rc=$?
43
+ got=block; [ "$rc" -eq 0 ] && got=pass
44
+ if [ "$got" = "$want" ]; then
45
+ echo " ✓ $name ($want)"; pass=$((pass+1))
46
+ else
47
+ echo " ✗ $name: want=$want got=$got (rc=$rc)"; echo "$out" | head -1 | sed 's/^/ /'; fail=$((fail+1))
48
+ fi
49
+ }
50
+
51
+ echo ""
52
+ echo "[gate-policy-test] 조건부 auto-approve 게이트 분기"
53
+ echo ""
54
+ echo "── stage3-scope-verify (2→3) ──"
55
+ rm -f "$REPORT"
56
+
57
+ # minor (기본): auto_approve true → 승인/pending 무시하고 통과
58
+ mk '.stages."1_planning".substages."requirements".done=true | .stages."1_planning".substages."requirements".verification_pending=true | .policy={category:"minor",auto_approve:{"1_planning.requirements":true}}'
59
+ expect "minor 기본 auto-approve (승인 없이 통과)" pass stage3-scope-verify.sh
60
+
61
+ # major (기본): auto_approve true → 통과 (minor 와 동일 흐름 — category 는 라벨용)
62
+ mk '.stages."1_planning".substages."requirements".done=true | .policy={category:"major",auto_approve:{"1_planning.requirements":true}}'
63
+ expect "major 기본도 요구사항 게이트는 무인 통과" pass stage3-scope-verify.sh
64
+
65
+ # legacy(no policy) + 미승인 → 차단
66
+ mk '.stages."1_planning".substages."requirements".done=true | .stages."1_planning".substages."requirements".approved_by_user=false'
67
+ expect "구형 state 미승인 → 차단" block stage3-scope-verify.sh
68
+
69
+ # legacy(no policy) + 승인 → 통과
70
+ mk '.stages."1_planning".substages."requirements".done=true | .stages."1_planning".substages."requirements".approved_by_user=true | .stages."1_planning".substages."requirements".verification_pending=false'
71
+ expect "구형 state 사용자 승인 → 통과" pass stage3-scope-verify.sh
72
+
73
+ # auto-approve여도 인터뷰 미완료면 차단 (정합성 게이트는 독립)
74
+ mk '.stages."1_planning".substages."requirements".done=true | .stages."1_planning".substages."requirements".interview_required=true | .stages."1_planning".substages."requirements".interview_completed=false | .policy={category:"minor",auto_approve:{"1_planning.requirements":true}}'
75
+ expect "인터뷰 미완료 → 차단 (auto와 무관)" block stage3-scope-verify.sh
76
+
77
+ echo ""
78
+ echo "── stage4-dev-verify (3→4) ──"
79
+ # worktree 경로 검증을 위해 실제 git worktree 생성 (메인 repo의 형제)
80
+ WT="$(dirname "$TMP")/$(basename "$TMP")-TEST-1"
81
+ (cd "$ROOT" && git worktree add "$WT" -b test-branch 2>/dev/null || true)
82
+ mk '.stages."1_planning".substages."scope".done=true | .stages."1_planning".substages."scope".verification_pending=true | .stages."2_implementation".substages."analysis".done=true | .policy={category:"minor",auto_approve:{"1_planning.scope":true}} | .worktree="'"$WT"'"'
83
+ expect "minor auto-approve → 통과" pass stage4-dev-verify.sh
84
+ mk '.stages."1_planning".substages."scope".done=true | .stages."1_planning".substages."scope".approved_by_user=false | .stages."2_implementation".substages."analysis".done=true | .worktree="'"$WT"'"'
85
+ expect "구형 state 미승인 → 차단" block stage4-dev-verify.sh
86
+ mk '.stages."1_planning".substages."scope".done=true | .stages."1_planning".substages."scope".approved_by_user=true | .stages."2_implementation".substages."analysis".done=true | .worktree="'"$WT"'"'
87
+ expect "구형 state 승인 → 통과" pass stage4-dev-verify.sh
88
+
89
+ echo ""
90
+ echo "── stage6-commit-verify (5→6) ──"
91
+ TESTS='.stages."1_planning".substages."jira".done=true | .stages."1_planning".substages."requirements".done=true | .stages."1_planning".substages."scope".done=true | .stages."2_implementation".substages."dev".done=true | .stages."2_implementation".substages."test".unit="pass" | .stages."2_implementation".substages."test".integration="skip" | .stages."2_implementation".substages."test".coverage="exempt"'
92
+
93
+ # minor (기본): commit auto_approve true → 보고서/승인 없이 통과
94
+ rm -f "$REPORT"
95
+ mk "$TESTS | .policy={category:\"minor\",auto_approve:{\"3_delivery.commit\":true}}"
96
+ expect "minor 기본 → 휴먼 게이트 없이 통과" pass stage6-commit-verify.sh
97
+
98
+ # major (기본): commit auto_approve true → 보고서/승인 없이 통과 (minor 와 동일 흐름)
99
+ rm -f "$REPORT"
100
+ mk "$TESTS | .policy={category:\"major\",auto_approve:{\"3_delivery.commit\":true}}"
101
+ expect "major 기본 (auto_approve=true) → 휴먼 게이트 없이 통과" pass stage6-commit-verify.sh
102
+
103
+ # HITL opt-in: 보고서 없음 + pending 없음 = 초기 상태 → 통과 (publisher 첫 dispatch 허용)
104
+ rm -f "$REPORT"
105
+ mk "$TESTS | .policy={category:\"major\",auto_approve:{\"3_delivery.commit\":false}}"
106
+ expect "HITL opt-in + 보고서 없음 (초기 상태) → 통과" pass stage6-commit-verify.sh
107
+
108
+ # HITL opt-in: 보고서 없음 + pending=true → 차단 (publisher가 보고서 생성 후 pending 세팅, 승인 대기)
109
+ rm -f "$REPORT"
110
+ mk "$TESTS | .policy={category:\"major\",auto_approve:{\"3_delivery.commit\":false}} | .stages.\"3_delivery\".substages.\"commit\".verification_pending=true"
111
+ expect "HITL opt-in + 보고서 없음 + pending=true → 차단" block stage6-commit-verify.sh
112
+
113
+ # HITL opt-in: 보고서 있으나 미승인 → 차단
114
+ echo "# 변경 보고서" > "$REPORT"
115
+ mk "$TESTS | .policy={category:\"major\",auto_approve:{\"3_delivery.commit\":false}} | .stages.\"3_delivery\".substages.\"commit\".approved_by_user=false"
116
+ expect "HITL opt-in + 보고서O + 미승인 → 차단" block stage6-commit-verify.sh
117
+
118
+ # HITL opt-in: 보고서 있고 승인 + pending=false → 통과
119
+ mk "$TESTS | .policy={category:\"major\",auto_approve:{\"3_delivery.commit\":false}} | .stages.\"3_delivery\".substages.\"commit\".approved_by_user=true | .stages.\"3_delivery\".substages.\"commit\".verification_pending=false"
120
+ expect "HITL opt-in + 보고서O + 승인 → 통과" pass stage6-commit-verify.sh
121
+
122
+ # HITL opt-in: 승인했으나 verification_pending=true → 차단
123
+ mk "$TESTS | .policy={category:\"major\",auto_approve:{\"3_delivery.commit\":false}} | .stages.\"3_delivery\".substages.\"commit\".approved_by_user=true | .stages.\"3_delivery\".substages.\"commit\".verification_pending=true"
124
+ expect "HITL opt-in + pending 잔류 → 차단" block stage6-commit-verify.sh
125
+
126
+ # legacy(no policy) → 휴먼 게이트 없이 통과 (backward-compat)
127
+ rm -f "$REPORT"
128
+ mk "$TESTS"
129
+ expect "구형 state → 휴먼 게이트 없이 통과" pass stage6-commit-verify.sh
130
+
131
+ echo ""
132
+ echo "── stage8-review-verify (7→8) ──"
133
+ BV='.stages."1_planning".substages."jira".done=true | .stages."1_planning".substages."requirements".done=true | .stages."1_planning".substages."scope".done=true | .stages."2_implementation".substages."dev".done=true | .stages."2_implementation".substages."test".unit="pass" | .stages."3_delivery".substages."commit".done=true | .stages."3_delivery".substages."pr".draft_url="http://pr/1" | .stages."3_delivery".substages."pr".body_validation={no_orphan_scenarios:true,template_match:true,section_content_match:true} | .stages."3_delivery".substages."pr".reviewer_added=true | .stages."3_delivery".substages."review".comments=1 | .stages."3_delivery".substages."review".all_comments_inline=true'
134
+ mk "$BV | .policy={category:\"minor\",auto_approve:{\"3_delivery.pr\":true}}"
135
+ expect "minor auto-approve → 통과" pass stage8-review-verify.sh
136
+ mk "$BV | .stages.\"3_delivery\".substages.\"pr\".approved_by_user=false"
137
+ expect "구형 state 미승인 → 차단" block stage8-review-verify.sh
138
+ mk "$BV | .stages.\"3_delivery\".substages.\"pr\".approved_by_user=true | .stages.\"3_delivery\".substages.\"pr\".verification_pending=false"
139
+ expect "구형 state 승인 → 통과" pass stage8-review-verify.sh
140
+ mk '.stages."1_planning".substages."jira".done=true | .stages."1_planning".substages."requirements".done=true | .stages."1_planning".substages."scope".done=true | .stages."2_implementation".substages."dev".done=true | .stages."2_implementation".substages."test".unit="pass" | .stages."3_delivery".substages."commit".done=true | .stages."3_delivery".substages."pr".draft_url="http://pr/1" | .stages."3_delivery".substages."pr".body_validation={no_orphan_scenarios:false,template_match:true,section_content_match:true} | .stages."3_delivery".substages."pr".reviewer_added=true | .stages."3_delivery".substages."review".comments=1 | .stages."3_delivery".substages."review".all_comments_inline=true | .policy={category:"minor",auto_approve:{"3_delivery.pr":true}}'
141
+ expect "body_validation false → 차단 (auto와 무관)" block stage8-review-verify.sh
142
+
143
+ BSS='.stages."1_planning".substages."jira".done=true | .stages."1_planning".substages."requirements".done=true | .stages."1_planning".substages."scope".done=true | .stages."2_implementation".substages."dev".done=true | .stages."2_implementation".substages."test".unit="pass" | .stages."3_delivery".substages."commit".done=true | .stages."3_delivery".substages."pr".draft_url="http://pr/1" | .stages."3_delivery".substages."pr".body_validation={no_orphan_scenarios:true,template_match:true,section_content_match:true} | .stages."3_delivery".substages."pr".reviewer_self_skipped=true | .stages."3_delivery".substages."review".comments=1 | .stages."3_delivery".substages."review".all_comments_inline=true'
144
+ mk "$BSS | .policy={category:\"minor\",auto_approve:{\"3_delivery.pr\":true}}"
145
+ expect "reviewer_self_skipped=true → reviewer 없어도 통과" pass stage8-review-verify.sh
146
+ mk '.stages."1_planning".substages."jira".done=true | .stages."1_planning".substages."requirements".done=true | .stages."1_planning".substages."scope".done=true | .stages."2_implementation".substages."dev".done=true | .stages."2_implementation".substages."test".unit="pass" | .stages."3_delivery".substages."commit".done=true | .stages."3_delivery".substages."pr".draft_url="http://pr/1" | .stages."3_delivery".substages."pr".body_validation={no_orphan_scenarios:true,template_match:true,section_content_match:true} | .stages."3_delivery".substages."review".comments=1 | .stages."3_delivery".substages."review".all_comments_inline=true | .policy={category:"minor",auto_approve:{"3_delivery.pr":true}}'
147
+ expect "reviewer_added·reviewer_self_skipped 모두 없음 → 차단" block stage8-review-verify.sh
148
+
149
+ echo ""
150
+ echo "[gate-policy-test] $pass passed, $fail failed"
151
+ echo ""
152
+ [ "$fail" -eq 0 ]