@bernierllc/braingrid-cli-wrapper 0.1.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 (74) hide show
  1. package/.eslintrc.cjs +29 -0
  2. package/README.md +401 -0
  3. package/coverage/base.css +224 -0
  4. package/coverage/block-navigation.js +87 -0
  5. package/coverage/favicon.png +0 -0
  6. package/coverage/index.html +131 -0
  7. package/coverage/lcov-report/base.css +224 -0
  8. package/coverage/lcov-report/block-navigation.js +87 -0
  9. package/coverage/lcov-report/favicon.png +0 -0
  10. package/coverage/lcov-report/index.html +131 -0
  11. package/coverage/lcov-report/prettify.css +1 -0
  12. package/coverage/lcov-report/prettify.js +2 -0
  13. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  14. package/coverage/lcov-report/sorter.js +210 -0
  15. package/coverage/lcov-report/src/cli.ts.html +298 -0
  16. package/coverage/lcov-report/src/commands/createIdea.ts.html +193 -0
  17. package/coverage/lcov-report/src/commands/createTask.ts.html +235 -0
  18. package/coverage/lcov-report/src/commands/index.html +176 -0
  19. package/coverage/lcov-report/src/commands/listProjects.ts.html +160 -0
  20. package/coverage/lcov-report/src/commands/listTasks.ts.html +226 -0
  21. package/coverage/lcov-report/src/commands/updateTaskStatus.ts.html +205 -0
  22. package/coverage/lcov-report/src/index.html +146 -0
  23. package/coverage/lcov-report/src/index.ts.html +172 -0
  24. package/coverage/lcov-report/src/models.ts.html +364 -0
  25. package/coverage/lcov.info +240 -0
  26. package/coverage/prettify.css +1 -0
  27. package/coverage/prettify.js +2 -0
  28. package/coverage/sort-arrow-sprite.png +0 -0
  29. package/coverage/sorter.js +210 -0
  30. package/coverage/src/cli.ts.html +298 -0
  31. package/coverage/src/commands/createIdea.ts.html +193 -0
  32. package/coverage/src/commands/createTask.ts.html +235 -0
  33. package/coverage/src/commands/index.html +176 -0
  34. package/coverage/src/commands/listProjects.ts.html +160 -0
  35. package/coverage/src/commands/listTasks.ts.html +226 -0
  36. package/coverage/src/commands/updateTaskStatus.ts.html +205 -0
  37. package/coverage/src/index.html +146 -0
  38. package/coverage/src/index.ts.html +172 -0
  39. package/coverage/src/models.ts.html +364 -0
  40. package/dist/cli.d.ts +7 -0
  41. package/dist/cli.js +53 -0
  42. package/dist/commands/createIdea.d.ts +5 -0
  43. package/dist/commands/createIdea.js +29 -0
  44. package/dist/commands/createTask.d.ts +11 -0
  45. package/dist/commands/createTask.js +34 -0
  46. package/dist/commands/listProjects.d.ts +5 -0
  47. package/dist/commands/listProjects.js +24 -0
  48. package/dist/commands/listTasks.d.ts +10 -0
  49. package/dist/commands/listTasks.js +35 -0
  50. package/dist/commands/updateTaskStatus.d.ts +10 -0
  51. package/dist/commands/updateTaskStatus.js +27 -0
  52. package/dist/index.d.ts +6 -0
  53. package/dist/index.js +28 -0
  54. package/dist/models.d.ts +89 -0
  55. package/dist/models.js +74 -0
  56. package/jest.config.cjs +22 -0
  57. package/package.json +46 -0
  58. package/src/__tests__/execa-mock-validation.test.ts +34 -0
  59. package/src/cli.test.ts +86 -0
  60. package/src/cli.ts +71 -0
  61. package/src/commands/createIdea.test.ts +77 -0
  62. package/src/commands/createIdea.ts +36 -0
  63. package/src/commands/createTask.test.ts +100 -0
  64. package/src/commands/createTask.ts +50 -0
  65. package/src/commands/listProjects.test.ts +72 -0
  66. package/src/commands/listProjects.ts +25 -0
  67. package/src/commands/listTasks.test.ts +183 -0
  68. package/src/commands/listTasks.ts +47 -0
  69. package/src/commands/updateTaskStatus.test.ts +96 -0
  70. package/src/commands/updateTaskStatus.ts +40 -0
  71. package/src/index.ts +29 -0
  72. package/src/models.test.ts +197 -0
  73. package/src/models.ts +93 -0
  74. package/tsconfig.json +18 -0
package/.eslintrc.cjs ADDED
@@ -0,0 +1,29 @@
1
+ /*
2
+ Copyright (c) 2025 Bernier LLC
3
+
4
+ This file is licensed to the client under a limited-use license.
5
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
6
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
+ */
8
+
9
+ module.exports = {
10
+ parser: '@typescript-eslint/parser',
11
+ extends: [
12
+ 'eslint:recommended',
13
+ 'plugin:@typescript-eslint/recommended',
14
+ ],
15
+ parserOptions: {
16
+ ecmaVersion: 2020,
17
+ sourceType: 'module',
18
+ },
19
+ rules: {
20
+ '@typescript-eslint/no-explicit-any': 'warn',
21
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
22
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
23
+ },
24
+ env: {
25
+ node: true,
26
+ jest: true,
27
+ },
28
+ };
29
+
package/README.md ADDED
@@ -0,0 +1,401 @@
1
+ # @bernierllc/braingrid-cli-wrapper
2
+
3
+ Type-safe wrapper for the BrainGrid CLI that provides a clean, programmatic interface for interacting with BrainGrid projects, requirements, and tasks.
4
+
5
+ ## Overview
6
+
7
+ This package provides atomic utilities for interacting with the BrainGrid CLI in a type-safe manner. It wraps BrainGrid CLI commands with Zod schema validation, ensuring type safety and proper error handling.
8
+
9
+ ## Features
10
+
11
+ - **Type-safe API**: Full TypeScript support with Zod schema validation
12
+ - **Error Handling**: Custom error types with detailed error information
13
+ - **CLI Integration**: Seamless integration with BrainGrid CLI commands
14
+ - **Schema Validation**: Automatic validation of CLI responses using Zod schemas
15
+ - **Minimal Dependencies**: Only depends on `execa` and `zod`
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @bernierllc/braingrid-cli-wrapper
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```typescript
26
+ import { createIdea, listProjects, createTask } from '@bernierllc/braingrid-cli-wrapper';
27
+
28
+ // Create a new requirement (IDEA)
29
+ const requirement = await createIdea('Add OAuth2 authentication', 'proj-123');
30
+ console.log(`Created requirement ${requirement.id} with status ${requirement.status}`);
31
+
32
+ // List all projects
33
+ const projects = await listProjects();
34
+ console.log(`Found ${projects.length} projects`);
35
+
36
+ // Create a task under a requirement
37
+ const task = await createTask('req-456', {
38
+ title: 'Build login UI',
39
+ description: 'Create login form component',
40
+ tags: ['DEV', 'frontend'],
41
+ dependencies: ['task-100']
42
+ });
43
+ console.log(`Created task ${task.id}`);
44
+ ```
45
+
46
+ ## API Reference
47
+
48
+ ### Commands
49
+
50
+ #### `createIdea(prompt: string, projectId?: string): Promise<BrainGridRequirement>`
51
+
52
+ Creates a new requirement (IDEA) in BrainGrid.
53
+
54
+ **Input:**
55
+ - `prompt` (string, required): Description of the requirement/idea
56
+ - `projectId` (string, optional): Project ID to associate with the requirement
57
+
58
+ **Output:**
59
+ - Returns a `BrainGridRequirement` object with:
60
+ - `id`: Requirement ID
61
+ - `projectId`: Associated project ID
62
+ - `title`: Requirement title
63
+ - `status`: Requirement status (IDEA, PLANNED, IN_PROGRESS, COMPLETED, CANCELLED, PAUSED)
64
+ - `description`: Optional description
65
+ - `createdAt`: Optional creation timestamp
66
+ - `updatedAt`: Optional update timestamp
67
+
68
+ **Example:**
69
+ ```typescript
70
+ const req = await createIdea('Add user authentication system');
71
+ // { id: 'req-123', projectId: 'proj-456', title: 'Add user authentication system', status: 'IDEA' }
72
+ ```
73
+
74
+ #### `listProjects(): Promise<BrainGridProject[]>`
75
+
76
+ Lists all projects in BrainGrid.
77
+
78
+ **Input:** None
79
+
80
+ **Output:**
81
+ - Returns an array of `BrainGridProject` objects with:
82
+ - `id`: Project ID
83
+ - `name`: Project name
84
+ - `description`: Optional project description
85
+
86
+ **Example:**
87
+ ```typescript
88
+ const projects = await listProjects();
89
+ // [{ id: 'proj-1', name: 'My Project', description: 'Project description' }]
90
+ ```
91
+
92
+ #### `createTask(reqId: string, options: CreateTaskOptions): Promise<BrainGridTask>`
93
+
94
+ Creates a task under a requirement.
95
+
96
+ **Input:**
97
+ - `reqId` (string, required): Requirement ID
98
+ - `options` (CreateTaskOptions, required):
99
+ - `title` (string, required): Task title
100
+ - `description` (string, optional): Task description
101
+ - `tags` (string[], optional): Task tags
102
+ - `dependencies` (string[], optional): Task dependency IDs
103
+
104
+ **Output:**
105
+ - Returns a `BrainGridTask` object with:
106
+ - `id`: Task ID
107
+ - `reqId`: Parent requirement ID
108
+ - `title`: Task title
109
+ - `status`: Task status (TODO, READY, BLOCKED, IN_PROGRESS, COMPLETED, FAILED, PAUSED)
110
+ - `description`: Optional description
111
+ - `tags`: Optional array of tags
112
+ - `dependencies`: Optional array of dependency IDs
113
+ - `assignedTo`: Optional assignee ID
114
+ - `createdAt`: Optional creation timestamp
115
+ - `updatedAt`: Optional update timestamp
116
+ - `metadata`: Optional metadata object
117
+
118
+ **Example:**
119
+ ```typescript
120
+ const task = await createTask('req-123', {
121
+ title: 'Build login UI',
122
+ description: 'Create login form component',
123
+ tags: ['DEV', 'frontend'],
124
+ dependencies: ['task-100']
125
+ });
126
+ // { id: 'task-456', reqId: 'req-123', title: 'Build login UI', status: 'TODO', ... }
127
+ ```
128
+
129
+ #### `listTasks(options?: ListTasksOptions): Promise<BrainGridTask[]>`
130
+
131
+ Lists tasks with optional filters.
132
+
133
+ **Input:**
134
+ - `options` (ListTasksOptions, optional):
135
+ - `reqId` (string, optional): Filter by requirement ID
136
+ - `status` (TaskStatus[], optional): Filter by status array
137
+ - `tags` (string[], optional): Filter by tags array
138
+
139
+ **Output:**
140
+ - Returns an array of `BrainGridTask` objects
141
+
142
+ **Example:**
143
+ ```typescript
144
+ // List all tasks
145
+ const allTasks = await listTasks();
146
+
147
+ // List tasks for a specific requirement
148
+ const reqTasks = await listTasks({ reqId: 'req-123' });
149
+
150
+ // List tasks by status
151
+ const inProgressTasks = await listTasks({ status: ['IN_PROGRESS'] });
152
+
153
+ // Combine filters
154
+ const filteredTasks = await listTasks({
155
+ reqId: 'req-123',
156
+ status: ['TODO', 'READY'],
157
+ tags: ['DEV']
158
+ });
159
+ ```
160
+
161
+ #### `updateTaskStatus(taskId: string, options: UpdateTaskOptions): Promise<void>`
162
+
163
+ Updates task status and metadata.
164
+
165
+ **Input:**
166
+ - `taskId` (string, required): Task ID to update
167
+ - `options` (UpdateTaskOptions, optional):
168
+ - `status` (TaskStatus, optional): New task status
169
+ - `assignedTo` (string, optional): Assignee ID
170
+ - `metadata` (Record<string, unknown>, optional): Metadata object
171
+
172
+ **Output:** Promise that resolves when update is complete
173
+
174
+ **Example:**
175
+ ```typescript
176
+ // Update task status
177
+ await updateTaskStatus('task-123', { status: 'IN_PROGRESS' });
178
+
179
+ // Update with assignee
180
+ await updateTaskStatus('task-123', {
181
+ status: 'IN_PROGRESS',
182
+ assignedTo: 'user-456'
183
+ });
184
+
185
+ // Update with metadata
186
+ await updateTaskStatus('task-123', {
187
+ status: 'IN_PROGRESS',
188
+ metadata: { progress: 50, notes: 'Half done' }
189
+ });
190
+ ```
191
+
192
+ ### Types
193
+
194
+ #### `BrainGridProject`
195
+
196
+ ```typescript
197
+ interface BrainGridProject {
198
+ id: string;
199
+ name: string;
200
+ description?: string;
201
+ }
202
+ ```
203
+
204
+ #### `BrainGridRequirement`
205
+
206
+ ```typescript
207
+ interface BrainGridRequirement {
208
+ id: string;
209
+ projectId: string;
210
+ title: string;
211
+ status: RequirementStatus;
212
+ description?: string;
213
+ createdAt?: string;
214
+ updatedAt?: string;
215
+ }
216
+ ```
217
+
218
+ #### `BrainGridTask`
219
+
220
+ ```typescript
221
+ interface BrainGridTask {
222
+ id: string;
223
+ reqId: string;
224
+ title: string;
225
+ status: TaskStatus;
226
+ description?: string;
227
+ tags?: string[];
228
+ dependencies?: string[];
229
+ assignedTo?: string;
230
+ createdAt?: string;
231
+ updatedAt?: string;
232
+ metadata?: Record<string, unknown>;
233
+ }
234
+ ```
235
+
236
+ #### `RequirementStatus`
237
+
238
+ ```typescript
239
+ type RequirementStatus = 'IDEA' | 'PLANNED' | 'IN_PROGRESS' | 'COMPLETED' | 'CANCELLED' | 'PAUSED';
240
+ ```
241
+
242
+ #### `TaskStatus`
243
+
244
+ ```typescript
245
+ type TaskStatus = 'TODO' | 'READY' | 'BLOCKED' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED' | 'PAUSED';
246
+ ```
247
+
248
+ ### Error Handling
249
+
250
+ The package throws `BrainGridCliError` when CLI commands fail:
251
+
252
+ ```typescript
253
+ class BrainGridCliError extends Error {
254
+ command: string;
255
+ exitCode: number;
256
+ stderr: string;
257
+ }
258
+ ```
259
+
260
+ **Example:**
261
+ ```typescript
262
+ import { createIdea, BrainGridCliError } from '@bernierllc/braingrid-cli-wrapper';
263
+
264
+ try {
265
+ const req = await createIdea('Test requirement');
266
+ } catch (error) {
267
+ if (error instanceof BrainGridCliError) {
268
+ console.error(`CLI command failed: ${error.command}`);
269
+ console.error(`Exit code: ${error.exitCode}`);
270
+ console.error(`Error output: ${error.stderr}`);
271
+ }
272
+ }
273
+ ```
274
+
275
+ ## Configuration
276
+
277
+ ### Environment Variables
278
+
279
+ - `BRAINGRID_CLI_PATH`: Custom path to the BrainGrid CLI executable (defaults to `'braingrid'`)
280
+
281
+ **Example:**
282
+ ```bash
283
+ export BRAINGRID_CLI_PATH=/custom/path/braingrid
284
+ ```
285
+
286
+ ## Usage Examples
287
+
288
+ ### Complete Workflow
289
+
290
+ ```typescript
291
+ import {
292
+ listProjects,
293
+ createIdea,
294
+ createTask,
295
+ listTasks,
296
+ updateTaskStatus
297
+ } from '@bernierllc/braingrid-cli-wrapper';
298
+
299
+ async function workflow() {
300
+ // 1. List projects
301
+ const projects = await listProjects();
302
+ const project = projects[0];
303
+
304
+ // 2. Create a requirement
305
+ const requirement = await createIdea(
306
+ 'Build user authentication system',
307
+ project.id
308
+ );
309
+
310
+ // 3. Create tasks
311
+ const task1 = await createTask(requirement.id, {
312
+ title: 'Design authentication flow',
313
+ tags: ['DESIGN']
314
+ });
315
+
316
+ const task2 = await createTask(requirement.id, {
317
+ title: 'Implement login endpoint',
318
+ tags: ['DEV', 'backend'],
319
+ dependencies: [task1.id]
320
+ });
321
+
322
+ // 4. List tasks
323
+ const tasks = await listTasks({ reqId: requirement.id });
324
+ console.log(`Created ${tasks.length} tasks`);
325
+
326
+ // 5. Update task status
327
+ await updateTaskStatus(task1.id, { status: 'COMPLETED' });
328
+ await updateTaskStatus(task2.id, {
329
+ status: 'IN_PROGRESS',
330
+ assignedTo: 'user-123'
331
+ });
332
+ }
333
+ ```
334
+
335
+ ### Error Handling Example
336
+
337
+ ```typescript
338
+ import { createIdea, BrainGridCliError } from '@bernierllc/braingrid-cli-wrapper';
339
+
340
+ async function createRequirementSafely(prompt: string) {
341
+ try {
342
+ const req = await createIdea(prompt);
343
+ return req;
344
+ } catch (error) {
345
+ if (error instanceof BrainGridCliError) {
346
+ console.error(`BrainGrid CLI error: ${error.message}`);
347
+ console.error(`Command: ${error.command}`);
348
+ console.error(`Exit code: ${error.exitCode}`);
349
+ console.error(`Stderr: ${error.stderr}`);
350
+ throw new Error('Failed to create requirement');
351
+ }
352
+ throw error;
353
+ }
354
+ }
355
+ ```
356
+
357
+ ## Testing
358
+
359
+ ```bash
360
+ # Run tests
361
+ npm test
362
+
363
+ # Run tests with coverage
364
+ npm run test:coverage
365
+
366
+ # Run tests in watch mode
367
+ npm run test:watch
368
+ ```
369
+
370
+ ## Integration Status
371
+
372
+ ### Logger Integration
373
+ **Status**: not-applicable
374
+
375
+ This is a pure utility core package with no dependencies. Logging is handled by consuming packages. Does not require @bernierllc/logger integration.
376
+
377
+ ### Docs-Suite Integration
378
+ **Status**: ready
379
+
380
+ Complete API documentation with TypeScript types and examples available for documentation suite integration.
381
+
382
+ ### NeverHub Integration
383
+ **Status**: not-applicable
384
+
385
+ Pure utility package with no runtime dependencies. NeverHub integration is handled at the service-level packages that consume this utility. Does not require @bernierllc/neverhub-adapter integration.
386
+
387
+ ## Core Package Compliance
388
+
389
+ This package follows the core package rules:
390
+
391
+ - ✅ **Atomic functionality**: Single responsibility - wraps BrainGrid CLI
392
+ - ✅ **No internal dependencies**: Only depends on external packages (`execa`, `zod`)
393
+ - ✅ **Pure functions**: Explicit inputs/outputs with type safety
394
+ - ✅ **Full test coverage**: Comprehensive test suite for all commands
395
+ - ✅ **Single entrypoint**: All exports via `index.ts`
396
+ - ✅ **Strict typing**: TypeScript strict mode enabled, no implicit `any`
397
+ - ✅ **Documentation**: Complete README with purpose, usage, and examples
398
+
399
+ ## License
400
+
401
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,224 @@
1
+ body, html {
2
+ margin:0; padding: 0;
3
+ height: 100%;
4
+ }
5
+ body {
6
+ font-family: Helvetica Neue, Helvetica, Arial;
7
+ font-size: 14px;
8
+ color:#333;
9
+ }
10
+ .small { font-size: 12px; }
11
+ *, *:after, *:before {
12
+ -webkit-box-sizing:border-box;
13
+ -moz-box-sizing:border-box;
14
+ box-sizing:border-box;
15
+ }
16
+ h1 { font-size: 20px; margin: 0;}
17
+ h2 { font-size: 14px; }
18
+ pre {
19
+ font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
20
+ margin: 0;
21
+ padding: 0;
22
+ -moz-tab-size: 2;
23
+ -o-tab-size: 2;
24
+ tab-size: 2;
25
+ }
26
+ a { color:#0074D9; text-decoration:none; }
27
+ a:hover { text-decoration:underline; }
28
+ .strong { font-weight: bold; }
29
+ .space-top1 { padding: 10px 0 0 0; }
30
+ .pad2y { padding: 20px 0; }
31
+ .pad1y { padding: 10px 0; }
32
+ .pad2x { padding: 0 20px; }
33
+ .pad2 { padding: 20px; }
34
+ .pad1 { padding: 10px; }
35
+ .space-left2 { padding-left:55px; }
36
+ .space-right2 { padding-right:20px; }
37
+ .center { text-align:center; }
38
+ .clearfix { display:block; }
39
+ .clearfix:after {
40
+ content:'';
41
+ display:block;
42
+ height:0;
43
+ clear:both;
44
+ visibility:hidden;
45
+ }
46
+ .fl { float: left; }
47
+ @media only screen and (max-width:640px) {
48
+ .col3 { width:100%; max-width:100%; }
49
+ .hide-mobile { display:none!important; }
50
+ }
51
+
52
+ .quiet {
53
+ color: #7f7f7f;
54
+ color: rgba(0,0,0,0.5);
55
+ }
56
+ .quiet a { opacity: 0.7; }
57
+
58
+ .fraction {
59
+ font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
60
+ font-size: 10px;
61
+ color: #555;
62
+ background: #E8E8E8;
63
+ padding: 4px 5px;
64
+ border-radius: 3px;
65
+ vertical-align: middle;
66
+ }
67
+
68
+ div.path a:link, div.path a:visited { color: #333; }
69
+ table.coverage {
70
+ border-collapse: collapse;
71
+ margin: 10px 0 0 0;
72
+ padding: 0;
73
+ }
74
+
75
+ table.coverage td {
76
+ margin: 0;
77
+ padding: 0;
78
+ vertical-align: top;
79
+ }
80
+ table.coverage td.line-count {
81
+ text-align: right;
82
+ padding: 0 5px 0 20px;
83
+ }
84
+ table.coverage td.line-coverage {
85
+ text-align: right;
86
+ padding-right: 10px;
87
+ min-width:20px;
88
+ }
89
+
90
+ table.coverage td span.cline-any {
91
+ display: inline-block;
92
+ padding: 0 5px;
93
+ width: 100%;
94
+ }
95
+ .missing-if-branch {
96
+ display: inline-block;
97
+ margin-right: 5px;
98
+ border-radius: 3px;
99
+ position: relative;
100
+ padding: 0 4px;
101
+ background: #333;
102
+ color: yellow;
103
+ }
104
+
105
+ .skip-if-branch {
106
+ display: none;
107
+ margin-right: 10px;
108
+ position: relative;
109
+ padding: 0 4px;
110
+ background: #ccc;
111
+ color: white;
112
+ }
113
+ .missing-if-branch .typ, .skip-if-branch .typ {
114
+ color: inherit !important;
115
+ }
116
+ .coverage-summary {
117
+ border-collapse: collapse;
118
+ width: 100%;
119
+ }
120
+ .coverage-summary tr { border-bottom: 1px solid #bbb; }
121
+ .keyline-all { border: 1px solid #ddd; }
122
+ .coverage-summary td, .coverage-summary th { padding: 10px; }
123
+ .coverage-summary tbody { border: 1px solid #bbb; }
124
+ .coverage-summary td { border-right: 1px solid #bbb; }
125
+ .coverage-summary td:last-child { border-right: none; }
126
+ .coverage-summary th {
127
+ text-align: left;
128
+ font-weight: normal;
129
+ white-space: nowrap;
130
+ }
131
+ .coverage-summary th.file { border-right: none !important; }
132
+ .coverage-summary th.pct { }
133
+ .coverage-summary th.pic,
134
+ .coverage-summary th.abs,
135
+ .coverage-summary td.pct,
136
+ .coverage-summary td.abs { text-align: right; }
137
+ .coverage-summary td.file { white-space: nowrap; }
138
+ .coverage-summary td.pic { min-width: 120px !important; }
139
+ .coverage-summary tfoot td { }
140
+
141
+ .coverage-summary .sorter {
142
+ height: 10px;
143
+ width: 7px;
144
+ display: inline-block;
145
+ margin-left: 0.5em;
146
+ background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
147
+ }
148
+ .coverage-summary .sorted .sorter {
149
+ background-position: 0 -20px;
150
+ }
151
+ .coverage-summary .sorted-desc .sorter {
152
+ background-position: 0 -10px;
153
+ }
154
+ .status-line { height: 10px; }
155
+ /* yellow */
156
+ .cbranch-no { background: yellow !important; color: #111; }
157
+ /* dark red */
158
+ .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
159
+ .low .chart { border:1px solid #C21F39 }
160
+ .highlighted,
161
+ .highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
162
+ background: #C21F39 !important;
163
+ }
164
+ /* medium red */
165
+ .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
166
+ /* light red */
167
+ .low, .cline-no { background:#FCE1E5 }
168
+ /* light green */
169
+ .high, .cline-yes { background:rgb(230,245,208) }
170
+ /* medium green */
171
+ .cstat-yes { background:rgb(161,215,106) }
172
+ /* dark green */
173
+ .status-line.high, .high .cover-fill { background:rgb(77,146,33) }
174
+ .high .chart { border:1px solid rgb(77,146,33) }
175
+ /* dark yellow (gold) */
176
+ .status-line.medium, .medium .cover-fill { background: #f9cd0b; }
177
+ .medium .chart { border:1px solid #f9cd0b; }
178
+ /* light yellow */
179
+ .medium { background: #fff4c2; }
180
+
181
+ .cstat-skip { background: #ddd; color: #111; }
182
+ .fstat-skip { background: #ddd; color: #111 !important; }
183
+ .cbranch-skip { background: #ddd !important; color: #111; }
184
+
185
+ span.cline-neutral { background: #eaeaea; }
186
+
187
+ .coverage-summary td.empty {
188
+ opacity: .5;
189
+ padding-top: 4px;
190
+ padding-bottom: 4px;
191
+ line-height: 1;
192
+ color: #888;
193
+ }
194
+
195
+ .cover-fill, .cover-empty {
196
+ display:inline-block;
197
+ height: 12px;
198
+ }
199
+ .chart {
200
+ line-height: 0;
201
+ }
202
+ .cover-empty {
203
+ background: white;
204
+ }
205
+ .cover-full {
206
+ border-right: none !important;
207
+ }
208
+ pre.prettyprint {
209
+ border: none !important;
210
+ padding: 0 !important;
211
+ margin: 0 !important;
212
+ }
213
+ .com { color: #999 !important; }
214
+ .ignore-none { color: #999; font-weight: normal; }
215
+
216
+ .wrapper {
217
+ min-height: 100%;
218
+ height: auto !important;
219
+ height: 100%;
220
+ margin: 0 auto -48px;
221
+ }
222
+ .footer, .push {
223
+ height: 48px;
224
+ }