oxe-cc 1.2.1 → 1.4.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/.cursor/commands/oxe-ask.md +2 -2
- package/.cursor/commands/oxe-capabilities.md +2 -2
- package/.cursor/commands/oxe-checkpoint.md +2 -2
- package/.cursor/commands/oxe-compact.md +2 -2
- package/.cursor/commands/oxe-dashboard.md +2 -2
- package/.cursor/commands/oxe-debug.md +2 -2
- package/.cursor/commands/oxe-discuss.md +2 -2
- package/.cursor/commands/oxe-execute.md +5 -2
- package/.cursor/commands/oxe-forensics.md +2 -2
- package/.cursor/commands/oxe-help.md +2 -2
- package/.cursor/commands/oxe-loop.md +2 -2
- package/.cursor/commands/oxe-milestone.md +2 -2
- package/.cursor/commands/oxe-next.md +2 -2
- package/.cursor/commands/oxe-obs.md +2 -2
- package/.cursor/commands/oxe-plan-agent.md +2 -2
- package/.cursor/commands/oxe-plan.md +2 -2
- package/.cursor/commands/oxe-project.md +2 -2
- package/.cursor/commands/oxe-quick.md +2 -2
- package/.cursor/commands/oxe-research.md +2 -2
- package/.cursor/commands/oxe-retro.md +2 -2
- package/.cursor/commands/oxe-review-pr.md +2 -2
- package/.cursor/commands/oxe-route.md +2 -2
- package/.cursor/commands/oxe-scan.md +2 -2
- package/.cursor/commands/oxe-security.md +2 -2
- package/.cursor/commands/oxe-session.md +2 -2
- package/.cursor/commands/oxe-ship.md +2 -2
- package/.cursor/commands/oxe-skill.md +2 -2
- package/.cursor/commands/oxe-spec.md +2 -2
- package/.cursor/commands/oxe-ui-review.md +2 -2
- package/.cursor/commands/oxe-ui-spec.md +2 -2
- package/.cursor/commands/oxe-update.md +2 -2
- package/.cursor/commands/oxe-validate-gaps.md +2 -2
- package/.cursor/commands/oxe-verify.md +5 -2
- package/.cursor/commands/oxe-workstream.md +2 -2
- package/.cursor/commands/oxe.md +2 -2
- package/.github/copilot-instructions.md +13 -13
- package/.github/prompts/oxe-ask.prompt.md +2 -2
- package/.github/prompts/oxe-capabilities.prompt.md +2 -2
- package/.github/prompts/oxe-checkpoint.prompt.md +2 -2
- package/.github/prompts/oxe-compact.prompt.md +2 -2
- package/.github/prompts/oxe-dashboard.prompt.md +2 -2
- package/.github/prompts/oxe-debug.prompt.md +2 -2
- package/.github/prompts/oxe-discuss.prompt.md +2 -2
- package/.github/prompts/oxe-execute.prompt.md +5 -2
- package/.github/prompts/oxe-forensics.prompt.md +2 -2
- package/.github/prompts/oxe-help.prompt.md +2 -2
- package/.github/prompts/oxe-loop.prompt.md +2 -2
- package/.github/prompts/oxe-milestone.prompt.md +2 -2
- package/.github/prompts/oxe-next.prompt.md +2 -2
- package/.github/prompts/oxe-obs.prompt.md +2 -2
- package/.github/prompts/oxe-plan-agent.prompt.md +2 -2
- package/.github/prompts/oxe-plan.prompt.md +2 -2
- package/.github/prompts/oxe-project.prompt.md +2 -2
- package/.github/prompts/oxe-quick.prompt.md +2 -2
- package/.github/prompts/oxe-research.prompt.md +2 -2
- package/.github/prompts/oxe-retro.prompt.md +2 -2
- package/.github/prompts/oxe-review-pr.prompt.md +2 -2
- package/.github/prompts/oxe-route.prompt.md +2 -2
- package/.github/prompts/oxe-scan.prompt.md +2 -2
- package/.github/prompts/oxe-security.prompt.md +2 -2
- package/.github/prompts/oxe-session.prompt.md +2 -2
- package/.github/prompts/oxe-ship.prompt.md +2 -2
- package/.github/prompts/oxe-skill.prompt.md +2 -2
- package/.github/prompts/oxe-spec.prompt.md +2 -2
- package/.github/prompts/oxe-ui-review.prompt.md +2 -2
- package/.github/prompts/oxe-ui-spec.prompt.md +2 -2
- package/.github/prompts/oxe-update.prompt.md +2 -2
- package/.github/prompts/oxe-validate-gaps.prompt.md +2 -2
- package/.github/prompts/oxe-verify.prompt.md +5 -2
- package/.github/prompts/oxe-workstream.prompt.md +2 -2
- package/.github/prompts/oxe.prompt.md +2 -2
- package/AGENTS.md +5 -3
- package/CHANGELOG.md +72 -10
- package/LICENSE +21 -674
- package/README.md +631 -535
- package/bin/banner.txt +6 -6
- package/bin/lib/oxe-agent-install.cjs +69 -69
- package/bin/lib/oxe-azure.cjs +1445 -1445
- package/bin/lib/oxe-context-engine.cjs +867 -867
- package/bin/lib/oxe-dashboard.cjs +76 -28
- package/bin/lib/oxe-operational.cjs +2144 -1340
- package/bin/lib/oxe-project-health.cjs +483 -1
- package/bin/lib/oxe-runtime-semantics.cjs +12 -0
- package/bin/oxe-cc.js +554 -152
- package/commands/oxe/ask.md +2 -2
- package/commands/oxe/capabilities.md +2 -2
- package/commands/oxe/checkpoint.md +2 -2
- package/commands/oxe/compact.md +2 -2
- package/commands/oxe/dashboard.md +2 -2
- package/commands/oxe/debug.md +2 -2
- package/commands/oxe/discuss.md +2 -2
- package/commands/oxe/execute.md +5 -2
- package/commands/oxe/forensics.md +2 -2
- package/commands/oxe/help.md +2 -2
- package/commands/oxe/loop.md +2 -2
- package/commands/oxe/milestone.md +2 -2
- package/commands/oxe/next.md +2 -2
- package/commands/oxe/obs.md +2 -2
- package/commands/oxe/oxe.md +2 -2
- package/commands/oxe/plan-agent.md +2 -2
- package/commands/oxe/plan.md +2 -2
- package/commands/oxe/project.md +2 -2
- package/commands/oxe/quick.md +2 -2
- package/commands/oxe/research.md +2 -2
- package/commands/oxe/retro.md +2 -2
- package/commands/oxe/review-pr.md +2 -2
- package/commands/oxe/route.md +2 -2
- package/commands/oxe/scan.md +2 -2
- package/commands/oxe/security.md +2 -2
- package/commands/oxe/session.md +2 -2
- package/commands/oxe/ship.md +2 -2
- package/commands/oxe/skill.md +2 -2
- package/commands/oxe/spec.md +2 -2
- package/commands/oxe/ui-review.md +2 -2
- package/commands/oxe/ui-spec.md +2 -2
- package/commands/oxe/update.md +2 -2
- package/commands/oxe/validate-gaps.md +2 -2
- package/commands/oxe/verify.md +5 -2
- package/commands/oxe/workstream.md +2 -2
- package/lib/runtime/delivery/branch-manager.d.ts +1 -0
- package/lib/runtime/delivery/branch-manager.js +7 -0
- package/lib/runtime/delivery/ci-checks.js +34 -1
- package/lib/runtime/delivery/delivery-records.d.ts +34 -0
- package/lib/runtime/delivery/delivery-records.js +48 -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 +26 -2
- package/lib/runtime/delivery/promotion-pipeline.js +111 -14
- package/lib/runtime/gate/gate-manager.d.ts +41 -0
- package/lib/runtime/gate/gate-manager.js +108 -1
- package/lib/runtime/index.d.ts +2 -2
- package/lib/runtime/index.js +3 -1
- package/lib/runtime/models/gate-decision.d.ts +4 -1
- package/lib/runtime/models/workspace.d.ts +3 -0
- package/lib/runtime/plugins/capability-adapter.d.ts +12 -0
- package/lib/runtime/plugins/capability-adapter.js +204 -0
- package/lib/runtime/plugins/capability-matrix.d.ts +5 -0
- package/lib/runtime/plugins/capability-matrix.js +48 -17
- package/lib/runtime/plugins/index.d.ts +1 -0
- package/lib/runtime/plugins/index.js +1 -0
- package/lib/runtime/plugins/plugin-abi.d.ts +2 -0
- package/lib/runtime/plugins/plugin-manifest.d.ts +1 -1
- package/lib/runtime/plugins/plugin-manifest.js +6 -2
- package/lib/runtime/plugins/plugin-registry.d.ts +46 -0
- package/lib/runtime/plugins/plugin-registry.js +79 -2
- package/lib/runtime/policy/policy-engine.d.ts +19 -0
- package/lib/runtime/policy/policy-engine.js +76 -4
- package/lib/runtime/projection/projection-engine.d.ts +9 -1
- package/lib/runtime/projection/projection-engine.js +73 -3
- package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +43 -1
- package/lib/runtime/scheduler/multi-agent-coordinator.js +151 -39
- package/lib/runtime/scheduler/run-journal.d.ts +1 -1
- package/lib/runtime/scheduler/scheduler.d.ts +19 -1
- package/lib/runtime/scheduler/scheduler.js +258 -13
- package/lib/runtime/verification/verification-compiler.d.ts +43 -0
- package/lib/runtime/verification/verification-compiler.js +137 -0
- package/lib/runtime/verification/verification-manifest.d.ts +9 -0
- package/lib/runtime/verification/verification-manifest.js +56 -6
- package/lib/runtime/workspace/strategies/ephemeral-container.d.ts +1 -0
- package/lib/runtime/workspace/strategies/ephemeral-container.js +4 -0
- package/lib/runtime/workspace/strategies/git-worktree.d.ts +1 -0
- package/lib/runtime/workspace/strategies/git-worktree.js +2 -0
- package/lib/runtime/workspace/strategies/inplace.d.ts +1 -0
- package/lib/runtime/workspace/strategies/inplace.js +2 -0
- package/lib/runtime/workspace/workspace-manager.d.ts +2 -1
- package/lib/sdk/README.md +20 -8
- package/lib/sdk/index.cjs +33 -24
- package/lib/sdk/index.d.ts +149 -14
- package/oxe/templates/ACTIVE-RUN.template.json +32 -32
- package/oxe/templates/CAPABILITIES.template.md +7 -7
- package/oxe/templates/CAPABILITY.template.md +45 -45
- package/oxe/templates/CHECKPOINTS.template.md +7 -7
- package/oxe/templates/EXECUTION-RUNTIME.template.md +68 -68
- package/oxe/templates/HYPOTHESES.template.md +33 -33
- package/oxe/templates/LESSONS-METRICS.template.json +13 -13
- package/oxe/templates/NOTES.template.md +16 -16
- package/oxe/templates/PLAN-REVIEW.template.md +31 -31
- package/oxe/templates/SESSION.template.md +34 -34
- package/oxe/templates/SKILL.template.md +26 -26
- package/oxe/templates/STATE.md +55 -55
- package/oxe/templates/WORKFLOW_AUTHORING.md +18 -18
- package/oxe/workflows/ask.md +96 -96
- package/oxe/workflows/capabilities.md +25 -25
- package/oxe/workflows/dashboard.md +33 -33
- package/oxe/workflows/discuss.md +12 -12
- package/oxe/workflows/execute.md +14 -0
- package/oxe/workflows/help.md +352 -352
- package/oxe/workflows/next.md +22 -22
- package/oxe/workflows/oxe.md +6 -6
- package/oxe/workflows/plan-agent.md +9 -9
- package/oxe/workflows/plan.md +51 -20
- package/oxe/workflows/quick.md +10 -10
- package/oxe/workflows/references/reasoning-discovery.md +28 -28
- package/oxe/workflows/references/reasoning-execution.md +29 -29
- package/oxe/workflows/references/reasoning-planning.md +32 -32
- package/oxe/workflows/references/reasoning-review.md +29 -29
- package/oxe/workflows/references/reasoning-status.md +24 -24
- package/oxe/workflows/references/robustness-elevation.md +295 -295
- package/oxe/workflows/references/workflow-runtime-contracts.json +952 -930
- package/oxe/workflows/route.md +16 -16
- package/oxe/workflows/session.md +213 -213
- package/oxe/workflows/ship.md +142 -142
- package/oxe/workflows/skill.md +44 -44
- package/oxe/workflows/ui-review.md +36 -36
- package/oxe/workflows/verify-audit.md +73 -73
- package/oxe/workflows/verify.md +10 -0
- package/package.json +92 -92
- package/packages/runtime/package.json +16 -15
- package/packages/runtime/src/audit/audit-trail.ts +243 -243
- package/packages/runtime/src/audit/index.ts +2 -2
- package/packages/runtime/src/audit/policy-pack.ts +62 -62
- package/packages/runtime/src/compiler/graph-compiler.ts +245 -245
- package/packages/runtime/src/compiler/index.ts +1 -1
- package/packages/runtime/src/context/context-pack-builder.ts +259 -259
- package/packages/runtime/src/context/context-pack-store.ts +197 -197
- package/packages/runtime/src/context/context-profiles.ts +60 -60
- package/packages/runtime/src/context/index.ts +3 -3
- package/packages/runtime/src/decision/decision-engine.ts +174 -174
- package/packages/runtime/src/decision/decision-memo.ts +211 -211
- package/packages/runtime/src/decision/index.ts +2 -2
- package/packages/runtime/src/delivery/branch-manager.ts +91 -84
- package/packages/runtime/src/delivery/ci-checks.ts +285 -252
- package/packages/runtime/src/delivery/delivery-records.ts +75 -0
- package/packages/runtime/src/delivery/index.ts +5 -4
- package/packages/runtime/src/delivery/pr-manager.ts +112 -112
- package/packages/runtime/src/delivery/promotion-pipeline.ts +334 -180
- package/packages/runtime/src/events/bus.ts +92 -92
- package/packages/runtime/src/events/catalog.ts +29 -29
- package/packages/runtime/src/events/envelope.ts +14 -14
- package/packages/runtime/src/events/index.ts +3 -3
- package/packages/runtime/src/evidence/evidence-store.ts +130 -130
- package/packages/runtime/src/evidence/index.ts +1 -1
- package/packages/runtime/src/gate/gate-manager.ts +289 -137
- package/packages/runtime/src/gate/index.ts +1 -1
- package/packages/runtime/src/index.ts +41 -37
- package/packages/runtime/src/models/attempt.ts +19 -19
- package/packages/runtime/src/models/evidence.ts +21 -21
- package/packages/runtime/src/models/gate-decision.ts +25 -21
- package/packages/runtime/src/models/index.ts +8 -8
- package/packages/runtime/src/models/run.ts +24 -24
- package/packages/runtime/src/models/session.ts +11 -11
- package/packages/runtime/src/models/verification-result.ts +10 -10
- package/packages/runtime/src/models/work-item.ts +25 -25
- package/packages/runtime/src/models/workspace.ts +31 -28
- package/packages/runtime/src/plugins/capability-adapter.ts +206 -0
- package/packages/runtime/src/plugins/capability-matrix.ts +126 -83
- package/packages/runtime/src/plugins/index.ts +5 -4
- package/packages/runtime/src/plugins/plugin-abi.ts +97 -95
- package/packages/runtime/src/plugins/plugin-manifest.ts +118 -113
- package/packages/runtime/src/plugins/plugin-registry.ts +232 -124
- package/packages/runtime/src/policy/index.ts +1 -1
- package/packages/runtime/src/policy/policy-engine.ts +330 -244
- package/packages/runtime/src/projection/index.ts +1 -1
- package/packages/runtime/src/projection/projection-engine.ts +328 -249
- package/packages/runtime/src/reducers/debug-reducer.ts +36 -36
- package/packages/runtime/src/reducers/index.ts +2 -2
- package/packages/runtime/src/reducers/run-state-reducer.ts +269 -269
- package/packages/runtime/src/scheduler/agent-registry.ts +132 -132
- package/packages/runtime/src/scheduler/agent-roles.ts +109 -109
- package/packages/runtime/src/scheduler/index.ts +4 -4
- package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +521 -333
- package/packages/runtime/src/scheduler/run-journal.ts +62 -62
- package/packages/runtime/src/scheduler/scheduler.ts +722 -441
- package/packages/runtime/src/verification/index.ts +2 -2
- package/packages/runtime/src/verification/verification-compiler.ts +436 -225
- package/packages/runtime/src/verification/verification-manifest.ts +252 -192
- package/packages/runtime/src/workspace/index.ts +5 -5
- package/packages/runtime/src/workspace/strategies/ephemeral-container.ts +126 -121
- package/packages/runtime/src/workspace/strategies/git-worktree.ts +79 -77
- package/packages/runtime/src/workspace/strategies/inplace.ts +38 -35
- package/packages/runtime/src/workspace/workspace-manager.ts +16 -15
- package/packages/runtime/tsconfig.json +17 -17
- package/vscode-extension/.vscodeignore +7 -7
- package/vscode-extension/LICENSE +21 -0
- package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
- package/vscode-extension/oxe-agents-1.4.0.vsix +0 -0
- package/vscode-extension/package.json +184 -184
- package/vscode-extension/src/extension.js +310 -310
- package/vscode-extension/src/shared/contextLoader.js +137 -137
- package/vscode-extension/src/shared/contractBuilder.js +159 -159
- package/vscode-extension/src/shared/stateReader.js +101 -101
|
@@ -1,259 +1,259 @@
|
|
|
1
|
-
import type { WorkItem } from '../models/work-item';
|
|
2
|
-
import type { Evidence } from '../models/evidence';
|
|
3
|
-
import type { RunState } from '../reducers/run-state-reducer';
|
|
4
|
-
import type { ContextProfile } from './context-profiles';
|
|
5
|
-
import type { AutonomyTier } from '../policy/policy-engine';
|
|
6
|
-
|
|
7
|
-
export interface ContextArtifact {
|
|
8
|
-
id: string;
|
|
9
|
-
kind: 'evidence' | 'lesson' | 'file' | 'summary';
|
|
10
|
-
content: string;
|
|
11
|
-
relevanceScore: number;
|
|
12
|
-
tags: string[];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface LessonMetric {
|
|
16
|
-
lesson_id: string;
|
|
17
|
-
title: string;
|
|
18
|
-
tags: string[];
|
|
19
|
-
embedding?: number[];
|
|
20
|
-
content: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface ContextPackOptions {
|
|
24
|
-
maxArtifacts?: number;
|
|
25
|
-
maxTokensEstimate?: number;
|
|
26
|
-
deduplicateThreshold?: number;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface ContextPack {
|
|
30
|
-
work_item_id: string;
|
|
31
|
-
artifacts: ContextArtifact[];
|
|
32
|
-
total_artifacts_considered: number;
|
|
33
|
-
redundancy_removed: number;
|
|
34
|
-
built_at: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// ─── Quality scoring ─────────────────────────────────────────────────────────
|
|
38
|
-
|
|
39
|
-
export interface ContextQualityScore {
|
|
40
|
-
completeness: number;
|
|
41
|
-
relevance_mean: number;
|
|
42
|
-
redundancy: number;
|
|
43
|
-
recency_score: number;
|
|
44
|
-
overall: number;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function scorePackQuality(pack: ContextPack, profile: ContextProfile): ContextQualityScore {
|
|
48
|
-
const expectedKinds = Object.keys(profile.artifact_kind_weights) as ContextArtifact['kind'][];
|
|
49
|
-
const presentKinds = new Set(pack.artifacts.map((a) => a.kind));
|
|
50
|
-
const completeness = expectedKinds.length > 0
|
|
51
|
-
? expectedKinds.filter((k) => presentKinds.has(k)).length / expectedKinds.length
|
|
52
|
-
: 0;
|
|
53
|
-
|
|
54
|
-
const relevance_mean = pack.artifacts.length > 0
|
|
55
|
-
? pack.artifacts.reduce((sum, a) => sum + a.relevanceScore, 0) / pack.artifacts.length
|
|
56
|
-
: 0;
|
|
57
|
-
|
|
58
|
-
const total = pack.total_artifacts_considered;
|
|
59
|
-
const redundancy = total > 0 ? 1 - (pack.artifacts.length / total) : 0;
|
|
60
|
-
|
|
61
|
-
const ageMs = Date.now() - new Date(pack.built_at).getTime();
|
|
62
|
-
const maxAgeMs = 24 * 60 * 60 * 1000;
|
|
63
|
-
const recency_score = Math.max(0, 1 - ageMs / maxAgeMs);
|
|
64
|
-
|
|
65
|
-
const overall = Math.min(1,
|
|
66
|
-
0.3 * completeness +
|
|
67
|
-
0.35 * relevance_mean +
|
|
68
|
-
0.1 * (1 - redundancy) +
|
|
69
|
-
0.25 * recency_score
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
completeness: Math.round(completeness * 100) / 100,
|
|
74
|
-
relevance_mean: Math.round(relevance_mean * 100) / 100,
|
|
75
|
-
redundancy: Math.round(redundancy * 100) / 100,
|
|
76
|
-
recency_score: Math.round(recency_score * 100) / 100,
|
|
77
|
-
overall: Math.round(overall * 100) / 100,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// ─── Relevance scoring ────────────────────────────────────────────────────────
|
|
82
|
-
|
|
83
|
-
function scoreEvidenceRelevance(evidence: Evidence, workItem: WorkItem): number {
|
|
84
|
-
let score = 0.5;
|
|
85
|
-
const eid = evidence.evidence_id.toLowerCase();
|
|
86
|
-
const title = workItem.title.toLowerCase();
|
|
87
|
-
const scope = workItem.mutation_scope ?? [];
|
|
88
|
-
|
|
89
|
-
if (scope.some((s) => eid.includes(s.toLowerCase()))) score += 0.3;
|
|
90
|
-
if (title.split(/\s+/).some((w) => w.length > 3 && eid.includes(w))) score += 0.1;
|
|
91
|
-
if (evidence.type === 'junit_xml') score += 0.05;
|
|
92
|
-
if (evidence.type === 'diff') score += 0.05;
|
|
93
|
-
|
|
94
|
-
return Math.min(score, 1.0);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function scoreLessonRelevance(lesson: LessonMetric, workItem: WorkItem): number {
|
|
98
|
-
const itemTags = new Set([
|
|
99
|
-
...workItem.mutation_scope.map((s) => s.toLowerCase()),
|
|
100
|
-
...workItem.title.toLowerCase().split(/\s+/).filter((w) => w.length > 3),
|
|
101
|
-
]);
|
|
102
|
-
|
|
103
|
-
const lessonTags = lesson.tags.map((t) => t.toLowerCase());
|
|
104
|
-
const overlap = lessonTags.filter((t) => itemTags.has(t)).length;
|
|
105
|
-
const jaccard = overlap / (itemTags.size + lessonTags.length - overlap || 1);
|
|
106
|
-
|
|
107
|
-
return Math.min(0.3 + jaccard * 0.7, 1.0);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// ─── Redundancy elimination ───────────────────────────────────────────────────
|
|
111
|
-
|
|
112
|
-
function cosineSimilarity(a: ContextArtifact, b: ContextArtifact): number {
|
|
113
|
-
const wordsA = new Set(a.content.toLowerCase().split(/\W+/).filter((w) => w.length > 3));
|
|
114
|
-
const wordsB = new Set(b.content.toLowerCase().split(/\W+/).filter((w) => w.length > 3));
|
|
115
|
-
if (wordsA.size === 0 || wordsB.size === 0) return 0;
|
|
116
|
-
|
|
117
|
-
let intersection = 0;
|
|
118
|
-
for (const w of wordsA) if (wordsB.has(w)) intersection++;
|
|
119
|
-
return intersection / Math.sqrt(wordsA.size * wordsB.size);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function deduplicateArtifacts(artifacts: ContextArtifact[], threshold: number): { kept: ContextArtifact[]; removed: number } {
|
|
123
|
-
const kept: ContextArtifact[] = [];
|
|
124
|
-
let removed = 0;
|
|
125
|
-
|
|
126
|
-
for (const candidate of artifacts) {
|
|
127
|
-
const isDuplicate = kept.some((existing) => cosineSimilarity(candidate, existing) >= threshold);
|
|
128
|
-
if (isDuplicate) {
|
|
129
|
-
removed++;
|
|
130
|
-
} else {
|
|
131
|
-
kept.push(candidate);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return { kept, removed };
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// ─── Token budget estimation ──────────────────────────────────────────────────
|
|
139
|
-
|
|
140
|
-
function estimateTokens(text: string): number {
|
|
141
|
-
return Math.ceil(text.length / 4);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function applyTokenBudget(artifacts: ContextArtifact[], maxTokens: number): ContextArtifact[] {
|
|
145
|
-
let used = 0;
|
|
146
|
-
const result: ContextArtifact[] = [];
|
|
147
|
-
for (const a of artifacts) {
|
|
148
|
-
const t = estimateTokens(a.content);
|
|
149
|
-
if (used + t > maxTokens) break;
|
|
150
|
-
result.push(a);
|
|
151
|
-
used += t;
|
|
152
|
-
}
|
|
153
|
-
return result;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// ─── Context Pack Builder ─────────────────────────────────────────────────────
|
|
157
|
-
|
|
158
|
-
export class ContextPackBuilder {
|
|
159
|
-
constructor(private readonly opts: ContextPackOptions = {}) {}
|
|
160
|
-
|
|
161
|
-
build(
|
|
162
|
-
workItem: WorkItem,
|
|
163
|
-
state: RunState,
|
|
164
|
-
evidenceItems: Evidence[],
|
|
165
|
-
evidenceContents: Map<string, string>,
|
|
166
|
-
lessons: LessonMetric[],
|
|
167
|
-
): ContextPack {
|
|
168
|
-
const {
|
|
169
|
-
maxArtifacts = 20,
|
|
170
|
-
maxTokensEstimate = 8000,
|
|
171
|
-
deduplicateThreshold = 0.85,
|
|
172
|
-
} = this.opts;
|
|
173
|
-
|
|
174
|
-
const raw: ContextArtifact[] = [];
|
|
175
|
-
|
|
176
|
-
// Score and collect evidence
|
|
177
|
-
for (const ev of evidenceItems) {
|
|
178
|
-
const content = evidenceContents.get(ev.evidence_id) ?? '';
|
|
179
|
-
if (!content) continue;
|
|
180
|
-
raw.push({
|
|
181
|
-
id: ev.evidence_id,
|
|
182
|
-
kind: 'evidence',
|
|
183
|
-
content,
|
|
184
|
-
relevanceScore: scoreEvidenceRelevance(ev, workItem),
|
|
185
|
-
tags: [ev.type, workItem.work_item_id],
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Score and collect lessons
|
|
190
|
-
for (const lesson of lessons) {
|
|
191
|
-
raw.push({
|
|
192
|
-
id: lesson.lesson_id,
|
|
193
|
-
kind: 'lesson',
|
|
194
|
-
content: lesson.content,
|
|
195
|
-
relevanceScore: scoreLessonRelevance(lesson, workItem),
|
|
196
|
-
tags: lesson.tags,
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Add run-level summary if available
|
|
201
|
-
const completedCount = state.completedWorkItems.size;
|
|
202
|
-
if (completedCount > 0) {
|
|
203
|
-
raw.push({
|
|
204
|
-
id: `run-summary-${workItem.run_id}`,
|
|
205
|
-
kind: 'summary',
|
|
206
|
-
content: `Run progress: ${completedCount} completed, ${state.failedWorkItems.size} failed, ${state.blockedWorkItems.size} blocked.`,
|
|
207
|
-
relevanceScore: 0.4,
|
|
208
|
-
tags: ['run-context'],
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const totalConsidered = raw.length;
|
|
213
|
-
|
|
214
|
-
// Sort by relevance descending
|
|
215
|
-
raw.sort((a, b) => b.relevanceScore - a.relevanceScore);
|
|
216
|
-
|
|
217
|
-
// Deduplicate
|
|
218
|
-
const { kept, removed } = deduplicateArtifacts(raw, deduplicateThreshold);
|
|
219
|
-
|
|
220
|
-
// Apply max artifacts cap
|
|
221
|
-
const capped = kept.slice(0, maxArtifacts);
|
|
222
|
-
|
|
223
|
-
// Apply token budget
|
|
224
|
-
const final = applyTokenBudget(capped, maxTokensEstimate);
|
|
225
|
-
|
|
226
|
-
return {
|
|
227
|
-
work_item_id: workItem.work_item_id,
|
|
228
|
-
artifacts: final,
|
|
229
|
-
total_artifacts_considered: totalConsidered,
|
|
230
|
-
redundancy_removed: removed,
|
|
231
|
-
built_at: new Date().toISOString(),
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/** Convenience: build with no evidence, just lessons and state summary */
|
|
236
|
-
buildLightweight(workItem: WorkItem, state: RunState, lessons: LessonMetric[]): ContextPack {
|
|
237
|
-
return this.build(workItem, state, [], new Map(), lessons);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Filter artifacts to those whose path-like tags are within mutation_scope.
|
|
242
|
-
* L0/L1 tiers apply the filter; L2/L3 skip it (full access).
|
|
243
|
-
*/
|
|
244
|
-
filterByMutationScope(
|
|
245
|
-
artifacts: ContextArtifact[],
|
|
246
|
-
mutationScope: string[],
|
|
247
|
-
autonomyTier: AutonomyTier
|
|
248
|
-
): ContextArtifact[] {
|
|
249
|
-
if (autonomyTier === 'L2' || autonomyTier === 'L3') return artifacts;
|
|
250
|
-
const scope = mutationScope.map((s) => s.toLowerCase());
|
|
251
|
-
return artifacts.filter((a) => {
|
|
252
|
-
const pathTags = a.tags.filter((t) => t.includes('/') || t.includes('\\'));
|
|
253
|
-
if (pathTags.length === 0) return true;
|
|
254
|
-
return pathTags.some((tag) =>
|
|
255
|
-
scope.some((s) => tag.toLowerCase().includes(s) || s.includes(tag.toLowerCase()))
|
|
256
|
-
);
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
}
|
|
1
|
+
import type { WorkItem } from '../models/work-item';
|
|
2
|
+
import type { Evidence } from '../models/evidence';
|
|
3
|
+
import type { RunState } from '../reducers/run-state-reducer';
|
|
4
|
+
import type { ContextProfile } from './context-profiles';
|
|
5
|
+
import type { AutonomyTier } from '../policy/policy-engine';
|
|
6
|
+
|
|
7
|
+
export interface ContextArtifact {
|
|
8
|
+
id: string;
|
|
9
|
+
kind: 'evidence' | 'lesson' | 'file' | 'summary';
|
|
10
|
+
content: string;
|
|
11
|
+
relevanceScore: number;
|
|
12
|
+
tags: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface LessonMetric {
|
|
16
|
+
lesson_id: string;
|
|
17
|
+
title: string;
|
|
18
|
+
tags: string[];
|
|
19
|
+
embedding?: number[];
|
|
20
|
+
content: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ContextPackOptions {
|
|
24
|
+
maxArtifacts?: number;
|
|
25
|
+
maxTokensEstimate?: number;
|
|
26
|
+
deduplicateThreshold?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ContextPack {
|
|
30
|
+
work_item_id: string;
|
|
31
|
+
artifacts: ContextArtifact[];
|
|
32
|
+
total_artifacts_considered: number;
|
|
33
|
+
redundancy_removed: number;
|
|
34
|
+
built_at: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ─── Quality scoring ─────────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
export interface ContextQualityScore {
|
|
40
|
+
completeness: number;
|
|
41
|
+
relevance_mean: number;
|
|
42
|
+
redundancy: number;
|
|
43
|
+
recency_score: number;
|
|
44
|
+
overall: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function scorePackQuality(pack: ContextPack, profile: ContextProfile): ContextQualityScore {
|
|
48
|
+
const expectedKinds = Object.keys(profile.artifact_kind_weights) as ContextArtifact['kind'][];
|
|
49
|
+
const presentKinds = new Set(pack.artifacts.map((a) => a.kind));
|
|
50
|
+
const completeness = expectedKinds.length > 0
|
|
51
|
+
? expectedKinds.filter((k) => presentKinds.has(k)).length / expectedKinds.length
|
|
52
|
+
: 0;
|
|
53
|
+
|
|
54
|
+
const relevance_mean = pack.artifacts.length > 0
|
|
55
|
+
? pack.artifacts.reduce((sum, a) => sum + a.relevanceScore, 0) / pack.artifacts.length
|
|
56
|
+
: 0;
|
|
57
|
+
|
|
58
|
+
const total = pack.total_artifacts_considered;
|
|
59
|
+
const redundancy = total > 0 ? 1 - (pack.artifacts.length / total) : 0;
|
|
60
|
+
|
|
61
|
+
const ageMs = Date.now() - new Date(pack.built_at).getTime();
|
|
62
|
+
const maxAgeMs = 24 * 60 * 60 * 1000;
|
|
63
|
+
const recency_score = Math.max(0, 1 - ageMs / maxAgeMs);
|
|
64
|
+
|
|
65
|
+
const overall = Math.min(1,
|
|
66
|
+
0.3 * completeness +
|
|
67
|
+
0.35 * relevance_mean +
|
|
68
|
+
0.1 * (1 - redundancy) +
|
|
69
|
+
0.25 * recency_score
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
completeness: Math.round(completeness * 100) / 100,
|
|
74
|
+
relevance_mean: Math.round(relevance_mean * 100) / 100,
|
|
75
|
+
redundancy: Math.round(redundancy * 100) / 100,
|
|
76
|
+
recency_score: Math.round(recency_score * 100) / 100,
|
|
77
|
+
overall: Math.round(overall * 100) / 100,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ─── Relevance scoring ────────────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
function scoreEvidenceRelevance(evidence: Evidence, workItem: WorkItem): number {
|
|
84
|
+
let score = 0.5;
|
|
85
|
+
const eid = evidence.evidence_id.toLowerCase();
|
|
86
|
+
const title = workItem.title.toLowerCase();
|
|
87
|
+
const scope = workItem.mutation_scope ?? [];
|
|
88
|
+
|
|
89
|
+
if (scope.some((s) => eid.includes(s.toLowerCase()))) score += 0.3;
|
|
90
|
+
if (title.split(/\s+/).some((w) => w.length > 3 && eid.includes(w))) score += 0.1;
|
|
91
|
+
if (evidence.type === 'junit_xml') score += 0.05;
|
|
92
|
+
if (evidence.type === 'diff') score += 0.05;
|
|
93
|
+
|
|
94
|
+
return Math.min(score, 1.0);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function scoreLessonRelevance(lesson: LessonMetric, workItem: WorkItem): number {
|
|
98
|
+
const itemTags = new Set([
|
|
99
|
+
...workItem.mutation_scope.map((s) => s.toLowerCase()),
|
|
100
|
+
...workItem.title.toLowerCase().split(/\s+/).filter((w) => w.length > 3),
|
|
101
|
+
]);
|
|
102
|
+
|
|
103
|
+
const lessonTags = lesson.tags.map((t) => t.toLowerCase());
|
|
104
|
+
const overlap = lessonTags.filter((t) => itemTags.has(t)).length;
|
|
105
|
+
const jaccard = overlap / (itemTags.size + lessonTags.length - overlap || 1);
|
|
106
|
+
|
|
107
|
+
return Math.min(0.3 + jaccard * 0.7, 1.0);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ─── Redundancy elimination ───────────────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
function cosineSimilarity(a: ContextArtifact, b: ContextArtifact): number {
|
|
113
|
+
const wordsA = new Set(a.content.toLowerCase().split(/\W+/).filter((w) => w.length > 3));
|
|
114
|
+
const wordsB = new Set(b.content.toLowerCase().split(/\W+/).filter((w) => w.length > 3));
|
|
115
|
+
if (wordsA.size === 0 || wordsB.size === 0) return 0;
|
|
116
|
+
|
|
117
|
+
let intersection = 0;
|
|
118
|
+
for (const w of wordsA) if (wordsB.has(w)) intersection++;
|
|
119
|
+
return intersection / Math.sqrt(wordsA.size * wordsB.size);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function deduplicateArtifacts(artifacts: ContextArtifact[], threshold: number): { kept: ContextArtifact[]; removed: number } {
|
|
123
|
+
const kept: ContextArtifact[] = [];
|
|
124
|
+
let removed = 0;
|
|
125
|
+
|
|
126
|
+
for (const candidate of artifacts) {
|
|
127
|
+
const isDuplicate = kept.some((existing) => cosineSimilarity(candidate, existing) >= threshold);
|
|
128
|
+
if (isDuplicate) {
|
|
129
|
+
removed++;
|
|
130
|
+
} else {
|
|
131
|
+
kept.push(candidate);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return { kept, removed };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ─── Token budget estimation ──────────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
function estimateTokens(text: string): number {
|
|
141
|
+
return Math.ceil(text.length / 4);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function applyTokenBudget(artifacts: ContextArtifact[], maxTokens: number): ContextArtifact[] {
|
|
145
|
+
let used = 0;
|
|
146
|
+
const result: ContextArtifact[] = [];
|
|
147
|
+
for (const a of artifacts) {
|
|
148
|
+
const t = estimateTokens(a.content);
|
|
149
|
+
if (used + t > maxTokens) break;
|
|
150
|
+
result.push(a);
|
|
151
|
+
used += t;
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ─── Context Pack Builder ─────────────────────────────────────────────────────
|
|
157
|
+
|
|
158
|
+
export class ContextPackBuilder {
|
|
159
|
+
constructor(private readonly opts: ContextPackOptions = {}) {}
|
|
160
|
+
|
|
161
|
+
build(
|
|
162
|
+
workItem: WorkItem,
|
|
163
|
+
state: RunState,
|
|
164
|
+
evidenceItems: Evidence[],
|
|
165
|
+
evidenceContents: Map<string, string>,
|
|
166
|
+
lessons: LessonMetric[],
|
|
167
|
+
): ContextPack {
|
|
168
|
+
const {
|
|
169
|
+
maxArtifacts = 20,
|
|
170
|
+
maxTokensEstimate = 8000,
|
|
171
|
+
deduplicateThreshold = 0.85,
|
|
172
|
+
} = this.opts;
|
|
173
|
+
|
|
174
|
+
const raw: ContextArtifact[] = [];
|
|
175
|
+
|
|
176
|
+
// Score and collect evidence
|
|
177
|
+
for (const ev of evidenceItems) {
|
|
178
|
+
const content = evidenceContents.get(ev.evidence_id) ?? '';
|
|
179
|
+
if (!content) continue;
|
|
180
|
+
raw.push({
|
|
181
|
+
id: ev.evidence_id,
|
|
182
|
+
kind: 'evidence',
|
|
183
|
+
content,
|
|
184
|
+
relevanceScore: scoreEvidenceRelevance(ev, workItem),
|
|
185
|
+
tags: [ev.type, workItem.work_item_id],
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Score and collect lessons
|
|
190
|
+
for (const lesson of lessons) {
|
|
191
|
+
raw.push({
|
|
192
|
+
id: lesson.lesson_id,
|
|
193
|
+
kind: 'lesson',
|
|
194
|
+
content: lesson.content,
|
|
195
|
+
relevanceScore: scoreLessonRelevance(lesson, workItem),
|
|
196
|
+
tags: lesson.tags,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Add run-level summary if available
|
|
201
|
+
const completedCount = state.completedWorkItems.size;
|
|
202
|
+
if (completedCount > 0) {
|
|
203
|
+
raw.push({
|
|
204
|
+
id: `run-summary-${workItem.run_id}`,
|
|
205
|
+
kind: 'summary',
|
|
206
|
+
content: `Run progress: ${completedCount} completed, ${state.failedWorkItems.size} failed, ${state.blockedWorkItems.size} blocked.`,
|
|
207
|
+
relevanceScore: 0.4,
|
|
208
|
+
tags: ['run-context'],
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const totalConsidered = raw.length;
|
|
213
|
+
|
|
214
|
+
// Sort by relevance descending
|
|
215
|
+
raw.sort((a, b) => b.relevanceScore - a.relevanceScore);
|
|
216
|
+
|
|
217
|
+
// Deduplicate
|
|
218
|
+
const { kept, removed } = deduplicateArtifacts(raw, deduplicateThreshold);
|
|
219
|
+
|
|
220
|
+
// Apply max artifacts cap
|
|
221
|
+
const capped = kept.slice(0, maxArtifacts);
|
|
222
|
+
|
|
223
|
+
// Apply token budget
|
|
224
|
+
const final = applyTokenBudget(capped, maxTokensEstimate);
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
work_item_id: workItem.work_item_id,
|
|
228
|
+
artifacts: final,
|
|
229
|
+
total_artifacts_considered: totalConsidered,
|
|
230
|
+
redundancy_removed: removed,
|
|
231
|
+
built_at: new Date().toISOString(),
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** Convenience: build with no evidence, just lessons and state summary */
|
|
236
|
+
buildLightweight(workItem: WorkItem, state: RunState, lessons: LessonMetric[]): ContextPack {
|
|
237
|
+
return this.build(workItem, state, [], new Map(), lessons);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Filter artifacts to those whose path-like tags are within mutation_scope.
|
|
242
|
+
* L0/L1 tiers apply the filter; L2/L3 skip it (full access).
|
|
243
|
+
*/
|
|
244
|
+
filterByMutationScope(
|
|
245
|
+
artifacts: ContextArtifact[],
|
|
246
|
+
mutationScope: string[],
|
|
247
|
+
autonomyTier: AutonomyTier
|
|
248
|
+
): ContextArtifact[] {
|
|
249
|
+
if (autonomyTier === 'L2' || autonomyTier === 'L3') return artifacts;
|
|
250
|
+
const scope = mutationScope.map((s) => s.toLowerCase());
|
|
251
|
+
return artifacts.filter((a) => {
|
|
252
|
+
const pathTags = a.tags.filter((t) => t.includes('/') || t.includes('\\'));
|
|
253
|
+
if (pathTags.length === 0) return true;
|
|
254
|
+
return pathTags.some((tag) =>
|
|
255
|
+
scope.some((s) => tag.toLowerCase().includes(s) || s.includes(tag.toLowerCase()))
|
|
256
|
+
);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|