@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.
- package/dist/adapters.d.ts +42 -3
- package/dist/adapters.js +133 -3
- package/dist/admission-composite.d.ts +112 -1
- package/dist/admission-composite.js +85 -4
- package/dist/admission-enrichment.d.ts +12 -3
- package/dist/admission-enrichment.js +64 -13
- package/dist/admission-score.d.ts +30 -0
- package/dist/admission-score.js +4 -1
- package/dist/analysis/file-walker.js +5 -0
- package/dist/backlog-adapter.d.ts +45 -0
- package/dist/backlog-adapter.js +145 -1
- package/dist/calibration.d.ts +81 -0
- package/dist/calibration.js +76 -0
- package/dist/cli/commands/git-remote.js +1 -1
- package/dist/cli/commands/init-features.d.ts +301 -2
- package/dist/cli/commands/init-features.js +647 -7
- package/dist/cli/commands/init-templates.d.ts +198 -1
- package/dist/cli/commands/init-templates.js +943 -1
- package/dist/cli/commands/init.d.ts +45 -0
- package/dist/cli/commands/init.js +147 -5
- package/dist/cli/commands/run.js +9 -1
- package/dist/cli/index.d.ts +11 -0
- package/dist/cli/index.js +42 -8
- package/dist/compliance/composer.d.ts +79 -0
- package/dist/compliance/composer.js +258 -0
- package/dist/compliance/errors.d.ts +64 -0
- package/dist/compliance/errors.js +85 -0
- package/dist/compliance/loader.d.ts +52 -0
- package/dist/compliance/loader.js +124 -0
- package/dist/compliance/types.d.ts +184 -0
- package/dist/compliance/types.js +41 -0
- package/dist/compliance-clearance.d.ts +269 -0
- package/dist/compliance-clearance.js +269 -0
- package/dist/config.js +17 -0
- package/dist/cost-tracker.d.ts +22 -0
- package/dist/cost-tracker.js +41 -0
- package/dist/cycle-utils.js +14 -1
- package/dist/database/adapters/external.js +5 -1
- package/dist/embedding/adapters/openai-text-embedding-3-small.d.ts +71 -0
- package/dist/embedding/adapters/openai-text-embedding-3-small.js +190 -0
- package/dist/embedding/consumers/tessellation-drift.d.ts +74 -0
- package/dist/embedding/consumers/tessellation-drift.js +76 -0
- package/dist/embedding/cross-provider.d.ts +78 -0
- package/dist/embedding/cross-provider.js +75 -0
- package/dist/embedding/deprecation.d.ts +151 -0
- package/dist/embedding/deprecation.js +229 -0
- package/dist/embedding/errors.d.ts +90 -0
- package/dist/embedding/errors.js +150 -0
- package/dist/embedding/index.d.ts +29 -0
- package/dist/embedding/index.js +24 -0
- package/dist/embedding/pipeline-load.d.ts +146 -0
- package/dist/embedding/pipeline-load.js +178 -0
- package/dist/embedding/registry.d.ts +45 -0
- package/dist/embedding/registry.js +61 -0
- package/dist/embedding/stale-vector.d.ts +110 -0
- package/dist/embedding/stale-vector.js +92 -0
- package/dist/embedding/storage/index.d.ts +51 -0
- package/dist/embedding/storage/index.js +43 -0
- package/dist/embedding/storage/jsonl-backend.d.ts +150 -0
- package/dist/embedding/storage/jsonl-backend.js +332 -0
- package/dist/embedding/storage/types.d.ts +135 -0
- package/dist/embedding/storage/types.js +13 -0
- package/dist/embedding/types.d.ts +180 -0
- package/dist/embedding/types.js +10 -0
- package/dist/execute.d.ts +29 -2
- package/dist/execute.js +200 -38
- package/dist/fix-review.js +1 -1
- package/dist/index.d.ts +14 -2
- package/dist/index.js +19 -2
- package/dist/journey/inheritance-validator.d.ts +396 -0
- package/dist/journey/inheritance-validator.js +370 -0
- package/dist/journey/metric-snapshot.d.ts +403 -0
- package/dist/journey/metric-snapshot.js +370 -0
- package/dist/journey/state-id-drift-rule.d.ts +137 -0
- package/dist/journey/state-id-drift-rule.js +245 -0
- package/dist/journey-sa2-router.d.ts +395 -0
- package/dist/journey-sa2-router.js +308 -0
- package/dist/otel-exporter.js +0 -3
- package/dist/runners/claude-code.js +3 -3
- package/dist/runners/review-agent.js +6 -2
- package/dist/runners/runner-registry.d.ts +36 -0
- package/dist/runners/runner-registry.js +90 -0
- package/dist/runtime/attestations.d.ts +173 -13
- package/dist/runtime/attestations.js +265 -43
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/sa-scoring/exemplar-bank.js +3 -1
- package/dist/sa-scoring/layer3-llm.js +6 -1
- package/dist/sa-scoring/revision-proposal-config.d.ts +178 -0
- package/dist/sa-scoring/revision-proposal-config.js +198 -0
- package/dist/sa-scoring/revision-proposal.d.ts +285 -0
- package/dist/sa-scoring/revision-proposal.js +417 -0
- package/dist/shared.d.ts +28 -0
- package/dist/shared.js +37 -0
- package/dist/signal-ingestion/adapters/community-thread.d.ts +43 -0
- package/dist/signal-ingestion/adapters/community-thread.js +55 -0
- package/dist/signal-ingestion/adapters/in-app-feedback.d.ts +67 -0
- package/dist/signal-ingestion/adapters/in-app-feedback.js +51 -0
- package/dist/signal-ingestion/adapters/manual.d.ts +78 -0
- package/dist/signal-ingestion/adapters/manual.js +112 -0
- package/dist/signal-ingestion/adapters/support-ticket.d.ts +47 -0
- package/dist/signal-ingestion/adapters/support-ticket.js +51 -0
- package/dist/signal-ingestion/classifier.d.ts +205 -0
- package/dist/signal-ingestion/classifier.js +494 -0
- package/dist/signal-ingestion/clustering-types.d.ts +36 -0
- package/dist/signal-ingestion/clustering-types.js +14 -0
- package/dist/signal-ingestion/clustering.d.ts +200 -0
- package/dist/signal-ingestion/clustering.js +413 -0
- package/dist/signal-ingestion/config.d.ts +351 -0
- package/dist/signal-ingestion/config.js +587 -0
- package/dist/signal-ingestion/d1.d.ts +252 -0
- package/dist/signal-ingestion/d1.js +235 -0
- package/dist/signal-ingestion/errors.d.ts +73 -0
- package/dist/signal-ingestion/errors.js +108 -0
- package/dist/signal-ingestion/governance-events.d.ts +181 -0
- package/dist/signal-ingestion/governance-events.js +189 -0
- package/dist/signal-ingestion/index.d.ts +35 -0
- package/dist/signal-ingestion/index.js +53 -0
- package/dist/signal-ingestion/manual-share-metric.d.ts +93 -0
- package/dist/signal-ingestion/manual-share-metric.js +106 -0
- package/dist/signal-ingestion/registry.d.ts +40 -0
- package/dist/signal-ingestion/registry.js +137 -0
- package/dist/signal-ingestion/residency.d.ts +227 -0
- package/dist/signal-ingestion/residency.js +238 -0
- package/dist/signal-ingestion/significance.d.ts +554 -0
- package/dist/signal-ingestion/significance.js +555 -0
- package/dist/signal-ingestion/types.d.ts +191 -0
- package/dist/signal-ingestion/types.js +8 -0
- package/dist/substrate/drift-composition.d.ts +270 -0
- package/dist/substrate/drift-composition.js +306 -0
- package/dist/substrate/drift-tui-surface.d.ts +61 -0
- package/dist/substrate/drift-tui-surface.js +102 -0
- package/dist/substrate/identity-class.d.ts +176 -0
- package/dist/substrate/identity-class.js +201 -0
- package/dist/tessellation/cross-soul-provenance-rule.d.ts +133 -0
- package/dist/tessellation/cross-soul-provenance-rule.js +171 -0
- package/dist/tessellation/inter-soul-embedding-distance-rule.d.ts +61 -0
- package/dist/tessellation/inter-soul-embedding-distance-rule.js +67 -0
- package/dist/tessellation/rule-registry.d.ts +269 -0
- package/dist/tessellation/rule-registry.js +92 -0
- package/dist/tessellation/soul-slug-ast-scan-rule.d.ts +90 -0
- package/dist/tessellation/soul-slug-ast-scan-rule.js +158 -0
- package/dist/tessellation-admission.d.ts +162 -0
- package/dist/tessellation-admission.js +146 -0
- package/dist/tessellation-drift.d.ts +246 -0
- package/dist/tessellation-drift.js +250 -0
- package/dist/validate-config.js +13 -0
- package/dist/validate-issue.js +2 -2
- package/dist/variant/cardinality-activation.d.ts +126 -0
- package/dist/variant/cardinality-activation.js +101 -0
- package/dist/variant/deprecation-lifecycle.d.ts +184 -0
- package/dist/variant/deprecation-lifecycle.js +208 -0
- package/dist/variant/drift-extension.d.ts +136 -0
- package/dist/variant/drift-extension.js +164 -0
- package/dist/variant/engineering-review.d.ts +185 -0
- package/dist/variant/engineering-review.js +142 -0
- package/dist/variant/index.d.ts +32 -0
- package/dist/variant/index.js +32 -0
- package/dist/variant/inheritance-validator.d.ts +165 -0
- package/dist/variant/inheritance-validator.js +139 -0
- package/dist/variant/internal-adopter/index.d.ts +11 -0
- package/dist/variant/internal-adopter/index.js +10 -0
- package/dist/variant/internal-adopter/products.d.ts +156 -0
- package/dist/variant/internal-adopter/products.js +366 -0
- package/dist/variant-admission.d.ts +316 -0
- package/dist/variant-admission.js +247 -0
- package/dist/webhook-manager.js +7 -1
- package/package.json +15 -12
package/dist/adapters.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* into the dogfood pipeline.
|
|
5
5
|
*/
|
|
6
6
|
import type { AiSdlcConfig } from './config.js';
|
|
7
|
-
import { type IssueTracker, type AdapterRegistry, type ScanOptions, type ScanResult, type WebhookBridge, type GitAdapterFetcher, type GitResolveResult, type AuditLog, type AuditSink, type Sandbox, type SecretStore, type MemoryStore, type EventBus, type CIPipeline } from '@ai-sdlc/reference';
|
|
7
|
+
import { type IssueTracker, type SourceControl, type AdapterRegistry, type ScanOptions, type ScanResult, type WebhookBridge, type GitAdapterFetcher, type GitResolveResult, type AuditLog, type AuditSink, type Sandbox, type SecretStore, type MemoryStore, type EventBus, type CIPipeline } from '@ai-sdlc/reference';
|
|
8
8
|
/**
|
|
9
9
|
* Create an adapter registry pre-loaded with all built-in and community adapters.
|
|
10
10
|
*/
|
|
@@ -70,6 +70,45 @@ export declare function resolveIssueTrackerFromConfig(config: AiSdlcConfig, fall
|
|
|
70
70
|
secretRef: string;
|
|
71
71
|
};
|
|
72
72
|
}): IssueTracker;
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
/**
|
|
74
|
+
* A no-op SourceControl adapter for local-only repositories (no remote).
|
|
75
|
+
*
|
|
76
|
+
* When an adopter has no 'origin' remote (or sets `type: local` in their
|
|
77
|
+
* AdapterBinding), the pipeline must not block on API calls. This adapter:
|
|
78
|
+
*
|
|
79
|
+
* - `createBranch` — delegates to the local git command-line (via execute.ts)
|
|
80
|
+
* so the branch checkout path works unchanged.
|
|
81
|
+
* - `createPR` — resolves immediately with a sentinel local PR object; the
|
|
82
|
+
* caller (execute.ts step 15) should check `pr.url` to detect the skip.
|
|
83
|
+
* - All other methods are no-ops.
|
|
84
|
+
*
|
|
85
|
+
* Callers detect local-only mode by checking `pr.url === 'local'` and skip
|
|
86
|
+
* tracker comments + Slack notifications for the PR URL.
|
|
87
|
+
*/
|
|
88
|
+
export declare function createLocalSourceControl(): SourceControl;
|
|
89
|
+
/**
|
|
90
|
+
* Resolve a SourceControl adapter from the AdapterBinding whose
|
|
91
|
+
* `spec.interface === 'SourceControl'`.
|
|
92
|
+
*
|
|
93
|
+
* Resolution order (first wins):
|
|
94
|
+
* 1. `type: github` → existing GitHub adapter using `spec.config` or fallback.
|
|
95
|
+
* 2. `type: gitlab` → GitLab adapter with `spec.config.url` (required for
|
|
96
|
+
* self-hosted) and optional `spec.config.token.secretRef`.
|
|
97
|
+
* 3. `type: local` → local-only no-op adapter that skips push/create-pr.
|
|
98
|
+
* 4. No SourceControl AdapterBinding present → GitHub (current default, no regression).
|
|
99
|
+
*
|
|
100
|
+
* When multiple SourceControl bindings exist, the FIRST one wins. This is an
|
|
101
|
+
* intentional design choice — multiple SourceControl bindings are unusual and
|
|
102
|
+
* the pipeline has a single active remote. If this constraint is too tight,
|
|
103
|
+
* escalate to the Decision Catalog before changing it.
|
|
104
|
+
*/
|
|
105
|
+
export declare function resolveSourceControlFromConfig(config: AiSdlcConfig, fallbackGitHubConfig: {
|
|
106
|
+
org: string;
|
|
107
|
+
repo: string;
|
|
108
|
+
token: {
|
|
109
|
+
secretRef: string;
|
|
110
|
+
};
|
|
111
|
+
}): SourceControl;
|
|
112
|
+
export { createGitHubCIPipeline, createGitHubSourceControl, createDockerSandbox, createLinearIssueTracker, resolveSecret, createGitLabSourceControl, createGitLabCIPipeline, createJiraIssueTracker, createBacklogMdIssueTracker, createWebhookServer, createGitHubWebhookProvider, verifyGitHubSignature, createGitLabWebhookProvider, verifyGitLabToken, createJiraWebhookProvider, createLinearWebhookProvider, verifyLinearSignature, createAdapterRegistry, validateAdapterMetadata, parseMetadataYaml, scanLocalAdapters, createStubCodeAnalysis, createStubMessenger, createStubDeploymentTarget, createStubGitLabCI, createStubGitLabSource, createStubJira, createStubBitbucket, createStubSonarQube, createStubSemgrep, createInMemoryAuditSink, createFileSink, createEnvSecretStore, createInMemoryMemoryStore, createInProcessEventBus, createStubSandbox, createCompositeIssueTracker, createWebhookBridge, parseGitAdapterRef, buildRawUrl, createGitAdapterFetcher, createStubGitAdapterFetcher, resolveGitAdapter, } from '@ai-sdlc/reference';
|
|
113
|
+
export type { AdapterRegistry, AdapterMetadata, AdapterStability, AdapterFactory, MetadataValidationResult, ScanOptions, ScanResult, WebhookBridge, WebhookTransformer, GitAdapterReference, GitAdapterFetcher, GitResolveResult, CIPipeline, SourceControl, CodeAnalysis, Messenger, DeploymentTarget, EventBus, IssueTracker, LinearClientLike, IssueComment, AdapterInterfaces, EventStream, IssueFilter, CommitStatus, TestResults, CoverageReport, Finding, SeveritySummary, DeploymentStatus, StubCodeAnalysisConfig, StubCodeAnalysisAdapter, NotificationLogEntry, StubMessengerAdapter, StubDeploymentTargetAdapter, StubGitLabCIAdapter, StubGitLabSourceAdapter, StubJiraAdapter, StubBitbucketAdapter, StubSonarQubeConfig, StubSonarQubeAdapter, StubSemgrepConfig, StubSemgrepAdapter, AuditSink, AuditLog, InMemoryAuditSink, SecretStore, Sandbox, MemoryStore, InMemoryMemoryStore, InProcessEventBus, DockerSandboxConfig, BuildStatus, GitLabConfig, JiraConfig, BacklogMdConfig, BacklogFs, WebhookServer, WebhookServerConfig, WebhookProviderConfig, GitHubWebhookConfig, GitHubWebhookBridges, GitLabWebhookConfig, JiraWebhookConfig, LinearWebhookConfig, CompositeIssueTrackerConfig, BackendRoute, } from '@ai-sdlc/reference';
|
|
75
114
|
//# sourceMappingURL=adapters.d.ts.map
|
package/dist/adapters.js
CHANGED
|
@@ -24,8 +24,10 @@ createWebhookBridge,
|
|
|
24
24
|
createStubGitAdapterFetcher, createGitAdapterFetcher, resolveGitAdapter,
|
|
25
25
|
// GitHub CI adapter
|
|
26
26
|
createGitHubCIPipeline,
|
|
27
|
-
// GitHub issue tracker
|
|
28
|
-
createGitHubIssueTracker,
|
|
27
|
+
// GitHub source control + issue tracker
|
|
28
|
+
createGitHubSourceControl, createGitHubIssueTracker,
|
|
29
|
+
// GitLab source control
|
|
30
|
+
createGitLabSourceControl,
|
|
29
31
|
// Composite issue tracker
|
|
30
32
|
createCompositeIssueTracker,
|
|
31
33
|
// Production adapters (for resolveIssueTrackerFromConfig)
|
|
@@ -228,10 +230,138 @@ export function resolveIssueTrackerFromConfig(config, fallbackGitHubConfig) {
|
|
|
228
230
|
}
|
|
229
231
|
return createCompositeIssueTracker({ backends });
|
|
230
232
|
}
|
|
233
|
+
// ── Source-control resolution from config ────────────────────────────
|
|
234
|
+
/**
|
|
235
|
+
* A no-op SourceControl adapter for local-only repositories (no remote).
|
|
236
|
+
*
|
|
237
|
+
* When an adopter has no 'origin' remote (or sets `type: local` in their
|
|
238
|
+
* AdapterBinding), the pipeline must not block on API calls. This adapter:
|
|
239
|
+
*
|
|
240
|
+
* - `createBranch` — delegates to the local git command-line (via execute.ts)
|
|
241
|
+
* so the branch checkout path works unchanged.
|
|
242
|
+
* - `createPR` — resolves immediately with a sentinel local PR object; the
|
|
243
|
+
* caller (execute.ts step 15) should check `pr.url` to detect the skip.
|
|
244
|
+
* - All other methods are no-ops.
|
|
245
|
+
*
|
|
246
|
+
* Callers detect local-only mode by checking `pr.url === 'local'` and skip
|
|
247
|
+
* tracker comments + Slack notifications for the PR URL.
|
|
248
|
+
*/
|
|
249
|
+
export function createLocalSourceControl() {
|
|
250
|
+
return {
|
|
251
|
+
async createBranch(input) {
|
|
252
|
+
// Branches are created via git CLI in execute.ts; this is a passthrough stub.
|
|
253
|
+
return { name: input.name, sha: '' };
|
|
254
|
+
},
|
|
255
|
+
async createPR(_input) {
|
|
256
|
+
// Sentinel URL signals to the pipeline that we are in local-only mode and
|
|
257
|
+
// no remote PR was created. The pipeline checks for this and skips the
|
|
258
|
+
// "PR created" comment + Slack notification (avoiding noise).
|
|
259
|
+
return {
|
|
260
|
+
id: 'local',
|
|
261
|
+
title: _input.title,
|
|
262
|
+
sourceBranch: _input.sourceBranch,
|
|
263
|
+
targetBranch: _input.targetBranch ?? 'main',
|
|
264
|
+
status: 'open',
|
|
265
|
+
author: 'local',
|
|
266
|
+
url: 'local',
|
|
267
|
+
};
|
|
268
|
+
},
|
|
269
|
+
async mergePR(_id, _strategy) {
|
|
270
|
+
return { sha: '', merged: false };
|
|
271
|
+
},
|
|
272
|
+
async getFileContents(_path, _ref) {
|
|
273
|
+
throw new Error('getFileContents: local-only source control has no remote to read from');
|
|
274
|
+
},
|
|
275
|
+
async listChangedFiles(_prId) {
|
|
276
|
+
return [];
|
|
277
|
+
},
|
|
278
|
+
async setCommitStatus(_sha, _status) {
|
|
279
|
+
/* no-op: no remote to post status to */
|
|
280
|
+
},
|
|
281
|
+
watchPREvents(_filter) {
|
|
282
|
+
return {
|
|
283
|
+
async *[Symbol.asyncIterator]() {
|
|
284
|
+
/* no-op: no remote events in local-only mode */
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Resolve a SourceControl adapter from the AdapterBinding whose
|
|
292
|
+
* `spec.interface === 'SourceControl'`.
|
|
293
|
+
*
|
|
294
|
+
* Resolution order (first wins):
|
|
295
|
+
* 1. `type: github` → existing GitHub adapter using `spec.config` or fallback.
|
|
296
|
+
* 2. `type: gitlab` → GitLab adapter with `spec.config.url` (required for
|
|
297
|
+
* self-hosted) and optional `spec.config.token.secretRef`.
|
|
298
|
+
* 3. `type: local` → local-only no-op adapter that skips push/create-pr.
|
|
299
|
+
* 4. No SourceControl AdapterBinding present → GitHub (current default, no regression).
|
|
300
|
+
*
|
|
301
|
+
* When multiple SourceControl bindings exist, the FIRST one wins. This is an
|
|
302
|
+
* intentional design choice — multiple SourceControl bindings are unusual and
|
|
303
|
+
* the pipeline has a single active remote. If this constraint is too tight,
|
|
304
|
+
* escalate to the Decision Catalog before changing it.
|
|
305
|
+
*/
|
|
306
|
+
export function resolveSourceControlFromConfig(config, fallbackGitHubConfig) {
|
|
307
|
+
const bindings = (config.adapterBindings ?? []).filter((b) => b.spec.interface === 'SourceControl');
|
|
308
|
+
if (bindings.length === 0) {
|
|
309
|
+
// No SourceControl binding — default to GitHub exactly as before (AC #2).
|
|
310
|
+
return createGitHubSourceControl(fallbackGitHubConfig);
|
|
311
|
+
}
|
|
312
|
+
// First binding wins (see JSDoc above for rationale).
|
|
313
|
+
const binding = bindings[0];
|
|
314
|
+
const cfg = binding.spec.config ?? {};
|
|
315
|
+
switch (binding.spec.type) {
|
|
316
|
+
case 'github': {
|
|
317
|
+
// Honor spec.config.token.secretRef when present (consistent with the GitLab case).
|
|
318
|
+
// Fall back to the fallback token so existing GitHub adopters are unaffected.
|
|
319
|
+
const tokenSecretRef = cfg.token?.secretRef ??
|
|
320
|
+
fallbackGitHubConfig.token.secretRef;
|
|
321
|
+
return createGitHubSourceControl({
|
|
322
|
+
org: cfg.org ?? fallbackGitHubConfig.org,
|
|
323
|
+
repo: cfg.repo ?? fallbackGitHubConfig.repo,
|
|
324
|
+
token: { secretRef: tokenSecretRef },
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
case 'gitlab': {
|
|
328
|
+
// `url` is required for self-hosted GitLab; defaults to gitlab.com for SaaS.
|
|
329
|
+
const baseUrl = cfg.url ?? 'https://gitlab.com';
|
|
330
|
+
// projectId is required — an empty value produces confusing API responses
|
|
331
|
+
// (encodeURIComponent('') → '' → the request hits /api/v4/projects/ which
|
|
332
|
+
// returns the list of all projects, not the configured one).
|
|
333
|
+
const projectId = cfg.projectId;
|
|
334
|
+
if (!projectId && projectId !== 0) {
|
|
335
|
+
throw new Error(`SourceControl AdapterBinding '${binding.metadata.name}' (type: gitlab) is missing a required ` +
|
|
336
|
+
`spec.config.projectId. Set it to the numeric project ID or the URL-encoded path ` +
|
|
337
|
+
`(e.g. "group%2Fsubgroup%2Fproject" or 12345).`);
|
|
338
|
+
}
|
|
339
|
+
// Token: use secretRef from config if present, else fall back to env GITLAB_TOKEN.
|
|
340
|
+
const tokenSecretRef = cfg.token?.secretRef ?? 'gitlab-token';
|
|
341
|
+
const gitLabCfg = {
|
|
342
|
+
baseUrl,
|
|
343
|
+
projectId,
|
|
344
|
+
token: { secretRef: tokenSecretRef },
|
|
345
|
+
};
|
|
346
|
+
return createGitLabSourceControl(gitLabCfg);
|
|
347
|
+
}
|
|
348
|
+
case 'local': {
|
|
349
|
+
return createLocalSourceControl();
|
|
350
|
+
}
|
|
351
|
+
default: {
|
|
352
|
+
// Unknown type — emit a warning so mistyped types (e.g. 'bitbucket') surface
|
|
353
|
+
// visibly, then fall back to GitHub so the pipeline keeps running.
|
|
354
|
+
console.warn(`[ai-sdlc] SourceControl AdapterBinding '${binding.metadata.name}' has unknown type ` +
|
|
355
|
+
`'${binding.spec.type}'. Falling back to the GitHub adapter. ` +
|
|
356
|
+
`Supported types: github, gitlab, local.`);
|
|
357
|
+
return createGitHubSourceControl(fallbackGitHubConfig);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
231
361
|
// Direct re-exports (passthrough)
|
|
232
362
|
export {
|
|
233
363
|
// Core adapters
|
|
234
|
-
createGitHubCIPipeline, createDockerSandbox, createLinearIssueTracker, resolveSecret,
|
|
364
|
+
createGitHubCIPipeline, createGitHubSourceControl, createDockerSandbox, createLinearIssueTracker, resolveSecret,
|
|
235
365
|
// Production adapters
|
|
236
366
|
createGitLabSourceControl, createGitLabCIPipeline, createJiraIssueTracker,
|
|
237
367
|
// Backlog.md adapter
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Admission-subset composite (RFC-0008 §A.6).
|
|
2
|
+
* Admission-subset composite (RFC-0008 §A.6 + RFC-0009 Phase 2.1).
|
|
3
3
|
*
|
|
4
4
|
* The admission gate uses a subset of the full PPA composite:
|
|
5
5
|
*
|
|
@@ -23,10 +23,18 @@
|
|
|
23
23
|
* The `override` bypass is preserved at position 1: when the input has
|
|
24
24
|
* `override: true`, we return `composite = Infinity` without running
|
|
25
25
|
* the admission math — identical to the legacy PPA behaviour.
|
|
26
|
+
*
|
|
27
|
+
* **RFC-0009 Phase 2.1 tessellation extension:**
|
|
28
|
+
* When `AdmissionCompositeOptions.tessellationContext` is provided, the
|
|
29
|
+
* composite routes SA and Eρ₄ (designSystemReadiness) through soul scope
|
|
30
|
+
* per RFC-0009 §6. See `tessellation-admission.ts` for the routing algorithm.
|
|
26
31
|
*/
|
|
27
32
|
import type { PriorityConfig, PriorityInput, PriorityScore } from '@ai-sdlc/reference';
|
|
28
33
|
import type { AdmissionInput } from './admission-score.js';
|
|
29
34
|
import { type AdmissionHumanCurveResult } from './admission-hc.js';
|
|
35
|
+
import { type TessellationContext, type TessellatedSaResult } from './tessellation-admission.js';
|
|
36
|
+
import { type VariantContext, type VariantScopedSaResult } from './variant-admission.js';
|
|
37
|
+
import { type ComplianceClearanceContext, type ComplianceClearanceResult } from './compliance-clearance.js';
|
|
30
38
|
/**
|
|
31
39
|
* Result of the admission composite — returns a `PriorityScore`
|
|
32
40
|
* (backward-compatible with `scoreIssueForAdmission` consumers) plus
|
|
@@ -44,6 +52,33 @@ export interface AdmissionComposite {
|
|
|
44
52
|
designSystemReadiness: number;
|
|
45
53
|
executionReality: number;
|
|
46
54
|
humanCurve: AdmissionHumanCurveResult;
|
|
55
|
+
/**
|
|
56
|
+
* RFC-0009 Phase 2.1 — tessellation routing result.
|
|
57
|
+
* Present when `AdmissionCompositeOptions.tessellationContext` was
|
|
58
|
+
* supplied. Absent (undefined) when the single-DID path was used.
|
|
59
|
+
*/
|
|
60
|
+
tessellation?: TessellatedSaResult;
|
|
61
|
+
/**
|
|
62
|
+
* RFC-0017 Phase 2 — variant routing result.
|
|
63
|
+
* Present when `AdmissionCompositeOptions.variantContext` was supplied.
|
|
64
|
+
* Absent (undefined) when the single-soul path was used (backward-compat).
|
|
65
|
+
*
|
|
66
|
+
* `variantScopedSa` represents the variant-resolved soul-alignment value
|
|
67
|
+
* that REPLACED the tessellation/soul-aggregate `soulAlignment` when the
|
|
68
|
+
* work item declared `targetedVariants` of one of the affected souls.
|
|
69
|
+
*/
|
|
70
|
+
variant?: VariantScopedSaResult;
|
|
71
|
+
/**
|
|
72
|
+
* RFC-0009 Phase 4.1 — Eρ₅ Compliance Clearance result.
|
|
73
|
+
* Present when `AdmissionCompositeOptions.complianceClearanceContext`
|
|
74
|
+
* was supplied AND the adopter has opted in (`enabled: true`).
|
|
75
|
+
*
|
|
76
|
+
* When `er5 === 0` the composite is GATED to zero — the work item cannot
|
|
77
|
+
* proceed without resolving the violation. The `routingPath` field
|
|
78
|
+
* surfaces the decision branch for audit purposes; when the adopter has
|
|
79
|
+
* not opted in, the breakdown field is elided (backward-compat).
|
|
80
|
+
*/
|
|
81
|
+
complianceClearance?: ComplianceClearanceResult;
|
|
47
82
|
};
|
|
48
83
|
}
|
|
49
84
|
export interface AdmissionCompositeOptions {
|
|
@@ -62,8 +97,84 @@ export interface AdmissionCompositeOptions {
|
|
|
62
97
|
* cannot extract. Only fields with defined values overwrite.
|
|
63
98
|
*/
|
|
64
99
|
priorityInputOverrides?: Partial<PriorityInput>;
|
|
100
|
+
/**
|
|
101
|
+
* RFC-0009 Phase 2.1 — Tessellated DID context.
|
|
102
|
+
*
|
|
103
|
+
* When present, SA and Eρ₄ (designSystemReadiness) are computed using
|
|
104
|
+
* soul-scope routing per RFC-0009 §6 instead of the platform-aggregate
|
|
105
|
+
* DSB. The routing algorithm:
|
|
106
|
+
*
|
|
107
|
+
* resolveAffectedSouls(w) → scope filter from dep-graph snapshot
|
|
108
|
+
* |souls| == 0 → min over ALL souls (substrate-only degenerate)
|
|
109
|
+
* |souls| == 1 → score against that soul's DSB
|
|
110
|
+
* |souls| > 1 → crossSoulScoringRule (default `min`) over affected souls
|
|
111
|
+
*
|
|
112
|
+
* @see tessellation-admission.ts + spec/rfcs/RFC-0009 §6
|
|
113
|
+
*/
|
|
114
|
+
tessellationContext?: TessellationContext;
|
|
115
|
+
/**
|
|
116
|
+
* RFC-0017 Phase 2 — variant-scope routing context.
|
|
117
|
+
*
|
|
118
|
+
* When present AND the work item declares `targetedVariants[]` of one of
|
|
119
|
+
* the affected souls, the composite's `soulAlignment` value is REFINED
|
|
120
|
+
* by per-variant Sα₁ + Sα₂ scoring per RFC-0017 §5.4:
|
|
121
|
+
*
|
|
122
|
+
* resolveTargetedVariants(w) → variant scope filter from work-item targeting
|
|
123
|
+
* |targets| == 0 → backward-compat: soul-aggregate Sα/Eρ₄ unchanged
|
|
124
|
+
* |targets| == 1 → variant's per-variant Sα₁ + Sα₂ replaces soul-aggregate
|
|
125
|
+
* |targets| > 1 → crossVariantAggregation (default `min`) over targeted variants
|
|
126
|
+
*
|
|
127
|
+
* Composes cleanly with `tessellationContext` — soul-scope tessellation runs
|
|
128
|
+
* first, then variant routing refines the resulting Sα/Eρ₄ to variant scope.
|
|
129
|
+
* Work items WITHOUT `targetedVariants` preserve the tessellation result
|
|
130
|
+
* unchanged (backward-compat per RFC-0017 §7).
|
|
131
|
+
*
|
|
132
|
+
* @see variant-admission.ts + spec/rfcs/RFC-0017 §5.4 + §6.2
|
|
133
|
+
*/
|
|
134
|
+
variantContext?: VariantContext;
|
|
135
|
+
/**
|
|
136
|
+
* RFC-0009 Phase 4.1 — Eρ₅ Compliance Clearance context.
|
|
137
|
+
*
|
|
138
|
+
* When present AND `enabled: true`, the admission composite applies the
|
|
139
|
+
* Eρ₅ multiplier (categorical 0/1 gating) per RFC-0009 §7.1:
|
|
140
|
+
*
|
|
141
|
+
* Eρ₅ = 0 if any declared regime is violated → composite gated to 0
|
|
142
|
+
* Eρ₅ = 1 otherwise → composite unchanged
|
|
143
|
+
*
|
|
144
|
+
* When absent OR `enabled: false`, Eρ₅ is not applied — backward-compatible
|
|
145
|
+
* with Phase 2/3 behavior. The opt-in gate is intentional per RFC-0009 §10
|
|
146
|
+
* Phase 4; promotion to default-on is subject to ecosystem feedback.
|
|
147
|
+
*
|
|
148
|
+
* The regime set is the union of (a) each affected soul's
|
|
149
|
+
* `triad.engineering.complianceRegimes` (passed through
|
|
150
|
+
* `perSoulRegimes`) and (b) any RFC-0022 `CompliancePosture` regimes
|
|
151
|
+
* (passed through `posture`). Both pass the OQ-5 hard-regulatory scope
|
|
152
|
+
* filter; soft regimes are filtered at declaration time.
|
|
153
|
+
*
|
|
154
|
+
* Composes with `tessellationContext` — the soul scope from tessellation
|
|
155
|
+
* routing is used to select which souls' regimes apply to this work item.
|
|
156
|
+
*
|
|
157
|
+
* @see compliance-clearance.ts + spec/rfcs/RFC-0009 §7.1 + §10
|
|
158
|
+
* @see spec/rfcs/RFC-0022 (consumption surface)
|
|
159
|
+
*/
|
|
160
|
+
complianceClearanceContext?: ComplianceClearanceContext;
|
|
65
161
|
}
|
|
66
162
|
export declare function computeAdmissionComposite(input: AdmissionInput, config?: PriorityConfig, options?: AdmissionCompositeOptions): AdmissionComposite;
|
|
163
|
+
/**
|
|
164
|
+
* Combine variant-scope Sα₁ (audience resonance) + Sα₂ (vibe coherence) into
|
|
165
|
+
* a single soul-alignment value for the admission composite's SA pillar.
|
|
166
|
+
*
|
|
167
|
+
* The legacy admission composite uses a single `soulAlignment` scalar that
|
|
168
|
+
* conceptually rolls Sα₁ + Sα₂ together (RFC-0008 §A.6 SA pillar). When
|
|
169
|
+
* variant routing splits them out per RFC-0017 §5.4, we recombine via the
|
|
170
|
+
* arithmetic mean — equal weighting matches the soul-aggregate combination
|
|
171
|
+
* implied by `pillar-breakdown.ts` and avoids favouring one Sα facet over
|
|
172
|
+
* the other when both are equally variant-bounded.
|
|
173
|
+
*
|
|
174
|
+
* Exported for unit testing + so downstream callers can replicate the
|
|
175
|
+
* combination logic if they need to surface the constituent pieces.
|
|
176
|
+
*/
|
|
177
|
+
export declare function combineVariantSaForSoulAlignment(sa1: number, sa2: number): number;
|
|
67
178
|
/**
|
|
68
179
|
* Compute admission confidence in [0, 1] as a 50/50 blend of two
|
|
69
180
|
* independent evidence channels:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Admission-subset composite (RFC-0008 §A.6).
|
|
2
|
+
* Admission-subset composite (RFC-0008 §A.6 + RFC-0009 Phase 2.1).
|
|
3
3
|
*
|
|
4
4
|
* The admission gate uses a subset of the full PPA composite:
|
|
5
5
|
*
|
|
@@ -23,10 +23,18 @@
|
|
|
23
23
|
* The `override` bypass is preserved at position 1: when the input has
|
|
24
24
|
* `override: true`, we return `composite = Infinity` without running
|
|
25
25
|
* the admission math — identical to the legacy PPA behaviour.
|
|
26
|
+
*
|
|
27
|
+
* **RFC-0009 Phase 2.1 tessellation extension:**
|
|
28
|
+
* When `AdmissionCompositeOptions.tessellationContext` is provided, the
|
|
29
|
+
* composite routes SA and Eρ₄ (designSystemReadiness) through soul scope
|
|
30
|
+
* per RFC-0009 §6. See `tessellation-admission.ts` for the routing algorithm.
|
|
26
31
|
*/
|
|
27
32
|
import { mapIssueToPriorityInput } from './admission-score.js';
|
|
28
33
|
import { computeAutonomyFactor, computeDefectRiskFactor, computeReadinessFromDesignSystemContext, } from './admission-enrichment.js';
|
|
29
34
|
import { computeAdmissionHumanCurve } from './admission-hc.js';
|
|
35
|
+
import { computeTessellatedScores, } from './tessellation-admission.js';
|
|
36
|
+
import { computeVariantScopedScores, } from './variant-admission.js';
|
|
37
|
+
import { computeComplianceClearance, } from './compliance-clearance.js';
|
|
30
38
|
const DEFAULT_SIGNAL = 0.5;
|
|
31
39
|
export function computeAdmissionComposite(input, config, options) {
|
|
32
40
|
const timestamp = new Date().toISOString();
|
|
@@ -77,7 +85,7 @@ export function computeAdmissionComposite(input, config, options) {
|
|
|
77
85
|
};
|
|
78
86
|
}
|
|
79
87
|
// ── SA (soul alignment) — SA-1 override (M5) or label-based fallback ──
|
|
80
|
-
const
|
|
88
|
+
const baseSoulAlignment = clamp01(options?.soulAlignmentOverride ?? priorityInput.soulAlignment ?? DEFAULT_SIGNAL);
|
|
81
89
|
// ── D-pi_adjusted ─────────────────────────────────────────────
|
|
82
90
|
const demand = priorityInput.demandSignal ?? DEFAULT_SIGNAL;
|
|
83
91
|
const consensus = priorityInput.teamConsensus ?? DEFAULT_SIGNAL;
|
|
@@ -91,12 +99,49 @@ export function computeAdmissionComposite(input, config, options) {
|
|
|
91
99
|
const complexity = priorityInput.complexity ?? 5;
|
|
92
100
|
const baseExecutionReality = clamp01(1 - complexity / 10);
|
|
93
101
|
const autonomyFactor = computeAutonomyFactor(input.autonomyContext);
|
|
94
|
-
const
|
|
102
|
+
const baseDesignSystemReadiness = computeReadinessFromDesignSystemContext(input.designSystemContext);
|
|
103
|
+
// ── RFC-0009 Phase 2.1: tessellation soul-scope routing ────────
|
|
104
|
+
// When tessellationContext is present, route SA and Eρ₄ through soul
|
|
105
|
+
// scope per RFC-0009 §6. When absent, single-DID path applies.
|
|
106
|
+
//
|
|
107
|
+
// Prefer the canonical workItemId (e.g. "AISDLC-313") over the GitHub-style
|
|
108
|
+
// "#313" so the dep-graph snapshot lookup matches the backlog task ID format.
|
|
109
|
+
const workItemId = input.workItemId ?? `#${input.issueNumber}`;
|
|
110
|
+
const tessellationResult = computeTessellatedScores(workItemId, baseSoulAlignment, baseDesignSystemReadiness, options?.tessellationContext);
|
|
111
|
+
// ── RFC-0017 Phase 2: variant-scope refinement ────────────────
|
|
112
|
+
// When `variantContext` is provided AND the work item declares
|
|
113
|
+
// `targetedVariants[]`, the per-variant Sα₁ + Sα₂ scores REFINE the
|
|
114
|
+
// soul-aggregate `soulAlignment` from tessellation. The combined SA score
|
|
115
|
+
// fed to the composite is the mean of the variant-resolved Sα₁ + Sα₂
|
|
116
|
+
// (both feed soul-alignment per RFC-0008 §A.6 SA pillar definition).
|
|
117
|
+
// When no targeting declared OR variantContext is absent, this is a
|
|
118
|
+
// passthrough — the tessellation result is preserved unchanged
|
|
119
|
+
// (backward-compat per RFC-0017 §7).
|
|
120
|
+
const variantResult = computeVariantScopedScores(workItemId, tessellationResult.soulAlignment, tessellationResult.soulAlignment, options?.variantContext);
|
|
121
|
+
const soulAlignment = variantResult.routingPath === 'no-variant-routing'
|
|
122
|
+
? tessellationResult.soulAlignment
|
|
123
|
+
: combineVariantSaForSoulAlignment(variantResult.sa1, variantResult.sa2);
|
|
124
|
+
const designSystemReadiness = tessellationResult.er4;
|
|
95
125
|
const executionReality = Math.min(baseExecutionReality * autonomyFactor, designSystemReadiness);
|
|
126
|
+
// ── RFC-0009 Phase 4.1: Eρ₅ Compliance Clearance ──────────────
|
|
127
|
+
// Categorical 0/1 gating per §7.1. When the adopter has opted in AND any
|
|
128
|
+
// declared regime is violated, the composite is gated to 0 (work item
|
|
129
|
+
// cannot proceed without resolving the violation). When the adopter has
|
|
130
|
+
// not opted in (default), this returns er5=1 and the composite is
|
|
131
|
+
// unchanged — full backward compatibility with Phase 2/3 behavior.
|
|
132
|
+
//
|
|
133
|
+
// Uses the same `affectedSoulIds` resolved by tessellation routing, so the
|
|
134
|
+
// regime check follows the work item's actual soul scope. Substrate-only
|
|
135
|
+
// work (affectedSoulIds = []) falls through to the `__platform` sentinel.
|
|
136
|
+
const complianceClearanceResult = computeComplianceClearance(workItemId, tessellationResult.affectedSoulIds, options?.complianceClearanceContext);
|
|
96
137
|
// ── HC (tanh-compressed with HC_design) ───────────────────────
|
|
97
138
|
const humanCurve = computeAdmissionHumanCurve(input);
|
|
98
139
|
// ── §A.6 admission subset composite ───────────────────────────
|
|
99
|
-
const composite = soulAlignment *
|
|
140
|
+
const composite = soulAlignment *
|
|
141
|
+
demandPressureAdjusted *
|
|
142
|
+
executionReality *
|
|
143
|
+
complianceClearanceResult.er5 *
|
|
144
|
+
(1 + humanCurve.hcComposite);
|
|
100
145
|
const score = {
|
|
101
146
|
composite,
|
|
102
147
|
dimensions: {
|
|
@@ -116,6 +161,20 @@ export function computeAdmissionComposite(input, config, options) {
|
|
|
116
161
|
confidence: computeAdmissionConfidence(input, priorityInput, options),
|
|
117
162
|
timestamp,
|
|
118
163
|
};
|
|
164
|
+
// Only include tessellation breakdown when the caller provided a context
|
|
165
|
+
// (non-tessellated path produces routingPath: 'non-tessellated' but we
|
|
166
|
+
// elide the field to preserve backward compat with callers that don't
|
|
167
|
+
// destructure the breakdown exhaustively).
|
|
168
|
+
const tessellationBreakdown = options?.tessellationContext !== undefined ? tessellationResult : undefined;
|
|
169
|
+
// Variant breakdown surfaced ONLY when the caller wired a variant context
|
|
170
|
+
// AND the work item actually targeted variants. Pure backward-compat for
|
|
171
|
+
// callers on the soul-aggregate path.
|
|
172
|
+
const variantBreakdown = options?.variantContext !== undefined && variantResult.routingPath !== 'no-variant-routing'
|
|
173
|
+
? variantResult
|
|
174
|
+
: undefined;
|
|
175
|
+
// Compliance clearance breakdown surfaced ONLY when the adopter opted in
|
|
176
|
+
// (avoids polluting the breakdown shape for Phase 2/3 callers).
|
|
177
|
+
const complianceClearanceBreakdown = options?.complianceClearanceContext?.enabled === true ? complianceClearanceResult : undefined;
|
|
119
178
|
return {
|
|
120
179
|
score,
|
|
121
180
|
breakdown: {
|
|
@@ -128,9 +187,31 @@ export function computeAdmissionComposite(input, config, options) {
|
|
|
128
187
|
designSystemReadiness,
|
|
129
188
|
executionReality,
|
|
130
189
|
humanCurve,
|
|
190
|
+
...(tessellationBreakdown !== undefined ? { tessellation: tessellationBreakdown } : {}),
|
|
191
|
+
...(variantBreakdown !== undefined ? { variant: variantBreakdown } : {}),
|
|
192
|
+
...(complianceClearanceBreakdown !== undefined
|
|
193
|
+
? { complianceClearance: complianceClearanceBreakdown }
|
|
194
|
+
: {}),
|
|
131
195
|
},
|
|
132
196
|
};
|
|
133
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Combine variant-scope Sα₁ (audience resonance) + Sα₂ (vibe coherence) into
|
|
200
|
+
* a single soul-alignment value for the admission composite's SA pillar.
|
|
201
|
+
*
|
|
202
|
+
* The legacy admission composite uses a single `soulAlignment` scalar that
|
|
203
|
+
* conceptually rolls Sα₁ + Sα₂ together (RFC-0008 §A.6 SA pillar). When
|
|
204
|
+
* variant routing splits them out per RFC-0017 §5.4, we recombine via the
|
|
205
|
+
* arithmetic mean — equal weighting matches the soul-aggregate combination
|
|
206
|
+
* implied by `pillar-breakdown.ts` and avoids favouring one Sα facet over
|
|
207
|
+
* the other when both are equally variant-bounded.
|
|
208
|
+
*
|
|
209
|
+
* Exported for unit testing + so downstream callers can replicate the
|
|
210
|
+
* combination logic if they need to surface the constituent pieces.
|
|
211
|
+
*/
|
|
212
|
+
export function combineVariantSaForSoulAlignment(sa1, sa2) {
|
|
213
|
+
return clamp01((sa1 + sa2) / 2);
|
|
214
|
+
}
|
|
134
215
|
// ── Admission confidence (AISDLC-172) ──────────────────────────────────
|
|
135
216
|
/**
|
|
136
217
|
* `PriorityInput` fields that the admission mapper (`mapIssueToPriorityInput`)
|
|
@@ -92,15 +92,24 @@ export declare function complexityToAutonomyLevel(complexity: number): number;
|
|
|
92
92
|
*/
|
|
93
93
|
export declare function computeAutonomyFactor(ctx: AutonomyContext | undefined): number;
|
|
94
94
|
/**
|
|
95
|
-
* Compute the C5 design-authority weight per §A.5
|
|
95
|
+
* Compute the C5 design-authority weight per §A.5 (Source 1) plus
|
|
96
|
+
* the RFC-0008 §C5 Source 3 compliance-assessment signal.
|
|
96
97
|
*
|
|
98
|
+
* Source 1 (principal participation):
|
|
97
99
|
* non-authority → 0.0
|
|
98
100
|
* authority + positive → +0.6 × modulation
|
|
99
101
|
* authority + negative → -0.4 × modulation
|
|
100
102
|
* authority + no type → +0.3 × modulation
|
|
101
103
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
+
* where `modulation = 1.2 - areaComplianceScore` when the score is
|
|
105
|
+
* supplied, else `1.0` (unmodulated base weight).
|
|
106
|
+
*
|
|
107
|
+
* Source 3 (compliance assessment — additive):
|
|
108
|
+
* `signal.complianceSignal` contributes directly when present (see
|
|
109
|
+
* `buildDesignAuthoritySignal`). This fires from DSB health data
|
|
110
|
+
* alone — no principal participation required — so a fully-loaded DSB
|
|
111
|
+
* with high token compliance produces `hcDesign > 0` regardless of
|
|
112
|
+
* whether a design-authority principal commented on the issue.
|
|
104
113
|
*/
|
|
105
114
|
export declare function computeDesignAuthorityWeight(signal: DesignAuthoritySignal | undefined): number;
|
|
106
115
|
/**
|
|
@@ -204,23 +204,65 @@ const DESIGN_AUTHORITY_BASE_WEIGHT = Object.freeze({
|
|
|
204
204
|
unspecified: 0.3,
|
|
205
205
|
});
|
|
206
206
|
/**
|
|
207
|
-
* Compute the C5 design-authority weight per §A.5
|
|
207
|
+
* Compute the C5 design-authority weight per §A.5 (Source 1) plus
|
|
208
|
+
* the RFC-0008 §C5 Source 3 compliance-assessment signal.
|
|
208
209
|
*
|
|
210
|
+
* Source 1 (principal participation):
|
|
209
211
|
* non-authority → 0.0
|
|
210
212
|
* authority + positive → +0.6 × modulation
|
|
211
213
|
* authority + negative → -0.4 × modulation
|
|
212
214
|
* authority + no type → +0.3 × modulation
|
|
213
215
|
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
+
* where `modulation = 1.2 - areaComplianceScore` when the score is
|
|
217
|
+
* supplied, else `1.0` (unmodulated base weight).
|
|
218
|
+
*
|
|
219
|
+
* Source 3 (compliance assessment — additive):
|
|
220
|
+
* `signal.complianceSignal` contributes directly when present (see
|
|
221
|
+
* `buildDesignAuthoritySignal`). This fires from DSB health data
|
|
222
|
+
* alone — no principal participation required — so a fully-loaded DSB
|
|
223
|
+
* with high token compliance produces `hcDesign > 0` regardless of
|
|
224
|
+
* whether a design-authority principal commented on the issue.
|
|
216
225
|
*/
|
|
217
226
|
export function computeDesignAuthorityWeight(signal) {
|
|
218
|
-
if (!signal
|
|
227
|
+
if (!signal)
|
|
228
|
+
return 0;
|
|
229
|
+
// Source 1: principal-participation weight.
|
|
230
|
+
const participationWeight = signal.isDesignAuthority
|
|
231
|
+
? (() => {
|
|
232
|
+
const signalType = signal.signalType ?? 'unspecified';
|
|
233
|
+
const base = DESIGN_AUTHORITY_BASE_WEIGHT[signalType];
|
|
234
|
+
const modulation = signal.areaComplianceScore !== undefined ? 1.2 - signal.areaComplianceScore : 1;
|
|
235
|
+
return base * modulation;
|
|
236
|
+
})()
|
|
237
|
+
: 0;
|
|
238
|
+
// Source 3: compliance-assessment signal (additive).
|
|
239
|
+
const complianceWeight = signal.complianceSignal ?? 0;
|
|
240
|
+
return participationWeight + complianceWeight;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* RFC-0008 §C5 Source 3 — map DSB token-compliance coverage to a
|
|
244
|
+
* small automatic signal for HC_design.
|
|
245
|
+
*
|
|
246
|
+
* >= 0.8 (80 %) → +0.3 (design system is healthy — small positive)
|
|
247
|
+
* < 0.4 (40 %) → −0.2 (design system is fragile — small negative)
|
|
248
|
+
* otherwise → 0.0 (neutral)
|
|
249
|
+
*
|
|
250
|
+
* The signal is intentionally small so it cannot outweigh Source 1
|
|
251
|
+
* (principal-participation, which carries base weights up to ±0.6).
|
|
252
|
+
* A DSB with missing status data returns 0 (graceful degradation).
|
|
253
|
+
*/
|
|
254
|
+
function computeComplianceSignal(binding) {
|
|
255
|
+
const rawCoverage = binding.status?.tokenCompliance?.currentCoverage;
|
|
256
|
+
if (rawCoverage === undefined || Number.isNaN(rawCoverage))
|
|
219
257
|
return 0;
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
const
|
|
223
|
-
|
|
258
|
+
// Normalise: values > 1 are percent (0-100), values ≤ 1 are already fractions.
|
|
259
|
+
const coverage = rawCoverage > 1 ? rawCoverage / 100 : rawCoverage;
|
|
260
|
+
const clamped = Math.min(1, Math.max(0, coverage));
|
|
261
|
+
if (clamped >= 0.8)
|
|
262
|
+
return 0.3;
|
|
263
|
+
if (clamped < 0.4)
|
|
264
|
+
return -0.2;
|
|
265
|
+
return 0;
|
|
224
266
|
}
|
|
225
267
|
function buildDesignAuthoritySignal(input, ctx) {
|
|
226
268
|
if (!ctx.designSystemBinding)
|
|
@@ -228,23 +270,32 @@ function buildDesignAuthoritySignal(input, ctx) {
|
|
|
228
270
|
// AISDLC-171: surface whether the DSB declares any design authority
|
|
229
271
|
// principals at all. This is a diagnostic flag — it does NOT participate
|
|
230
272
|
// in the HC_design weight calculation (per RFC-0008 §14.2, only
|
|
231
|
-
// principals who participate as author/commenter can emit HC_design
|
|
232
|
-
//
|
|
233
|
-
// authority structure" from "DSB has design authority but no
|
|
234
|
-
// participated in this issue".
|
|
273
|
+
// principals who participate as author/commenter can emit HC_design via
|
|
274
|
+
// Source 1). The flag lets pillarBreakdown distinguish "DSB has no
|
|
275
|
+
// design authority structure" from "DSB has design authority but no
|
|
276
|
+
// principal participated in this issue".
|
|
235
277
|
const principalsDeclared = (ctx.designSystemBinding.spec.stewardship.designAuthority.principals?.length ?? 0) > 0;
|
|
236
278
|
const { isDesignAuthority, signalType } = checkDesignAuthority({
|
|
237
279
|
authorLogin: input.authorLogin,
|
|
238
280
|
commenterLogins: input.commenterLogins,
|
|
239
281
|
labels: input.labels,
|
|
240
282
|
}, ctx.designSystemBinding);
|
|
283
|
+
// RFC-0008 §C5 Source 3: compliance-assessment auto-signal from DSB health.
|
|
284
|
+
// Fires regardless of principal participation — gives a fully-loaded DSB
|
|
285
|
+
// a non-zero hcDesign even when no design-authority principal commented.
|
|
286
|
+
const complianceSignal = computeComplianceSignal(ctx.designSystemBinding);
|
|
241
287
|
if (!isDesignAuthority) {
|
|
242
|
-
return {
|
|
288
|
+
return {
|
|
289
|
+
isDesignAuthority: false,
|
|
290
|
+
principalsDeclared,
|
|
291
|
+
...(complianceSignal !== 0 ? { complianceSignal } : {}),
|
|
292
|
+
};
|
|
243
293
|
}
|
|
244
294
|
return {
|
|
245
295
|
isDesignAuthority: true,
|
|
246
296
|
signalType,
|
|
247
297
|
principalsDeclared,
|
|
298
|
+
...(complianceSignal !== 0 ? { complianceSignal } : {}),
|
|
248
299
|
...(ctx.areaComplianceScore !== undefined
|
|
249
300
|
? { areaComplianceScore: ctx.areaComplianceScore }
|
|
250
301
|
: {}),
|