@vibesdotdev/traversal 0.0.0-stage → 1.0.0-rc.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/LICENSE +18 -0
- package/README.md +2 -2
- package/dist/execution-schemas.d.ts +2373 -0
- package/dist/execution-schemas.d.ts.map +1 -0
- package/dist/execution-schemas.js +102 -0
- package/dist/execution-schemas.js.map +1 -0
- package/dist/graph-schemas.d.ts +17 -0
- package/dist/graph-schemas.d.ts.map +1 -0
- package/dist/graph-schemas.js +9 -0
- package/dist/graph-schemas.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +23 -0
- package/dist/plugin.js.map +1 -0
- package/dist/schemas.d.ts +60 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +11 -0
- package/dist/schemas.js.map +1 -0
- package/dist/strategies.d.ts +16 -0
- package/dist/strategies.d.ts.map +1 -0
- package/dist/strategies.js +76 -0
- package/dist/strategies.js.map +1 -0
- package/dist/svelte/GraphRunSection.svelte +56 -0
- package/dist/svelte/GraphRunSection.svelte.d.ts +8 -0
- package/dist/svelte/GraphRunSection.svelte.d.ts.map +1 -0
- package/dist/svelte/GraphRunView.svelte +222 -0
- package/dist/svelte/GraphRunView.svelte.d.ts +11 -0
- package/dist/svelte/GraphRunView.svelte.d.ts.map +1 -0
- package/dist/svelte/index.d.ts +3 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +2 -0
- package/dist/tracking/index.d.ts +2 -0
- package/dist/tracking/index.d.ts.map +1 -0
- package/dist/tracking/index.js +2 -0
- package/dist/tracking/index.js.map +1 -0
- package/dist/tracking/selected-traversal.d.ts +9 -0
- package/dist/tracking/selected-traversal.d.ts.map +1 -0
- package/dist/tracking/selected-traversal.js +40 -0
- package/dist/tracking/selected-traversal.js.map +1 -0
- package/dist/tracking/traversal-view.d.ts +68 -0
- package/dist/tracking/traversal-view.d.ts.map +1 -0
- package/dist/tracking/traversal-view.js +253 -0
- package/dist/tracking/traversal-view.js.map +1 -0
- package/dist/tracking-schemas.d.ts +56 -0
- package/dist/tracking-schemas.d.ts.map +1 -0
- package/dist/tracking-schemas.js +33 -0
- package/dist/tracking-schemas.js.map +1 -0
- package/package.json +86 -4
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Presents recorded traversal projections. No fetch, store, scheduler, or stamp parsing.
|
|
3
|
+
Missing observation stays unobserved. blockedBy renders only when the projection recorded it.
|
|
4
|
+
-->
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { RunEvidence } from '@vibesdotdev/runnable/svelte';
|
|
7
|
+
import type { Snippet } from 'svelte';
|
|
8
|
+
import { Button } from '@vibesdotdev/kit/components/ui/button';
|
|
9
|
+
import { Badge } from '@vibesdotdev/kit/components/ui/badge';
|
|
10
|
+
import { Card } from '@vibesdotdev/kit/components/ui/card';
|
|
11
|
+
import type {
|
|
12
|
+
TraversalNodeView,
|
|
13
|
+
TraversalRevisionView,
|
|
14
|
+
TraversalView,
|
|
15
|
+
TraversalVisitEvidence,
|
|
16
|
+
} from '../tracking/traversal-view.js';
|
|
17
|
+
|
|
18
|
+
interface Props {
|
|
19
|
+
traversals: readonly TraversalView[];
|
|
20
|
+
onselect?: (runId: string) => void;
|
|
21
|
+
drill?: Snippet<[TraversalNodeView]>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let { traversals, onselect, drill }: Props = $props();
|
|
25
|
+
let opened = $state<string | null>(null);
|
|
26
|
+
let evidenceOpen = $state<Record<string, boolean>>({});
|
|
27
|
+
|
|
28
|
+
function isBetween(stamp: TraversalVisitEvidence['stamp']): stamp is Extract<TraversalVisitEvidence['stamp'], { between: true }> {
|
|
29
|
+
return 'between' in stamp && stamp.between === true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function visitKey(record: TraversalVisitEvidence): string {
|
|
33
|
+
const stamp = record.stamp;
|
|
34
|
+
const mark = isBetween(stamp)
|
|
35
|
+
? `between:${stamp.step}:${stamp.coordinationOrdinal}`
|
|
36
|
+
: `${stamp.id}:${stamp.step}:${stamp.revision}:${stamp.attempt}`;
|
|
37
|
+
return JSON.stringify([record.run.id, mark]);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function nodeKey(traversalId: string, revision: number, nodeId: string): string {
|
|
41
|
+
return JSON.stringify([traversalId, revision, nodeId]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function panelId(traversalId: string, revision: number): string {
|
|
45
|
+
return `graph-run-${encodeURIComponent(JSON.stringify([traversalId, revision]))}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function fact(outcome: TraversalNodeView['outcome']): string {
|
|
49
|
+
if (outcome === undefined) return 'outcome unobserved';
|
|
50
|
+
if (outcome.status === 'done') return 'done';
|
|
51
|
+
if (outcome.status === 'not-done') {
|
|
52
|
+
return outcome.failure?.message ? `not-done: ${outcome.reason}; ${outcome.failure.message}` : `not-done: ${outcome.reason}`;
|
|
53
|
+
}
|
|
54
|
+
if (outcome.status === 'disputed') return `disputed: ${outcome.why}`;
|
|
55
|
+
if (outcome.cause.kind === 'dependency') return `skipped: ${outcome.reason} (dependency; blockedBy ${outcome.cause.blockedBy.join(', ')})`;
|
|
56
|
+
return `skipped: ${outcome.reason} (${outcome.cause.kind})`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function recordFact(record: TraversalVisitEvidence): string {
|
|
60
|
+
const stamp = record.stamp;
|
|
61
|
+
const where = isBetween(stamp)
|
|
62
|
+
? `coordinator step ${stamp.step} ordinal ${stamp.coordinationOrdinal}`
|
|
63
|
+
: `node ${stamp.id} step ${stamp.step} stamp revision ${stamp.revision} attempt ${stamp.attempt}`;
|
|
64
|
+
const ref = record.run.ref;
|
|
65
|
+
const reference = ref ? [ref.jobId && `job ${ref.jobId}`, ref.aiCallRunId && `ai call ${ref.aiCallRunId}`, ref.ciRunId && `ci ${ref.ciRunId}`, ref.executionReference && `execution ${ref.executionReference}`].filter(Boolean).join(', ') : '';
|
|
66
|
+
return [where, `run ${record.run.id}`, `runnable ${record.run.runnableId}`, record.run.parentRunId && `parent ${record.run.parentRunId}`, `run status ${record.run.status}`, fact(record.run.outcome), reference].filter(Boolean).join('; ');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function looseVisits(revision: TraversalRevisionView): TraversalVisitEvidence[] {
|
|
70
|
+
const attached = new Set<string>();
|
|
71
|
+
for (const step of revision.steps) for (const record of step.coordinators) attached.add(visitKey(record));
|
|
72
|
+
for (const node of revision.nodes) for (const record of node.records) attached.add(visitKey(record));
|
|
73
|
+
return revision.visits.filter((record) => !attached.has(visitKey(record)));
|
|
74
|
+
}
|
|
75
|
+
</script>
|
|
76
|
+
|
|
77
|
+
{#snippet recordRow(record: TraversalVisitEvidence)}
|
|
78
|
+
<li class="grid min-w-0 gap-2 rounded-md bg-muted/30 p-3">
|
|
79
|
+
<p class="break-words text-xs leading-relaxed text-muted-foreground">{recordFact(record)}</p>
|
|
80
|
+
{#if onselect}
|
|
81
|
+
<div class="flex flex-wrap gap-2">
|
|
82
|
+
<Button variant="outline" size="sm" type="button" onclick={() => onselect?.(record.run.id)}>Select run {record.run.id}</Button>
|
|
83
|
+
{#if record.run.parentRunId}
|
|
84
|
+
<Button variant="outline" size="sm" type="button" onclick={() => record.run.parentRunId && onselect?.(record.run.parentRunId)}>Select parent {record.run.parentRunId}</Button>
|
|
85
|
+
{/if}
|
|
86
|
+
</div>
|
|
87
|
+
{/if}
|
|
88
|
+
</li>
|
|
89
|
+
{/snippet}
|
|
90
|
+
|
|
91
|
+
{#snippet nodeCard(traversalId: string, revision: number, node: TraversalNodeView)}
|
|
92
|
+
<Card role="article" aria-label={node.node.label ?? node.node.id} data-observation={node.observation} data-outcome={node.outcome?.status} class="gap-3 rounded-lg border-l-4 px-4 py-3 data-[outcome=done]:border-l-success data-[outcome=not-done]:border-l-destructive data-[outcome=disputed]:border-l-warning data-[outcome=skipped]:border-l-muted-foreground">
|
|
93
|
+
<div class="flex flex-wrap items-start justify-between gap-2"><h5 class="text-sm font-semibold">{node.node.label ?? node.node.id}</h5><Badge variant="outline">{node.observation}</Badge></div>
|
|
94
|
+
<p>{node.node.id}{#if node.node.kind}; kind {node.node.kind}{/if}; steps {node.steps.join(', ') || 'none'}</p>
|
|
95
|
+
{#if node.observation === 'recorded'}<p>{fact(node.outcome)}</p>{/if}
|
|
96
|
+
{#if node.blockedBy !== undefined}<p>Blocked by: {node.blockedBy.length ? node.blockedBy.join(', ') : '(empty)'}</p>{/if}
|
|
97
|
+
{#if node.failure}<p role="alert">Execution: {node.failure.message} <code>{node.failure.code}</code></p>{/if}
|
|
98
|
+
{#if node.attempts.length}
|
|
99
|
+
<details><summary>Durable attempt history ({node.attempts.length})</summary>
|
|
100
|
+
<ul>{#each node.attempts as attempt}<li>Revision {attempt.revision}, attempt {attempt.attempt}; {fact(attempt.outcome)}; job {attempt.jobId ?? 'not recorded'}</li>{/each}</ul>
|
|
101
|
+
</details>
|
|
102
|
+
{/if}
|
|
103
|
+
{#if node.cohorts.length}
|
|
104
|
+
<ul aria-label="Cohorts of {node.node.id}">
|
|
105
|
+
{#each node.cohorts as cohort, index (`${node.node.id}:${index}`)}<li>cohort {cohort.join(' → ')}</li>{/each}
|
|
106
|
+
</ul>
|
|
107
|
+
{/if}
|
|
108
|
+
{#if drill}
|
|
109
|
+
<Button variant="outline" size="sm" type="button" aria-expanded={opened === nodeKey(traversalId, revision, node.node.id)} aria-controls={panelId(traversalId, revision)} onclick={() => {
|
|
110
|
+
const key = nodeKey(traversalId, revision, node.node.id);
|
|
111
|
+
opened = opened === key ? null : key;
|
|
112
|
+
}}>Details for {node.node.id}</Button>
|
|
113
|
+
{/if}
|
|
114
|
+
{#if node.records.length}
|
|
115
|
+
<ul aria-label="Attempts for {node.node.id}">
|
|
116
|
+
{#each node.records as record (visitKey(record))}{@render recordRow(record)}{/each}
|
|
117
|
+
</ul>
|
|
118
|
+
{/if}
|
|
119
|
+
</Card>
|
|
120
|
+
{/snippet}
|
|
121
|
+
|
|
122
|
+
<div class="graph-run text-sm">
|
|
123
|
+
{#if traversals.length === 0}<p>No traversals recorded.</p>{/if}
|
|
124
|
+
{#each traversals as traversal (traversal.traversalId)}
|
|
125
|
+
<section>
|
|
126
|
+
<h2 class="break-all text-base font-semibold">Traversal <code class="text-sm">{traversal.traversalId}</code></h2>
|
|
127
|
+
{#each traversal.revisions as revision (revision.revision)}
|
|
128
|
+
<section>
|
|
129
|
+
<div class="flex items-center gap-2 border-b border-border pb-3"><h3 class="text-sm font-semibold">Revision {revision.revision}</h3><Badge variant="secondary">{revision.nodes.length} nodes</Badge></div>
|
|
130
|
+
{#if revision.planAmbiguous}<p>plans ambiguous</p>{/if}
|
|
131
|
+
{#if revision.executionAmbiguous}<p role="alert">Conflicting execution records; all evidence is retained below.</p>{/if}
|
|
132
|
+
{#each revision.plans as plan (JSON.stringify([plan.owner.id, plan.artifactId]))}
|
|
133
|
+
<p>plan {plan.artifactId}; source {plan.plan.source}; strategy {plan.plan.strategy}; onFailure {plan.plan.onFailure}; owner run {plan.owner.id}; run status {plan.owner.status}</p>
|
|
134
|
+
{#if onselect}<Button variant="outline" size="sm" type="button" onclick={() => onselect?.(plan.owner.id)}>Select run {plan.owner.id}</Button>{/if}
|
|
135
|
+
{#if plan.plan.cycles.length}
|
|
136
|
+
<ul aria-label="Cycles in {plan.artifactId}">
|
|
137
|
+
{#each plan.plan.cycles as cycle, index (`${plan.artifactId}:${index}`)}<li>cycle {cycle.join(' → ')}</li>{/each}
|
|
138
|
+
</ul>
|
|
139
|
+
{/if}
|
|
140
|
+
{/each}
|
|
141
|
+
{#if revision.nodes.some((node) => node.dependencies.length > 0)}
|
|
142
|
+
<ul aria-label="Dependency edges">
|
|
143
|
+
{#each revision.nodes as node (node.node.id)}
|
|
144
|
+
{#each node.dependencies as edge (`${node.node.id}:${edge.id}`)}
|
|
145
|
+
<li>{node.node.id} depends on {edge.id}; {edge.inCohort ? 'in cohort' : 'outside cohort'}; observation {edge.observation}{#if edge.observation === 'recorded'}; {fact(edge.outcome)}{/if}</li>
|
|
146
|
+
{/each}
|
|
147
|
+
{/each}
|
|
148
|
+
</ul>
|
|
149
|
+
{/if}
|
|
150
|
+
<ol class="tiers">
|
|
151
|
+
{#each revision.steps as tier (tier.step.index)}
|
|
152
|
+
<li>
|
|
153
|
+
<h4 class="text-sm font-semibold">Step {tier.step.index}</h4>
|
|
154
|
+
<p>{revision.nodes.filter(node => node.steps.includes(tier.step.index) && node.outcome).length} of {tier.step.ids.length} outcomes recorded</p>
|
|
155
|
+
<p>{tier.step.ids.join(', ') || 'no node ids'}</p>
|
|
156
|
+
{#if tier.ambiguous}<p>coordinators ambiguous</p>{/if}
|
|
157
|
+
{#if tier.coordinators.length}
|
|
158
|
+
<ul aria-label="Coordinators for step {tier.step.index}">
|
|
159
|
+
{#each tier.coordinators as record (visitKey(record))}{@render recordRow(record)}{/each}
|
|
160
|
+
</ul>
|
|
161
|
+
{/if}
|
|
162
|
+
{#each revision.nodes.filter((node) => node.steps.includes(tier.step.index)) as node (node.node.id)}
|
|
163
|
+
{@render nodeCard(traversal.traversalId, revision.revision, node)}
|
|
164
|
+
{/each}
|
|
165
|
+
</li>
|
|
166
|
+
{/each}
|
|
167
|
+
</ol>
|
|
168
|
+
{#each revision.executions as evidence (JSON.stringify([evidence.owner.id, evidence.artifactId]))}
|
|
169
|
+
{@const evidenceKey = JSON.stringify([traversal.traversalId, revision.revision, evidence.owner.id, evidence.artifactId])}
|
|
170
|
+
<details bind:open={evidenceOpen[evidenceKey]}><summary>Recorded execution evidence · {evidence.artifactId}</summary>{#if evidenceOpen[evidenceKey]}<RunEvidence title="Recorded traversal execution" value={evidence.execution} />{/if}</details>
|
|
171
|
+
{/each}
|
|
172
|
+
{#each revision.nodes.filter((node) => node.steps.length === 0) as node (node.node.id)}
|
|
173
|
+
{@render nodeCard(traversal.traversalId, revision.revision, node)}
|
|
174
|
+
{/each}
|
|
175
|
+
{#if looseVisits(revision).length}
|
|
176
|
+
<section>
|
|
177
|
+
<h4>Visits not attached to a plan node</h4>
|
|
178
|
+
<ul>
|
|
179
|
+
{#each looseVisits(revision) as record (visitKey(record))}{@render recordRow(record)}{/each}
|
|
180
|
+
</ul>
|
|
181
|
+
</section>
|
|
182
|
+
{/if}
|
|
183
|
+
{#if drill && opened}
|
|
184
|
+
{#each revision.nodes.filter((node) => nodeKey(traversal.traversalId, revision.revision, node.node.id) === opened) as node (node.node.id)}
|
|
185
|
+
<div id={panelId(traversal.traversalId, revision.revision)}>{@render drill(node)}</div>
|
|
186
|
+
{/each}
|
|
187
|
+
{/if}
|
|
188
|
+
</section>
|
|
189
|
+
{/each}
|
|
190
|
+
{#if traversal.unmatched.length}
|
|
191
|
+
<section>
|
|
192
|
+
<h3>Unmatched records</h3>
|
|
193
|
+
<ul>
|
|
194
|
+
{#each traversal.unmatched as record (visitKey(record))}{@render recordRow(record)}{/each}
|
|
195
|
+
</ul>
|
|
196
|
+
</section>
|
|
197
|
+
{/if}
|
|
198
|
+
{#each traversal.unmatchedExecutions as evidence (JSON.stringify([evidence.owner.id, evidence.artifactId]))}
|
|
199
|
+
{@const evidenceKey = JSON.stringify([traversal.traversalId, evidence.revision, evidence.owner.id, evidence.artifactId])}
|
|
200
|
+
<details bind:open={evidenceOpen[evidenceKey]}><summary>Execution without its recorded plan · revision {evidence.revision}</summary>{#if evidenceOpen[evidenceKey]}<RunEvidence title="Recorded traversal execution" value={evidence.execution} />{/if}</details>
|
|
201
|
+
{/each}
|
|
202
|
+
</section>
|
|
203
|
+
{/each}
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
<style>
|
|
207
|
+
.graph-run, .graph-run section { display: grid; gap: 0.75rem; min-width: 0; }
|
|
208
|
+
.tiers {
|
|
209
|
+
display: grid;
|
|
210
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
|
|
211
|
+
gap: 1rem;
|
|
212
|
+
margin: 0;
|
|
213
|
+
padding: 0;
|
|
214
|
+
list-style: none;
|
|
215
|
+
}
|
|
216
|
+
ul { margin: 0; padding-left: 1.25rem; }
|
|
217
|
+
p { margin: 0; overflow-wrap: anywhere; line-height: 1.6; }
|
|
218
|
+
details { border: 1px solid var(--border); border-radius: var(--radius); padding: .75rem; }
|
|
219
|
+
summary { cursor: pointer; font-weight: 500; overflow-wrap: anywhere; }
|
|
220
|
+
summary:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
|
|
221
|
+
.tiers > li { display: grid; align-content: start; gap: .75rem; }
|
|
222
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { TraversalNodeView, TraversalView } from '../tracking/traversal-view.ts';
|
|
3
|
+
interface Props {
|
|
4
|
+
traversals: readonly TraversalView[];
|
|
5
|
+
onselect?: (runId: string) => void;
|
|
6
|
+
drill?: Snippet<[TraversalNodeView]>;
|
|
7
|
+
}
|
|
8
|
+
declare const GraphRunView: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type GraphRunView = ReturnType<typeof GraphRunView>;
|
|
10
|
+
export default GraphRunView;
|
|
11
|
+
//# sourceMappingURL=GraphRunView.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GraphRunView.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/GraphRunView.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAItC,OAAO,KAAK,EACV,iBAAiB,EAEjB,aAAa,EAEb,MAAM,+BAA+B,CAAC;AAGvC,UAAU,KAAK;IACd,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;CACrC;AAqMF,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tracking/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tracking/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RunnableClient, RunnableSnapshot, RunnableWatchSnapshot } from '@vibesdotdev/runnable';
|
|
2
|
+
import { type TraversalView } from './traversal-view.ts';
|
|
3
|
+
/** Only recorded plan evidence admits a descendant read; other selected runs need none. */
|
|
4
|
+
export declare function selectedTraversalRunId(selected: RunnableSnapshot | null): string | null;
|
|
5
|
+
/** The full selected owner supplies artifacts; record-only descendants supply visit stamps. */
|
|
6
|
+
export declare function selectedTraversalViews(selected: RunnableSnapshot | null, records: RunnableWatchSnapshot | null): readonly TraversalView[];
|
|
7
|
+
/** Own only the selected subtree subscription, including a close before admission finishes. */
|
|
8
|
+
export declare function followTraversalRecords(source: Pick<RunnableClient, 'watch'>, runId: string | null, receive: (snapshot: RunnableWatchSnapshot) => void, failed: (cause: unknown) => void): () => Promise<void>;
|
|
9
|
+
//# sourceMappingURL=selected-traversal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selected-traversal.d.ts","sourceRoot":"","sources":["../../src/tracking/selected-traversal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACrG,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAG9E,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAGvF;AAED,+FAA+F;AAC/F,wBAAgB,sBAAsB,CACrC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,EACjC,OAAO,EAAE,qBAAqB,GAAG,IAAI,GACnC,SAAS,aAAa,EAAE,CAO1B;AAED,+FAA+F;AAC/F,wBAAgB,sBAAsB,CACrC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,EACrC,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,OAAO,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,EAClD,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAC9B,MAAM,OAAO,CAAC,IAAI,CAAC,CAmBrB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { buildTraversalViews } from "./traversal-view.js";
|
|
2
|
+
import { TRAVERSAL_PLAN_ARTIFACT } from "../tracking-schemas.js";
|
|
3
|
+
/** Only recorded plan evidence admits a descendant read; other selected runs need none. */
|
|
4
|
+
export function selectedTraversalRunId(selected) {
|
|
5
|
+
return selected?.artifacts.some(artifact => artifact.artifactKind === TRAVERSAL_PLAN_ARTIFACT)
|
|
6
|
+
? selected.run.id : null;
|
|
7
|
+
}
|
|
8
|
+
/** The full selected owner supplies artifacts; record-only descendants supply visit stamps. */
|
|
9
|
+
export function selectedTraversalViews(selected, records) {
|
|
10
|
+
if (!selected)
|
|
11
|
+
return records ? buildTraversalViews(records) : [];
|
|
12
|
+
const snapshots = [selected, ...(records?.runs ?? []).filter(row => row.run.id !== selected.run.id)];
|
|
13
|
+
return buildTraversalViews(snapshots).filter(view => view.revisions.some(revision => revision.plans.some(evidence => evidence.owner.id === selected.run.id)));
|
|
14
|
+
}
|
|
15
|
+
/** Own only the selected subtree subscription, including a close before admission finishes. */
|
|
16
|
+
export function followTraversalRecords(source, runId, receive, failed) {
|
|
17
|
+
if (runId === null)
|
|
18
|
+
return async () => { };
|
|
19
|
+
let closed = false;
|
|
20
|
+
let closing;
|
|
21
|
+
const opening = source.watch({ under: runId }, snapshot => {
|
|
22
|
+
if (!closed)
|
|
23
|
+
receive(snapshot);
|
|
24
|
+
}, {
|
|
25
|
+
projection: 'records',
|
|
26
|
+
onError: cause => { if (!closed)
|
|
27
|
+
failed(cause); }
|
|
28
|
+
});
|
|
29
|
+
// Keep setup rejection handled while the view owns this asynchronous admission.
|
|
30
|
+
void opening.catch(cause => { if (!closed)
|
|
31
|
+
failed(cause); });
|
|
32
|
+
return () => {
|
|
33
|
+
if (closing)
|
|
34
|
+
return closing;
|
|
35
|
+
closed = true;
|
|
36
|
+
closing = opening.then(stop => stop());
|
|
37
|
+
return closing;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=selected-traversal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selected-traversal.js","sourceRoot":"","sources":["../../src/tracking/selected-traversal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAsB,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,2FAA2F;AAC3F,MAAM,UAAU,sBAAsB,CAAC,QAAiC;IACvE,OAAO,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,YAAY,KAAK,uBAAuB,CAAC;QAC7F,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3B,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,sBAAsB,CACrC,QAAiC,EACjC,OAAqC;IAErC,IAAI,CAAC,QAAQ;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAElE,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACrG,OAAO,mBAAmB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CACnF,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CACtE,CAAC,CAAC;AACJ,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,sBAAsB,CACrC,MAAqC,EACrC,KAAoB,EACpB,OAAkD,EAClD,MAAgC;IAEhC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;IAC1C,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,OAAkC,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,EAAE;QACzD,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC,EAAE;QACF,UAAU,EAAE,SAAS;QACrB,OAAO,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM;YAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KACjD,CAAC,CAAC;IACH,gFAAgF;IAChF,KAAK,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7D,OAAO,GAAG,EAAE;QACX,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,MAAM,GAAG,IAAI,CAAC;QACd,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC;IAChB,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { RunArtifactWrite, RunnableSnapshot, RunnableTrackedRun, RunnableWatchSnapshot, SkipCause } from '@vibesdotdev/runnable';
|
|
2
|
+
import { type TraversalPlan, type TraversalExecution, type VisitStamp } from '@vibesdotdev/traversal/schemas';
|
|
3
|
+
export type TraversalRunRef = Pick<RunnableTrackedRun, 'id' | 'runnableId' | 'status' | 'parentRunId' | 'outcome' | 'ref'>;
|
|
4
|
+
export type TraversalObservation = 'unobserved' | 'recorded' | 'ambiguous';
|
|
5
|
+
type BlockedBy = Extract<SkipCause, {
|
|
6
|
+
kind: 'dependency';
|
|
7
|
+
}>['blockedBy'];
|
|
8
|
+
export interface TraversalPlanEvidence {
|
|
9
|
+
readonly plan: TraversalPlan;
|
|
10
|
+
readonly artifactId: RunArtifactWrite['id'];
|
|
11
|
+
readonly owner: TraversalRunRef;
|
|
12
|
+
}
|
|
13
|
+
export interface TraversalExecutionEvidence {
|
|
14
|
+
readonly traversalId: TraversalPlan['traversalId'];
|
|
15
|
+
readonly revision: TraversalPlan['revision'];
|
|
16
|
+
readonly execution: TraversalExecution;
|
|
17
|
+
readonly artifactId: RunArtifactWrite['id'];
|
|
18
|
+
readonly owner: TraversalRunRef;
|
|
19
|
+
}
|
|
20
|
+
export interface TraversalVisitEvidence {
|
|
21
|
+
readonly stamp: VisitStamp;
|
|
22
|
+
readonly run: TraversalRunRef;
|
|
23
|
+
}
|
|
24
|
+
export interface TraversalDependencyEvidence {
|
|
25
|
+
readonly id: TraversalPlan['nodes'][number]['dependsOn'][number];
|
|
26
|
+
readonly inCohort: boolean;
|
|
27
|
+
readonly observation: TraversalObservation;
|
|
28
|
+
readonly outcome: RunnableTrackedRun['outcome'];
|
|
29
|
+
}
|
|
30
|
+
export interface TraversalNodeView {
|
|
31
|
+
readonly node: TraversalPlan['nodes'][number];
|
|
32
|
+
readonly steps: ReadonlyArray<TraversalPlan['steps'][number]['index']>;
|
|
33
|
+
readonly cohorts: ReadonlyArray<TraversalPlan['cycles'][number]>;
|
|
34
|
+
readonly records: readonly TraversalVisitEvidence[];
|
|
35
|
+
readonly dependencies: readonly TraversalDependencyEvidence[];
|
|
36
|
+
readonly observation: TraversalObservation;
|
|
37
|
+
/** Greatest stamp revision, then attempt, when no semantic key collides. History stays on `records`. */
|
|
38
|
+
readonly outcome: RunnableTrackedRun['outcome'];
|
|
39
|
+
/** A recorded dependency skip. Unobserved is not treated as blocked. */
|
|
40
|
+
readonly blockedBy: BlockedBy | undefined;
|
|
41
|
+
readonly attempts: TraversalExecution['attempts'][string];
|
|
42
|
+
readonly failure: TraversalExecution['failures'][string] | undefined;
|
|
43
|
+
}
|
|
44
|
+
export interface TraversalStepView {
|
|
45
|
+
readonly step: TraversalPlan['steps'][number];
|
|
46
|
+
readonly coordinators: readonly TraversalVisitEvidence[];
|
|
47
|
+
readonly ambiguous: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface TraversalRevisionView {
|
|
50
|
+
readonly revision: TraversalPlan['revision'];
|
|
51
|
+
readonly plans: readonly TraversalPlanEvidence[];
|
|
52
|
+
readonly planAmbiguous: boolean;
|
|
53
|
+
readonly nodes: readonly TraversalNodeView[];
|
|
54
|
+
readonly steps: readonly TraversalStepView[];
|
|
55
|
+
readonly visits: readonly TraversalVisitEvidence[];
|
|
56
|
+
readonly executions: readonly TraversalExecutionEvidence[];
|
|
57
|
+
readonly executionAmbiguous: boolean;
|
|
58
|
+
}
|
|
59
|
+
export interface TraversalView {
|
|
60
|
+
readonly traversalId: TraversalPlan['traversalId'];
|
|
61
|
+
readonly revisions: readonly TraversalRevisionView[];
|
|
62
|
+
readonly unmatched: readonly TraversalVisitEvidence[];
|
|
63
|
+
readonly unmatchedExecutions: readonly TraversalExecutionEvidence[];
|
|
64
|
+
}
|
|
65
|
+
/** Project watch runs, or a snapshot list, into per-traversal views. */
|
|
66
|
+
export declare function buildTraversalViews(input: RunnableWatchSnapshot | readonly RunnableSnapshot[]): readonly TraversalView[];
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=traversal-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traversal-view.d.ts","sourceRoot":"","sources":["../../src/tracking/traversal-view.ts"],"names":[],"mappings":"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"}
|