@boyingliu01/xp-gate 0.9.1 → 0.9.3
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/adapters/cpp.sh +3 -3
- package/adapters/dart.sh +2 -2
- package/adapters/flutter.sh +2 -2
- package/adapters/java.sh +4 -4
- package/adapters/kotlin.sh +4 -4
- package/adapters/objectivec.sh +2 -2
- package/adapters/plugins/p3c-java/scripts/install-maven-p3c.sh +3 -3
- package/adapters/plugins/whalecloud-java/scripts/install-maven-whalecloud.sh +3 -3
- package/adapters/powershell.sh +3 -3
- package/adapters/python.sh +2 -2
- package/adapters/shell.sh +3 -3
- package/adapters/swift.sh +2 -2
- package/mock-policy/AGENTS.md +2 -2
- package/mutation/AGENTS.md +2 -2
- package/package.json +1 -1
- package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +2 -2
- package/plugins/claude-code/skills/sprint-flow/AGENTS.md +2 -2
- package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +2 -2
- package/plugins/opencode/__tests__/tui-plugin.test.ts +306 -0
- package/plugins/opencode/__tests__/xp-gate-update.test.ts +255 -0
- package/plugins/opencode/index.ts +158 -75
- package/plugins/opencode/package.json +14 -3
- package/plugins/opencode/skills/delphi-review/AGENTS.md +2 -2
- package/plugins/opencode/skills/sprint-flow/AGENTS.md +2 -2
- package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +2 -2
- package/plugins/opencode/tsconfig.json +1 -1
- package/plugins/opencode/tui-plugin.ts +188 -0
- package/plugins/qoder/skills/delphi-review/AGENTS.md +2 -2
- package/plugins/qoder/skills/sprint-flow/AGENTS.md +2 -2
- package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +2 -2
- package/principles/AGENTS.md +2 -2
- package/skills/delphi-review/AGENTS.md +2 -2
- package/skills/sprint-flow/AGENTS.md +2 -2
- package/skills/test-specification-alignment/AGENTS.md +2 -2
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XP-Gate OpenCode TUI Slot Plugin
|
|
3
|
+
*
|
|
4
|
+
* Registers sidebar_content slot to display Sprint Flow progress
|
|
5
|
+
* from .sprint-state/sprint-state.json.
|
|
6
|
+
*
|
|
7
|
+
* This is a separate plugin file because SDK 1.x PluginModule does not
|
|
8
|
+
* support server + tui in the same module. Users register this file
|
|
9
|
+
* in ~/.config/opencode/tui.json as:
|
|
10
|
+
* { "plugin": ["@boyingliu01/opencode-plugin/tui"] }
|
|
11
|
+
*
|
|
12
|
+
* The npm package exports "./tui" from package.json for this resolution.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
16
|
+
import { join } from "node:path"
|
|
17
|
+
import type { TuiPlugin, TuiSlotPlugin, TuiSlotProps } from "@opencode-ai/plugin/tui"
|
|
18
|
+
|
|
19
|
+
// ── Sprint state schema ──
|
|
20
|
+
|
|
21
|
+
interface SprintReq {
|
|
22
|
+
name?: string
|
|
23
|
+
status?: "completed" | "in_progress" | "pending"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface SprintPhaseHistory {
|
|
27
|
+
phase: number | string
|
|
28
|
+
phase_name?: string
|
|
29
|
+
status?: "completed" | "in_progress" | "pending"
|
|
30
|
+
started_at?: string
|
|
31
|
+
completed_at?: string
|
|
32
|
+
duration_seconds?: number
|
|
33
|
+
reqs?: Record<string, SprintReq>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface SprintState {
|
|
37
|
+
id?: string
|
|
38
|
+
phase?: number | string
|
|
39
|
+
status?: string
|
|
40
|
+
started_at?: string
|
|
41
|
+
task_description?: string
|
|
42
|
+
isolation?: { branch?: string; worktree_path?: string }
|
|
43
|
+
metrics?: { tests_passed?: number; tests_failed?: number; coverage_pct?: number }
|
|
44
|
+
phase_history?: SprintPhaseHistory[]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ── Constants ──
|
|
48
|
+
|
|
49
|
+
const PHASE_NAMES: Record<string, string> = {
|
|
50
|
+
"-1": "ISOLATE",
|
|
51
|
+
"-0.5": "AUTO-ESTIMATE",
|
|
52
|
+
"0": "THINK",
|
|
53
|
+
"1": "PLAN",
|
|
54
|
+
"2": "BUILD",
|
|
55
|
+
"3": "REVIEW",
|
|
56
|
+
"4": "USER ACCEPT",
|
|
57
|
+
"5": "FEEDBACK",
|
|
58
|
+
"6": "SHIP",
|
|
59
|
+
"7": "LAND",
|
|
60
|
+
"8": "CLEANUP",
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const PHASE_ORDER = ["-1", "-0.5", "0", "1", "2", "3", "4", "5", "6", "7", "8"]
|
|
64
|
+
|
|
65
|
+
// ── Helpers ──
|
|
66
|
+
|
|
67
|
+
function readSprintState(dir: string): SprintState | null {
|
|
68
|
+
try {
|
|
69
|
+
const stateFile = join(dir, ".sprint-state", "sprint-state.json")
|
|
70
|
+
if (!existsSync(stateFile)) return null
|
|
71
|
+
return JSON.parse(readFileSync(stateFile, "utf8"))
|
|
72
|
+
} catch {
|
|
73
|
+
return null
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isStale(state: SprintState): boolean {
|
|
78
|
+
if (!state || !state.started_at) return false
|
|
79
|
+
const started = new Date(state.started_at).getTime()
|
|
80
|
+
if (isNaN(started)) return false
|
|
81
|
+
let latest = started
|
|
82
|
+
if (Array.isArray(state.phase_history)) {
|
|
83
|
+
for (const ph of state.phase_history) {
|
|
84
|
+
if (ph.completed_at) {
|
|
85
|
+
const t = new Date(ph.completed_at).getTime()
|
|
86
|
+
if (!isNaN(t) && t > latest) latest = t
|
|
87
|
+
}
|
|
88
|
+
if (ph.started_at) {
|
|
89
|
+
const t = new Date(ph.started_at).getTime()
|
|
90
|
+
if (!isNaN(t) && t > latest) latest = t
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return Date.now() - latest > 3_600_000
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function statusSymbol(status: string | undefined, key: string, currentPhase: string | number | undefined): string {
|
|
98
|
+
if (status === "completed") return "✓"
|
|
99
|
+
if (status === "in_progress") return "→"
|
|
100
|
+
if (String(currentPhase) === key) return "·"
|
|
101
|
+
return "○"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function renderPhaseLine(key: string, history: SprintPhaseHistory | undefined, currentPhase: string | number | undefined): string {
|
|
105
|
+
const name = history?.phase_name || PHASE_NAMES[key] || key
|
|
106
|
+
const status = history?.status || (String(currentPhase) === key ? "in_progress" : "pending")
|
|
107
|
+
const sym = statusSymbol(status, key, currentPhase)
|
|
108
|
+
return `${sym} ${name.padEnd(14)} ${status === "completed" ? "done" : status === "in_progress" ? "active" : ""}`
|
|
109
|
+
.replace(/\s+$/, "")
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function renderSprintSidebar(state: SprintState): string {
|
|
113
|
+
if (!state || !state.task_description) return ""
|
|
114
|
+
|
|
115
|
+
const lines: string[] = []
|
|
116
|
+
const metrics = state.metrics || {}
|
|
117
|
+
const currentPhase = state.phase
|
|
118
|
+
|
|
119
|
+
// Build lookup
|
|
120
|
+
const historyByPhase: Record<string, SprintPhaseHistory> = {}
|
|
121
|
+
if (Array.isArray(state.phase_history)) {
|
|
122
|
+
for (const ph of state.phase_history) {
|
|
123
|
+
historyByPhase[String(ph.phase)] = ph
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Title
|
|
128
|
+
lines.push(`SPRINT: ${state.task_description}`)
|
|
129
|
+
|
|
130
|
+
// Metrics
|
|
131
|
+
const metricParts: string[] = []
|
|
132
|
+
if (metrics.tests_passed != null) {
|
|
133
|
+
metricParts.push(`tests:${metrics.tests_passed}`)
|
|
134
|
+
}
|
|
135
|
+
if (metrics.coverage_pct != null) {
|
|
136
|
+
metricParts.push(`cov:${metrics.coverage_pct}%`)
|
|
137
|
+
}
|
|
138
|
+
if (metricParts.length > 0) {
|
|
139
|
+
lines.push(metricParts.join(" "))
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Stale warning
|
|
143
|
+
if (isStale(state)) {
|
|
144
|
+
lines.push("⚠ idle >1h")
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Phase progress
|
|
148
|
+
for (const key of PHASE_ORDER) {
|
|
149
|
+
const history = historyByPhase[key]
|
|
150
|
+
// Only show phases with activity or current
|
|
151
|
+
if (!history && String(currentPhase) !== key) continue
|
|
152
|
+
const line = renderPhaseLine(key, history, currentPhase)
|
|
153
|
+
lines.push(line)
|
|
154
|
+
|
|
155
|
+
// REQ-level progress for BUILD phase
|
|
156
|
+
if (key === "2" && history?.reqs) {
|
|
157
|
+
const reqNames = Object.entries(history.reqs)
|
|
158
|
+
.filter(([, r]) => r.name)
|
|
159
|
+
.map(([id, r]) => ` ${statusSymbol(r.status, id, undefined)} ${r.name}`)
|
|
160
|
+
if (reqNames.length > 0) lines.push(...reqNames)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return lines.join("\n")
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ── TUI Slot Plugin ──
|
|
168
|
+
|
|
169
|
+
const tuiPlugin: TuiSlotPlugin = {
|
|
170
|
+
slots: {
|
|
171
|
+
sidebar_content: (_props: TuiSlotProps) => {
|
|
172
|
+
const dir = process.env.XP_GATE_PROJECT_DIR || process.cwd()
|
|
173
|
+
const state = readSprintState(dir)
|
|
174
|
+
if (!state) return null
|
|
175
|
+
const text = renderSprintSidebar(state)
|
|
176
|
+
if (!text) return null
|
|
177
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
178
|
+
return text as any
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Wrap as TuiPlugin (async factory)
|
|
184
|
+
const plugin: TuiPlugin = async (api, _options, _meta) => {
|
|
185
|
+
api.slots.register(tuiPlugin)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export { plugin as tui, readSprintState, renderSprintSidebar }
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
3
|
**Generated:** 2026-06-18
|
|
4
|
-
**Commit:**
|
|
4
|
+
**Commit:** b67fc85
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
3
|
**Generated:** 2026-06-18
|
|
4
|
-
**Commit:**
|
|
4
|
+
**Commit:** b67fc85
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**11-phase** development pipeline: ISOLATE → AUTO-ESTIMATE → THINK → PLAN → BUILD → REVIEW → USER ACCEPTANCE → FEEDBACK → SHIP → LAND → CLEANUP. Phase 2 default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE in Phase 1: design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
3
|
**Generated:** 2026-06-18
|
|
4
|
-
**Commit:**
|
|
4
|
+
**Commit:** b67fc85
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|
package/principles/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# PRINCIPLES CHECKER MODULE
|
|
2
2
|
|
|
3
3
|
**Generated:** 2026-06-18
|
|
4
|
-
**Commit:**
|
|
4
|
+
**Commit:** b67fc85
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Clean Code & SOLID principles checker — **Gate 4** of pre-commit. 14 rules × 9 language adapters, SARIF 2.1.0 output. Houses the **Boy Scout Rule** enforcement engine (Gate 6) and warning-baseline storage.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
3
|
**Generated:** 2026-06-18
|
|
4
|
-
**Commit:**
|
|
4
|
+
**Commit:** b67fc85
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
3
|
**Generated:** 2026-06-18
|
|
4
|
-
**Commit:**
|
|
4
|
+
**Commit:** b67fc85
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**11-phase** development pipeline: ISOLATE → AUTO-ESTIMATE → THINK → PLAN → BUILD → REVIEW → USER ACCEPTANCE → FEEDBACK → SHIP → LAND → CLEANUP. Phase 2 default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE in Phase 1: design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
3
|
**Generated:** 2026-06-18
|
|
4
|
-
**Commit:**
|
|
4
|
+
**Commit:** b67fc85
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|