@ai-sdlc/orchestrator 0.10.0 → 0.13.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/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/init-features.d.ts +301 -2
- package/dist/cli/commands/init-features.js +634 -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/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 +171 -30
- 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/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/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 +252 -40
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +1 -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/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/package.json +10 -8
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EmbeddingAdapter interface per RFC-0019 §5.
|
|
3
|
+
*
|
|
4
|
+
* Every embedding adapter MUST implement this interface. Adapters are registered
|
|
5
|
+
* in orchestrator/src/embedding/registry.ts and resolved by name at pipeline-load.
|
|
6
|
+
*
|
|
7
|
+
* The pattern mirrors HarnessAdapter (RFC-0010 §13) and DatabaseBranchAdapter (RFC-0010 §15).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Result of an adapter liveness probe (isAvailable()).
|
|
11
|
+
*/
|
|
12
|
+
export interface EmbeddingAvailability {
|
|
13
|
+
available: boolean;
|
|
14
|
+
/** Structured reason — helps operators understand what to fix. */
|
|
15
|
+
reason?: 'env-var-missing' | 'health-check-failed' | 'rate-limited' | 'unknown';
|
|
16
|
+
/** Human-readable detail naming the missing env var or failing probe. */
|
|
17
|
+
detail?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Runtime dependency declaration for an embedding adapter.
|
|
21
|
+
* Parallel to HarnessRequires in RFC-0010 §13.8.
|
|
22
|
+
*/
|
|
23
|
+
export interface EmbeddingRequires {
|
|
24
|
+
/** Environment variable required by this adapter (e.g., 'OPENAI_API_KEY'). */
|
|
25
|
+
envVar?: string;
|
|
26
|
+
/** Optional npm package or binary name required (for local/ONNX adapters). */
|
|
27
|
+
binary?: string;
|
|
28
|
+
/** Semver range for the binary, if applicable. */
|
|
29
|
+
versionRange?: string;
|
|
30
|
+
/** Path to model file (e.g., for ONNX-based adapters). */
|
|
31
|
+
modelFile?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Billing model for the adapter — drives cost-tracker routing.
|
|
35
|
+
*
|
|
36
|
+
* - 'pay-per-token': tokens are billed via provider invoice (e.g., OpenAI).
|
|
37
|
+
* embeddingTokens are recorded in cost-tracker but do NOT consume SubscriptionLedger
|
|
38
|
+
* window quota (OQ-7 re-walkthrough).
|
|
39
|
+
* - 'subscription-quota': tokens are billed via the operator's subscription
|
|
40
|
+
* (e.g., future Anthropic embeddings). Routes through SubscriptionLedger via
|
|
41
|
+
* the inputTokens/outputTokens mechanism.
|
|
42
|
+
*/
|
|
43
|
+
export type EmbeddingBillingModel = 'pay-per-token' | 'subscription-quota';
|
|
44
|
+
/**
|
|
45
|
+
* Capability matrix for an embedding adapter (RFC-0019 §6.2).
|
|
46
|
+
* Normative for in-tree adapters; adopter-registered adapters SHOULD declare these.
|
|
47
|
+
*/
|
|
48
|
+
export interface EmbeddingCapabilities {
|
|
49
|
+
/** Output vector length. */
|
|
50
|
+
dimensions: number;
|
|
51
|
+
/** Maximum tokens per single embed() call. */
|
|
52
|
+
maxInputTokens: number;
|
|
53
|
+
/** Whether the adapter implements embedBatch(). */
|
|
54
|
+
supportsBatching: boolean;
|
|
55
|
+
/** Whether the adapter runs locally (no external API call). */
|
|
56
|
+
selfHosted: boolean;
|
|
57
|
+
/** Billing model — drives cost-tracker routing (OQ-7 re-walkthrough). */
|
|
58
|
+
billingModel: EmbeddingBillingModel;
|
|
59
|
+
/** Approximate cost per 1M tokens in USD (for display / cost estimation). Null for local. */
|
|
60
|
+
approxCostPer1MTokens?: number;
|
|
61
|
+
/**
|
|
62
|
+
* Adapter-declared default deprecation grace period in days per RFC-0019
|
|
63
|
+
* §9.1 OQ-4 re-walkthrough. When set, this overrides the framework default
|
|
64
|
+
* (90d) but is itself overridden by per-org `gracePeriodDays`. Fast-moving
|
|
65
|
+
* providers (e.g., Cohere with 6-month deprecation cycles) declare a smaller
|
|
66
|
+
* value here so the warning window scales to the provider's actual lifecycle.
|
|
67
|
+
*
|
|
68
|
+
* The three-layer precedence is:
|
|
69
|
+
* per-org `gracePeriodDays` (highest)
|
|
70
|
+
* adapter `defaultGracePeriodDays` (this field)
|
|
71
|
+
* framework `FRAMEWORK_DEFAULT_GRACE_PERIOD_DAYS` (90, lowest)
|
|
72
|
+
*/
|
|
73
|
+
defaultGracePeriodDays?: number;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The EmbeddingAdapter interface per RFC-0019 §5.
|
|
77
|
+
* Implemented by every embedding adapter registered in the registry.
|
|
78
|
+
*/
|
|
79
|
+
export interface EmbeddingAdapter {
|
|
80
|
+
/**
|
|
81
|
+
* Canonical adapter alias — the value adopters set in Pipeline.spec.embedding.provider.
|
|
82
|
+
* MUST be unique across the registry. Convention: '<vendor>-<model-family>-<size>'.
|
|
83
|
+
* Examples: 'openai-text-embedding-3-small', 'cohere-embed-v3-multilingual'.
|
|
84
|
+
*/
|
|
85
|
+
readonly name: string;
|
|
86
|
+
/**
|
|
87
|
+
* Provider-specific model identifier — passed to the upstream API.
|
|
88
|
+
* Example: 'text-embedding-3-small' (posted to OpenAI's /embeddings endpoint).
|
|
89
|
+
*/
|
|
90
|
+
readonly modelId: string;
|
|
91
|
+
/**
|
|
92
|
+
* Snapshot identifier — ISO date for date-pinned snapshots, semver for versioned models.
|
|
93
|
+
* Used as part of the storage key so vectors don't collide across model snapshots.
|
|
94
|
+
* Example: '2024-01-25' for OpenAI's 2024-01-25 text-embedding-3-small snapshot.
|
|
95
|
+
*/
|
|
96
|
+
readonly modelVersion: string;
|
|
97
|
+
/**
|
|
98
|
+
* Vector length the adapter emits. Validated against storage on first write.
|
|
99
|
+
* Redundant with capabilities.dimensions but declared at the top level for
|
|
100
|
+
* fast dimension-mismatch detection without unpacking capabilities.
|
|
101
|
+
*/
|
|
102
|
+
readonly dimensions: number;
|
|
103
|
+
/** Static capability matrix. */
|
|
104
|
+
readonly capabilities: EmbeddingCapabilities;
|
|
105
|
+
/** Runtime dependency declaration. */
|
|
106
|
+
readonly requires: EmbeddingRequires;
|
|
107
|
+
/**
|
|
108
|
+
* ISO date when the deprecation warning period starts.
|
|
109
|
+
* When set, pipeline-load emits EmbeddingModelDeprecating warning 90d before
|
|
110
|
+
* and EmbeddingModelDeprecated error at/after this date.
|
|
111
|
+
*/
|
|
112
|
+
readonly deprecatedAt?: string;
|
|
113
|
+
/**
|
|
114
|
+
* ISO date when the adapter is removed.
|
|
115
|
+
* When set AND today >= removedAt, pipeline-load FAILS with EmbeddingModelRemoved.
|
|
116
|
+
*/
|
|
117
|
+
readonly removedAt?: string;
|
|
118
|
+
/**
|
|
119
|
+
* Canonical name of the adapter operators should migrate to.
|
|
120
|
+
* Included in deprecation warnings/errors.
|
|
121
|
+
*/
|
|
122
|
+
readonly replacementAlias?: string;
|
|
123
|
+
/**
|
|
124
|
+
* Embed a single text string. Returns the vector as number[].
|
|
125
|
+
*
|
|
126
|
+
* Implementations MUST:
|
|
127
|
+
* - throw on empty input (no silent zero-vector emission)
|
|
128
|
+
* - throw on input exceeding the provider's per-call token limit
|
|
129
|
+
* - return a vector of length === this.dimensions (orchestrator validates post-hoc)
|
|
130
|
+
*
|
|
131
|
+
* @param text - Source text to embed. MUST be non-empty.
|
|
132
|
+
* @param consumerLabel - Optional label for cost attribution per OQ-6 re-walkthrough.
|
|
133
|
+
* Default: 'unspecified'. Examples: 'rfc-0009-tessellation-drift', 'rfc-0008-ppa-similarity'.
|
|
134
|
+
*/
|
|
135
|
+
embed(text: string, consumerLabel?: string): Promise<number[]>;
|
|
136
|
+
/**
|
|
137
|
+
* Optional batch interface. Adapters MAY implement for efficiency; orchestrator
|
|
138
|
+
* calls embed() in a loop when this is undefined.
|
|
139
|
+
* Implementations MUST preserve input order in the returned array.
|
|
140
|
+
*
|
|
141
|
+
* @param texts - Array of source texts to embed. Each MUST be non-empty.
|
|
142
|
+
* @param consumerLabel - Optional label for cost attribution. Applies to all texts in batch.
|
|
143
|
+
*/
|
|
144
|
+
embedBatch?(texts: string[], consumerLabel?: string): Promise<number[][]>;
|
|
145
|
+
/**
|
|
146
|
+
* Cheap liveness probe. Combines env-var presence (e.g., OPENAI_API_KEY)
|
|
147
|
+
* + lightweight provider health check (optional).
|
|
148
|
+
* Result MAY be cached for the orchestrator's lifetime.
|
|
149
|
+
*/
|
|
150
|
+
isAvailable(): Promise<EmbeddingAvailability>;
|
|
151
|
+
/**
|
|
152
|
+
* Stable identifier for the credential / account in scope. Used by cost-tracker
|
|
153
|
+
* to attribute spend per credential. MUST be a one-way derivation (e.g., SHA-256
|
|
154
|
+
* of the API key + adapter name) and MUST NOT leak the credential itself.
|
|
155
|
+
* Returns null when the adapter cannot derive an account identity (e.g., self-hosted).
|
|
156
|
+
*/
|
|
157
|
+
getAccountId(): Promise<string | null>;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Record of a single embedding cost event, passed to the cost-tracker.
|
|
161
|
+
* Captures the (provider, modelVersion, accountId, consumerLabel) dimensions
|
|
162
|
+
* per OQ-6 re-walkthrough.
|
|
163
|
+
*/
|
|
164
|
+
export interface EmbeddingCostRecord {
|
|
165
|
+
/** Adapter name (e.g., 'openai-text-embedding-3-small'). */
|
|
166
|
+
provider: string;
|
|
167
|
+
/** Adapter model version (e.g., '2024-01-25'). */
|
|
168
|
+
modelVersion: string;
|
|
169
|
+
/** One-way hash of the API credential, or null for self-hosted. */
|
|
170
|
+
accountId: string | null;
|
|
171
|
+
/** Consumer attribution label for per-consumer cost breakdown. Default: 'unspecified'. */
|
|
172
|
+
consumerLabel: string;
|
|
173
|
+
/** Total tokens consumed by this embed() call. */
|
|
174
|
+
tokens: number;
|
|
175
|
+
/** USD cost for this call. */
|
|
176
|
+
costUsd: number;
|
|
177
|
+
/** Billing model — used to decide whether to decrement SubscriptionLedger. */
|
|
178
|
+
billingModel: EmbeddingBillingModel;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EmbeddingAdapter interface per RFC-0019 §5.
|
|
3
|
+
*
|
|
4
|
+
* Every embedding adapter MUST implement this interface. Adapters are registered
|
|
5
|
+
* in orchestrator/src/embedding/registry.ts and resolved by name at pipeline-load.
|
|
6
|
+
*
|
|
7
|
+
* The pattern mirrors HarnessAdapter (RFC-0010 §13) and DatabaseBranchAdapter (RFC-0010 §15).
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
package/dist/execute.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* create branch -> invoke agent -> authorize -> validate -> push -> create PR -> comment
|
|
7
7
|
*/
|
|
8
8
|
import { type IssueTracker, type SourceControl, type AuditLog, type MetricStore, type AgentMemory, type ExpressionEvaluator, type LLMEvaluator, type SecretStore } from '@ai-sdlc/reference';
|
|
9
|
+
import { type AiSdlcConfig } from './config.js';
|
|
9
10
|
import { type Logger } from './logger.js';
|
|
10
11
|
import type { AgentRunner } from './runners/types.js';
|
|
11
12
|
import { type SecurityContext } from './security.js';
|
|
@@ -30,8 +31,14 @@ export interface ExecuteOptions {
|
|
|
30
31
|
configDir?: string;
|
|
31
32
|
/** Override the working directory (defaults to `process.cwd()`). */
|
|
32
33
|
workDir?: string;
|
|
33
|
-
/** Inject a custom runner (for testing). */
|
|
34
|
+
/** Inject a custom runner (for testing). Wins over runnerName and registry. */
|
|
34
35
|
runner?: AgentRunner;
|
|
36
|
+
/**
|
|
37
|
+
* Select a runner by name from the registry (maps to `--runner <name>` CLI flag).
|
|
38
|
+
* Must be registered (built-in, env-discovered, or loaded via AI_SDLC_RUNNER_PLUGIN).
|
|
39
|
+
* Throws when the name is unknown — no silent fallback.
|
|
40
|
+
*/
|
|
41
|
+
runnerName?: string;
|
|
35
42
|
/** Inject a custom issue tracker (for testing). */
|
|
36
43
|
tracker?: IssueTracker;
|
|
37
44
|
/** Inject a custom source control adapter (for testing). */
|
|
@@ -85,6 +92,20 @@ export interface ExecuteOptions {
|
|
|
85
92
|
*/
|
|
86
93
|
pipelineOverride?: import('@ai-sdlc/reference').Pipeline;
|
|
87
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Build an actionable error message when a required resource kind is absent.
|
|
97
|
+
*
|
|
98
|
+
* The loader silently drops resource-shaped YAML files that fail schema
|
|
99
|
+
* validation (recording them as `config.warnings`). Without this helper, the
|
|
100
|
+
* caller would only see "No <Kind> resource found in .ai-sdlc/" with no pointer
|
|
101
|
+
* to the real cause. This helper attaches any relevant warnings so the adopter
|
|
102
|
+
* knows *which* file to fix and *why* it was dropped.
|
|
103
|
+
*
|
|
104
|
+
* Non-resource YAMLs (no apiVersion+kind) are silently skipped by design
|
|
105
|
+
* (AISDLC-722 guard); this helper is only called when the resource is truly
|
|
106
|
+
* absent — i.e. no file with the right kind and a passing schema exists.
|
|
107
|
+
*/
|
|
108
|
+
export declare function buildMissingResourceError(kind: string, config: AiSdlcConfig, configDir: string): string;
|
|
88
109
|
/**
|
|
89
110
|
* Execute the full AI-SDLC pipeline for a given issue ID.
|
|
90
111
|
*/
|
|
@@ -116,9 +137,15 @@ export declare function restoreOriginalBranch(workDir: string, originalHead: str
|
|
|
116
137
|
* rebase HEAD onto origin/<branch>, retry once. Rebase conflicts surface as
|
|
117
138
|
* the original error so the operator can resolve manually.
|
|
118
139
|
*
|
|
140
|
+
* Local-only mode (AISDLC-530 / AISDLC-527): when there is no 'origin' remote,
|
|
141
|
+
* push is skipped gracefully (returns true to signal the skip). This mirrors the
|
|
142
|
+
* AISDLC-527 fetch guard at step 7 — we detect the "no such remote" pattern in
|
|
143
|
+
* the push error and swallow it exactly as the fetch step does.
|
|
144
|
+
*
|
|
145
|
+
* @returns `true` when push was skipped (local-only repo), `false` when pushed successfully.
|
|
119
146
|
* @internal — exported for unit tests.
|
|
120
147
|
*/
|
|
121
148
|
export declare function pushBranchWithRebase(workDir: string, branchName: string, log: {
|
|
122
149
|
info: (msg: string) => void;
|
|
123
|
-
} | undefined): Promise<
|
|
150
|
+
} | undefined): Promise<boolean>;
|
|
124
151
|
//# sourceMappingURL=execute.d.ts.map
|
package/dist/execute.js
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
* load config -> fetch issue -> validate -> check autonomy ->
|
|
6
6
|
* create branch -> invoke agent -> authorize -> validate -> push -> create PR -> comment
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { routeByComplexity, evaluatePromotion, evaluateComplexity, selectModel, withSpan, getMeter, SPAN_NAMES, METRIC_NAMES, ATTRIBUTE_KEYS, } from '@ai-sdlc/reference';
|
|
9
9
|
import { loadConfigAsync } from './config.js';
|
|
10
10
|
import { validateIssue, validateIssueWithExtensions, parseComplexity } from './validate-issue.js';
|
|
11
11
|
import { validateAgentOutput } from './validate-agent-output.js';
|
|
12
12
|
import { createLogger } from './logger.js';
|
|
13
13
|
import { createStructuredConsoleLogger, createStructuredBufferLogger, } from './structured-logger.js';
|
|
14
|
-
import {
|
|
14
|
+
import { createRunnerRegistry, resolveRunner } from './runners/runner-registry.js';
|
|
15
15
|
import { execFileAsync, getGitHubConfig, resolveRepoRoot, createDefaultAuditLog, resolveAutonomyLevel, resolveConstraints, isAutonomousStrategy, recordMetric, evaluatePipelineCompliance, authorizeFilesChanged, interpolateBranchPattern, interpolatePRTitle, issueIdToNumber, formatIssueRef, buildIssueTemplateVars, } from './shared.js';
|
|
16
16
|
import { cleanGitEnv } from './runtime/git-env.js';
|
|
17
17
|
import { checkKillSwitch, issueAgentCredentials, revokeAgentCredentials, classifyAndSubmitApproval, createPipelineSecurity, } from './security.js';
|
|
@@ -23,7 +23,7 @@ import { createPipelineExpressionEvaluator, createPipelineLLMEvaluator, createPi
|
|
|
23
23
|
import { verifyAuditIntegrity, createFileAuditLog, loadAuditEntries, computeAuditHash, } from './audit-extended.js';
|
|
24
24
|
import { renderTemplate } from './notifications.js';
|
|
25
25
|
import { admitIssueResource, createPipelineAdmission, } from './admission.js';
|
|
26
|
-
import { createPipelineAdapterRegistry, createPipelineWebhookBridge, resolveAdapterFromGit, scanPipelineAdapters, resolveIssueTrackerFromConfig, } from './adapters.js';
|
|
26
|
+
import { createPipelineAdapterRegistry, createPipelineWebhookBridge, resolveAdapterFromGit, scanPipelineAdapters, resolveIssueTrackerFromConfig, resolveSourceControlFromConfig, } from './adapters.js';
|
|
27
27
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
28
28
|
import { join } from 'node:path';
|
|
29
29
|
import { defaultSandboxConstraints, DEFAULT_CONFIG_DIR_NAME, DEFAULT_PR_FOOTER, DEFAULT_LINT_COMMAND, DEFAULT_FORMAT_COMMAND, DEFAULT_COMMIT_MESSAGE_TEMPLATE, DEFAULT_COMMIT_CO_AUTHOR, NOTIFICATION_TITLES, } from './defaults.js';
|
|
@@ -35,6 +35,33 @@ import { CostTracker } from './cost-tracker.js';
|
|
|
35
35
|
import { enrichAgentContext } from './context-enrichment.js';
|
|
36
36
|
import { reportGateCheckRuns } from './check-runs.js';
|
|
37
37
|
import { WorktreePoolManager, readParallelismMode } from './runtime/index.js';
|
|
38
|
+
/**
|
|
39
|
+
* Build an actionable error message when a required resource kind is absent.
|
|
40
|
+
*
|
|
41
|
+
* The loader silently drops resource-shaped YAML files that fail schema
|
|
42
|
+
* validation (recording them as `config.warnings`). Without this helper, the
|
|
43
|
+
* caller would only see "No <Kind> resource found in .ai-sdlc/" with no pointer
|
|
44
|
+
* to the real cause. This helper attaches any relevant warnings so the adopter
|
|
45
|
+
* knows *which* file to fix and *why* it was dropped.
|
|
46
|
+
*
|
|
47
|
+
* Non-resource YAMLs (no apiVersion+kind) are silently skipped by design
|
|
48
|
+
* (AISDLC-722 guard); this helper is only called when the resource is truly
|
|
49
|
+
* absent — i.e. no file with the right kind and a passing schema exists.
|
|
50
|
+
*/
|
|
51
|
+
export function buildMissingResourceError(kind, config, configDir) {
|
|
52
|
+
const base = `No ${kind} resource found in ${configDir}`;
|
|
53
|
+
// Find any warnings that mention this kind — these are resource-shaped files
|
|
54
|
+
// that had `apiVersion`+`kind` but failed schema validation and were dropped.
|
|
55
|
+
const relevant = (config.warnings ?? []).filter((w) => w.error.includes('validation failed') || w.error.includes('unknown kind'));
|
|
56
|
+
if (relevant.length === 0) {
|
|
57
|
+
return `${base}. Add a ${kind} YAML file to your .ai-sdlc/ directory. Run \`ai-sdlc init\` to scaffold a minimal working configuration.`;
|
|
58
|
+
}
|
|
59
|
+
const details = relevant.map((w) => ` - ${w.file}: ${w.error}`).join('\n');
|
|
60
|
+
return (`${base}.\n` +
|
|
61
|
+
`The following file(s) declared a resource but failed schema validation and were dropped:\n` +
|
|
62
|
+
`${details}\n` +
|
|
63
|
+
`Fix the validation error(s) above, or run \`ai-sdlc init\` to scaffold a minimal working configuration.`);
|
|
64
|
+
}
|
|
38
65
|
/**
|
|
39
66
|
* Execute the full AI-SDLC pipeline for a given issue ID.
|
|
40
67
|
*/
|
|
@@ -89,13 +116,13 @@ export async function executePipeline(issueId, options = {}) {
|
|
|
89
116
|
});
|
|
90
117
|
}
|
|
91
118
|
if (!config.qualityGate) {
|
|
92
|
-
throw new Error('
|
|
119
|
+
throw new Error(buildMissingResourceError('QualityGate', config, configDir));
|
|
93
120
|
}
|
|
94
121
|
if (!config.agentRole) {
|
|
95
|
-
throw new Error('
|
|
122
|
+
throw new Error(buildMissingResourceError('AgentRole', config, configDir));
|
|
96
123
|
}
|
|
97
124
|
if (!config.autonomyPolicy) {
|
|
98
|
-
throw new Error('
|
|
125
|
+
throw new Error(buildMissingResourceError('AutonomyPolicy', config, configDir));
|
|
99
126
|
}
|
|
100
127
|
// Capture narrowed types for use in closures
|
|
101
128
|
const qualityGate = config.qualityGate;
|
|
@@ -114,7 +141,11 @@ export async function executePipeline(issueId, options = {}) {
|
|
|
114
141
|
const { org, repo } = getGitHubConfig(options.secretStore);
|
|
115
142
|
const ghConfig = { org, repo, token: { secretRef: 'github-token' } };
|
|
116
143
|
const tracker = options.tracker ?? resolveIssueTrackerFromConfig(config, ghConfig);
|
|
117
|
-
|
|
144
|
+
// Resolve the source-control adapter from AdapterBinding config.
|
|
145
|
+
// options.sourceControl injection still wins (programmatic/testing use).
|
|
146
|
+
// When no SourceControl AdapterBinding is present, defaults to GitHub exactly
|
|
147
|
+
// as before — no regression for existing GitHub adopters (AC #2, AISDLC-530).
|
|
148
|
+
const sc = options.sourceControl ?? resolveSourceControlFromConfig(config, ghConfig);
|
|
118
149
|
// 3. Fetch issue
|
|
119
150
|
log.stage('validate-issue');
|
|
120
151
|
const issue = await tracker.getIssue(issueId);
|
|
@@ -233,6 +264,12 @@ export async function restoreOriginalBranch(workDir, originalHead, log) {
|
|
|
233
264
|
* rebase HEAD onto origin/<branch>, retry once. Rebase conflicts surface as
|
|
234
265
|
* the original error so the operator can resolve manually.
|
|
235
266
|
*
|
|
267
|
+
* Local-only mode (AISDLC-530 / AISDLC-527): when there is no 'origin' remote,
|
|
268
|
+
* push is skipped gracefully (returns true to signal the skip). This mirrors the
|
|
269
|
+
* AISDLC-527 fetch guard at step 7 — we detect the "no such remote" pattern in
|
|
270
|
+
* the push error and swallow it exactly as the fetch step does.
|
|
271
|
+
*
|
|
272
|
+
* @returns `true` when push was skipped (local-only repo), `false` when pushed successfully.
|
|
236
273
|
* @internal — exported for unit tests.
|
|
237
274
|
*/
|
|
238
275
|
export async function pushBranchWithRebase(workDir, branchName, log) {
|
|
@@ -241,10 +278,16 @@ export async function pushBranchWithRebase(workDir, branchName, log) {
|
|
|
241
278
|
const env = cleanGitEnv();
|
|
242
279
|
try {
|
|
243
280
|
await execFileAsync('git', ['push', 'origin', branchName], { cwd: workDir, env });
|
|
244
|
-
return;
|
|
281
|
+
return false;
|
|
245
282
|
}
|
|
246
283
|
catch (err) {
|
|
247
284
|
const stderr = err.stderr ?? err.message;
|
|
285
|
+
// Local-only repos: no 'origin' remote configured — skip push gracefully.
|
|
286
|
+
// Mirror the AISDLC-527 fetch guard pattern exactly.
|
|
287
|
+
if (/no such remote|does not appear to be a git repository/i.test(stderr)) {
|
|
288
|
+
log?.info(`[pipeline] git push skipped: no 'origin' remote configured (local-only repo)`);
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
248
291
|
if (!/non-fast-forward|rejected/i.test(stderr)) {
|
|
249
292
|
throw err;
|
|
250
293
|
}
|
|
@@ -267,6 +310,7 @@ export async function pushBranchWithRebase(workDir, branchName, log) {
|
|
|
267
310
|
`Resolve conflicts manually and re-run the pipeline.`);
|
|
268
311
|
}
|
|
269
312
|
await execFileAsync('git', ['push', 'origin', branchName], { cwd: workDir, env });
|
|
313
|
+
return false;
|
|
270
314
|
}
|
|
271
315
|
async function executePipelineBody(issueId, issue, config, qualityGate, agentRole, autonomyPolicy, tracker, sc, auditLog, metricStore, options, log, workDir) {
|
|
272
316
|
const issueNumber = issueIdToNumber(issueId);
|
|
@@ -411,11 +455,53 @@ async function executePipelineBody(issueId, issue, config, qualityGate, agentRol
|
|
|
411
455
|
const branchName = interpolateBranchPattern(config.pipeline?.spec.branching?.pattern, branchVars);
|
|
412
456
|
await sc.createBranch({ name: branchName });
|
|
413
457
|
// cleanGitEnv() prevents leaked GIT_DIR from corrupting these calls (AISDLC-72).
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
458
|
+
// Guard: skip fetch when no 'origin' remote is configured (local-only repos).
|
|
459
|
+
// The push step already degrades gracefully for local repos; fetch must too.
|
|
460
|
+
//
|
|
461
|
+
// AISDLC-530 review fix: track whether we are in local-only mode so the checkout
|
|
462
|
+
// step can use `git checkout -b` (create) instead of `git checkout` (switch to
|
|
463
|
+
// existing). Remote paths create the branch via the SC adapter API THEN fetch it
|
|
464
|
+
// locally — so the branch already exists locally after the fetch, and plain
|
|
465
|
+
// `git checkout <name>` is correct. Local-only paths never have a remote, the
|
|
466
|
+
// SC adapter's createBranch is a no-op, so the branch does NOT exist yet and we
|
|
467
|
+
// MUST use `-b` to create it in one step.
|
|
468
|
+
let localOnlyMode = false;
|
|
469
|
+
try {
|
|
470
|
+
await execFileAsync('git', ['fetch', 'origin', branchName], {
|
|
471
|
+
cwd: workDir,
|
|
472
|
+
env: cleanGitEnv(),
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
catch (fetchErr) {
|
|
476
|
+
const fetchMsg = fetchErr.stderr ??
|
|
477
|
+
fetchErr.message ??
|
|
478
|
+
'';
|
|
479
|
+
// Only swallow the "origin remote is not configured at all" shape (local-only
|
|
480
|
+
// repos). Do NOT match a bare "not found" — that also matches "repository not
|
|
481
|
+
// found" (origin IS configured but the URL is wrong/deleted/inaccessible), which
|
|
482
|
+
// must propagate as a real config error rather than be silently skipped
|
|
483
|
+
// (AISDLC-527 code-review finding).
|
|
484
|
+
if (/no such remote|does not appear to be a git repository/i.test(fetchMsg)) {
|
|
485
|
+
log.info(`[pipeline] git fetch skipped: no 'origin' remote configured (local-only repo)`);
|
|
486
|
+
localOnlyMode = true;
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
throw fetchErr;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
// Local-only: branch was never pushed to a remote, so we must CREATE it with
|
|
493
|
+
// `git checkout -b <name>`. Remote paths: branch was fetched from origin, so
|
|
494
|
+
// it exists locally as FETCH_HEAD / refs/remotes/origin/<name> — plain
|
|
495
|
+
// `git checkout <name>` switches to the already-created tracking branch.
|
|
496
|
+
if (localOnlyMode) {
|
|
497
|
+
await execFileAsync('git', ['checkout', '-b', branchName], {
|
|
498
|
+
cwd: workDir,
|
|
499
|
+
env: cleanGitEnv(),
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
await execFileAsync('git', ['checkout', branchName], { cwd: workDir, env: cleanGitEnv() });
|
|
504
|
+
}
|
|
419
505
|
// 8. Resolve agent constraints
|
|
420
506
|
const resolved = resolveConstraints(agentRole.spec.constraints, currentLevel);
|
|
421
507
|
// 8b. Model selection: choose model based on complexity and budget pressure
|
|
@@ -444,7 +530,18 @@ async function executePipelineBody(issueId, issue, config, qualityGate, agentRol
|
|
|
444
530
|
`| Complexity | ${complexity} |\n` +
|
|
445
531
|
`| Strategy | ${strategy} |\n`);
|
|
446
532
|
await notifySlack(`:hammer_and_wrench: Agent working on \`${branchName}\` (model: ${selectedModel ?? 'default'}, complexity: ${complexity})`);
|
|
447
|
-
|
|
533
|
+
// Resolve runner via registry (after discoverFromEnv):
|
|
534
|
+
// 1. options.runner injection (tests / programmatic override) — wins
|
|
535
|
+
// 2. options.runnerName (--runner flag) — must be registered; throws on unknown
|
|
536
|
+
// 3. AI_SDLC_RUNNER_PLUGIN env — dynamically loaded plugin
|
|
537
|
+
// 4. ClaudeCodeRunner built-in default
|
|
538
|
+
// NOTE: env-discovered runners (openai, copilot, etc.) are registered + selectable by
|
|
539
|
+
// name via --runner, but do NOT auto-win on env-var presence (AISDLC-529 code review).
|
|
540
|
+
const runnerRegistry = createRunnerRegistry();
|
|
541
|
+
const runner = await resolveRunner(runnerRegistry, {
|
|
542
|
+
injectedRunner: options.runner,
|
|
543
|
+
runnerName: options.runnerName,
|
|
544
|
+
});
|
|
448
545
|
// Set up progress tracking — collects streaming events for the activity log
|
|
449
546
|
const progressLog = [];
|
|
450
547
|
const onProgress = (event) => {
|
|
@@ -535,7 +632,13 @@ async function executePipelineBody(issueId, issue, config, qualityGate, agentRol
|
|
|
535
632
|
await tracker.addComment(issueId, `## ${agentFailComment.title}\n\n${agentFailComment.body}`);
|
|
536
633
|
throw new Error(`Agent failed on issue ${formatIssueRef(issueId)}: ${err}`);
|
|
537
634
|
}
|
|
538
|
-
|
|
635
|
+
// Guard: ensure filesChanged is always an array even when a runner returns
|
|
636
|
+
// a partial AgentResult. Downstream consumers (.length, .map, etc.) crash
|
|
637
|
+
// on undefined — defaulting here keeps all reads safe (AISDLC-527).
|
|
638
|
+
result = {
|
|
639
|
+
...stepOutput,
|
|
640
|
+
filesChanged: stepOutput.filesChanged ?? [],
|
|
641
|
+
};
|
|
539
642
|
log.stageEnd('agent');
|
|
540
643
|
auditLog.record({
|
|
541
644
|
actor: 'system',
|
|
@@ -561,9 +664,29 @@ async function executePipelineBody(issueId, issue, config, qualityGate, agentRol
|
|
|
561
664
|
}
|
|
562
665
|
}
|
|
563
666
|
// 10. ABAC authorization check (if write permissions are defined)
|
|
564
|
-
|
|
667
|
+
// Guard: default to [] when permissions.write is undefined (minimal/default autonomy configs
|
|
668
|
+
// may omit the write list, causing .length to throw on undefined — AISDLC-527).
|
|
669
|
+
//
|
|
670
|
+
// NOTE on the empty/undefined case (AISDLC-527 security-review finding): per the
|
|
671
|
+
// framework's existing autonomy-policy semantics, an empty write allowlist means
|
|
672
|
+
// "no per-file write restriction at this level" (the default autonomy level ships
|
|
673
|
+
// `write: []`), so this block intentionally SKIPS per-file authorization when the
|
|
674
|
+
// list is empty. The `?? []` makes a *missing* list behave the same as an explicit
|
|
675
|
+
// empty one rather than crashing. Because skipping authorization is a permissive
|
|
676
|
+
// (fail-open) path, we log it so it is auditable rather than silent. Tightening the
|
|
677
|
+
// empty-allowlist semantics to fail-closed is a framework-wide policy change (it would
|
|
678
|
+
// change the meaning of the default `write: []` level) and is tracked separately, NOT
|
|
679
|
+
// resolved in this crash-guard task. Downstream `validateAgentOutput` blocked-paths +
|
|
680
|
+
// branch protection + human merge remain as defense-in-depth.
|
|
681
|
+
const writePermissions = currentLevel.permissions.write ?? [];
|
|
682
|
+
if (writePermissions.length > 0) {
|
|
565
683
|
authorizeFilesChanged(result.filesChanged, currentLevel.permissions, agentRole.spec.constraints, auditLog, agentRole.metadata.name);
|
|
566
684
|
}
|
|
685
|
+
else {
|
|
686
|
+
log.info(`[pipeline] ABAC per-file write authorization skipped: autonomy level '${currentLevel.name ?? 'unknown'}' ` +
|
|
687
|
+
`has an empty/undefined permissions.write allowlist (framework default semantics). ` +
|
|
688
|
+
`Downstream blocked-paths validation + branch protection still apply.`);
|
|
689
|
+
}
|
|
567
690
|
// 11. Post activity log so users can see what the agent did
|
|
568
691
|
const activitySection = progressLog.length > 0
|
|
569
692
|
? `### Activity Log\n\n\`\`\`\n${progressLog.slice(-40).join('\n')}\n\`\`\``
|
|
@@ -577,15 +700,20 @@ async function executePipelineBody(issueId, issue, config, qualityGate, agentRol
|
|
|
577
700
|
// cleanly. Without this, re-runs against an existing remote branch (e.g. when
|
|
578
701
|
// the issue branch was updated by another pipeline run or by a hand-edit)
|
|
579
702
|
// reject with non-fast-forward and the agent's work is stranded locally.
|
|
703
|
+
//
|
|
704
|
+
// Local-only mode (AISDLC-530): when there's no 'origin' remote, the push
|
|
705
|
+
// is skipped just like the fetch step at step 7. We detect this by attempting
|
|
706
|
+
// the push and checking for the "no such remote" pattern — same approach
|
|
707
|
+
// AISDLC-527 uses for the fetch guard above (build on, not duplicate).
|
|
580
708
|
log.stage('push');
|
|
581
|
-
await pushBranchWithRebase(workDir, branchName, log);
|
|
709
|
+
const pushSkipped = await pushBranchWithRebase(workDir, branchName, log);
|
|
582
710
|
log.stageEnd('push');
|
|
583
711
|
auditLog.record({
|
|
584
712
|
actor: 'system',
|
|
585
713
|
action: 'push',
|
|
586
714
|
resource: `branch/${branchName}`,
|
|
587
715
|
decision: 'allowed',
|
|
588
|
-
details: { filesChanged: result.filesChanged.length, issueId },
|
|
716
|
+
details: { filesChanged: result.filesChanged.length, issueId, localOnly: pushSkipped },
|
|
589
717
|
});
|
|
590
718
|
// 13. Validate agent output against guardrails (after push)
|
|
591
719
|
const validation = await withSpan(SPAN_NAMES.PIPELINE_STAGE, {
|
|
@@ -774,26 +902,39 @@ async function executePipelineBody(issueId, issue, config, qualityGate, agentRol
|
|
|
774
902
|
targetBranch,
|
|
775
903
|
});
|
|
776
904
|
log.stageEnd('create-pr');
|
|
905
|
+
// Local-only mode (AISDLC-530): when the source-control adapter is local,
|
|
906
|
+
// createPR returns a sentinel pr.url === 'local' — record as skipped.
|
|
907
|
+
const isLocalPr = prResult.url === 'local';
|
|
908
|
+
if (isLocalPr) {
|
|
909
|
+
log.info(`[pipeline] create-pr skipped: local-only mode (no remote). ` +
|
|
910
|
+
`Branch '${branchName}' is available locally.`);
|
|
911
|
+
}
|
|
777
912
|
auditLog.record({
|
|
778
913
|
actor: 'system',
|
|
779
914
|
action: 'create',
|
|
780
915
|
resource: 'pull-request',
|
|
781
916
|
decision: 'allowed',
|
|
782
|
-
details: { prUrl: prResult.url, issueId },
|
|
917
|
+
details: { prUrl: prResult.url, issueId, localOnly: isLocalPr },
|
|
783
918
|
});
|
|
784
919
|
return prResult;
|
|
785
920
|
});
|
|
786
|
-
// 14. Comment on issue with success (use notification template when available)
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
921
|
+
// 14. Comment on issue with success (use notification template when available).
|
|
922
|
+
// Local-only mode (AISDLC-530): skip tracker comment + Slack notification when
|
|
923
|
+
// there is no remote PR URL — posting "PR created: local" to the tracker would
|
|
924
|
+
// be misleading and is not actionable.
|
|
925
|
+
const isLocalOnlyPr = pr.url === 'local';
|
|
926
|
+
if (!isLocalOnlyPr) {
|
|
927
|
+
const notifTemplates = config.pipeline?.spec.notifications?.templates;
|
|
928
|
+
const prCreatedTemplate = notifTemplates?.['pr-created'];
|
|
929
|
+
const prCreatedComment = prCreatedTemplate
|
|
930
|
+
? renderTemplate(prCreatedTemplate, {
|
|
931
|
+
prUrl: pr.url,
|
|
932
|
+
issueNumber: issueId,
|
|
933
|
+
})
|
|
934
|
+
: { title: NOTIFICATION_TITLES.prCreated, body: `Pull request created: ${pr.url}` };
|
|
935
|
+
await tracker.addComment(issueId, `## ${prCreatedComment.title}\n\n${prCreatedComment.body}`);
|
|
936
|
+
await notifySlack(`:pull_request: PR created: ${pr.url}`);
|
|
937
|
+
}
|
|
797
938
|
// 14b. Record cost from agent result
|
|
798
939
|
if (options.costTracker && result.tokenUsage) {
|
|
799
940
|
const tu = result.tokenUsage;
|
package/dist/index.d.ts
CHANGED
|
@@ -22,8 +22,12 @@ export { computePriority, rankWorkItems, type PriorityScore, type PriorityInput,
|
|
|
22
22
|
export { checkAction, enforceAction, DEFAULT_BLOCKED_ACTIONS, type ActionEnforcementResult, } from './action-enforcement.js';
|
|
23
23
|
export { scoreIssueForAdmission, mapIssueToPriorityInput, type AdmissionInput, type AdmissionThresholds, type IssueAdmissionResult, type AuthorAssociation, type DesignSystemContext, type AutonomyContext, type CodeAreaQuality, type DesignAuthoritySignal, type DesignAuthoritySignalType, type DesignQualityMetrics, } from './admission-score.js';
|
|
24
24
|
export { enrichAdmissionInput, computeDesignSystemReadiness, computeReadinessFromDesignSystemContext, computeDefectRiskFactor, computeAutonomyFactor, computeDesignAuthorityWeight, complexityToAutonomyLevel, type EnrichmentContext, type LifecyclePhase, } from './admission-enrichment.js';
|
|
25
|
-
export { computeAdmissionComposite, type AdmissionComposite } from './admission-composite.js';
|
|
26
|
-
export {
|
|
25
|
+
export { computeAdmissionComposite, type AdmissionComposite, type AdmissionCompositeOptions, } from './admission-composite.js';
|
|
26
|
+
export { resolveAffectedSouls, applyCrossSoulRule, computeTessellatedScores, type DepGraphSoulEntry, type SoulScores, type TessellationContext, type TessellatedSaResult, } from './tessellation-admission.js';
|
|
27
|
+
export { detectTessellationDrift, DEFAULT_DIVERGENCE_THRESHOLD, type TessellationDriftRule, type TessellationDriftDetectedEvent, type AstScanDetails, type AstScanFinding, type CrossSoulProvenanceDetails, type CrossSoulProvenanceFinding, type SubstrateFile, type ProvenanceAuditEntry, type TessellationDriftConfig, type TessellationDriftInput, type TessellationDriftResult, } from './tessellation-drift.js';
|
|
28
|
+
export { parseTargetedVariantRef, resolveTargetedVariants, applyCrossVariantRule, computeVariantScopedScores, defaultCrossSoulVariantRule, type VariantOverlay, type VariantDesignOverridesFramework, type VariantDesignOverridesExt, type VariantScores, type VariantConfig, type VariantAggregationRule, type WorkItemVariantTargeting, type VariantContext, type ParsedVariantRef, type VariantScopedSaResult, } from './variant-admission.js';
|
|
29
|
+
export { combineVariantSaForSoulAlignment } from './admission-composite.js';
|
|
30
|
+
export { parseBacklogTask, loadBacklogTaskFromRoot, mapBacklogTaskToAdmissionInput, loadSoulTracks, loadMaintainers, extractCodeAreaFromReferences, parseBodyReferences, type BacklogTaskSnapshot, type BacklogAcceptanceCriterion, type BacklogMappingOptions, type BacklogAdmissionMapping, } from './backlog-adapter.js';
|
|
27
31
|
export { computePillarBreakdown, detectTensions, pillarSignalScore, type PillarBreakdown, type PillarContribution, type PillarName, type SharedDimensions, type TensionFlag, type TensionFlagType, type HcChannelBreakdown, } from './pillar-breakdown.js';
|
|
28
32
|
export { compileDid, validatePhase2bReadiness, hashDidSpec, canonicalJson, tokenize, serializeForStore, deserializeFromStore, type CompiledDid, type CompiledScopeLists, type CompiledScopeEntry, type CompiledConstraintRule, type CompiledAntiPattern, type CompiledAntiPatternLists, type CompiledMeasurableSignal, type Bm25Corpus, type Bm25Document, type PrincipleCorpora, type ReadinessResult, } from './sa-scoring/did-compiler.js';
|
|
29
33
|
export { HttpDepparseClient, FakeDepparseClient, DepparseError, type DepparseClient, type DepparseMatch, type DepparseMatchRequest, type DepparseMatchResponse, type DepparseHealth, type DepparseErrorKind, } from './sa-scoring/depparse-client.js';
|
|
@@ -36,6 +40,7 @@ export { SAFeedbackStore, SA_FEEDBACK_LABELS, classifyLabel, recordOverrideFeedb
|
|
|
36
40
|
export { computeCalibrationCoefficient, buildCategoryCoefficients, type CategoryFeedback, type BuildCategoryCoefficientsInput, } from './calibration.js';
|
|
37
41
|
export { autoCalibratePhaseWeights, computePhase3Weights, decideCalibrationDirection, renderCalibrationDiff, WEIGHT_FLOOR, WEIGHT_CEILING, DEFAULT_SHIFT_SIZE, DEFAULT_WINDOW_DAYS, PRECISION_DELTA_THRESHOLD, type PrecisionPair, type CalibrationDecision, type ComputePhase3WeightsInput, type AutoCalibrateDeps, type AutoCalibrateResult, type DimensionDiff, } from './sa-scoring/auto-calibrate.js';
|
|
38
42
|
export { detectSoulDrift, computeWindowStats, computeTrend, describeDriftSource, DEFAULT_MEAN_THRESHOLD, DEFAULT_STDDEV_THRESHOLD, DEFAULT_CONSECUTIVE_WINDOWS, DEFAULT_RECOVERY_MS, type SoulDriftDetectedEvent, type DriftTrend, type WindowStats, type DriftDetectorDeps, } from './sa-scoring/drift-monitor.js';
|
|
43
|
+
export { classifyDrift, deriveApprovalPath, computeConfidence, evaluateRevisionProposal, triggerConditionMet, isFieldLocked, isProposalExpired, archiveExpiredProposals, recordRejection, computeRejectionPrecedentFactor, DEFAULT_DISMISS_THRESHOLD, DEFAULT_DEMAND_MISALIGNMENT_THRESHOLD, DEFAULT_DRIFT_EVENTS_THRESHOLD, DEFAULT_TRIGGER_WINDOW_DAYS, DEFAULT_PROPOSAL_EXPIRY_DAYS, HEALTHY_ICP_MATCH_MIN, UNHEALTHY_ICP_MATCH_MAX, type DriftClassification, type IdentityClass, type ApprovalPath, type ProposalStatus, type ProposalConfidence, type ClassificationEvidence, type TriggerEvidence, type TriggerConditions, type TriggerConfig, type CalibrationLockConfig, type DIDRevisionProposalEvent, type SoulHealthDiagnosticEvent, type DIDRevisionProposalExpiredEvent, type ProposalRejectionRecord, type EvaluateRevisionProposalInput, type EvaluateRevisionProposalResult, } from './sa-scoring/revision-proposal.js';
|
|
39
44
|
export { handleCoreIdentityChanged, type CoreIdentityChangedEvent, type BacklogReshuffledEvent, type SoulGraphStaleFlag, type RescoreDeps, type HandleResult, } from './sa-scoring/rescore-orchestrator.js';
|
|
40
45
|
export { scoreSoulAlignment, resolveSoulAlignmentOverride, type ScoreSoulAlignmentInput, type ScoreSoulAlignmentDeps, type SoulAlignmentScoringResult, } from './sa-scoring/index.js';
|
|
41
46
|
export type { SaDimension, FeedbackSignal } from './state/types.js';
|
|
@@ -47,6 +52,10 @@ export { createPipelineAdapterRegistry, createPipelineWebhookBridge, resolveAdap
|
|
|
47
52
|
export { createPipelineReconciler, createGateReconciler, createAutonomyReconciler, hasResourceChanged, fingerprintResource, } from './reconcilers.js';
|
|
48
53
|
export { createFileAuditLog, verifyAuditIntegrity, loadAuditEntries, rotateAuditLog, computeAuditHash, } from './audit-extended.js';
|
|
49
54
|
export { checkFrameworkCompliance, getControlCatalog, getFrameworkMappings, listSupportedFrameworks, } from './compliance-extended.js';
|
|
55
|
+
export { HARD_REGULATORY_REGIME_PREFIXES, isHardRegulatoryRegime, validateComplianceRegimes, computeComplianceClearance, type ValidateComplianceRegimesResult, type ComplianceViolation, type ComplianceViolationEntry, type SoulComplianceRegimes, type ComplianceClearanceContext, type ComplianceClearanceResult, } from './compliance-clearance.js';
|
|
56
|
+
export { loadCompliancePosture, DEFAULT_COMPLIANCE_MANIFEST_PATH, type LoadCompliancePostureOptions, } from './compliance/loader.js';
|
|
57
|
+
export { MissingComplianceAttestation, MissingDerivedGateOverrideNotes, UnknownRegime, CompliancePostureValidationError, } from './compliance/errors.js';
|
|
58
|
+
export { BASELINE_DERIVED_GATES, BASELINE_POSTURE, type CompliancePosture, type Regime, type DerivedGates, type PartialDerivedGatesOverrides, type AuditExportSpec, } from './compliance/types.js';
|
|
50
59
|
export { createSilentLogger, withPipelineSpanSync, getPipelineTracer, validateResourceSchema, } from './telemetry-extended.js';
|
|
51
60
|
export { ClaudeCodeRunner, ClaudeCodeRunner as GitHubActionsRunner, GenericLLMRunner, CopilotRunner, CursorRunner, CodexRunner, RunnerRegistry, createRunnerRegistry, SecurityTriageRunner, ReviewAgentRunner, REVIEW_PROMPTS, type AgentRunner, type AgentContext, type AgentResult, type AgentProgressEvent, type GenericLLMConfig, type RegisteredRunner, type SecurityTriageConfig, type TriageVerdict, type ReviewAgentConfig, type ReviewType, type ReviewFinding, type ReviewVerdict, } from './runners/index.js';
|
|
52
61
|
export type { TokenUsage } from './runners/index.js';
|
|
@@ -98,6 +107,9 @@ export { WorktreePoolManager, WorktreePoolError, WorktreeOwnershipError, determi
|
|
|
98
107
|
export { HarnessRegistry, UnknownHarnessError, ClaudeCodeAdapter, CodexAdapter, createDefaultHarnessRegistry, probeVersion, matchesRange, enforceIndependence, validateIndependenceGraph, CyclicIndependenceConstraintError, type HarnessAdapter, type HarnessAvailability, type HarnessCapabilities, type HarnessEvent, type HarnessInput, type HarnessName, type HarnessRequires, type HarnessResult, type HarnessResultStatus, type ClaudeCodeAdapterDeps, type CodexAdapterDeps, type IndependenceResult, type UpstreamRun, type ToolDefinition, } from './harness/index.js';
|
|
99
108
|
export { SubscriptionLedger, validateTenantShares, evaluateSchedule, CalibrationStore, COLD_START_DEFAULT, buildBurnDownReport, analyzeTier, PLAN_COSTS_USD, isOffPeakAt, nextOffPeakStart, ageInDays, freshnessLevel, DEFAULT_TENANT, COLD_START_DEFAULT_INPUT, COLD_START_DEFAULT_OUTPUT, ESTIMATE_VARIANCE_THRESHOLD, ROLLING_WINDOW_SIZE, type SubscriptionPlan, type Schedule, type TokenEstimate, type LedgerKey, type WindowState, type AdmissionDecision, type BurnDownReport, type LedgerEvent, type BillingMode, type QuotaSource, type OffPeakSchedule, type BurnDownInput, type CalibrationStoreDeps, type LedgerDeps, type ScheduleDecision, type ScheduleEvaluationContext, type Confidence, type ContentionEvent, type TierAnalysisInput, type TierAnalysisResult, type FreshnessLevel, } from './scheduling/index.js';
|
|
100
109
|
export { DatabaseAdapterRegistry, UnknownDatabaseAdapterError, SqliteCopyAdapter, NeonAdapter, PgSnapshotRestoreAdapter, ExternalAdapter, createDefaultDatabaseAdapterRegistry, buildInjectionOverrides, parsePostgresUrl, maskConnectionString, enforceTopologyGuard, buildMigrationDivergedEvent, DatabaseBranchAdapterError, BranchTopologyForbiddenError, type DatabaseBranchAdapter, type DatabaseBranchCapabilities, type DatabaseBranchHandle, type DatabaseAdapterName, type ResolvedDatabaseBranchPool, type DatabaseAccess, type SqliteCopyAdapterDeps, type NeonAdapterDeps, type PgSnapshotRestoreAdapterDeps, type ExternalAdapterDeps, type InjectedEnvOverrides, type KnownInFlightBranches, type MigrationDivergedEvent, } from './database/index.js';
|
|
110
|
+
export { AdapterCredentialInvalid, CommunityThreadSignalSourceAdapter, ManualSignalIncomplete, ManualSignalSourceAdapter, SignalSourceRegistry, SignalSourceUnavailable, SupportTicketSignalSourceAdapter, UnknownSignalSource, createDefaultSignalSourceRegistry, fetchSignalsFromAvailableAdapters, getSignalSourceAdapter, type AdapterCredentialInvalidDecision, type CommunityThreadAdapterOptions, type CustomerTier, type ManualSignalIncompleteDecision, type ManualSignalInput, type RawSignal, type SignalFetchResult, type SignalSourceAdapter, type SignalSourceName, type SignalTier, type SupportTicketAdapterOptions, } from './signal-ingestion/index.js';
|
|
111
|
+
export { classifySignals, computeRecencyDecay, computeSignalWeight, resolveCustomerTier, resolveIcpResonance, tokenize as tokenizeSignalPayload, DEFAULT_SIGNAL_INGESTION_CONFIG, DEFAULT_SIGNAL_INGESTION_CONFIG_PATH, SignalIngestionConfigError, loadSignalIngestionConfig, type ClassificationResult, type ClassifiedSignal, type ClassifySignalsOptions, type ClusteringConfig, type CustomerTierRegistry, type ICPResonance, type IcpResonanceWeights, type LoadSignalIngestionConfigOptions, type SaResonanceThresholds, type SignalIngestionConfig, type SignalLanguageUnsupportedDecision, type Tier2SignificanceThreshold, type TierMultipliers, } from './signal-ingestion/index.js';
|
|
112
|
+
export { aggregateD1FromClusters, composeD1Inputs, computeClusterD1, enrichDemandSignalFromClusters, type AggregatedD1Result, type ClusterD1Score, type ClusterMatcher, type ComposeD1InputsArgs, type ComposedD1Result, type D1CompositionWeights, type EnrichDemandSignalArgs, type EnrichDemandSignalResult, } from './signal-ingestion/index.js';
|
|
101
113
|
export { StateWriter, appendEvent, readEvents, atomicWriteJson, listActiveStates, HEARTBEAT_INTERVAL_MS, HEARTBEAT_STALE_MS, type RuntimeState, type ArtifactEvent, type StageStatus, } from './artifacts/index.js';
|
|
102
114
|
export { runWorkerPool, withMergeGate, forceReleaseMergeGate, isBranchUpToDate, MergeGateLockTimeoutError, decideRequeue, appendTriageHistory, type WorkItem, type WorkerPoolDeps, type WorkerPoolEvent, type WorkerPoolResult, type FailureEvent, type RequeueTrigger, type RequeueDecision, type RequeueDecisionInput, type TriageHistoryEntry, type FailureClassification, type MergeGateDeps, } from './dispatch/index.js';
|
|
103
115
|
export { ModelRegistry, ModelRemovedError, UnknownAliasError, DEFAULT_REGISTRY, decideFromRawOutput, decideFromInvocationFailure, validateClassifierOutput, defaultRulesetDecision, appendCalibrationEntry, ALL_REVIEWERS, type ModelEntry, type ResolutionContext, type ResolutionResult, type ResolutionEvent, type ReviewerName, type ClassifierOutput, type ClassifierDecision, type FellOpenReason, type CalibrationLogEntry, type DiffSummary, } from './models/index.js';
|