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.
- package/LICENSE +21 -0
- package/README.md +193 -0
- package/agents/makdoong2-analyzer.md +135 -0
- package/agents/makdoong2-engineer.md +165 -0
- package/agents/makdoong2-planner.md +267 -0
- package/agents/makdoong2-publisher.md +481 -0
- package/agents/makdoong2-team-leader.md +249 -0
- package/agents/makdoong2-verifier.md +353 -0
- package/assets/makdoong2-team.default.json +46 -0
- package/assets/makdoong2-team.schema.json +357 -0
- package/bin/cli.js +404 -0
- package/dist/agent-stage-config.d.ts +15 -0
- package/dist/agent-stage-config.js +119 -0
- package/dist/config.d.ts +79 -0
- package/dist/config.js +96 -0
- package/dist/logger.d.ts +14 -0
- package/dist/logger.js +131 -0
- package/dist/mcp-secret-injector.d.ts +56 -0
- package/dist/mcp-secret-injector.js +89 -0
- package/dist/model-chain-cli.d.ts +1 -0
- package/dist/model-chain-cli.js +21 -0
- package/dist/model-fallback-policy.d.ts +69 -0
- package/dist/model-fallback-policy.js +211 -0
- package/dist/opencode-plugin.d.ts +8 -0
- package/dist/opencode-plugin.js +2457 -0
- package/dist/poll-sub-session.d.ts +139 -0
- package/dist/poll-sub-session.js +494 -0
- package/dist/redact-secrets.d.ts +3 -0
- package/dist/redact-secrets.js +68 -0
- package/dist/session-index.d.ts +11 -0
- package/dist/session-index.js +71 -0
- package/dist/skill-mcp-registry.d.ts +59 -0
- package/dist/skill-mcp-registry.js +178 -0
- package/dist/stall-escalation.d.ts +1 -0
- package/dist/stall-escalation.js +22 -0
- package/dist/tmux-monitor.d.ts +193 -0
- package/dist/tmux-monitor.js +694 -0
- package/dist/verdict-hash.d.ts +1 -0
- package/dist/verdict-hash.js +62 -0
- package/gates/stage-analysis-verify.sh +84 -0
- package/gates/stage2-requirements-verify.sh +13 -0
- package/gates/stage3-scope-verify.sh +45 -0
- package/gates/stage4-dev-post-verify.sh +64 -0
- package/gates/stage4-dev-verify.sh +36 -0
- package/gates/stage5-coverage-verify.sh +36 -0
- package/gates/stage5-test-verify.sh +24 -0
- package/gates/stage6-commit-verify.sh +41 -0
- package/gates/stage6-post-commit-verify.sh +131 -0
- package/gates/stage7-post-pr-verify.sh +53 -0
- package/gates/stage7-pr-verify.sh +48 -0
- package/gates/stage8-post-review-verify.sh +84 -0
- package/gates/stage8-review-verify.sh +45 -0
- package/gates/verify.sh +44 -0
- package/opencode.json.example +40 -0
- package/package.json +84 -0
- package/postinstall.mjs +56 -0
- package/references/commit-convention.md +130 -0
- package/references/jira-issue-templates.md +203 -0
- package/references/pr-template.md +381 -0
- package/scripts/config.sh +46 -0
- package/scripts/coverage-record.sh +67 -0
- package/scripts/gate-policy-test.sh +152 -0
- package/scripts/install-lib.mjs +1029 -0
- package/scripts/lint-agent-prompts.sh +74 -0
- package/scripts/log-event.sh +44 -0
- package/scripts/model-policy.mjs +183 -0
- package/scripts/publish-if-changed.sh +207 -0
- package/scripts/release.sh +276 -0
- package/scripts/rollback-commits.sh +35 -0
- package/scripts/smoke-test.mjs +194 -0
- package/scripts/state.sh +192 -0
- package/scripts/test-postinstall.mjs +141 -0
- package/scripts/with-fallback.sh +56 -0
- package/scripts/wt-sync-ignored.sh +193 -0
- package/skills/_lib/load-secret.sh +149 -0
- package/skills/bamboo-ci/SKILL.md +81 -0
- package/skills/bamboo-ci/run-bamboo.sh +23 -0
- package/skills/bitbucket-research/SKILL.md +87 -0
- package/skills/bitbucket-research/run-repos.sh +23 -0
- package/skills/confluence-research/SKILL.md +75 -0
- package/skills/confluence-research/run-docs.sh +23 -0
- package/skills/github-oss-research/SKILL.md +59 -0
- package/skills/jira-research/SKILL.md +75 -0
- package/skills/jira-research/run-works.sh +23 -0
- package/src/hooks/guard-bash.sh +67 -0
- package/src/hooks/session-start.sh +96 -0
- package/src/hooks/sync-state.sh +47 -0
- package/stages/01-jira.md +43 -0
- package/stages/01-planning.md +229 -0
- package/stages/02-requirements.md +298 -0
- package/stages/03-scope.md +81 -0
- package/stages/04-analysis.md +281 -0
- package/stages/05-worktree-dev.md +124 -0
- package/stages/06-test.md +161 -0
- package/stages/07-commit.md +229 -0
- package/stages/08-pr.md +177 -0
- package/stages/09-review-comments.md +277 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# stage8-post-review-verify.sh <issue> — 8단계(리뷰 코멘트) post-execution 게이트
|
|
3
|
+
#
|
|
4
|
+
# 원칙: entry gate 는 전제조건, post-verify 는 완료 조건. publisher 가 §3-2 마지막에
|
|
5
|
+
# .done=true 를 기록하기 직전 본 스크립트를 호출한다. 실패 시 exit 2 로 publisher
|
|
6
|
+
# 재작업 loop 를 유도한다 (Bitbucket 에 부족한 코멘트 재 posting).
|
|
7
|
+
#
|
|
8
|
+
# 검사 항목 (완료조건):
|
|
9
|
+
# 1) review-comment-plan.json 존재 (LLM 사전 설계 아티팩트)
|
|
10
|
+
# 2) plan.commit_count == atomic_review.count_commits (계획된 커밋 수 = 실제 커밋 수)
|
|
11
|
+
# 3) plan.plan[] 모든 항목의 comments 배열 길이 >= 1 (계획 단계에서 커밋당 최소 1개)
|
|
12
|
+
# 4) comments_per_commit 마커의 모든 값 >= 1 (실제 posting 결과가 커밋당 최소 1개)
|
|
13
|
+
# 5) comments 총합 == comments_per_commit 값들의 합 (합계 정합성)
|
|
14
|
+
# 6) all_comments_inline == true (인라인 앵커 자기선언 — verifier 가 Bitbucket 재조회로 교차검증)
|
|
15
|
+
# 7) .stages.3_delivery.substages.review.done == true
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
18
|
+
ISSUE="${1:?usage: stage8-post-review-verify.sh <issue>}"
|
|
19
|
+
P="$("$HERE/../scripts/state.sh" root)/.makdoong2-team/$ISSUE/state.json"
|
|
20
|
+
fail(){ echo "MAKDOONG2-POSTGATE BLOCKED [3_delivery.review_post]: $1" >&2; exit 2; }
|
|
21
|
+
[ -f "$P" ] || fail "state.json 없음"
|
|
22
|
+
q(){ "$HERE/../scripts/state.sh" get "$ISSUE" "$1" 2>/dev/null || echo "__MISSING__"; }
|
|
23
|
+
|
|
24
|
+
CC="$(q '.stages."3_delivery".substages."commit".atomic_review.count_commits')"
|
|
25
|
+
case "$CC" in
|
|
26
|
+
''|null|__MISSING__) fail "commit.atomic_review.count_commits 미기록 — commit substage 를 먼저 완료" ;;
|
|
27
|
+
esac
|
|
28
|
+
[ "$CC" -ge 1 ] 2>/dev/null || fail "count_commits 가 정수 아니거나 <1: $CC"
|
|
29
|
+
|
|
30
|
+
PLAN_REL_RAW="$(q '.stages."3_delivery".substages."review".plan_path')"
|
|
31
|
+
PLAN_REL="$(printf '%s' "$PLAN_REL_RAW" | tr -d '"')"
|
|
32
|
+
case "$PLAN_REL_RAW" in
|
|
33
|
+
''|null|__MISSING__) fail "review.plan_path 미기록 — publisher 가 review-comment-plan.json 을 먼저 산출해야 함" ;;
|
|
34
|
+
esac
|
|
35
|
+
if [[ "$PLAN_REL" == /* ]]; then
|
|
36
|
+
PLAN_PATH="$PLAN_REL"
|
|
37
|
+
else
|
|
38
|
+
PLAN_PATH="$("$HERE/../scripts/state.sh" root)/$PLAN_REL"
|
|
39
|
+
fi
|
|
40
|
+
[ -f "$PLAN_PATH" ] || fail "review-comment-plan.json 파일 없음: $PLAN_PATH"
|
|
41
|
+
|
|
42
|
+
jq -e . "$PLAN_PATH" >/dev/null 2>&1 || fail "review-comment-plan.json JSON parse 실패: $PLAN_PATH"
|
|
43
|
+
|
|
44
|
+
PLAN_CC="$(jq -r '.commit_count // empty' "$PLAN_PATH")"
|
|
45
|
+
[ -n "$PLAN_CC" ] || fail "plan.commit_count 필드 없음"
|
|
46
|
+
[ "$PLAN_CC" = "$CC" ] \
|
|
47
|
+
|| fail "plan.commit_count($PLAN_CC) != atomic_review.count_commits($CC) — 계획된 커밋 수 불일치"
|
|
48
|
+
|
|
49
|
+
PLAN_LEN="$(jq -r '.plan | length' "$PLAN_PATH")"
|
|
50
|
+
[ "$PLAN_LEN" = "$CC" ] || fail "plan.plan 배열 길이($PLAN_LEN) != count_commits($CC)"
|
|
51
|
+
|
|
52
|
+
UNDER_PLAN="$(jq -r '[.plan[] | select((.comments // [] | length) < 1)] | length' "$PLAN_PATH")"
|
|
53
|
+
[ "$UNDER_PLAN" = "0" ] || fail "계획 단계에서 $UNDER_PLAN 개 커밋에 코멘트가 0개 — 커밋당 최소 1개 필요"
|
|
54
|
+
|
|
55
|
+
CPC="$(q '.stages."3_delivery".substages."review".comments_per_commit')"
|
|
56
|
+
case "$CPC" in
|
|
57
|
+
''|null|__MISSING__|'{}') fail "comments_per_commit 마커 미기록 또는 빈 객체 — 실제 posting 결과를 커밋별로 집계해야 함" ;;
|
|
58
|
+
esac
|
|
59
|
+
|
|
60
|
+
CPC_LEN="$(printf '%s' "$CPC" | jq -r 'length' 2>/dev/null || echo 0)"
|
|
61
|
+
[ "$CPC_LEN" = "$CC" ] \
|
|
62
|
+
|| fail "comments_per_commit 항목 수($CPC_LEN) != count_commits($CC) — 모든 커밋에 코멘트 매핑 필요"
|
|
63
|
+
|
|
64
|
+
CPC_UNDER="$(printf '%s' "$CPC" | jq -r '[to_entries[] | select((.value|tonumber) < 1)] | length' 2>/dev/null || echo -1)"
|
|
65
|
+
[ "$CPC_UNDER" = "0" ] || fail "$CPC_UNDER 개 커밋의 실제 앵커 코멘트 수가 0개 — 재작성 필요"
|
|
66
|
+
|
|
67
|
+
CPC_SUM="$(printf '%s' "$CPC" | jq -r '[.[] | tonumber] | add' 2>/dev/null || echo -1)"
|
|
68
|
+
COMMENTS="$(q '.stages."3_delivery".substages."review".comments')"
|
|
69
|
+
[ "$COMMENTS" = "$CPC_SUM" ] \
|
|
70
|
+
|| fail "review.comments($COMMENTS) != Σcomments_per_commit($CPC_SUM) — 합계 불일치"
|
|
71
|
+
|
|
72
|
+
AI="$(q '.stages."3_delivery".substages."review".all_comments_inline')"
|
|
73
|
+
[ "$AI" = "true" ] \
|
|
74
|
+
|| fail "all_comments_inline=$AI — 모든 코멘트가 filePath+line 앵커를 가져야 함"
|
|
75
|
+
|
|
76
|
+
D="$(q '.stages."3_delivery".substages."review".done')"
|
|
77
|
+
[ "$D" = "true" ] || fail "review.done 이 true 아님(=$D) — publisher 가 완료 마킹을 누락"
|
|
78
|
+
|
|
79
|
+
# [comment.status 전수 검증] status 필드가 존재하는 plan 에서만 적용 (하위 호환)
|
|
80
|
+
NOT_POSTED="$(jq -r '[.plan[].comments[] | select(has("status") and .status != "posted")] | length' "$PLAN_PATH")"
|
|
81
|
+
[ "$NOT_POSTED" = "0" ] \
|
|
82
|
+
|| fail "plan.json 에 status가 \"posted\" 가 아닌 comment 가 ${NOT_POSTED}개 남아 있음 — 미완료 코멘트 posting 후 status 갱신 필요"
|
|
83
|
+
|
|
84
|
+
echo "MAKDOONG2-POSTGATE OK: 3_delivery.review_post"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# stage8-review-verify.sh <issue> — 8단계(리뷰 코멘트) 진입 게이트
|
|
3
|
+
#
|
|
4
|
+
# 원칙: entry gate 는 substage 진입 "전제조건" 만 검사한다.
|
|
5
|
+
# 완료 조건(코멘트 개수, per-commit 매핑, 인라인 앵커 여부 등)은 publisher 가 substage
|
|
6
|
+
# 수행 후 stage8-post-review-verify.sh + verifier 에서 검증된다.
|
|
7
|
+
#
|
|
8
|
+
# 검사 항목 (전제조건):
|
|
9
|
+
# 1) state.json 존재
|
|
10
|
+
# 2) pr substage 산출물: draft_url, body_validation 3항목, reviewer 마커
|
|
11
|
+
# 3) HITL: auto_approve 미설정 시 사용자 승인 완료
|
|
12
|
+
#
|
|
13
|
+
# 제거된 조건 (완료조건 → post-verify 로 이동):
|
|
14
|
+
# * .stages.3_delivery.substages.review.comments >= 1
|
|
15
|
+
# * .stages.3_delivery.substages.review.all_comments_inline == true
|
|
16
|
+
# → 두 값 모두 publisher 가 §8-2 에서 인라인 코멘트를 작성한 뒤에 기록하는 완료 마커이므로
|
|
17
|
+
# entry gate 에 두면 first-entry 자체가 불가능(chicken-and-egg).
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
20
|
+
ISSUE="${1:?usage: stage8-review-verify.sh <issue>}"
|
|
21
|
+
P="$("$HERE/../scripts/state.sh" root)/.makdoong2-team/$ISSUE/state.json"
|
|
22
|
+
fail(){ echo "MAKDOONG2-GATE BLOCKED [3_delivery.review]: $1" >&2; exit 2; }
|
|
23
|
+
[ -f "$P" ] || fail "state.json 없음 — planning phase부터 시작하라"
|
|
24
|
+
q(){ "$HERE/../scripts/state.sh" get "$ISSUE" "$1" 2>/dev/null || echo "__MISSING__"; }
|
|
25
|
+
U="$(q '.stages."3_delivery".substages."pr".draft_url')"
|
|
26
|
+
{ [ -n "$U" ] && [ "$U" != "null" ] && [ "$U" != "__MISSING__" ]; } || fail "pr substage (Draft PR) 미생성"
|
|
27
|
+
for k in no_orphan_scenarios template_match section_content_match; do
|
|
28
|
+
v="$(q ".stages.\"3_delivery\".substages.\"pr\".body_validation.$k")"
|
|
29
|
+
[ "$v" = "true" ] || fail "PR 본문 검증 미통과(body_validation.$k=$v) — PR substage 세 검증을 모두 통과 후 기록해야 함"
|
|
30
|
+
done
|
|
31
|
+
|
|
32
|
+
REVIEWER_ADDED="$(q '.stages."3_delivery".substages."pr".reviewer_added')"
|
|
33
|
+
REVIEWER_SELF_SKIPPED="$(q '.stages."3_delivery".substages."pr".reviewer_self_skipped')"
|
|
34
|
+
if [ "$REVIEWER_ADDED" != "true" ] && [ "$REVIEWER_SELF_SKIPPED" != "true" ]; then
|
|
35
|
+
fail "PR에 reviewer 미추가(reviewer_added=$REVIEWER_ADDED, reviewer_self_skipped=$REVIEWER_SELF_SKIPPED) — 08-pr.md §7-4에 따라 토큰 소유자를 reviewer로 추가(reviewer_added=true)하거나, 토큰 소유자가 PR 작성자와 동일하여 추가가 불가한 경우 reviewer_self_skipped=true 를 기록해야 함"
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
if [ "$(q '.policy.auto_approve."3_delivery.pr"')" != "true" ]; then
|
|
39
|
+
[ "$(q '.stages."3_delivery".substages."pr".approved_by_user')" = "true" ] \
|
|
40
|
+
|| fail "pr substage 사용자 미승인 — Draft PR 검토 후 approved_by_user를 기록하라 (또는 .policy.auto_approve.\"3_delivery.pr\" 미설정)"
|
|
41
|
+
if [ "$(q '.stages."3_delivery".substages."pr".verification_pending')" = "true" ]; then
|
|
42
|
+
fail "pr substage 검증 대기 중(verification_pending) — 사용자 승인 후 approved_by_user를 기록하고 verification_pending을 false로 해소하라"
|
|
43
|
+
fi
|
|
44
|
+
fi
|
|
45
|
+
echo "MAKDOONG2-GATE OK: 3_delivery.review"
|
package/gates/verify.sh
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# verify.sh <issue> <target_stage> — 단계별 검증 게이트 디스패처.
|
|
3
|
+
# 각 단계의 검증 로직은 stage{N}-*-verify.sh에 위임한다.
|
|
4
|
+
# 의존: jq, git (각 하위 스크립트에서 사용)
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
7
|
+
ISSUE="${1:?usage: verify.sh <issue> <stage>}"
|
|
8
|
+
TARGET="${2:?usage: verify.sh <issue> <stage>}"
|
|
9
|
+
|
|
10
|
+
case "$TARGET" in
|
|
11
|
+
1_planning.jira)
|
|
12
|
+
JIRA_DONE="$("$HERE/../scripts/state.sh" get "$ISSUE" '.stages."1_planning".substages."jira".done' 2>/dev/null || echo "false")"
|
|
13
|
+
if [ "$JIRA_DONE" = "true" ]; then
|
|
14
|
+
echo "MAKDOONG2-GATE BLOCKED [1_planning.jira]: 이미 done=true 완료됨 — auto_advance_stage 로 다음 단계 진행" >&2
|
|
15
|
+
exit 2
|
|
16
|
+
fi
|
|
17
|
+
echo "MAKDOONG2-GATE OK: $TARGET (jira validation handled by extension gate)" ;;
|
|
18
|
+
1_planning.requirements)
|
|
19
|
+
"$HERE/stage2-requirements-verify.sh" "$ISSUE" ;;
|
|
20
|
+
1_planning.scope)
|
|
21
|
+
"$HERE/stage3-scope-verify.sh" "$ISSUE" ;;
|
|
22
|
+
2_implementation.analysis)
|
|
23
|
+
"$HERE/stage-analysis-verify.sh" "$ISSUE" ;;
|
|
24
|
+
2_implementation.dev)
|
|
25
|
+
"$HERE/stage4-dev-verify.sh" "$ISSUE" ;;
|
|
26
|
+
2_implementation.dev_post)
|
|
27
|
+
"$HERE/stage4-dev-post-verify.sh" "$ISSUE" ;;
|
|
28
|
+
2_implementation.test)
|
|
29
|
+
"$HERE/stage5-test-verify.sh" "$ISSUE" ;;
|
|
30
|
+
3_delivery.commit)
|
|
31
|
+
"$HERE/stage6-commit-verify.sh" "$ISSUE" ;;
|
|
32
|
+
3_delivery.commit_post | 6_commit_post)
|
|
33
|
+
"$HERE/stage6-post-commit-verify.sh" "$ISSUE" ;;
|
|
34
|
+
3_delivery.pr)
|
|
35
|
+
"$HERE/stage7-pr-verify.sh" "$ISSUE" ;;
|
|
36
|
+
3_delivery.pr_post)
|
|
37
|
+
"$HERE/stage7-post-pr-verify.sh" "$ISSUE" ;;
|
|
38
|
+
3_delivery.review)
|
|
39
|
+
"$HERE/stage8-review-verify.sh" "$ISSUE" ;;
|
|
40
|
+
3_delivery.review_post)
|
|
41
|
+
"$HERE/stage8-post-review-verify.sh" "$ISSUE" ;;
|
|
42
|
+
*)
|
|
43
|
+
echo "MAKDOONG2-GATE OK: $TARGET" ;;
|
|
44
|
+
esac
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://opencode.ai/config.json",
|
|
3
|
+
"instructions": [
|
|
4
|
+
"~/.config/opencode/custom_instructions.md"
|
|
5
|
+
],
|
|
6
|
+
"autoupdate": false,
|
|
7
|
+
"_comment_plugin": "makdoong2-team install이 자동으로 npm 패키지 이름(makdoong2-team)을 주입한다. 직접 편집 불필요.",
|
|
8
|
+
"plugin": [
|
|
9
|
+
"makdoong2-team"
|
|
10
|
+
],
|
|
11
|
+
"permission": {
|
|
12
|
+
"bash": {
|
|
13
|
+
"*": "allow",
|
|
14
|
+
"git commit*": "deny",
|
|
15
|
+
"git push*": "deny",
|
|
16
|
+
"git push --force*": "deny",
|
|
17
|
+
"git reset --hard*": "ask",
|
|
18
|
+
"git branch -D*": "ask",
|
|
19
|
+
"git worktree remove*": "ask",
|
|
20
|
+
"git worktree add*": "ask",
|
|
21
|
+
"rm -rf*": "ask"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"mcp": {
|
|
25
|
+
"_comment": "Site-wide MCP only. Per-stage MCP (works/repos/docs) is embedded in skills/*/SKILL.md for lazy loading.",
|
|
26
|
+
"chrome-devtools-mcp": {
|
|
27
|
+
"type": "local",
|
|
28
|
+
"command": ["npx", "-y", "chrome-devtools-mcp@latest"],
|
|
29
|
+
"enabled": true
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"tools": {
|
|
33
|
+
"chrome-devtools-mcp*": true,
|
|
34
|
+
"verify_stage": true,
|
|
35
|
+
"dispatch_stage": true,
|
|
36
|
+
"dispatch_verifier": true,
|
|
37
|
+
"auto_advance_stage": true,
|
|
38
|
+
"get_fallback_model": true
|
|
39
|
+
}
|
|
40
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "makdoong2-team",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "내 일을 대신해주는 막둥이들. Self-contained opencode plugin for 사내 workflow: per-stage specialist agents, deterministic shell gates, primary-only enforcement, and a model fallback advisor.",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"opencode",
|
|
10
|
+
"opencode-plugin",
|
|
11
|
+
"plugin",
|
|
12
|
+
"agent",
|
|
13
|
+
"workflow",
|
|
14
|
+
"jira",
|
|
15
|
+
"multi-agent",
|
|
16
|
+
"makdoong2"
|
|
17
|
+
],
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "dist/opencode-plugin.js",
|
|
20
|
+
"types": "dist/opencode-plugin.d.ts",
|
|
21
|
+
"bin": {
|
|
22
|
+
"makdoong2-team": "bin/cli.js"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"import": "./dist/opencode-plugin.js",
|
|
27
|
+
"types": "./dist/opencode-plugin.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./schema.json": "./assets/makdoong2-team.schema.json"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"bin",
|
|
33
|
+
"dist",
|
|
34
|
+
"src/hooks",
|
|
35
|
+
"agents",
|
|
36
|
+
"gates",
|
|
37
|
+
"stages",
|
|
38
|
+
"references",
|
|
39
|
+
"scripts",
|
|
40
|
+
"skills",
|
|
41
|
+
"assets",
|
|
42
|
+
"opencode.json.example",
|
|
43
|
+
"postinstall.mjs"
|
|
44
|
+
],
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/y00njinuk/makdoong2-team.git"
|
|
48
|
+
},
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"engines": {
|
|
51
|
+
"opencode": ">=1.18.0",
|
|
52
|
+
"node": ">=20.0.0",
|
|
53
|
+
"tmux": ">=3.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"@opencode-ai/plugin": "^1.18.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@opencode-ai/plugin": "1.18.15",
|
|
60
|
+
"@opencode-ai/sdk": "1.18.15",
|
|
61
|
+
"@types/node": "^22.20.1",
|
|
62
|
+
"husky": "^9.0.0",
|
|
63
|
+
"typescript": "^5.7.0"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"build": "tsc -p tsconfig.build.json",
|
|
67
|
+
"clean": "node -e \"import('node:fs').then(({rmSync})=>rmSync('dist',{recursive:true,force:true}))\"",
|
|
68
|
+
"prepack": "npm run clean && npm run build",
|
|
69
|
+
"postinstall": "node postinstall.mjs",
|
|
70
|
+
"prepare": "husky install",
|
|
71
|
+
"test": "XDG_CONFIG_HOME=\"$(mktemp -d)\" XDG_CACHE_HOME=\"$(mktemp -d)\" npm run test:all",
|
|
72
|
+
"test:all": "npm run build && bash scripts/lint-agent-prompts.sh && node scripts/smoke-test.mjs && bash scripts/gate-policy-test.sh && node test/install-lib.test.mjs && node test/skill-mcp-registry.test.mjs && node --test test/state-write-guard.test.mjs && node --test test/state-sh-schema.test.mjs && node --test test/state-sh-init-review-shape.test.mjs && node --test test/doctor-phantom-scan.test.mjs && node --test test/mcp-secret-injector.test.mjs && node --test test/poll-sub-session.test.mjs && node --test test/tmux-monitor.test.mjs && node --test test/gate-already-done-block.test.mjs && node --test test/gate-hybrid-first-entry.test.mjs && node --test test/gate-post-pr-verify.test.mjs && node --test test/gate-post-review-verify.test.mjs && node --test test/worktree-sync-gate.test.mjs && node --test test/planner-prompt-early-exit.test.mjs && node --test test/plugin-bug-fixes.test.mjs && node --test test/omo-tmux-detection.test.mjs && node --test test/empty-output-done-override.test.mjs && node --test test/tmux-monitor-orphan.test.mjs && node --test test/poll-permission-scope.test.mjs && node --test test/dispatch-review-fixes.test.mjs && node --test test/dispatch-stage-redispatch.test.mjs && node --test test/dispatch-stage-dev-resume-prompt.test.mjs && node --test test/logger.test.mjs && node --test test/redact-secrets.test.mjs && node --test test/commit-atomicity-verify.test.mjs && node --test test/verdict-reason-injection.test.mjs && node --test test/verdict-hash-normalize.test.mjs && node --test test/session-index-fallback.test.mjs && node --test test/plugin-exports-shape.test.mjs && node --test test/stale-worktree-recovery.test.mjs && node --test test/rollback-commits.test.mjs && node --test test/config-dir-home-fallback.test.mjs && node --test test/state-path-migration.test.mjs && node --test test/state-path-relative.test.mjs && node --test test/with-fallback-no-bun.test.mjs && node --test test/doctor-exit-code.test.mjs && node --test test/example-config-portability.test.mjs",
|
|
73
|
+
"test:install": "node test/install-lib.test.mjs",
|
|
74
|
+
"test:postinstall": "node scripts/test-postinstall.mjs",
|
|
75
|
+
"release": "bash scripts/release.sh",
|
|
76
|
+
"release:patch": "bash scripts/release.sh patch",
|
|
77
|
+
"release:minor": "bash scripts/release.sh minor",
|
|
78
|
+
"release:major": "bash scripts/release.sh major"
|
|
79
|
+
},
|
|
80
|
+
"homepage": "https://github.com/y00njinuk/makdoong2-team#readme",
|
|
81
|
+
"bugs": {
|
|
82
|
+
"url": "https://github.com/y00njinuk/makdoong2-team/issues"
|
|
83
|
+
}
|
|
84
|
+
}
|
package/postinstall.mjs
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// postinstall.mjs — Auto-install on npm install -g
|
|
3
|
+
//
|
|
4
|
+
// Runs ONLY when:
|
|
5
|
+
// - npm_config_global === "true" (global install), OR
|
|
6
|
+
// - MAKDOONG2_AUTO_INSTALL === "1" (opt-in for local-dep scenarios)
|
|
7
|
+
//
|
|
8
|
+
// Skips when:
|
|
9
|
+
// - CI environment (unless MAKDOONG2_AUTO_INSTALL=1)
|
|
10
|
+
// - Local install (unless MAKDOONG2_AUTO_INSTALL=1)
|
|
11
|
+
//
|
|
12
|
+
// On failure: warns and exits 0 (don't break npm install)
|
|
13
|
+
|
|
14
|
+
import { dirname } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
import { install, resolveConfigDir } from "./scripts/install-lib.mjs";
|
|
17
|
+
|
|
18
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
|
|
20
|
+
function shouldRun() {
|
|
21
|
+
const isGlobal = process.env.npm_config_global === "true";
|
|
22
|
+
const optIn = process.env.MAKDOONG2_AUTO_INSTALL === "1";
|
|
23
|
+
const isCI = process.env.CI === "true" || process.env.CONTINUOUS_INTEGRATION === "true";
|
|
24
|
+
|
|
25
|
+
if (isCI && !optIn) {
|
|
26
|
+
console.log("[makdoong2-team] postinstall: CI detected — skipping. Run `makdoong2-team install` manually.");
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
if (!isGlobal && !optIn) {
|
|
30
|
+
console.log("[makdoong2-team] postinstall: local install detected — skipping. Run `makdoong2-team install` to deploy, or set MAKDOONG2_AUTO_INSTALL=1.");
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function main() {
|
|
37
|
+
if (!shouldRun()) return;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const configDir = resolveConfigDir(undefined);
|
|
41
|
+
console.log(`[makdoong2-team] postinstall: deploying to ${configDir}`);
|
|
42
|
+
install({
|
|
43
|
+
configDir,
|
|
44
|
+
pkgRoot: HERE,
|
|
45
|
+
force: false,
|
|
46
|
+
patchOpencode: "idempotent",
|
|
47
|
+
});
|
|
48
|
+
console.log("[makdoong2-team] postinstall: done. Run `makdoong2-team doctor` to verify.");
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.warn(`[makdoong2-team] postinstall: ${err.message}`);
|
|
51
|
+
console.warn("[makdoong2-team] postinstall: install incomplete — run `makdoong2-team install` to retry.");
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
main();
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Git Commit Message Convention
|
|
2
|
+
|
|
3
|
+
주인이 제공한 팀 커밋 컨벤션. makdoong2-team 스킬의 6단계에서 참조한다.
|
|
4
|
+
|
|
5
|
+
## 참조
|
|
6
|
+
- [How to write a git commit message](https://cbea.ms/git-commit/)
|
|
7
|
+
- [How to write better git commit messages (freeCodeCamp)](https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/)
|
|
8
|
+
- [robertpainsi/commit-message-guidelines (gist)](https://gist.github.com/robertpainsi/b632364184e70900af4ab688decf6f53)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 주요 원칙
|
|
13
|
+
|
|
14
|
+
### 제목과 본문 구조
|
|
15
|
+
- 제목과 본문은 **빈 줄**로 구분한다.
|
|
16
|
+
- 본문은 필요할 경우에만 작성한다.
|
|
17
|
+
- 제목은 **50자로 제한**한다 (한글은 25자 내외).
|
|
18
|
+
- 요약이 어렵다면 한 번에 너무 많은 변경사항을 커밋하는 것은 아닌지 고민하고, **atomic commit**을 고려한다.
|
|
19
|
+
- 제목은 **대문자로 시작**한다 (Type 부분).
|
|
20
|
+
- 제목 끝에 **마침표를 붙이지 않는다**.
|
|
21
|
+
- 제목은 **명령조(imperative)**로 작성한다. 한글도 명령조를 유지한다 ("추가한다" 대신 "추가").
|
|
22
|
+
- 본문은 한글 기준 줄당 약 40자 (영문 72자 상당).
|
|
23
|
+
|
|
24
|
+
### 본문 작성 원칙
|
|
25
|
+
본문은 "어떻게"보다 **"무엇을, 왜"**에 집중한다.
|
|
26
|
+
- 왜 이렇게 변경했는가?
|
|
27
|
+
- 변경사항이 어떤 영향을 미쳤는가?
|
|
28
|
+
- 왜 변화가 필요했는가?
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Type 일람
|
|
33
|
+
|
|
34
|
+
| Type | 설명 |
|
|
35
|
+
|------|------|
|
|
36
|
+
| **Feat** | 새로운 기능 추가 |
|
|
37
|
+
| **Fix** | 버그 수정 |
|
|
38
|
+
| **Chore** | fix/feature와 관계없고 src 또는 test 파일을 수정하지 않는 변경 (의존성 업데이트 등) |
|
|
39
|
+
| **Refactor** | 버그 수정이나 기능 추가가 아닌 리팩토링 |
|
|
40
|
+
| **Docs** | 문서 업데이트 (README 등 마크다운 파일 포함) |
|
|
41
|
+
| **Style** | 코드 의미에 영향을 주지 않는 변경 (공백, 세미콜론 누락 등 포매팅) |
|
|
42
|
+
| **Test** | 테스트 추가 또는 기존 테스트 수정 |
|
|
43
|
+
| **Perf** | 성능 개선 |
|
|
44
|
+
| **Ci** | CI(Continuous Integration) 관련 |
|
|
45
|
+
| **Build** | 빌드 시스템 또는 외부 의존성에 영향을 주는 변경 |
|
|
46
|
+
| **Revert** | 이전 커밋 되돌리기 |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 이슈 종료(Close) 키워드
|
|
51
|
+
|
|
52
|
+
- `close`, `closes`, `closed`
|
|
53
|
+
- `fix`, `fixes`, `fixed`
|
|
54
|
+
- `resolve`, `resolves`, `resolved`
|
|
55
|
+
|
|
56
|
+
**사용 구분**:
|
|
57
|
+
- 내부 이슈 → `close`, `fix`
|
|
58
|
+
- 외부 요청에 의한 이슈 → `resolve`
|
|
59
|
+
|
|
60
|
+
해당 커밋이 master로 커밋되거나, 커밋의 브랜치가 master로 머지될 때 자동으로 이슈가 종료된다.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 커밋 운영 가이드
|
|
65
|
+
|
|
66
|
+
- 로컬 브랜치 커밋은 자유롭게 하되, PR 전에 **커밋을 정리**한다 (rebase, squash 등).
|
|
67
|
+
- 수정 목적이 일관된 하나의 기능 또는 요구사항이면 **1 PR 1 Commit**을 권장한다.
|
|
68
|
+
- 분량이 많으면 기능을 적절히 분리하여(**atomic commit**) 작은 단위로 만든다.
|
|
69
|
+
- 이슈와 기능을 **잘게 쪼개야 한다**.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 커밋 메시지 포맷
|
|
74
|
+
|
|
75
|
+
### 기본 포맷
|
|
76
|
+
```
|
|
77
|
+
<Type>: [이슈키] <명령조 요약>
|
|
78
|
+
|
|
79
|
+
[본문: 왜, 무엇을]
|
|
80
|
+
|
|
81
|
+
[Footer: 이슈 링크]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 예시 1 — 이슈를 footer에 기재
|
|
85
|
+
```
|
|
86
|
+
Feat: 기능 구현
|
|
87
|
+
|
|
88
|
+
이러이러한 이유로 이렇게 수정한다
|
|
89
|
+
|
|
90
|
+
[RV] PROJ-00000
|
|
91
|
+
[AI] 100%
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 예시 2 — 이슈를 제목에 포함
|
|
95
|
+
```
|
|
96
|
+
Feat: PROJ-00000 - 기능 구현
|
|
97
|
+
|
|
98
|
+
이러이러한 이유로 이렇게 수정한다
|
|
99
|
+
|
|
100
|
+
[RV] PROJ-00000
|
|
101
|
+
[AI] 100%
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 예시 3 — 간단한 수정 (한 줄)
|
|
105
|
+
```
|
|
106
|
+
Docs: PROJ-00000 - 기능 설명 추가
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 예시 4 — 한글 본문 포함
|
|
110
|
+
```
|
|
111
|
+
Feat: PROJ-38356 - 상품 캐시 조회 API 구현
|
|
112
|
+
|
|
113
|
+
클라이언트에서 캐시 조회 요청이 들어오면 요청 파라미터
|
|
114
|
+
기반으로 캐시 키를 계산하여 Redis 캐시를 조회한다.
|
|
115
|
+
|
|
116
|
+
기존에는 Cassandra만 조회했지만 최근 변경 내역의 지연을
|
|
117
|
+
줄이기 위해 Redis를 1차 조회 대상으로 사용한다.
|
|
118
|
+
|
|
119
|
+
- Redis Cache Entity와 Cassandra Entity 간 변환을 정의한다
|
|
120
|
+
- Redis Cache Key 생성 함수를 추가한다
|
|
121
|
+
- 캐시 미스가 발생하면 Cassandra fallback을 유지한다
|
|
122
|
+
|
|
123
|
+
[RV] PROJ-38356
|
|
124
|
+
[AI] 100%
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 기타
|
|
130
|
+
- **Git 사용은 command line을 권장**한다.
|