canary-test-cli 5.15.0 → 6.0.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.
Files changed (79) hide show
  1. package/agent/frameworks/registry.json +655 -0
  2. package/bin/canary.js +20 -15
  3. package/dist/doctor-manifest.d.ts +94 -0
  4. package/dist/doctor.d.ts +67 -0
  5. package/dist/engine/analysis/cli.js +270 -0
  6. package/dist/engine/analysis/engine.js +146 -0
  7. package/dist/engine/analysis/reports.js +0 -0
  8. package/dist/engine/analysis/rows.js +9 -0
  9. package/dist/engine/cli-commands.js +618 -0
  10. package/dist/engine/cli-common.js +60 -0
  11. package/dist/engine/cli.core.js +208 -0
  12. package/dist/engine/cli.js +31 -0
  13. package/dist/engine/company-knowledge-cli.js +201 -0
  14. package/dist/engine/core/ci-env.js +33 -0
  15. package/dist/engine/core/classifier.js +192 -0
  16. package/dist/engine/core/company-knowledge.js +765 -0
  17. package/dist/engine/core/config-validation.js +74 -0
  18. package/dist/engine/core/detection.js +48 -0
  19. package/dist/engine/core/domain-scanner.js +212 -0
  20. package/dist/engine/core/environment-detect.js +410 -0
  21. package/dist/engine/core/executor.js +181 -0
  22. package/dist/engine/core/feedback.js +93 -0
  23. package/dist/engine/core/fixture-scanner.js +173 -0
  24. package/dist/engine/core/framework-registry.js +123 -0
  25. package/dist/engine/core/mcp-validator.js +218 -0
  26. package/dist/engine/core/metadata-scanner.js +147 -0
  27. package/dist/engine/core/migrator.js +1112 -0
  28. package/dist/engine/core/overlays.js +176 -0
  29. package/dist/engine/core/pattern-healer.js +147 -0
  30. package/dist/engine/core/pattern-matcher.js +255 -0
  31. package/dist/engine/core/quality-scorer.js +213 -0
  32. package/dist/engine/core/recommender.js +152 -0
  33. package/dist/engine/core/reporter.js +211 -0
  34. package/dist/engine/core/scaffolder.js +236 -0
  35. package/dist/engine/core/skill-registry.js +522 -0
  36. package/dist/engine/core/static-linter.js +237 -0
  37. package/dist/engine/core/ticket-updater.js +639 -0
  38. package/dist/engine/core/workflow-discovery.js +693 -0
  39. package/dist/engine/guardian/agent-tier.js +338 -0
  40. package/dist/engine/guardian/analysis-emit.js +201 -0
  41. package/dist/engine/guardian/cli.js +787 -0
  42. package/dist/engine/guardian/coverage.js +1055 -0
  43. package/dist/engine/guardian/delta-emitter.js +46 -0
  44. package/dist/engine/guardian/diff-extractor.js +257 -0
  45. package/dist/engine/guardian/hard-gate.js +373 -0
  46. package/dist/engine/guardian/impact-mapper.js +121 -0
  47. package/dist/engine/guardian/pr-check.js +975 -0
  48. package/dist/engine/guardian/pr-comment.js +200 -0
  49. package/dist/engine/guardian/summary-emitter.js +94 -0
  50. package/dist/engine/guardian/tier.js +58 -0
  51. package/dist/engine/history/cli.js +303 -0
  52. package/dist/engine/history/detector.js +68 -0
  53. package/dist/engine/history/ndjson-store.js +177 -0
  54. package/dist/engine/history/record.js +14 -0
  55. package/dist/engine/history/schema.js +59 -0
  56. package/dist/engine/history/store.js +47 -0
  57. package/dist/engine/history/supabase-store.js +113 -0
  58. package/dist/engine/main-deps.js +105 -0
  59. package/dist/engine/mcp-server.js +647 -0
  60. package/dist/engine/package.json +4 -0
  61. package/dist/engine/skills-cli.js +181 -0
  62. package/dist/engine/ui/banner.js +50 -0
  63. package/dist/engine/util/coalesce.js +12 -0
  64. package/dist/engine/util/round.js +43 -0
  65. package/dist/engine/workflow-cli.js +242 -0
  66. package/dist/engine-checks.d.ts +49 -0
  67. package/dist/overlay-commands.d.ts +81 -0
  68. package/dist/overlay-conflicts.d.ts +33 -0
  69. package/dist/overlay-lint.d.ts +19 -0
  70. package/dist/overlays-registry.d.ts +74 -0
  71. package/dist/reporters/testtracker.d.ts +89 -0
  72. package/dist/reporters/testtracker.js +195 -0
  73. package/dist/router.d.ts +12 -0
  74. package/dist/router.js +4 -4
  75. package/dist/skill-requirements.d.ts +57 -0
  76. package/dist/source-spec.d.ts +20 -0
  77. package/package.json +30 -6
  78. package/bin/canary +0 -0
  79. package/scripts/install.js +0 -104
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Map an `ApiDiff` against test coverage rows to produce impact gaps.
3
+ *
4
+ * Faithful TypeScript port of `agent/guardian/impact_mapper.py`. Coverage rows
5
+ * come from canary coverage (coverage-report.json) — each row identifies which
6
+ * test exercises which endpoint.
7
+ *
8
+ * Severity rules:
9
+ * CRITICAL — removed endpoint with existing tests (tests will break)
10
+ * HIGH — added endpoint with no coverage (gap), or changed with no coverage
11
+ * MEDIUM — changed endpoint with existing tests (silent contract drift risk)
12
+ * LOW — added endpoint that already has coverage (rare, shared fixtures)
13
+ */
14
+ import { ChangeType } from './diff-extractor.js';
15
+ /** Python: `Severity(str, Enum)`. */
16
+ export var Severity;
17
+ (function (Severity) {
18
+ Severity["CRITICAL"] = "critical";
19
+ Severity["HIGH"] = "high";
20
+ Severity["MEDIUM"] = "medium";
21
+ Severity["LOW"] = "low";
22
+ })(Severity || (Severity = {}));
23
+ /**
24
+ * Python: `Severity.sort_key` (ascending — CRITICAL sorts first). Imported by
25
+ * other guardian modules as the canonical severity ordering.
26
+ */
27
+ export const SEVERITY_SORT_KEY = {
28
+ [Severity.CRITICAL]: 0,
29
+ [Severity.HIGH]: 1,
30
+ [Severity.MEDIUM]: 2,
31
+ [Severity.LOW]: 3,
32
+ };
33
+ /** Python: `Severity.sort_key` accessor. */
34
+ export function severitySortKey(severity) {
35
+ return SEVERITY_SORT_KEY[severity];
36
+ }
37
+ /** Python: `ImpactGap` dataclass. */
38
+ export class ImpactGap {
39
+ path;
40
+ method;
41
+ // `string | null`: carries through an EndpointChange.operation_id that was a
42
+ // present-null in the source spec (Python assigns change.operation_id as-is).
43
+ operation_id;
44
+ change_type;
45
+ severity;
46
+ affected_tests;
47
+ constructor(init) {
48
+ this.path = init.path;
49
+ this.method = init.method;
50
+ this.operation_id = init.operation_id;
51
+ this.change_type = init.change_type;
52
+ this.severity = init.severity;
53
+ this.affected_tests = init.affected_tests ?? [];
54
+ }
55
+ }
56
+ /**
57
+ * Python: `_normalize_path`. Normalize path parameter syntax for matching:
58
+ * converts both `:id` and `{id}` forms to `{id}` so coverage rows and OpenAPI
59
+ * paths match regardless of which convention is used.
60
+ */
61
+ function normalizePath(path) {
62
+ return path.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, '{$1}');
63
+ }
64
+ function coverageKey(path, method) {
65
+ return JSON.stringify([normalizePath(path), method.toLowerCase()]);
66
+ }
67
+ /**
68
+ * Python: `map_impact`. Map diff changes to test impact gaps, sorted by
69
+ * severity (stable — CRITICAL first).
70
+ */
71
+ export function mapImpact(diff, coverageRows) {
72
+ // Build a lookup: normalized_path+method -> list of test_names.
73
+ const coverage = new Map();
74
+ for (const row of coverageRows) {
75
+ const key = coverageKey(row.path, row.method);
76
+ const existing = coverage.get(key);
77
+ if (existing) {
78
+ existing.push(row.test_name);
79
+ }
80
+ else {
81
+ coverage.set(key, [row.test_name]);
82
+ }
83
+ }
84
+ const gaps = [];
85
+ for (const change of diff.removed) {
86
+ const tests = coverage.get(coverageKey(change.path, change.method)) ?? [];
87
+ gaps.push(new ImpactGap({
88
+ path: change.path,
89
+ method: change.method,
90
+ operation_id: change.operation_id,
91
+ change_type: ChangeType.REMOVED,
92
+ severity: tests.length ? Severity.CRITICAL : Severity.HIGH,
93
+ affected_tests: tests,
94
+ }));
95
+ }
96
+ for (const change of diff.added) {
97
+ const tests = coverage.get(coverageKey(change.path, change.method)) ?? [];
98
+ gaps.push(new ImpactGap({
99
+ path: change.path,
100
+ method: change.method,
101
+ operation_id: change.operation_id,
102
+ change_type: ChangeType.ADDED,
103
+ severity: tests.length ? Severity.LOW : Severity.HIGH,
104
+ affected_tests: tests,
105
+ }));
106
+ }
107
+ for (const change of diff.changed) {
108
+ const tests = coverage.get(coverageKey(change.path, change.method)) ?? [];
109
+ gaps.push(new ImpactGap({
110
+ path: change.path,
111
+ method: change.method,
112
+ operation_id: change.operation_id,
113
+ change_type: ChangeType.CHANGED,
114
+ severity: tests.length ? Severity.MEDIUM : Severity.HIGH,
115
+ affected_tests: tests,
116
+ }));
117
+ }
118
+ // Python `sorted(...)` returns a new list and is stable.
119
+ return [...gaps].sort((a, b) => severitySortKey(a.severity) - severitySortKey(b.severity));
120
+ }
121
+ //# sourceMappingURL=impact-mapper.js.map