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,211 @@
1
+ import { logger } from "./logger.js";
2
+ // Built-in primary allow-list. The runtime allow-list (`getAllowedPrimaries()`)
3
+ // is the union of these defaults and any extra IDs supplied by the user via
4
+ // `makdoong2-team.json` `model_policy.allowed_primaries`. Defaults are kept
5
+ // in the set so a typo in user config can never lock out the built-in primaries.
6
+ export const DEFAULT_ALLOWED_PRIMARIES = new Set([
7
+ "github-copilot/claude-haiku-4.5",
8
+ "github-copilot/claude-opus-4.5",
9
+ "github-copilot/claude-opus-4.6",
10
+ "github-copilot/claude-opus-4.6-fast",
11
+ "github-copilot/claude-opus-4.7",
12
+ "github-copilot/claude-opus-4.7-fast",
13
+ "github-copilot/claude-opus-4.8",
14
+ "github-copilot/claude-opus-4.8-fast",
15
+ "github-copilot/claude-opus-41",
16
+ "github-copilot/claude-sonnet-4",
17
+ "github-copilot/claude-sonnet-4.5",
18
+ "github-copilot/claude-sonnet-4.6",
19
+ "github-copilot/claude-sonnet-5",
20
+ "github-copilot/gemini-2.5-pro",
21
+ "github-copilot/gemini-3-flash-preview",
22
+ "github-copilot/gemini-3-pro-preview",
23
+ "github-copilot/gemini-3.1-pro-preview",
24
+ "github-copilot/gemini-3.5-flash",
25
+ "github-copilot/gpt-4.1",
26
+ "github-copilot/gpt-4o",
27
+ "github-copilot/gpt-5",
28
+ "github-copilot/gpt-5-mini",
29
+ "github-copilot/gpt-5.1",
30
+ "github-copilot/gpt-5.1-codex",
31
+ "github-copilot/gpt-5.1-codex-max",
32
+ "github-copilot/gpt-5.1-codex-mini",
33
+ "github-copilot/gpt-5.2",
34
+ "github-copilot/gpt-5.2-codex",
35
+ "github-copilot/gpt-5.3-codex",
36
+ "github-copilot/gpt-5.4",
37
+ "github-copilot/gpt-5.4-mini",
38
+ "github-copilot/gpt-5.5",
39
+ "github-copilot/gpt-5.6-luna",
40
+ "github-copilot/gpt-5.6-sol",
41
+ "github-copilot/gpt-5.6-terra",
42
+ "github-copilot/grok-code-fast-1",
43
+ "github-copilot/kimi-k2.7-code",
44
+ "github-copilot/mai-code-1-flash-picker",
45
+ "local/qwen3.6-27b",
46
+ "local/qwen3.6-35b-a3b",
47
+ ]);
48
+ // Backwards-compat re-export (read-only snapshot of the *current* runtime set).
49
+ // External callers should prefer getAllowedPrimaries(); this binding stays
50
+ // in place for existing imports/tests.
51
+ export let ALLOWED_PRIMARIES = new Set(DEFAULT_ALLOWED_PRIMARIES);
52
+ // User-supplied additions (from `model_policy.allowed_primaries`).
53
+ let _extraAllowedPrimaries = new Set();
54
+ /** Current runtime allow-list (defaults ∪ extras). */
55
+ export function getAllowedPrimaries() {
56
+ return ALLOWED_PRIMARIES;
57
+ }
58
+ /** Tier rank for the "fallback strictly lower than primary" invariant. */
59
+ const TIER_RANK = { low: 1, medium: 2, high: 3, max: 4 };
60
+ /** Public read-only accessor — single place documenting tier ordering. */
61
+ export function tierRank(tier) {
62
+ return TIER_RANK[tier];
63
+ }
64
+ // Default chains. All agents now use local/qwen3.6-27b as primary (medium tier).
65
+ // Fallback chain degrades to strictly lower tier. Override per-agent via
66
+ // makdoong2-team.json `agents` block.
67
+ export const POLICIES = {
68
+ "makdoong2-team-leader": {
69
+ primary: { id: "local/qwen3.6-27b", variant: "high", tier: "medium" },
70
+ fallbacks: [{ id: "github-copilot/claude-haiku-4.5", tier: "low" }],
71
+ },
72
+ "makdoong2-analyzer": {
73
+ primary: { id: "local/qwen3.6-27b", variant: "high", tier: "medium" },
74
+ fallbacks: [{ id: "github-copilot/claude-haiku-4.5", tier: "low" }],
75
+ },
76
+ "makdoong2-planner": {
77
+ primary: { id: "local/qwen3.6-27b", variant: "high", tier: "medium" },
78
+ fallbacks: [{ id: "github-copilot/claude-haiku-4.5", tier: "low" }],
79
+ },
80
+ "makdoong2-engineer": {
81
+ primary: { id: "local/qwen3.6-27b", variant: "high", tier: "medium" },
82
+ fallbacks: [{ id: "github-copilot/claude-haiku-4.5", tier: "low" }],
83
+ },
84
+ "makdoong2-publisher": {
85
+ primary: { id: "local/qwen3.6-27b", variant: "high", tier: "medium" },
86
+ fallbacks: [{ id: "github-copilot/claude-haiku-4.5", tier: "low" }],
87
+ },
88
+ "makdoong2-verifier": {
89
+ primary: { id: "local/qwen3.6-27b", tier: "medium" },
90
+ fallbacks: [{ id: "github-copilot/claude-haiku-4.5", tier: "low" }],
91
+ },
92
+ };
93
+ /** Picks the next model in the chain. Idempotent — call with the same `current` and you get the same `next`. */
94
+ export function nextModel(input) {
95
+ const policy = POLICIES[input.agent];
96
+ if (!policy)
97
+ return { next: null, exhausted: true, chain: [], reasonAccepted: "unknown agent" };
98
+ const chain = [policy.primary, ...policy.fallbacks];
99
+ const idx = chain.findIndex(m => m.id === input.current);
100
+ // If current isn't in chain, start from the beginning. Otherwise advance.
101
+ const nextIdx = idx < 0 ? 0 : idx + 1;
102
+ if (nextIdx >= chain.length) {
103
+ return { next: null, exhausted: true, chain, reasonAccepted: input.reason ?? "unknown" };
104
+ }
105
+ return { next: chain[nextIdx], exhausted: false, chain, reasonAccepted: input.reason ?? "unknown" };
106
+ }
107
+ /**
108
+ * Validates the two policy invariants. Throws on violation so a malformed
109
+ * default table or env override fails fast at plugin load.
110
+ * 1. policy.primary.id ∈ ALLOWED_PRIMARIES (= defaults ∪ extras)
111
+ * 2. ∀ fb ∈ policy.fallbacks: TIER_RANK[fb.tier] < TIER_RANK[policy.primary.tier]
112
+ */
113
+ export function validatePolicies(policies = POLICIES) {
114
+ for (const [agent, policy] of Object.entries(policies)) {
115
+ if (!ALLOWED_PRIMARIES.has(policy.primary.id)) {
116
+ throw new Error(`[model-router] agent '${agent}' primary '${policy.primary.id}' violates policy ` +
117
+ `(allowed: ${[...ALLOWED_PRIMARIES].join(", ")})`);
118
+ }
119
+ const primaryRank = TIER_RANK[policy.primary.tier];
120
+ for (const fb of policy.fallbacks) {
121
+ if (TIER_RANK[fb.tier] >= primaryRank) {
122
+ throw new Error(`[model-router] agent '${agent}' fallback '${fb.id}' (tier=${fb.tier}) is not ` +
123
+ `strictly lower than primary (tier=${policy.primary.tier})`);
124
+ }
125
+ }
126
+ }
127
+ }
128
+ /** Normalize a fallback override entry → { id, tier }. */
129
+ function normalizeFallback(entry) {
130
+ if (typeof entry === "string")
131
+ return { id: entry, tier: "low" };
132
+ return { id: entry.id, tier: entry.tier ?? "low" };
133
+ }
134
+ /** Deep snapshot of a policies dict so we can roll back on validation failure. */
135
+ function snapshotPolicies(src) {
136
+ const out = {};
137
+ for (const [k, v] of Object.entries(src)) {
138
+ out[k] = {
139
+ primary: { ...v.primary },
140
+ fallbacks: v.fallbacks.map(f => ({ ...f })),
141
+ };
142
+ }
143
+ return out;
144
+ }
145
+ /** Restore POLICIES in place from a snapshot (preserves the exported binding). */
146
+ function restorePolicies(snapshot) {
147
+ for (const k of Object.keys(POLICIES))
148
+ delete POLICIES[k];
149
+ for (const [k, v] of Object.entries(snapshot))
150
+ POLICIES[k] = v;
151
+ }
152
+ /** Recompute the runtime ALLOWED_PRIMARIES (defaults ∪ extras). */
153
+ function recomputeAllowedPrimaries() {
154
+ const merged = new Set(DEFAULT_ALLOWED_PRIMARIES);
155
+ for (const id of _extraAllowedPrimaries)
156
+ merged.add(id);
157
+ ALLOWED_PRIMARIES = merged;
158
+ }
159
+ /**
160
+ * Apply per-agent overrides + model_policy overrides from makdoong2-team.json
161
+ * onto POLICIES and the runtime ALLOWED_PRIMARIES, then re-validate.
162
+ *
163
+ * Atomicity: on any validation failure, BOTH POLICIES and ALLOWED_PRIMARIES
164
+ * are restored to their pre-call snapshot so the runtime can keep loading
165
+ * with the built-in defaults instead of a half-applied corrupt state.
166
+ *
167
+ * Kept dependency-free (the blocks are passed in by the caller, not read here)
168
+ * so scripts/smoke-test.mjs can mirror this module without a config dependency.
169
+ */
170
+ export function applyConfigOverrides(agents, modelPolicy) {
171
+ // Always snapshot — even a no-op call should leave defaults intact on early throw.
172
+ const policiesSnapshot = snapshotPolicies(POLICIES);
173
+ const extrasSnapshot = new Set(_extraAllowedPrimaries);
174
+ const allowedSnapshot = ALLOWED_PRIMARIES;
175
+ try {
176
+ // 1) Site-level allow-list extension first, so per-agent overrides can
177
+ // legitimately reference newly-allowed primaries.
178
+ if (modelPolicy?.allowed_primaries) {
179
+ _extraAllowedPrimaries = new Set(modelPolicy.allowed_primaries.filter(s => typeof s === "string" && s.length > 0));
180
+ recomputeAllowedPrimaries();
181
+ }
182
+ // 2) Per-agent overrides.
183
+ if (agents) {
184
+ for (const [agent, ov] of Object.entries(agents)) {
185
+ if (!ov || !ov.model)
186
+ continue;
187
+ const existing = POLICIES[agent];
188
+ const tier = existing?.primary.tier ?? "medium";
189
+ const fbEntries = ov.fallback_models == null
190
+ ? (existing?.fallbacks.map(f => ({ id: f.id, tier: f.tier })) ?? [])
191
+ : Array.isArray(ov.fallback_models)
192
+ ? ov.fallback_models
193
+ : [ov.fallback_models];
194
+ POLICIES[agent] = {
195
+ primary: { id: ov.model, variant: ov.variant ?? existing?.primary.variant, tier },
196
+ fallbacks: fbEntries.map(normalizeFallback),
197
+ };
198
+ }
199
+ }
200
+ validatePolicies();
201
+ }
202
+ catch (e) {
203
+ // Roll back to the pre-call snapshot so callers see a clean, validated state.
204
+ restorePolicies(policiesSnapshot);
205
+ _extraAllowedPrimaries = extrasSnapshot;
206
+ ALLOWED_PRIMARIES = allowedSnapshot;
207
+ logger.error("[makdoong2-team] failed to apply overrides from makdoong2-team.json — defaults preserved:", e);
208
+ }
209
+ }
210
+ // Fail fast at module load if the default table is malformed.
211
+ validatePolicies();
@@ -0,0 +1,8 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ export declare function isOmoTmuxManaged(pluginEntries?: Array<string | [string, unknown]>): boolean;
3
+ export declare function shouldOverrideEmptyOutcome(outcomeKind: string, currentSuccess: boolean, doneMarkerValue: string | null): boolean;
4
+ export declare function shouldOverrideSessionGoneOutcome(outcomeKind: string, currentSuccess: boolean, doneMarkerValue: string | null): boolean;
5
+ export declare function looksLikeFileWrite(cmd: string): boolean;
6
+ export declare function looksLikeSealedStateWrite(cmd: string): boolean;
7
+ export declare const Makdoong2TeamPlugin: Plugin;
8
+ export default Makdoong2TeamPlugin;