tlc-claude-code 1.3.0 → 1.4.1

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 (105) hide show
  1. package/dashboard/dist/components/AuditPane.d.ts +30 -0
  2. package/dashboard/dist/components/AuditPane.js +127 -0
  3. package/dashboard/dist/components/AuditPane.test.d.ts +1 -0
  4. package/dashboard/dist/components/AuditPane.test.js +339 -0
  5. package/dashboard/dist/components/CompliancePane.d.ts +39 -0
  6. package/dashboard/dist/components/CompliancePane.js +96 -0
  7. package/dashboard/dist/components/CompliancePane.test.d.ts +1 -0
  8. package/dashboard/dist/components/CompliancePane.test.js +183 -0
  9. package/dashboard/dist/components/SSOPane.d.ts +36 -0
  10. package/dashboard/dist/components/SSOPane.js +71 -0
  11. package/dashboard/dist/components/SSOPane.test.d.ts +1 -0
  12. package/dashboard/dist/components/SSOPane.test.js +155 -0
  13. package/dashboard/dist/components/WorkspaceDocsPane.js +0 -16
  14. package/dashboard/dist/components/WorkspacePane.d.ts +1 -1
  15. package/dashboard/dist/components/ZeroRetentionPane.d.ts +44 -0
  16. package/dashboard/dist/components/ZeroRetentionPane.js +83 -0
  17. package/dashboard/dist/components/ZeroRetentionPane.test.d.ts +1 -0
  18. package/dashboard/dist/components/ZeroRetentionPane.test.js +160 -0
  19. package/package.json +1 -1
  20. package/server/lib/access-control-doc.js +541 -0
  21. package/server/lib/access-control-doc.test.js +672 -0
  22. package/server/lib/adr-generator.js +423 -0
  23. package/server/lib/adr-generator.test.js +586 -0
  24. package/server/lib/agent-progress-monitor.js +223 -0
  25. package/server/lib/agent-progress-monitor.test.js +202 -0
  26. package/server/lib/audit-attribution.js +191 -0
  27. package/server/lib/audit-attribution.test.js +359 -0
  28. package/server/lib/audit-classifier.js +202 -0
  29. package/server/lib/audit-classifier.test.js +209 -0
  30. package/server/lib/audit-command.js +275 -0
  31. package/server/lib/audit-command.test.js +325 -0
  32. package/server/lib/audit-exporter.js +380 -0
  33. package/server/lib/audit-exporter.test.js +464 -0
  34. package/server/lib/audit-logger.js +236 -0
  35. package/server/lib/audit-logger.test.js +364 -0
  36. package/server/lib/audit-query.js +257 -0
  37. package/server/lib/audit-query.test.js +352 -0
  38. package/server/lib/audit-storage.js +269 -0
  39. package/server/lib/audit-storage.test.js +272 -0
  40. package/server/lib/bulk-repo-init.js +342 -0
  41. package/server/lib/bulk-repo-init.test.js +388 -0
  42. package/server/lib/compliance-checklist.js +866 -0
  43. package/server/lib/compliance-checklist.test.js +476 -0
  44. package/server/lib/compliance-command.js +616 -0
  45. package/server/lib/compliance-command.test.js +551 -0
  46. package/server/lib/compliance-reporter.js +692 -0
  47. package/server/lib/compliance-reporter.test.js +707 -0
  48. package/server/lib/data-flow-doc.js +665 -0
  49. package/server/lib/data-flow-doc.test.js +659 -0
  50. package/server/lib/ephemeral-storage.js +249 -0
  51. package/server/lib/ephemeral-storage.test.js +254 -0
  52. package/server/lib/evidence-collector.js +627 -0
  53. package/server/lib/evidence-collector.test.js +901 -0
  54. package/server/lib/flow-diagram-generator.js +474 -0
  55. package/server/lib/flow-diagram-generator.test.js +446 -0
  56. package/server/lib/idp-manager.js +626 -0
  57. package/server/lib/idp-manager.test.js +587 -0
  58. package/server/lib/memory-exclusion.js +326 -0
  59. package/server/lib/memory-exclusion.test.js +241 -0
  60. package/server/lib/mfa-handler.js +452 -0
  61. package/server/lib/mfa-handler.test.js +490 -0
  62. package/server/lib/oauth-flow.js +375 -0
  63. package/server/lib/oauth-flow.test.js +487 -0
  64. package/server/lib/oauth-registry.js +190 -0
  65. package/server/lib/oauth-registry.test.js +306 -0
  66. package/server/lib/readme-generator.js +490 -0
  67. package/server/lib/readme-generator.test.js +493 -0
  68. package/server/lib/repo-dependency-tracker.js +261 -0
  69. package/server/lib/repo-dependency-tracker.test.js +350 -0
  70. package/server/lib/retention-policy.js +281 -0
  71. package/server/lib/retention-policy.test.js +486 -0
  72. package/server/lib/role-mapper.js +236 -0
  73. package/server/lib/role-mapper.test.js +395 -0
  74. package/server/lib/saml-provider.js +765 -0
  75. package/server/lib/saml-provider.test.js +643 -0
  76. package/server/lib/security-policy-generator.js +682 -0
  77. package/server/lib/security-policy-generator.test.js +544 -0
  78. package/server/lib/sensitive-detector.js +112 -0
  79. package/server/lib/sensitive-detector.test.js +209 -0
  80. package/server/lib/service-interaction-diagram.js +700 -0
  81. package/server/lib/service-interaction-diagram.test.js +638 -0
  82. package/server/lib/service-summary.js +553 -0
  83. package/server/lib/service-summary.test.js +619 -0
  84. package/server/lib/session-purge.js +460 -0
  85. package/server/lib/session-purge.test.js +312 -0
  86. package/server/lib/sso-command.js +544 -0
  87. package/server/lib/sso-command.test.js +552 -0
  88. package/server/lib/sso-session.js +492 -0
  89. package/server/lib/sso-session.test.js +670 -0
  90. package/server/lib/workspace-command.js +249 -0
  91. package/server/lib/workspace-command.test.js +264 -0
  92. package/server/lib/workspace-config.js +270 -0
  93. package/server/lib/workspace-config.test.js +312 -0
  94. package/server/lib/workspace-docs-command.js +547 -0
  95. package/server/lib/workspace-docs-command.test.js +692 -0
  96. package/server/lib/workspace-memory.js +451 -0
  97. package/server/lib/workspace-memory.test.js +403 -0
  98. package/server/lib/workspace-scanner.js +452 -0
  99. package/server/lib/workspace-scanner.test.js +677 -0
  100. package/server/lib/workspace-test-runner.js +315 -0
  101. package/server/lib/workspace-test-runner.test.js +294 -0
  102. package/server/lib/zero-retention-command.js +439 -0
  103. package/server/lib/zero-retention-command.test.js +448 -0
  104. package/server/lib/zero-retention.js +322 -0
  105. package/server/lib/zero-retention.test.js +258 -0
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Workspace Command - CLI interface for workspace operations
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { WorkspaceConfig } = require('./workspace-config.js');
8
+ const { BulkRepoInit } = require('./bulk-repo-init.js');
9
+ const { WorkspaceTestRunner } = require('./workspace-test-runner.js');
10
+ const { RepoDependencyTracker } = require('./repo-dependency-tracker.js');
11
+
12
+ const CONFIG_FILENAME = '.tlc-workspace.json';
13
+
14
+ class WorkspaceCommand {
15
+ constructor(rootDir) {
16
+ this.rootDir = rootDir;
17
+ this.configPath = path.join(rootDir, CONFIG_FILENAME);
18
+ this.config = null;
19
+ this._loadConfig();
20
+ }
21
+
22
+ /**
23
+ * Load existing workspace config
24
+ */
25
+ _loadConfig() {
26
+ if (fs.existsSync(this.configPath)) {
27
+ try {
28
+ this.config = JSON.parse(fs.readFileSync(this.configPath, 'utf-8'));
29
+ } catch (err) {
30
+ this.config = null;
31
+ }
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Save workspace config
37
+ */
38
+ _saveConfig() {
39
+ fs.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2), 'utf-8');
40
+ }
41
+
42
+ /**
43
+ * Check if workspace is initialized
44
+ */
45
+ isInitialized() {
46
+ return this.config !== null;
47
+ }
48
+
49
+ /**
50
+ * Get current config
51
+ */
52
+ getConfig() {
53
+ return this.config;
54
+ }
55
+
56
+ /**
57
+ * Initialize workspace - scan, detect, and optionally bulk-init repos
58
+ */
59
+ async init(options = {}) {
60
+ const { dryRun = false, confirm = false } = options;
61
+
62
+ const workspaceConfig = new WorkspaceConfig(this.rootDir);
63
+ const bulkInit = new BulkRepoInit(this.rootDir);
64
+
65
+ // Discover repos
66
+ const discovered = workspaceConfig.discoverRepos();
67
+
68
+ // Find uninitialized repos
69
+ const needsInit = bulkInit.findUninitializedRepos();
70
+
71
+ const result = {
72
+ discovered,
73
+ needsInit,
74
+ initialized: 0,
75
+ skipped: discovered.length - needsInit.length,
76
+ errors: [],
77
+ };
78
+
79
+ if (dryRun) {
80
+ return result;
81
+ }
82
+
83
+ if (confirm) {
84
+ // Initialize all uninitialized repos
85
+ if (needsInit.length > 0) {
86
+ const initResult = bulkInit.initializeAll();
87
+ result.initialized = initResult.initialized;
88
+ result.errors = initResult.errors;
89
+ }
90
+
91
+ // Create workspace config
92
+ this.config = {
93
+ root: this.rootDir,
94
+ repos: discovered,
95
+ createdAt: new Date().toISOString(),
96
+ };
97
+ this._saveConfig();
98
+ }
99
+
100
+ return result;
101
+ }
102
+
103
+ /**
104
+ * Add a repo to the workspace
105
+ */
106
+ async add(repoPath) {
107
+ if (!this.isInitialized()) {
108
+ throw new Error('Workspace not initialized. Run init first.');
109
+ }
110
+
111
+ const absolutePath = path.isAbsolute(repoPath)
112
+ ? repoPath
113
+ : path.join(this.rootDir, repoPath);
114
+
115
+ const relativePath = path.relative(this.rootDir, absolutePath);
116
+
117
+ // Check repo exists
118
+ if (!fs.existsSync(absolutePath)) {
119
+ throw new Error(`Repository not found: ${repoPath}`);
120
+ }
121
+
122
+ // Auto-initialize if no .tlc.json
123
+ const tlcPath = path.join(absolutePath, '.tlc.json');
124
+ if (!fs.existsSync(tlcPath)) {
125
+ const bulkInit = new BulkRepoInit(this.rootDir);
126
+ bulkInit.initializeRepo(relativePath);
127
+ }
128
+
129
+ // Add to config if not already present
130
+ if (!this.config.repos.includes(relativePath)) {
131
+ this.config.repos.push(relativePath);
132
+ this._saveConfig();
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Remove a repo from the workspace (does not delete files)
138
+ */
139
+ async remove(repoPath) {
140
+ if (!this.isInitialized()) {
141
+ throw new Error('Workspace not initialized. Run init first.');
142
+ }
143
+
144
+ const relativePath = path.isAbsolute(repoPath)
145
+ ? path.relative(this.rootDir, repoPath)
146
+ : repoPath;
147
+
148
+ this.config.repos = this.config.repos.filter(r => r !== relativePath);
149
+ this._saveConfig();
150
+ }
151
+
152
+ /**
153
+ * List all repos with status
154
+ */
155
+ async list() {
156
+ if (!this.isInitialized()) {
157
+ throw new Error('Workspace not initialized. Run init first.');
158
+ }
159
+
160
+ const repos = [];
161
+
162
+ for (const repoName of this.config.repos) {
163
+ const repoPath = path.join(this.rootDir, repoName);
164
+ const info = {
165
+ name: repoName,
166
+ path: repoName,
167
+ status: 'ready',
168
+ hasTlc: false,
169
+ packageName: repoName,
170
+ };
171
+
172
+ // Check .tlc.json
173
+ const tlcPath = path.join(repoPath, '.tlc.json');
174
+ info.hasTlc = fs.existsSync(tlcPath);
175
+ info.status = info.hasTlc ? 'ready' : 'needs-init';
176
+
177
+ // Get package name
178
+ const pkgPath = path.join(repoPath, 'package.json');
179
+ if (fs.existsSync(pkgPath)) {
180
+ try {
181
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
182
+ if (pkg.name) {
183
+ info.packageName = pkg.name;
184
+ }
185
+ } catch (err) {
186
+ // Ignore
187
+ }
188
+ }
189
+
190
+ repos.push(info);
191
+ }
192
+
193
+ return repos;
194
+ }
195
+
196
+ /**
197
+ * Run tests across workspace
198
+ */
199
+ async test(options = {}) {
200
+ if (!this.isInitialized()) {
201
+ throw new Error('Workspace not initialized. Run init first.');
202
+ }
203
+
204
+ const runner = new WorkspaceTestRunner(this.rootDir, this.config.repos);
205
+ return runner.runTests(options);
206
+ }
207
+
208
+ /**
209
+ * Generate dependency graph (Mermaid)
210
+ */
211
+ async graph() {
212
+ if (!this.isInitialized()) {
213
+ throw new Error('Workspace not initialized. Run init first.');
214
+ }
215
+
216
+ const tracker = new RepoDependencyTracker(this.rootDir, this.config.repos);
217
+ return tracker.generateMermaidDiagram();
218
+ }
219
+
220
+ /**
221
+ * Get workspace status overview
222
+ */
223
+ async status() {
224
+ if (!this.isInitialized()) {
225
+ throw new Error('Workspace not initialized. Run init first.');
226
+ }
227
+
228
+ const repoList = await this.list();
229
+ const tracker = new RepoDependencyTracker(this.rootDir, this.config.repos);
230
+
231
+ return {
232
+ root: this.rootDir,
233
+ repoCount: this.config.repos.length,
234
+ repos: repoList.map(r => ({
235
+ name: r.name,
236
+ hasTlc: r.hasTlc,
237
+ status: r.status,
238
+ dependencies: tracker.getDependencies(r.name),
239
+ dependents: tracker.getDependents(r.name),
240
+ })),
241
+ dependencyGraph: tracker.getDependencyGraph(),
242
+ cycles: tracker.detectCircularDependencies(),
243
+ };
244
+ }
245
+ }
246
+
247
+ module.exports = {
248
+ WorkspaceCommand,
249
+ };
@@ -0,0 +1,264 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import os from 'os';
5
+
6
+ const { WorkspaceCommand } = await import('./workspace-command.js');
7
+
8
+ describe('WorkspaceCommand', () => {
9
+ let tempDir;
10
+ let command;
11
+
12
+ beforeEach(() => {
13
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'workspace-cmd-test-'));
14
+ });
15
+
16
+ afterEach(() => {
17
+ fs.rmSync(tempDir, { recursive: true, force: true });
18
+ });
19
+
20
+ function createRepo(name, options = {}) {
21
+ const repoPath = path.join(tempDir, name);
22
+ fs.mkdirSync(repoPath, { recursive: true });
23
+
24
+ fs.writeFileSync(
25
+ path.join(repoPath, 'package.json'),
26
+ JSON.stringify({
27
+ name: options.packageName || name,
28
+ version: '1.0.0',
29
+ scripts: { test: 'echo "pass"' },
30
+ dependencies: options.dependencies || {},
31
+ }, null, 2)
32
+ );
33
+
34
+ if (options.hasTlc) {
35
+ fs.writeFileSync(
36
+ path.join(repoPath, '.tlc.json'),
37
+ JSON.stringify({ project: name }, null, 2)
38
+ );
39
+ }
40
+
41
+ return repoPath;
42
+ }
43
+
44
+ describe('init', () => {
45
+ it('scans subdirectories for repos', async () => {
46
+ createRepo('repo-a');
47
+ createRepo('repo-b');
48
+
49
+ command = new WorkspaceCommand(tempDir);
50
+ const result = await command.init({ dryRun: true });
51
+
52
+ expect(result.discovered).toContain('repo-a');
53
+ expect(result.discovered).toContain('repo-b');
54
+ });
55
+
56
+ it('shows which repos need TLC setup', async () => {
57
+ createRepo('initialized', { hasTlc: true });
58
+ createRepo('uninitialized', { hasTlc: false });
59
+
60
+ command = new WorkspaceCommand(tempDir);
61
+ const result = await command.init({ dryRun: true });
62
+
63
+ expect(result.needsInit).toContain('uninitialized');
64
+ expect(result.needsInit).not.toContain('initialized');
65
+ });
66
+
67
+ it('bulk-initializes repos on confirm', async () => {
68
+ createRepo('new-repo-1');
69
+ createRepo('new-repo-2');
70
+
71
+ command = new WorkspaceCommand(tempDir);
72
+ const result = await command.init({ confirm: true });
73
+
74
+ expect(fs.existsSync(path.join(tempDir, 'new-repo-1', '.tlc.json'))).toBe(true);
75
+ expect(fs.existsSync(path.join(tempDir, 'new-repo-2', '.tlc.json'))).toBe(true);
76
+ expect(result.initialized).toBe(2);
77
+ });
78
+
79
+ it('creates .tlc-workspace.json', async () => {
80
+ createRepo('my-repo');
81
+
82
+ command = new WorkspaceCommand(tempDir);
83
+ await command.init({ confirm: true });
84
+
85
+ const configPath = path.join(tempDir, '.tlc-workspace.json');
86
+ expect(fs.existsSync(configPath)).toBe(true);
87
+
88
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
89
+ expect(config.repos).toContain('my-repo');
90
+ });
91
+
92
+ it('skips hidden directories and node_modules', async () => {
93
+ createRepo('valid-repo');
94
+ fs.mkdirSync(path.join(tempDir, '.hidden'));
95
+ fs.writeFileSync(path.join(tempDir, '.hidden', 'package.json'), '{}');
96
+ fs.mkdirSync(path.join(tempDir, 'node_modules'));
97
+ fs.writeFileSync(path.join(tempDir, 'node_modules', 'package.json'), '{}');
98
+
99
+ command = new WorkspaceCommand(tempDir);
100
+ const result = await command.init({ dryRun: true });
101
+
102
+ expect(result.discovered).toContain('valid-repo');
103
+ expect(result.discovered).not.toContain('.hidden');
104
+ expect(result.discovered).not.toContain('node_modules');
105
+ });
106
+ });
107
+
108
+ describe('add', () => {
109
+ it('adds repo to workspace', async () => {
110
+ createRepo('existing-repo', { hasTlc: true });
111
+
112
+ command = new WorkspaceCommand(tempDir);
113
+ await command.init({ confirm: true });
114
+ await command.add('existing-repo');
115
+
116
+ const config = command.getConfig();
117
+ expect(config.repos).toContain('existing-repo');
118
+ });
119
+
120
+ it('auto-initializes repo if no .tlc.json', async () => {
121
+ createRepo('uninit-repo');
122
+
123
+ command = new WorkspaceCommand(tempDir);
124
+ await command.init({ confirm: true });
125
+ await command.add('uninit-repo');
126
+
127
+ expect(fs.existsSync(path.join(tempDir, 'uninit-repo', '.tlc.json'))).toBe(true);
128
+ });
129
+
130
+ it('throws if repo does not exist', async () => {
131
+ command = new WorkspaceCommand(tempDir);
132
+ await command.init({ confirm: true });
133
+
134
+ await expect(command.add('nonexistent')).rejects.toThrow(/not found/i);
135
+ });
136
+ });
137
+
138
+ describe('remove', () => {
139
+ it('removes repo from config', async () => {
140
+ createRepo('to-remove', { hasTlc: true });
141
+
142
+ command = new WorkspaceCommand(tempDir);
143
+ await command.init({ confirm: true });
144
+ await command.remove('to-remove');
145
+
146
+ const config = command.getConfig();
147
+ expect(config.repos).not.toContain('to-remove');
148
+ });
149
+
150
+ it('does not delete repo files', async () => {
151
+ createRepo('keep-files', { hasTlc: true });
152
+
153
+ command = new WorkspaceCommand(tempDir);
154
+ await command.init({ confirm: true });
155
+ await command.remove('keep-files');
156
+
157
+ // Files should still exist
158
+ expect(fs.existsSync(path.join(tempDir, 'keep-files', 'package.json'))).toBe(true);
159
+ });
160
+ });
161
+
162
+ describe('list', () => {
163
+ it('shows repos with status (ready/needs-init)', async () => {
164
+ createRepo('ready-repo', { hasTlc: true });
165
+ createRepo('needs-init-repo', { hasTlc: false });
166
+
167
+ command = new WorkspaceCommand(tempDir);
168
+ await command.init({ confirm: true });
169
+ const list = await command.list();
170
+
171
+ const readyRepo = list.find(r => r.name === 'ready-repo');
172
+ const needsInitRepo = list.find(r => r.name === 'needs-init-repo');
173
+
174
+ expect(readyRepo.status).toBe('ready');
175
+ // After init with confirm, all repos should be ready
176
+ expect(needsInitRepo.status).toBe('ready');
177
+ });
178
+
179
+ it('shows repo names and paths', async () => {
180
+ createRepo('my-app', { packageName: '@org/my-app' });
181
+
182
+ command = new WorkspaceCommand(tempDir);
183
+ await command.init({ confirm: true });
184
+ const list = await command.list();
185
+
186
+ const repo = list.find(r => r.name === 'my-app');
187
+ expect(repo.packageName).toBe('@org/my-app');
188
+ expect(repo.path).toBe('my-app');
189
+ });
190
+ });
191
+
192
+ describe('test', () => {
193
+ it('runs unified test runner', async () => {
194
+ createRepo('test-repo');
195
+
196
+ command = new WorkspaceCommand(tempDir);
197
+ await command.init({ confirm: true });
198
+ const result = await command.test();
199
+
200
+ expect(result.summary.total).toBe(1);
201
+ expect(result.summary.passed).toBe(1);
202
+ });
203
+
204
+ it('passes options to test runner', async () => {
205
+ createRepo('repo-1');
206
+ createRepo('repo-2');
207
+
208
+ command = new WorkspaceCommand(tempDir);
209
+ await command.init({ confirm: true });
210
+ const result = await command.test({ filter: ['repo-1'] });
211
+
212
+ expect(Object.keys(result.repos)).toEqual(['repo-1']);
213
+ });
214
+ });
215
+
216
+ describe('graph', () => {
217
+ it('outputs Mermaid diagram', async () => {
218
+ createRepo('core', { packageName: 'core' });
219
+ createRepo('api', {
220
+ packageName: 'api',
221
+ dependencies: { core: 'workspace:*' },
222
+ });
223
+
224
+ command = new WorkspaceCommand(tempDir);
225
+ await command.init({ confirm: true });
226
+ const diagram = await command.graph();
227
+
228
+ expect(diagram).toContain('graph TD');
229
+ expect(diagram).toContain('api');
230
+ expect(diagram).toContain('core');
231
+ expect(diagram).toContain('-->');
232
+ });
233
+ });
234
+
235
+ describe('status', () => {
236
+ it('shows repo health overview', async () => {
237
+ createRepo('healthy-repo', { hasTlc: true });
238
+
239
+ command = new WorkspaceCommand(tempDir);
240
+ await command.init({ confirm: true });
241
+ const status = await command.status();
242
+
243
+ expect(status.repos).toHaveLength(1);
244
+ expect(status.repos[0].name).toBe('healthy-repo');
245
+ expect(status.repos[0].hasTlc).toBe(true);
246
+ });
247
+ });
248
+
249
+ describe('error handling', () => {
250
+ it('handles workspace not initialized error', async () => {
251
+ command = new WorkspaceCommand(tempDir);
252
+
253
+ await expect(command.list()).rejects.toThrow(/not initialized/i);
254
+ });
255
+
256
+ it('handles empty workspace', async () => {
257
+ command = new WorkspaceCommand(tempDir);
258
+ const result = await command.init({ confirm: true });
259
+
260
+ expect(result.discovered).toEqual([]);
261
+ expect(result.initialized).toBe(0);
262
+ });
263
+ });
264
+ });