@lwelliott/cortex-cli 1.0.3
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/LICENSE +21 -0
- package/README.md +159 -0
- package/dist/cli/audit.d.ts +3 -0
- package/dist/cli/audit.d.ts.map +1 -0
- package/dist/cli/audit.js +78 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/doc.d.ts +3 -0
- package/dist/cli/doc.d.ts.map +1 -0
- package/dist/cli/doc.js +291 -0
- package/dist/cli/doc.js.map +1 -0
- package/dist/cli/entity.d.ts +3 -0
- package/dist/cli/entity.d.ts.map +1 -0
- package/dist/cli/entity.js +135 -0
- package/dist/cli/entity.js.map +1 -0
- package/dist/cli/format-selector.d.ts +30 -0
- package/dist/cli/format-selector.d.ts.map +1 -0
- package/dist/cli/format-selector.js +101 -0
- package/dist/cli/format-selector.js.map +1 -0
- package/dist/cli/formatters/audit-formatter.d.ts +33 -0
- package/dist/cli/formatters/audit-formatter.d.ts.map +1 -0
- package/dist/cli/formatters/audit-formatter.js +204 -0
- package/dist/cli/formatters/audit-formatter.js.map +1 -0
- package/dist/cli/formatters/json.d.ts +10 -0
- package/dist/cli/formatters/json.d.ts.map +1 -0
- package/dist/cli/formatters/json.js +31 -0
- package/dist/cli/formatters/json.js.map +1 -0
- package/dist/cli/formatters/markdown.d.ts +12 -0
- package/dist/cli/formatters/markdown.d.ts.map +1 -0
- package/dist/cli/formatters/markdown.js +341 -0
- package/dist/cli/formatters/markdown.js.map +1 -0
- package/dist/cli/formatters/quiet.d.ts +15 -0
- package/dist/cli/formatters/quiet.d.ts.map +1 -0
- package/dist/cli/formatters/quiet.js +75 -0
- package/dist/cli/formatters/quiet.js.map +1 -0
- package/dist/cli/formatters/table.d.ts +11 -0
- package/dist/cli/formatters/table.d.ts.map +1 -0
- package/dist/cli/formatters/table.js +726 -0
- package/dist/cli/formatters/table.js.map +1 -0
- package/dist/cli/graph.d.ts +3 -0
- package/dist/cli/graph.d.ts.map +1 -0
- package/dist/cli/graph.js +209 -0
- package/dist/cli/graph.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +144 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/lesson.d.ts +3 -0
- package/dist/cli/lesson.d.ts.map +1 -0
- package/dist/cli/lesson.js +85 -0
- package/dist/cli/lesson.js.map +1 -0
- package/dist/cli/project-resolver.d.ts +17 -0
- package/dist/cli/project-resolver.d.ts.map +1 -0
- package/dist/cli/project-resolver.js +25 -0
- package/dist/cli/project-resolver.js.map +1 -0
- package/dist/cli/project.d.ts +12 -0
- package/dist/cli/project.d.ts.map +1 -0
- package/dist/cli/project.js +169 -0
- package/dist/cli/project.js.map +1 -0
- package/dist/cli/relation.d.ts +3 -0
- package/dist/cli/relation.d.ts.map +1 -0
- package/dist/cli/relation.js +128 -0
- package/dist/cli/relation.js.map +1 -0
- package/dist/cli/review.d.ts +3 -0
- package/dist/cli/review.d.ts.map +1 -0
- package/dist/cli/review.js +131 -0
- package/dist/cli/review.js.map +1 -0
- package/dist/cli/router.d.ts +38 -0
- package/dist/cli/router.d.ts.map +1 -0
- package/dist/cli/router.js +49 -0
- package/dist/cli/router.js.map +1 -0
- package/dist/cli/schema.d.ts +3 -0
- package/dist/cli/schema.d.ts.map +1 -0
- package/dist/cli/schema.js +94 -0
- package/dist/cli/schema.js.map +1 -0
- package/dist/cli/sprint.d.ts +12 -0
- package/dist/cli/sprint.d.ts.map +1 -0
- package/dist/cli/sprint.js +200 -0
- package/dist/cli/sprint.js.map +1 -0
- package/dist/cli/task.d.ts +12 -0
- package/dist/cli/task.d.ts.map +1 -0
- package/dist/cli/task.js +252 -0
- package/dist/cli/task.js.map +1 -0
- package/dist/cli/test-report.d.ts +3 -0
- package/dist/cli/test-report.d.ts.map +1 -0
- package/dist/cli/test-report.js +134 -0
- package/dist/cli/test-report.js.map +1 -0
- package/dist/cli/validate.d.ts +8 -0
- package/dist/cli/validate.d.ts.map +1 -0
- package/dist/cli/validate.js +86 -0
- package/dist/cli/validate.js.map +1 -0
- package/dist/config/config.d.ts +18 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +70 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/registry.d.ts +52 -0
- package/dist/config/registry.d.ts.map +1 -0
- package/dist/config/registry.js +193 -0
- package/dist/config/registry.js.map +1 -0
- package/dist/config/resolver.d.ts +26 -0
- package/dist/config/resolver.d.ts.map +1 -0
- package/dist/config/resolver.js +87 -0
- package/dist/config/resolver.js.map +1 -0
- package/dist/db/builtin-schema-constants.d.ts +109 -0
- package/dist/db/builtin-schema-constants.d.ts.map +1 -0
- package/dist/db/builtin-schema-constants.js +32 -0
- package/dist/db/builtin-schema-constants.js.map +1 -0
- package/dist/db/connection.d.ts +34 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +140 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/generated/schema-types.d.ts +134 -0
- package/dist/db/generated/schema-types.d.ts.map +1 -0
- package/dist/db/generated/schema-types.js +31 -0
- package/dist/db/generated/schema-types.js.map +1 -0
- package/dist/db/locks.d.ts +106 -0
- package/dist/db/locks.d.ts.map +1 -0
- package/dist/db/locks.js +211 -0
- package/dist/db/locks.js.map +1 -0
- package/dist/db/migration.d.ts +65 -0
- package/dist/db/migration.d.ts.map +1 -0
- package/dist/db/migration.js +233 -0
- package/dist/db/migration.js.map +1 -0
- package/dist/db/retry.d.ts +26 -0
- package/dist/db/retry.d.ts.map +1 -0
- package/dist/db/retry.js +71 -0
- package/dist/db/retry.js.map +1 -0
- package/dist/db/schema.d.ts +21 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +830 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/models/common.d.ts +27 -0
- package/dist/models/common.d.ts.map +1 -0
- package/dist/models/common.js +4 -0
- package/dist/models/common.js.map +1 -0
- package/dist/models/document.d.ts +89 -0
- package/dist/models/document.d.ts.map +1 -0
- package/dist/models/document.js +5 -0
- package/dist/models/document.js.map +1 -0
- package/dist/models/entity-model.d.ts +30 -0
- package/dist/models/entity-model.d.ts.map +1 -0
- package/dist/models/entity-model.js +99 -0
- package/dist/models/entity-model.js.map +1 -0
- package/dist/models/entity.d.ts +88 -0
- package/dist/models/entity.d.ts.map +1 -0
- package/dist/models/entity.js +5 -0
- package/dist/models/entity.js.map +1 -0
- package/dist/models/graph-schema.d.ts +43 -0
- package/dist/models/graph-schema.d.ts.map +1 -0
- package/dist/models/graph-schema.js +76 -0
- package/dist/models/graph-schema.js.map +1 -0
- package/dist/models/project.d.ts +49 -0
- package/dist/models/project.d.ts.map +1 -0
- package/dist/models/project.js +18 -0
- package/dist/models/project.js.map +1 -0
- package/dist/models/relation.d.ts +35 -0
- package/dist/models/relation.d.ts.map +1 -0
- package/dist/models/relation.js +212 -0
- package/dist/models/relation.js.map +1 -0
- package/dist/models/review.d.ts +86 -0
- package/dist/models/review.d.ts.map +1 -0
- package/dist/models/review.js +5 -0
- package/dist/models/review.js.map +1 -0
- package/dist/models/sprint.d.ts +38 -0
- package/dist/models/sprint.d.ts.map +1 -0
- package/dist/models/sprint.js +4 -0
- package/dist/models/sprint.js.map +1 -0
- package/dist/models/task.d.ts +75 -0
- package/dist/models/task.d.ts.map +1 -0
- package/dist/models/task.js +4 -0
- package/dist/models/task.js.map +1 -0
- package/dist/models/validation.d.ts +25 -0
- package/dist/models/validation.d.ts.map +1 -0
- package/dist/models/validation.js +4 -0
- package/dist/models/validation.js.map +1 -0
- package/dist/services/audit-check-service.d.ts +16 -0
- package/dist/services/audit-check-service.d.ts.map +1 -0
- package/dist/services/audit-check-service.js +137 -0
- package/dist/services/audit-check-service.js.map +1 -0
- package/dist/services/audit-checks/dangling-relations-check.d.ts +7 -0
- package/dist/services/audit-checks/dangling-relations-check.d.ts.map +1 -0
- package/dist/services/audit-checks/dangling-relations-check.js +52 -0
- package/dist/services/audit-checks/dangling-relations-check.js.map +1 -0
- package/dist/services/audit-checks/duplicate-ids-check.d.ts +4 -0
- package/dist/services/audit-checks/duplicate-ids-check.d.ts.map +1 -0
- package/dist/services/audit-checks/duplicate-ids-check.js +49 -0
- package/dist/services/audit-checks/duplicate-ids-check.js.map +1 -0
- package/dist/services/audit-checks/fix-engine.d.ts +24 -0
- package/dist/services/audit-checks/fix-engine.d.ts.map +1 -0
- package/dist/services/audit-checks/fix-engine.js +114 -0
- package/dist/services/audit-checks/fix-engine.js.map +1 -0
- package/dist/services/audit-checks/fr-nfr-to-fs-nfs-check.d.ts +9 -0
- package/dist/services/audit-checks/fr-nfr-to-fs-nfs-check.d.ts.map +1 -0
- package/dist/services/audit-checks/fr-nfr-to-fs-nfs-check.js +56 -0
- package/dist/services/audit-checks/fr-nfr-to-fs-nfs-check.js.map +1 -0
- package/dist/services/audit-checks/fs-nfs-to-sad-ad-qa-check.d.ts +10 -0
- package/dist/services/audit-checks/fs-nfs-to-sad-ad-qa-check.d.ts.map +1 -0
- package/dist/services/audit-checks/fs-nfs-to-sad-ad-qa-check.js +57 -0
- package/dist/services/audit-checks/fs-nfs-to-sad-ad-qa-check.js.map +1 -0
- package/dist/services/audit-checks/fs-nfs-to-ts-check.d.ts +9 -0
- package/dist/services/audit-checks/fs-nfs-to-ts-check.d.ts.map +1 -0
- package/dist/services/audit-checks/fs-nfs-to-ts-check.js +56 -0
- package/dist/services/audit-checks/fs-nfs-to-ts-check.js.map +1 -0
- package/dist/services/audit-checks/inverse-consistency-check.d.ts +7 -0
- package/dist/services/audit-checks/inverse-consistency-check.d.ts.map +1 -0
- package/dist/services/audit-checks/inverse-consistency-check.js +54 -0
- package/dist/services/audit-checks/inverse-consistency-check.js.map +1 -0
- package/dist/services/audit-checks/mapping-check.d.ts +4 -0
- package/dist/services/audit-checks/mapping-check.d.ts.map +1 -0
- package/dist/services/audit-checks/mapping-check.js +74 -0
- package/dist/services/audit-checks/mapping-check.js.map +1 -0
- package/dist/services/audit-checks/orphan-documents-check.d.ts +9 -0
- package/dist/services/audit-checks/orphan-documents-check.d.ts.map +1 -0
- package/dist/services/audit-checks/orphan-documents-check.js +54 -0
- package/dist/services/audit-checks/orphan-documents-check.js.map +1 -0
- package/dist/services/audit-checks/orphan-entities-check.d.ts +4 -0
- package/dist/services/audit-checks/orphan-entities-check.d.ts.map +1 -0
- package/dist/services/audit-checks/orphan-entities-check.js +39 -0
- package/dist/services/audit-checks/orphan-entities-check.js.map +1 -0
- package/dist/services/audit-checks/sad-ad-qa-tc-to-src-check.d.ts +9 -0
- package/dist/services/audit-checks/sad-ad-qa-tc-to-src-check.d.ts.map +1 -0
- package/dist/services/audit-checks/sad-ad-qa-tc-to-src-check.js +56 -0
- package/dist/services/audit-checks/sad-ad-qa-tc-to-src-check.js.map +1 -0
- package/dist/services/audit-checks/sprint-consistency-check.d.ts +4 -0
- package/dist/services/audit-checks/sprint-consistency-check.d.ts.map +1 -0
- package/dist/services/audit-checks/sprint-consistency-check.js +80 -0
- package/dist/services/audit-checks/sprint-consistency-check.js.map +1 -0
- package/dist/services/audit-checks/src-filesystem-only-check.d.ts +10 -0
- package/dist/services/audit-checks/src-filesystem-only-check.d.ts.map +1 -0
- package/dist/services/audit-checks/src-filesystem-only-check.js +106 -0
- package/dist/services/audit-checks/src-filesystem-only-check.js.map +1 -0
- package/dist/services/audit-checks/ts-to-tc-check.d.ts +10 -0
- package/dist/services/audit-checks/ts-to-tc-check.d.ts.map +1 -0
- package/dist/services/audit-checks/ts-to-tc-check.js +58 -0
- package/dist/services/audit-checks/ts-to-tc-check.js.map +1 -0
- package/dist/services/audit-checks/type-mismatch-check.d.ts +4 -0
- package/dist/services/audit-checks/type-mismatch-check.d.ts.map +1 -0
- package/dist/services/audit-checks/type-mismatch-check.js +55 -0
- package/dist/services/audit-checks/type-mismatch-check.js.map +1 -0
- package/dist/services/audit-checks/types.d.ts +66 -0
- package/dist/services/audit-checks/types.d.ts.map +1 -0
- package/dist/services/audit-checks/types.js +30 -0
- package/dist/services/audit-checks/types.js.map +1 -0
- package/dist/services/audit-checks/us-to-fr-nfr-check.d.ts +9 -0
- package/dist/services/audit-checks/us-to-fr-nfr-check.d.ts.map +1 -0
- package/dist/services/audit-checks/us-to-fr-nfr-check.js +56 -0
- package/dist/services/audit-checks/us-to-fr-nfr-check.js.map +1 -0
- package/dist/services/doc-entity-mapping.d.ts +19 -0
- package/dist/services/doc-entity-mapping.d.ts.map +1 -0
- package/dist/services/doc-entity-mapping.js +35 -0
- package/dist/services/doc-entity-mapping.js.map +1 -0
- package/dist/services/document-service.d.ts +58 -0
- package/dist/services/document-service.d.ts.map +1 -0
- package/dist/services/document-service.js +409 -0
- package/dist/services/document-service.js.map +1 -0
- package/dist/services/graph-export-service.d.ts +12 -0
- package/dist/services/graph-export-service.d.ts.map +1 -0
- package/dist/services/graph-export-service.js +112 -0
- package/dist/services/graph-export-service.js.map +1 -0
- package/dist/services/graph-service.d.ts +21 -0
- package/dist/services/graph-service.d.ts.map +1 -0
- package/dist/services/graph-service.js +49 -0
- package/dist/services/graph-service.js.map +1 -0
- package/dist/services/graph-validation-service.d.ts +13 -0
- package/dist/services/graph-validation-service.d.ts.map +1 -0
- package/dist/services/graph-validation-service.js +171 -0
- package/dist/services/graph-validation-service.js.map +1 -0
- package/dist/services/project.d.ts +80 -0
- package/dist/services/project.d.ts.map +1 -0
- package/dist/services/project.js +256 -0
- package/dist/services/project.js.map +1 -0
- package/dist/services/review-service.d.ts +81 -0
- package/dist/services/review-service.d.ts.map +1 -0
- package/dist/services/review-service.js +242 -0
- package/dist/services/review-service.js.map +1 -0
- package/dist/services/schema-migration-service.d.ts +44 -0
- package/dist/services/schema-migration-service.d.ts.map +1 -0
- package/dist/services/schema-migration-service.js +894 -0
- package/dist/services/schema-migration-service.js.map +1 -0
- package/dist/services/sprint.d.ts +71 -0
- package/dist/services/sprint.d.ts.map +1 -0
- package/dist/services/sprint.js +238 -0
- package/dist/services/sprint.js.map +1 -0
- package/dist/services/stage-validator.d.ts +36 -0
- package/dist/services/stage-validator.d.ts.map +1 -0
- package/dist/services/stage-validator.js +78 -0
- package/dist/services/stage-validator.js.map +1 -0
- package/dist/services/task.d.ts +75 -0
- package/dist/services/task.d.ts.map +1 -0
- package/dist/services/task.js +487 -0
- package/dist/services/task.js.map +1 -0
- package/dist/services/validation.d.ts +24 -0
- package/dist/services/validation.d.ts.map +1 -0
- package/dist/services/validation.js +53 -0
- package/dist/services/validation.js.map +1 -0
- package/dist/state-machines/sprint-state.d.ts +25 -0
- package/dist/state-machines/sprint-state.d.ts.map +1 -0
- package/dist/state-machines/sprint-state.js +64 -0
- package/dist/state-machines/sprint-state.js.map +1 -0
- package/dist/state-machines/task-state.d.ts +31 -0
- package/dist/state-machines/task-state.d.ts.map +1 -0
- package/dist/state-machines/task-state.js +83 -0
- package/dist/state-machines/task-state.js.map +1 -0
- package/dist/utils/errors.d.ts +673 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +1447 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/format.d.ts +52 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +65 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/validators/board-integrity.d.ts +25 -0
- package/dist/validators/board-integrity.d.ts.map +1 -0
- package/dist/validators/board-integrity.js +102 -0
- package/dist/validators/board-integrity.js.map +1 -0
- package/dist/validators/board-shape.d.ts +13 -0
- package/dist/validators/board-shape.d.ts.map +1 -0
- package/dist/validators/board-shape.js +74 -0
- package/dist/validators/board-shape.js.map +1 -0
- package/dist/validators/owner-validator.d.ts +30 -0
- package/dist/validators/owner-validator.d.ts.map +1 -0
- package/dist/validators/owner-validator.js +70 -0
- package/dist/validators/owner-validator.js.map +1 -0
- package/dist/validators/spawn-legality.d.ts +19 -0
- package/dist/validators/spawn-legality.d.ts.map +1 -0
- package/dist/validators/spawn-legality.js +77 -0
- package/dist/validators/spawn-legality.js.map +1 -0
- package/dist/validators/state-field-checker.d.ts +8 -0
- package/dist/validators/state-field-checker.d.ts.map +1 -0
- package/dist/validators/state-field-checker.js +47 -0
- package/dist/validators/state-field-checker.js.map +1 -0
- package/dist/validators/state-field-recorder.d.ts +39 -0
- package/dist/validators/state-field-recorder.d.ts.map +1 -0
- package/dist/validators/state-field-recorder.js +62 -0
- package/dist/validators/state-field-recorder.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { ValidationResult } from '../models/entity';
|
|
3
|
+
/**
|
|
4
|
+
* Validate the entire graph for integrity violations.
|
|
5
|
+
* Read-only: does not modify any data.
|
|
6
|
+
*
|
|
7
|
+
* Checks:
|
|
8
|
+
* 1. Dangling relations (from_id or to_id references non-existent document)
|
|
9
|
+
* 2. Type constraint violations (doc type not in relation type's from_types/to_types)
|
|
10
|
+
* 3. Cardinality violations (one_to_one/one_to_many/many_to_one exceeded)
|
|
11
|
+
*/
|
|
12
|
+
export declare function validateGraph(db: Database.Database): ValidationResult;
|
|
13
|
+
//# sourceMappingURL=graph-validation-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-validation-service.d.ts","sourceRoot":"","sources":["../../src/services/graph-validation-service.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAA2B,MAAM,kBAAkB,CAAC;AAElF;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,gBAAgB,CA2JrE"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Graph validation service: read-only graph integrity checks
|
|
3
|
+
// SAD-0003: MOD-011 Graph Validation
|
|
4
|
+
// AD-0009: Validation services are read-only
|
|
5
|
+
// SAD-0035: Updated to use documents(id) instead of entities(id)
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.validateGraph = validateGraph;
|
|
8
|
+
/**
|
|
9
|
+
* Validate the entire graph for integrity violations.
|
|
10
|
+
* Read-only: does not modify any data.
|
|
11
|
+
*
|
|
12
|
+
* Checks:
|
|
13
|
+
* 1. Dangling relations (from_id or to_id references non-existent document)
|
|
14
|
+
* 2. Type constraint violations (doc type not in relation type's from_types/to_types)
|
|
15
|
+
* 3. Cardinality violations (one_to_one/one_to_many/many_to_one exceeded)
|
|
16
|
+
*/
|
|
17
|
+
function validateGraph(db) {
|
|
18
|
+
const violations = [];
|
|
19
|
+
// 1. Check for dangling relations (SAD-0035: use documents instead of entities)
|
|
20
|
+
const danglingFrom = db.prepare(`
|
|
21
|
+
SELECT r.id, r.from_id, r.rel_type, r.to_id
|
|
22
|
+
FROM relations r
|
|
23
|
+
LEFT JOIN documents d ON r.from_id = d.id
|
|
24
|
+
WHERE d.id IS NULL
|
|
25
|
+
`).all();
|
|
26
|
+
for (const rel of danglingFrom) {
|
|
27
|
+
violations.push({
|
|
28
|
+
type: 'dangling',
|
|
29
|
+
relationId: rel.id,
|
|
30
|
+
fromId: rel.from_id,
|
|
31
|
+
relType: rel.rel_type,
|
|
32
|
+
toId: rel.to_id,
|
|
33
|
+
message: `Relation ${rel.id}: from_id "${rel.from_id}" references non-existent document`,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const danglingTo = db.prepare(`
|
|
37
|
+
SELECT r.id, r.from_id, r.rel_type, r.to_id
|
|
38
|
+
FROM relations r
|
|
39
|
+
LEFT JOIN documents d ON r.to_id = d.id
|
|
40
|
+
WHERE d.id IS NULL
|
|
41
|
+
`).all();
|
|
42
|
+
for (const rel of danglingTo) {
|
|
43
|
+
violations.push({
|
|
44
|
+
type: 'dangling',
|
|
45
|
+
relationId: rel.id,
|
|
46
|
+
fromId: rel.from_id,
|
|
47
|
+
relType: rel.rel_type,
|
|
48
|
+
toId: rel.to_id,
|
|
49
|
+
message: `Relation ${rel.id}: to_id "${rel.to_id}" references non-existent document`,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
// 2. Check type constraint violations (SAD-0035: use documents instead of entities)
|
|
53
|
+
const relationTypes = db.prepare('SELECT * FROM relation_types').all();
|
|
54
|
+
const relations = db.prepare('SELECT r.id, r.from_id, r.rel_type, r.to_id, d_from.type as from_type, d_to.type as to_type FROM relations r LEFT JOIN documents d_from ON r.from_id = d_from.id LEFT JOIN documents d_to ON r.to_id = d_to.id').all();
|
|
55
|
+
for (const rel of relations) {
|
|
56
|
+
const rt = relationTypes.find(t => t.name === rel.rel_type);
|
|
57
|
+
if (!rt)
|
|
58
|
+
continue;
|
|
59
|
+
const fromTypes = safeParseJson(rt.from_types, []);
|
|
60
|
+
const toTypes = safeParseJson(rt.to_types, []);
|
|
61
|
+
if (fromTypes.length > 0 && rel.from_type && !fromTypes.includes(rel.from_type)) {
|
|
62
|
+
violations.push({
|
|
63
|
+
type: 'type_constraint',
|
|
64
|
+
relationId: rel.id,
|
|
65
|
+
fromId: rel.from_id,
|
|
66
|
+
relType: rel.rel_type,
|
|
67
|
+
toId: rel.to_id,
|
|
68
|
+
message: `Relation ${rel.id}: from entity type "${rel.from_type}" not in allowed types [${fromTypes.join(', ')}]`,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (toTypes.length > 0 && rel.to_type && !toTypes.includes(rel.to_type)) {
|
|
72
|
+
violations.push({
|
|
73
|
+
type: 'type_constraint',
|
|
74
|
+
relationId: rel.id,
|
|
75
|
+
fromId: rel.from_id,
|
|
76
|
+
relType: rel.rel_type,
|
|
77
|
+
toId: rel.to_id,
|
|
78
|
+
message: `Relation ${rel.id}: to entity type "${rel.to_type}" not in allowed types [${toTypes.join(', ')}]`,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// 3. Check cardinality violations
|
|
83
|
+
for (const rt of relationTypes) {
|
|
84
|
+
const cardinality = (rt.cardinality ?? 'many_to_many');
|
|
85
|
+
if (cardinality === 'many_to_many')
|
|
86
|
+
continue;
|
|
87
|
+
if (cardinality === 'one_to_one') {
|
|
88
|
+
const violators = db.prepare(`
|
|
89
|
+
SELECT from_id, rel_type, COUNT(*) as cnt
|
|
90
|
+
FROM relations WHERE rel_type = ?
|
|
91
|
+
GROUP BY from_id HAVING cnt > 1
|
|
92
|
+
`).all(rt.name);
|
|
93
|
+
for (const v of violators) {
|
|
94
|
+
violations.push({
|
|
95
|
+
type: 'cardinality',
|
|
96
|
+
relationId: 0,
|
|
97
|
+
fromId: v.from_id,
|
|
98
|
+
relType: v.rel_type,
|
|
99
|
+
toId: '',
|
|
100
|
+
message: `Cardinality one_to_one violated: entity "${v.from_id}" has ${v.cnt} outgoing "${v.rel_type}" relations`,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const violatorsTo = db.prepare(`
|
|
104
|
+
SELECT to_id, rel_type, COUNT(*) as cnt
|
|
105
|
+
FROM relations WHERE rel_type = ?
|
|
106
|
+
GROUP BY to_id HAVING cnt > 1
|
|
107
|
+
`).all(rt.name);
|
|
108
|
+
for (const v of violatorsTo) {
|
|
109
|
+
violations.push({
|
|
110
|
+
type: 'cardinality',
|
|
111
|
+
relationId: 0,
|
|
112
|
+
fromId: '',
|
|
113
|
+
relType: v.rel_type,
|
|
114
|
+
toId: v.to_id,
|
|
115
|
+
message: `Cardinality one_to_one violated: entity "${v.to_id}" has ${v.cnt} incoming "${v.rel_type}" relations`,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (cardinality === 'one_to_many') {
|
|
120
|
+
// one_to_many: each target (to_id) can have at most one incoming relation of this type
|
|
121
|
+
const violatorsTo = db.prepare(`
|
|
122
|
+
SELECT to_id, rel_type, COUNT(*) as cnt
|
|
123
|
+
FROM relations WHERE rel_type = ?
|
|
124
|
+
GROUP BY to_id HAVING cnt > 1
|
|
125
|
+
`).all(rt.name);
|
|
126
|
+
for (const v of violatorsTo) {
|
|
127
|
+
violations.push({
|
|
128
|
+
type: 'cardinality',
|
|
129
|
+
relationId: 0,
|
|
130
|
+
fromId: '',
|
|
131
|
+
relType: v.rel_type,
|
|
132
|
+
toId: v.to_id,
|
|
133
|
+
message: `Cardinality one_to_many violated: entity "${v.to_id}" has ${v.cnt} incoming "${v.rel_type}" relations`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (cardinality === 'many_to_one') {
|
|
138
|
+
// many_to_one: each source (from_id) can have at most one outgoing relation of this type
|
|
139
|
+
const violators = db.prepare(`
|
|
140
|
+
SELECT from_id, rel_type, COUNT(*) as cnt
|
|
141
|
+
FROM relations WHERE rel_type = ?
|
|
142
|
+
GROUP BY from_id HAVING cnt > 1
|
|
143
|
+
`).all(rt.name);
|
|
144
|
+
for (const v of violators) {
|
|
145
|
+
violations.push({
|
|
146
|
+
type: 'cardinality',
|
|
147
|
+
relType: v.rel_type,
|
|
148
|
+
relationId: 0,
|
|
149
|
+
fromId: v.from_id,
|
|
150
|
+
toId: '',
|
|
151
|
+
message: `Cardinality many_to_one violated: entity "${v.from_id}" has ${v.cnt} outgoing "${v.rel_type}" relations`,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
valid: violations.length === 0,
|
|
158
|
+
violations,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function safeParseJson(raw, fallback) {
|
|
162
|
+
if (!raw)
|
|
163
|
+
return fallback;
|
|
164
|
+
try {
|
|
165
|
+
return JSON.parse(raw);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return fallback;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=graph-validation-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-validation-service.js","sourceRoot":"","sources":["../../src/services/graph-validation-service.ts"],"names":[],"mappings":";AAAA,6DAA6D;AAC7D,qCAAqC;AACrC,6CAA6C;AAC7C,iEAAiE;;AAcjE,sCA2JC;AApKD;;;;;;;;GAQG;AACH,SAAgB,aAAa,CAAC,EAAqB;IACjD,MAAM,UAAU,GAAgB,EAAE,CAAC;IAEnC,gFAAgF;IAChF,MAAM,YAAY,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;GAK/B,CAAC,CAAC,GAAG,EAA6E,CAAC;IAEpF,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,UAAU,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,GAAG,CAAC,EAAE;YAClB,MAAM,EAAE,GAAG,CAAC,OAAO;YACnB,OAAO,EAAE,GAAG,CAAC,QAAQ;YACrB,IAAI,EAAE,GAAG,CAAC,KAAK;YACf,OAAO,EAAE,YAAY,GAAG,CAAC,EAAE,cAAc,GAAG,CAAC,OAAO,oCAAoC;SACzF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;GAK7B,CAAC,CAAC,GAAG,EAA6E,CAAC;IAEpF,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,UAAU,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,GAAG,CAAC,EAAE;YAClB,MAAM,EAAE,GAAG,CAAC,OAAO;YACnB,OAAO,EAAE,GAAG,CAAC,QAAQ;YACrB,IAAI,EAAE,GAAG,CAAC,KAAK;YACf,OAAO,EAAE,YAAY,GAAG,CAAC,EAAE,YAAY,GAAG,CAAC,KAAK,oCAAoC;SACrF,CAAC,CAAC;IACL,CAAC;IAED,oFAAoF;IACpF,MAAM,aAAa,GAAG,EAAE,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC,GAAG,EAAoB,CAAC;IACzF,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC,gNAAgN,CAAC,CAAC,GAAG,EAA+H,CAAC;IAElX,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5D,IAAI,CAAC,EAAE;YAAE,SAAS;QAElB,MAAM,SAAS,GAAG,aAAa,CAAW,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,aAAa,CAAW,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAEzD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAChF,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,iBAAiB;gBACvB,UAAU,EAAE,GAAG,CAAC,EAAE;gBAClB,MAAM,EAAE,GAAG,CAAC,OAAO;gBACnB,OAAO,EAAE,GAAG,CAAC,QAAQ;gBACrB,IAAI,EAAE,GAAG,CAAC,KAAK;gBACf,OAAO,EAAE,YAAY,GAAG,CAAC,EAAE,uBAAuB,GAAG,CAAC,SAAS,2BAA2B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;aAClH,CAAC,CAAC;QACL,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACxE,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,iBAAiB;gBACvB,UAAU,EAAE,GAAG,CAAC,EAAE;gBAClB,MAAM,EAAE,GAAG,CAAC,OAAO;gBACnB,OAAO,EAAE,GAAG,CAAC,QAAQ;gBACrB,IAAI,EAAE,GAAG,CAAC,KAAK;gBACf,OAAO,EAAE,YAAY,GAAG,CAAC,EAAE,qBAAqB,GAAG,CAAC,OAAO,2BAA2B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;aAC5G,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,KAAK,MAAM,EAAE,IAAI,aAAa,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,CAAC,EAAE,CAAC,WAAW,IAAI,cAAc,CAAW,CAAC;QACjE,IAAI,WAAW,KAAK,cAAc;YAAE,SAAS;QAE7C,IAAI,WAAW,KAAK,YAAY,EAAE,CAAC;YACjC,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC;;;;OAI5B,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAA8D,CAAC;YAC7E,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC1B,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,aAAa;oBACnB,UAAU,EAAE,CAAC;oBACb,MAAM,EAAE,CAAC,CAAC,OAAO;oBACjB,OAAO,EAAE,CAAC,CAAC,QAAQ;oBACnB,IAAI,EAAE,EAAE;oBACR,OAAO,EAAE,4CAA4C,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,QAAQ,aAAa;iBAClH,CAAC,CAAC;YACL,CAAC;YACD,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC;;;;OAI9B,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAA4D,CAAC;YAC3E,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;gBAC5B,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,aAAa;oBACnB,UAAU,EAAE,CAAC;oBACb,MAAM,EAAE,EAAE;oBACV,OAAO,EAAE,CAAC,CAAC,QAAQ;oBACnB,IAAI,EAAE,CAAC,CAAC,KAAK;oBACb,OAAO,EAAE,4CAA4C,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,QAAQ,aAAa;iBAChH,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,IAAI,WAAW,KAAK,aAAa,EAAE,CAAC;YAClC,uFAAuF;YACvF,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC;;;;OAI9B,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAA4D,CAAC;YAC3E,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;gBAC5B,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,aAAa;oBACnB,UAAU,EAAE,CAAC;oBACb,MAAM,EAAE,EAAE;oBACV,OAAO,EAAE,CAAC,CAAC,QAAQ;oBACnB,IAAI,EAAE,CAAC,CAAC,KAAK;oBACb,OAAO,EAAE,6CAA6C,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,QAAQ,aAAa;iBACjH,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,IAAI,WAAW,KAAK,aAAa,EAAE,CAAC;YAClC,yFAAyF;YACzF,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC;;;;OAI5B,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAA8D,CAAC;YAC7E,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC1B,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,aAAa;oBACnB,OAAO,EAAE,CAAC,CAAC,QAAQ;oBACnB,UAAU,EAAE,CAAC;oBACb,MAAM,EAAE,CAAC,CAAC,OAAO;oBACjB,IAAI,EAAE,EAAE;oBACR,OAAO,EAAE,6CAA6C,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,QAAQ,aAAa;iBACnH,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,UAAU,CAAC,MAAM,KAAK,CAAC;QAC9B,UAAU;KACX,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAI,GAA8B,EAAE,QAAW;IACnE,IAAI,CAAC,GAAG;QAAE,OAAO,QAAQ,CAAC;IAC1B,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;IAAC,CAAC;IACpC,MAAM,CAAC;QAAC,OAAO,QAAQ,CAAC;IAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { ProjectResult, ProjectInfo, ProjectsRegistry } from '../models/project';
|
|
2
|
+
import { resolveProject } from '../config/resolver';
|
|
3
|
+
/** Options for project operations */
|
|
4
|
+
export interface ProjectServiceOptions {
|
|
5
|
+
/** Override registry path (for testing) */
|
|
6
|
+
registryPath?: string;
|
|
7
|
+
/** Override cwd for resolution (for testing) */
|
|
8
|
+
cwd?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Validate project name format per FR-URD-002-0011:
|
|
12
|
+
* - Lowercase alphanumeric and hyphens only
|
|
13
|
+
* - Starts with a letter
|
|
14
|
+
* - Ends with a letter or digit
|
|
15
|
+
* - No consecutive hyphens
|
|
16
|
+
* - 1–64 characters
|
|
17
|
+
*
|
|
18
|
+
* @throws ProjectEmptyNameError (ERR-PROJ-003) if name is empty/whitespace
|
|
19
|
+
* @throws ProjectInvalidNameError (ERR-PROJ-008) if name format is invalid
|
|
20
|
+
*/
|
|
21
|
+
export declare function validateProjectName(name: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* Create a new project: make the folder, initialize pmp/project.db,
|
|
24
|
+
* register in ~/.config/cortex-cli/registry.json.
|
|
25
|
+
*
|
|
26
|
+
* @throws ProjectEmptyNameError (ERR-PROJ-003) if name is empty
|
|
27
|
+
* @throws ProjectInvalidNameError (ERR-PROJ-008) if name format is invalid
|
|
28
|
+
* @throws DuplicateProjectError (ERR-PROJ-001) if the project name already exists
|
|
29
|
+
* @throws ProjectPathExistsError (ERR-PROJ-002) if the folder path already exists (directory)
|
|
30
|
+
* @throws ProjectPathNotDirectoryError (ERR-PROJ-013) if the path exists as a file/symlink
|
|
31
|
+
*/
|
|
32
|
+
export declare function createProject(name: string, folder: string, opts?: ProjectServiceOptions): ProjectResult;
|
|
33
|
+
/**
|
|
34
|
+
* Register an existing project folder.
|
|
35
|
+
* Creates pmp/project.db if it doesn't exist.
|
|
36
|
+
* Adds to ~/.config/cortex-cli/registry.json.
|
|
37
|
+
*
|
|
38
|
+
* @throws ProjectEmptyNameError (ERR-PROJ-003) if name is empty
|
|
39
|
+
* @throws ProjectInvalidNameError (ERR-PROJ-008) if name format is invalid
|
|
40
|
+
* @throws DuplicateProjectError (ERR-PROJ-001) if the project name already exists
|
|
41
|
+
* @throws ProjectFolderNotFoundError (ERR-PROJ-005) if the folder doesn't exist
|
|
42
|
+
*/
|
|
43
|
+
export declare function registerProject(name: string, folder: string, opts?: ProjectServiceOptions): ProjectResult;
|
|
44
|
+
/**
|
|
45
|
+
* Remove a project from the global registry.
|
|
46
|
+
* Does NOT delete the project folder or database.
|
|
47
|
+
*
|
|
48
|
+
* @throws ProjectNotFoundError (ERR-PROJ-007) if the project doesn't exist
|
|
49
|
+
*/
|
|
50
|
+
export declare function removeProject(name: string, opts?: ProjectServiceOptions): {
|
|
51
|
+
name: string;
|
|
52
|
+
folder: string;
|
|
53
|
+
dbPath: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* List all registered projects.
|
|
57
|
+
*/
|
|
58
|
+
export declare function listAllProjects(opts?: ProjectServiceOptions): ProjectsRegistry;
|
|
59
|
+
/**
|
|
60
|
+
* Set the default project.
|
|
61
|
+
*
|
|
62
|
+
* @throws ProjectNotFoundError (ERR-PROJ-007) if the project doesn't exist
|
|
63
|
+
*/
|
|
64
|
+
export declare function setProjectDefault(name: string, opts?: ProjectServiceOptions): void;
|
|
65
|
+
/**
|
|
66
|
+
* Get the current default project name.
|
|
67
|
+
*/
|
|
68
|
+
export declare function getDefaultProjectName(opts?: ProjectServiceOptions): string | null;
|
|
69
|
+
/**
|
|
70
|
+
* Show project details: folder, database path, sprint summary, entity counts.
|
|
71
|
+
*
|
|
72
|
+
* @throws ProjectNotFoundError (ERR-PROJ-007) if the project doesn't exist
|
|
73
|
+
*/
|
|
74
|
+
export declare function getProjectInfo(name: string, opts?: ProjectServiceOptions): ProjectInfo;
|
|
75
|
+
/**
|
|
76
|
+
* Resolve the project to use for a command.
|
|
77
|
+
* Delegates to ProjectResolver.
|
|
78
|
+
*/
|
|
79
|
+
export declare function resolveProjectForCommand(opts?: ProjectServiceOptions): ReturnType<typeof resolveProject>;
|
|
80
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/services/project.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAWtF,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAYpD,qCAAqC;AACrC,MAAM,WAAW,qBAAqB;IACpC,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CA4BtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,aAAa,CA2DvG;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,aAAa,CA2CzG;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAS1H;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,qBAAqB,GAAG,gBAAgB,CAE9E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAElF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,CAAC,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CAGjF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,WAAW,CAmCtF;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,CAAC,EAAE,qBAAqB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAKxG"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Project service: orchestrates database and registry
|
|
3
|
+
// Implements AD-0004: ProjectService Orchestrates Database and Registry
|
|
4
|
+
// + FS-SS-002-0001 (create), FS-SS-002-0002 (register)
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateProjectName = validateProjectName;
|
|
7
|
+
exports.createProject = createProject;
|
|
8
|
+
exports.registerProject = registerProject;
|
|
9
|
+
exports.removeProject = removeProject;
|
|
10
|
+
exports.listAllProjects = listAllProjects;
|
|
11
|
+
exports.setProjectDefault = setProjectDefault;
|
|
12
|
+
exports.getDefaultProjectName = getDefaultProjectName;
|
|
13
|
+
exports.getProjectInfo = getProjectInfo;
|
|
14
|
+
exports.resolveProjectForCommand = resolveProjectForCommand;
|
|
15
|
+
const fs_1 = require("fs");
|
|
16
|
+
const path_1 = require("path");
|
|
17
|
+
const connection_1 = require("../db/connection");
|
|
18
|
+
const migration_1 = require("../db/migration");
|
|
19
|
+
const registry_1 = require("../config/registry");
|
|
20
|
+
const resolver_1 = require("../config/resolver");
|
|
21
|
+
const errors_1 = require("../utils/errors");
|
|
22
|
+
/**
|
|
23
|
+
* Validate project name format per FR-URD-002-0011:
|
|
24
|
+
* - Lowercase alphanumeric and hyphens only
|
|
25
|
+
* - Starts with a letter
|
|
26
|
+
* - Ends with a letter or digit
|
|
27
|
+
* - No consecutive hyphens
|
|
28
|
+
* - 1–64 characters
|
|
29
|
+
*
|
|
30
|
+
* @throws ProjectEmptyNameError (ERR-PROJ-003) if name is empty/whitespace
|
|
31
|
+
* @throws ProjectInvalidNameError (ERR-PROJ-008) if name format is invalid
|
|
32
|
+
*/
|
|
33
|
+
function validateProjectName(name) {
|
|
34
|
+
if (!name || name.trim().length === 0) {
|
|
35
|
+
throw new errors_1.ProjectEmptyNameError();
|
|
36
|
+
}
|
|
37
|
+
// Single character: just needs to be a lowercase letter
|
|
38
|
+
if (name.length === 1) {
|
|
39
|
+
if (!/^[a-z]$/.test(name)) {
|
|
40
|
+
throw new errors_1.ProjectInvalidNameError(name);
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// Multi-character: full regex
|
|
45
|
+
// /^[a-z][a-z0-9-]{0,62}[a-z0-9]$/ plus no consecutive hyphens
|
|
46
|
+
if (!/^[a-z][a-z0-9-]{0,62}[a-z0-9]$/.test(name)) {
|
|
47
|
+
throw new errors_1.ProjectInvalidNameError(name);
|
|
48
|
+
}
|
|
49
|
+
// Check for consecutive hyphens
|
|
50
|
+
if (name.includes('--')) {
|
|
51
|
+
throw new errors_1.ProjectInvalidNameError(name);
|
|
52
|
+
}
|
|
53
|
+
// Check total length (1-64)
|
|
54
|
+
if (name.length > 64) {
|
|
55
|
+
throw new errors_1.ProjectInvalidNameError(name);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Create a new project: make the folder, initialize pmp/project.db,
|
|
60
|
+
* register in ~/.config/cortex-cli/registry.json.
|
|
61
|
+
*
|
|
62
|
+
* @throws ProjectEmptyNameError (ERR-PROJ-003) if name is empty
|
|
63
|
+
* @throws ProjectInvalidNameError (ERR-PROJ-008) if name format is invalid
|
|
64
|
+
* @throws DuplicateProjectError (ERR-PROJ-001) if the project name already exists
|
|
65
|
+
* @throws ProjectPathExistsError (ERR-PROJ-002) if the folder path already exists (directory)
|
|
66
|
+
* @throws ProjectPathNotDirectoryError (ERR-PROJ-013) if the path exists as a file/symlink
|
|
67
|
+
*/
|
|
68
|
+
function createProject(name, folder, opts) {
|
|
69
|
+
// Validate name format (FS-SS-002-0001 VR-003/VR-006)
|
|
70
|
+
validateProjectName(name);
|
|
71
|
+
// Check for duplicate name
|
|
72
|
+
try {
|
|
73
|
+
const existing = (0, registry_1.getProject)(name, opts?.registryPath);
|
|
74
|
+
if (existing) {
|
|
75
|
+
throw new errors_1.DuplicateProjectError(name);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
// ProjectNotFoundError is expected if name doesn't exist yet
|
|
80
|
+
if (!(err instanceof errors_1.ProjectNotFoundError))
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
83
|
+
const absoluteFolder = (0, path_1.resolve)(folder);
|
|
84
|
+
// Check if path already exists (FS-SS-002-0001 VR-002)
|
|
85
|
+
if ((0, fs_1.existsSync)(absoluteFolder)) {
|
|
86
|
+
const stat = (0, fs_1.lstatSync)(absoluteFolder);
|
|
87
|
+
if (stat.isDirectory()) {
|
|
88
|
+
throw new errors_1.ProjectPathExistsError(absoluteFolder);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
throw new errors_1.ProjectPathNotDirectoryError(absoluteFolder);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Create the project folder
|
|
95
|
+
try {
|
|
96
|
+
(0, fs_1.mkdirSync)(absoluteFolder, { recursive: true });
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
throw new errors_1.ProjectFolderCreateError(absoluteFolder, err instanceof Error ? err.message : String(err));
|
|
100
|
+
}
|
|
101
|
+
const dbPath = `${absoluteFolder}/pmp/project.db`;
|
|
102
|
+
const dbExisted = (0, fs_1.existsSync)(dbPath);
|
|
103
|
+
// Initialize the database
|
|
104
|
+
const db = (0, connection_1.openConnection)(dbPath);
|
|
105
|
+
try {
|
|
106
|
+
(0, migration_1.initializeSchema)(db);
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
db.close();
|
|
110
|
+
}
|
|
111
|
+
// Register in global registry
|
|
112
|
+
const registry = (0, registry_1.addProject)(name, absoluteFolder, opts?.registryPath);
|
|
113
|
+
const isDefault = registry.default === name;
|
|
114
|
+
return {
|
|
115
|
+
name,
|
|
116
|
+
folder: absoluteFolder,
|
|
117
|
+
dbPath,
|
|
118
|
+
isNew: !dbExisted,
|
|
119
|
+
isDefault,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Register an existing project folder.
|
|
124
|
+
* Creates pmp/project.db if it doesn't exist.
|
|
125
|
+
* Adds to ~/.config/cortex-cli/registry.json.
|
|
126
|
+
*
|
|
127
|
+
* @throws ProjectEmptyNameError (ERR-PROJ-003) if name is empty
|
|
128
|
+
* @throws ProjectInvalidNameError (ERR-PROJ-008) if name format is invalid
|
|
129
|
+
* @throws DuplicateProjectError (ERR-PROJ-001) if the project name already exists
|
|
130
|
+
* @throws ProjectFolderNotFoundError (ERR-PROJ-005) if the folder doesn't exist
|
|
131
|
+
*/
|
|
132
|
+
function registerProject(name, folder, opts) {
|
|
133
|
+
// Validate name format (FS-SS-002-0002 VR-005)
|
|
134
|
+
validateProjectName(name);
|
|
135
|
+
// Check for duplicate name
|
|
136
|
+
try {
|
|
137
|
+
const existing = (0, registry_1.getProject)(name, opts?.registryPath);
|
|
138
|
+
if (existing) {
|
|
139
|
+
throw new errors_1.DuplicateProjectError(name);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
if (!(err instanceof errors_1.ProjectNotFoundError))
|
|
144
|
+
throw err;
|
|
145
|
+
}
|
|
146
|
+
const absoluteFolder = (0, path_1.resolve)(folder);
|
|
147
|
+
// Verify folder exists (FS-SS-002-0002 VR-001)
|
|
148
|
+
if (!(0, fs_1.existsSync)(absoluteFolder)) {
|
|
149
|
+
throw new errors_1.ProjectFolderNotFoundError(absoluteFolder);
|
|
150
|
+
}
|
|
151
|
+
const dbPath = `${absoluteFolder}/pmp/project.db`;
|
|
152
|
+
const dbExisted = (0, fs_1.existsSync)(dbPath);
|
|
153
|
+
// Initialize the database
|
|
154
|
+
const db = (0, connection_1.openConnection)(dbPath);
|
|
155
|
+
try {
|
|
156
|
+
(0, migration_1.initializeSchema)(db);
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
db.close();
|
|
160
|
+
}
|
|
161
|
+
// Register in global registry
|
|
162
|
+
const registry = (0, registry_1.addProject)(name, absoluteFolder, opts?.registryPath);
|
|
163
|
+
const isDefault = registry.default === name;
|
|
164
|
+
return {
|
|
165
|
+
name,
|
|
166
|
+
folder: absoluteFolder,
|
|
167
|
+
dbPath,
|
|
168
|
+
isNew: !dbExisted,
|
|
169
|
+
isDefault,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Remove a project from the global registry.
|
|
174
|
+
* Does NOT delete the project folder or database.
|
|
175
|
+
*
|
|
176
|
+
* @throws ProjectNotFoundError (ERR-PROJ-007) if the project doesn't exist
|
|
177
|
+
*/
|
|
178
|
+
function removeProject(name, opts) {
|
|
179
|
+
const entry = (0, registry_1.getProject)(name, opts?.registryPath);
|
|
180
|
+
(0, registry_1.removeProject)(name, opts?.registryPath);
|
|
181
|
+
return {
|
|
182
|
+
name,
|
|
183
|
+
folder: entry.folder,
|
|
184
|
+
dbPath: `${entry.folder}/pmp/project.db`,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* List all registered projects.
|
|
189
|
+
*/
|
|
190
|
+
function listAllProjects(opts) {
|
|
191
|
+
return (0, registry_1.listProjects)(opts?.registryPath);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Set the default project.
|
|
195
|
+
*
|
|
196
|
+
* @throws ProjectNotFoundError (ERR-PROJ-007) if the project doesn't exist
|
|
197
|
+
*/
|
|
198
|
+
function setProjectDefault(name, opts) {
|
|
199
|
+
(0, registry_1.setDefaultProject)(name, opts?.registryPath);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get the current default project name.
|
|
203
|
+
*/
|
|
204
|
+
function getDefaultProjectName(opts) {
|
|
205
|
+
const registry = (0, registry_1.loadRegistry)(opts?.registryPath);
|
|
206
|
+
return registry.default;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Show project details: folder, database path, sprint summary, entity counts.
|
|
210
|
+
*
|
|
211
|
+
* @throws ProjectNotFoundError (ERR-PROJ-007) if the project doesn't exist
|
|
212
|
+
*/
|
|
213
|
+
function getProjectInfo(name, opts) {
|
|
214
|
+
const entry = (0, registry_1.getProject)(name, opts?.registryPath);
|
|
215
|
+
const registry = (0, registry_1.loadRegistry)(opts?.registryPath);
|
|
216
|
+
const dbPath = `${entry.folder}/pmp/project.db`;
|
|
217
|
+
const isDefault = registry.default === name;
|
|
218
|
+
// Query the database for summary counts
|
|
219
|
+
let sprintCount = 0;
|
|
220
|
+
let activeSprintCount = 0;
|
|
221
|
+
let docCount = 0;
|
|
222
|
+
let taskCount = 0;
|
|
223
|
+
if ((0, fs_1.existsSync)(dbPath)) {
|
|
224
|
+
const db = (0, connection_1.openConnection)(dbPath);
|
|
225
|
+
try {
|
|
226
|
+
sprintCount = db.prepare('SELECT COUNT(*) as c FROM sprints').get().c;
|
|
227
|
+
activeSprintCount = db.prepare("SELECT COUNT(*) as c FROM sprints WHERE status IN ('PLANNING','IN EXECUTION','CLOSING')").get().c;
|
|
228
|
+
docCount = db.prepare('SELECT COUNT(*) as c FROM documents').get().c;
|
|
229
|
+
taskCount = db.prepare('SELECT COUNT(*) as c FROM tasks').get().c;
|
|
230
|
+
}
|
|
231
|
+
finally {
|
|
232
|
+
db.close();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
name,
|
|
237
|
+
folder: entry.folder,
|
|
238
|
+
dbPath,
|
|
239
|
+
isDefault,
|
|
240
|
+
sprintCount,
|
|
241
|
+
activeSprintCount,
|
|
242
|
+
docCount,
|
|
243
|
+
taskCount,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Resolve the project to use for a command.
|
|
248
|
+
* Delegates to ProjectResolver.
|
|
249
|
+
*/
|
|
250
|
+
function resolveProjectForCommand(opts) {
|
|
251
|
+
return (0, resolver_1.resolveProject)({
|
|
252
|
+
registryPath: opts?.registryPath,
|
|
253
|
+
cwd: opts?.cwd,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/services/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { Review, ReviewDetail, ReviewAddOptions, TestReport, TestReportAddOptions, Lesson, LessonAddOptions, LessonResult, LessonUpdateFields } from '../models/review';
|
|
3
|
+
/**
|
|
4
|
+
* Add a review with explicit caller-provided 4-digit ID.
|
|
5
|
+
* Content must be provided (from --content-file).
|
|
6
|
+
*
|
|
7
|
+
* SAD-0031 Part A: No advisory lock — caller provides explicit ID.
|
|
8
|
+
* Duplicate validation via EXISTS on composite index (sprint_id, review_num).
|
|
9
|
+
*/
|
|
10
|
+
export declare function addReview(db: Database.Database, sprintId: string, reviewId: string, reviewType: string, verdict: string, content: string, opts?: ReviewAddOptions): Review;
|
|
11
|
+
/**
|
|
12
|
+
* List reviews for a sprint.
|
|
13
|
+
*/
|
|
14
|
+
export declare function listReviews(db: Database.Database, sprintId: string, filters?: {
|
|
15
|
+
type?: string;
|
|
16
|
+
verdict?: string;
|
|
17
|
+
}): Review[];
|
|
18
|
+
/**
|
|
19
|
+
* Get a review by review number within a sprint (SAD-0010 Part C).
|
|
20
|
+
* Both reviewNum and sprintId are required.
|
|
21
|
+
*
|
|
22
|
+
* @param db - Database connection
|
|
23
|
+
* @param reviewNum - Review number (1-based, displayed to user)
|
|
24
|
+
* @param sprintId - Sprint ID (required)
|
|
25
|
+
* @returns Review detail
|
|
26
|
+
* @throws ReviewNotInSprintError if review not found in the specified sprint
|
|
27
|
+
*/
|
|
28
|
+
export declare function getReview(db: Database.Database, reviewNum: number, sprintId: string): ReviewDetail;
|
|
29
|
+
/**
|
|
30
|
+
* Add a test report with explicit caller-provided 4-digit ID.
|
|
31
|
+
* SAD-0031 Part A: No advisory lock, no task association.
|
|
32
|
+
* Duplicate validation via EXISTS on composite index (sprint_id, id).
|
|
33
|
+
*/
|
|
34
|
+
export declare function addTestReport(db: Database.Database, sprintId: string, testReportId: string, total: number, passed: number, failed: number, opts?: TestReportAddOptions): TestReport;
|
|
35
|
+
/**
|
|
36
|
+
* List test reports. Task filter removed per SAD-0031 Part B.
|
|
37
|
+
*/
|
|
38
|
+
export declare function listTestReports(db: Database.Database, sprintId?: string): TestReport[];
|
|
39
|
+
/**
|
|
40
|
+
* Get a single test report by caller-provided ID and sprint.
|
|
41
|
+
* SAD-0031 Part A: sprint-scoped lookup by explicit ID string.
|
|
42
|
+
*
|
|
43
|
+
* @param db - Database connection
|
|
44
|
+
* @param testReportId - Caller-provided test report ID (e.g., "0001")
|
|
45
|
+
* @param sprintId - Sprint ID (required per URD-026)
|
|
46
|
+
* @returns Test report
|
|
47
|
+
* @throws error with ERR-TESTREPORT-004 if not found
|
|
48
|
+
*/
|
|
49
|
+
export declare function getTestReport(db: Database.Database, testReportId: string, sprintId: string): TestReport;
|
|
50
|
+
/**
|
|
51
|
+
* Add a lesson (retained for internal use, e.g., sprint lessons-data export).
|
|
52
|
+
* Not CLI-facing — the CLI exposes only show and update.
|
|
53
|
+
* Post-URD-026: metadata removed, content-only.
|
|
54
|
+
*/
|
|
55
|
+
export declare function addLesson(db: Database.Database, _sprintId: string, _title: string, description: string, _category: string, _opts?: LessonAddOptions): Lesson;
|
|
56
|
+
/**
|
|
57
|
+
* List lessons (retained for internal use; post-URD-026 no longer sprint-scoped).
|
|
58
|
+
* Not CLI-facing.
|
|
59
|
+
*/
|
|
60
|
+
export declare function listLessons(db: Database.Database, _sprintId?: string): Lesson[];
|
|
61
|
+
/**
|
|
62
|
+
* Get the project's single lesson (singleton pattern, SAD-0010 Part B).
|
|
63
|
+
* No ID argument — exactly one lesson per project.
|
|
64
|
+
*
|
|
65
|
+
* @param db - Database connection
|
|
66
|
+
* @returns LessonResult
|
|
67
|
+
* @throws LessonNotFoundError (ERR-LESSON-001) if no lesson exists
|
|
68
|
+
*/
|
|
69
|
+
export declare function getLesson(db: Database.Database): LessonResult;
|
|
70
|
+
/**
|
|
71
|
+
* Update the project's single lesson (singleton pattern, post-URD-026).
|
|
72
|
+
* Upsert semantics per AD-0029: creates if absent, updates if exists.
|
|
73
|
+
* Content-only — all metadata fields removed (URD-026 Part B).
|
|
74
|
+
*
|
|
75
|
+
* @param db - Database connection
|
|
76
|
+
* @param updates - Fields to update; content required
|
|
77
|
+
* @returns Updated LessonResult
|
|
78
|
+
* @throws LessonNoUpdateFieldsError if content is empty/missing
|
|
79
|
+
*/
|
|
80
|
+
export declare function updateLesson(db: Database.Database, updates: LessonUpdateFields): LessonResult;
|
|
81
|
+
//# sourceMappingURL=review-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-service.d.ts","sourceRoot":"","sources":["../../src/services/review-service.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,EAAE,gBAAgB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAiC7K;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,gBAAgB,GACtB,MAAM,CAuCR;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,MAAM,EAAE,CAUV;AAWD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAalG;AAID;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,oBAAoB,GAC1B,UAAU,CAsCZ;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,UAAU,EAAE,CAOd;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CAQvG;AAcD;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,gBAAgB,GACvB,MAAM,CAgBR;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/E;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,YAAY,CAM7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,OAAO,EAAE,kBAAkB,GAC1B,YAAY,CA2Bd"}
|