principles-disciple 1.80.0 → 1.82.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 (64) hide show
  1. package/openclaw.plugin.json +1 -1
  2. package/package.json +1 -1
  3. package/src/commands/strategy.ts +0 -18
  4. package/src/i18n/commands.ts +0 -12
  5. package/src/index.ts +47 -22
  6. package/src/service/correction-observer-service.ts +200 -0
  7. package/src/service/evolution-worker.ts +2 -123
  8. package/templates/langs/en/core/BOOTSTRAP.md +4 -18
  9. package/templates/langs/en/skills/bootstrap-tools/SKILL.md +1 -1
  10. package/templates/langs/en/skills/init-strategy/SKILL.md +1 -1
  11. package/templates/langs/en/skills/pd-mentor/SKILL.md +8 -23
  12. package/templates/langs/zh/core/BOOTSTRAP.md +2 -15
  13. package/templates/langs/zh/skills/bootstrap-tools/SKILL.md +1 -1
  14. package/templates/langs/zh/skills/init-strategy/SKILL.md +1 -1
  15. package/templates/langs/zh/skills/pd-mentor/SKILL.md +7 -22
  16. package/tests/commands/strategy.test.ts +3 -18
  17. package/tests/service/correction-observer-service.test.ts +331 -0
  18. package/tests/service/evolution-worker.correction-observer.test.ts +41 -164
  19. package/templates/langs/en/skills/ai-sprint-orchestration/EXAMPLES.md +0 -63
  20. package/templates/langs/en/skills/ai-sprint-orchestration/REFERENCE.md +0 -136
  21. package/templates/langs/en/skills/ai-sprint-orchestration/SKILL.md +0 -67
  22. package/templates/langs/en/skills/ai-sprint-orchestration/references/agent-registry.json +0 -143
  23. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +0 -107
  24. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +0 -107
  25. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +0 -95
  26. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +0 -98
  27. package/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +0 -58
  28. package/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +0 -190
  29. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +0 -310
  30. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +0 -683
  31. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +0 -604
  32. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +0 -32
  33. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +0 -707
  34. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/run.mjs +0 -3455
  35. package/templates/langs/en/skills/evolve-system/SKILL.md +0 -46
  36. package/templates/langs/en/skills/manage-okr/SKILL.md +0 -96
  37. package/templates/langs/en/skills/pd-daily/SKILL.md +0 -199
  38. package/templates/langs/en/skills/pd-grooming/SKILL.md +0 -46
  39. package/templates/langs/zh/skills/ai-sprint-orchestration/EXAMPLES.md +0 -63
  40. package/templates/langs/zh/skills/ai-sprint-orchestration/REFERENCE.md +0 -136
  41. package/templates/langs/zh/skills/ai-sprint-orchestration/SKILL.md +0 -67
  42. package/templates/langs/zh/skills/ai-sprint-orchestration/references/agent-registry.json +0 -143
  43. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +0 -107
  44. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +0 -107
  45. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/nocturnal-trinity-quality-enhancement.json +0 -111
  46. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +0 -95
  47. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +0 -98
  48. package/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +0 -58
  49. package/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +0 -190
  50. package/templates/langs/zh/skills/ai-sprint-orchestration/runtime/.gitignore +0 -2
  51. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +0 -310
  52. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +0 -683
  53. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +0 -604
  54. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +0 -32
  55. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +0 -707
  56. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +0 -3455
  57. package/templates/langs/zh/skills/ai-sprint-orchestration/test/archive.test.mjs +0 -230
  58. package/templates/langs/zh/skills/ai-sprint-orchestration/test/contract-enforcement.test.mjs +0 -672
  59. package/templates/langs/zh/skills/ai-sprint-orchestration/test/decision.test.mjs +0 -1321
  60. package/templates/langs/zh/skills/ai-sprint-orchestration/test/run.test.mjs +0 -1435
  61. package/templates/langs/zh/skills/evolve-system/SKILL.md +0 -46
  62. package/templates/langs/zh/skills/manage-okr/SKILL.md +0 -109
  63. package/templates/langs/zh/skills/pd-daily/SKILL.md +0 -283
  64. package/templates/langs/zh/skills/pd-grooming/SKILL.md +0 -46
@@ -1,230 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import fs from 'fs';
4
- import path from 'path';
5
- import os from 'os';
6
- import { fileURLToPath } from 'url';
7
- import { archiveRunById } from '../scripts/lib/archive.mjs';
8
-
9
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
-
11
- function makeMockRunDir() {
12
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'archive-test-'));
13
- const runDir = path.join(tmpDir, 'run');
14
-
15
- // Create minimal sprint structure
16
- fs.mkdirSync(path.join(runDir, 'stages', '01-investigate'), { recursive: true });
17
-
18
- const state = {
19
- runId: 'test-run-001',
20
- taskId: 'test-task',
21
- title: 'Test sprint',
22
- status: 'completed',
23
- currentStageIndex: 0,
24
- currentStage: 'investigate',
25
- currentRound: 1,
26
- createdAt: '2026-04-01T00:00:00.000Z',
27
- updatedAt: '2026-04-01T00:10:00.000Z',
28
- };
29
- fs.writeFileSync(path.join(runDir, 'sprint.json'), JSON.stringify(state, null, 2));
30
-
31
- // Scorecard
32
- fs.writeFileSync(path.join(runDir, 'stages', '01-investigate', 'scorecard.json'), JSON.stringify({
33
- stage: 'investigate',
34
- round: 1,
35
- outcome: 'advance',
36
- approvalCount: 2,
37
- blockerCount: 0,
38
- reviewerAVerdict: 'APPROVE',
39
- reviewerBVerdict: 'APPROVE',
40
- }));
41
-
42
- // Timeline
43
- fs.writeFileSync(path.join(runDir, 'timeline.md'), '# Timeline\n\n- 2026-04-01T00:00:00Z Started\n');
44
-
45
- return { tmpDir, runDir, state };
46
- }
47
-
48
- function cleanup(tmpDir) {
49
- fs.rmSync(tmpDir, { recursive: true, force: true });
50
- }
51
-
52
- test('archiveRun creates archive with all expected files', () => {
53
- const { tmpDir, runDir } = makeMockRunDir();
54
- const archiveDest = path.join(tmpDir, 'archive', 'test-run-001');
55
-
56
- try {
57
- // Monkey-patch sprintRoot to use our temp dir
58
- const result = archiveRunWithTmpRoot(runDir, 'test-run-001', tmpDir);
59
-
60
- assert.ok(fs.existsSync(result));
61
- assert.ok(fs.existsSync(path.join(result, 'archive-summary.md')));
62
- assert.ok(fs.existsSync(path.join(result, 'archive-meta.json')));
63
- assert.ok(fs.existsSync(path.join(result, 'sprint.json')));
64
- assert.ok(fs.existsSync(path.join(result, 'timeline.md')));
65
- assert.ok(fs.existsSync(path.join(result, 'stages', '01-investigate', 'scorecard.json')));
66
- assert.ok(fs.existsSync(path.join(result, 'git', 'branch.txt')));
67
-
68
- // Verify meta
69
- const meta = JSON.parse(fs.readFileSync(path.join(result, 'archive-meta.json'), 'utf8'));
70
- assert.equal(meta.status, 'completed');
71
- assert.equal(meta.runId, 'test-run-001');
72
- } finally {
73
- cleanup(tmpDir);
74
- }
75
- });
76
-
77
- test('archiveRun rejects second archive (idempotency)', () => {
78
- const { tmpDir, runDir } = makeMockRunDir();
79
-
80
- try {
81
- archiveRunWithTmpRoot(runDir, 'test-run-001', tmpDir);
82
- // Second call should throw
83
- let threw = false;
84
- try {
85
- archiveRunWithTmpRoot(runDir, 'test-run-001', tmpDir);
86
- } catch (e) {
87
- threw = true;
88
- assert.match(e.message, /Already archived/);
89
- }
90
- assert.ok(threw, 'Expected "Already archived" error on second archive');
91
- } finally {
92
- cleanup(tmpDir);
93
- }
94
- });
95
-
96
- test('archiveRunById throws for non-existent run', () => {
97
- assert.throws(() => archiveRunById('nonexistent-run-99999'), /Run not found/);
98
- });
99
-
100
- test('archive-summary.md contains stage progress table', () => {
101
- const { tmpDir, runDir } = makeMockRunDir();
102
-
103
- try {
104
- const result = archiveRunWithTmpRoot(runDir, 'test-run-001', tmpDir);
105
- const summary = fs.readFileSync(path.join(result, 'archive-summary.md'), 'utf8');
106
-
107
- assert.ok(summary.includes('Stage Progress'));
108
- assert.ok(summary.includes('investigate'));
109
- assert.ok(summary.includes('advance'));
110
- assert.ok(summary.includes('APPROVE'));
111
- assert.ok(summary.includes('Total wall time'));
112
- } finally {
113
- cleanup(tmpDir);
114
- }
115
- });
116
-
117
- test('archive handles empty stages gracefully', () => {
118
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'archive-test-'));
119
- const runDir = path.join(tmpDir, 'run');
120
-
121
- fs.mkdirSync(path.join(runDir, 'stages'), { recursive: true });
122
- fs.writeFileSync(path.join(runDir, 'sprint.json'), JSON.stringify({
123
- runId: 'empty-stages',
124
- taskId: 'test',
125
- title: 'Empty stages test',
126
- status: 'halted',
127
- currentStageIndex: 0,
128
- currentStage: 'investigate',
129
- currentRound: 1,
130
- haltReason: { type: 'test', details: 'just testing', blockers: [] },
131
- createdAt: '2026-04-01T00:00:00.000Z',
132
- updatedAt: '2026-04-01T00:05:00.000Z',
133
- }));
134
- fs.writeFileSync(path.join(runDir, 'timeline.md'), '# Timeline\n');
135
-
136
- try {
137
- const result = archiveRunWithTmpRoot(runDir, 'empty-stages', tmpDir);
138
- const summary = fs.readFileSync(path.join(result, 'archive-summary.md'), 'utf8');
139
- assert.ok(summary.includes('No stage scorecards found'));
140
- assert.ok(summary.includes('Halt Reason'));
141
- } finally {
142
- cleanup(tmpDir);
143
- }
144
- });
145
-
146
- /**
147
- * Helper: run archiveRun with a custom archive root (temp dir).
148
- * We directly call the module's archiveRun but override the archiveRoot.
149
- */
150
- function archiveRunWithTmpRoot(runDir, runId, tmpRoot) {
151
- const destDir = path.join(tmpRoot, 'archive', runId);
152
-
153
- // Check idempotency
154
- const metaPath = path.join(destDir, 'archive-meta.json');
155
- if (fs.existsSync(metaPath)) {
156
- const meta = JSON.parse(fs.readFileSync(metaPath, 'utf8'));
157
- if (meta.status === 'completed') {
158
- throw new Error(`Already archived: ${destDir}`);
159
- }
160
- fs.rmSync(destDir, { recursive: true, force: true });
161
- }
162
-
163
- const state = JSON.parse(fs.readFileSync(path.join(runDir, 'sprint.json'), 'utf8'));
164
-
165
- fs.mkdirSync(destDir, { recursive: true });
166
- try {
167
- fs.cpSync(runDir, destDir, { recursive: true });
168
- } catch {
169
- // Fallback
170
- }
171
-
172
- // Simulate git capture (just write a placeholder)
173
- const gitDir = path.join(destDir, 'git');
174
- fs.mkdirSync(gitDir, { recursive: true });
175
- fs.writeFileSync(path.join(gitDir, 'branch.txt'), 'test-branch\n');
176
- fs.writeFileSync(path.join(gitDir, 'log.txt'), 'abc123 test commit\n');
177
- fs.writeFileSync(path.join(gitDir, 'modified-files.txt'), 'src/test.ts\n');
178
- fs.writeFileSync(path.join(gitDir, 'diff.patch'), '');
179
- fs.writeFileSync(path.join(gitDir, 'status.txt'), 'M src/test.ts\n');
180
-
181
- // Generate summary inline (same logic as archive.mjs)
182
- const lines = [
183
- `# Sprint Archive: ${state.title || state.taskId}`,
184
- '',
185
- '## Identity',
186
- `- Run ID: ${state.runId}`,
187
- `- Task: ${state.taskId}`,
188
- `- Status: ${state.status}`,
189
- `- Archived at: ${new Date().toISOString()}`,
190
- '',
191
- '## Timeline',
192
- `- Created: ${state.createdAt}`,
193
- `- Updated: ${state.updatedAt}`,
194
- `- Total wall time: ${((Date.parse(state.updatedAt) - Date.parse(state.createdAt)) / 60000).toFixed(1)} minutes`,
195
- '',
196
- ];
197
-
198
- // Stage progress
199
- const stagesDir = path.join(destDir, 'stages');
200
- const stageEntries = [];
201
- if (fs.existsSync(stagesDir)) {
202
- for (const dir of fs.readdirSync(stagesDir).sort()) {
203
- const scPath = path.join(stagesDir, dir, 'scorecard.json');
204
- if (fs.existsSync(scPath)) {
205
- const sc = JSON.parse(fs.readFileSync(scPath, 'utf8'));
206
- stageEntries.push({ dir, ...sc });
207
- }
208
- }
209
- }
210
-
211
- lines.push('## Stage Progress');
212
- if (stageEntries.length > 0) {
213
- lines.push('| Stage | Outcome | Round | Approvals | Blockers | Reviewer A | Reviewer B |');
214
- lines.push('|-------|---------|-------|-----------|----------|-----------|-----------|');
215
- for (const s of stageEntries) {
216
- lines.push(`| ${s.dir} | ${s.outcome} | ${s.round} | ${s.approvalCount}/2 | ${s.blockerCount ?? 0} | ${s.reviewerAVerdict} | ${s.reviewerBVerdict} |`);
217
- }
218
- } else {
219
- lines.push('No stage scorecards found.');
220
- }
221
-
222
- if (state.haltReason) {
223
- lines.push('', '## Halt Reason', `- Type: ${state.haltReason.type}`, `- Details: ${state.haltReason.details}`);
224
- }
225
-
226
- fs.writeFileSync(path.join(destDir, 'archive-summary.md'), lines.join('\n') + '\n');
227
- fs.writeFileSync(metaPath, JSON.stringify({ runId, archivedAt: new Date().toISOString(), status: 'completed' }));
228
-
229
- return destDir;
230
- }