@eddacraft/anvil-aps 0.1.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.
- package/AGENTS.md +155 -0
- package/LICENSE +14 -0
- package/README.md +57 -0
- package/TODO.md +40 -0
- package/dist/filter/context-bundle.d.ts +81 -0
- package/dist/filter/context-bundle.d.ts.map +1 -0
- package/dist/filter/context-bundle.js +230 -0
- package/dist/filter/index.d.ts +85 -0
- package/dist/filter/index.d.ts.map +1 -0
- package/dist/filter/index.js +169 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/loader/index.d.ts +80 -0
- package/dist/loader/index.d.ts.map +1 -0
- package/dist/loader/index.js +253 -0
- package/dist/parser/index.d.ts +24 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +22 -0
- package/dist/parser/parse-document.d.ts +17 -0
- package/dist/parser/parse-document.d.ts.map +1 -0
- package/dist/parser/parse-document.js +219 -0
- package/dist/parser/parse-index.d.ts +31 -0
- package/dist/parser/parse-index.d.ts.map +1 -0
- package/dist/parser/parse-index.js +251 -0
- package/dist/parser/parse-task.d.ts +30 -0
- package/dist/parser/parse-task.d.ts.map +1 -0
- package/dist/parser/parse-task.js +261 -0
- package/dist/state/index.d.ts +307 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +689 -0
- package/dist/templates/generator.d.ts +71 -0
- package/dist/templates/generator.d.ts.map +1 -0
- package/dist/templates/generator.js +723 -0
- package/dist/templates/index.d.ts +5 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +4 -0
- package/dist/types/index.d.ts +131 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +107 -0
- package/dist/validator/index.d.ts +83 -0
- package/dist/validator/index.d.ts.map +1 -0
- package/dist/validator/index.js +611 -0
- package/docs/APS-Anvil-Integration.md +750 -0
- package/docs/APS-Conventions.md +635 -0
- package/docs/APS-NonGoals.md +455 -0
- package/docs/APS-Planning-Spec-v0.1.md +362 -0
- package/examples/README.md +170 -0
- package/examples/feature-auth.aps.md +87 -0
- package/examples/refactor-error-handling.aps.md +119 -0
- package/examples/system-ecommerce/APS.md +57 -0
- package/examples/system-ecommerce/modules/auth.aps.md +38 -0
- package/examples/system-ecommerce/modules/cart.aps.md +53 -0
- package/examples/system-ecommerce/modules/payments.aps.md +68 -0
- package/examples/system-ecommerce/modules/products.aps.md +53 -0
- package/package.json +34 -0
- package/project.json +37 -0
- package/scripts/generate-templates.js +33 -0
- package/src/filter/context-bundle.ts +312 -0
- package/src/filter/filter.test.ts +317 -0
- package/src/filter/index.ts +249 -0
- package/src/index.ts +16 -0
- package/src/loader/index.ts +364 -0
- package/src/loader/loader.test.ts +224 -0
- package/src/parser/__fixtures__/invalid-task-id-not-padded.aps.md +7 -0
- package/src/parser/__fixtures__/invalid-task-id.aps.md +8 -0
- package/src/parser/__fixtures__/minimal-task.aps.md +7 -0
- package/src/parser/__fixtures__/non-scope-hyphenated.aps.md +10 -0
- package/src/parser/__fixtures__/simple-index.aps.md +35 -0
- package/src/parser/__fixtures__/simple-plan.aps.md +19 -0
- package/src/parser/index.ts +30 -0
- package/src/parser/parse-document.test.ts +603 -0
- package/src/parser/parse-document.ts +262 -0
- package/src/parser/parse-index.test.ts +316 -0
- package/src/parser/parse-index.ts +298 -0
- package/src/parser/parse-task.test.ts +476 -0
- package/src/parser/parse-task.ts +325 -0
- package/src/state/__fixtures__/invalid-plan.aps.md +9 -0
- package/src/state/__fixtures__/test-plan.aps.md +20 -0
- package/src/state/index.ts +879 -0
- package/src/state/state.test.ts +645 -0
- package/src/templates/generator.test.ts +378 -0
- package/src/templates/generator.ts +776 -0
- package/src/templates/index.ts +5 -0
- package/src/types/index.ts +168 -0
- package/src/validator/__fixtures__/broken-links.aps.md +10 -0
- package/src/validator/__fixtures__/circular-deps-index.aps.md +26 -0
- package/src/validator/__fixtures__/circular-modules/module-a.aps.md +9 -0
- package/src/validator/__fixtures__/circular-modules/module-b.aps.md +9 -0
- package/src/validator/__fixtures__/circular-modules/module-c.aps.md +9 -0
- package/src/validator/__fixtures__/dup-modules/module-a.aps.md +9 -0
- package/src/validator/__fixtures__/dup-modules/module-b.aps.md +9 -0
- package/src/validator/__fixtures__/duplicate-ids-index.aps.md +15 -0
- package/src/validator/__fixtures__/invalid-task-id.aps.md +17 -0
- package/src/validator/__fixtures__/missing-confidence.aps.md +9 -0
- package/src/validator/__fixtures__/missing-h1.aps.md +5 -0
- package/src/validator/__fixtures__/missing-intent.aps.md +9 -0
- package/src/validator/__fixtures__/missing-modules-section.aps.md +7 -0
- package/src/validator/__fixtures__/missing-tasks-section.aps.md +7 -0
- package/src/validator/__fixtures__/modules/auth.aps.md +17 -0
- package/src/validator/__fixtures__/modules/payments.aps.md +13 -0
- package/src/validator/__fixtures__/scope-mismatch.aps.md +14 -0
- package/src/validator/__fixtures__/valid-index.aps.md +24 -0
- package/src/validator/__fixtures__/valid-leaf.aps.md +22 -0
- package/src/validator/index.ts +776 -0
- package/src/validator/validator.test.ts +269 -0
- package/templates/index-full.md +94 -0
- package/templates/index-minimal.md +16 -0
- package/templates/index-template.md +63 -0
- package/templates/leaf-full.md +76 -0
- package/templates/leaf-minimal.md +14 -0
- package/templates/leaf-template.md +55 -0
- package/templates/simple-full.md +56 -0
- package/templates/simple-minimal.md +14 -0
- package/templates/simple-template.md +30 -0
- package/tsconfig.json +19 -0
- package/tsconfig.lib.json +14 -0
- package/tsconfig.lib.tsbuildinfo +1 -0
- package/tsconfig.spec.json +9 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +15 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# APS Package (@eddacraft/anvil-aps)
|
|
2
|
+
|
|
3
|
+
> APS document parsing, validation, state management, and template generation
|
|
4
|
+
|
|
5
|
+
**Parent**: See root `AGENTS.md` for project-wide conventions.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
packages/aps/src/
|
|
11
|
+
├── parser/ # Markdown AST parsing (remark/unified)
|
|
12
|
+
│ └── index.ts # Extract tasks, modules, metadata from .aps.md
|
|
13
|
+
├── loader/ # Document loading and graph resolution
|
|
14
|
+
│ └── index.ts # Load plans, resolve dependencies
|
|
15
|
+
├── validator/ # Validation rules (745 lines)
|
|
16
|
+
│ └── index.ts # 8 validation rules for APS documents
|
|
17
|
+
├── filter/ # Task/module filtering
|
|
18
|
+
│ └── index.ts # Context bundle generation
|
|
19
|
+
├── state/ # Task state management (844 lines)
|
|
20
|
+
│ └── index.ts # .anvil/state.json, locking
|
|
21
|
+
├── templates/ # Template generation (607 lines)
|
|
22
|
+
│ └── generator.ts # Create .aps.md from prompts
|
|
23
|
+
├── types/ # Zod schemas and TypeScript types
|
|
24
|
+
│ └── index.ts # APSDocument, Task, Module schemas
|
|
25
|
+
└── index.ts # Barrel exports with subpath access
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Where to Look
|
|
29
|
+
|
|
30
|
+
| Task | Location | Notes |
|
|
31
|
+
| ------------------- | ------------------------ | ---------------------------- |
|
|
32
|
+
| Add validation rule | `validator/index.ts` | Follow existing rule pattern |
|
|
33
|
+
| Modify parsing | `parser/index.ts` | Uses remark AST visitors |
|
|
34
|
+
| Add state operation | `state/index.ts` | Modify state.json schema |
|
|
35
|
+
| Add template | `templates/generator.ts` | Template string functions |
|
|
36
|
+
| Add filter | `filter/index.ts` | Task selection logic |
|
|
37
|
+
|
|
38
|
+
## Validation Rules
|
|
39
|
+
|
|
40
|
+
8 built-in rules in `validator/index.ts`:
|
|
41
|
+
|
|
42
|
+
| Rule | Purpose |
|
|
43
|
+
| ----------------------- | ------------------------------------ |
|
|
44
|
+
| `required-sections` | Ensure mandatory sections exist |
|
|
45
|
+
| `task-format` | Validate task ID format (TASK-001) |
|
|
46
|
+
| `task-intent` | Tasks must have clear intent |
|
|
47
|
+
| `broken-links` | Detect references to missing modules |
|
|
48
|
+
| `duplicate-ids` | No duplicate task/module IDs |
|
|
49
|
+
| `circular-dependencies` | Detect circular module dependencies |
|
|
50
|
+
| `scope-mismatch` | Task scope matches module boundary |
|
|
51
|
+
| `orphan-modules` | Modules must be referenced |
|
|
52
|
+
|
|
53
|
+
## Adding a Validation Rule
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// In validator/index.ts
|
|
57
|
+
function validateMyRule(doc: APSDocument): ValidationIssue[] {
|
|
58
|
+
const issues: ValidationIssue[] = [];
|
|
59
|
+
|
|
60
|
+
// Check something...
|
|
61
|
+
if (condition) {
|
|
62
|
+
issues.push({
|
|
63
|
+
type: 'error', // or 'warning'
|
|
64
|
+
rule: 'my-rule',
|
|
65
|
+
message: 'What went wrong',
|
|
66
|
+
path: doc.path,
|
|
67
|
+
line: lineNumber, // Optional
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return issues;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Add to validateDocument():
|
|
75
|
+
issues.push(...validateMyRule(doc));
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## State Management
|
|
79
|
+
|
|
80
|
+
Task execution state stored in `.anvil/state.json`:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import {
|
|
84
|
+
loadState,
|
|
85
|
+
saveState,
|
|
86
|
+
lockTask,
|
|
87
|
+
unlockTask,
|
|
88
|
+
} from '@eddacraft/anvil-aps/state';
|
|
89
|
+
|
|
90
|
+
// Load current state
|
|
91
|
+
const state = await loadState(projectRoot);
|
|
92
|
+
|
|
93
|
+
// Lock a task for execution
|
|
94
|
+
const lock = await lockTask(state, 'TASK-001', {
|
|
95
|
+
executor: 'user@example.com',
|
|
96
|
+
reason: 'Implementing feature',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Update task status
|
|
100
|
+
await updateTaskStatus(state, 'TASK-001', 'in_progress');
|
|
101
|
+
|
|
102
|
+
// Unlock when done
|
|
103
|
+
await unlockTask(state, 'TASK-001');
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Parser Usage
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import { parseAPSDocument } from '@eddacraft/anvil-aps/parser';
|
|
110
|
+
|
|
111
|
+
const doc = await parseAPSDocument(content, { path: 'plans/index.aps.md' });
|
|
112
|
+
|
|
113
|
+
// Access parsed structure
|
|
114
|
+
doc.metadata; // Title, version, status
|
|
115
|
+
doc.modules; // Array of Module objects
|
|
116
|
+
doc.tasks; // Array of Task objects
|
|
117
|
+
doc.dependencies; // Module dependency graph
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Template Generation
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { generateTemplate } from '@eddacraft/anvil-aps/templates';
|
|
124
|
+
|
|
125
|
+
const content = await generateTemplate('module', {
|
|
126
|
+
name: 'my-feature',
|
|
127
|
+
description: 'Implements something cool',
|
|
128
|
+
tasks: ['FEAT-001', 'FEAT-002'],
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Write to file
|
|
132
|
+
await writeFile('plans/modules/my-feature.aps.md', content);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Scripts
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
nx test aps # All APS tests
|
|
139
|
+
nx test aps --testNamePattern="validator" # Validator tests only
|
|
140
|
+
pnpm -F aps run generate:templates # Regenerate template examples
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Anti-Patterns (This Package)
|
|
144
|
+
|
|
145
|
+
- Never modify state.json directly - use state management functions
|
|
146
|
+
- Never skip validation before loading documents
|
|
147
|
+
- Always handle circular dependencies gracefully
|
|
148
|
+
- Always preserve AST positions for error reporting
|
|
149
|
+
|
|
150
|
+
## Testing
|
|
151
|
+
|
|
152
|
+
- Fixture-based with realistic APS documents
|
|
153
|
+
- Test files in `validator/__fixtures__/`, `parser/__fixtures__/`
|
|
154
|
+
- Comprehensive edge cases for validation rules
|
|
155
|
+
- State management tests with temp directories
|
package/LICENSE
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Copyright (c) 2026 EddaCraft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
PROPRIETARY AND CONFIDENTIAL
|
|
4
|
+
|
|
5
|
+
This software and associated documentation files (the "Software") are the
|
|
6
|
+
exclusive property of EddaCraft. Unauthorised copying, modification,
|
|
7
|
+
distribution, or use of this Software, via any medium, is strictly prohibited
|
|
8
|
+
without the express written permission of EddaCraft.
|
|
9
|
+
|
|
10
|
+
The Software is provided for evaluation and testing purposes only to authorised
|
|
11
|
+
beta testers. No licence is granted to use, copy, modify, or distribute the
|
|
12
|
+
Software for any other purpose.
|
|
13
|
+
|
|
14
|
+
For licensing enquiries, contact: legal@eddacraft.com
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# @eddacraft/anvil-aps
|
|
2
|
+
|
|
3
|
+
Anvil Planning Spec (APS) library for parsing, loading, validating, and managing
|
|
4
|
+
planning documents.
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
The `@eddacraft/anvil-aps` package provides a complete toolkit for working with
|
|
9
|
+
Anvil Planning Spec documents:
|
|
10
|
+
|
|
11
|
+
- **Parser**: Parse Markdown-based planning documents using remark AST
|
|
12
|
+
- **Loader**: Load and resolve planning document graphs with dependency tracking
|
|
13
|
+
- **Validator**: Validate planning documents against APS rules
|
|
14
|
+
- **State**: Manage task state and locking for concurrent execution
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add @eddacraft/anvil-aps
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
Coming soon - see `docs/` directory for detailed documentation.
|
|
25
|
+
|
|
26
|
+
## Documentation
|
|
27
|
+
|
|
28
|
+
- [APS Planning Spec](./docs/APS-Planning-Spec-v0.1.md) - Full specification
|
|
29
|
+
- [APS Conventions](./docs/APS-Conventions.md) - Markdown conventions and
|
|
30
|
+
patterns
|
|
31
|
+
- [Non-Goals](./docs/APS-NonGoals.md) - What APS explicitly does not do
|
|
32
|
+
- [Anvil Integration](./docs/APS-Anvil-Integration.md) - How APS integrates with
|
|
33
|
+
Anvil CLI
|
|
34
|
+
|
|
35
|
+
## Development
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Build the package
|
|
39
|
+
nx build aps
|
|
40
|
+
|
|
41
|
+
# Run tests
|
|
42
|
+
nx test aps
|
|
43
|
+
|
|
44
|
+
# Run tests in watch mode
|
|
45
|
+
nx test aps --watch
|
|
46
|
+
|
|
47
|
+
# Type check
|
|
48
|
+
pnpm typecheck
|
|
49
|
+
|
|
50
|
+
# Lint
|
|
51
|
+
nx lint aps
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Licence
|
|
55
|
+
|
|
56
|
+
Copyright (c) 2026 EddaCraft. All rights reserved. See [LICENSE](../../LICENSE)
|
|
57
|
+
for details.
|
package/TODO.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# APS Package Status
|
|
2
|
+
|
|
3
|
+
> **Full Plan**: `plans/index.aps.md` (module: aps-markdown-adapter)
|
|
4
|
+
>
|
|
5
|
+
> This package is **complete**. See the plan document for adapter work.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Package Status: Complete ✅
|
|
10
|
+
|
|
11
|
+
The `@eddacraft/anvil-aps` library provides:
|
|
12
|
+
|
|
13
|
+
- **Parser** — `parseDocument()`, `parseIndex()`, `parseTask()`
|
|
14
|
+
- **Loader** — `loadPlan()` with multi-module support
|
|
15
|
+
- **Filter** — `filterPlan()` with scope/tag/owner/task filtering
|
|
16
|
+
- **Validator** — `validatePlanningDoc()` with issue reporting
|
|
17
|
+
- **State** — Task locking/unlocking via `.anvil/state.json`
|
|
18
|
+
- **Templates** — `generateIndexTemplate()`, `generateLeafTemplate()`
|
|
19
|
+
|
|
20
|
+
### Test Coverage
|
|
21
|
+
|
|
22
|
+
| Module | Coverage | Tests |
|
|
23
|
+
| --------- | --------- | ------- |
|
|
24
|
+
| parser | 89.5% | 31 |
|
|
25
|
+
| loader | 96% | 18 |
|
|
26
|
+
| validator | 97.9% | 27 |
|
|
27
|
+
| state | 94.2% | 35 |
|
|
28
|
+
| filter | 89.6% | 30 |
|
|
29
|
+
| templates | 100% | 26 |
|
|
30
|
+
| **Total** | **93.1%** | **167** |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Related Work
|
|
35
|
+
|
|
36
|
+
See `plans/modules/aps-markdown-adapter.aps.md` for adapter integration.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
_Last updated: January 2026_
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Bundle Builder
|
|
3
|
+
*
|
|
4
|
+
* Generates context bundles for LLM consumption from filtered plans.
|
|
5
|
+
* Outputs both text (Markdown) and JSON formats.
|
|
6
|
+
*/
|
|
7
|
+
import type { FilteredPlan } from './index.js';
|
|
8
|
+
/**
|
|
9
|
+
* Context bundle in JSON format
|
|
10
|
+
*/
|
|
11
|
+
export interface ContextBundleJSON {
|
|
12
|
+
/** Plan title */
|
|
13
|
+
title: string;
|
|
14
|
+
/** Filter criteria that was applied */
|
|
15
|
+
filter: {
|
|
16
|
+
scopes?: string[];
|
|
17
|
+
modules?: string[];
|
|
18
|
+
tasks?: string[];
|
|
19
|
+
owners?: string[];
|
|
20
|
+
tags?: string[];
|
|
21
|
+
priorities?: string[];
|
|
22
|
+
confidences?: string[];
|
|
23
|
+
};
|
|
24
|
+
/** Summary statistics */
|
|
25
|
+
summary: {
|
|
26
|
+
totalModules: number;
|
|
27
|
+
totalTasks: number;
|
|
28
|
+
tasksByConfidence: {
|
|
29
|
+
high: number;
|
|
30
|
+
medium: number;
|
|
31
|
+
low: number;
|
|
32
|
+
};
|
|
33
|
+
tasksByStatus: {
|
|
34
|
+
open: number;
|
|
35
|
+
locked: number;
|
|
36
|
+
completed: number;
|
|
37
|
+
cancelled: number;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
/** Modules with their tasks */
|
|
41
|
+
modules: Array<{
|
|
42
|
+
id: string;
|
|
43
|
+
scope?: string;
|
|
44
|
+
owner?: string;
|
|
45
|
+
priority?: string;
|
|
46
|
+
tags?: string[];
|
|
47
|
+
tasks: Array<{
|
|
48
|
+
id: string;
|
|
49
|
+
title: string;
|
|
50
|
+
intent: string;
|
|
51
|
+
confidence: string;
|
|
52
|
+
status: string;
|
|
53
|
+
scopes?: string[];
|
|
54
|
+
tags?: string[];
|
|
55
|
+
dependencies?: string[];
|
|
56
|
+
inputs?: string[];
|
|
57
|
+
expectedOutcome?: string;
|
|
58
|
+
}>;
|
|
59
|
+
}>;
|
|
60
|
+
/** Dependency graph (module -> dependencies) */
|
|
61
|
+
dependencyGraph: Record<string, string[]>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Build a context bundle from a filtered plan
|
|
65
|
+
*
|
|
66
|
+
* @param filtered - The filtered plan
|
|
67
|
+
* @returns Context bundle in JSON format
|
|
68
|
+
*/
|
|
69
|
+
export declare function buildContextBundleJSON(filtered: FilteredPlan): ContextBundleJSON;
|
|
70
|
+
/**
|
|
71
|
+
* Build a context bundle in Markdown text format
|
|
72
|
+
*
|
|
73
|
+
* @param filtered - The filtered plan
|
|
74
|
+
* @returns Markdown text suitable for LLM context
|
|
75
|
+
*/
|
|
76
|
+
export declare function buildContextBundleText(filtered: FilteredPlan): string;
|
|
77
|
+
/**
|
|
78
|
+
* Build context for a single task (focused view)
|
|
79
|
+
*/
|
|
80
|
+
export declare function buildTaskContext(filtered: FilteredPlan, taskId: string): string | null;
|
|
81
|
+
//# sourceMappingURL=context-bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-bundle.d.ts","sourceRoot":"","sources":["../../src/filter/context-bundle.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IAEd,uCAAuC;IACvC,MAAM,EAAE;QACN,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC;IAEF,yBAAyB;IACzB,OAAO,EAAE;QACP,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,iBAAiB,EAAE;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,MAAM,EAAE,MAAM,CAAC;YACf,GAAG,EAAE,MAAM,CAAC;SACb,CAAC;QACF,aAAa,EAAE;YACb,IAAI,EAAE,MAAM,CAAC;YACb,MAAM,EAAE,MAAM,CAAC;YACf,SAAS,EAAE,MAAM,CAAC;YAClB,SAAS,EAAE,MAAM,CAAC;SACnB,CAAC;KACH,CAAC;IAEF,+BAA+B;IAC/B,OAAO,EAAE,KAAK,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,KAAK,EAAE,KAAK,CAAC;YACX,EAAE,EAAE,MAAM,CAAC;YACX,KAAK,EAAE,MAAM,CAAC;YACd,MAAM,EAAE,MAAM,CAAC;YACf,UAAU,EAAE,MAAM,CAAC;YACnB,MAAM,EAAE,MAAM,CAAC;YACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;YAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;YAChB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;YACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;YAClB,eAAe,CAAC,EAAE,MAAM,CAAC;SAC1B,CAAC,CAAC;KACJ,CAAC,CAAC;IAEH,gDAAgD;IAChD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC3C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,YAAY,GAAG,iBAAiB,CAqEhF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CA+FrE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA2DtF"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Bundle Builder
|
|
3
|
+
*
|
|
4
|
+
* Generates context bundles for LLM consumption from filtered plans.
|
|
5
|
+
* Outputs both text (Markdown) and JSON formats.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Build a context bundle from a filtered plan
|
|
9
|
+
*
|
|
10
|
+
* @param filtered - The filtered plan
|
|
11
|
+
* @returns Context bundle in JSON format
|
|
12
|
+
*/
|
|
13
|
+
export function buildContextBundleJSON(filtered) {
|
|
14
|
+
const { plan, modules, tasks, criteria } = filtered;
|
|
15
|
+
// Build summary statistics
|
|
16
|
+
const summary = {
|
|
17
|
+
totalModules: modules.length,
|
|
18
|
+
totalTasks: tasks.length,
|
|
19
|
+
tasksByConfidence: {
|
|
20
|
+
high: tasks.filter((t) => t.confidence === 'high').length,
|
|
21
|
+
medium: tasks.filter((t) => t.confidence === 'medium').length,
|
|
22
|
+
low: tasks.filter((t) => t.confidence === 'low').length,
|
|
23
|
+
},
|
|
24
|
+
tasksByStatus: {
|
|
25
|
+
open: tasks.filter((t) => (t.status ?? 'open') === 'open').length,
|
|
26
|
+
locked: tasks.filter((t) => t.status === 'locked').length,
|
|
27
|
+
completed: tasks.filter((t) => t.status === 'completed').length,
|
|
28
|
+
cancelled: tasks.filter((t) => t.status === 'cancelled').length,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
// Build module data with tasks
|
|
32
|
+
const moduleData = modules.map((module) => {
|
|
33
|
+
const moduleTasks = tasks.filter((t) => module.tasks.some((mt) => mt.id === t.id));
|
|
34
|
+
return {
|
|
35
|
+
id: module.id,
|
|
36
|
+
scope: module.metadata.scope,
|
|
37
|
+
owner: module.metadata.owner,
|
|
38
|
+
priority: module.metadata.priority,
|
|
39
|
+
tags: module.metadata.tags,
|
|
40
|
+
tasks: moduleTasks.map((t) => ({
|
|
41
|
+
id: t.id,
|
|
42
|
+
title: t.title,
|
|
43
|
+
intent: t.intent,
|
|
44
|
+
confidence: t.confidence,
|
|
45
|
+
status: t.status ?? 'open',
|
|
46
|
+
scopes: t.scopes,
|
|
47
|
+
tags: t.tags,
|
|
48
|
+
dependencies: t.dependencies,
|
|
49
|
+
inputs: t.inputs,
|
|
50
|
+
expectedOutcome: t.expectedOutcome,
|
|
51
|
+
})),
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
// Build dependency graph for filtered modules
|
|
55
|
+
const dependencyGraph = {};
|
|
56
|
+
for (const module of modules) {
|
|
57
|
+
const deps = plan.dependencyGraph.get(module.id) ?? [];
|
|
58
|
+
// Only include dependencies that are in the filtered set
|
|
59
|
+
const filteredDeps = deps.filter((d) => modules.some((m) => m.id === d));
|
|
60
|
+
dependencyGraph[module.id] = filteredDeps;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
title: plan.title,
|
|
64
|
+
filter: {
|
|
65
|
+
scopes: criteria.scopes,
|
|
66
|
+
modules: criteria.modules,
|
|
67
|
+
tasks: criteria.tasks,
|
|
68
|
+
owners: criteria.owners,
|
|
69
|
+
tags: criteria.tags,
|
|
70
|
+
priorities: criteria.priorities,
|
|
71
|
+
confidences: criteria.confidences,
|
|
72
|
+
},
|
|
73
|
+
summary,
|
|
74
|
+
modules: moduleData,
|
|
75
|
+
dependencyGraph,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Build a context bundle in Markdown text format
|
|
80
|
+
*
|
|
81
|
+
* @param filtered - The filtered plan
|
|
82
|
+
* @returns Markdown text suitable for LLM context
|
|
83
|
+
*/
|
|
84
|
+
export function buildContextBundleText(filtered) {
|
|
85
|
+
const { plan, modules, tasks, criteria } = filtered;
|
|
86
|
+
const lines = [];
|
|
87
|
+
// Header
|
|
88
|
+
lines.push(`# ${plan.title}`);
|
|
89
|
+
lines.push('');
|
|
90
|
+
// Filter info
|
|
91
|
+
const filterParts = [];
|
|
92
|
+
if (criteria.scopes?.length)
|
|
93
|
+
filterParts.push(`scopes: ${criteria.scopes.join(', ')}`);
|
|
94
|
+
if (criteria.modules?.length)
|
|
95
|
+
filterParts.push(`modules: ${criteria.modules.join(', ')}`);
|
|
96
|
+
if (criteria.tasks?.length)
|
|
97
|
+
filterParts.push(`tasks: ${criteria.tasks.join(', ')}`);
|
|
98
|
+
if (criteria.owners?.length)
|
|
99
|
+
filterParts.push(`owners: ${criteria.owners.join(', ')}`);
|
|
100
|
+
if (criteria.tags?.length)
|
|
101
|
+
filterParts.push(`tags: ${criteria.tags.join(', ')}`);
|
|
102
|
+
if (criteria.priorities?.length)
|
|
103
|
+
filterParts.push(`priorities: ${criteria.priorities.join(', ')}`);
|
|
104
|
+
if (criteria.confidences?.length)
|
|
105
|
+
filterParts.push(`confidences: ${criteria.confidences.join(', ')}`);
|
|
106
|
+
if (filterParts.length > 0) {
|
|
107
|
+
lines.push(`> Filtered by: ${filterParts.join('; ')}`);
|
|
108
|
+
lines.push('');
|
|
109
|
+
}
|
|
110
|
+
// Summary
|
|
111
|
+
lines.push('## Summary');
|
|
112
|
+
lines.push('');
|
|
113
|
+
lines.push(`- **Modules:** ${modules.length}`);
|
|
114
|
+
lines.push(`- **Tasks:** ${tasks.length}`);
|
|
115
|
+
const highConfidence = tasks.filter((t) => t.confidence === 'high').length;
|
|
116
|
+
const mediumConfidence = tasks.filter((t) => t.confidence === 'medium').length;
|
|
117
|
+
const lowConfidence = tasks.filter((t) => t.confidence === 'low').length;
|
|
118
|
+
lines.push(`- **Confidence:** ${highConfidence} high, ${mediumConfidence} medium, ${lowConfidence} low`);
|
|
119
|
+
const openTasks = tasks.filter((t) => (t.status ?? 'open') === 'open').length;
|
|
120
|
+
const lockedTasks = tasks.filter((t) => t.status === 'locked').length;
|
|
121
|
+
const completedTasks = tasks.filter((t) => t.status === 'completed').length;
|
|
122
|
+
lines.push(`- **Status:** ${openTasks} open, ${lockedTasks} locked, ${completedTasks} completed`);
|
|
123
|
+
lines.push('');
|
|
124
|
+
// Modules and tasks
|
|
125
|
+
for (const module of modules) {
|
|
126
|
+
lines.push(`## Module: ${module.id}`);
|
|
127
|
+
lines.push('');
|
|
128
|
+
if (module.metadata.scope)
|
|
129
|
+
lines.push(`**Scope:** ${module.metadata.scope}`);
|
|
130
|
+
if (module.metadata.owner)
|
|
131
|
+
lines.push(`**Owner:** ${module.metadata.owner}`);
|
|
132
|
+
if (module.metadata.priority)
|
|
133
|
+
lines.push(`**Priority:** ${module.metadata.priority}`);
|
|
134
|
+
if (module.metadata.tags?.length)
|
|
135
|
+
lines.push(`**Tags:** ${module.metadata.tags.join(', ')}`);
|
|
136
|
+
const deps = plan.dependencyGraph.get(module.id) ?? [];
|
|
137
|
+
if (deps.length > 0)
|
|
138
|
+
lines.push(`**Dependencies:** ${deps.join(', ')}`);
|
|
139
|
+
lines.push('');
|
|
140
|
+
// Tasks for this module
|
|
141
|
+
const moduleTasks = tasks.filter((t) => module.tasks.some((mt) => mt.id === t.id));
|
|
142
|
+
if (moduleTasks.length === 0) {
|
|
143
|
+
lines.push('*No tasks match the filter criteria.*');
|
|
144
|
+
lines.push('');
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
lines.push('### Tasks');
|
|
148
|
+
lines.push('');
|
|
149
|
+
for (const task of moduleTasks) {
|
|
150
|
+
lines.push(`#### ${task.id}: ${task.title}`);
|
|
151
|
+
lines.push('');
|
|
152
|
+
lines.push(`**Intent:** ${task.intent}`);
|
|
153
|
+
lines.push(`**Confidence:** ${task.confidence}`);
|
|
154
|
+
lines.push(`**Status:** ${task.status ?? 'open'}`);
|
|
155
|
+
if (task.scopes?.length)
|
|
156
|
+
lines.push(`**Scopes:** ${task.scopes.join(', ')}`);
|
|
157
|
+
if (task.tags?.length)
|
|
158
|
+
lines.push(`**Tags:** ${task.tags.join(', ')}`);
|
|
159
|
+
if (task.dependencies?.length)
|
|
160
|
+
lines.push(`**Dependencies:** ${task.dependencies.join(', ')}`);
|
|
161
|
+
if (task.expectedOutcome)
|
|
162
|
+
lines.push(`**Expected Outcome:** ${task.expectedOutcome}`);
|
|
163
|
+
if (task.inputs?.length) {
|
|
164
|
+
lines.push('**Inputs:**');
|
|
165
|
+
for (const input of task.inputs) {
|
|
166
|
+
lines.push(`- ${input}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
lines.push('');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return lines.join('\n');
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Build context for a single task (focused view)
|
|
176
|
+
*/
|
|
177
|
+
export function buildTaskContext(filtered, taskId) {
|
|
178
|
+
const task = filtered.tasks.find((t) => t.id === taskId);
|
|
179
|
+
if (!task)
|
|
180
|
+
return null;
|
|
181
|
+
const lines = [];
|
|
182
|
+
lines.push(`# Task: ${task.id}`);
|
|
183
|
+
lines.push('');
|
|
184
|
+
lines.push(`## ${task.title}`);
|
|
185
|
+
lines.push('');
|
|
186
|
+
lines.push(`**Intent:** ${task.intent}`);
|
|
187
|
+
lines.push('');
|
|
188
|
+
lines.push(`**Confidence:** ${task.confidence}`);
|
|
189
|
+
lines.push(`**Status:** ${task.status ?? 'open'}`);
|
|
190
|
+
if (task.scopes?.length) {
|
|
191
|
+
lines.push('');
|
|
192
|
+
lines.push(`**Scopes:** ${task.scopes.join(', ')}`);
|
|
193
|
+
lines.push('');
|
|
194
|
+
lines.push('> These scopes define what files/modules this task is allowed to modify.');
|
|
195
|
+
}
|
|
196
|
+
if (task.tags?.length) {
|
|
197
|
+
lines.push('');
|
|
198
|
+
lines.push(`**Tags:** ${task.tags.join(', ')}`);
|
|
199
|
+
}
|
|
200
|
+
if (task.dependencies?.length) {
|
|
201
|
+
lines.push('');
|
|
202
|
+
lines.push('## Dependencies');
|
|
203
|
+
lines.push('');
|
|
204
|
+
lines.push('This task depends on:');
|
|
205
|
+
for (const dep of task.dependencies) {
|
|
206
|
+
const depTask = filtered.plan.allTasks.find((t) => t.id === dep);
|
|
207
|
+
if (depTask) {
|
|
208
|
+
lines.push(`- **${dep}:** ${depTask.title} (${depTask.status ?? 'open'})`);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
lines.push(`- **${dep}:** (not found)`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (task.inputs?.length) {
|
|
216
|
+
lines.push('');
|
|
217
|
+
lines.push('## Inputs');
|
|
218
|
+
lines.push('');
|
|
219
|
+
for (const input of task.inputs) {
|
|
220
|
+
lines.push(`- ${input}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (task.expectedOutcome) {
|
|
224
|
+
lines.push('');
|
|
225
|
+
lines.push('## Expected Outcome');
|
|
226
|
+
lines.push('');
|
|
227
|
+
lines.push(task.expectedOutcome);
|
|
228
|
+
}
|
|
229
|
+
return lines.join('\n');
|
|
230
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filter module - Task and module filtering for APS plans
|
|
3
|
+
*
|
|
4
|
+
* Provides filtering capabilities for:
|
|
5
|
+
* - Scope-based filtering (by module scope or task scopes)
|
|
6
|
+
* - Module-based filtering (by module ID)
|
|
7
|
+
* - Task-based filtering (by task ID)
|
|
8
|
+
* - Metadata filtering (owner, tags, priority, confidence)
|
|
9
|
+
*
|
|
10
|
+
* Also provides context bundle generation for LLM consumption.
|
|
11
|
+
*/
|
|
12
|
+
export { buildContextBundleJSON, buildContextBundleText, buildTaskContext, type ContextBundleJSON, } from './context-bundle.js';
|
|
13
|
+
import type { LoadedPlan, LoadedModule } from '../loader/index.js';
|
|
14
|
+
import type { Task, Priority, Confidence } from '../types/index.js';
|
|
15
|
+
/**
|
|
16
|
+
* Filter criteria for tasks and modules
|
|
17
|
+
*/
|
|
18
|
+
export interface FilterCriteria {
|
|
19
|
+
/** Filter by scope (matches module scope or task scopes) */
|
|
20
|
+
scopes?: string[];
|
|
21
|
+
/** Filter by module ID */
|
|
22
|
+
modules?: string[];
|
|
23
|
+
/** Filter by specific task IDs */
|
|
24
|
+
tasks?: string[];
|
|
25
|
+
/** Filter by owner (e.g., @alice) */
|
|
26
|
+
owners?: string[];
|
|
27
|
+
/** Filter by tags (matches any) */
|
|
28
|
+
tags?: string[];
|
|
29
|
+
/** Filter by priority levels */
|
|
30
|
+
priorities?: Priority[];
|
|
31
|
+
/** Filter by confidence levels */
|
|
32
|
+
confidences?: Confidence[];
|
|
33
|
+
/** Filter by task status */
|
|
34
|
+
statuses?: Array<'open' | 'locked' | 'completed' | 'cancelled'>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Result of filtering a plan
|
|
38
|
+
*/
|
|
39
|
+
export interface FilteredPlan {
|
|
40
|
+
/** Original plan reference */
|
|
41
|
+
plan: LoadedPlan;
|
|
42
|
+
/** Filtered modules (only those matching criteria) */
|
|
43
|
+
modules: LoadedModule[];
|
|
44
|
+
/** Filtered tasks (only those matching criteria) */
|
|
45
|
+
tasks: Task[];
|
|
46
|
+
/** Applied filter criteria */
|
|
47
|
+
criteria: FilterCriteria;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Filter a loaded plan by the given criteria
|
|
51
|
+
*
|
|
52
|
+
* @param plan - The loaded plan to filter
|
|
53
|
+
* @param criteria - Filter criteria to apply
|
|
54
|
+
* @returns Filtered plan with matching modules and tasks
|
|
55
|
+
*/
|
|
56
|
+
export declare function filterPlan(plan: LoadedPlan, criteria: FilterCriteria): FilteredPlan;
|
|
57
|
+
/**
|
|
58
|
+
* Filter tasks by scope (convenience function)
|
|
59
|
+
*/
|
|
60
|
+
export declare function filterByScope(plan: LoadedPlan, scopes: string[]): Task[];
|
|
61
|
+
/**
|
|
62
|
+
* Filter tasks by module (convenience function)
|
|
63
|
+
*/
|
|
64
|
+
export declare function filterByModule(plan: LoadedPlan, moduleIds: string[]): Task[];
|
|
65
|
+
/**
|
|
66
|
+
* Filter tasks by tags (convenience function)
|
|
67
|
+
*/
|
|
68
|
+
export declare function filterByTags(plan: LoadedPlan, tags: string[]): Task[];
|
|
69
|
+
/**
|
|
70
|
+
* Filter tasks by owner (convenience function)
|
|
71
|
+
*/
|
|
72
|
+
export declare function filterByOwner(plan: LoadedPlan, owners: string[]): Task[];
|
|
73
|
+
/**
|
|
74
|
+
* Filter tasks by priority (convenience function)
|
|
75
|
+
*/
|
|
76
|
+
export declare function filterByPriority(plan: LoadedPlan, priorities: Priority[]): Task[];
|
|
77
|
+
/**
|
|
78
|
+
* Filter tasks by confidence (convenience function)
|
|
79
|
+
*/
|
|
80
|
+
export declare function filterByConfidence(plan: LoadedPlan, confidences: Confidence[]): Task[];
|
|
81
|
+
/**
|
|
82
|
+
* Get tasks matching specific IDs
|
|
83
|
+
*/
|
|
84
|
+
export declare function getTasksById(plan: LoadedPlan, taskIds: string[]): Task[];
|
|
85
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/filter/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,iBAAiB,GACvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAEjB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,gCAAgC;IAChC,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;IAExB,kCAAkC;IAClC,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAE3B,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC,CAAC;CACjE;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,8BAA8B;IAC9B,IAAI,EAAE,UAAU,CAAC;IAEjB,sDAAsD;IACtD,OAAO,EAAE,YAAY,EAAE,CAAC;IAExB,oDAAoD;IACpD,KAAK,EAAE,IAAI,EAAE,CAAC;IAEd,8BAA8B;IAC9B,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,GAAG,YAAY,CA+GnF;AAcD;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAExE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAE5E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAErE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAExE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,CAEjF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,CAEtF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAExE"}
|