@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,331 @@
1
+ /**
2
+ * Bridge between stateless admission scoring and the stateful orchestrator
3
+ * (RFC-0008 Addendum A §A.2 – §A.5).
4
+ *
5
+ * `enrichAdmissionInput()` reads from the orchestrator's state store and
6
+ * resolved resources to populate the RFC-0008 context fields on
7
+ * `AdmissionInput`, then `computeDesignSystemReadiness()` produces the
8
+ * Eρ₄ scalar that feeds the admission composite in §A.6.
9
+ *
10
+ * Scope for AISDLC-43: implement C2 (Eρ₄) only. C3/C4/C5 are populated
11
+ * by later tasks (AISDLC-44/45/46).
12
+ */
13
+ import { checkHasFrontendComponents } from './code-area-classifier.js';
14
+ import { checkDesignAuthority } from './design-authority.js';
15
+ /**
16
+ * Minimum data points required before `code_area_metrics` is trusted
17
+ * enough to drive defect-risk penalties (RFC-0008 §7.4 Open Question 4).
18
+ */
19
+ export const CODE_AREA_METRICS_MIN_DATA_POINTS = 10;
20
+ /** Default window (ms) for `getCodeAreaMetrics` lookups — 90 days. */
21
+ const DEFAULT_METRICS_WINDOW_MS = 90 * 24 * 60 * 60 * 1000;
22
+ /**
23
+ * Populate `designSystemContext` on the admission input using the
24
+ * resolved DSB and state store. Returns the input unchanged when no DSB
25
+ * is available (preDesignSystem phase — caller falls through to the
26
+ * stateless path).
27
+ */
28
+ export function enrichAdmissionInput(input, ctx) {
29
+ const binding = ctx.designSystemBinding;
30
+ const codeAreaQuality = ctx.codeArea
31
+ ? buildCodeAreaQuality(ctx.codeArea, ctx.stateStore, ctx.now)
32
+ : undefined;
33
+ const autonomyContext = buildAutonomyContext(ctx);
34
+ const designAuthoritySignal = buildDesignAuthoritySignal(input, ctx);
35
+ if (!binding) {
36
+ const next = { ...input };
37
+ // When ctx.codeArea is set but buildCodeAreaQuality returns undefined
38
+ // (insufficient data), explicitly clear any stale value that may have
39
+ // been carried over from input — otherwise the spread above preserves
40
+ // it and drives a bogus defect-risk penalty.
41
+ if (ctx.codeArea)
42
+ next.codeAreaQuality = codeAreaQuality;
43
+ if (autonomyContext)
44
+ next.autonomyContext = autonomyContext;
45
+ if (designAuthoritySignal)
46
+ next.designAuthoritySignal = designAuthoritySignal;
47
+ return next;
48
+ }
49
+ const catalogCoverageRaw = binding.status?.catalogHealth?.coveragePercent;
50
+ const tokenComplianceRaw = binding.status?.tokenCompliance?.currentCoverage;
51
+ const catalogCoverage = normalizeCoverage(catalogCoverageRaw);
52
+ const tokenCompliance = normalizeCoverage(tokenComplianceRaw);
53
+ const baselineCoverage = ctx.stateStore
54
+ ? computeBaselineCoverage(ctx.stateStore, binding.metadata.name)
55
+ : 0;
56
+ const ageDays = computeDsbAgeDays(ctx.dsbAdoptedAt, ctx.now);
57
+ const phase = detectLifecyclePhase(binding, catalogCoverage, ageDays);
58
+ const context = {
59
+ catalogCoverage,
60
+ tokenCompliance,
61
+ inBootstrapPhase: phase === 'catalogBootstrap',
62
+ baselineCoverage,
63
+ catalogGaps: ctx.catalogGaps ?? [],
64
+ };
65
+ return {
66
+ ...input,
67
+ designSystemContext: context,
68
+ // When ctx.codeArea is set we always write codeAreaQuality — either
69
+ // the computed value or `undefined` — so stale input.codeAreaQuality
70
+ // can't silently drive a penalty under fresh enrichment context.
71
+ ...(ctx.codeArea ? { codeAreaQuality } : {}),
72
+ ...(autonomyContext ? { autonomyContext } : {}),
73
+ ...(designAuthoritySignal ? { designAuthoritySignal } : {}),
74
+ };
75
+ }
76
+ /**
77
+ * Read code-area metrics within the 90-day window and project them into
78
+ * the `CodeAreaQuality` shape. Returns undefined when the metric row is
79
+ * missing or has fewer than `CODE_AREA_METRICS_MIN_DATA_POINTS` samples —
80
+ * downstream defect-risk consumers treat "absent" as 0 penalty.
81
+ */
82
+ function buildCodeAreaQuality(codeArea, store, now) {
83
+ if (!store) {
84
+ // No state → fall back to heuristic classification only.
85
+ return { hasFrontendComponents: checkHasFrontendComponents(codeArea) };
86
+ }
87
+ const windowStart = new Date((now ?? (() => Date.now()))() - DEFAULT_METRICS_WINDOW_MS).toISOString();
88
+ const metrics = store.getCodeAreaMetrics(codeArea, { since: windowStart });
89
+ if (!metrics || (metrics.dataPointCount ?? 0) < CODE_AREA_METRICS_MIN_DATA_POINTS) {
90
+ return undefined;
91
+ }
92
+ const designQuality = parseDesignQuality(metrics.designMetricsJson);
93
+ return {
94
+ defectDensity: metrics.defectDensity,
95
+ churnRate: metrics.churnRate,
96
+ prRejectionRate: metrics.prRejectionRate,
97
+ hasFrontendComponents: metrics.hasFrontendComponents ?? false,
98
+ ...(designQuality ? { designQuality } : {}),
99
+ };
100
+ }
101
+ function parseDesignQuality(json) {
102
+ if (!json)
103
+ return undefined;
104
+ try {
105
+ const parsed = JSON.parse(json);
106
+ if (parsed.designCIPassRate === undefined &&
107
+ parsed.designReviewRejectionRate === undefined &&
108
+ parsed.usabilitySimPassRate === undefined) {
109
+ return undefined;
110
+ }
111
+ return parsed;
112
+ }
113
+ catch {
114
+ return undefined;
115
+ }
116
+ }
117
+ /**
118
+ * Compute the C3 defect-risk factor per §A.5. Returns 0 when
119
+ * `codeAreaQuality` is absent (insufficient data → no penalty).
120
+ *
121
+ * !hasFrontendComponents → 0.5×dd + 0.3×churn + 0.2×prRej
122
+ * hasFrontendComponents
123
+ * no designQuality → same as pure code (no blend target)
124
+ * with designQuality → 0.7 × code + 0.3 × design
125
+ * where design = 0.4×(1-ciPass)
126
+ * + 0.4×reviewRej
127
+ * + 0.2×(1-usabPass)
128
+ *
129
+ * Final value is clamped to [0, 0.5].
130
+ */
131
+ export function computeDefectRiskFactor(quality) {
132
+ if (!quality)
133
+ return 0;
134
+ const code = 0.5 * (quality.defectDensity ?? 0) +
135
+ 0.3 * (quality.churnRate ?? 0) +
136
+ 0.2 * (quality.prRejectionRate ?? 0);
137
+ if (!quality.hasFrontendComponents || !quality.designQuality) {
138
+ return clamp(code, 0, 0.5);
139
+ }
140
+ const dq = quality.designQuality;
141
+ const ciPass = dq.designCIPassRate ?? 1;
142
+ const reviewRej = dq.designReviewRejectionRate ?? 0;
143
+ const usabPass = dq.usabilitySimPassRate ?? 1;
144
+ const design = 0.4 * (1 - ciPass) + 0.4 * reviewRej + 0.2 * (1 - usabPass);
145
+ const blended = 0.7 * code + 0.3 * design;
146
+ return clamp(blended, 0, 0.5);
147
+ }
148
+ function clamp(value, min, max) {
149
+ return Math.min(max, Math.max(min, value));
150
+ }
151
+ // ── C4 Autonomy Factor ─────────────────────────────────────────────────
152
+ /**
153
+ * Map task complexity to the required autonomy level per §A.4:
154
+ * complexity ≤ 3 → level 1
155
+ * complexity ≤ 6 → level 2
156
+ * else → level 3
157
+ */
158
+ export function complexityToAutonomyLevel(complexity) {
159
+ if (complexity <= 3)
160
+ return 1;
161
+ if (complexity <= 6)
162
+ return 2;
163
+ return 3;
164
+ }
165
+ /**
166
+ * Compute the C4 autonomy factor per §A.5:
167
+ * gap = requiredLevel - currentEarnedLevel
168
+ * gap > 0 → max(0.1, 1.0 - gap × 0.4)
169
+ * gap ≤ 0 → 1.0
170
+ */
171
+ export function computeAutonomyFactor(ctx) {
172
+ if (!ctx)
173
+ return 1.0;
174
+ const gap = ctx.requiredLevel - ctx.currentEarnedLevel;
175
+ if (gap <= 0)
176
+ return 1.0;
177
+ return Math.max(0.1, 1.0 - gap * 0.4);
178
+ }
179
+ function buildAutonomyContext(ctx) {
180
+ if (!ctx.autonomyPolicy)
181
+ return undefined;
182
+ const agents = ctx.autonomyPolicy.status?.agents ?? [];
183
+ if (agents.length === 0)
184
+ return undefined;
185
+ const selected = ctx.agentName
186
+ ? agents.find((a) => a.name === ctx.agentName)
187
+ : pickMostPermissiveAgent(agents);
188
+ if (!selected)
189
+ return undefined;
190
+ const currentEarnedLevel = selected.currentLevel;
191
+ const requiredLevel = ctx.complexity !== undefined ? complexityToAutonomyLevel(ctx.complexity) : currentEarnedLevel;
192
+ return { currentEarnedLevel, requiredLevel };
193
+ }
194
+ function pickMostPermissiveAgent(agents) {
195
+ return agents.reduce((best, a) => (a.currentLevel > best.currentLevel ? a : best), agents[0]);
196
+ }
197
+ // ── C5 Design Authority Signal + HC_design ─────────────────────────────
198
+ /** Base weights per signal type (§A.5) before compliance modulation. */
199
+ const DESIGN_AUTHORITY_BASE_WEIGHT = Object.freeze({
200
+ 'advances-design-coherence': 0.6,
201
+ 'fills-catalog-gap': 0.6,
202
+ 'fragments-component-catalog': -0.4,
203
+ 'misaligned-with-brand': -0.4,
204
+ unspecified: 0.3,
205
+ });
206
+ /**
207
+ * Compute the C5 design-authority weight per §A.5.
208
+ *
209
+ * non-authority → 0.0
210
+ * authority + positive → +0.6 × modulation
211
+ * authority + negative → -0.4 × modulation
212
+ * authority + no type → +0.3 × modulation
213
+ *
214
+ * where `modulation = 1.2 - areaComplianceScore` when the score is
215
+ * supplied, else `1.0` (unmodulated base weight).
216
+ */
217
+ export function computeDesignAuthorityWeight(signal) {
218
+ if (!signal || !signal.isDesignAuthority)
219
+ return 0;
220
+ const signalType = signal.signalType ?? 'unspecified';
221
+ const base = DESIGN_AUTHORITY_BASE_WEIGHT[signalType];
222
+ const modulation = signal.areaComplianceScore !== undefined ? 1.2 - signal.areaComplianceScore : 1;
223
+ return base * modulation;
224
+ }
225
+ function buildDesignAuthoritySignal(input, ctx) {
226
+ if (!ctx.designSystemBinding)
227
+ return undefined;
228
+ const { isDesignAuthority, signalType } = checkDesignAuthority({
229
+ authorLogin: input.authorLogin,
230
+ commenterLogins: input.commenterLogins,
231
+ labels: input.labels,
232
+ }, ctx.designSystemBinding);
233
+ if (!isDesignAuthority)
234
+ return { isDesignAuthority: false };
235
+ return {
236
+ isDesignAuthority: true,
237
+ signalType,
238
+ ...(ctx.areaComplianceScore !== undefined
239
+ ? { areaComplianceScore: ctx.areaComplianceScore }
240
+ : {}),
241
+ };
242
+ }
243
+ /**
244
+ * Compute the C2 Eρ₄ design-system readiness scalar in [0, 1] per §A.5.
245
+ *
246
+ * preDesignSystem: 1.0 (no DSB → no penalty)
247
+ * catalogBootstrap: max(0.3, 0.4×cat + 0.3×tok + 0.3×baseline)
248
+ * postDesignSystem: 0.4×cat + 0.3×tok + 0.3×baseline
249
+ */
250
+ export function computeDesignSystemReadiness(ctx) {
251
+ const binding = ctx.designSystemBinding;
252
+ if (!binding)
253
+ return 1.0;
254
+ const catalogCoverage = normalizeCoverage(binding.status?.catalogHealth?.coveragePercent);
255
+ const tokenCompliance = normalizeCoverage(binding.status?.tokenCompliance?.currentCoverage);
256
+ const baselineCoverage = ctx.stateStore
257
+ ? computeBaselineCoverage(ctx.stateStore, binding.metadata.name)
258
+ : 0;
259
+ const ageDays = computeDsbAgeDays(ctx.dsbAdoptedAt, ctx.now);
260
+ const phase = detectLifecyclePhase(binding, catalogCoverage, ageDays);
261
+ const computed = 0.4 * catalogCoverage + 0.3 * tokenCompliance + 0.3 * baselineCoverage;
262
+ if (phase === 'catalogBootstrap')
263
+ return Math.max(0.3, computed);
264
+ return computed;
265
+ }
266
+ /**
267
+ * Compute the C2 Eρ₄ scalar directly from the DesignSystemContext
268
+ * already populated on an `AdmissionInput` (no DSB/state lookups).
269
+ *
270
+ * undefined (preDesignSystem) → 1.0
271
+ * inBootstrapPhase → max(0.3, computed)
272
+ * else → computed
273
+ *
274
+ * Used by the admission composite (§A.6) to avoid re-reading the state
275
+ * store on every score call.
276
+ */
277
+ export function computeReadinessFromDesignSystemContext(context) {
278
+ if (!context)
279
+ return 1.0;
280
+ const catalogCoverage = normalizeCoverage(context.catalogCoverage);
281
+ const tokenCompliance = normalizeCoverage(context.tokenCompliance);
282
+ const baselineCoverage = normalizeCoverage(context.baselineCoverage);
283
+ const computed = 0.4 * catalogCoverage + 0.3 * tokenCompliance + 0.3 * baselineCoverage;
284
+ if (context.inBootstrapPhase)
285
+ return Math.max(0.3, computed);
286
+ return computed;
287
+ }
288
+ export function detectLifecyclePhase(binding, normalizedCatalogCoverage, ageDays) {
289
+ if (!binding)
290
+ return 'preDesignSystem';
291
+ if (normalizedCatalogCoverage < 0.2 && ageDays < 90)
292
+ return 'catalogBootstrap';
293
+ return 'postDesignSystem';
294
+ }
295
+ /**
296
+ * Days since the DSB was adopted. Returns 0 when no adoption timestamp
297
+ * is supplied — the conservative default (treats DSB as brand-new and
298
+ * favours the bootstrap floor).
299
+ */
300
+ export function computeDsbAgeDays(adoptedAt, now) {
301
+ if (!adoptedAt)
302
+ return 0;
303
+ const adoptedMs = Date.parse(adoptedAt);
304
+ if (Number.isNaN(adoptedMs))
305
+ return 0;
306
+ const nowMs = (now ?? (() => Date.now()))();
307
+ const diffMs = Math.max(0, nowMs - adoptedMs);
308
+ return diffMs / (1000 * 60 * 60 * 24);
309
+ }
310
+ /**
311
+ * Fraction of the UI under visual-regression monitoring for this binding,
312
+ * derived from approved baselines in `visual_regression_results`.
313
+ *
314
+ * Definition (§A.5 proxy): `approvedBaselines / totalBaselines`. Returns
315
+ * 0 when no history exists (bootstrap protection: avoids over-crediting
316
+ * readiness when the monitor hasn't run yet).
317
+ */
318
+ export function computeBaselineCoverage(store, bindingName) {
319
+ const history = store.getVisualRegressionResults(bindingName, 1000);
320
+ if (history.length === 0)
321
+ return 0;
322
+ const approved = history.filter((r) => Boolean(r.approved)).length;
323
+ return approved / history.length;
324
+ }
325
+ function normalizeCoverage(value) {
326
+ if (value === undefined || Number.isNaN(value))
327
+ return 0;
328
+ const clamped = value > 1 ? value / 100 : value;
329
+ return Math.min(1, Math.max(0, clamped));
330
+ }
331
+ //# sourceMappingURL=admission-enrichment.js.map
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Admission-specific Human Curve composite (RFC-0008 §A.6, Amendment 4).
3
+ *
4
+ * The admission HC differs from the legacy PPA HC in two ways:
5
+ * 1. Four terms instead of three — HC_design enters at 0.10 weight.
6
+ * 2. Weights are (0.2, 0.45, 0.25, 0.10) rather than (0.5, 0.3, 0.2).
7
+ *
8
+ * HC_design flows through tanh alongside the other three components;
9
+ * it is NOT a direct soul-alignment modifier (Amendment 5 correction
10
+ * to the v3 draft).
11
+ *
12
+ * The `override` bypass on `PriorityInput` is still position-1: this
13
+ * module never runs when an override is active — the admission
14
+ * composite (AISDLC-48) short-circuits on override before calling
15
+ * `computeAdmissionHumanCurve`.
16
+ */
17
+ import type { AdmissionInput, DesignAuthoritySignal } from './admission-score.js';
18
+ /**
19
+ * Fixed §A.6 weights. Exposed for validation and for downstream callers
20
+ * that need to introspect the HC decomposition.
21
+ */
22
+ export declare const HC_WEIGHTS: Readonly<{
23
+ explicit: 0.2;
24
+ consensus: 0.45;
25
+ decision: 0.25;
26
+ design: 0.1;
27
+ }>;
28
+ /** Sum of HC_WEIGHTS — must equal 1.0 exactly (AC #2). */
29
+ export declare const HC_WEIGHT_SUM: number;
30
+ export interface AdmissionHumanCurveResult {
31
+ /** Signed explicit-priority signal in [-1, 1]. */
32
+ hcExplicit: number;
33
+ /** Signed consensus signal in [-1, 1]. */
34
+ hcConsensus: number;
35
+ /** Signed meeting-decision signal in [-1, 1] (0 = neutral when absent). */
36
+ hcDecision: number;
37
+ /** Signed design-authority signal in [-1, 1]. */
38
+ hcDesign: number;
39
+ /** Weighted sum before tanh. */
40
+ hcRaw: number;
41
+ /** `tanh(hcRaw)` — the HC value consumed by the admission composite. */
42
+ hcComposite: number;
43
+ }
44
+ export declare function deriveHcExplicit(input: Pick<AdmissionInput, 'labels'>): number;
45
+ export declare function deriveHcConsensus(input: Pick<AdmissionInput, 'reactionCount' | 'authorAssociation'>): number;
46
+ /**
47
+ * HC_decision — meeting-decision signal in [-1, 1].
48
+ *
49
+ * AdmissionInput has no dedicated meeting-decision field. We return
50
+ * neutral (0) by default. Callers that later add a GitHub-comment
51
+ * parser for `/decide approve` / `/decide reject` can plumb it through
52
+ * via an optional AdmissionInput field without breaking this shape.
53
+ */
54
+ export declare function deriveHcDecision(_input: AdmissionInput): number;
55
+ export declare function deriveHcDesign(signal: DesignAuthoritySignal | undefined): number;
56
+ /**
57
+ * Compute the admission HC composite from an `AdmissionInput`.
58
+ * Returns both the weighted pre-tanh sum and the tanh-compressed value
59
+ * for auditability.
60
+ */
61
+ export declare function computeAdmissionHumanCurve(input: AdmissionInput): AdmissionHumanCurveResult;
62
+ //# sourceMappingURL=admission-hc.d.ts.map
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Admission-specific Human Curve composite (RFC-0008 §A.6, Amendment 4).
3
+ *
4
+ * The admission HC differs from the legacy PPA HC in two ways:
5
+ * 1. Four terms instead of three — HC_design enters at 0.10 weight.
6
+ * 2. Weights are (0.2, 0.45, 0.25, 0.10) rather than (0.5, 0.3, 0.2).
7
+ *
8
+ * HC_design flows through tanh alongside the other three components;
9
+ * it is NOT a direct soul-alignment modifier (Amendment 5 correction
10
+ * to the v3 draft).
11
+ *
12
+ * The `override` bypass on `PriorityInput` is still position-1: this
13
+ * module never runs when an override is active — the admission
14
+ * composite (AISDLC-48) short-circuits on override before calling
15
+ * `computeAdmissionHumanCurve`.
16
+ */
17
+ import { computeDesignAuthorityWeight } from './admission-enrichment.js';
18
+ /**
19
+ * Fixed §A.6 weights. Exposed for validation and for downstream callers
20
+ * that need to introspect the HC decomposition.
21
+ */
22
+ export const HC_WEIGHTS = Object.freeze({
23
+ explicit: 0.2,
24
+ consensus: 0.45,
25
+ decision: 0.25,
26
+ design: 0.1,
27
+ });
28
+ /** Sum of HC_WEIGHTS — must equal 1.0 exactly (AC #2). */
29
+ export const HC_WEIGHT_SUM = HC_WEIGHTS.explicit + HC_WEIGHTS.consensus + HC_WEIGHTS.decision + HC_WEIGHTS.design;
30
+ const TRUSTED_ASSOCIATIONS = new Set(['OWNER', 'MEMBER', 'COLLABORATOR']);
31
+ export function deriveHcExplicit(input) {
32
+ const labels = input.labels;
33
+ if (labels.includes('high') || labels.includes('P0') || labels.includes('critical')) {
34
+ return 1.0;
35
+ }
36
+ if (labels.includes('low') || labels.includes('backlog'))
37
+ return -1.0;
38
+ return 0;
39
+ }
40
+ export function deriveHcConsensus(input) {
41
+ const isTrusted = TRUSTED_ASSOCIATIONS.has(input.authorAssociation ?? 'NONE');
42
+ const reactionConsensus = Math.min(1, input.reactionCount / 5);
43
+ // Trusted authors carry implicit team consensus — floor at 0.5 before centering.
44
+ const base = isTrusted ? Math.max(0.5, reactionConsensus) : reactionConsensus;
45
+ // [0, 1] → [-1, 1]
46
+ return base * 2 - 1;
47
+ }
48
+ /**
49
+ * HC_decision — meeting-decision signal in [-1, 1].
50
+ *
51
+ * AdmissionInput has no dedicated meeting-decision field. We return
52
+ * neutral (0) by default. Callers that later add a GitHub-comment
53
+ * parser for `/decide approve` / `/decide reject` can plumb it through
54
+ * via an optional AdmissionInput field without breaking this shape.
55
+ */
56
+ export function deriveHcDecision(_input) {
57
+ return 0;
58
+ }
59
+ export function deriveHcDesign(signal) {
60
+ const raw = computeDesignAuthorityWeight(signal);
61
+ return clamp(raw, -1, 1);
62
+ }
63
+ /**
64
+ * Compute the admission HC composite from an `AdmissionInput`.
65
+ * Returns both the weighted pre-tanh sum and the tanh-compressed value
66
+ * for auditability.
67
+ */
68
+ export function computeAdmissionHumanCurve(input) {
69
+ const hcExplicit = deriveHcExplicit(input);
70
+ const hcConsensus = deriveHcConsensus(input);
71
+ const hcDecision = deriveHcDecision(input);
72
+ const hcDesign = deriveHcDesign(input.designAuthoritySignal);
73
+ const hcRaw = HC_WEIGHTS.explicit * hcExplicit +
74
+ HC_WEIGHTS.consensus * hcConsensus +
75
+ HC_WEIGHTS.decision * hcDecision +
76
+ HC_WEIGHTS.design * hcDesign;
77
+ const hcComposite = Math.tanh(hcRaw);
78
+ return { hcExplicit, hcConsensus, hcDecision, hcDesign, hcRaw, hcComposite };
79
+ }
80
+ function clamp(value, min, max) {
81
+ return Math.min(max, Math.max(min, value));
82
+ }
83
+ //# sourceMappingURL=admission-hc.js.map
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Issue admission scoring — maps GitHub issue fields to PPA dimensions
3
+ * and determines whether an issue should enter the pipeline.
4
+ *
5
+ * Extracted from dogfood/scripts/ppa-score.ts for reuse across CLI
6
+ * scripts and workflows.
7
+ */
8
+ import type { PriorityInput, PriorityScore, PriorityConfig } from './priority.js';
9
+ import { type PillarBreakdown } from './pillar-breakdown.js';
10
+ /**
11
+ * GitHub author_association values indicating trust level.
12
+ * OWNER/MEMBER/COLLABORATOR = trusted (project team)
13
+ * CONTRIBUTOR = semi-trusted (has had PRs merged)
14
+ * NONE = untrusted (external)
15
+ */
16
+ export type AuthorAssociation = 'OWNER' | 'MEMBER' | 'COLLABORATOR' | 'CONTRIBUTOR' | 'FIRST_TIMER' | 'FIRST_TIME_CONTRIBUTOR' | 'NONE';
17
+ export interface AdmissionInput {
18
+ issueNumber: number;
19
+ title: string;
20
+ body: string;
21
+ labels: string[];
22
+ /** Total thumbsUp + heart reactions. */
23
+ reactionCount: number;
24
+ /** Number of human comments. */
25
+ commentCount: number;
26
+ /** ISO timestamp of issue creation. */
27
+ createdAt: string;
28
+ /** GitHub author_association — determines trust-based signal boosting. */
29
+ authorAssociation?: AuthorAssociation;
30
+ /** GitHub login of the issue author (used by C5 principal match). */
31
+ authorLogin?: string;
32
+ /** GitHub logins of anyone who commented on the issue (C5 principal match). */
33
+ commenterLogins?: string[];
34
+ /** C2 Eρ₄ inputs — populated by enrichAdmissionInput() (AISDLC-43). */
35
+ designSystemContext?: DesignSystemContext;
36
+ /** C4 inputs — current earned autonomy vs. required level (AISDLC-45). */
37
+ autonomyContext?: AutonomyContext;
38
+ /** C3 inputs — defect/churn/rejection signals per code area (AISDLC-44). */
39
+ codeAreaQuality?: CodeAreaQuality;
40
+ /** C5 inputs — HC_design signal from design-authority principals (AISDLC-46). */
41
+ designAuthoritySignal?: DesignAuthoritySignal;
42
+ /**
43
+ * Backlog-task signals (RFC-0010 dual-workflow). Populated when the issue comes
44
+ * from a Backlog.md task instead of GitHub. Used to discriminate between tasks
45
+ * that share identical GitHub-style signals (no reactions / no comments / OWNER
46
+ * author) — typical for the internal backlog workflow.
47
+ */
48
+ backlogContext?: BacklogContext;
49
+ }
50
+ export interface BacklogContext {
51
+ /** Frontmatter `priority` field — operator's stated importance. */
52
+ priority?: 'critical' | 'high' | 'medium' | 'low';
53
+ /** Number of tasks this one is blocked by (frontmatter `dependencies`). */
54
+ dependencyCount?: number;
55
+ /** Number of file/RFC/URL references in the task body. */
56
+ referenceCount?: number;
57
+ /** Number of acceptance criteria — proxy for scope. */
58
+ acceptanceCriteriaCount?: number;
59
+ /** Frontmatter `status` value (e.g. "To Do", "Draft", "In Progress", "Done"). */
60
+ status?: string;
61
+ }
62
+ export interface DesignSystemContext {
63
+ /** Catalog coverage percent (0–100) from DSB.status.catalogHealth. */
64
+ catalogCoverage?: number;
65
+ /** Token compliance percent (0–100) from DSB.status.tokenCompliance. */
66
+ tokenCompliance?: number;
67
+ /** True when DSB is young or catalog coverage is below the bootstrap floor. */
68
+ inBootstrapPhase?: boolean;
69
+ /** Baseline coverage from visual_regression_results before DSB adoption. */
70
+ baselineCoverage?: number;
71
+ /** Component/token gaps preventing the issue from being built catalog-first. */
72
+ catalogGaps?: string[];
73
+ }
74
+ export interface AutonomyContext {
75
+ /** The AutonomyPolicy-issued earned level for the current agent (0–3). */
76
+ currentEarnedLevel: number;
77
+ /** Level required by the issue's complexity band (≤3→1, ≤6→2, else→3). */
78
+ requiredLevel: number;
79
+ }
80
+ export interface DesignQualityMetrics {
81
+ /** Fraction of design CI checks passing in the window (0–1). */
82
+ designCIPassRate?: number;
83
+ /** Fraction of PRs in the area rejected on design grounds (0–1). */
84
+ designReviewRejectionRate?: number;
85
+ /** Fraction of usability-sim tasks completed successfully (0–1). */
86
+ usabilitySimPassRate?: number;
87
+ }
88
+ export interface CodeAreaQuality {
89
+ defectDensity?: number;
90
+ churnRate?: number;
91
+ prRejectionRate?: number;
92
+ /** True when the code area produces frontend artifacts gated by the DSB. */
93
+ hasFrontendComponents: boolean;
94
+ /** Present only when `hasFrontendComponents === true`. */
95
+ designQuality?: DesignQualityMetrics;
96
+ }
97
+ export type DesignAuthoritySignalType = 'advances-design-coherence' | 'fills-catalog-gap' | 'fragments-component-catalog' | 'misaligned-with-brand' | 'unspecified';
98
+ export interface DesignAuthoritySignal {
99
+ /** True when the issue author/commenter is a DSB designAuthority principal. */
100
+ isDesignAuthority: boolean;
101
+ /** The signal type parsed from labels or structured comments. */
102
+ signalType?: DesignAuthoritySignalType;
103
+ /** The issue's code area compliance score in [0, 1] (used to modulate weight). */
104
+ areaComplianceScore?: number;
105
+ }
106
+ export interface AdmissionThresholds {
107
+ minimumScore: number;
108
+ minimumConfidence: number;
109
+ }
110
+ export interface IssueAdmissionResult {
111
+ admitted: boolean;
112
+ score: PriorityScore;
113
+ reason: string;
114
+ suggestions?: string[];
115
+ /**
116
+ * RFC-0008 §A.6 — pillar attribution + tension flags. Required on
117
+ * every admission result so reviewers can act on pillar mismatches.
118
+ */
119
+ pillarBreakdown: PillarBreakdown;
120
+ }
121
+ /**
122
+ * Map GitHub issue fields to PPA PriorityInput dimensions.
123
+ *
124
+ * Heuristics (ported from dogfood/scripts/ppa-score.ts):
125
+ * - Labels → bug severity, soul alignment hints, builder conviction
126
+ * - Reactions → team consensus, customer request count
127
+ * - Comments → demand signal
128
+ * - Body complexity section → complexity score
129
+ * - Issue age → competitive drift
130
+ */
131
+ export declare function mapIssueToPriorityInput(input: AdmissionInput): PriorityInput;
132
+ /**
133
+ * Score a GitHub issue for pipeline admission using the RFC-0008 §A.6
134
+ * admission-subset composite.
135
+ *
136
+ * P_admission = SA × D-pi_adjusted × ER × (1 + HC)
137
+ *
138
+ * M-phi, E-tau, C-kappa are deferred to runtime scoring — they apply
139
+ * when an admitted issue is picked up for execution, not at the gate.
140
+ *
141
+ * Returns whether the issue is admitted (score and confidence above
142
+ * thresholds) along with the full score and, if rejected, suggestions
143
+ * for improvement.
144
+ */
145
+ export declare function scoreIssueForAdmission(input: AdmissionInput, thresholds: AdmissionThresholds, priorityConfig?: PriorityConfig, options?: import('./admission-composite.js').AdmissionCompositeOptions): IssueAdmissionResult;
146
+ /** Map backlog frontmatter priority string to the typed BacklogContext shape. */
147
+ export declare function normalizeBacklogPriority(p: string | null | undefined): BacklogContext['priority'];
148
+ //# sourceMappingURL=admission-score.d.ts.map