@boyingliu01/xp-gate 0.15.5 → 0.18.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 (165) hide show
  1. package/adapter-common.sh +0 -0
  2. package/adapters/cpp.sh +0 -0
  3. package/adapters/dart.sh +0 -0
  4. package/adapters/flutter.sh +0 -0
  5. package/adapters/go.sh +0 -0
  6. package/adapters/iac.sh +0 -0
  7. package/adapters/java.sh +0 -0
  8. package/adapters/kotlin.sh +0 -0
  9. package/adapters/objectivec.sh +0 -0
  10. package/adapters/plugins/book299-20132-python/scripts/install-gradle.sh +0 -0
  11. package/adapters/plugins/book299-20132-python/scripts/install-maven.sh +0 -0
  12. package/adapters/plugins/book299-4081-c/scripts/install-gradle.sh +0 -0
  13. package/adapters/plugins/book299-4081-c/scripts/install-maven.sh +0 -0
  14. package/adapters/plugins/book299-4083-javascriptes5/scripts/install-gradle.sh +0 -0
  15. package/adapters/plugins/book299-4083-javascriptes5/scripts/install-maven.sh +0 -0
  16. package/adapters/powershell.sh +0 -0
  17. package/adapters/python.sh +0 -0
  18. package/adapters/shell.sh +0 -0
  19. package/adapters/swift.sh +0 -0
  20. package/adapters/typescript.sh +0 -0
  21. package/bin/xp-gate.js +29 -1
  22. package/gate-3.sh +0 -0
  23. package/gate-4.sh +0 -0
  24. package/gate-7.sh +0 -0
  25. package/gate-8.sh +0 -0
  26. package/gate-9.sh +0 -0
  27. package/hooks/adapter-common.sh +0 -0
  28. package/hooks/gate-3.sh +0 -0
  29. package/hooks/gate-4.sh +0 -0
  30. package/hooks/gate-7.sh +0 -0
  31. package/hooks/gate-8.sh +0 -0
  32. package/hooks/gate-9.sh +0 -0
  33. package/hooks/lib/now-ms.sh +33 -0
  34. package/hooks/pre-commit +63 -47
  35. package/hooks/pre-push +0 -0
  36. package/hooks/sprint-gate.sh +291 -0
  37. package/lib/__tests__/check-version.test.js +122 -0
  38. package/lib/__tests__/doctor.test.js +13 -15
  39. package/lib/__tests__/gate-audit.test.ts +38 -0
  40. package/lib/__tests__/phase-transition.test.js +512 -272
  41. package/lib/__tests__/retro.test.js +131 -0
  42. package/lib/__tests__/sprint-audit.test.js +207 -207
  43. package/lib/__tests__/sprint-status-rework.test.js +184 -0
  44. package/lib/check-version.js +9 -0
  45. package/lib/doctor-tui.js +268 -198
  46. package/lib/doctor.js +15 -3
  47. package/lib/gate-audit.ts +18 -7
  48. package/lib/gate-runner.js +77 -30
  49. package/lib/init.js +10 -0
  50. package/lib/language-tools.js +833 -833
  51. package/lib/mattpocock-license-verdict.json +7 -0
  52. package/lib/phase-transition.js +499 -249
  53. package/lib/retro.js +222 -0
  54. package/lib/shared-utils.js +7 -0
  55. package/lib/sprint-audit.js +235 -235
  56. package/lib/sprint-init.js +207 -0
  57. package/lib/sprint-state-migrator.js +1 -0
  58. package/lib/sprint-status.js +111 -0
  59. package/mock-policy/AGENTS.md +3 -3
  60. package/mutation/AGENTS.md +3 -3
  61. package/package.json +3 -2
  62. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  63. package/plugins/claude-code/bin/delphi-review-guard.sh +0 -0
  64. package/plugins/claude-code/bin/xp-gate-check +0 -0
  65. package/plugins/claude-code/skills/batch-grill-me/SKILL.md +15 -0
  66. package/plugins/claude-code/skills/delphi-review/AGENTS.md +3 -3
  67. package/plugins/claude-code/skills/delphi-review/SKILL.md +59 -4
  68. package/plugins/claude-code/skills/delphi-review/references/requirements.md +390 -0
  69. package/plugins/claude-code/skills/delphi-review/references/round-templates.md +67 -0
  70. package/plugins/claude-code/skills/domain-modeling/ADR-FORMAT.md +64 -0
  71. package/plugins/claude-code/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  72. package/plugins/claude-code/skills/domain-modeling/SKILL.md +74 -0
  73. package/plugins/claude-code/skills/grill-with-docs/SKILL.md +7 -0
  74. package/plugins/claude-code/skills/grilling/SKILL.md +12 -0
  75. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
  76. package/plugins/claude-code/skills/sprint-flow/SKILL.md +168 -43
  77. package/plugins/claude-code/skills/sprint-flow/references/components/memory.md +1 -1
  78. package/plugins/claude-code/skills/sprint-flow/references/components/middleware.md +1 -1
  79. package/plugins/claude-code/skills/sprint-flow/references/components/skill-invocations.md +21 -20
  80. package/plugins/claude-code/skills/sprint-flow/references/components/tool-descriptions.md +22 -23
  81. package/plugins/claude-code/skills/sprint-flow/references/orchestration-rules.md +14 -12
  82. package/plugins/claude-code/skills/sprint-flow/references/phase-2-design.md +145 -133
  83. package/plugins/claude-code/skills/sprint-flow/references/phase-3-build.md +69 -2
  84. package/plugins/claude-code/skills/sprint-flow/references/phase-4-verify.md +93 -31
  85. package/plugins/claude-code/skills/sprint-flow/references/phase-5-ship.md +99 -14
  86. package/plugins/claude-code/skills/sprint-flow/references/phase-6-close.md +37 -5
  87. package/plugins/claude-code/skills/sprint-flow/references/phase-overview.md +58 -53
  88. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
  89. package/plugins/claude-code/skills/test-specification-alignment/SKILL.md +8 -3
  90. package/plugins/claude-code/skills/to-issues/SKILL.md +1 -1
  91. package/plugins/opencode/index.ts +1 -0
  92. package/plugins/opencode/package.json +1 -1
  93. package/plugins/opencode/skills/batch-grill-me/SKILL.md +15 -0
  94. package/plugins/opencode/skills/delphi-review/AGENTS.md +3 -3
  95. package/plugins/opencode/skills/delphi-review/SKILL.md +59 -4
  96. package/plugins/opencode/skills/delphi-review/references/requirements.md +390 -0
  97. package/plugins/opencode/skills/delphi-review/references/round-templates.md +67 -0
  98. package/plugins/opencode/skills/domain-modeling/ADR-FORMAT.md +64 -0
  99. package/plugins/opencode/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  100. package/plugins/opencode/skills/domain-modeling/SKILL.md +74 -0
  101. package/plugins/opencode/skills/grill-with-docs/SKILL.md +7 -0
  102. package/plugins/opencode/skills/grilling/SKILL.md +12 -0
  103. package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
  104. package/plugins/opencode/skills/sprint-flow/SKILL.md +168 -43
  105. package/plugins/opencode/skills/sprint-flow/references/components/memory.md +1 -1
  106. package/plugins/opencode/skills/sprint-flow/references/components/middleware.md +1 -1
  107. package/plugins/opencode/skills/sprint-flow/references/components/skill-invocations.md +21 -20
  108. package/plugins/opencode/skills/sprint-flow/references/components/tool-descriptions.md +22 -23
  109. package/plugins/opencode/skills/sprint-flow/references/orchestration-rules.md +14 -12
  110. package/plugins/opencode/skills/sprint-flow/references/phase-2-design.md +145 -133
  111. package/plugins/opencode/skills/sprint-flow/references/phase-3-build.md +69 -2
  112. package/plugins/opencode/skills/sprint-flow/references/phase-4-verify.md +93 -31
  113. package/plugins/opencode/skills/sprint-flow/references/phase-5-ship.md +99 -14
  114. package/plugins/opencode/skills/sprint-flow/references/phase-6-close.md +37 -5
  115. package/plugins/opencode/skills/sprint-flow/references/phase-overview.md +58 -53
  116. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
  117. package/plugins/opencode/skills/test-specification-alignment/SKILL.md +8 -3
  118. package/plugins/opencode/skills/to-issues/SKILL.md +1 -1
  119. package/plugins/qoder/agents/delphi-architecture.md +48 -48
  120. package/plugins/qoder/agents/delphi-feasibility.md +48 -48
  121. package/plugins/qoder/agents/delphi-technical.md +48 -48
  122. package/plugins/qoder/bin/sprint-flow-guard.sh +0 -0
  123. package/plugins/qoder/bin/xp-gate-check +0 -0
  124. package/plugins/qoder/plugin.json +1 -1
  125. package/plugins/qoder/skills/delphi-review/AGENTS.md +3 -3
  126. package/plugins/qoder/skills/sprint-flow/AGENTS.md +3 -3
  127. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +3 -3
  128. package/principles/AGENTS.md +3 -3
  129. package/scripts/__tests__/check-mattpocock-license.test.js +229 -0
  130. package/scripts/__tests__/sync-package-content.test.js +50 -0
  131. package/scripts/check-mattpocock-license.cjs +302 -0
  132. package/scripts/delphi-external-review.cjs +432 -432
  133. package/scripts/migrate-audit-anomalies.mjs +78 -0
  134. package/scripts/sync-package-content.js +52 -5
  135. package/skills/batch-grill-me/SKILL.md +15 -0
  136. package/skills/delphi-review/AGENTS.md +3 -3
  137. package/skills/delphi-review/SKILL.md +59 -4
  138. package/skills/delphi-review/references/requirements.md +390 -0
  139. package/skills/delphi-review/references/round-templates.md +67 -0
  140. package/skills/domain-modeling/ADR-FORMAT.md +64 -0
  141. package/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  142. package/skills/domain-modeling/SKILL.md +74 -0
  143. package/skills/grill-with-docs/SKILL.md +7 -0
  144. package/skills/grilling/SKILL.md +12 -0
  145. package/skills/sprint-flow/AGENTS.md +3 -3
  146. package/skills/sprint-flow/SKILL.md +168 -43
  147. package/skills/sprint-flow/references/components/memory.md +1 -1
  148. package/skills/sprint-flow/references/components/middleware.md +1 -1
  149. package/skills/sprint-flow/references/components/skill-invocations.md +21 -20
  150. package/skills/sprint-flow/references/components/tool-descriptions.md +22 -23
  151. package/skills/sprint-flow/references/orchestration-rules.md +14 -12
  152. package/skills/sprint-flow/references/phase-2-design.md +145 -133
  153. package/skills/sprint-flow/references/phase-3-build.md +69 -2
  154. package/skills/sprint-flow/references/phase-4-verify.md +93 -31
  155. package/skills/sprint-flow/references/phase-5-ship.md +99 -14
  156. package/skills/sprint-flow/references/phase-6-close.md +37 -5
  157. package/skills/sprint-flow/references/phase-overview.md +58 -53
  158. package/skills/test-specification-alignment/AGENTS.md +3 -3
  159. package/skills/test-specification-alignment/SKILL.md +8 -3
  160. package/skills/to-issues/SKILL.md +1 -1
  161. package/adapters/gate-3.sh +0 -68
  162. package/adapters/gate-4.sh +0 -80
  163. package/adapters/gate-7.sh +0 -45
  164. package/adapters/gate-8.sh +0 -56
  165. package/adapters/gate-9.sh +0 -104
@@ -0,0 +1,184 @@
1
+ /**
2
+ * TDD: written RED first (Phase G per design §12)
3
+ * @test REQ-REWORK-001 Sprint rework rate tracking (#369)
4
+ * @intent Validate xp-gate sprint-status --rework-check computes rework rate for closed sprints
5
+ */
6
+ const path = require('path');
7
+ const fs = require('fs');
8
+ const os = require('os');
9
+ const { execSync } = require('child_process');
10
+
11
+ const { handleSprintStatus } = require('../sprint-status');
12
+
13
+ let TMP_DIR;
14
+ let cwdSpy;
15
+
16
+ function git(cmd, dir) {
17
+ return execSync(`git ${cmd}`, { cwd: dir || TMP_DIR, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
18
+ }
19
+
20
+ function writeSprintState(state, dir) {
21
+ const sd = path.join(dir || TMP_DIR, '.sprint-state');
22
+ fs.mkdirSync(sd, { recursive: true });
23
+ fs.writeFileSync(path.join(sd, 'sprint-state.json'), JSON.stringify(state, null, 2));
24
+ }
25
+
26
+ function writeHistoryFile(name, state, dir) {
27
+ const hd = path.join(dir || TMP_DIR, '.sprint-state', 'sprint-history');
28
+ fs.mkdirSync(hd, { recursive: true });
29
+ fs.writeFileSync(path.join(hd, name), JSON.stringify(state, null, 2));
30
+ }
31
+
32
+ function makeCommit(msg, dir) {
33
+ const d = dir || TMP_DIR;
34
+ fs.appendFileSync(path.join(d, 'file.txt'), `${msg}-${Date.now()}\n`);
35
+ git('add -A', d);
36
+ git(`commit --no-verify -m "${msg}"`, d);
37
+ }
38
+
39
+ function daysAgo(n) {
40
+ return new Date(Date.now() - n * 86400000).toISOString();
41
+ }
42
+
43
+ beforeAll(() => {
44
+ TMP_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'rework-test-'));
45
+ cwdSpy = vi.spyOn(process, 'cwd');
46
+ });
47
+
48
+ beforeEach(() => {
49
+ cwdSpy.mockReturnValue(TMP_DIR);
50
+ });
51
+
52
+ afterAll(() => {
53
+ cwdSpy.mockRestore();
54
+ fs.rmSync(TMP_DIR, { recursive: true, force: true });
55
+ });
56
+
57
+ describe('sprint-status --rework-check (#369)', () => {
58
+ // TDD: written RED first (G phase per design §12)
59
+ test('(a) no closed sprints → exit 0 + graceful message', async () => {
60
+ writeSprintState({
61
+ _schema_version: 1,
62
+ id: 'sprint-open',
63
+ task_description: 'Open sprint',
64
+ phase: 3,
65
+ status: 'in_progress',
66
+ started_at: daysAgo(1),
67
+ isolation: { worktree_path: null, branch: 'main' },
68
+ phase_history: [],
69
+ metrics: {},
70
+ });
71
+
72
+ const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
73
+ const code = await handleSprintStatus(['--rework-check', '--window-days', '7', '--dir', TMP_DIR]);
74
+ const output = logSpy.mock.calls.map(c => c.join(' ')).join('\n');
75
+ logSpy.mockRestore();
76
+
77
+ expect(code).toBe(0);
78
+ expect(output).toContain('No closed sprints within');
79
+ });
80
+
81
+ // TDD: written RED first (G phase per design §12)
82
+ test('(b) 2 fix / 10 total → rework_rate 0.2, no alert, state file updated', async () => {
83
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'rework-b-'));
84
+ cwdSpy.mockReturnValue(dir);
85
+
86
+ git('init', dir);
87
+ git('config user.email "test@test.com"', dir);
88
+ git('config user.name "Test"', dir);
89
+ makeCommit('feat: initial', dir);
90
+ makeCommit('fix: resolve login bug', dir);
91
+ makeCommit('fix(auth): handle timeout', dir);
92
+
93
+ writeSprintState({
94
+ _schema_version: 1,
95
+ id: 'sprint-b',
96
+ task_description: 'Sprint B',
97
+ phase: 6,
98
+ status: 'completed',
99
+ started_at: daysAgo(9),
100
+ isolation: { worktree_path: null, branch: 'main' },
101
+ phase_history: [],
102
+ metrics: { completed_at: daysAgo(2), total_sprint_commits: 10 },
103
+ }, dir);
104
+
105
+ const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
106
+ const code = await handleSprintStatus(['--rework-check', '--window-days', '7', '--dir', dir]);
107
+ const output = logSpy.mock.calls.map(c => c.join(' ')).join('\n');
108
+ logSpy.mockRestore();
109
+
110
+ expect(code).toBe(0);
111
+ expect(output).toContain('20.0%');
112
+ expect(output).not.toContain('⚠️');
113
+
114
+ const updated = JSON.parse(
115
+ fs.readFileSync(path.join(dir, '.sprint-state', 'sprint-state.json'), 'utf8')
116
+ );
117
+ expect(updated.metrics.rework_rate).toBeCloseTo(0.2, 1);
118
+
119
+ fs.rmSync(dir, { recursive: true, force: true });
120
+ });
121
+
122
+ // TDD: written RED first (G phase per design §12)
123
+ test('(c) 5 fix / 10 total → rework_rate 0.5, alert printed', async () => {
124
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'rework-c-'));
125
+ cwdSpy.mockReturnValue(dir);
126
+
127
+ git('init', dir);
128
+ git('config user.email "test@test.com"', dir);
129
+ git('config user.name "Test"', dir);
130
+ makeCommit('fix: one', dir);
131
+ makeCommit('fix: two', dir);
132
+ makeCommit('bugfix: three', dir);
133
+ makeCommit('hotfix: four', dir);
134
+ makeCommit('patch: five', dir);
135
+ makeCommit('feat: six', dir);
136
+
137
+ writeSprintState({
138
+ _schema_version: 1,
139
+ id: 'sprint-c',
140
+ task_description: 'Sprint C',
141
+ phase: 6,
142
+ status: 'completed',
143
+ started_at: daysAgo(9),
144
+ isolation: { worktree_path: null, branch: 'main' },
145
+ phase_history: [],
146
+ metrics: { completed_at: daysAgo(2), total_sprint_commits: 10 },
147
+ }, dir);
148
+
149
+ const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
150
+ const code = await handleSprintStatus(['--rework-check', '--window-days', '7', '--dir', dir]);
151
+ const output = logSpy.mock.calls.map(c => c.join(' ')).join('\n');
152
+ logSpy.mockRestore();
153
+
154
+ expect(code).toBe(0);
155
+ expect(output).toContain('50.0%');
156
+ expect(output).toContain('⚠️');
157
+ expect(output).toContain('sprint-c');
158
+
159
+ fs.rmSync(dir, { recursive: true, force: true });
160
+ });
161
+
162
+ // TDD: written RED first (G phase per design §12)
163
+ test('(d) --window-days 1 filters out sprints closed >1 day ago', async () => {
164
+ writeHistoryFile('sprint-old.json', {
165
+ _schema_version: 1,
166
+ id: 'sprint-old',
167
+ task_description: 'Old sprint',
168
+ phase: 6,
169
+ status: 'completed',
170
+ started_at: daysAgo(20),
171
+ isolation: { worktree_path: null, branch: 'main' },
172
+ phase_history: [],
173
+ metrics: { completed_at: daysAgo(10), total_sprint_commits: 10 },
174
+ });
175
+
176
+ const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
177
+ const code = await handleSprintStatus(['--rework-check', '--window-days', '1', '--dir', TMP_DIR]);
178
+ const output = logSpy.mock.calls.map(c => c.join(' ')).join('\n');
179
+ logSpy.mockRestore();
180
+
181
+ expect(code).toBe(0);
182
+ expect(output).toContain('No closed sprints within 1 day');
183
+ });
184
+ });
@@ -89,6 +89,15 @@ function readCache() {
89
89
  }
90
90
 
91
91
  function writeCache(latest, publishedAt) {
92
+ // Validate version before writing — prevent corrupted/non-semver values
93
+ // from persisting in version-cache.json (e.g. undefined, empty string, placeholders).
94
+ // Uses 3-digit semver: MAJOR.MINOR.PATCH with optional pre-release tag.
95
+ const semverRegex = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
96
+ if (typeof latest !== 'string' || !semverRegex.test(latest)) {
97
+ console.warn(`[version-cache] Invalid version "${latest}" — not writing to cache`);
98
+ return;
99
+ }
100
+
92
101
  const cp = cachePath();
93
102
  if (!cp) return;
94
103
  ensureDir(path.dirname(cp));