tlc-claude-code 2.7.0 → 2.9.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 (30) hide show
  1. package/.claude/commands/tlc/audit.md +12 -0
  2. package/.claude/commands/tlc/autofix.md +12 -0
  3. package/.claude/commands/tlc/build.md +35 -4
  4. package/.claude/commands/tlc/cleanup.md +13 -1
  5. package/.claude/commands/tlc/coverage.md +12 -0
  6. package/.claude/commands/tlc/discuss.md +12 -0
  7. package/.claude/commands/tlc/docs.md +13 -1
  8. package/.claude/commands/tlc/edge-cases.md +13 -1
  9. package/.claude/commands/tlc/plan.md +32 -6
  10. package/.claude/commands/tlc/preflight.md +12 -0
  11. package/.claude/commands/tlc/progress.md +41 -15
  12. package/.claude/commands/tlc/refactor.md +12 -0
  13. package/.claude/commands/tlc/review-pr.md +32 -11
  14. package/.claude/commands/tlc/review.md +12 -0
  15. package/.claude/commands/tlc/security.md +13 -1
  16. package/.claude/commands/tlc/status.md +42 -3
  17. package/.claude/commands/tlc/tlc.md +32 -16
  18. package/.claude/commands/tlc/verify.md +12 -0
  19. package/.claude/commands/tlc/watchci.md +12 -0
  20. package/package.json +1 -1
  21. package/scripts/renumber-phases.js +283 -0
  22. package/scripts/renumber-phases.test.js +305 -0
  23. package/server/lib/orchestration/completion-checker.js +52 -2
  24. package/server/lib/orchestration/completion-checker.test.js +64 -0
  25. package/server/lib/orchestration/session-status.js +28 -4
  26. package/server/lib/orchestration/session-status.test.js +44 -1
  27. package/server/lib/orchestration/skill-dispatcher.js +270 -0
  28. package/server/lib/orchestration/skill-dispatcher.test.js +449 -0
  29. package/server/lib/workspace-manifest.js +138 -0
  30. package/server/lib/workspace-manifest.test.js +179 -0
@@ -0,0 +1,179 @@
1
+ import { afterEach, describe, expect, it } from 'vitest';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+
6
+ const {
7
+ discoverWorkspace,
8
+ resolveRepo,
9
+ resolvePhase,
10
+ } = await import('./workspace-manifest.js');
11
+
12
+ function makeTmpDir() {
13
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'workspace-manifest-'));
14
+ }
15
+
16
+ function writeJson(filePath, value) {
17
+ fs.writeFileSync(filePath, JSON.stringify(value, null, 2));
18
+ }
19
+
20
+ function removeDir(dirPath) {
21
+ fs.rmSync(dirPath, { recursive: true, force: true });
22
+ }
23
+
24
+ function createManifest(overrides = {}) {
25
+ return {
26
+ workspace: 'tlc-platform',
27
+ repos: {
28
+ TLC: { path: 'TLC', prefix: 'TLC', role: 'Runtime library' },
29
+ 'tlc-core': { path: 'tlc-core', prefix: 'CORE', role: 'Execution substrate' },
30
+ 'tlc-standalone': {
31
+ path: 'tlc-standalone',
32
+ prefix: 'SA',
33
+ role: 'Provider-agnostic CLI',
34
+ },
35
+ },
36
+ orchestrator: { url: 'http://localhost:3100', provider: 'tlc-core' },
37
+ ...overrides,
38
+ };
39
+ }
40
+
41
+ describe('workspace-manifest', () => {
42
+ const tempDirs = [];
43
+
44
+ afterEach(() => {
45
+ while (tempDirs.length > 0) {
46
+ removeDir(tempDirs.pop());
47
+ }
48
+ });
49
+
50
+ it('discoverWorkspace from subdirectory finds manifest at parent', () => {
51
+ const rootDir = makeTmpDir();
52
+ tempDirs.push(rootDir);
53
+
54
+ const nestedDir = path.join(rootDir, 'TLC', 'server', 'lib');
55
+ fs.mkdirSync(nestedDir, { recursive: true });
56
+ writeJson(path.join(rootDir, '.tlc-workspace.json'), createManifest());
57
+
58
+ const manifest = discoverWorkspace(nestedDir);
59
+
60
+ expect(manifest).not.toBeNull();
61
+ expect(manifest.workspace).toBe('tlc-platform');
62
+ expect(manifest.repos.TLC.path).toBe('TLC');
63
+ expect(manifest.repos['tlc-core'].prefix).toBe('CORE');
64
+ });
65
+
66
+ it('resolveRepo("CORE") returns tlc-core metadata', () => {
67
+ const manifest = createManifest();
68
+
69
+ expect(resolveRepo(manifest, 'CORE')).toEqual({
70
+ path: 'tlc-core',
71
+ prefix: 'CORE',
72
+ role: 'Execution substrate',
73
+ });
74
+ });
75
+
76
+ it('resolvePhase("CORE-2") parses correctly', () => {
77
+ const manifest = createManifest();
78
+
79
+ expect(resolvePhase(manifest, 'CORE-2', 'TLC')).toEqual({
80
+ repo: 'tlc-core',
81
+ prefix: 'CORE',
82
+ phase: '2',
83
+ });
84
+ });
85
+
86
+ it('resolvePhase("108", "TLC") returns TLC-108', () => {
87
+ const manifest = createManifest();
88
+
89
+ expect(resolvePhase(manifest, '108', 'TLC')).toEqual({
90
+ repo: 'TLC',
91
+ prefix: 'TLC',
92
+ phase: '108',
93
+ });
94
+ });
95
+
96
+ it('discoverWorkspace from /tmp returns null when no manifest exists in tree', () => {
97
+ const rootDir = makeTmpDir();
98
+ tempDirs.push(rootDir);
99
+
100
+ const nestedDir = path.join(rootDir, 'lonely', 'child');
101
+ fs.mkdirSync(nestedDir, { recursive: true });
102
+
103
+ expect(discoverWorkspace(nestedDir)).toBeNull();
104
+ });
105
+
106
+ it('resolveRepo("UNKNOWN") returns null', () => {
107
+ const manifest = createManifest();
108
+
109
+ expect(resolveRepo(manifest, 'UNKNOWN')).toBeNull();
110
+ });
111
+
112
+ it('resolvePhase("NOPE-1") returns null', () => {
113
+ const manifest = createManifest();
114
+
115
+ expect(resolvePhase(manifest, 'NOPE-1', 'TLC')).toBeNull();
116
+ });
117
+
118
+ it('invalid JSON throws descriptive error', () => {
119
+ const rootDir = makeTmpDir();
120
+ tempDirs.push(rootDir);
121
+
122
+ fs.writeFileSync(
123
+ path.join(rootDir, '.tlc-workspace.json'),
124
+ '{"workspace":"tlc-platform","repos":'
125
+ );
126
+
127
+ expect(() => discoverWorkspace(rootDir)).toThrow(/parse workspace manifest/i);
128
+ });
129
+
130
+ it('manifest missing repos key throws descriptive error', () => {
131
+ const rootDir = makeTmpDir();
132
+ tempDirs.push(rootDir);
133
+
134
+ writeJson(path.join(rootDir, '.tlc-workspace.json'), {
135
+ workspace: 'tlc-platform',
136
+ orchestrator: { url: 'http://localhost:3100', provider: 'tlc-core' },
137
+ });
138
+
139
+ expect(() => discoverWorkspace(rootDir)).toThrow(/missing repos key/i);
140
+ });
141
+
142
+ it('discoverWorkspace accepts a file path and searches from its parent directory', () => {
143
+ const rootDir = makeTmpDir();
144
+ tempDirs.push(rootDir);
145
+
146
+ const repoDir = path.join(rootDir, 'TLC');
147
+ const filePath = path.join(repoDir, 'server', 'lib', 'workspace-manifest.js');
148
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
149
+ fs.writeFileSync(filePath, '// fixture');
150
+ writeJson(path.join(rootDir, '.tlc-workspace.json'), createManifest());
151
+
152
+ const manifest = discoverWorkspace(filePath);
153
+
154
+ expect(manifest.repos['tlc-standalone']).toEqual({
155
+ path: 'tlc-standalone',
156
+ prefix: 'SA',
157
+ role: 'Provider-agnostic CLI',
158
+ });
159
+ });
160
+
161
+ it('resolvePhase returns null for unprefixed phase when current repo prefix is unknown', () => {
162
+ const manifest = createManifest();
163
+
164
+ expect(resolvePhase(manifest, '108', 'NOPE')).toBeNull();
165
+ });
166
+
167
+ it('resolvePhase returns null when current repo prefix is not provided for unprefixed phase', () => {
168
+ const manifest = createManifest();
169
+
170
+ expect(resolvePhase(manifest, '108')).toBeNull();
171
+ });
172
+
173
+ it('resolveRepo returns null when prefix is missing', () => {
174
+ const manifest = createManifest();
175
+
176
+ expect(resolveRepo(manifest)).toBeNull();
177
+ expect(resolveRepo(manifest, '')).toBeNull();
178
+ });
179
+ });