@ai-sdlc/orchestrator 0.5.0 → 0.9.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 (227) hide show
  1. package/dist/action-enforcement.d.ts +26 -0
  2. package/dist/action-enforcement.js +70 -0
  3. package/dist/admission-composite.d.ts +67 -0
  4. package/dist/admission-composite.js +158 -0
  5. package/dist/admission-enrichment.d.ts +142 -0
  6. package/dist/admission-enrichment.js +331 -0
  7. package/dist/admission-hc.d.ts +62 -0
  8. package/dist/admission-hc.js +83 -0
  9. package/dist/admission-score.d.ts +148 -0
  10. package/dist/admission-score.js +237 -0
  11. package/dist/analysis/analyzer.js +3 -2
  12. package/dist/analysis/convention-detector.d.ts +85 -2
  13. package/dist/analysis/convention-detector.js +375 -70
  14. package/dist/analysis/diff-analyzer.d.ts +33 -0
  15. package/dist/analysis/diff-analyzer.js +122 -0
  16. package/dist/analysis/hotspot-analyzer.js +3 -1
  17. package/dist/analysis/index.d.ts +2 -1
  18. package/dist/analysis/index.js +2 -1
  19. package/dist/artifacts/index.d.ts +65 -0
  20. package/dist/artifacts/index.js +142 -0
  21. package/dist/backlog-adapter.d.ts +121 -0
  22. package/dist/backlog-adapter.js +438 -0
  23. package/dist/calibration.d.ts +43 -0
  24. package/dist/calibration.js +76 -0
  25. package/dist/cli/commands/agents.d.ts +24 -0
  26. package/dist/cli/commands/agents.js +66 -1
  27. package/dist/cli/commands/git-remote.d.ts +49 -0
  28. package/dist/cli/commands/git-remote.js +91 -0
  29. package/dist/cli/commands/health.d.ts +4 -0
  30. package/dist/cli/commands/health.js +13 -1
  31. package/dist/cli/commands/init.d.ts +26 -0
  32. package/dist/cli/commands/init.js +164 -22
  33. package/dist/cli/commands/mcp-setup.d.ts +31 -0
  34. package/dist/cli/commands/mcp-setup.js +78 -8
  35. package/dist/cli/formatters/table.js +15 -2
  36. package/dist/cli/index.d.ts +14 -1
  37. package/dist/cli/index.js +81 -20
  38. package/dist/cli/versions.d.ts +57 -0
  39. package/dist/cli/versions.js +128 -0
  40. package/dist/code-area-classifier.d.ts +21 -0
  41. package/dist/code-area-classifier.js +48 -0
  42. package/dist/config.d.ts +33 -1
  43. package/dist/config.js +78 -8
  44. package/dist/cycle-utils.d.ts +51 -0
  45. package/dist/cycle-utils.js +77 -0
  46. package/dist/database/adapters/external.d.ts +24 -0
  47. package/dist/database/adapters/external.js +80 -0
  48. package/dist/database/adapters/neon.d.ts +41 -0
  49. package/dist/database/adapters/neon.js +98 -0
  50. package/dist/database/adapters/pg-snapshot-restore.d.ts +28 -0
  51. package/dist/database/adapters/pg-snapshot-restore.js +68 -0
  52. package/dist/database/adapters/sqlite-copy.d.ts +32 -0
  53. package/dist/database/adapters/sqlite-copy.js +145 -0
  54. package/dist/database/connection-injection.d.ts +35 -0
  55. package/dist/database/connection-injection.js +93 -0
  56. package/dist/database/index.d.ts +12 -0
  57. package/dist/database/index.js +23 -0
  58. package/dist/database/registry.d.ts +13 -0
  59. package/dist/database/registry.js +27 -0
  60. package/dist/database/topology.d.ts +52 -0
  61. package/dist/database/topology.js +44 -0
  62. package/dist/database/types.d.ts +89 -0
  63. package/dist/database/types.js +26 -0
  64. package/dist/defaults.d.ts +5 -0
  65. package/dist/defaults.js +5 -0
  66. package/dist/design-authority.d.ts +40 -0
  67. package/dist/design-authority.js +71 -0
  68. package/dist/design-lookahead.d.ts +64 -0
  69. package/dist/design-lookahead.js +86 -0
  70. package/dist/design-quality-trend.d.ts +87 -0
  71. package/dist/design-quality-trend.js +190 -0
  72. package/dist/design-system-context.d.ts +46 -0
  73. package/dist/design-system-context.js +80 -0
  74. package/dist/design-system-correction-loop.d.ts +64 -0
  75. package/dist/design-system-correction-loop.js +128 -0
  76. package/dist/design-system-metrics.d.ts +61 -0
  77. package/dist/design-system-metrics.js +104 -0
  78. package/dist/design-system-stewardship.d.ts +22 -0
  79. package/dist/design-system-stewardship.js +85 -0
  80. package/dist/design-system-validation.d.ts +37 -0
  81. package/dist/design-system-validation.js +88 -0
  82. package/dist/dispatch/index.d.ts +4 -0
  83. package/dist/dispatch/index.js +4 -0
  84. package/dist/dispatch/merge-gate.d.ts +46 -0
  85. package/dist/dispatch/merge-gate.js +90 -0
  86. package/dist/dispatch/requeue.d.ts +57 -0
  87. package/dist/dispatch/requeue.js +131 -0
  88. package/dist/dispatch/worker-pool.d.ts +62 -0
  89. package/dist/dispatch/worker-pool.js +60 -0
  90. package/dist/execute.d.ts +40 -0
  91. package/dist/execute.js +295 -30
  92. package/dist/fix-ci.js +40 -3
  93. package/dist/fix-review.d.ts +66 -0
  94. package/dist/fix-review.js +448 -0
  95. package/dist/harness/adapters/claude-code.d.ts +29 -0
  96. package/dist/harness/adapters/claude-code.js +191 -0
  97. package/dist/harness/adapters/codex.d.ts +25 -0
  98. package/dist/harness/adapters/codex.js +61 -0
  99. package/dist/harness/independence.d.ts +51 -0
  100. package/dist/harness/independence.js +67 -0
  101. package/dist/harness/index.d.ts +14 -0
  102. package/dist/harness/index.js +20 -0
  103. package/dist/harness/registry.d.ts +17 -0
  104. package/dist/harness/registry.js +31 -0
  105. package/dist/harness/types.d.ts +123 -0
  106. package/dist/harness/types.js +8 -0
  107. package/dist/harness/version-probe.d.ts +14 -0
  108. package/dist/harness/version-probe.js +123 -0
  109. package/dist/index.d.ts +39 -5
  110. package/dist/index.js +48 -3
  111. package/dist/models/classifier.d.ts +76 -0
  112. package/dist/models/classifier.js +221 -0
  113. package/dist/models/index.d.ts +3 -0
  114. package/dist/models/index.js +3 -0
  115. package/dist/models/registry.d.ts +97 -0
  116. package/dist/models/registry.js +173 -0
  117. package/dist/pillar-breakdown.d.ts +63 -0
  118. package/dist/pillar-breakdown.js +153 -0
  119. package/dist/pipeline-cycle-detector.d.ts +70 -0
  120. package/dist/pipeline-cycle-detector.js +111 -0
  121. package/dist/priority.d.ts +7 -76
  122. package/dist/priority.js +18 -5
  123. package/dist/review-meta.d.ts +65 -0
  124. package/dist/review-meta.js +149 -0
  125. package/dist/review.d.ts +35 -0
  126. package/dist/review.js +84 -0
  127. package/dist/runners/claude-code-sdk.d.ts +31 -0
  128. package/dist/runners/claude-code-sdk.js +238 -0
  129. package/dist/runners/claude-code.d.ts +3 -0
  130. package/dist/runners/claude-code.js +319 -73
  131. package/dist/runners/codex.js +4 -1
  132. package/dist/runners/copilot.js +4 -1
  133. package/dist/runners/cursor.js +4 -1
  134. package/dist/runners/git-utils.d.ts +81 -0
  135. package/dist/runners/git-utils.js +201 -0
  136. package/dist/runners/index.d.ts +5 -1
  137. package/dist/runners/index.js +4 -0
  138. package/dist/runners/review-agent.d.ts +67 -0
  139. package/dist/runners/review-agent.js +350 -0
  140. package/dist/runners/runner-registry.js +10 -0
  141. package/dist/runners/sdk-review-runner.d.ts +65 -0
  142. package/dist/runners/sdk-review-runner.js +185 -0
  143. package/dist/runners/security-triage.d.ts +20 -4
  144. package/dist/runners/security-triage.js +42 -14
  145. package/dist/runners/types.d.ts +25 -0
  146. package/dist/runtime/attestations.d.ts +274 -0
  147. package/dist/runtime/attestations.js +460 -0
  148. package/dist/runtime/git-env.d.ts +53 -0
  149. package/dist/runtime/git-env.js +60 -0
  150. package/dist/runtime/index.d.ts +7 -0
  151. package/dist/runtime/index.js +7 -0
  152. package/dist/runtime/parallelism-flag.d.ts +10 -0
  153. package/dist/runtime/parallelism-flag.js +18 -0
  154. package/dist/runtime/port-allocator.d.ts +21 -0
  155. package/dist/runtime/port-allocator.js +66 -0
  156. package/dist/runtime/worktree-pool.d.ts +86 -0
  157. package/dist/runtime/worktree-pool.js +204 -0
  158. package/dist/runtime/worktree.d.ts +25 -0
  159. package/dist/runtime/worktree.js +111 -0
  160. package/dist/sa-scoring/auto-calibrate.d.ts +69 -0
  161. package/dist/sa-scoring/auto-calibrate.js +107 -0
  162. package/dist/sa-scoring/c1-sa2-computable.d.ts +42 -0
  163. package/dist/sa-scoring/c1-sa2-computable.js +59 -0
  164. package/dist/sa-scoring/composite.d.ts +107 -0
  165. package/dist/sa-scoring/composite.js +139 -0
  166. package/dist/sa-scoring/depparse-client.d.ts +79 -0
  167. package/dist/sa-scoring/depparse-client.js +187 -0
  168. package/dist/sa-scoring/did-compiler.d.ts +122 -0
  169. package/dist/sa-scoring/did-compiler.js +286 -0
  170. package/dist/sa-scoring/drift-monitor.d.ts +84 -0
  171. package/dist/sa-scoring/drift-monitor.js +186 -0
  172. package/dist/sa-scoring/exemplar-bank.d.ts +78 -0
  173. package/dist/sa-scoring/exemplar-bank.js +154 -0
  174. package/dist/sa-scoring/feedback-store.d.ts +100 -0
  175. package/dist/sa-scoring/feedback-store.js +156 -0
  176. package/dist/sa-scoring/index.d.ts +71 -0
  177. package/dist/sa-scoring/index.js +158 -0
  178. package/dist/sa-scoring/layer1-deterministic.d.ts +115 -0
  179. package/dist/sa-scoring/layer1-deterministic.js +298 -0
  180. package/dist/sa-scoring/layer2-structural.d.ts +71 -0
  181. package/dist/sa-scoring/layer2-structural.js +151 -0
  182. package/dist/sa-scoring/layer3-llm.d.ts +86 -0
  183. package/dist/sa-scoring/layer3-llm.js +282 -0
  184. package/dist/sa-scoring/rescore-orchestrator.d.ts +52 -0
  185. package/dist/sa-scoring/rescore-orchestrator.js +47 -0
  186. package/dist/scheduling/burn-down.d.ts +27 -0
  187. package/dist/scheduling/burn-down.js +43 -0
  188. package/dist/scheduling/calibration.d.ts +42 -0
  189. package/dist/scheduling/calibration.js +150 -0
  190. package/dist/scheduling/index.d.ts +8 -0
  191. package/dist/scheduling/index.js +8 -0
  192. package/dist/scheduling/ledger.d.ts +59 -0
  193. package/dist/scheduling/ledger.js +216 -0
  194. package/dist/scheduling/off-peak.d.ts +27 -0
  195. package/dist/scheduling/off-peak.js +112 -0
  196. package/dist/scheduling/schedule-decision.d.ts +39 -0
  197. package/dist/scheduling/schedule-decision.js +89 -0
  198. package/dist/scheduling/tier-analysis.d.ts +47 -0
  199. package/dist/scheduling/tier-analysis.js +81 -0
  200. package/dist/scheduling/types.d.ts +140 -0
  201. package/dist/scheduling/types.js +11 -0
  202. package/dist/shared.d.ts +13 -0
  203. package/dist/shared.js +32 -0
  204. package/dist/state/index.d.ts +1 -1
  205. package/dist/state/schema.d.ts +6 -1
  206. package/dist/state/schema.js +276 -1
  207. package/dist/state/store.d.ts +71 -1
  208. package/dist/state/store.js +464 -7
  209. package/dist/state/types.d.ts +174 -0
  210. package/dist/types.d.ts +1 -1
  211. package/dist/validate-agent-output.js +4 -1
  212. package/dist/watch.js +6 -0
  213. package/dist/workflow-patterns/artifact-writer.d.ts +16 -0
  214. package/dist/workflow-patterns/artifact-writer.js +34 -0
  215. package/dist/workflow-patterns/classifiers.d.ts +10 -0
  216. package/dist/workflow-patterns/classifiers.js +72 -0
  217. package/dist/workflow-patterns/detector.d.ts +27 -0
  218. package/dist/workflow-patterns/detector.js +186 -0
  219. package/dist/workflow-patterns/index.d.ts +8 -0
  220. package/dist/workflow-patterns/index.js +7 -0
  221. package/dist/workflow-patterns/proposal-generator.d.ts +15 -0
  222. package/dist/workflow-patterns/proposal-generator.js +183 -0
  223. package/dist/workflow-patterns/telemetry-ingest.d.ts +27 -0
  224. package/dist/workflow-patterns/telemetry-ingest.js +103 -0
  225. package/dist/workflow-patterns/types.d.ts +61 -0
  226. package/dist/workflow-patterns/types.js +11 -0
  227. package/package.json +2 -2
@@ -0,0 +1,71 @@
1
+ /**
2
+ * C5 — Design authority signal detection (RFC-0008 §A.5).
3
+ *
4
+ * Determines whether the issue's author or any commenter is listed as a
5
+ * `designAuthority` principal on the resolved DesignSystemBinding, and
6
+ * parses the explicit signal type from issue labels (preferred) or
7
+ * structured comment markers.
8
+ */
9
+ /**
10
+ * Label-encoded design signal types. Short, stable slugs keep GitHub
11
+ * label names readable; the map below converts them to the
12
+ * `DesignAuthoritySignalType` used downstream.
13
+ */
14
+ const LABEL_TO_SIGNAL = Object.freeze({
15
+ 'design/advances-coherence': 'advances-design-coherence',
16
+ 'design/fills-gap': 'fills-catalog-gap',
17
+ 'design/fragments-catalog': 'fragments-component-catalog',
18
+ 'design/misaligned-brand': 'misaligned-with-brand',
19
+ });
20
+ /**
21
+ * Determine whether the issue author or any commenter is a
22
+ * designAuthority principal, and resolve the signal type from labels.
23
+ * Returns `{ isDesignAuthority: false, signalType: 'unspecified' }`
24
+ * when no DSB is present.
25
+ */
26
+ export function checkDesignAuthority(input, binding) {
27
+ const principals = binding?.spec.stewardship.designAuthority.principals ?? [];
28
+ const authorityParticipants = collectAuthorityParticipants(input, principals);
29
+ const isDesignAuthority = authorityParticipants.length > 0;
30
+ const signalType = parseDesignSignalType(input.labels);
31
+ return { isDesignAuthority, signalType };
32
+ }
33
+ function collectAuthorityParticipants(input, principals) {
34
+ if (principals.length === 0)
35
+ return [];
36
+ const principalSet = new Set(principals.map((p) => p.toLowerCase()));
37
+ const participants = [];
38
+ if (input.authorLogin && principalSet.has(input.authorLogin.toLowerCase())) {
39
+ participants.push(input.authorLogin);
40
+ }
41
+ for (const c of input.commenterLogins ?? []) {
42
+ if (principalSet.has(c.toLowerCase()))
43
+ participants.push(c);
44
+ }
45
+ return participants;
46
+ }
47
+ /**
48
+ * Resolve the design-signal type from issue labels.
49
+ *
50
+ * Priority order mirrors the RFC's weighting (positive signals first),
51
+ * so an issue tagged with both a positive and a negative label resolves
52
+ * to the positive one. This is deliberate: design authorities shouldn't
53
+ * dual-tag in practice, but if they do, we don't want to default to the
54
+ * punitive path.
55
+ */
56
+ export function parseDesignSignalType(labels) {
57
+ const priority = [
58
+ 'advances-design-coherence',
59
+ 'fills-catalog-gap',
60
+ 'fragments-component-catalog',
61
+ 'misaligned-with-brand',
62
+ ];
63
+ const lowered = labels.map((l) => l.toLowerCase());
64
+ for (const target of priority) {
65
+ const label = Object.entries(LABEL_TO_SIGNAL).find(([, v]) => v === target)?.[0];
66
+ if (label && lowered.includes(label))
67
+ return target;
68
+ }
69
+ return 'unspecified';
70
+ }
71
+ //# sourceMappingURL=design-authority.js.map
@@ -0,0 +1,64 @@
1
+ /**
2
+ * C7 — Design Lookahead Notification (RFC-0008 §11 + Amendment 6).
3
+ *
4
+ * Fires a notification when a backlog item has:
5
+ * 1. Stayed in the top-10 of the prioritized backlog for ≥48h
6
+ * (OQ-7 stability threshold against priority churn)
7
+ * 2. Design-system impact (any of: frontend code area, catalog gaps,
8
+ * or `PRODUCT_HIGH_DESIGN_LOW` tension flag)
9
+ * 3. Not been notified within the last 7 days
10
+ * (dedupe via `design_lookahead_notifications` table)
11
+ *
12
+ * The payload is the full `PillarBreakdown` plus gap and tension
13
+ * information — design reviewers need the structured context to decide
14
+ * whether to unblock, reprioritize, or flag the item.
15
+ */
16
+ import type { StateStore } from './state/store.js';
17
+ import type { PillarBreakdown, TensionFlag } from './pillar-breakdown.js';
18
+ export interface DesignLookaheadConfig {
19
+ /** Min time an issue must have been in top-N to qualify. Default 48h. */
20
+ stabilityThresholdMs: number;
21
+ /** Min time since last notification before re-notifying. Default 7d. */
22
+ dedupeExpiryMs: number;
23
+ /** Cutoff for "top" (ignored when `items` is already pre-filtered). */
24
+ topN: number;
25
+ }
26
+ export declare const DEFAULT_LOOKAHEAD_CONFIG: DesignLookaheadConfig;
27
+ export interface BacklogItem {
28
+ issueNumber: number;
29
+ /** Composite score that placed this item in top-N. */
30
+ composite: number;
31
+ /** Pillar breakdown from the admission composite. */
32
+ pillarBreakdown: PillarBreakdown;
33
+ /** When the item first entered the top-N (ISO timestamp). */
34
+ enteredTop10At?: string;
35
+ /** Whether the code area has frontend components (C3 classifier). */
36
+ hasFrontendComponents?: boolean;
37
+ /** Catalog gaps surfaced during enrichment (C2). */
38
+ catalogGaps?: string[];
39
+ }
40
+ export type DesignImpactReason = 'frontend-components' | 'catalog-gaps' | 'product-design-tension';
41
+ export interface DesignLookaheadNotification {
42
+ type: 'DesignLookaheadNotification';
43
+ issueNumber: number;
44
+ notifiedAt: string;
45
+ /** Reasons this item was flagged (ordered as detected). */
46
+ reasons: DesignImpactReason[];
47
+ pillarBreakdown: PillarBreakdown;
48
+ catalogGaps: string[];
49
+ tensionFlags: TensionFlag[];
50
+ }
51
+ export declare function detectDesignImpactReasons(item: BacklogItem): DesignImpactReason[];
52
+ export interface DesignLookaheadDetectorDeps {
53
+ stateStore: StateStore;
54
+ now?: () => number;
55
+ config?: Partial<DesignLookaheadConfig>;
56
+ }
57
+ /**
58
+ * Run one scheduler tick. `items` should already be the top-N backlog
59
+ * items in descending composite order; caller is responsible for
60
+ * tracking `enteredTop10At` across ticks. Returns the notifications
61
+ * to emit + persist for this tick.
62
+ */
63
+ export declare function detectDesignLookaheadNotifications(items: readonly BacklogItem[], deps: DesignLookaheadDetectorDeps): DesignLookaheadNotification[];
64
+ //# sourceMappingURL=design-lookahead.d.ts.map
@@ -0,0 +1,86 @@
1
+ /**
2
+ * C7 — Design Lookahead Notification (RFC-0008 §11 + Amendment 6).
3
+ *
4
+ * Fires a notification when a backlog item has:
5
+ * 1. Stayed in the top-10 of the prioritized backlog for ≥48h
6
+ * (OQ-7 stability threshold against priority churn)
7
+ * 2. Design-system impact (any of: frontend code area, catalog gaps,
8
+ * or `PRODUCT_HIGH_DESIGN_LOW` tension flag)
9
+ * 3. Not been notified within the last 7 days
10
+ * (dedupe via `design_lookahead_notifications` table)
11
+ *
12
+ * The payload is the full `PillarBreakdown` plus gap and tension
13
+ * information — design reviewers need the structured context to decide
14
+ * whether to unblock, reprioritize, or flag the item.
15
+ */
16
+ // ── Thresholds ─────────────────────────────────────────────────────────
17
+ const DEFAULT_STABILITY_MS = 48 * 60 * 60 * 1000;
18
+ const DEFAULT_DEDUPE_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000;
19
+ const DEFAULT_TOP_N = 10;
20
+ export const DEFAULT_LOOKAHEAD_CONFIG = {
21
+ stabilityThresholdMs: DEFAULT_STABILITY_MS,
22
+ dedupeExpiryMs: DEFAULT_DEDUPE_EXPIRY_MS,
23
+ topN: DEFAULT_TOP_N,
24
+ };
25
+ // ── Impact detection ───────────────────────────────────────────────────
26
+ export function detectDesignImpactReasons(item) {
27
+ const reasons = [];
28
+ if (item.hasFrontendComponents)
29
+ reasons.push('frontend-components');
30
+ if ((item.catalogGaps ?? []).length > 0)
31
+ reasons.push('catalog-gaps');
32
+ if (item.pillarBreakdown.tensions.some((t) => t.type === 'PRODUCT_HIGH_DESIGN_LOW')) {
33
+ reasons.push('product-design-tension');
34
+ }
35
+ return reasons;
36
+ }
37
+ /**
38
+ * Run one scheduler tick. `items` should already be the top-N backlog
39
+ * items in descending composite order; caller is responsible for
40
+ * tracking `enteredTop10At` across ticks. Returns the notifications
41
+ * to emit + persist for this tick.
42
+ */
43
+ export function detectDesignLookaheadNotifications(items, deps) {
44
+ const config = { ...DEFAULT_LOOKAHEAD_CONFIG, ...deps.config };
45
+ const nowMs = (deps.now ?? (() => Date.now()))();
46
+ const topItems = items.slice(0, config.topN);
47
+ const emissions = [];
48
+ for (const item of topItems) {
49
+ // 1. Stability check — must have been in top-N ≥ stabilityThresholdMs.
50
+ if (!item.enteredTop10At)
51
+ continue;
52
+ const enteredMs = Date.parse(item.enteredTop10At);
53
+ if (Number.isNaN(enteredMs))
54
+ continue;
55
+ if (nowMs - enteredMs < config.stabilityThresholdMs)
56
+ continue;
57
+ // 2. Design-system impact.
58
+ const reasons = detectDesignImpactReasons(item);
59
+ if (reasons.length === 0)
60
+ continue;
61
+ // 3. Dedupe via notification table.
62
+ const existing = deps.stateStore.getDesignLookaheadNotification(item.issueNumber);
63
+ if (existing?.lastNotifiedAt) {
64
+ const lastMs = Date.parse(existing.lastNotifiedAt);
65
+ if (!Number.isNaN(lastMs) && nowMs - lastMs < config.dedupeExpiryMs)
66
+ continue;
67
+ }
68
+ // 4. Emit + record.
69
+ const notification = {
70
+ type: 'DesignLookaheadNotification',
71
+ issueNumber: item.issueNumber,
72
+ notifiedAt: new Date(nowMs).toISOString(),
73
+ reasons,
74
+ pillarBreakdown: item.pillarBreakdown,
75
+ catalogGaps: item.catalogGaps ?? [],
76
+ tensionFlags: item.pillarBreakdown.tensions,
77
+ };
78
+ emissions.push(notification);
79
+ deps.stateStore.upsertDesignLookaheadNotification({
80
+ issueNumber: item.issueNumber,
81
+ pillarBreakdownJson: JSON.stringify(item.pillarBreakdown),
82
+ });
83
+ }
84
+ return emissions;
85
+ }
86
+ //# sourceMappingURL=design-lookahead.js.map
@@ -0,0 +1,87 @@
1
+ /**
2
+ * DesignQualityTrendDegrading detector (RFC-0008 Addendum A §A.8).
3
+ *
4
+ * Periodic monitor that analyses rolling windows over
5
+ * `code_area_metrics` (designMetricsJson) and `token_compliance_history`
6
+ * to catch degradation *before* it shows up in the admission hot path
7
+ * via the C3 defect-risk factor. Emits one event per code area on
8
+ * first detection and is hysteretic — does not re-fire until recovery.
9
+ */
10
+ import type { DesignSystemBinding } from '@ai-sdlc/reference';
11
+ import type { StateStore } from './state/store.js';
12
+ import type { CodeAreaMetricsRecord, TokenComplianceRecord } from './state/types.js';
13
+ export interface TrendAnalysisConfig {
14
+ /** Minimum number of data points in the recent window. */
15
+ windowPrs: number;
16
+ /** Maximum age of measurements to include (days). */
17
+ windowDays: number;
18
+ /** Drop in designCIPassRate (absolute) that triggers the condition. */
19
+ ciDropThreshold: number;
20
+ /** Rise in designReviewRejectionRate (absolute) that triggers. */
21
+ reviewIncreaseThreshold: number;
22
+ /** Minimum consecutive 'declining' compliance trends to trigger. */
23
+ consecutiveNegativeCompliance: number;
24
+ }
25
+ export declare const DEFAULT_TREND_CONFIG: TrendAnalysisConfig;
26
+ export type TrendCondition = 'designCIPassRate' | 'designReviewRejectionRate' | 'tokenComplianceTrend';
27
+ /**
28
+ * Partition the history into `recent` (newest `windowPrs` records or
29
+ * anything inside `windowDays`) and `baseline` (everything older). The
30
+ * recent window fills by whichever bound hits first — that gives us a
31
+ * consistent signal whether activity is sparse or bursty.
32
+ *
33
+ * History is assumed to be in descending `computed_at` order (as returned
34
+ * by `getCodeAreaMetricsHistory`).
35
+ */
36
+ export declare function splitHistoryByWindow<T extends {
37
+ computedAt?: string;
38
+ }>(history: readonly T[], config: Pick<TrendAnalysisConfig, 'windowPrs' | 'windowDays'>, nowMs: number): {
39
+ recent: T[];
40
+ baseline: T[];
41
+ };
42
+ export interface ConditionEvaluation {
43
+ triggered: boolean;
44
+ recentValue?: number;
45
+ baselineValue?: number;
46
+ delta?: number;
47
+ }
48
+ export declare function evaluateCiPassRate(recent: readonly CodeAreaMetricsRecord[], baseline: readonly CodeAreaMetricsRecord[], threshold: number): ConditionEvaluation;
49
+ export declare function evaluateReviewRejectionRate(recent: readonly CodeAreaMetricsRecord[], baseline: readonly CodeAreaMetricsRecord[], threshold: number): ConditionEvaluation;
50
+ export declare function evaluateTokenComplianceTrend(history: readonly TokenComplianceRecord[], minConsecutive: number): ConditionEvaluation;
51
+ export interface TrendAnalysisResult {
52
+ codeArea: string;
53
+ triggered: boolean;
54
+ conditions: Partial<Record<TrendCondition, ConditionEvaluation>>;
55
+ }
56
+ export declare function analyzeTrend(codeArea: string, codeAreaHistory: readonly CodeAreaMetricsRecord[], tokenComplianceHistory: readonly TokenComplianceRecord[], nowMs: number, overrides?: Partial<TrendAnalysisConfig>): TrendAnalysisResult;
57
+ export interface DesignQualityTrendDegradingEvent {
58
+ type: 'DesignQualityTrendDegrading';
59
+ codeArea: string;
60
+ bindingName?: string;
61
+ triggeredAt: string;
62
+ triggeredConditions: TrendCondition[];
63
+ conditions: TrendAnalysisResult['conditions'];
64
+ notifiedPrincipals: string[];
65
+ issueBodyMarkdown: string;
66
+ }
67
+ export interface DesignQualityTrendDetectorDeps {
68
+ stateStore: StateStore;
69
+ /** Resolve a code area to its owning DSB, if any. */
70
+ getBindingForCodeArea?: (codeArea: string) => DesignSystemBinding | undefined;
71
+ /** Timestamp of the last emission for this area (hysteresis state). */
72
+ getLastTriggerAt?: (codeArea: string) => string | undefined;
73
+ /** Required quiet window (ms) with no trigger before re-firing. */
74
+ hysteresisRecoveryMs?: number;
75
+ /** Clock injection (defaults to `Date.now`). */
76
+ now?: () => number;
77
+ /** Partial config override. */
78
+ config?: Partial<TrendAnalysisConfig>;
79
+ }
80
+ /**
81
+ * Run the trend analysis for one code area. Returns an event when the
82
+ * trend is currently degrading AND the hysteresis quiet window has
83
+ * elapsed since the last trigger (or no prior trigger). Returns
84
+ * undefined otherwise.
85
+ */
86
+ export declare function detectDesignQualityTrendDegrading(codeArea: string, deps: DesignQualityTrendDetectorDeps): DesignQualityTrendDegradingEvent | undefined;
87
+ //# sourceMappingURL=design-quality-trend.d.ts.map
@@ -0,0 +1,190 @@
1
+ /**
2
+ * DesignQualityTrendDegrading detector (RFC-0008 Addendum A §A.8).
3
+ *
4
+ * Periodic monitor that analyses rolling windows over
5
+ * `code_area_metrics` (designMetricsJson) and `token_compliance_history`
6
+ * to catch degradation *before* it shows up in the admission hot path
7
+ * via the C3 defect-risk factor. Emits one event per code area on
8
+ * first detection and is hysteretic — does not re-fire until recovery.
9
+ */
10
+ export const DEFAULT_TREND_CONFIG = {
11
+ windowPrs: 10,
12
+ windowDays: 30,
13
+ ciDropThreshold: 0.15,
14
+ reviewIncreaseThreshold: 0.2,
15
+ consecutiveNegativeCompliance: 5,
16
+ };
17
+ function parseDesignMetrics(json) {
18
+ if (!json)
19
+ return undefined;
20
+ try {
21
+ return JSON.parse(json);
22
+ }
23
+ catch {
24
+ return undefined;
25
+ }
26
+ }
27
+ // ── Window selection ───────────────────────────────────────────────────
28
+ /**
29
+ * Partition the history into `recent` (newest `windowPrs` records or
30
+ * anything inside `windowDays`) and `baseline` (everything older). The
31
+ * recent window fills by whichever bound hits first — that gives us a
32
+ * consistent signal whether activity is sparse or bursty.
33
+ *
34
+ * History is assumed to be in descending `computed_at` order (as returned
35
+ * by `getCodeAreaMetricsHistory`).
36
+ */
37
+ export function splitHistoryByWindow(history, config, nowMs) {
38
+ const cutoffMs = nowMs - config.windowDays * 24 * 60 * 60 * 1000;
39
+ const recent = [];
40
+ for (const row of history) {
41
+ if (recent.length >= config.windowPrs)
42
+ break;
43
+ const ts = row.computedAt ? Date.parse(row.computedAt) : NaN;
44
+ if (Number.isNaN(ts))
45
+ continue;
46
+ if (ts < cutoffMs)
47
+ break;
48
+ recent.push(row);
49
+ }
50
+ const baseline = history.slice(recent.length);
51
+ return { recent, baseline };
52
+ }
53
+ export function evaluateCiPassRate(recent, baseline, threshold) {
54
+ const recentMean = meanDesignMetric(recent, 'designCIPassRate');
55
+ const baselineMean = meanDesignMetric(baseline, 'designCIPassRate');
56
+ if (recentMean === undefined || baselineMean === undefined) {
57
+ return { triggered: false };
58
+ }
59
+ const delta = baselineMean - recentMean; // positive ⇒ dropped
60
+ return {
61
+ triggered: delta >= threshold,
62
+ recentValue: recentMean,
63
+ baselineValue: baselineMean,
64
+ delta,
65
+ };
66
+ }
67
+ export function evaluateReviewRejectionRate(recent, baseline, threshold) {
68
+ const recentMean = meanDesignMetric(recent, 'designReviewRejectionRate');
69
+ const baselineMean = meanDesignMetric(baseline, 'designReviewRejectionRate');
70
+ if (recentMean === undefined || baselineMean === undefined) {
71
+ return { triggered: false };
72
+ }
73
+ const delta = recentMean - baselineMean; // positive ⇒ rejections rising
74
+ return {
75
+ triggered: delta >= threshold,
76
+ recentValue: recentMean,
77
+ baselineValue: baselineMean,
78
+ delta,
79
+ };
80
+ }
81
+ export function evaluateTokenComplianceTrend(history, minConsecutive) {
82
+ // history is descending (newest first). Walk newest→oldest, counting
83
+ // a run of declining coverages.
84
+ let streak = 0;
85
+ for (let i = 0; i < history.length - 1; i++) {
86
+ if (history[i].coveragePercent < history[i + 1].coveragePercent)
87
+ streak++;
88
+ else
89
+ break;
90
+ }
91
+ return {
92
+ triggered: streak >= minConsecutive,
93
+ recentValue: streak,
94
+ };
95
+ }
96
+ function meanDesignMetric(rows, key) {
97
+ const values = [];
98
+ for (const row of rows) {
99
+ const blob = parseDesignMetrics(row.designMetricsJson);
100
+ const value = blob?.[key];
101
+ if (typeof value === 'number' && !Number.isNaN(value))
102
+ values.push(value);
103
+ }
104
+ if (values.length === 0)
105
+ return undefined;
106
+ return values.reduce((a, b) => a + b, 0) / values.length;
107
+ }
108
+ export function analyzeTrend(codeArea, codeAreaHistory, tokenComplianceHistory, nowMs, overrides = {}) {
109
+ const config = { ...DEFAULT_TREND_CONFIG, ...overrides };
110
+ const { recent, baseline } = splitHistoryByWindow(codeAreaHistory, config, nowMs);
111
+ const ci = evaluateCiPassRate(recent, baseline, config.ciDropThreshold);
112
+ const review = evaluateReviewRejectionRate(recent, baseline, config.reviewIncreaseThreshold);
113
+ const compliance = evaluateTokenComplianceTrend(tokenComplianceHistory, config.consecutiveNegativeCompliance);
114
+ const conditions = {};
115
+ if (ci.triggered)
116
+ conditions.designCIPassRate = ci;
117
+ if (review.triggered)
118
+ conditions.designReviewRejectionRate = review;
119
+ if (compliance.triggered)
120
+ conditions.tokenComplianceTrend = compliance;
121
+ return {
122
+ codeArea,
123
+ triggered: Object.keys(conditions).length > 0,
124
+ conditions,
125
+ };
126
+ }
127
+ /**
128
+ * Run the trend analysis for one code area. Returns an event when the
129
+ * trend is currently degrading AND the hysteresis quiet window has
130
+ * elapsed since the last trigger (or no prior trigger). Returns
131
+ * undefined otherwise.
132
+ */
133
+ export function detectDesignQualityTrendDegrading(codeArea, deps) {
134
+ const nowMs = (deps.now ?? (() => Date.now()))();
135
+ // Hysteresis: skip if we've emitted recently within the recovery window.
136
+ const lastTriggerAt = deps.getLastTriggerAt?.(codeArea);
137
+ if (lastTriggerAt) {
138
+ const lastMs = Date.parse(lastTriggerAt);
139
+ const recoveryMs = deps.hysteresisRecoveryMs ?? 7 * 24 * 60 * 60 * 1000; // 7d default
140
+ if (!Number.isNaN(lastMs) && nowMs - lastMs < recoveryMs)
141
+ return undefined;
142
+ }
143
+ const history = deps.stateStore.getCodeAreaMetricsHistory(codeArea, { limit: 100 });
144
+ const binding = deps.getBindingForCodeArea?.(codeArea);
145
+ const tokenHistory = binding
146
+ ? deps.stateStore.getTokenComplianceHistory(binding.metadata.name)
147
+ : [];
148
+ const result = analyzeTrend(codeArea, history, tokenHistory, nowMs, deps.config);
149
+ if (!result.triggered)
150
+ return undefined;
151
+ const principals = binding ? gatherPrincipals(binding) : [];
152
+ const triggeredConditions = Object.keys(result.conditions);
153
+ return {
154
+ type: 'DesignQualityTrendDegrading',
155
+ codeArea,
156
+ bindingName: binding?.metadata.name,
157
+ triggeredAt: new Date(nowMs).toISOString(),
158
+ triggeredConditions,
159
+ conditions: result.conditions,
160
+ notifiedPrincipals: principals,
161
+ issueBodyMarkdown: renderIssueBody(result, binding),
162
+ };
163
+ }
164
+ function gatherPrincipals(binding) {
165
+ const design = binding.spec.stewardship.designAuthority.principals;
166
+ const engineering = binding.spec.stewardship.engineeringAuthority.principals;
167
+ const unique = new Set([...design, ...engineering]);
168
+ return Array.from(unique);
169
+ }
170
+ function renderIssueBody(result, binding) {
171
+ const lines = [
172
+ `## DesignQualityTrendDegrading — ${result.codeArea}`,
173
+ '',
174
+ binding
175
+ ? `Linked DesignSystemBinding: **${binding.metadata.name}**`
176
+ : 'No linked DesignSystemBinding',
177
+ '',
178
+ '### Triggered conditions',
179
+ '',
180
+ ];
181
+ for (const [name, evaluation] of Object.entries(result.conditions)) {
182
+ const baseline = evaluation.baselineValue !== undefined ? evaluation.baselineValue.toFixed(3) : 'n/a';
183
+ const current = evaluation.recentValue !== undefined ? evaluation.recentValue.toFixed(3) : 'n/a';
184
+ const delta = evaluation.delta !== undefined ? evaluation.delta.toFixed(3) : 'n/a';
185
+ lines.push(`- **${name}** — baseline ${baseline}, recent ${current}, delta ${delta}`);
186
+ }
187
+ lines.push('', '---', 'Investigate the code area and file follow-up tasks as needed.');
188
+ return lines.join('\n');
189
+ }
190
+ //# sourceMappingURL=design-quality-trend.js.map
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Context strategy selection for design-system-aware agents (RFC-0006 §7.2).
3
+ *
4
+ * Implements the 5-step decision tree that determines how much design
5
+ * system context an agent receives.
6
+ */
7
+ import type { ContextStrategy, DesignSystemBinding } from '@ai-sdlc/reference';
8
+ export interface TaskContext {
9
+ /** The trigger event type (e.g., 'design-token.changed', 'issue.assigned'). */
10
+ triggerEvent?: string;
11
+ /** Whether the task involves modifying existing components. */
12
+ modifiesComponents?: boolean;
13
+ /** Whether the task creates a new component. */
14
+ createsNewComponent?: boolean;
15
+ /** Whether the task involves both tokens AND component composition. */
16
+ touchesTokensAndComponents?: boolean;
17
+ /** Reusability score from the design-context stage (0.0-1.0). */
18
+ reusabilityScore?: number;
19
+ }
20
+ export interface ContextStrategyResult {
21
+ strategy: ContextStrategy;
22
+ reason: string;
23
+ }
24
+ /**
25
+ * Select the context strategy using the 5-step decision tree from RFC-0006 §7.2.
26
+ *
27
+ * 1. Token-change trigger with no component mods → tokens-only
28
+ * 2. Modifying/composing existing components → manifest-first
29
+ * 3. Creating new component → full
30
+ * 4. Both tokens AND composition → full
31
+ * 5. Reusability score < 0.5 → full
32
+ *
33
+ * Falls back to manifest-first as the default.
34
+ */
35
+ export declare function selectContextStrategy(task: TaskContext, binding: DesignSystemBinding): ContextStrategyResult;
36
+ /**
37
+ * Re-evaluate context strategy after scope change (RFC-0006 §7.2 bottom).
38
+ * Called after design impact review if the approved scope differs from
39
+ * the initial scope.
40
+ */
41
+ export declare function reEvaluateStrategy(originalTask: TaskContext, updatedTask: TaskContext, binding: DesignSystemBinding): {
42
+ changed: boolean;
43
+ result: ContextStrategyResult;
44
+ reason?: string;
45
+ };
46
+ //# sourceMappingURL=design-system-context.d.ts.map
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Context strategy selection for design-system-aware agents (RFC-0006 §7.2).
3
+ *
4
+ * Implements the 5-step decision tree that determines how much design
5
+ * system context an agent receives.
6
+ */
7
+ /**
8
+ * Select the context strategy using the 5-step decision tree from RFC-0006 §7.2.
9
+ *
10
+ * 1. Token-change trigger with no component mods → tokens-only
11
+ * 2. Modifying/composing existing components → manifest-first
12
+ * 3. Creating new component → full
13
+ * 4. Both tokens AND composition → full
14
+ * 5. Reusability score < 0.5 → full
15
+ *
16
+ * Falls back to manifest-first as the default.
17
+ */
18
+ export function selectContextStrategy(task, binding) {
19
+ const agentConfig = binding.spec;
20
+ // If contextStrategyOverride is 'fixed', use the declared strategy
21
+ if (agentConfig.designSystem?.contextStrategyOverride === 'fixed') {
22
+ const fixed = (agentConfig.designSystem?.contextStrategy ??
23
+ 'manifest-first');
24
+ return { strategy: fixed, reason: 'Fixed strategy override — using declared contextStrategy' };
25
+ }
26
+ // Step 1: Token-change trigger with no component modifications
27
+ if (task.triggerEvent === 'design-token.changed' &&
28
+ !task.modifiesComponents &&
29
+ !task.createsNewComponent) {
30
+ return {
31
+ strategy: 'tokens-only',
32
+ reason: 'Token-change trigger with no component modifications',
33
+ };
34
+ }
35
+ // Step 2: Modifying/composing existing components only
36
+ if (task.modifiesComponents && !task.createsNewComponent && !task.touchesTokensAndComponents) {
37
+ return {
38
+ strategy: 'manifest-first',
39
+ reason: 'Modifying existing components — manifest sufficient',
40
+ };
41
+ }
42
+ // Step 3: Creating a new component
43
+ if (task.createsNewComponent) {
44
+ return { strategy: 'full', reason: 'New component creation requires full context' };
45
+ }
46
+ // Step 4: Both tokens AND component composition
47
+ if (task.touchesTokensAndComponents) {
48
+ return {
49
+ strategy: 'full',
50
+ reason: 'Task touches both tokens and components — escalating to full',
51
+ };
52
+ }
53
+ // Step 5: Low reusability score
54
+ if (task.reusabilityScore !== undefined && task.reusabilityScore < 0.5) {
55
+ return {
56
+ strategy: 'full',
57
+ reason: `Reusability score ${task.reusabilityScore} < 0.5 — catalog insufficient`,
58
+ };
59
+ }
60
+ // Default
61
+ return { strategy: 'manifest-first', reason: 'Default strategy' };
62
+ }
63
+ /**
64
+ * Re-evaluate context strategy after scope change (RFC-0006 §7.2 bottom).
65
+ * Called after design impact review if the approved scope differs from
66
+ * the initial scope.
67
+ */
68
+ export function reEvaluateStrategy(originalTask, updatedTask, binding) {
69
+ const original = selectContextStrategy(originalTask, binding);
70
+ const updated = selectContextStrategy(updatedTask, binding);
71
+ if (original.strategy !== updated.strategy) {
72
+ return {
73
+ changed: true,
74
+ result: updated,
75
+ reason: 'scope-changed-at-impact-review',
76
+ };
77
+ }
78
+ return { changed: false, result: original };
79
+ }
80
+ //# sourceMappingURL=design-system-context.js.map