@ai-sdlc/orchestrator 0.10.0 → 0.14.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 (168) hide show
  1. package/dist/adapters.d.ts +42 -3
  2. package/dist/adapters.js +133 -3
  3. package/dist/admission-composite.d.ts +112 -1
  4. package/dist/admission-composite.js +85 -4
  5. package/dist/admission-enrichment.d.ts +12 -3
  6. package/dist/admission-enrichment.js +64 -13
  7. package/dist/admission-score.d.ts +30 -0
  8. package/dist/admission-score.js +4 -1
  9. package/dist/analysis/file-walker.js +5 -0
  10. package/dist/backlog-adapter.d.ts +45 -0
  11. package/dist/backlog-adapter.js +145 -1
  12. package/dist/calibration.d.ts +81 -0
  13. package/dist/calibration.js +76 -0
  14. package/dist/cli/commands/git-remote.js +1 -1
  15. package/dist/cli/commands/init-features.d.ts +301 -2
  16. package/dist/cli/commands/init-features.js +647 -7
  17. package/dist/cli/commands/init-templates.d.ts +198 -1
  18. package/dist/cli/commands/init-templates.js +943 -1
  19. package/dist/cli/commands/init.d.ts +45 -0
  20. package/dist/cli/commands/init.js +147 -5
  21. package/dist/cli/commands/run.js +9 -1
  22. package/dist/cli/index.d.ts +11 -0
  23. package/dist/cli/index.js +42 -8
  24. package/dist/compliance/composer.d.ts +79 -0
  25. package/dist/compliance/composer.js +258 -0
  26. package/dist/compliance/errors.d.ts +64 -0
  27. package/dist/compliance/errors.js +85 -0
  28. package/dist/compliance/loader.d.ts +52 -0
  29. package/dist/compliance/loader.js +124 -0
  30. package/dist/compliance/types.d.ts +184 -0
  31. package/dist/compliance/types.js +41 -0
  32. package/dist/compliance-clearance.d.ts +269 -0
  33. package/dist/compliance-clearance.js +269 -0
  34. package/dist/config.js +17 -0
  35. package/dist/cost-tracker.d.ts +22 -0
  36. package/dist/cost-tracker.js +41 -0
  37. package/dist/cycle-utils.js +14 -1
  38. package/dist/database/adapters/external.js +5 -1
  39. package/dist/embedding/adapters/openai-text-embedding-3-small.d.ts +71 -0
  40. package/dist/embedding/adapters/openai-text-embedding-3-small.js +190 -0
  41. package/dist/embedding/consumers/tessellation-drift.d.ts +74 -0
  42. package/dist/embedding/consumers/tessellation-drift.js +76 -0
  43. package/dist/embedding/cross-provider.d.ts +78 -0
  44. package/dist/embedding/cross-provider.js +75 -0
  45. package/dist/embedding/deprecation.d.ts +151 -0
  46. package/dist/embedding/deprecation.js +229 -0
  47. package/dist/embedding/errors.d.ts +90 -0
  48. package/dist/embedding/errors.js +150 -0
  49. package/dist/embedding/index.d.ts +29 -0
  50. package/dist/embedding/index.js +24 -0
  51. package/dist/embedding/pipeline-load.d.ts +146 -0
  52. package/dist/embedding/pipeline-load.js +178 -0
  53. package/dist/embedding/registry.d.ts +45 -0
  54. package/dist/embedding/registry.js +61 -0
  55. package/dist/embedding/stale-vector.d.ts +110 -0
  56. package/dist/embedding/stale-vector.js +92 -0
  57. package/dist/embedding/storage/index.d.ts +51 -0
  58. package/dist/embedding/storage/index.js +43 -0
  59. package/dist/embedding/storage/jsonl-backend.d.ts +150 -0
  60. package/dist/embedding/storage/jsonl-backend.js +332 -0
  61. package/dist/embedding/storage/types.d.ts +135 -0
  62. package/dist/embedding/storage/types.js +13 -0
  63. package/dist/embedding/types.d.ts +180 -0
  64. package/dist/embedding/types.js +10 -0
  65. package/dist/execute.d.ts +29 -2
  66. package/dist/execute.js +200 -38
  67. package/dist/fix-review.js +1 -1
  68. package/dist/index.d.ts +14 -2
  69. package/dist/index.js +19 -2
  70. package/dist/journey/inheritance-validator.d.ts +396 -0
  71. package/dist/journey/inheritance-validator.js +370 -0
  72. package/dist/journey/metric-snapshot.d.ts +403 -0
  73. package/dist/journey/metric-snapshot.js +370 -0
  74. package/dist/journey/state-id-drift-rule.d.ts +137 -0
  75. package/dist/journey/state-id-drift-rule.js +245 -0
  76. package/dist/journey-sa2-router.d.ts +395 -0
  77. package/dist/journey-sa2-router.js +308 -0
  78. package/dist/otel-exporter.js +0 -3
  79. package/dist/runners/claude-code.js +3 -3
  80. package/dist/runners/review-agent.js +6 -2
  81. package/dist/runners/runner-registry.d.ts +36 -0
  82. package/dist/runners/runner-registry.js +90 -0
  83. package/dist/runtime/attestations.d.ts +173 -13
  84. package/dist/runtime/attestations.js +265 -43
  85. package/dist/runtime/index.d.ts +1 -1
  86. package/dist/runtime/index.js +1 -1
  87. package/dist/sa-scoring/exemplar-bank.js +3 -1
  88. package/dist/sa-scoring/layer3-llm.js +6 -1
  89. package/dist/sa-scoring/revision-proposal-config.d.ts +178 -0
  90. package/dist/sa-scoring/revision-proposal-config.js +198 -0
  91. package/dist/sa-scoring/revision-proposal.d.ts +285 -0
  92. package/dist/sa-scoring/revision-proposal.js +417 -0
  93. package/dist/shared.d.ts +28 -0
  94. package/dist/shared.js +37 -0
  95. package/dist/signal-ingestion/adapters/community-thread.d.ts +43 -0
  96. package/dist/signal-ingestion/adapters/community-thread.js +55 -0
  97. package/dist/signal-ingestion/adapters/in-app-feedback.d.ts +67 -0
  98. package/dist/signal-ingestion/adapters/in-app-feedback.js +51 -0
  99. package/dist/signal-ingestion/adapters/manual.d.ts +78 -0
  100. package/dist/signal-ingestion/adapters/manual.js +112 -0
  101. package/dist/signal-ingestion/adapters/support-ticket.d.ts +47 -0
  102. package/dist/signal-ingestion/adapters/support-ticket.js +51 -0
  103. package/dist/signal-ingestion/classifier.d.ts +205 -0
  104. package/dist/signal-ingestion/classifier.js +494 -0
  105. package/dist/signal-ingestion/clustering-types.d.ts +36 -0
  106. package/dist/signal-ingestion/clustering-types.js +14 -0
  107. package/dist/signal-ingestion/clustering.d.ts +200 -0
  108. package/dist/signal-ingestion/clustering.js +413 -0
  109. package/dist/signal-ingestion/config.d.ts +351 -0
  110. package/dist/signal-ingestion/config.js +587 -0
  111. package/dist/signal-ingestion/d1.d.ts +252 -0
  112. package/dist/signal-ingestion/d1.js +235 -0
  113. package/dist/signal-ingestion/errors.d.ts +73 -0
  114. package/dist/signal-ingestion/errors.js +108 -0
  115. package/dist/signal-ingestion/governance-events.d.ts +181 -0
  116. package/dist/signal-ingestion/governance-events.js +189 -0
  117. package/dist/signal-ingestion/index.d.ts +35 -0
  118. package/dist/signal-ingestion/index.js +53 -0
  119. package/dist/signal-ingestion/manual-share-metric.d.ts +93 -0
  120. package/dist/signal-ingestion/manual-share-metric.js +106 -0
  121. package/dist/signal-ingestion/registry.d.ts +40 -0
  122. package/dist/signal-ingestion/registry.js +137 -0
  123. package/dist/signal-ingestion/residency.d.ts +227 -0
  124. package/dist/signal-ingestion/residency.js +238 -0
  125. package/dist/signal-ingestion/significance.d.ts +554 -0
  126. package/dist/signal-ingestion/significance.js +555 -0
  127. package/dist/signal-ingestion/types.d.ts +191 -0
  128. package/dist/signal-ingestion/types.js +8 -0
  129. package/dist/substrate/drift-composition.d.ts +270 -0
  130. package/dist/substrate/drift-composition.js +306 -0
  131. package/dist/substrate/drift-tui-surface.d.ts +61 -0
  132. package/dist/substrate/drift-tui-surface.js +102 -0
  133. package/dist/substrate/identity-class.d.ts +176 -0
  134. package/dist/substrate/identity-class.js +201 -0
  135. package/dist/tessellation/cross-soul-provenance-rule.d.ts +133 -0
  136. package/dist/tessellation/cross-soul-provenance-rule.js +171 -0
  137. package/dist/tessellation/inter-soul-embedding-distance-rule.d.ts +61 -0
  138. package/dist/tessellation/inter-soul-embedding-distance-rule.js +67 -0
  139. package/dist/tessellation/rule-registry.d.ts +269 -0
  140. package/dist/tessellation/rule-registry.js +92 -0
  141. package/dist/tessellation/soul-slug-ast-scan-rule.d.ts +90 -0
  142. package/dist/tessellation/soul-slug-ast-scan-rule.js +158 -0
  143. package/dist/tessellation-admission.d.ts +162 -0
  144. package/dist/tessellation-admission.js +146 -0
  145. package/dist/tessellation-drift.d.ts +246 -0
  146. package/dist/tessellation-drift.js +250 -0
  147. package/dist/validate-config.js +13 -0
  148. package/dist/validate-issue.js +2 -2
  149. package/dist/variant/cardinality-activation.d.ts +126 -0
  150. package/dist/variant/cardinality-activation.js +101 -0
  151. package/dist/variant/deprecation-lifecycle.d.ts +184 -0
  152. package/dist/variant/deprecation-lifecycle.js +208 -0
  153. package/dist/variant/drift-extension.d.ts +136 -0
  154. package/dist/variant/drift-extension.js +164 -0
  155. package/dist/variant/engineering-review.d.ts +185 -0
  156. package/dist/variant/engineering-review.js +142 -0
  157. package/dist/variant/index.d.ts +32 -0
  158. package/dist/variant/index.js +32 -0
  159. package/dist/variant/inheritance-validator.d.ts +165 -0
  160. package/dist/variant/inheritance-validator.js +139 -0
  161. package/dist/variant/internal-adopter/index.d.ts +11 -0
  162. package/dist/variant/internal-adopter/index.js +10 -0
  163. package/dist/variant/internal-adopter/products.d.ts +156 -0
  164. package/dist/variant/internal-adopter/products.js +366 -0
  165. package/dist/variant-admission.d.ts +316 -0
  166. package/dist/variant-admission.js +247 -0
  167. package/dist/webhook-manager.js +7 -1
  168. package/package.json +15 -12
@@ -3,5 +3,5 @@ export { slugifyBranch, worktreePath, verifyOwnership, assertOwnership, isExisti
3
3
  export { WorktreePoolManager, WorktreePoolError, DEFAULT_POOL_ROOT, DEFAULT_STALE_THRESHOLD_DAYS, type WorktreePoolSpec, type WorktreePoolManagerDeps, type AllocateOptions, type WorktreeHandle, } from './worktree-pool.js';
4
4
  export { readParallelismMode, isParallelismEnabled, FLAG_NAME as PARALLELISM_FLAG, type ParallelismMode, } from './parallelism-flag.js';
5
5
  export { cleanGitEnv, gitExecFile } from './git-env.js';
6
- export { ACCEPTED_SCHEMA_VERSIONS, DSSE_PAYLOAD_TYPE, buildPredicate, generateSigningKeyPair, paeEncode, sha1Hex, sha256Hex, signAttestation, validateTrustedReviewers, verifyAttestation, type AttestationPredicate, type DsseEnvelope, type DsseSignature, type ReviewerEntry, type SchemaVersion, type SubjectDigest, type TrustedReviewer, type VerifyResult, } from './attestations.js';
6
+ export { ACCEPTED_SCHEMA_VERSIONS, ATTESTATION_ENVELOPE_PATH_PATTERN, CONTENTHASH_SHARED_CHURN_FILES, CONTENTHASHV4_IGNORE_FILES, DSSE_PAYLOAD_TYPE, INDEPENDENCE_REQUIRED_ROLES, REQUIRED_REVIEWER_AGENT_IDS, REVIEWER_ROLE_EQUIVALENCES, buildPredicate, collectChangedFileDeltaEntries, collectChangedFileEntries, collectChangedFileEntriesForV5, computeContentHash, computeContentHashV3, computeContentHashV4, computeContentHashV5, generateSigningKeyPair, isAttestationEnvelopePath, isIgnoredForContentHash, paeEncode, projectDeltaEntriesToHeadEntries, sha1Hex, sha256Hex, signAttestation, validatePredicateShape, validateTrustedReviewers, verifyAttestation, type AttestationPredicate, type BuildPredicateInputs, type ChangedFileDeltaEntry, type ChangedFileEntry, type ChangedFileHeadEntry, type ChangedFileV5Entry, type CollectChangedFileEntriesOptions, type DsseEnvelope, type DsseSignature, type ReviewerEntry, type SchemaVersion, type SubjectDigest, type TrustedReviewer, type V5CollectResult, type VerifyOptions, type VerifyResult, } from './attestations.js';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -3,5 +3,5 @@ export { slugifyBranch, worktreePath, verifyOwnership, assertOwnership, isExisti
3
3
  export { WorktreePoolManager, WorktreePoolError, DEFAULT_POOL_ROOT, DEFAULT_STALE_THRESHOLD_DAYS, } from './worktree-pool.js';
4
4
  export { readParallelismMode, isParallelismEnabled, FLAG_NAME as PARALLELISM_FLAG, } from './parallelism-flag.js';
5
5
  export { cleanGitEnv, gitExecFile } from './git-env.js';
6
- export { ACCEPTED_SCHEMA_VERSIONS, DSSE_PAYLOAD_TYPE, buildPredicate, generateSigningKeyPair, paeEncode, sha1Hex, sha256Hex, signAttestation, validateTrustedReviewers, verifyAttestation, } from './attestations.js';
6
+ export { ACCEPTED_SCHEMA_VERSIONS, ATTESTATION_ENVELOPE_PATH_PATTERN, CONTENTHASH_SHARED_CHURN_FILES, CONTENTHASHV4_IGNORE_FILES, DSSE_PAYLOAD_TYPE, INDEPENDENCE_REQUIRED_ROLES, REQUIRED_REVIEWER_AGENT_IDS, REVIEWER_ROLE_EQUIVALENCES, buildPredicate, collectChangedFileDeltaEntries, collectChangedFileEntries, collectChangedFileEntriesForV5, computeContentHash, computeContentHashV3, computeContentHashV4, computeContentHashV5, generateSigningKeyPair, isAttestationEnvelopePath, isIgnoredForContentHash, paeEncode, projectDeltaEntriesToHeadEntries, sha1Hex, sha256Hex, signAttestation, validatePredicateShape, validateTrustedReviewers, verifyAttestation, } from './attestations.js';
7
7
  //# sourceMappingURL=index.js.map
@@ -29,7 +29,9 @@ export function loadExemplarBank(filePath) {
29
29
  doc = parseYaml(raw);
30
30
  }
31
31
  catch (err) {
32
- throw new Error(`Failed to parse SA exemplar bank at ${filePath}: ${err.message}`);
32
+ throw new Error(`Failed to parse SA exemplar bank at ${filePath}: ${err.message}`, {
33
+ cause: err,
34
+ });
33
35
  }
34
36
  if (!doc || typeof doc !== 'object' || !('exemplars' in doc)) {
35
37
  throw new Error(`SA exemplar bank ${filePath} must contain a top-level "exemplars" array`);
@@ -180,7 +180,12 @@ export function buildSa2Prompt(ctx) {
180
180
  }
181
181
  /** Extract the first JSON object from a raw LLM reply. */
182
182
  export function extractJson(raw) {
183
- const fenced = raw.match(/```(?:json)?\s*([\s\S]*?)```/i);
183
+ // Drop the leading optional-whitespace group entirely: any `[ \t]*`/`\s*`
184
+ // before the lazy `[\s\S]*?` capture overlaps it (both match space/tab),
185
+ // which is the polynomial-backtracking source (CodeQL js/polynomial-redos).
186
+ // The bounded `\n?` (0-or-1, not a `*`) is safe, and `.trim()` below absorbs
187
+ // any residual leading whitespace the capture picks up.
188
+ const fenced = raw.match(/```(?:json)?\n?([\s\S]*?)```/i);
184
189
  const candidate = fenced ? fenced[1] : raw;
185
190
  try {
186
191
  return JSON.parse(candidate.trim());
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Per-org calibration.yaml configuration for RFC-0031 DIDRevisionProposal
3
+ * mechanism (Refit AISDLC-310).
4
+ *
5
+ * Exposes OQ-12.1 (confidence thresholds) and OQ-12.5 (rejection weights +
6
+ * penalty floor) as per-org configurable values. Defaults match the values
7
+ * shipped by AISDLC-271 / PR #476 and operator-affirmed during the 2026-05-16
8
+ * audit (RFC-0031 §12.1 + §12.5 resolutions).
9
+ *
10
+ * Usage:
11
+ * 1. Load the `.ai-sdlc/calibration.yaml` file.
12
+ * 2. Call `parseRevisionProposalCalibrationYaml(content)` — validates +
13
+ * returns a fully-resolved config with all defaults filled in.
14
+ * 3. Pass the resolved config to `computeConfidence()`,
15
+ * `recordRejection()`, and `computeRejectionPrecedentFactor()`.
16
+ *
17
+ * Validation rules (enforced at load time):
18
+ * - `highSampleSize > lowSampleSize > 0`
19
+ * - All weights in `[0, 1]`
20
+ * - `confidencePenaltyFloor` in `[0, 1]`
21
+ */
22
+ /** Minimum total signals (dismiss + escalate + drift) for HIGH confidence. */
23
+ export declare const DEFAULT_CONFIDENCE_HIGH_SAMPLE_SIZE = 20;
24
+ /** Below this total signal count the proposal is LOW confidence. */
25
+ export declare const DEFAULT_CONFIDENCE_LOW_SAMPLE_SIZE = 5;
26
+ /** Rejection precedent weight applied when the rejected proposal had HIGH confidence. */
27
+ export declare const DEFAULT_REJECTION_WEIGHT_HIGH = 0.8;
28
+ /** Rejection precedent weight applied when the rejected proposal had MEDIUM confidence. */
29
+ export declare const DEFAULT_REJECTION_WEIGHT_MEDIUM = 0.5;
30
+ /** Rejection precedent weight applied when the rejected proposal had LOW confidence. */
31
+ export declare const DEFAULT_REJECTION_WEIGHT_LOW = 0.2;
32
+ /**
33
+ * Minimum value for the rejection precedent factor.
34
+ * 0.2 = at most 80% suppression of future proposal confidence.
35
+ */
36
+ export declare const DEFAULT_CONFIDENCE_PENALTY_FLOOR = 0.2;
37
+ /**
38
+ * Confidence threshold configuration (OQ-12.1).
39
+ *
40
+ * Sample size = `dismissSignals + escalateSignals + driftEvents`.
41
+ */
42
+ export interface ConfidenceThresholdsConfig {
43
+ /**
44
+ * Total signal count ≥ this value contributes toward HIGH confidence
45
+ * (alongside non-ambiguous classification and `evolving` identityClass).
46
+ *
47
+ * @default 20
48
+ */
49
+ highSampleSize: number;
50
+ /**
51
+ * Total signal count < this value forces LOW confidence.
52
+ *
53
+ * Must be < `highSampleSize`.
54
+ * @default 5
55
+ */
56
+ lowSampleSize: number;
57
+ }
58
+ /**
59
+ * Rejection precedent weights (OQ-12.5).
60
+ *
61
+ * These weights are stored on each `ProposalRejectionRecord` and averaged
62
+ * by `computeRejectionPrecedentFactor()` to suppress future proposal
63
+ * confidence for repeatedly-rejected fields.
64
+ */
65
+ export interface RejectionPrecedentWeightsConfig {
66
+ /**
67
+ * Weight when the rejected proposal had HIGH confidence.
68
+ * Higher weight = stronger suppression of future proposals.
69
+ * @default 0.8
70
+ */
71
+ highConfidenceRejection: number;
72
+ /**
73
+ * Weight when the rejected proposal had MEDIUM confidence.
74
+ * @default 0.5
75
+ */
76
+ mediumConfidenceRejection: number;
77
+ /**
78
+ * Weight when the rejected proposal had LOW confidence.
79
+ * @default 0.2
80
+ */
81
+ lowConfidenceRejection: number;
82
+ }
83
+ /**
84
+ * Rejection precedent configuration block (OQ-12.5).
85
+ */
86
+ export interface RejectionPrecedentConfig {
87
+ weights: RejectionPrecedentWeightsConfig;
88
+ /**
89
+ * Minimum value returned by `computeRejectionPrecedentFactor()`.
90
+ * Prevents the precedent factor from suppressing proposals entirely.
91
+ *
92
+ * Formula: `factor = max(confidencePenaltyFloor, 1.0 - avgWeight × 0.5)`
93
+ * @default 0.2
94
+ */
95
+ confidencePenaltyFloor: number;
96
+ }
97
+ /**
98
+ * Raw (partial) calibration config shape as it appears in `calibration.yaml`.
99
+ * All fields are optional; missing values fall back to defaults.
100
+ */
101
+ export interface RevisionProposalCalibrationConfig {
102
+ /** Fields that should never receive auto-proposals (OQ-12.3 — existing). */
103
+ lockNoProposal?: string[];
104
+ /** Override confidence thresholds (OQ-12.1). */
105
+ confidenceThresholds?: Partial<ConfidenceThresholdsConfig>;
106
+ /** Override rejection precedent weights + floor (OQ-12.5). */
107
+ rejectionPrecedent?: {
108
+ weights?: Partial<RejectionPrecedentWeightsConfig>;
109
+ confidencePenaltyFloor?: number;
110
+ };
111
+ }
112
+ /**
113
+ * Fully-resolved calibration config — all optional fields replaced with
114
+ * defaults. This is the shape passed to the revision-proposal functions.
115
+ */
116
+ export interface ResolvedRevisionProposalCalibrationConfig {
117
+ lockNoProposal: string[];
118
+ confidenceThresholds: ConfidenceThresholdsConfig;
119
+ rejectionPrecedent: RejectionPrecedentConfig;
120
+ }
121
+ /** The compile-time default resolved config (shipped AISDLC-271 values). */
122
+ export declare const DEFAULT_RESOLVED_CALIBRATION_CONFIG: ResolvedRevisionProposalCalibrationConfig;
123
+ export interface ConfigValidationError {
124
+ field: string;
125
+ message: string;
126
+ }
127
+ export type ConfigValidationResult = {
128
+ valid: true;
129
+ } | {
130
+ valid: false;
131
+ errors: ConfigValidationError[];
132
+ };
133
+ /**
134
+ * Validate a partial calibration config against the RFC-0031 §12.6 rules.
135
+ *
136
+ * Rules:
137
+ * - `highSampleSize > lowSampleSize > 0`
138
+ * - all weights in `[0, 1]`
139
+ * - `confidencePenaltyFloor` in `[0, 1]`
140
+ *
141
+ * Missing fields default to the shipped values and are not validated
142
+ * (a partial config that omits a field is always valid for that field).
143
+ */
144
+ export declare function validateRevisionProposalCalibrationConfig(config: RevisionProposalCalibrationConfig): ConfigValidationResult;
145
+ /**
146
+ * Merge a partial `RevisionProposalCalibrationConfig` with defaults to
147
+ * produce a fully-resolved config. Does NOT validate — call
148
+ * `validateRevisionProposalCalibrationConfig()` first if you need to
149
+ * surface errors to the operator.
150
+ */
151
+ export declare function resolveRevisionProposalCalibrationConfig(config?: RevisionProposalCalibrationConfig): ResolvedRevisionProposalCalibrationConfig;
152
+ /**
153
+ * Parse and validate a `.ai-sdlc/calibration.yaml` file's content.
154
+ *
155
+ * Expected top-level shape:
156
+ * ```yaml
157
+ * calibration:
158
+ * lockNoProposal: [...]
159
+ * confidenceThresholds:
160
+ * highSampleSize: 20
161
+ * lowSampleSize: 5
162
+ * rejectionPrecedent:
163
+ * weights:
164
+ * highConfidenceRejection: 0.8
165
+ * mediumConfidenceRejection: 0.5
166
+ * lowConfidenceRejection: 0.2
167
+ * confidencePenaltyFloor: 0.2
168
+ * ```
169
+ *
170
+ * Missing fields are filled with defaults. Validation failures throw with
171
+ * a descriptive message listing all constraint violations.
172
+ *
173
+ * @param yamlContent Raw UTF-8 content of `calibration.yaml`.
174
+ * @returns Fully-resolved config ready to pass to revision-proposal functions.
175
+ * @throws {Error} When the YAML fails RFC-0031 §12.6 validation rules.
176
+ */
177
+ export declare function parseRevisionProposalCalibrationYaml(yamlContent: string): ResolvedRevisionProposalCalibrationConfig;
178
+ //# sourceMappingURL=revision-proposal-config.d.ts.map
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Per-org calibration.yaml configuration for RFC-0031 DIDRevisionProposal
3
+ * mechanism (Refit AISDLC-310).
4
+ *
5
+ * Exposes OQ-12.1 (confidence thresholds) and OQ-12.5 (rejection weights +
6
+ * penalty floor) as per-org configurable values. Defaults match the values
7
+ * shipped by AISDLC-271 / PR #476 and operator-affirmed during the 2026-05-16
8
+ * audit (RFC-0031 §12.1 + §12.5 resolutions).
9
+ *
10
+ * Usage:
11
+ * 1. Load the `.ai-sdlc/calibration.yaml` file.
12
+ * 2. Call `parseRevisionProposalCalibrationYaml(content)` — validates +
13
+ * returns a fully-resolved config with all defaults filled in.
14
+ * 3. Pass the resolved config to `computeConfidence()`,
15
+ * `recordRejection()`, and `computeRejectionPrecedentFactor()`.
16
+ *
17
+ * Validation rules (enforced at load time):
18
+ * - `highSampleSize > lowSampleSize > 0`
19
+ * - All weights in `[0, 1]`
20
+ * - `confidencePenaltyFloor` in `[0, 1]`
21
+ */
22
+ import { parse as parseYaml } from 'yaml';
23
+ // ── Default constants ─────────────────────────────────────────────────
24
+ /** Minimum total signals (dismiss + escalate + drift) for HIGH confidence. */
25
+ export const DEFAULT_CONFIDENCE_HIGH_SAMPLE_SIZE = 20;
26
+ /** Below this total signal count the proposal is LOW confidence. */
27
+ export const DEFAULT_CONFIDENCE_LOW_SAMPLE_SIZE = 5;
28
+ /** Rejection precedent weight applied when the rejected proposal had HIGH confidence. */
29
+ export const DEFAULT_REJECTION_WEIGHT_HIGH = 0.8;
30
+ /** Rejection precedent weight applied when the rejected proposal had MEDIUM confidence. */
31
+ export const DEFAULT_REJECTION_WEIGHT_MEDIUM = 0.5;
32
+ /** Rejection precedent weight applied when the rejected proposal had LOW confidence. */
33
+ export const DEFAULT_REJECTION_WEIGHT_LOW = 0.2;
34
+ /**
35
+ * Minimum value for the rejection precedent factor.
36
+ * 0.2 = at most 80% suppression of future proposal confidence.
37
+ */
38
+ export const DEFAULT_CONFIDENCE_PENALTY_FLOOR = 0.2;
39
+ /** The compile-time default resolved config (shipped AISDLC-271 values). */
40
+ export const DEFAULT_RESOLVED_CALIBRATION_CONFIG = {
41
+ lockNoProposal: [],
42
+ confidenceThresholds: {
43
+ highSampleSize: DEFAULT_CONFIDENCE_HIGH_SAMPLE_SIZE,
44
+ lowSampleSize: DEFAULT_CONFIDENCE_LOW_SAMPLE_SIZE,
45
+ },
46
+ rejectionPrecedent: {
47
+ weights: {
48
+ highConfidenceRejection: DEFAULT_REJECTION_WEIGHT_HIGH,
49
+ mediumConfidenceRejection: DEFAULT_REJECTION_WEIGHT_MEDIUM,
50
+ lowConfidenceRejection: DEFAULT_REJECTION_WEIGHT_LOW,
51
+ },
52
+ confidencePenaltyFloor: DEFAULT_CONFIDENCE_PENALTY_FLOOR,
53
+ },
54
+ };
55
+ /**
56
+ * Validate a partial calibration config against the RFC-0031 §12.6 rules.
57
+ *
58
+ * Rules:
59
+ * - `highSampleSize > lowSampleSize > 0`
60
+ * - all weights in `[0, 1]`
61
+ * - `confidencePenaltyFloor` in `[0, 1]`
62
+ *
63
+ * Missing fields default to the shipped values and are not validated
64
+ * (a partial config that omits a field is always valid for that field).
65
+ */
66
+ export function validateRevisionProposalCalibrationConfig(config) {
67
+ const errors = [];
68
+ // ── Confidence thresholds ────────────────────────────────────────
69
+ const thresholds = config.confidenceThresholds;
70
+ if (thresholds !== undefined) {
71
+ const high = thresholds.highSampleSize ?? DEFAULT_CONFIDENCE_HIGH_SAMPLE_SIZE;
72
+ const low = thresholds.lowSampleSize ?? DEFAULT_CONFIDENCE_LOW_SAMPLE_SIZE;
73
+ if (thresholds.lowSampleSize !== undefined && thresholds.lowSampleSize <= 0) {
74
+ errors.push({
75
+ field: 'confidenceThresholds.lowSampleSize',
76
+ message: `must be > 0 (got ${thresholds.lowSampleSize})`,
77
+ });
78
+ }
79
+ if (thresholds.highSampleSize !== undefined && thresholds.highSampleSize <= 0) {
80
+ errors.push({
81
+ field: 'confidenceThresholds.highSampleSize',
82
+ message: `must be > 0 (got ${thresholds.highSampleSize})`,
83
+ });
84
+ }
85
+ // highSampleSize must be strictly greater than lowSampleSize
86
+ if (high <= low) {
87
+ errors.push({
88
+ field: 'confidenceThresholds',
89
+ message: `highSampleSize (${high}) must be > lowSampleSize (${low})`,
90
+ });
91
+ }
92
+ }
93
+ // ── Rejection precedent ──────────────────────────────────────────
94
+ const rp = config.rejectionPrecedent;
95
+ if (rp !== undefined) {
96
+ const weights = rp.weights;
97
+ if (weights !== undefined) {
98
+ const weightFields = [
99
+ ['highConfidenceRejection', weights.highConfidenceRejection],
100
+ ['mediumConfidenceRejection', weights.mediumConfidenceRejection],
101
+ ['lowConfidenceRejection', weights.lowConfidenceRejection],
102
+ ];
103
+ for (const [key, value] of weightFields) {
104
+ if (value !== undefined && (value < 0 || value > 1)) {
105
+ errors.push({
106
+ field: `rejectionPrecedent.weights.${key}`,
107
+ message: `must be in [0, 1] (got ${value})`,
108
+ });
109
+ }
110
+ }
111
+ }
112
+ if (rp.confidencePenaltyFloor !== undefined &&
113
+ (rp.confidencePenaltyFloor < 0 || rp.confidencePenaltyFloor > 1)) {
114
+ errors.push({
115
+ field: 'rejectionPrecedent.confidencePenaltyFloor',
116
+ message: `must be in [0, 1] (got ${rp.confidencePenaltyFloor})`,
117
+ });
118
+ }
119
+ }
120
+ if (errors.length > 0)
121
+ return { valid: false, errors };
122
+ return { valid: true };
123
+ }
124
+ // ── Resolution (merge partial config with defaults) ───────────────────
125
+ /**
126
+ * Merge a partial `RevisionProposalCalibrationConfig` with defaults to
127
+ * produce a fully-resolved config. Does NOT validate — call
128
+ * `validateRevisionProposalCalibrationConfig()` first if you need to
129
+ * surface errors to the operator.
130
+ */
131
+ export function resolveRevisionProposalCalibrationConfig(config = {}) {
132
+ const d = DEFAULT_RESOLVED_CALIBRATION_CONFIG;
133
+ return {
134
+ lockNoProposal: config.lockNoProposal ?? d.lockNoProposal,
135
+ confidenceThresholds: {
136
+ highSampleSize: config.confidenceThresholds?.highSampleSize ?? d.confidenceThresholds.highSampleSize,
137
+ lowSampleSize: config.confidenceThresholds?.lowSampleSize ?? d.confidenceThresholds.lowSampleSize,
138
+ },
139
+ rejectionPrecedent: {
140
+ weights: {
141
+ highConfidenceRejection: config.rejectionPrecedent?.weights?.highConfidenceRejection ??
142
+ d.rejectionPrecedent.weights.highConfidenceRejection,
143
+ mediumConfidenceRejection: config.rejectionPrecedent?.weights?.mediumConfidenceRejection ??
144
+ d.rejectionPrecedent.weights.mediumConfidenceRejection,
145
+ lowConfidenceRejection: config.rejectionPrecedent?.weights?.lowConfidenceRejection ??
146
+ d.rejectionPrecedent.weights.lowConfidenceRejection,
147
+ },
148
+ confidencePenaltyFloor: config.rejectionPrecedent?.confidencePenaltyFloor ??
149
+ d.rejectionPrecedent.confidencePenaltyFloor,
150
+ },
151
+ };
152
+ }
153
+ // ── YAML loading ──────────────────────────────────────────────────────
154
+ /**
155
+ * Parse and validate a `.ai-sdlc/calibration.yaml` file's content.
156
+ *
157
+ * Expected top-level shape:
158
+ * ```yaml
159
+ * calibration:
160
+ * lockNoProposal: [...]
161
+ * confidenceThresholds:
162
+ * highSampleSize: 20
163
+ * lowSampleSize: 5
164
+ * rejectionPrecedent:
165
+ * weights:
166
+ * highConfidenceRejection: 0.8
167
+ * mediumConfidenceRejection: 0.5
168
+ * lowConfidenceRejection: 0.2
169
+ * confidencePenaltyFloor: 0.2
170
+ * ```
171
+ *
172
+ * Missing fields are filled with defaults. Validation failures throw with
173
+ * a descriptive message listing all constraint violations.
174
+ *
175
+ * @param yamlContent Raw UTF-8 content of `calibration.yaml`.
176
+ * @returns Fully-resolved config ready to pass to revision-proposal functions.
177
+ * @throws {Error} When the YAML fails RFC-0031 §12.6 validation rules.
178
+ */
179
+ export function parseRevisionProposalCalibrationYaml(yamlContent) {
180
+ const doc = parseYaml(yamlContent);
181
+ const raw = (doc?.calibration ?? {});
182
+ const config = {
183
+ lockNoProposal: Array.isArray(raw.lockNoProposal) ? raw.lockNoProposal : undefined,
184
+ confidenceThresholds: raw.confidenceThresholds !== null && typeof raw.confidenceThresholds === 'object'
185
+ ? raw.confidenceThresholds
186
+ : undefined,
187
+ rejectionPrecedent: raw.rejectionPrecedent !== null && typeof raw.rejectionPrecedent === 'object'
188
+ ? raw.rejectionPrecedent
189
+ : undefined,
190
+ };
191
+ const validation = validateRevisionProposalCalibrationConfig(config);
192
+ if (!validation.valid) {
193
+ const lines = validation.errors.map((e) => ` ${e.field}: ${e.message}`).join('\n');
194
+ throw new Error(`calibration.yaml validation failed (RFC-0031 §12.6):\n${lines}`);
195
+ }
196
+ return resolveRevisionProposalCalibrationConfig(config);
197
+ }
198
+ //# sourceMappingURL=revision-proposal-config.js.map