oxe-cc 1.0.0 → 1.2.1
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/.cursor/commands/oxe-ask.md +1 -1
- package/.cursor/commands/oxe-capabilities.md +1 -1
- package/.cursor/commands/oxe-checkpoint.md +1 -1
- package/.cursor/commands/oxe-compact.md +1 -1
- package/.cursor/commands/oxe-dashboard.md +1 -1
- package/.cursor/commands/oxe-debug.md +1 -1
- package/.cursor/commands/oxe-discuss.md +1 -1
- package/.cursor/commands/oxe-execute.md +2 -2
- package/.cursor/commands/oxe-forensics.md +1 -1
- package/.cursor/commands/oxe-help.md +1 -1
- package/.cursor/commands/oxe-loop.md +1 -1
- package/.cursor/commands/oxe-milestone.md +1 -1
- package/.cursor/commands/oxe-next.md +1 -1
- package/.cursor/commands/oxe-obs.md +1 -1
- package/.cursor/commands/oxe-plan-agent.md +1 -1
- package/.cursor/commands/oxe-plan.md +1 -1
- package/.cursor/commands/oxe-project.md +1 -1
- package/.cursor/commands/oxe-quick.md +1 -1
- package/.cursor/commands/oxe-research.md +1 -1
- package/.cursor/commands/oxe-retro.md +1 -1
- package/.cursor/commands/oxe-review-pr.md +1 -1
- package/.cursor/commands/oxe-route.md +1 -1
- package/.cursor/commands/oxe-scan.md +1 -1
- package/.cursor/commands/oxe-security.md +1 -1
- package/.cursor/commands/oxe-session.md +2 -2
- package/.cursor/commands/oxe-ship.md +45 -0
- package/.cursor/commands/oxe-skill.md +1 -1
- package/.cursor/commands/oxe-spec.md +1 -1
- package/.cursor/commands/oxe-ui-review.md +1 -1
- package/.cursor/commands/oxe-ui-spec.md +1 -1
- package/.cursor/commands/oxe-update.md +1 -1
- package/.cursor/commands/oxe-validate-gaps.md +1 -1
- package/.cursor/commands/oxe-verify.md +1 -1
- package/.cursor/commands/oxe-workstream.md +1 -1
- package/.cursor/commands/oxe.md +4 -4
- package/.github/copilot-instructions.md +91 -1
- package/.github/prompts/oxe-ask.prompt.md +1 -1
- package/.github/prompts/oxe-capabilities.prompt.md +1 -1
- package/.github/prompts/oxe-checkpoint.prompt.md +1 -1
- package/.github/prompts/oxe-compact.prompt.md +1 -1
- package/.github/prompts/oxe-dashboard.prompt.md +1 -1
- package/.github/prompts/oxe-debug.prompt.md +1 -1
- package/.github/prompts/oxe-discuss.prompt.md +1 -1
- package/.github/prompts/oxe-execute.prompt.md +2 -2
- package/.github/prompts/oxe-forensics.prompt.md +1 -1
- package/.github/prompts/oxe-help.prompt.md +1 -1
- package/.github/prompts/oxe-loop.prompt.md +1 -1
- package/.github/prompts/oxe-milestone.prompt.md +1 -1
- package/.github/prompts/oxe-next.prompt.md +1 -1
- package/.github/prompts/oxe-obs.prompt.md +1 -1
- package/.github/prompts/oxe-plan-agent.prompt.md +1 -1
- package/.github/prompts/oxe-plan.prompt.md +1 -1
- package/.github/prompts/oxe-project.prompt.md +1 -1
- package/.github/prompts/oxe-quick.prompt.md +1 -1
- package/.github/prompts/oxe-research.prompt.md +1 -1
- package/.github/prompts/oxe-retro.prompt.md +1 -1
- package/.github/prompts/oxe-review-pr.prompt.md +1 -1
- package/.github/prompts/oxe-route.prompt.md +1 -1
- package/.github/prompts/oxe-scan.prompt.md +1 -1
- package/.github/prompts/oxe-security.prompt.md +1 -1
- package/.github/prompts/oxe-session.prompt.md +2 -2
- package/.github/prompts/oxe-ship.prompt.md +45 -0
- package/.github/prompts/oxe-skill.prompt.md +1 -1
- package/.github/prompts/oxe-spec.prompt.md +1 -1
- package/.github/prompts/oxe-ui-review.prompt.md +1 -1
- package/.github/prompts/oxe-ui-spec.prompt.md +1 -1
- package/.github/prompts/oxe-update.prompt.md +1 -1
- package/.github/prompts/oxe-validate-gaps.prompt.md +1 -1
- package/.github/prompts/oxe-verify.prompt.md +1 -1
- package/.github/prompts/oxe-workstream.prompt.md +1 -1
- package/.github/prompts/oxe.prompt.md +3 -3
- package/AGENTS.md +43 -28
- package/CHANGELOG.md +158 -0
- package/README.md +72 -50
- package/bin/banner.txt +1 -1
- package/bin/lib/oxe-project-health.cjs +1 -1
- package/commands/oxe/ask.md +5 -1
- package/commands/oxe/checkpoint.md +1 -1
- package/commands/oxe/compact.md +1 -1
- package/commands/oxe/debug.md +1 -1
- package/commands/oxe/execute.md +2 -2
- package/commands/oxe/forensics.md +1 -1
- package/commands/oxe/loop.md +1 -1
- package/commands/oxe/milestone.md +1 -1
- package/commands/oxe/next.md +1 -1
- package/commands/oxe/obs.md +1 -1
- package/commands/oxe/oxe.md +3 -3
- package/commands/oxe/project.md +1 -1
- package/commands/oxe/research.md +1 -1
- package/commands/oxe/retro.md +1 -1
- package/commands/oxe/review-pr.md +1 -1
- package/commands/oxe/route.md +1 -1
- package/commands/oxe/scan.md +1 -1
- package/commands/oxe/security.md +1 -1
- package/commands/oxe/session.md +2 -2
- package/commands/oxe/ship.md +49 -0
- package/commands/oxe/spec.md +2 -2
- package/commands/oxe/ui-review.md +1 -1
- package/commands/oxe/ui-spec.md +1 -1
- package/commands/oxe/validate-gaps.md +1 -1
- package/commands/oxe/verify.md +2 -2
- package/commands/oxe/workstream.md +1 -1
- package/lib/runtime/audit/audit-trail.d.ts +71 -0
- package/lib/runtime/audit/audit-trail.js +154 -0
- package/lib/runtime/audit/index.d.ts +2 -0
- package/lib/runtime/audit/index.js +18 -0
- package/lib/runtime/audit/policy-pack.d.ts +15 -0
- package/lib/runtime/audit/policy-pack.js +57 -0
- package/lib/runtime/context/context-pack-builder.d.ts +15 -0
- package/lib/runtime/context/context-pack-builder.js +42 -0
- package/lib/runtime/context/context-pack-store.d.ts +38 -0
- package/lib/runtime/context/context-pack-store.js +142 -0
- package/lib/runtime/context/context-profiles.d.ts +11 -0
- package/lib/runtime/context/context-profiles.js +51 -0
- package/lib/runtime/context/index.d.ts +2 -0
- package/lib/runtime/context/index.js +2 -0
- package/lib/runtime/decision/decision-engine.d.ts +43 -0
- package/lib/runtime/decision/decision-engine.js +127 -0
- package/lib/runtime/decision/decision-memo.d.ts +53 -0
- package/lib/runtime/decision/decision-memo.js +173 -0
- package/lib/runtime/decision/index.d.ts +2 -0
- package/lib/runtime/decision/index.js +18 -0
- package/lib/runtime/delivery/index.d.ts +1 -0
- package/lib/runtime/delivery/index.js +1 -0
- package/lib/runtime/delivery/promotion-pipeline.d.ts +39 -0
- package/lib/runtime/delivery/promotion-pipeline.js +127 -0
- package/lib/runtime/index.d.ts +3 -0
- package/lib/runtime/index.js +4 -0
- package/lib/runtime/plugins/capability-matrix.d.ts +20 -0
- package/lib/runtime/plugins/capability-matrix.js +59 -0
- package/lib/runtime/plugins/index.d.ts +2 -0
- package/lib/runtime/plugins/index.js +2 -0
- package/lib/runtime/plugins/plugin-manifest.d.ts +22 -0
- package/lib/runtime/plugins/plugin-manifest.js +91 -0
- package/lib/runtime/plugins/plugin-registry.js +5 -0
- package/lib/runtime/policy/policy-engine.d.ts +28 -1
- package/lib/runtime/policy/policy-engine.js +96 -5
- package/lib/runtime/reducers/run-state-reducer.d.ts +26 -0
- package/lib/runtime/reducers/run-state-reducer.js +117 -1
- package/lib/runtime/scheduler/agent-registry.d.ts +44 -0
- package/lib/runtime/scheduler/agent-registry.js +96 -0
- package/lib/runtime/scheduler/agent-roles.d.ts +54 -0
- package/lib/runtime/scheduler/agent-roles.js +62 -0
- package/lib/runtime/scheduler/index.d.ts +3 -0
- package/lib/runtime/scheduler/index.js +3 -0
- package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +2 -0
- package/lib/runtime/scheduler/multi-agent-coordinator.js +91 -4
- package/lib/runtime/scheduler/run-journal.d.ts +18 -0
- package/lib/runtime/scheduler/run-journal.js +54 -0
- package/lib/runtime/scheduler/scheduler.d.ts +11 -1
- package/lib/runtime/scheduler/scheduler.js +135 -7
- package/lib/runtime/verification/index.d.ts +1 -0
- package/lib/runtime/verification/index.js +1 -0
- package/lib/runtime/verification/verification-manifest.d.ts +58 -0
- package/lib/runtime/verification/verification-manifest.js +129 -0
- package/oxe/workflows/ask.md +4 -0
- package/oxe/workflows/checkpoint.md +14 -10
- package/oxe/workflows/debug.md +19 -15
- package/oxe/workflows/execute.md +30 -2
- package/oxe/workflows/forensics.md +13 -9
- package/oxe/workflows/help.md +97 -49
- package/oxe/workflows/loop.md +17 -13
- package/oxe/workflows/obs.md +4 -0
- package/oxe/workflows/oxe.md +64 -31
- package/oxe/workflows/project.md +6 -1
- package/oxe/workflows/references/workflow-runtime-contracts.json +23 -0
- package/oxe/workflows/research.md +32 -28
- package/oxe/workflows/retro.md +4 -0
- package/oxe/workflows/review-pr.md +15 -11
- package/oxe/workflows/scan.md +4 -0
- package/oxe/workflows/security.md +14 -10
- package/oxe/workflows/session.md +17 -1
- package/oxe/workflows/ship.md +142 -0
- package/oxe/workflows/spec.md +15 -0
- package/oxe/workflows/ui-review.md +20 -16
- package/oxe/workflows/ui-spec.md +7 -3
- package/oxe/workflows/validate-gaps.md +13 -9
- package/oxe/workflows/verify.md +42 -3
- package/package.json +1 -1
- package/packages/runtime/src/audit/audit-trail.ts +243 -0
- package/packages/runtime/src/audit/index.ts +2 -0
- package/packages/runtime/src/audit/policy-pack.ts +62 -0
- package/packages/runtime/src/context/context-pack-builder.ts +66 -0
- package/packages/runtime/src/context/context-pack-store.ts +197 -0
- package/packages/runtime/src/context/context-profiles.ts +60 -0
- package/packages/runtime/src/context/index.ts +2 -0
- package/packages/runtime/src/decision/decision-engine.ts +174 -0
- package/packages/runtime/src/decision/decision-memo.ts +211 -0
- package/packages/runtime/src/decision/index.ts +2 -0
- package/packages/runtime/src/delivery/index.ts +1 -0
- package/packages/runtime/src/delivery/promotion-pipeline.ts +180 -0
- package/packages/runtime/src/index.ts +5 -0
- package/packages/runtime/src/plugins/capability-matrix.ts +83 -0
- package/packages/runtime/src/plugins/index.ts +2 -0
- package/packages/runtime/src/plugins/plugin-manifest.ts +113 -0
- package/packages/runtime/src/plugins/plugin-registry.ts +5 -0
- package/packages/runtime/src/policy/policy-engine.ts +138 -7
- package/packages/runtime/src/reducers/run-state-reducer.ts +143 -1
- package/packages/runtime/src/scheduler/agent-registry.ts +132 -0
- package/packages/runtime/src/scheduler/agent-roles.ts +109 -0
- package/packages/runtime/src/scheduler/index.ts +3 -0
- package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +106 -4
- package/packages/runtime/src/scheduler/run-journal.ts +62 -0
- package/packages/runtime/src/scheduler/scheduler.ts +168 -8
- package/packages/runtime/src/verification/index.ts +1 -0
- package/packages/runtime/src/verification/verification-manifest.ts +192 -0
- package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DecisionEngine = void 0;
|
|
7
|
+
exports.appendDecision = appendDecision;
|
|
8
|
+
exports.loadDecisionLog = loadDecisionLog;
|
|
9
|
+
exports.queryDecisions = queryDecisions;
|
|
10
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const fs_1 = __importDefault(require("fs"));
|
|
13
|
+
function computeSeniority(confidence) {
|
|
14
|
+
if (confidence >= 0.9)
|
|
15
|
+
return 'expert';
|
|
16
|
+
if (confidence >= 0.75)
|
|
17
|
+
return 'senior';
|
|
18
|
+
if (confidence >= 0.5)
|
|
19
|
+
return 'standard';
|
|
20
|
+
return 'junior';
|
|
21
|
+
}
|
|
22
|
+
class DecisionEngine {
|
|
23
|
+
evaluate(input) {
|
|
24
|
+
const signals = [];
|
|
25
|
+
let type = 'proceed';
|
|
26
|
+
let confidence = 0.8;
|
|
27
|
+
let rationale = '';
|
|
28
|
+
if (!input.policy_allowed) {
|
|
29
|
+
signals.push('policy_denied');
|
|
30
|
+
type = 'abort';
|
|
31
|
+
confidence = 1.0;
|
|
32
|
+
rationale = 'Policy denied execution — aborting without retry.';
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
signals.push('policy_allowed');
|
|
36
|
+
if (input.gate_pending && !input.gate_approved) {
|
|
37
|
+
signals.push('gate_pending');
|
|
38
|
+
type = 'escalate_gate';
|
|
39
|
+
confidence = 0.95;
|
|
40
|
+
rationale = 'Human gate pending — escalating for approval before proceeding.';
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
if (input.gate_approved)
|
|
44
|
+
signals.push('gate_approved');
|
|
45
|
+
if (input.risk_level === 'high' || input.risk_level === 'critical') {
|
|
46
|
+
signals.push('risk_high');
|
|
47
|
+
confidence = Math.max(0.4, confidence - 0.3);
|
|
48
|
+
rationale += 'High residual risk detected. ';
|
|
49
|
+
}
|
|
50
|
+
if (input.retry_count >= input.max_retries) {
|
|
51
|
+
signals.push('retry_budget_exhausted');
|
|
52
|
+
type = 'abort';
|
|
53
|
+
confidence = 0.9;
|
|
54
|
+
rationale += `Retry budget exhausted (${input.retry_count}/${input.max_retries}).`;
|
|
55
|
+
}
|
|
56
|
+
else if (input.retry_count > 0) {
|
|
57
|
+
signals.push('retry_budget_available');
|
|
58
|
+
type = 'retry';
|
|
59
|
+
confidence = 0.7;
|
|
60
|
+
rationale += `Retrying (attempt ${input.retry_count + 1}/${input.max_retries + 1}).`;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
if (input.evidence_count > 0) {
|
|
64
|
+
signals.push('evidence_sufficient');
|
|
65
|
+
confidence = Math.min(1.0, confidence + 0.1);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
signals.push('evidence_missing');
|
|
69
|
+
confidence = Math.max(0.3, confidence - 0.2);
|
|
70
|
+
}
|
|
71
|
+
if (input.lesson_match) {
|
|
72
|
+
signals.push('lesson_match');
|
|
73
|
+
type = 'promote_lesson';
|
|
74
|
+
confidence = Math.min(1.0, confidence + 0.05);
|
|
75
|
+
}
|
|
76
|
+
if (!rationale)
|
|
77
|
+
rationale = 'All signals green — proceeding with execution.';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
decision_id: `dec-${crypto_1.default.randomBytes(4).toString('hex')}`,
|
|
83
|
+
work_item_id: input.work_item_id ?? null,
|
|
84
|
+
run_id: input.run_id,
|
|
85
|
+
type,
|
|
86
|
+
seniority: computeSeniority(confidence),
|
|
87
|
+
confidence: Math.round(confidence * 100) / 100,
|
|
88
|
+
signals,
|
|
89
|
+
rationale: rationale.trim(),
|
|
90
|
+
timestamp: new Date().toISOString(),
|
|
91
|
+
...(input.memo !== undefined ? { memo: input.memo } : {}),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.DecisionEngine = DecisionEngine;
|
|
96
|
+
function appendDecision(projectRoot, runId, record) {
|
|
97
|
+
const p = logPath(projectRoot, runId);
|
|
98
|
+
fs_1.default.mkdirSync(path_1.default.dirname(p), { recursive: true });
|
|
99
|
+
const log = loadDecisionLog(projectRoot, runId) ?? { run_id: runId, decisions: [] };
|
|
100
|
+
log.decisions.push(record);
|
|
101
|
+
fs_1.default.writeFileSync(p, JSON.stringify(log, null, 2), 'utf8');
|
|
102
|
+
}
|
|
103
|
+
function loadDecisionLog(projectRoot, runId) {
|
|
104
|
+
const p = logPath(projectRoot, runId);
|
|
105
|
+
if (!fs_1.default.existsSync(p))
|
|
106
|
+
return null;
|
|
107
|
+
try {
|
|
108
|
+
return JSON.parse(fs_1.default.readFileSync(p, 'utf8'));
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function queryDecisions(log, filter) {
|
|
115
|
+
return log.decisions.filter((d) => {
|
|
116
|
+
if (filter.type && d.type !== filter.type)
|
|
117
|
+
return false;
|
|
118
|
+
if (filter.workItemId && d.work_item_id !== filter.workItemId)
|
|
119
|
+
return false;
|
|
120
|
+
if (filter.minConfidence !== undefined && d.confidence < filter.minConfidence)
|
|
121
|
+
return false;
|
|
122
|
+
return true;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function logPath(projectRoot, runId) {
|
|
126
|
+
return path_1.default.join(projectRoot, '.oxe', 'runs', runId, 'decisions.json');
|
|
127
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type ChangeStrategy = 'minimal_patch' | 'isolated_refactor' | 'expand_contract' | 'feature_flag' | 'no_op';
|
|
2
|
+
export interface BlastRadiusEstimate {
|
|
3
|
+
estimated_files: number;
|
|
4
|
+
subsystems: string[];
|
|
5
|
+
risk_score: number;
|
|
6
|
+
reversible: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface RollbackPlan {
|
|
9
|
+
strategy: 'revert_commit' | 'restore_workspace' | 'undo_patch' | 'no_rollback';
|
|
10
|
+
steps: string[];
|
|
11
|
+
estimated_cost: 'low' | 'medium' | 'high';
|
|
12
|
+
preconditions: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface DecisionMemo {
|
|
15
|
+
memo_id: string;
|
|
16
|
+
work_item_id: string;
|
|
17
|
+
run_id: string;
|
|
18
|
+
problem_summary: string;
|
|
19
|
+
chosen_strategy: ChangeStrategy;
|
|
20
|
+
alternatives_rejected: Array<{
|
|
21
|
+
strategy: ChangeStrategy;
|
|
22
|
+
reason: string;
|
|
23
|
+
}>;
|
|
24
|
+
blast_radius: BlastRadiusEstimate;
|
|
25
|
+
rollback_plan: RollbackPlan;
|
|
26
|
+
min_evidence_required: string[];
|
|
27
|
+
confidence: number;
|
|
28
|
+
created_at: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function buildBlastRadius(mutationScope: string[], retryCount: number, riskLevel: string): BlastRadiusEstimate;
|
|
31
|
+
export declare function buildRollbackPlan(blastRadius: BlastRadiusEstimate, retryCount: number): RollbackPlan;
|
|
32
|
+
export declare class StrategySelector {
|
|
33
|
+
select(mutationScope: string[], retryCount: number, riskLevel: string): ChangeStrategy;
|
|
34
|
+
alternatives(chosen: ChangeStrategy, mutationScope: string[], riskLevel: string): Array<{
|
|
35
|
+
strategy: ChangeStrategy;
|
|
36
|
+
reason: string;
|
|
37
|
+
}>;
|
|
38
|
+
private rejectionReason;
|
|
39
|
+
}
|
|
40
|
+
export interface BuildMemoInput {
|
|
41
|
+
work_item_id: string;
|
|
42
|
+
run_id: string;
|
|
43
|
+
problem_summary: string;
|
|
44
|
+
mutation_scope: string[];
|
|
45
|
+
retry_count: number;
|
|
46
|
+
risk_level: string;
|
|
47
|
+
min_evidence_required?: string[];
|
|
48
|
+
confidence?: number;
|
|
49
|
+
}
|
|
50
|
+
export declare function buildMemo(input: BuildMemoInput): DecisionMemo;
|
|
51
|
+
export declare function saveMemo(projectRoot: string, memo: DecisionMemo): void;
|
|
52
|
+
export declare function loadMemo(projectRoot: string, runId: string, memoId: string): DecisionMemo | null;
|
|
53
|
+
export declare function listMemos(projectRoot: string, runId: string): DecisionMemo[];
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.StrategySelector = void 0;
|
|
7
|
+
exports.buildBlastRadius = buildBlastRadius;
|
|
8
|
+
exports.buildRollbackPlan = buildRollbackPlan;
|
|
9
|
+
exports.buildMemo = buildMemo;
|
|
10
|
+
exports.saveMemo = saveMemo;
|
|
11
|
+
exports.loadMemo = loadMemo;
|
|
12
|
+
exports.listMemos = listMemos;
|
|
13
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
14
|
+
const path_1 = __importDefault(require("path"));
|
|
15
|
+
const fs_1 = __importDefault(require("fs"));
|
|
16
|
+
// ─── BlastRadius estimation ───────────────────────────────────────────────────
|
|
17
|
+
function deriveSubsystems(mutationScope) {
|
|
18
|
+
const seen = new Set();
|
|
19
|
+
for (const p of mutationScope) {
|
|
20
|
+
const parts = p.replace(/\\/g, '/').split('/');
|
|
21
|
+
if (parts.length >= 2)
|
|
22
|
+
seen.add(parts[0]);
|
|
23
|
+
else
|
|
24
|
+
seen.add(p);
|
|
25
|
+
}
|
|
26
|
+
return [...seen];
|
|
27
|
+
}
|
|
28
|
+
function estimateRiskScore(mutationScope, retryCount, riskLevel) {
|
|
29
|
+
let score = 0;
|
|
30
|
+
score += Math.min(0.4, mutationScope.length * 0.05);
|
|
31
|
+
score += retryCount > 0 ? Math.min(0.2, retryCount * 0.05) : 0;
|
|
32
|
+
switch (riskLevel) {
|
|
33
|
+
case 'critical':
|
|
34
|
+
score += 0.4;
|
|
35
|
+
break;
|
|
36
|
+
case 'high':
|
|
37
|
+
score += 0.3;
|
|
38
|
+
break;
|
|
39
|
+
case 'medium':
|
|
40
|
+
score += 0.15;
|
|
41
|
+
break;
|
|
42
|
+
case 'low':
|
|
43
|
+
score += 0.05;
|
|
44
|
+
break;
|
|
45
|
+
default: break;
|
|
46
|
+
}
|
|
47
|
+
return Math.min(1, score);
|
|
48
|
+
}
|
|
49
|
+
function buildBlastRadius(mutationScope, retryCount, riskLevel) {
|
|
50
|
+
const risk_score = estimateRiskScore(mutationScope, retryCount, riskLevel);
|
|
51
|
+
return {
|
|
52
|
+
estimated_files: mutationScope.length,
|
|
53
|
+
subsystems: deriveSubsystems(mutationScope),
|
|
54
|
+
risk_score: Math.round(risk_score * 100) / 100,
|
|
55
|
+
reversible: riskLevel !== 'critical' && mutationScope.length <= 10,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// ─── RollbackPlan ─────────────────────────────────────────────────────────────
|
|
59
|
+
function buildRollbackPlan(blastRadius, retryCount) {
|
|
60
|
+
if (blastRadius.risk_score >= 0.7 || !blastRadius.reversible) {
|
|
61
|
+
return {
|
|
62
|
+
strategy: 'restore_workspace',
|
|
63
|
+
steps: ['snapshot workspace before mutation', 'restore snapshot on failure', 'verify clean state'],
|
|
64
|
+
estimated_cost: 'high',
|
|
65
|
+
preconditions: ['workspace snapshot available', 'no shared-state mutations'],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (retryCount > 1 || blastRadius.estimated_files > 5) {
|
|
69
|
+
return {
|
|
70
|
+
strategy: 'revert_commit',
|
|
71
|
+
steps: ['record commit SHA before change', 'git revert on failure'],
|
|
72
|
+
estimated_cost: 'medium',
|
|
73
|
+
preconditions: ['git repo initialized', 'changes committed atomically'],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
strategy: 'undo_patch',
|
|
78
|
+
steps: ['apply inverse patch'],
|
|
79
|
+
estimated_cost: 'low',
|
|
80
|
+
preconditions: ['original file state recorded'],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// ─── StrategySelector ────────────────────────────────────────────────────────
|
|
84
|
+
class StrategySelector {
|
|
85
|
+
select(mutationScope, retryCount, riskLevel) {
|
|
86
|
+
if (riskLevel === 'critical')
|
|
87
|
+
return 'feature_flag';
|
|
88
|
+
if (retryCount > 1)
|
|
89
|
+
return 'minimal_patch';
|
|
90
|
+
if (mutationScope.length > 8)
|
|
91
|
+
return 'isolated_refactor';
|
|
92
|
+
if (riskLevel === 'high')
|
|
93
|
+
return 'feature_flag';
|
|
94
|
+
if (mutationScope.length > 3)
|
|
95
|
+
return 'expand_contract';
|
|
96
|
+
if (mutationScope.length === 0)
|
|
97
|
+
return 'no_op';
|
|
98
|
+
return 'minimal_patch';
|
|
99
|
+
}
|
|
100
|
+
alternatives(chosen, mutationScope, riskLevel) {
|
|
101
|
+
const all = ['minimal_patch', 'isolated_refactor', 'expand_contract', 'feature_flag', 'no_op'];
|
|
102
|
+
return all
|
|
103
|
+
.filter((s) => s !== chosen)
|
|
104
|
+
.map((s) => ({ strategy: s, reason: this.rejectionReason(s, chosen, mutationScope, riskLevel) }));
|
|
105
|
+
}
|
|
106
|
+
rejectionReason(s, chosen, mutationScope, riskLevel) {
|
|
107
|
+
switch (s) {
|
|
108
|
+
case 'no_op': return 'mutation scope is non-empty; no-op would not satisfy requirements';
|
|
109
|
+
case 'feature_flag': return riskLevel !== 'critical' && riskLevel !== 'high' ? 'risk level does not warrant feature flag overhead' : `${chosen} preferred for scope size`;
|
|
110
|
+
case 'isolated_refactor': return mutationScope.length <= 8 ? 'scope is small enough for simpler strategy' : `${chosen} preferred`;
|
|
111
|
+
case 'expand_contract': return 'expand-contract requires coordinated deployment; overhead not justified here';
|
|
112
|
+
case 'minimal_patch': return `${chosen} preferred due to scope or risk level`;
|
|
113
|
+
default: return 'not applicable';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.StrategySelector = StrategySelector;
|
|
118
|
+
function buildMemo(input) {
|
|
119
|
+
const selector = new StrategySelector();
|
|
120
|
+
const chosen = selector.select(input.mutation_scope, input.retry_count, input.risk_level);
|
|
121
|
+
const blast_radius = buildBlastRadius(input.mutation_scope, input.retry_count, input.risk_level);
|
|
122
|
+
const rollback_plan = buildRollbackPlan(blast_radius, input.retry_count);
|
|
123
|
+
const alternatives_rejected = selector.alternatives(chosen, input.mutation_scope, input.risk_level);
|
|
124
|
+
return {
|
|
125
|
+
memo_id: `memo-${crypto_1.default.randomBytes(4).toString('hex')}`,
|
|
126
|
+
work_item_id: input.work_item_id,
|
|
127
|
+
run_id: input.run_id,
|
|
128
|
+
problem_summary: input.problem_summary,
|
|
129
|
+
chosen_strategy: chosen,
|
|
130
|
+
alternatives_rejected,
|
|
131
|
+
blast_radius,
|
|
132
|
+
rollback_plan,
|
|
133
|
+
min_evidence_required: input.min_evidence_required ?? [],
|
|
134
|
+
confidence: input.confidence ?? (1 - blast_radius.risk_score),
|
|
135
|
+
created_at: new Date().toISOString(),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function memoDir(projectRoot, runId) {
|
|
139
|
+
return path_1.default.join(projectRoot, '.oxe', 'runs', runId, 'memos');
|
|
140
|
+
}
|
|
141
|
+
function saveMemo(projectRoot, memo) {
|
|
142
|
+
const dir = memoDir(projectRoot, memo.run_id);
|
|
143
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
144
|
+
fs_1.default.writeFileSync(path_1.default.join(dir, `${memo.memo_id}.json`), JSON.stringify(memo, null, 2), 'utf8');
|
|
145
|
+
}
|
|
146
|
+
function loadMemo(projectRoot, runId, memoId) {
|
|
147
|
+
const p = path_1.default.join(memoDir(projectRoot, runId), `${memoId}.json`);
|
|
148
|
+
if (!fs_1.default.existsSync(p))
|
|
149
|
+
return null;
|
|
150
|
+
try {
|
|
151
|
+
return JSON.parse(fs_1.default.readFileSync(p, 'utf8'));
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function listMemos(projectRoot, runId) {
|
|
158
|
+
const dir = memoDir(projectRoot, runId);
|
|
159
|
+
if (!fs_1.default.existsSync(dir))
|
|
160
|
+
return [];
|
|
161
|
+
return fs_1.default
|
|
162
|
+
.readdirSync(dir)
|
|
163
|
+
.filter((f) => f.endsWith('.json'))
|
|
164
|
+
.map((f) => {
|
|
165
|
+
try {
|
|
166
|
+
return JSON.parse(fs_1.default.readFileSync(path_1.default.join(dir, f), 'utf8'));
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
.filter((m) => m !== null);
|
|
173
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./decision-engine"), exports);
|
|
18
|
+
__exportStar(require("./decision-memo"), exports);
|
|
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./branch-manager"), exports);
|
|
18
18
|
__exportStar(require("./pr-manager"), exports);
|
|
19
19
|
__exportStar(require("./ci-checks"), exports);
|
|
20
|
+
__exportStar(require("./promotion-pipeline"), exports);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PRManager } from './pr-manager';
|
|
2
|
+
import type { BranchManager } from './branch-manager';
|
|
3
|
+
import type { VerificationManifest, ResidualRiskLedger } from '../verification/verification-manifest';
|
|
4
|
+
import type { RunResult } from '../scheduler/scheduler';
|
|
5
|
+
export interface RunPRLink {
|
|
6
|
+
run_id: string;
|
|
7
|
+
branch: string;
|
|
8
|
+
pr_url: string | null;
|
|
9
|
+
pr_number: number | null;
|
|
10
|
+
status: 'pending' | 'open' | 'merged' | 'closed' | 'blocked';
|
|
11
|
+
created_at: string;
|
|
12
|
+
merged_at: string | null;
|
|
13
|
+
}
|
|
14
|
+
export interface PromotionOptions {
|
|
15
|
+
baseBranch?: string;
|
|
16
|
+
draftPR?: boolean;
|
|
17
|
+
autoMerge?: boolean;
|
|
18
|
+
mergeMethod?: 'merge' | 'squash' | 'rebase';
|
|
19
|
+
}
|
|
20
|
+
export type MergeGateVerdict = 'approved' | 'blocked' | 'needs_review';
|
|
21
|
+
export interface MergeGateReport {
|
|
22
|
+
verdict: MergeGateVerdict;
|
|
23
|
+
reasons: string[];
|
|
24
|
+
blocking_risks: string[];
|
|
25
|
+
}
|
|
26
|
+
export declare class MergeGateEvaluator {
|
|
27
|
+
evaluate(runResult: RunResult, manifest: VerificationManifest | null, riskLedger: ResidualRiskLedger | null): MergeGateReport;
|
|
28
|
+
}
|
|
29
|
+
export declare class PromotionPipeline {
|
|
30
|
+
private readonly projectRoot;
|
|
31
|
+
private readonly branchManager;
|
|
32
|
+
private readonly prManager;
|
|
33
|
+
private readonly gateEvaluator;
|
|
34
|
+
constructor(projectRoot: string, branchManager: BranchManager, prManager: PRManager, gateEvaluator?: MergeGateEvaluator);
|
|
35
|
+
buildPRBody(runResult: RunResult, manifest: VerificationManifest | null, riskLedger: ResidualRiskLedger | null): string;
|
|
36
|
+
promote(runResult: RunResult, manifest: VerificationManifest | null, riskLedger: ResidualRiskLedger | null, opts?: PromotionOptions): Promise<RunPRLink>;
|
|
37
|
+
savePRLink(runId: string, link: RunPRLink): void;
|
|
38
|
+
loadPRLink(runId: string): RunPRLink | null;
|
|
39
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PromotionPipeline = exports.MergeGateEvaluator = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
class MergeGateEvaluator {
|
|
10
|
+
evaluate(runResult, manifest, riskLedger) {
|
|
11
|
+
const reasons = [];
|
|
12
|
+
const blockingRisks = [];
|
|
13
|
+
if (runResult.failed.length > 0) {
|
|
14
|
+
reasons.push(`${runResult.failed.length} task(s) failed: ${runResult.failed.join(', ')}`);
|
|
15
|
+
}
|
|
16
|
+
if (runResult.blocked.length > 0) {
|
|
17
|
+
reasons.push(`${runResult.blocked.length} task(s) blocked: ${runResult.blocked.join(', ')}`);
|
|
18
|
+
}
|
|
19
|
+
if (manifest && !manifest.summary.all_passed) {
|
|
20
|
+
reasons.push(`Verification: ${manifest.summary.fail} check(s) failed, ${manifest.summary.error} error(s)`);
|
|
21
|
+
}
|
|
22
|
+
if (riskLedger) {
|
|
23
|
+
const critical = riskLedger.risks.filter((r) => r.severity === 'critical' || r.severity === 'high');
|
|
24
|
+
for (const risk of critical) {
|
|
25
|
+
blockingRisks.push(`[${risk.severity.toUpperCase()}] ${risk.description}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const hasBlockers = reasons.length > 0 || blockingRisks.length > 0;
|
|
29
|
+
const verdict = hasBlockers ? 'blocked' : 'approved';
|
|
30
|
+
return { verdict, reasons, blocking_risks: blockingRisks };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.MergeGateEvaluator = MergeGateEvaluator;
|
|
34
|
+
class PromotionPipeline {
|
|
35
|
+
constructor(projectRoot, branchManager, prManager, gateEvaluator = new MergeGateEvaluator()) {
|
|
36
|
+
this.projectRoot = projectRoot;
|
|
37
|
+
this.branchManager = branchManager;
|
|
38
|
+
this.prManager = prManager;
|
|
39
|
+
this.gateEvaluator = gateEvaluator;
|
|
40
|
+
}
|
|
41
|
+
buildPRBody(runResult, manifest, riskLedger) {
|
|
42
|
+
const lines = [];
|
|
43
|
+
lines.push('## OXE Run Summary');
|
|
44
|
+
lines.push('');
|
|
45
|
+
lines.push(`**Run ID:** \`${runResult.run_id}\``);
|
|
46
|
+
lines.push(`**Status:** ${runResult.status}`);
|
|
47
|
+
lines.push(`**Completed:** ${runResult.completed.length} tasks`);
|
|
48
|
+
if (runResult.failed.length > 0) {
|
|
49
|
+
lines.push(`**Failed:** ${runResult.failed.join(', ')}`);
|
|
50
|
+
}
|
|
51
|
+
if (runResult.blocked.length > 0) {
|
|
52
|
+
lines.push(`**Blocked:** ${runResult.blocked.join(', ')}`);
|
|
53
|
+
}
|
|
54
|
+
if (manifest) {
|
|
55
|
+
lines.push('');
|
|
56
|
+
lines.push('## Verification');
|
|
57
|
+
lines.push(`- Total: ${manifest.summary.total}`);
|
|
58
|
+
lines.push(`- Pass: ${manifest.summary.pass}`);
|
|
59
|
+
lines.push(`- Fail: ${manifest.summary.fail}`);
|
|
60
|
+
lines.push(`- Skip: ${manifest.summary.skip}`);
|
|
61
|
+
}
|
|
62
|
+
if (riskLedger && riskLedger.risks.length > 0) {
|
|
63
|
+
lines.push('');
|
|
64
|
+
lines.push('## Residual Risks');
|
|
65
|
+
for (const risk of riskLedger.risks) {
|
|
66
|
+
lines.push(`- [${risk.severity.toUpperCase()}] ${risk.description}`);
|
|
67
|
+
if (risk.mitigation)
|
|
68
|
+
lines.push(` - Mitigation: ${risk.mitigation}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
lines.push('');
|
|
72
|
+
lines.push('---');
|
|
73
|
+
lines.push('*Generated by OXE Runtime*');
|
|
74
|
+
return lines.join('\n');
|
|
75
|
+
}
|
|
76
|
+
async promote(runResult, manifest, riskLedger, opts = {}) {
|
|
77
|
+
const gateReport = this.gateEvaluator.evaluate(runResult, manifest, riskLedger);
|
|
78
|
+
const link = {
|
|
79
|
+
run_id: runResult.run_id,
|
|
80
|
+
branch: this.branchManager.currentBranch(),
|
|
81
|
+
pr_url: null,
|
|
82
|
+
pr_number: null,
|
|
83
|
+
status: 'pending',
|
|
84
|
+
created_at: new Date().toISOString(),
|
|
85
|
+
merged_at: null,
|
|
86
|
+
};
|
|
87
|
+
if (gateReport.verdict === 'blocked') {
|
|
88
|
+
link.status = 'blocked';
|
|
89
|
+
this.savePRLink(runResult.run_id, link);
|
|
90
|
+
return link;
|
|
91
|
+
}
|
|
92
|
+
const body = this.buildPRBody(runResult, manifest, riskLedger);
|
|
93
|
+
const title = `oxe: run ${runResult.run_id} — ${runResult.completed.length} tasks`;
|
|
94
|
+
const prResult = this.prManager.createDraft({
|
|
95
|
+
title,
|
|
96
|
+
body,
|
|
97
|
+
base: opts.baseBranch ?? 'main',
|
|
98
|
+
draft: opts.draftPR !== false,
|
|
99
|
+
});
|
|
100
|
+
if (!prResult.success || !prResult.url) {
|
|
101
|
+
link.status = 'blocked';
|
|
102
|
+
this.savePRLink(runResult.run_id, link);
|
|
103
|
+
return link;
|
|
104
|
+
}
|
|
105
|
+
link.pr_url = prResult.url;
|
|
106
|
+
link.status = 'open';
|
|
107
|
+
this.savePRLink(runResult.run_id, link);
|
|
108
|
+
return link;
|
|
109
|
+
}
|
|
110
|
+
savePRLink(runId, link) {
|
|
111
|
+
const p = path_1.default.join(this.projectRoot, '.oxe', 'runs', runId, 'pr-link.json');
|
|
112
|
+
fs_1.default.mkdirSync(path_1.default.dirname(p), { recursive: true });
|
|
113
|
+
fs_1.default.writeFileSync(p, JSON.stringify(link, null, 2), 'utf8');
|
|
114
|
+
}
|
|
115
|
+
loadPRLink(runId) {
|
|
116
|
+
const p = path_1.default.join(this.projectRoot, '.oxe', 'runs', runId, 'pr-link.json');
|
|
117
|
+
if (!fs_1.default.existsSync(p))
|
|
118
|
+
return null;
|
|
119
|
+
try {
|
|
120
|
+
return JSON.parse(fs_1.default.readFileSync(p, 'utf8'));
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
exports.PromotionPipeline = PromotionPipeline;
|
package/lib/runtime/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './workspace/index';
|
|
|
7
7
|
export * from './evidence/index';
|
|
8
8
|
export { compile as compileVerification, runCheck, runSuite, summarizeSuite, } from './verification/verification-compiler';
|
|
9
9
|
export type { CheckType, AcceptanceCheck, AcceptanceCheckSuite, CheckResult, } from './verification/verification-compiler';
|
|
10
|
+
export * from './verification/verification-manifest';
|
|
10
11
|
export * from './policy/index';
|
|
11
12
|
export * from './gate/index';
|
|
12
13
|
export * from './projection/index';
|
|
@@ -14,3 +15,5 @@ export * from './plugins/index';
|
|
|
14
15
|
export * from './delivery/index';
|
|
15
16
|
export * from './context/index';
|
|
16
17
|
export * from './scheduler/multi-agent-coordinator';
|
|
18
|
+
export * from './decision/index';
|
|
19
|
+
export * from './audit/index';
|
package/lib/runtime/index.js
CHANGED
|
@@ -30,6 +30,7 @@ Object.defineProperty(exports, "compileVerification", { enumerable: true, get: f
|
|
|
30
30
|
Object.defineProperty(exports, "runCheck", { enumerable: true, get: function () { return verification_compiler_1.runCheck; } });
|
|
31
31
|
Object.defineProperty(exports, "runSuite", { enumerable: true, get: function () { return verification_compiler_1.runSuite; } });
|
|
32
32
|
Object.defineProperty(exports, "summarizeSuite", { enumerable: true, get: function () { return verification_compiler_1.summarizeSuite; } });
|
|
33
|
+
__exportStar(require("./verification/verification-manifest"), exports);
|
|
33
34
|
__exportStar(require("./policy/index"), exports);
|
|
34
35
|
__exportStar(require("./gate/index"), exports);
|
|
35
36
|
__exportStar(require("./projection/index"), exports);
|
|
@@ -38,3 +39,6 @@ __exportStar(require("./plugins/index"), exports);
|
|
|
38
39
|
__exportStar(require("./delivery/index"), exports);
|
|
39
40
|
__exportStar(require("./context/index"), exports);
|
|
40
41
|
__exportStar(require("./scheduler/multi-agent-coordinator"), exports);
|
|
42
|
+
// R4 Public ABI — Decision, Audit & Enterprise
|
|
43
|
+
__exportStar(require("./decision/index"), exports);
|
|
44
|
+
__exportStar(require("./audit/index"), exports);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PluginRegistry } from './plugin-registry';
|
|
2
|
+
export type ApiStability = 'stable' | 'experimental' | 'deprecated';
|
|
3
|
+
export interface ProviderCapabilityEntry {
|
|
4
|
+
name: string;
|
|
5
|
+
provider_type: 'tool' | 'workspace' | 'verifier' | 'context';
|
|
6
|
+
stability: ApiStability;
|
|
7
|
+
since_abi_version: string;
|
|
8
|
+
deprecated_in?: string;
|
|
9
|
+
replacement?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface CapabilityMatrix {
|
|
12
|
+
abi_version: string;
|
|
13
|
+
entries: ProviderCapabilityEntry[];
|
|
14
|
+
}
|
|
15
|
+
export declare function buildMatrix(registry: PluginRegistry): CapabilityMatrix;
|
|
16
|
+
export declare function getStableEntries(matrix: CapabilityMatrix): ProviderCapabilityEntry[];
|
|
17
|
+
export declare function getExperimentalEntries(matrix: CapabilityMatrix): ProviderCapabilityEntry[];
|
|
18
|
+
export declare function getDeprecatedEntries(matrix: CapabilityMatrix): ProviderCapabilityEntry[];
|
|
19
|
+
export declare function markDeprecated(matrix: CapabilityMatrix, name: string, deprecatedIn: string, replacement?: string): CapabilityMatrix;
|
|
20
|
+
export declare function addEntry(matrix: CapabilityMatrix, entry: ProviderCapabilityEntry): CapabilityMatrix;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildMatrix = buildMatrix;
|
|
4
|
+
exports.getStableEntries = getStableEntries;
|
|
5
|
+
exports.getExperimentalEntries = getExperimentalEntries;
|
|
6
|
+
exports.getDeprecatedEntries = getDeprecatedEntries;
|
|
7
|
+
exports.markDeprecated = markDeprecated;
|
|
8
|
+
exports.addEntry = addEntry;
|
|
9
|
+
const plugin_manifest_1 = require("./plugin-manifest");
|
|
10
|
+
function buildMatrix(registry) {
|
|
11
|
+
const entries = [];
|
|
12
|
+
for (const plugin of registry.list()) {
|
|
13
|
+
const providers = plugin.providers ?? [];
|
|
14
|
+
for (const prov of providers) {
|
|
15
|
+
let provider_type;
|
|
16
|
+
if (prov.startsWith('tool:'))
|
|
17
|
+
provider_type = 'tool';
|
|
18
|
+
else if (prov.startsWith('workspace:'))
|
|
19
|
+
provider_type = 'workspace';
|
|
20
|
+
else if (prov.startsWith('verifier:'))
|
|
21
|
+
provider_type = 'verifier';
|
|
22
|
+
else if (prov.startsWith('context:'))
|
|
23
|
+
provider_type = 'context';
|
|
24
|
+
else
|
|
25
|
+
continue;
|
|
26
|
+
const name = prov.slice(prov.indexOf(':') + 1);
|
|
27
|
+
entries.push({
|
|
28
|
+
name,
|
|
29
|
+
provider_type,
|
|
30
|
+
stability: 'stable',
|
|
31
|
+
since_abi_version: plugin_manifest_1.CURRENT_ABI_VERSION,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return { abi_version: plugin_manifest_1.CURRENT_ABI_VERSION, entries };
|
|
36
|
+
}
|
|
37
|
+
function getStableEntries(matrix) {
|
|
38
|
+
return matrix.entries.filter((e) => e.stability === 'stable');
|
|
39
|
+
}
|
|
40
|
+
function getExperimentalEntries(matrix) {
|
|
41
|
+
return matrix.entries.filter((e) => e.stability === 'experimental');
|
|
42
|
+
}
|
|
43
|
+
function getDeprecatedEntries(matrix) {
|
|
44
|
+
return matrix.entries.filter((e) => e.stability === 'deprecated');
|
|
45
|
+
}
|
|
46
|
+
function markDeprecated(matrix, name, deprecatedIn, replacement) {
|
|
47
|
+
return {
|
|
48
|
+
...matrix,
|
|
49
|
+
entries: matrix.entries.map((e) => e.name === name
|
|
50
|
+
? { ...e, stability: 'deprecated', deprecated_in: deprecatedIn, replacement }
|
|
51
|
+
: e),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function addEntry(matrix, entry) {
|
|
55
|
+
if (matrix.entries.some((e) => e.name === entry.name && e.provider_type === entry.provider_type)) {
|
|
56
|
+
return matrix;
|
|
57
|
+
}
|
|
58
|
+
return { ...matrix, entries: [...matrix.entries, entry] };
|
|
59
|
+
}
|