oxe-cc 1.2.1 → 1.3.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/CHANGELOG.md +52 -17
- package/README.md +610 -551
- package/bin/banner.txt +1 -1
- 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 +9 -9
- 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/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 +17 -17
- 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/oxe-agents-1.0.0.vsix +0 -0
- package/vscode-extension/package.json +185 -185
- 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,36 +1,36 @@
|
|
|
1
|
-
import type { OxeEvent } from '../events/envelope';
|
|
2
|
-
import { createEmptyRunState, applyEventExported as applyEvent } from './run-state-reducer';
|
|
3
|
-
import type { RunState } from './run-state-reducer';
|
|
4
|
-
|
|
5
|
-
export interface ReplayStep {
|
|
6
|
-
index: number;
|
|
7
|
-
event: OxeEvent;
|
|
8
|
-
state: RunState;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function* stepReplay(events: OxeEvent[]): Generator<ReplayStep> {
|
|
12
|
-
let state = createEmptyRunState();
|
|
13
|
-
for (let i = 0; i < events.length; i++) {
|
|
14
|
-
state = applyEvent(state, events[i]);
|
|
15
|
-
yield { index: i, event: events[i], state };
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function replayUntil(
|
|
20
|
-
events: OxeEvent[],
|
|
21
|
-
predicate: (step: ReplayStep) => boolean
|
|
22
|
-
): ReplayStep | null {
|
|
23
|
-
for (const step of stepReplay(events)) {
|
|
24
|
-
if (predicate(step)) return step;
|
|
25
|
-
}
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function replaySlice(events: OxeEvent[], from: number, to: number): ReplayStep[] {
|
|
30
|
-
const steps: ReplayStep[] = [];
|
|
31
|
-
for (const step of stepReplay(events)) {
|
|
32
|
-
if (step.index >= from && step.index <= to) steps.push(step);
|
|
33
|
-
if (step.index > to) break;
|
|
34
|
-
}
|
|
35
|
-
return steps;
|
|
36
|
-
}
|
|
1
|
+
import type { OxeEvent } from '../events/envelope';
|
|
2
|
+
import { createEmptyRunState, applyEventExported as applyEvent } from './run-state-reducer';
|
|
3
|
+
import type { RunState } from './run-state-reducer';
|
|
4
|
+
|
|
5
|
+
export interface ReplayStep {
|
|
6
|
+
index: number;
|
|
7
|
+
event: OxeEvent;
|
|
8
|
+
state: RunState;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function* stepReplay(events: OxeEvent[]): Generator<ReplayStep> {
|
|
12
|
+
let state = createEmptyRunState();
|
|
13
|
+
for (let i = 0; i < events.length; i++) {
|
|
14
|
+
state = applyEvent(state, events[i]);
|
|
15
|
+
yield { index: i, event: events[i], state };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function replayUntil(
|
|
20
|
+
events: OxeEvent[],
|
|
21
|
+
predicate: (step: ReplayStep) => boolean
|
|
22
|
+
): ReplayStep | null {
|
|
23
|
+
for (const step of stepReplay(events)) {
|
|
24
|
+
if (predicate(step)) return step;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function replaySlice(events: OxeEvent[], from: number, to: number): ReplayStep[] {
|
|
30
|
+
const steps: ReplayStep[] = [];
|
|
31
|
+
for (const step of stepReplay(events)) {
|
|
32
|
+
if (step.index >= from && step.index <= to) steps.push(step);
|
|
33
|
+
if (step.index > to) break;
|
|
34
|
+
}
|
|
35
|
+
return steps;
|
|
36
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './run-state-reducer';
|
|
2
|
-
export * from './debug-reducer';
|
|
1
|
+
export * from './run-state-reducer';
|
|
2
|
+
export * from './debug-reducer';
|
|
@@ -1,269 +1,269 @@
|
|
|
1
|
-
import type { OxeEvent } from '../events/envelope';
|
|
2
|
-
import type { Run } from '../models/run';
|
|
3
|
-
import type { WorkItem } from '../models/work-item';
|
|
4
|
-
import type { Attempt } from '../models/attempt';
|
|
5
|
-
import type { Workspace } from '../models/workspace';
|
|
6
|
-
|
|
7
|
-
export interface PolicyDecisionRecord {
|
|
8
|
-
allowed: boolean;
|
|
9
|
-
gate_required: boolean;
|
|
10
|
-
reason: string;
|
|
11
|
-
rule_id: string | null;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface ToolFailureRecord {
|
|
15
|
-
tool: string;
|
|
16
|
-
error: string;
|
|
17
|
-
timestamp: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface RunState {
|
|
21
|
-
run: Run | null;
|
|
22
|
-
workItems: Map<string, WorkItem>;
|
|
23
|
-
attempts: Map<string, Attempt[]>;
|
|
24
|
-
workspaces: Map<string, Workspace>;
|
|
25
|
-
completedWorkItems: Set<string>;
|
|
26
|
-
failedWorkItems: Set<string>;
|
|
27
|
-
blockedWorkItems: Set<string>;
|
|
28
|
-
// Phase 1 extensions
|
|
29
|
-
retryCounts: Map<string, number>;
|
|
30
|
-
policyDecisions: Map<string, PolicyDecisionRecord>;
|
|
31
|
-
pendingGates: Set<string>;
|
|
32
|
-
resolvedGates: Map<string, { decision: string; actor?: string }>;
|
|
33
|
-
verificationStatus: Map<string, 'started' | 'completed' | 'failed'>;
|
|
34
|
-
evidenceRefs: Map<string, string[]>;
|
|
35
|
-
toolFailures: Map<string, ToolFailureRecord[]>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function createEmptyRunState(): RunState {
|
|
39
|
-
return {
|
|
40
|
-
run: null,
|
|
41
|
-
workItems: new Map(),
|
|
42
|
-
attempts: new Map(),
|
|
43
|
-
workspaces: new Map(),
|
|
44
|
-
completedWorkItems: new Set(),
|
|
45
|
-
failedWorkItems: new Set(),
|
|
46
|
-
blockedWorkItems: new Set(),
|
|
47
|
-
retryCounts: new Map(),
|
|
48
|
-
policyDecisions: new Map(),
|
|
49
|
-
pendingGates: new Set(),
|
|
50
|
-
resolvedGates: new Map(),
|
|
51
|
-
verificationStatus: new Map(),
|
|
52
|
-
evidenceRefs: new Map(),
|
|
53
|
-
toolFailures: new Map(),
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function reduce(events: OxeEvent[]): RunState {
|
|
58
|
-
return events.reduce(applyEvent, createEmptyRunState());
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Exported alias so debug-reducer can import applyEvent without circular issues
|
|
62
|
-
export { applyEvent as applyEventExported };
|
|
63
|
-
|
|
64
|
-
function applyEvent(state: RunState, event: OxeEvent): RunState {
|
|
65
|
-
switch (event.type) {
|
|
66
|
-
case 'RunStarted': {
|
|
67
|
-
const run = event.payload as unknown as Run;
|
|
68
|
-
return { ...state, run };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
case 'RunCompleted': {
|
|
72
|
-
if (!state.run) return state;
|
|
73
|
-
const status = (event.payload as { status?: Run['status'] }).status ?? 'completed';
|
|
74
|
-
return {
|
|
75
|
-
...state,
|
|
76
|
-
run: { ...state.run, status, ended_at: event.timestamp },
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
case 'WorkItemReady': {
|
|
81
|
-
if (!event.work_item_id) return state;
|
|
82
|
-
const workItems = new Map(state.workItems);
|
|
83
|
-
const existing = workItems.get(event.work_item_id);
|
|
84
|
-
if (existing) {
|
|
85
|
-
workItems.set(event.work_item_id, { ...existing, status: 'ready' });
|
|
86
|
-
} else {
|
|
87
|
-
const item = event.payload as unknown as WorkItem;
|
|
88
|
-
workItems.set(event.work_item_id, { ...item, work_item_id: event.work_item_id, status: 'ready' });
|
|
89
|
-
}
|
|
90
|
-
return { ...state, workItems };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
case 'AttemptStarted': {
|
|
94
|
-
if (!event.work_item_id || !event.attempt_id) return state;
|
|
95
|
-
const attempts = new Map(state.attempts);
|
|
96
|
-
const attempt: Attempt = {
|
|
97
|
-
attempt_id: event.attempt_id,
|
|
98
|
-
work_item_id: event.work_item_id,
|
|
99
|
-
attempt_number: (event.payload as { attempt_number?: number }).attempt_number ?? 1,
|
|
100
|
-
workspace_id: null,
|
|
101
|
-
agent_profile: null,
|
|
102
|
-
model: null,
|
|
103
|
-
started_at: event.timestamp,
|
|
104
|
-
ended_at: null,
|
|
105
|
-
outcome: null,
|
|
106
|
-
};
|
|
107
|
-
const existing = attempts.get(event.work_item_id) ?? [];
|
|
108
|
-
attempts.set(event.work_item_id, [...existing, attempt]);
|
|
109
|
-
return { ...state, attempts };
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
case 'WorkspaceAllocated': {
|
|
113
|
-
const ws = event.payload as unknown as Workspace;
|
|
114
|
-
if (!ws.workspace_id) return state;
|
|
115
|
-
const workspaces = new Map(state.workspaces);
|
|
116
|
-
workspaces.set(ws.workspace_id, { ...ws, status: 'ready' });
|
|
117
|
-
return { ...state, workspaces };
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
case 'WorkItemCompleted': {
|
|
121
|
-
if (!event.work_item_id) return state;
|
|
122
|
-
const workItems = new Map(state.workItems);
|
|
123
|
-
const item = workItems.get(event.work_item_id);
|
|
124
|
-
if (item) workItems.set(event.work_item_id, { ...item, status: 'completed' });
|
|
125
|
-
const completedWorkItems = new Set(state.completedWorkItems);
|
|
126
|
-
completedWorkItems.add(event.work_item_id);
|
|
127
|
-
// Collect evidence refs from payload
|
|
128
|
-
const evidence = (event.payload as { evidence?: string[] }).evidence ?? [];
|
|
129
|
-
if (evidence.length > 0) {
|
|
130
|
-
const evidenceRefs = new Map(state.evidenceRefs);
|
|
131
|
-
const existing = evidenceRefs.get(event.work_item_id) ?? [];
|
|
132
|
-
evidenceRefs.set(event.work_item_id, [...existing, ...evidence]);
|
|
133
|
-
return { ...state, workItems, completedWorkItems, evidenceRefs };
|
|
134
|
-
}
|
|
135
|
-
return { ...state, workItems, completedWorkItems };
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
case 'WorkItemBlocked': {
|
|
139
|
-
if (!event.work_item_id) return state;
|
|
140
|
-
const workItems = new Map(state.workItems);
|
|
141
|
-
const item = workItems.get(event.work_item_id);
|
|
142
|
-
if (item) workItems.set(event.work_item_id, { ...item, status: 'blocked' });
|
|
143
|
-
const blockedWorkItems = new Set(state.blockedWorkItems);
|
|
144
|
-
blockedWorkItems.add(event.work_item_id);
|
|
145
|
-
return { ...state, workItems, blockedWorkItems };
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
case 'RetryScheduled': {
|
|
149
|
-
if (!event.work_item_id) return state;
|
|
150
|
-
const retryCounts = new Map(state.retryCounts);
|
|
151
|
-
const current = retryCounts.get(event.work_item_id) ?? 0;
|
|
152
|
-
retryCounts.set(event.work_item_id, current + 1);
|
|
153
|
-
return { ...state, retryCounts };
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
case 'PolicyEvaluated': {
|
|
157
|
-
const p = event.payload as {
|
|
158
|
-
work_item_id?: string;
|
|
159
|
-
allowed?: boolean;
|
|
160
|
-
gate_required?: boolean;
|
|
161
|
-
reason?: string;
|
|
162
|
-
rule_id?: string | null;
|
|
163
|
-
};
|
|
164
|
-
const key = p.work_item_id ?? event.work_item_id;
|
|
165
|
-
if (!key) return state;
|
|
166
|
-
const policyDecisions = new Map(state.policyDecisions);
|
|
167
|
-
policyDecisions.set(key, {
|
|
168
|
-
allowed: p.allowed ?? true,
|
|
169
|
-
gate_required: p.gate_required ?? false,
|
|
170
|
-
reason: p.reason ?? '',
|
|
171
|
-
rule_id: p.rule_id ?? null,
|
|
172
|
-
});
|
|
173
|
-
return { ...state, policyDecisions };
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
case 'GateRequested': {
|
|
177
|
-
const gateId = (event.payload as { gate_id?: string }).gate_id;
|
|
178
|
-
if (!gateId) return state;
|
|
179
|
-
const pendingGates = new Set(state.pendingGates);
|
|
180
|
-
pendingGates.add(gateId);
|
|
181
|
-
return { ...state, pendingGates };
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
case 'GateResolved': {
|
|
185
|
-
const p = event.payload as { gate_id?: string; decision?: string; actor?: string };
|
|
186
|
-
if (!p.gate_id) return state;
|
|
187
|
-
const pendingGates = new Set(state.pendingGates);
|
|
188
|
-
pendingGates.delete(p.gate_id);
|
|
189
|
-
const resolvedGates = new Map(state.resolvedGates);
|
|
190
|
-
resolvedGates.set(p.gate_id, { decision: p.decision ?? 'approved', actor: p.actor });
|
|
191
|
-
return { ...state, pendingGates, resolvedGates };
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
case 'VerificationStarted': {
|
|
195
|
-
const key = event.work_item_id ?? (event.payload as { work_item_id?: string }).work_item_id;
|
|
196
|
-
if (!key) return state;
|
|
197
|
-
const verificationStatus = new Map(state.verificationStatus);
|
|
198
|
-
verificationStatus.set(key, 'started');
|
|
199
|
-
return { ...state, verificationStatus };
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
case 'VerificationCompleted': {
|
|
203
|
-
const p = event.payload as { work_item_id?: string; status?: 'completed' | 'failed' };
|
|
204
|
-
const key = event.work_item_id ?? p.work_item_id;
|
|
205
|
-
if (!key) return state;
|
|
206
|
-
const verificationStatus = new Map(state.verificationStatus);
|
|
207
|
-
verificationStatus.set(key, p.status ?? 'completed');
|
|
208
|
-
return { ...state, verificationStatus };
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
case 'ToolFailed': {
|
|
212
|
-
if (!event.work_item_id) return state;
|
|
213
|
-
const p = event.payload as { tool?: string; error?: string };
|
|
214
|
-
const toolFailures = new Map(state.toolFailures);
|
|
215
|
-
const existing = toolFailures.get(event.work_item_id) ?? [];
|
|
216
|
-
toolFailures.set(event.work_item_id, [
|
|
217
|
-
...existing,
|
|
218
|
-
{ tool: p.tool ?? 'unknown', error: p.error ?? '', timestamp: event.timestamp },
|
|
219
|
-
]);
|
|
220
|
-
return { ...state, toolFailures };
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
case 'EvidenceCollected': {
|
|
224
|
-
const p = event.payload as { work_item_id?: string; refs?: string[]; ref?: string };
|
|
225
|
-
const key = event.work_item_id ?? p.work_item_id;
|
|
226
|
-
if (!key) return state;
|
|
227
|
-
const refs = p.refs ?? (p.ref ? [p.ref] : []);
|
|
228
|
-
if (refs.length === 0) return state;
|
|
229
|
-
const evidenceRefs = new Map(state.evidenceRefs);
|
|
230
|
-
const existing = evidenceRefs.get(key) ?? [];
|
|
231
|
-
evidenceRefs.set(key, [...existing, ...refs]);
|
|
232
|
-
return { ...state, evidenceRefs };
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
default:
|
|
236
|
-
return state;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
export function getWorkItemStatus(
|
|
241
|
-
state: RunState,
|
|
242
|
-
workItemId: string
|
|
243
|
-
): WorkItem['status'] | null {
|
|
244
|
-
return state.workItems.get(workItemId)?.status ?? null;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
export function getAttemptCount(state: RunState, workItemId: string): number {
|
|
248
|
-
return state.attempts.get(workItemId)?.length ?? 0;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
export function getRetryCount(state: RunState, workItemId: string): number {
|
|
252
|
-
return state.retryCounts.get(workItemId) ?? 0;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
export function getPolicyDecision(state: RunState, workItemId: string): PolicyDecisionRecord | null {
|
|
256
|
-
return state.policyDecisions.get(workItemId) ?? null;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
export function getVerificationStatus(state: RunState, workItemId: string): 'started' | 'completed' | 'failed' | null {
|
|
260
|
-
return state.verificationStatus.get(workItemId) ?? null;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
export function getEvidenceRefs(state: RunState, workItemId: string): string[] {
|
|
264
|
-
return state.evidenceRefs.get(workItemId) ?? [];
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
export function getToolFailures(state: RunState, workItemId: string): ToolFailureRecord[] {
|
|
268
|
-
return state.toolFailures.get(workItemId) ?? [];
|
|
269
|
-
}
|
|
1
|
+
import type { OxeEvent } from '../events/envelope';
|
|
2
|
+
import type { Run } from '../models/run';
|
|
3
|
+
import type { WorkItem } from '../models/work-item';
|
|
4
|
+
import type { Attempt } from '../models/attempt';
|
|
5
|
+
import type { Workspace } from '../models/workspace';
|
|
6
|
+
|
|
7
|
+
export interface PolicyDecisionRecord {
|
|
8
|
+
allowed: boolean;
|
|
9
|
+
gate_required: boolean;
|
|
10
|
+
reason: string;
|
|
11
|
+
rule_id: string | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ToolFailureRecord {
|
|
15
|
+
tool: string;
|
|
16
|
+
error: string;
|
|
17
|
+
timestamp: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface RunState {
|
|
21
|
+
run: Run | null;
|
|
22
|
+
workItems: Map<string, WorkItem>;
|
|
23
|
+
attempts: Map<string, Attempt[]>;
|
|
24
|
+
workspaces: Map<string, Workspace>;
|
|
25
|
+
completedWorkItems: Set<string>;
|
|
26
|
+
failedWorkItems: Set<string>;
|
|
27
|
+
blockedWorkItems: Set<string>;
|
|
28
|
+
// Phase 1 extensions
|
|
29
|
+
retryCounts: Map<string, number>;
|
|
30
|
+
policyDecisions: Map<string, PolicyDecisionRecord>;
|
|
31
|
+
pendingGates: Set<string>;
|
|
32
|
+
resolvedGates: Map<string, { decision: string; actor?: string }>;
|
|
33
|
+
verificationStatus: Map<string, 'started' | 'completed' | 'failed'>;
|
|
34
|
+
evidenceRefs: Map<string, string[]>;
|
|
35
|
+
toolFailures: Map<string, ToolFailureRecord[]>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function createEmptyRunState(): RunState {
|
|
39
|
+
return {
|
|
40
|
+
run: null,
|
|
41
|
+
workItems: new Map(),
|
|
42
|
+
attempts: new Map(),
|
|
43
|
+
workspaces: new Map(),
|
|
44
|
+
completedWorkItems: new Set(),
|
|
45
|
+
failedWorkItems: new Set(),
|
|
46
|
+
blockedWorkItems: new Set(),
|
|
47
|
+
retryCounts: new Map(),
|
|
48
|
+
policyDecisions: new Map(),
|
|
49
|
+
pendingGates: new Set(),
|
|
50
|
+
resolvedGates: new Map(),
|
|
51
|
+
verificationStatus: new Map(),
|
|
52
|
+
evidenceRefs: new Map(),
|
|
53
|
+
toolFailures: new Map(),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function reduce(events: OxeEvent[]): RunState {
|
|
58
|
+
return events.reduce(applyEvent, createEmptyRunState());
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Exported alias so debug-reducer can import applyEvent without circular issues
|
|
62
|
+
export { applyEvent as applyEventExported };
|
|
63
|
+
|
|
64
|
+
function applyEvent(state: RunState, event: OxeEvent): RunState {
|
|
65
|
+
switch (event.type) {
|
|
66
|
+
case 'RunStarted': {
|
|
67
|
+
const run = event.payload as unknown as Run;
|
|
68
|
+
return { ...state, run };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
case 'RunCompleted': {
|
|
72
|
+
if (!state.run) return state;
|
|
73
|
+
const status = (event.payload as { status?: Run['status'] }).status ?? 'completed';
|
|
74
|
+
return {
|
|
75
|
+
...state,
|
|
76
|
+
run: { ...state.run, status, ended_at: event.timestamp },
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
case 'WorkItemReady': {
|
|
81
|
+
if (!event.work_item_id) return state;
|
|
82
|
+
const workItems = new Map(state.workItems);
|
|
83
|
+
const existing = workItems.get(event.work_item_id);
|
|
84
|
+
if (existing) {
|
|
85
|
+
workItems.set(event.work_item_id, { ...existing, status: 'ready' });
|
|
86
|
+
} else {
|
|
87
|
+
const item = event.payload as unknown as WorkItem;
|
|
88
|
+
workItems.set(event.work_item_id, { ...item, work_item_id: event.work_item_id, status: 'ready' });
|
|
89
|
+
}
|
|
90
|
+
return { ...state, workItems };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
case 'AttemptStarted': {
|
|
94
|
+
if (!event.work_item_id || !event.attempt_id) return state;
|
|
95
|
+
const attempts = new Map(state.attempts);
|
|
96
|
+
const attempt: Attempt = {
|
|
97
|
+
attempt_id: event.attempt_id,
|
|
98
|
+
work_item_id: event.work_item_id,
|
|
99
|
+
attempt_number: (event.payload as { attempt_number?: number }).attempt_number ?? 1,
|
|
100
|
+
workspace_id: null,
|
|
101
|
+
agent_profile: null,
|
|
102
|
+
model: null,
|
|
103
|
+
started_at: event.timestamp,
|
|
104
|
+
ended_at: null,
|
|
105
|
+
outcome: null,
|
|
106
|
+
};
|
|
107
|
+
const existing = attempts.get(event.work_item_id) ?? [];
|
|
108
|
+
attempts.set(event.work_item_id, [...existing, attempt]);
|
|
109
|
+
return { ...state, attempts };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
case 'WorkspaceAllocated': {
|
|
113
|
+
const ws = event.payload as unknown as Workspace;
|
|
114
|
+
if (!ws.workspace_id) return state;
|
|
115
|
+
const workspaces = new Map(state.workspaces);
|
|
116
|
+
workspaces.set(ws.workspace_id, { ...ws, status: 'ready' });
|
|
117
|
+
return { ...state, workspaces };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
case 'WorkItemCompleted': {
|
|
121
|
+
if (!event.work_item_id) return state;
|
|
122
|
+
const workItems = new Map(state.workItems);
|
|
123
|
+
const item = workItems.get(event.work_item_id);
|
|
124
|
+
if (item) workItems.set(event.work_item_id, { ...item, status: 'completed' });
|
|
125
|
+
const completedWorkItems = new Set(state.completedWorkItems);
|
|
126
|
+
completedWorkItems.add(event.work_item_id);
|
|
127
|
+
// Collect evidence refs from payload
|
|
128
|
+
const evidence = (event.payload as { evidence?: string[] }).evidence ?? [];
|
|
129
|
+
if (evidence.length > 0) {
|
|
130
|
+
const evidenceRefs = new Map(state.evidenceRefs);
|
|
131
|
+
const existing = evidenceRefs.get(event.work_item_id) ?? [];
|
|
132
|
+
evidenceRefs.set(event.work_item_id, [...existing, ...evidence]);
|
|
133
|
+
return { ...state, workItems, completedWorkItems, evidenceRefs };
|
|
134
|
+
}
|
|
135
|
+
return { ...state, workItems, completedWorkItems };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
case 'WorkItemBlocked': {
|
|
139
|
+
if (!event.work_item_id) return state;
|
|
140
|
+
const workItems = new Map(state.workItems);
|
|
141
|
+
const item = workItems.get(event.work_item_id);
|
|
142
|
+
if (item) workItems.set(event.work_item_id, { ...item, status: 'blocked' });
|
|
143
|
+
const blockedWorkItems = new Set(state.blockedWorkItems);
|
|
144
|
+
blockedWorkItems.add(event.work_item_id);
|
|
145
|
+
return { ...state, workItems, blockedWorkItems };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
case 'RetryScheduled': {
|
|
149
|
+
if (!event.work_item_id) return state;
|
|
150
|
+
const retryCounts = new Map(state.retryCounts);
|
|
151
|
+
const current = retryCounts.get(event.work_item_id) ?? 0;
|
|
152
|
+
retryCounts.set(event.work_item_id, current + 1);
|
|
153
|
+
return { ...state, retryCounts };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
case 'PolicyEvaluated': {
|
|
157
|
+
const p = event.payload as {
|
|
158
|
+
work_item_id?: string;
|
|
159
|
+
allowed?: boolean;
|
|
160
|
+
gate_required?: boolean;
|
|
161
|
+
reason?: string;
|
|
162
|
+
rule_id?: string | null;
|
|
163
|
+
};
|
|
164
|
+
const key = p.work_item_id ?? event.work_item_id;
|
|
165
|
+
if (!key) return state;
|
|
166
|
+
const policyDecisions = new Map(state.policyDecisions);
|
|
167
|
+
policyDecisions.set(key, {
|
|
168
|
+
allowed: p.allowed ?? true,
|
|
169
|
+
gate_required: p.gate_required ?? false,
|
|
170
|
+
reason: p.reason ?? '',
|
|
171
|
+
rule_id: p.rule_id ?? null,
|
|
172
|
+
});
|
|
173
|
+
return { ...state, policyDecisions };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
case 'GateRequested': {
|
|
177
|
+
const gateId = (event.payload as { gate_id?: string }).gate_id;
|
|
178
|
+
if (!gateId) return state;
|
|
179
|
+
const pendingGates = new Set(state.pendingGates);
|
|
180
|
+
pendingGates.add(gateId);
|
|
181
|
+
return { ...state, pendingGates };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
case 'GateResolved': {
|
|
185
|
+
const p = event.payload as { gate_id?: string; decision?: string; actor?: string };
|
|
186
|
+
if (!p.gate_id) return state;
|
|
187
|
+
const pendingGates = new Set(state.pendingGates);
|
|
188
|
+
pendingGates.delete(p.gate_id);
|
|
189
|
+
const resolvedGates = new Map(state.resolvedGates);
|
|
190
|
+
resolvedGates.set(p.gate_id, { decision: p.decision ?? 'approved', actor: p.actor });
|
|
191
|
+
return { ...state, pendingGates, resolvedGates };
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
case 'VerificationStarted': {
|
|
195
|
+
const key = event.work_item_id ?? (event.payload as { work_item_id?: string }).work_item_id;
|
|
196
|
+
if (!key) return state;
|
|
197
|
+
const verificationStatus = new Map(state.verificationStatus);
|
|
198
|
+
verificationStatus.set(key, 'started');
|
|
199
|
+
return { ...state, verificationStatus };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
case 'VerificationCompleted': {
|
|
203
|
+
const p = event.payload as { work_item_id?: string; status?: 'completed' | 'failed' };
|
|
204
|
+
const key = event.work_item_id ?? p.work_item_id;
|
|
205
|
+
if (!key) return state;
|
|
206
|
+
const verificationStatus = new Map(state.verificationStatus);
|
|
207
|
+
verificationStatus.set(key, p.status ?? 'completed');
|
|
208
|
+
return { ...state, verificationStatus };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
case 'ToolFailed': {
|
|
212
|
+
if (!event.work_item_id) return state;
|
|
213
|
+
const p = event.payload as { tool?: string; error?: string };
|
|
214
|
+
const toolFailures = new Map(state.toolFailures);
|
|
215
|
+
const existing = toolFailures.get(event.work_item_id) ?? [];
|
|
216
|
+
toolFailures.set(event.work_item_id, [
|
|
217
|
+
...existing,
|
|
218
|
+
{ tool: p.tool ?? 'unknown', error: p.error ?? '', timestamp: event.timestamp },
|
|
219
|
+
]);
|
|
220
|
+
return { ...state, toolFailures };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
case 'EvidenceCollected': {
|
|
224
|
+
const p = event.payload as { work_item_id?: string; refs?: string[]; ref?: string };
|
|
225
|
+
const key = event.work_item_id ?? p.work_item_id;
|
|
226
|
+
if (!key) return state;
|
|
227
|
+
const refs = p.refs ?? (p.ref ? [p.ref] : []);
|
|
228
|
+
if (refs.length === 0) return state;
|
|
229
|
+
const evidenceRefs = new Map(state.evidenceRefs);
|
|
230
|
+
const existing = evidenceRefs.get(key) ?? [];
|
|
231
|
+
evidenceRefs.set(key, [...existing, ...refs]);
|
|
232
|
+
return { ...state, evidenceRefs };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
default:
|
|
236
|
+
return state;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export function getWorkItemStatus(
|
|
241
|
+
state: RunState,
|
|
242
|
+
workItemId: string
|
|
243
|
+
): WorkItem['status'] | null {
|
|
244
|
+
return state.workItems.get(workItemId)?.status ?? null;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function getAttemptCount(state: RunState, workItemId: string): number {
|
|
248
|
+
return state.attempts.get(workItemId)?.length ?? 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function getRetryCount(state: RunState, workItemId: string): number {
|
|
252
|
+
return state.retryCounts.get(workItemId) ?? 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export function getPolicyDecision(state: RunState, workItemId: string): PolicyDecisionRecord | null {
|
|
256
|
+
return state.policyDecisions.get(workItemId) ?? null;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export function getVerificationStatus(state: RunState, workItemId: string): 'started' | 'completed' | 'failed' | null {
|
|
260
|
+
return state.verificationStatus.get(workItemId) ?? null;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function getEvidenceRefs(state: RunState, workItemId: string): string[] {
|
|
264
|
+
return state.evidenceRefs.get(workItemId) ?? [];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function getToolFailures(state: RunState, workItemId: string): ToolFailureRecord[] {
|
|
268
|
+
return state.toolFailures.get(workItemId) ?? [];
|
|
269
|
+
}
|