codebase-snapshot 0.9.9 → 0.9.14

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/dist/cli.d.cts CHANGED
@@ -1,6 +1,229 @@
1
- import { O as OutputFormat, D as DiscoveryMode } from './types-Ca4PmkiQ.cjs';
1
+ import { O as OutputFormat, D as DiscoveryMode, R as ResolvedSnapshotConfig } from './types-DIX6zWSt.cjs';
2
+
3
+ /**
4
+ * The machine-readable description of this tool.
5
+ *
6
+ * Everything an agent needs to use the tool without prior knowledge lives here:
7
+ * the invocation that works, the ordered workflow, the full option table with
8
+ * defaults, the exit-code contract, the presets, the artifacts, the config file
9
+ * names and the output layout. It exists because `--help` is prose written for a
10
+ * human, and an agent with no context cannot reliably parse prose.
11
+ *
12
+ * `codebase-snapshot describe --format json` prints this. Keep it in sync with the CLI — the
13
+ * test suite asserts that the defaults here match `resolveConfig`'s defaults, so
14
+ * drift fails the build rather than misleading an agent.
15
+ */
16
+ interface AgentContract {
17
+ generator: string;
18
+ package: string;
19
+ version: string;
20
+ schemaVersion: string;
21
+ contractVersion: string;
22
+ summary: string;
23
+ requires: {
24
+ node: string;
25
+ dependencies: string[];
26
+ };
27
+ invocation: {
28
+ oneShot: string;
29
+ installed: string;
30
+ bins: string[];
31
+ notes: string[];
32
+ };
33
+ workflow: Array<{
34
+ step: number;
35
+ id: string;
36
+ run: string;
37
+ expect: string;
38
+ notes?: string;
39
+ }>;
40
+ commands: Array<{
41
+ name: string;
42
+ aliases: string[];
43
+ summary: string;
44
+ positionals: string[];
45
+ exits: number[];
46
+ }>;
47
+ exitCodes: Record<string, string>;
48
+ options: Array<{
49
+ flag: string;
50
+ type: "string" | "boolean";
51
+ default?: string | number | boolean;
52
+ appliesTo: string;
53
+ summary: string;
54
+ }>;
55
+ presets: Array<{
56
+ name: string;
57
+ priority: number;
58
+ recommendedBudget: string | number;
59
+ excludes: string[];
60
+ }>;
61
+ artifacts: Array<{
62
+ name: string;
63
+ default: boolean;
64
+ summary: string;
65
+ }>;
66
+ config: {
67
+ fileNames: string[];
68
+ settings: Array<{
69
+ key: string;
70
+ type: string;
71
+ default: string | number | boolean | null;
72
+ summary: string;
73
+ }>;
74
+ };
75
+ output: {
76
+ layout: string[];
77
+ notes: string[];
78
+ };
79
+ safety: string[];
80
+ troubleshooting: Array<{
81
+ symptom: string;
82
+ cause: string;
83
+ fix: string;
84
+ }>;
85
+ /**
86
+ * The MCP server, described from the same objects the server serves.
87
+ *
88
+ * This block exists so an agent that has only ever run `describe` learns the server exists, and
89
+ * a test compares it against a live `tools/list` so the two cannot describe different tools.
90
+ */
91
+ mcp: {
92
+ command: string;
93
+ transport: "stdio";
94
+ protocolVersions: {
95
+ modern: string[];
96
+ legacy: string[];
97
+ default: string;
98
+ };
99
+ tools: Array<{
100
+ name: string;
101
+ title: string;
102
+ summary: string;
103
+ readOnly: boolean;
104
+ parameters: string[];
105
+ required: string[];
106
+ }>;
107
+ prompts: Array<{
108
+ name: string;
109
+ summary: string;
110
+ arguments: string[];
111
+ }>;
112
+ resources: string[];
113
+ resourceTemplates: string[];
114
+ notes: string[];
115
+ };
116
+ }
117
+ /** Builds the contract document. Cheap enough to call on every `describe`. */
118
+ declare function buildAgentContract(): AgentContract;
2
119
 
3
120
  type Command = "generate" | "validate" | "report" | "init" | "setup" | "explain" | "diff" | "describe" | "skill" | "mcp";
121
+ declare const CLI_OPTIONS: {
122
+ readonly cwd: {
123
+ readonly type: "string";
124
+ };
125
+ readonly "out-dir": {
126
+ readonly type: "string";
127
+ };
128
+ readonly "max-part-bytes": {
129
+ readonly type: "string";
130
+ };
131
+ readonly "large-file-bytes": {
132
+ readonly type: "string";
133
+ };
134
+ readonly "max-monolith-bytes": {
135
+ readonly type: "string";
136
+ };
137
+ readonly "include-monolith": {
138
+ readonly type: "boolean";
139
+ };
140
+ readonly "include-sensitive-files": {
141
+ readonly type: "boolean";
142
+ };
143
+ readonly "skip-artifacts": {
144
+ readonly type: "string";
145
+ };
146
+ readonly "only-artifacts": {
147
+ readonly type: "string";
148
+ };
149
+ readonly format: {
150
+ readonly type: "string";
151
+ };
152
+ readonly mode: {
153
+ readonly type: "string";
154
+ };
155
+ readonly "dry-run": {
156
+ readonly type: "boolean";
157
+ };
158
+ readonly watch: {
159
+ readonly type: "boolean";
160
+ };
161
+ readonly "no-config": {
162
+ readonly type: "boolean";
163
+ };
164
+ readonly discovery: {
165
+ readonly type: "string";
166
+ };
167
+ readonly "max-part-tokens": {
168
+ readonly type: "string";
169
+ };
170
+ readonly preset: {
171
+ readonly type: "string";
172
+ };
173
+ readonly include: {
174
+ readonly type: "string";
175
+ };
176
+ readonly exclude: {
177
+ readonly type: "string";
178
+ };
179
+ readonly yes: {
180
+ readonly type: "boolean";
181
+ };
182
+ readonly force: {
183
+ readonly type: "boolean";
184
+ };
185
+ readonly autopilot: {
186
+ readonly type: "boolean";
187
+ };
188
+ readonly install: {
189
+ readonly type: "boolean";
190
+ };
191
+ readonly "no-install": {
192
+ readonly type: "boolean";
193
+ };
194
+ readonly target: {
195
+ readonly type: "string";
196
+ };
197
+ readonly "no-update-check": {
198
+ readonly type: "boolean";
199
+ };
200
+ readonly "install-hook": {
201
+ readonly type: "boolean";
202
+ };
203
+ readonly "changed-since": {
204
+ readonly type: "string";
205
+ };
206
+ readonly "with-dependents": {
207
+ readonly type: "boolean";
208
+ };
209
+ readonly staged: {
210
+ readonly type: "boolean";
211
+ };
212
+ readonly skeleton: {
213
+ readonly type: "boolean";
214
+ };
215
+ readonly sarif: {
216
+ readonly type: "boolean";
217
+ };
218
+ readonly help: {
219
+ readonly type: "boolean";
220
+ readonly short: "h";
221
+ };
222
+ readonly version: {
223
+ readonly type: "boolean";
224
+ readonly short: "v";
225
+ };
226
+ };
4
227
  /** A user-input problem: printed without a stack trace, exits 2. */
5
228
  declare class UsageError extends Error {
6
229
  }
@@ -41,18 +264,44 @@ interface ParsedInvocation {
41
264
  includeMonolith?: boolean;
42
265
  includeSensitiveFiles?: boolean;
43
266
  maxPartBytes?: number;
267
+ /** A per-part ceiling in tokens; resolved into `maxPartBytes` by `resolveConfig`. */
268
+ maxPartTokens?: number;
44
269
  largeFileBytes?: number;
45
270
  maxMonolithBytes?: number | null;
46
271
  skipArtifacts?: string[];
272
+ /**
273
+ * The artifacts named by `--only-artifacts`, kept separately from the derived
274
+ * `skipArtifacts`.
275
+ *
276
+ * `--only-artifacts monolith` means "the six others off, the monolith on", which cannot
277
+ * be expressed by `skipArtifacts` alone: the monolith is off by default, so turning the
278
+ * others off left *everything* off and `init`/`setup` wrote a config that generated
279
+ * nothing. The wizard resolves this list itself.
280
+ */
281
+ onlyArtifacts?: string[];
47
282
  /** How candidates are discovered; `auto` when unset. */
48
283
  discovery?: DiscoveryMode;
284
+ /** The user asked not to be told about newer releases. */
285
+ noUpdateCheck?: boolean;
286
+ /** `init` and `setup` only: write a pre-commit hook that gates on `validate`. */
287
+ installHook?: boolean;
288
+ /** Only files changed since this git ref. */
289
+ changedSince?: string;
290
+ /** Only files staged for the next commit. */
291
+ staged?: boolean;
292
+ /** With the two above: also include the files that import a changed one. */
293
+ withDependents?: boolean;
294
+ /** Emit signatures instead of bodies for TypeScript and TSX. */
295
+ skeleton?: boolean;
296
+ /** Also write reports/audit.sarif for a CI security gate. */
297
+ sarif?: boolean;
49
298
  }
50
299
  declare function parsePositiveInteger(raw: string | undefined, optionName: string, minimum: number): number | undefined;
51
300
  /**
52
301
  * Parses a byte-budget option, accepting human-readable units (`120k`, `1.5mb`)
53
302
  * as well as raw byte counts.
54
303
  */
55
- declare function parseByteOption(raw: string | undefined, optionName: string, minimum: number): number | undefined;
304
+ declare function parseByteOption(raw: string | undefined, optionName: string, minimum: number, unit?: string): number | undefined;
56
305
  /**
57
306
  * Parses argv.
58
307
  *
@@ -136,5 +385,35 @@ declare function isGeneratedWatchPath(candidate: string, paths: WatchPaths): boo
136
385
  * because Windows does not always name the path our own writes produced.
137
386
  */
138
387
  declare function decideWatchEvent(state: WatchState, event: WatchEvent, paths: WatchPaths): WatchDecision;
388
+ /**
389
+ * Re-generates on every change under `cwd`.
390
+ *
391
+ * Events inside the resolved output and temporary directories are ignored, so
392
+ * writing a snapshot cannot feed the watcher. A source event that arrives while
393
+ * a run is in flight sets a pending flag and gets exactly one follow-up run;
394
+ * the settle window only suppresses unattributed events.
395
+ */
396
+ /**
397
+ * The directories the watcher must ignore, derived from a resolved config.
398
+ *
399
+ * A function rather than an inline literal because the loop now recomputes it after every config
400
+ * reload: a watcher that keeps the `outDir` it started with treats the new one as user content,
401
+ * regenerates, writes, sees that write, and never settles.
402
+ */
403
+ declare function watchPathsFor(config: ResolvedSnapshotConfig): WatchPaths;
404
+ /**
405
+ * Why `--watch` cannot work here, or `null` when it can.
406
+ *
407
+ * `fs.watch(dir, { recursive: true })` is only available on Linux from Node 20.13: before that it
408
+ * throws `ERR_FEATURE_UNAVAILABLE_ON_PLATFORM`. The package declares `engines: >=18`, so a user can
409
+ * legitimately be running a Node that cannot honour this flag — and what they got was an uncaught
410
+ * exception *after* the first snapshot had been written and "Watching for changes" printed, which
411
+ * reads as a broken tool rather than as a version requirement.
412
+ *
413
+ * The platform and version are parameters so the boundary is testable off the machine that happens
414
+ * to run the tests: this is the kind of check that is written on one OS and shipped broken to
415
+ * another, which is precisely how it went unnoticed.
416
+ */
417
+ declare function watchSupportProblem(platform?: string, version?: string): string | null;
139
418
 
140
- export { UsageError, WATCH_DEBOUNCE_MS, WATCH_SETTLE_MS, type WatchAction, type WatchDecision, type WatchEvent, type WatchPaths, type WatchState, beginWatchRun, cleanInstallEnv, decideWatchEvent, finishWatchRun, initialWatchState, isGeneratedWatchPath, main, parseByteOption, parseCliArgs, parsePositiveInteger };
419
+ export { CLI_OPTIONS, UsageError, WATCH_DEBOUNCE_MS, WATCH_SETTLE_MS, type WatchAction, type WatchDecision, type WatchEvent, type WatchPaths, type WatchState, beginWatchRun, buildAgentContract, cleanInstallEnv, decideWatchEvent, finishWatchRun, initialWatchState, isGeneratedWatchPath, main, parseByteOption, parseCliArgs, parsePositiveInteger, watchPathsFor, watchSupportProblem };
package/dist/cli.d.ts CHANGED
@@ -1,6 +1,229 @@
1
- import { O as OutputFormat, D as DiscoveryMode } from './types-Ca4PmkiQ.js';
1
+ import { O as OutputFormat, D as DiscoveryMode, R as ResolvedSnapshotConfig } from './types-DIX6zWSt.js';
2
+
3
+ /**
4
+ * The machine-readable description of this tool.
5
+ *
6
+ * Everything an agent needs to use the tool without prior knowledge lives here:
7
+ * the invocation that works, the ordered workflow, the full option table with
8
+ * defaults, the exit-code contract, the presets, the artifacts, the config file
9
+ * names and the output layout. It exists because `--help` is prose written for a
10
+ * human, and an agent with no context cannot reliably parse prose.
11
+ *
12
+ * `codebase-snapshot describe --format json` prints this. Keep it in sync with the CLI — the
13
+ * test suite asserts that the defaults here match `resolveConfig`'s defaults, so
14
+ * drift fails the build rather than misleading an agent.
15
+ */
16
+ interface AgentContract {
17
+ generator: string;
18
+ package: string;
19
+ version: string;
20
+ schemaVersion: string;
21
+ contractVersion: string;
22
+ summary: string;
23
+ requires: {
24
+ node: string;
25
+ dependencies: string[];
26
+ };
27
+ invocation: {
28
+ oneShot: string;
29
+ installed: string;
30
+ bins: string[];
31
+ notes: string[];
32
+ };
33
+ workflow: Array<{
34
+ step: number;
35
+ id: string;
36
+ run: string;
37
+ expect: string;
38
+ notes?: string;
39
+ }>;
40
+ commands: Array<{
41
+ name: string;
42
+ aliases: string[];
43
+ summary: string;
44
+ positionals: string[];
45
+ exits: number[];
46
+ }>;
47
+ exitCodes: Record<string, string>;
48
+ options: Array<{
49
+ flag: string;
50
+ type: "string" | "boolean";
51
+ default?: string | number | boolean;
52
+ appliesTo: string;
53
+ summary: string;
54
+ }>;
55
+ presets: Array<{
56
+ name: string;
57
+ priority: number;
58
+ recommendedBudget: string | number;
59
+ excludes: string[];
60
+ }>;
61
+ artifacts: Array<{
62
+ name: string;
63
+ default: boolean;
64
+ summary: string;
65
+ }>;
66
+ config: {
67
+ fileNames: string[];
68
+ settings: Array<{
69
+ key: string;
70
+ type: string;
71
+ default: string | number | boolean | null;
72
+ summary: string;
73
+ }>;
74
+ };
75
+ output: {
76
+ layout: string[];
77
+ notes: string[];
78
+ };
79
+ safety: string[];
80
+ troubleshooting: Array<{
81
+ symptom: string;
82
+ cause: string;
83
+ fix: string;
84
+ }>;
85
+ /**
86
+ * The MCP server, described from the same objects the server serves.
87
+ *
88
+ * This block exists so an agent that has only ever run `describe` learns the server exists, and
89
+ * a test compares it against a live `tools/list` so the two cannot describe different tools.
90
+ */
91
+ mcp: {
92
+ command: string;
93
+ transport: "stdio";
94
+ protocolVersions: {
95
+ modern: string[];
96
+ legacy: string[];
97
+ default: string;
98
+ };
99
+ tools: Array<{
100
+ name: string;
101
+ title: string;
102
+ summary: string;
103
+ readOnly: boolean;
104
+ parameters: string[];
105
+ required: string[];
106
+ }>;
107
+ prompts: Array<{
108
+ name: string;
109
+ summary: string;
110
+ arguments: string[];
111
+ }>;
112
+ resources: string[];
113
+ resourceTemplates: string[];
114
+ notes: string[];
115
+ };
116
+ }
117
+ /** Builds the contract document. Cheap enough to call on every `describe`. */
118
+ declare function buildAgentContract(): AgentContract;
2
119
 
3
120
  type Command = "generate" | "validate" | "report" | "init" | "setup" | "explain" | "diff" | "describe" | "skill" | "mcp";
121
+ declare const CLI_OPTIONS: {
122
+ readonly cwd: {
123
+ readonly type: "string";
124
+ };
125
+ readonly "out-dir": {
126
+ readonly type: "string";
127
+ };
128
+ readonly "max-part-bytes": {
129
+ readonly type: "string";
130
+ };
131
+ readonly "large-file-bytes": {
132
+ readonly type: "string";
133
+ };
134
+ readonly "max-monolith-bytes": {
135
+ readonly type: "string";
136
+ };
137
+ readonly "include-monolith": {
138
+ readonly type: "boolean";
139
+ };
140
+ readonly "include-sensitive-files": {
141
+ readonly type: "boolean";
142
+ };
143
+ readonly "skip-artifacts": {
144
+ readonly type: "string";
145
+ };
146
+ readonly "only-artifacts": {
147
+ readonly type: "string";
148
+ };
149
+ readonly format: {
150
+ readonly type: "string";
151
+ };
152
+ readonly mode: {
153
+ readonly type: "string";
154
+ };
155
+ readonly "dry-run": {
156
+ readonly type: "boolean";
157
+ };
158
+ readonly watch: {
159
+ readonly type: "boolean";
160
+ };
161
+ readonly "no-config": {
162
+ readonly type: "boolean";
163
+ };
164
+ readonly discovery: {
165
+ readonly type: "string";
166
+ };
167
+ readonly "max-part-tokens": {
168
+ readonly type: "string";
169
+ };
170
+ readonly preset: {
171
+ readonly type: "string";
172
+ };
173
+ readonly include: {
174
+ readonly type: "string";
175
+ };
176
+ readonly exclude: {
177
+ readonly type: "string";
178
+ };
179
+ readonly yes: {
180
+ readonly type: "boolean";
181
+ };
182
+ readonly force: {
183
+ readonly type: "boolean";
184
+ };
185
+ readonly autopilot: {
186
+ readonly type: "boolean";
187
+ };
188
+ readonly install: {
189
+ readonly type: "boolean";
190
+ };
191
+ readonly "no-install": {
192
+ readonly type: "boolean";
193
+ };
194
+ readonly target: {
195
+ readonly type: "string";
196
+ };
197
+ readonly "no-update-check": {
198
+ readonly type: "boolean";
199
+ };
200
+ readonly "install-hook": {
201
+ readonly type: "boolean";
202
+ };
203
+ readonly "changed-since": {
204
+ readonly type: "string";
205
+ };
206
+ readonly "with-dependents": {
207
+ readonly type: "boolean";
208
+ };
209
+ readonly staged: {
210
+ readonly type: "boolean";
211
+ };
212
+ readonly skeleton: {
213
+ readonly type: "boolean";
214
+ };
215
+ readonly sarif: {
216
+ readonly type: "boolean";
217
+ };
218
+ readonly help: {
219
+ readonly type: "boolean";
220
+ readonly short: "h";
221
+ };
222
+ readonly version: {
223
+ readonly type: "boolean";
224
+ readonly short: "v";
225
+ };
226
+ };
4
227
  /** A user-input problem: printed without a stack trace, exits 2. */
5
228
  declare class UsageError extends Error {
6
229
  }
@@ -41,18 +264,44 @@ interface ParsedInvocation {
41
264
  includeMonolith?: boolean;
42
265
  includeSensitiveFiles?: boolean;
43
266
  maxPartBytes?: number;
267
+ /** A per-part ceiling in tokens; resolved into `maxPartBytes` by `resolveConfig`. */
268
+ maxPartTokens?: number;
44
269
  largeFileBytes?: number;
45
270
  maxMonolithBytes?: number | null;
46
271
  skipArtifacts?: string[];
272
+ /**
273
+ * The artifacts named by `--only-artifacts`, kept separately from the derived
274
+ * `skipArtifacts`.
275
+ *
276
+ * `--only-artifacts monolith` means "the six others off, the monolith on", which cannot
277
+ * be expressed by `skipArtifacts` alone: the monolith is off by default, so turning the
278
+ * others off left *everything* off and `init`/`setup` wrote a config that generated
279
+ * nothing. The wizard resolves this list itself.
280
+ */
281
+ onlyArtifacts?: string[];
47
282
  /** How candidates are discovered; `auto` when unset. */
48
283
  discovery?: DiscoveryMode;
284
+ /** The user asked not to be told about newer releases. */
285
+ noUpdateCheck?: boolean;
286
+ /** `init` and `setup` only: write a pre-commit hook that gates on `validate`. */
287
+ installHook?: boolean;
288
+ /** Only files changed since this git ref. */
289
+ changedSince?: string;
290
+ /** Only files staged for the next commit. */
291
+ staged?: boolean;
292
+ /** With the two above: also include the files that import a changed one. */
293
+ withDependents?: boolean;
294
+ /** Emit signatures instead of bodies for TypeScript and TSX. */
295
+ skeleton?: boolean;
296
+ /** Also write reports/audit.sarif for a CI security gate. */
297
+ sarif?: boolean;
49
298
  }
50
299
  declare function parsePositiveInteger(raw: string | undefined, optionName: string, minimum: number): number | undefined;
51
300
  /**
52
301
  * Parses a byte-budget option, accepting human-readable units (`120k`, `1.5mb`)
53
302
  * as well as raw byte counts.
54
303
  */
55
- declare function parseByteOption(raw: string | undefined, optionName: string, minimum: number): number | undefined;
304
+ declare function parseByteOption(raw: string | undefined, optionName: string, minimum: number, unit?: string): number | undefined;
56
305
  /**
57
306
  * Parses argv.
58
307
  *
@@ -136,5 +385,35 @@ declare function isGeneratedWatchPath(candidate: string, paths: WatchPaths): boo
136
385
  * because Windows does not always name the path our own writes produced.
137
386
  */
138
387
  declare function decideWatchEvent(state: WatchState, event: WatchEvent, paths: WatchPaths): WatchDecision;
388
+ /**
389
+ * Re-generates on every change under `cwd`.
390
+ *
391
+ * Events inside the resolved output and temporary directories are ignored, so
392
+ * writing a snapshot cannot feed the watcher. A source event that arrives while
393
+ * a run is in flight sets a pending flag and gets exactly one follow-up run;
394
+ * the settle window only suppresses unattributed events.
395
+ */
396
+ /**
397
+ * The directories the watcher must ignore, derived from a resolved config.
398
+ *
399
+ * A function rather than an inline literal because the loop now recomputes it after every config
400
+ * reload: a watcher that keeps the `outDir` it started with treats the new one as user content,
401
+ * regenerates, writes, sees that write, and never settles.
402
+ */
403
+ declare function watchPathsFor(config: ResolvedSnapshotConfig): WatchPaths;
404
+ /**
405
+ * Why `--watch` cannot work here, or `null` when it can.
406
+ *
407
+ * `fs.watch(dir, { recursive: true })` is only available on Linux from Node 20.13: before that it
408
+ * throws `ERR_FEATURE_UNAVAILABLE_ON_PLATFORM`. The package declares `engines: >=18`, so a user can
409
+ * legitimately be running a Node that cannot honour this flag — and what they got was an uncaught
410
+ * exception *after* the first snapshot had been written and "Watching for changes" printed, which
411
+ * reads as a broken tool rather than as a version requirement.
412
+ *
413
+ * The platform and version are parameters so the boundary is testable off the machine that happens
414
+ * to run the tests: this is the kind of check that is written on one OS and shipped broken to
415
+ * another, which is precisely how it went unnoticed.
416
+ */
417
+ declare function watchSupportProblem(platform?: string, version?: string): string | null;
139
418
 
140
- export { UsageError, WATCH_DEBOUNCE_MS, WATCH_SETTLE_MS, type WatchAction, type WatchDecision, type WatchEvent, type WatchPaths, type WatchState, beginWatchRun, cleanInstallEnv, decideWatchEvent, finishWatchRun, initialWatchState, isGeneratedWatchPath, main, parseByteOption, parseCliArgs, parsePositiveInteger };
419
+ export { CLI_OPTIONS, UsageError, WATCH_DEBOUNCE_MS, WATCH_SETTLE_MS, type WatchAction, type WatchDecision, type WatchEvent, type WatchPaths, type WatchState, beginWatchRun, buildAgentContract, cleanInstallEnv, decideWatchEvent, finishWatchRun, initialWatchState, isGeneratedWatchPath, main, parseByteOption, parseCliArgs, parsePositiveInteger, watchPathsFor, watchSupportProblem };