@telora/daemon 0.18.40 → 0.18.55
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/build-info.json +12 -3
- package/dist/completion/advanceability.d.ts +66 -0
- package/dist/completion/advanceability.d.ts.map +1 -0
- package/dist/completion/advanceability.js +112 -0
- package/dist/completion/advanceability.js.map +1 -0
- package/dist/completion/event.d.ts +28 -52
- package/dist/completion/event.d.ts.map +1 -1
- package/dist/completion/event.js +79 -99
- package/dist/completion/event.js.map +1 -1
- package/dist/completion/progress-snapshot.d.ts +15 -4
- package/dist/completion/progress-snapshot.d.ts.map +1 -1
- package/dist/completion/progress-snapshot.js +20 -4
- package/dist/completion/progress-snapshot.js.map +1 -1
- package/dist/completion/team-completion.d.ts.map +1 -1
- package/dist/completion/team-completion.js +32 -2
- package/dist/completion/team-completion.js.map +1 -1
- package/dist/crash-recovery.d.ts +48 -0
- package/dist/crash-recovery.d.ts.map +1 -1
- package/dist/crash-recovery.js +166 -30
- package/dist/crash-recovery.js.map +1 -1
- package/dist/delivery-advance-block.d.ts +17 -1
- package/dist/delivery-advance-block.d.ts.map +1 -1
- package/dist/delivery-advance-block.js +31 -8
- package/dist/delivery-advance-block.js.map +1 -1
- package/dist/escalation-provenance.d.ts +5 -1
- package/dist/escalation-provenance.d.ts.map +1 -1
- package/dist/escalation-provenance.js +46 -4
- package/dist/escalation-provenance.js.map +1 -1
- package/dist/focus-executor.d.ts +7 -2
- package/dist/focus-executor.d.ts.map +1 -1
- package/dist/focus-executor.js +21 -9
- package/dist/focus-executor.js.map +1 -1
- package/dist/focus-lifecycle.d.ts.map +1 -1
- package/dist/focus-lifecycle.js +20 -0
- package/dist/focus-lifecycle.js.map +1 -1
- package/dist/git-activity.d.ts +15 -0
- package/dist/git-activity.d.ts.map +1 -1
- package/dist/git-activity.js +24 -0
- package/dist/git-activity.js.map +1 -1
- package/dist/git-genesis.d.ts +100 -0
- package/dist/git-genesis.d.ts.map +1 -0
- package/dist/git-genesis.js +231 -0
- package/dist/git-genesis.js.map +1 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +28 -5
- package/dist/git.js.map +1 -1
- package/dist/loop-engine-types.d.ts +40 -0
- package/dist/loop-engine-types.d.ts.map +1 -0
- package/dist/loop-engine-types.js +11 -0
- package/dist/loop-engine-types.js.map +1 -0
- package/dist/loop-engine.d.ts +52 -0
- package/dist/loop-engine.d.ts.map +1 -1
- package/dist/loop-engine.js +91 -10
- package/dist/loop-engine.js.map +1 -1
- package/dist/loop-llm-flag.d.ts +32 -0
- package/dist/loop-llm-flag.d.ts.map +1 -0
- package/dist/loop-llm-flag.js +35 -0
- package/dist/loop-llm-flag.js.map +1 -0
- package/dist/loop-operational-block.d.ts +44 -0
- package/dist/loop-operational-block.d.ts.map +1 -0
- package/dist/loop-operational-block.js +47 -0
- package/dist/loop-operational-block.js.map +1 -0
- package/dist/merge-back-loop.d.ts.map +1 -1
- package/dist/merge-back-loop.js +1 -0
- package/dist/merge-back-loop.js.map +1 -1
- package/dist/nexus-intake.d.ts +26 -3
- package/dist/nexus-intake.d.ts.map +1 -1
- package/dist/nexus-intake.js +62 -10
- package/dist/nexus-intake.js.map +1 -1
- package/dist/output-monitor.js +5 -8
- package/dist/output-monitor.js.map +1 -1
- package/dist/prd-controller.d.ts +0 -2
- package/dist/prd-controller.d.ts.map +1 -1
- package/dist/prd-controller.js +14 -35
- package/dist/prd-controller.js.map +1 -1
- package/dist/prd-divergence.d.ts +19 -8
- package/dist/prd-divergence.d.ts.map +1 -1
- package/dist/prd-divergence.js +7 -26
- package/dist/prd-divergence.js.map +1 -1
- package/dist/prd-viability.d.ts +14 -15
- package/dist/prd-viability.d.ts.map +1 -1
- package/dist/prd-viability.js +21 -34
- package/dist/prd-viability.js.map +1 -1
- package/dist/queries/prd.d.ts +24 -2
- package/dist/queries/prd.d.ts.map +1 -1
- package/dist/queries/prd.js +17 -0
- package/dist/queries/prd.js.map +1 -1
- package/dist/queries/schemas.d.ts +28 -0
- package/dist/queries/schemas.d.ts.map +1 -1
- package/dist/queries/schemas.js +26 -0
- package/dist/queries/schemas.js.map +1 -1
- package/dist/queries/sessions.d.ts +14 -0
- package/dist/queries/sessions.d.ts.map +1 -1
- package/dist/queries/sessions.js +19 -0
- package/dist/queries/sessions.js.map +1 -1
- package/dist/queries/starter-repo.d.ts +27 -0
- package/dist/queries/starter-repo.d.ts.map +1 -0
- package/dist/queries/starter-repo.js +32 -0
- package/dist/queries/starter-repo.js.map +1 -0
- package/dist/session-lineage.d.ts +25 -0
- package/dist/session-lineage.d.ts.map +1 -1
- package/dist/session-lineage.js +23 -0
- package/dist/session-lineage.js.map +1 -1
- package/dist/session-stamp.d.ts +63 -0
- package/dist/session-stamp.d.ts.map +1 -0
- package/dist/session-stamp.js +65 -0
- package/dist/session-stamp.js.map +1 -0
- package/dist/spawner/helpers.d.ts.map +1 -1
- package/dist/spawner/helpers.js +5 -8
- package/dist/spawner/helpers.js.map +1 -1
- package/dist/supabase.d.ts +2 -2
- package/dist/supabase.d.ts.map +1 -1
- package/dist/supabase.js +1 -1
- package/dist/supabase.js.map +1 -1
- package/dist/templates/claude-md.d.ts +1 -1
- package/dist/templates/claude-md.d.ts.map +1 -1
- package/dist/templates/claude-md.js +6 -3
- package/dist/templates/claude-md.js.map +1 -1
- package/dist/types/focus.d.ts +24 -0
- package/dist/types/focus.d.ts.map +1 -1
- package/dist/types/session.d.ts +24 -0
- package/dist/types/session.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/crash-recovery-cleanup.d.ts +0 -21
- package/dist/crash-recovery-cleanup.d.ts.map +0 -1
- package/dist/crash-recovery-cleanup.js +0 -205
- package/dist/crash-recovery-cleanup.js.map +0 -1
- package/dist/crash-recovery-scan.d.ts +0 -19
- package/dist/crash-recovery-scan.d.ts.map +0 -1
- package/dist/crash-recovery-scan.js +0 -145
- package/dist/crash-recovery-scan.js.map +0 -1
- package/dist/crash-recovery-types.d.ts +0 -49
- package/dist/crash-recovery-types.d.ts.map +0 -1
- package/dist/crash-recovery-types.js +0 -13
- package/dist/crash-recovery-types.js.map +0 -1
- package/dist/prd-clearance-engine.d.ts +0 -121
- package/dist/prd-clearance-engine.d.ts.map +0 -1
- package/dist/prd-clearance-engine.js +0 -164
- package/dist/prd-clearance-engine.js.map +0 -1
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Worktree scanning for crash recovery.
|
|
3
|
-
*
|
|
4
|
-
* Parses `git worktree list` output and reconciles against DB sessions
|
|
5
|
-
* and active focuses to classify worktrees as active or orphaned.
|
|
6
|
-
*/
|
|
7
|
-
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
8
|
-
import { join, resolve } from 'node:path';
|
|
9
|
-
import { runGitSync } from './git.js';
|
|
10
|
-
import { defaultDeps } from './crash-recovery-types.js';
|
|
11
|
-
// ── Helpers ──────────────────────────────────────────────────────
|
|
12
|
-
/**
|
|
13
|
-
* Extract the focus ID prefix (last 8 hex chars) from a worktree directory name.
|
|
14
|
-
* Focus worktree directories follow: agent-{role}-{name}-{8-char-id}
|
|
15
|
-
*/
|
|
16
|
-
function extractFocusIdPrefix(dirName) {
|
|
17
|
-
const match = dirName.match(/-([0-9a-f]{8})$/);
|
|
18
|
-
return match ? match[1] : null;
|
|
19
|
-
}
|
|
20
|
-
// ── Worktree scanning ────────────────────────────────────────────
|
|
21
|
-
/**
|
|
22
|
-
* Parse `git worktree list --porcelain` to build a map of
|
|
23
|
-
* worktree path -> branch name for all registered worktrees.
|
|
24
|
-
*/
|
|
25
|
-
export function parseWorktreeList(repoPath) {
|
|
26
|
-
const result = runGitSync(['worktree', 'list', '--porcelain'], repoPath);
|
|
27
|
-
const map = new Map();
|
|
28
|
-
if (!result.success)
|
|
29
|
-
return map;
|
|
30
|
-
let currentPath = null;
|
|
31
|
-
for (const line of result.output.split('\n')) {
|
|
32
|
-
if (line.startsWith('worktree ')) {
|
|
33
|
-
currentPath = line.slice('worktree '.length);
|
|
34
|
-
}
|
|
35
|
-
else if (line.startsWith('branch refs/heads/') && currentPath) {
|
|
36
|
-
map.set(currentPath, line.slice('branch refs/heads/'.length));
|
|
37
|
-
currentPath = null;
|
|
38
|
-
}
|
|
39
|
-
else if (line === '') {
|
|
40
|
-
currentPath = null;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return map;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Scan the worktree directory and reconcile against active DB sessions
|
|
47
|
-
* to classify each worktree as active or orphaned.
|
|
48
|
-
*/
|
|
49
|
-
export async function detectOrphanedWorktrees(config, deps = defaultDeps) {
|
|
50
|
-
const { worktreeDir, repoPath } = config;
|
|
51
|
-
// 1. Read all subdirectories in worktreeDir
|
|
52
|
-
if (!existsSync(worktreeDir))
|
|
53
|
-
return [];
|
|
54
|
-
const entries = readdirSync(worktreeDir);
|
|
55
|
-
const subdirs = entries.filter((entry) => {
|
|
56
|
-
const fullPath = join(worktreeDir, entry);
|
|
57
|
-
try {
|
|
58
|
-
return statSync(fullPath).isDirectory();
|
|
59
|
-
}
|
|
60
|
-
catch (e) {
|
|
61
|
-
console.debug(`[crash-recovery] Failed to stat ${fullPath} (may have been deleted):`, e.message);
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
if (subdirs.length === 0)
|
|
66
|
-
return [];
|
|
67
|
-
// 2. Parse git worktree list to map paths -> branch names
|
|
68
|
-
const worktreeMap = parseWorktreeList(repoPath);
|
|
69
|
-
// Build a reverse lookup: resolve worktree paths so we can match
|
|
70
|
-
const pathToBranch = new Map();
|
|
71
|
-
for (const [wtPath, branch] of worktreeMap) {
|
|
72
|
-
pathToBranch.set(resolve(wtPath), branch);
|
|
73
|
-
}
|
|
74
|
-
// 3. Query active sessions from DB
|
|
75
|
-
let activeSessions = [];
|
|
76
|
-
try {
|
|
77
|
-
activeSessions = await deps.getActiveSessions();
|
|
78
|
-
}
|
|
79
|
-
catch (err) {
|
|
80
|
-
console.warn(`[crash-recovery] Failed to query active sessions from DB: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
81
|
-
`Treating all worktrees as orphaned.`);
|
|
82
|
-
}
|
|
83
|
-
// Build set of branch names with active sessions
|
|
84
|
-
const activeBranches = new Set(activeSessions.map((s) => s.branch_name));
|
|
85
|
-
// Build map of branch -> session for linking
|
|
86
|
-
const branchToSession = new Map();
|
|
87
|
-
for (const session of activeSessions) {
|
|
88
|
-
branchToSession.set(session.branch_name, session);
|
|
89
|
-
}
|
|
90
|
-
// 3b. Query active focuses to preserve persistent worktrees
|
|
91
|
-
const activeFocusIdPrefixes = new Set();
|
|
92
|
-
try {
|
|
93
|
-
const activeFocuses = await deps.getActiveFocuses(config.organizationId, config.productId);
|
|
94
|
-
for (const s of activeFocuses) {
|
|
95
|
-
activeFocusIdPrefixes.add(s.focus_id.slice(0, 8));
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
console.warn(`[crash-recovery] Failed to query active focuses: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
100
|
-
`Persistent focus worktrees may be incorrectly classified as orphaned.`);
|
|
101
|
-
}
|
|
102
|
-
// 4. Classify each worktree subdirectory
|
|
103
|
-
const orphans = [];
|
|
104
|
-
for (const subdir of subdirs) {
|
|
105
|
-
const fullPath = resolve(join(worktreeDir, subdir));
|
|
106
|
-
const branchName = pathToBranch.get(fullPath);
|
|
107
|
-
if (!branchName) {
|
|
108
|
-
// Directory exists but no git worktree entry -- likely a stale directory.
|
|
109
|
-
// Check if it belongs to an active focus before classifying as orphan.
|
|
110
|
-
const idPrefix = extractFocusIdPrefix(subdir);
|
|
111
|
-
if (idPrefix && activeFocusIdPrefixes.has(idPrefix)) {
|
|
112
|
-
console.log(`[crash-recovery] Worktree belongs to active focus (persistent, no git entry): ${fullPath}`);
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
// Try to infer branch from directory name (agent-role-delivery pattern).
|
|
116
|
-
console.log(`[crash-recovery] Worktree directory has no git entry: ${fullPath}`);
|
|
117
|
-
orphans.push({
|
|
118
|
-
worktreePath: fullPath,
|
|
119
|
-
branchName: subdir.replace(/-/g, '/').replace(/^agent\//, 'agent/'),
|
|
120
|
-
session: null,
|
|
121
|
-
});
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
if (activeBranches.has(branchName)) {
|
|
125
|
-
// Active session exists -- leave alone
|
|
126
|
-
console.log(`[crash-recovery] Worktree is active (has DB session): ${fullPath} [${branchName}]`);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
// Check if this worktree belongs to an active focus (persistent worktree)
|
|
130
|
-
const idPrefix = extractFocusIdPrefix(subdir);
|
|
131
|
-
if (idPrefix && activeFocusIdPrefixes.has(idPrefix)) {
|
|
132
|
-
console.log(`[crash-recovery] Worktree belongs to active focus (persistent): ${fullPath} [${branchName}]`);
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
// No active session and no active focus -- orphaned
|
|
136
|
-
const session = branchToSession.get(branchName) ?? null;
|
|
137
|
-
orphans.push({
|
|
138
|
-
worktreePath: fullPath,
|
|
139
|
-
branchName,
|
|
140
|
-
session,
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
return orphans;
|
|
144
|
-
}
|
|
145
|
-
//# sourceMappingURL=crash-recovery-scan.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crash-recovery-scan.js","sourceRoot":"","sources":["../src/crash-recovery-scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Types and dependency injection for crash recovery.
|
|
3
|
-
*/
|
|
4
|
-
import type { AgentSession } from './types.js';
|
|
5
|
-
import { type CreateEscalationParams } from './queries/issues.js';
|
|
6
|
-
export interface OrphanedWorktree {
|
|
7
|
-
/** Absolute path to the worktree directory. */
|
|
8
|
-
worktreePath: string;
|
|
9
|
-
/** Git branch name (e.g. agent/developer/my-delivery). */
|
|
10
|
-
branchName: string;
|
|
11
|
-
/** DB session that was still marked active, if any. */
|
|
12
|
-
session: AgentSession | null;
|
|
13
|
-
}
|
|
14
|
-
export interface CleanupAction {
|
|
15
|
-
worktreePath: string;
|
|
16
|
-
branchName: string;
|
|
17
|
-
action: 'removed' | 'preserved' | 'safety-committed' | 'safety-committed-and-removed';
|
|
18
|
-
/** Set when a safety commit was created. */
|
|
19
|
-
commitHash?: string;
|
|
20
|
-
/** Set when the orphan was preserved due to unmerged commits. */
|
|
21
|
-
unmergedCommitCount?: number;
|
|
22
|
-
}
|
|
23
|
-
export interface RecoveryResult {
|
|
24
|
-
orphansDetected: number;
|
|
25
|
-
orphansCleaned: number;
|
|
26
|
-
orphansPreserved: number;
|
|
27
|
-
branchesPruned: number;
|
|
28
|
-
branchesPreserved: number;
|
|
29
|
-
actions: CleanupAction[];
|
|
30
|
-
errors: string[];
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Injectable dependencies for testing.
|
|
34
|
-
* Production code uses the defaults (real DB queries).
|
|
35
|
-
*/
|
|
36
|
-
export interface RecoveryDeps {
|
|
37
|
-
getActiveSessions: () => Promise<AgentSession[]>;
|
|
38
|
-
getActiveFocuses: (organizationId: string, productId?: string) => Promise<Array<{
|
|
39
|
-
focus_id: string;
|
|
40
|
-
focus_name: string;
|
|
41
|
-
assigned_agent_role_id: string | null;
|
|
42
|
-
}>>;
|
|
43
|
-
updateSession: (sessionId: string, updates: Record<string, unknown>) => Promise<unknown>;
|
|
44
|
-
createEscalation: (params: CreateEscalationParams) => Promise<{
|
|
45
|
-
escalationId: string | null;
|
|
46
|
-
} | void>;
|
|
47
|
-
}
|
|
48
|
-
export declare const defaultDeps: RecoveryDeps;
|
|
49
|
-
//# sourceMappingURL=crash-recovery-types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crash-recovery-types.d.ts","sourceRoot":"","sources":["../src/crash-recovery-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAoB,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAKpF,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,kBAAkB,GAAG,8BAA8B,CAAC;IACtF,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACjD,gBAAgB,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC,CAAC;IAClK,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzF,gBAAgB,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CACvG;AAED,eAAO,MAAM,WAAW,EAAE,YAKzB,CAAC"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Types and dependency injection for crash recovery.
|
|
3
|
-
*/
|
|
4
|
-
import { getActiveSessions, updateSession } from './queries/sessions.js';
|
|
5
|
-
import { createEscalation } from './queries/issues.js';
|
|
6
|
-
import { getActiveFocuses } from './queries/deliveries.js';
|
|
7
|
-
export const defaultDeps = {
|
|
8
|
-
getActiveSessions,
|
|
9
|
-
getActiveFocuses,
|
|
10
|
-
updateSession: (id, updates) => updateSession(id, updates),
|
|
11
|
-
createEscalation,
|
|
12
|
-
};
|
|
13
|
-
//# sourceMappingURL=crash-recovery-types.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crash-recovery-types.js","sourceRoot":"","sources":["../src/crash-recovery-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAA+B,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AA4C3D,MAAM,CAAC,MAAM,WAAW,GAAiB;IACvC,iBAAiB;IACjB,gBAAgB;IAChB,aAAa,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,OAA8C,CAAC;IACjG,gBAAgB;CACjB,CAAC"}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PRD obstacle clearance predicate engine -- Staged Assembly: PRD Layer.
|
|
3
|
-
*
|
|
4
|
-
* This module lifts the per-delivery verification engine one altitude up to the
|
|
5
|
-
* PRD Prerequisite Tree (PRT) obstacle. Where `verification-engine.ts` answers
|
|
6
|
-
* "is this delivery's injection cleared?", this answers "is this milestone's
|
|
7
|
-
* obstacle cleared?" -- and, in aggregate, "is the whole milestone complete?".
|
|
8
|
-
*
|
|
9
|
-
* The clearance predicate is BOTH the completion signal AND the divergence
|
|
10
|
-
* detector: a PRD (milestone) is done exactly when every obstacle's verifiable
|
|
11
|
-
* clearance predicate passes. (UDE #4 -> desired effect: milestone completion
|
|
12
|
-
* is computable.)
|
|
13
|
-
*
|
|
14
|
-
* Design constraints (delivery C):
|
|
15
|
-
* - PURE. No DB access, no reality-tree writes, no module-level mutable state.
|
|
16
|
-
* The caller fetches obstacles (from `prd_prt_nodes.clearance_predicate`) and
|
|
17
|
-
* passes them in; this module only computes verdicts.
|
|
18
|
-
* - Command execution is INJECTED via `ClearanceContext.runCommand` so tests
|
|
19
|
-
* never shell out. A `defaultRunCommand` is provided for real callers and
|
|
20
|
-
* mirrors `verification-engine.runDeterministicStrategy` (spawn `sh -c`, tail
|
|
21
|
-
* output at 4000 chars, exit 0 = pass) -- but returns the raw triple rather
|
|
22
|
-
* than a StrategyResult, keeping this module side-effect-light.
|
|
23
|
-
* - NO daemon-loop wiring here. Wiring into the focus/verification loop is a
|
|
24
|
-
* later delivery (D).
|
|
25
|
-
*
|
|
26
|
-
* Predicate kinds mirror the verification engine's strategy taxonomy:
|
|
27
|
-
* deterministic -- run shell checks; all exit 0 => cleared.
|
|
28
|
-
* behavioral -- runtime telemetry observation (deferred; no signal source).
|
|
29
|
-
* ai_inspection -- AI reads code/state and decides (deferred; no driver).
|
|
30
|
-
* human -- a human attests clearance (deferred; out of band).
|
|
31
|
-
*
|
|
32
|
-
* @module prd-clearance-engine
|
|
33
|
-
*/
|
|
34
|
-
/** The kinds of clearance predicate, mirroring verification strategy methods. */
|
|
35
|
-
export type ClearanceKind = 'deterministic' | 'behavioral' | 'ai_inspection' | 'human';
|
|
36
|
-
/** A single deterministic shell check within a predicate. */
|
|
37
|
-
export interface ClearanceCheck {
|
|
38
|
-
cmd: string;
|
|
39
|
-
label?: string;
|
|
40
|
-
}
|
|
41
|
-
/** An obstacle's verifiable clearance predicate (shape of `clearance_predicate`). */
|
|
42
|
-
export interface ClearancePredicate {
|
|
43
|
-
kind: ClearanceKind;
|
|
44
|
-
checks?: ClearanceCheck[];
|
|
45
|
-
}
|
|
46
|
-
/** Outcome of running one deterministic check. */
|
|
47
|
-
export interface ClearanceCheckResult {
|
|
48
|
-
cmd: string;
|
|
49
|
-
exitCode: number | null;
|
|
50
|
-
passed: boolean;
|
|
51
|
-
}
|
|
52
|
-
/** The verdict for a single obstacle's predicate. */
|
|
53
|
-
export interface ClearanceVerdict {
|
|
54
|
-
kind: ClearanceKind;
|
|
55
|
-
/** True only when the predicate is computable AND every check passed. */
|
|
56
|
-
cleared: boolean;
|
|
57
|
-
/** True when the predicate kind has no automatic signal source (deferred). */
|
|
58
|
-
deferred: boolean;
|
|
59
|
-
/** Human-readable summary of how the verdict was reached. */
|
|
60
|
-
evidence: string;
|
|
61
|
-
/** Populated for deterministic predicates; one entry per check run. */
|
|
62
|
-
checkResults?: ClearanceCheckResult[];
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Injected command runner. Mirrors the spawn semantics of
|
|
66
|
-
* `verification-engine.runDeterministicStrategy` but returns the raw triple so
|
|
67
|
-
* this module stays free of StrategyResult/outcome coupling.
|
|
68
|
-
*/
|
|
69
|
-
export type RunCommand = (cmd: string, cwd: string) => Promise<{
|
|
70
|
-
exitCode: number | null;
|
|
71
|
-
stdoutTail: string;
|
|
72
|
-
stderrTail: string;
|
|
73
|
-
}>;
|
|
74
|
-
/** Evaluation context: where to run, and (optionally) how to run. */
|
|
75
|
-
export interface ClearanceContext {
|
|
76
|
-
worktreeDir: string;
|
|
77
|
-
/** Defaults to `defaultRunCommand` when omitted. Tests inject a fake. */
|
|
78
|
-
runCommand?: RunCommand;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Real shell runner: spawn `sh -c <cmd>` in `cwd`, capture stdout/stderr tailed
|
|
82
|
-
* to 4000 chars, resolve `{ exitCode, stdoutTail, stderrTail }`. A spawn error
|
|
83
|
-
* resolves with `exitCode: null` (treated as a non-pass by callers). Mirrors
|
|
84
|
-
* `verification-engine.runDeterministicStrategy` but returns the raw triple.
|
|
85
|
-
*/
|
|
86
|
-
export declare const defaultRunCommand: RunCommand;
|
|
87
|
-
/**
|
|
88
|
-
* Evaluate a single obstacle's clearance predicate. PURE.
|
|
89
|
-
*
|
|
90
|
-
* - deterministic: run each check via `ctx.runCommand ?? defaultRunCommand`.
|
|
91
|
-
* exit 0 = passed. All pass => cleared. No checks (undefined/empty) =>
|
|
92
|
-
* not cleared, not deferred (a deterministic predicate with nothing to check
|
|
93
|
-
* cannot assert clearance).
|
|
94
|
-
* - behavioral | ai_inspection | human: deferred (cleared:false, deferred:true);
|
|
95
|
-
* evidence names the deferral reason.
|
|
96
|
-
*/
|
|
97
|
-
export declare function evaluateClearance(predicate: ClearancePredicate, ctx: ClearanceContext): Promise<ClearanceVerdict>;
|
|
98
|
-
/**
|
|
99
|
-
* Aggregate clearance across all obstacles of a PRT -- the "milestone
|
|
100
|
-
* completion is computable" primitive. PURE; the caller fetches the obstacles
|
|
101
|
-
* (each carrying its `clearance_predicate`).
|
|
102
|
-
*
|
|
103
|
-
* - `allCleared` is true only when there is at least one obstacle AND every
|
|
104
|
-
* obstacle's verdict is cleared. (An empty obstacle set cannot assert a
|
|
105
|
-
* complete milestone.)
|
|
106
|
-
* - `deferredCount` counts obstacles whose predicate could not be evaluated
|
|
107
|
-
* automatically -- these block `allCleared` and flag where human/AI signal
|
|
108
|
-
* is still required.
|
|
109
|
-
*/
|
|
110
|
-
export declare function evaluatePrtClearance(obstacles: {
|
|
111
|
-
nodeId: string;
|
|
112
|
-
predicate: ClearancePredicate;
|
|
113
|
-
}[], ctx: ClearanceContext): Promise<{
|
|
114
|
-
nodeVerdicts: {
|
|
115
|
-
nodeId: string;
|
|
116
|
-
verdict: ClearanceVerdict;
|
|
117
|
-
}[];
|
|
118
|
-
allCleared: boolean;
|
|
119
|
-
deferredCount: number;
|
|
120
|
-
}>;
|
|
121
|
-
//# sourceMappingURL=prd-clearance-engine.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prd-clearance-engine.d.ts","sourceRoot":"","sources":["../src/prd-clearance-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAWH,iFAAiF;AACjF,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,YAAY,GAAG,eAAe,GAAG,OAAO,CAAC;AAEvF,6DAA6D;AAC7D,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qFAAqF;AACrF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,CAAC,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED,kDAAkD;AAClD,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,qDAAqD;AACrD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,yEAAyE;IACzE,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,QAAQ,EAAE,OAAO,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACvC;AAED;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,CACvB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,KACR,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAElF,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAMD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAsC/B,CAAC;AAYF;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,kBAAkB,EAC7B,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA4C3B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,kBAAkB,CAAA;CAAE,EAAE,EAC9D,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC;IACT,YAAY,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,gBAAgB,CAAA;KAAE,EAAE,CAAC;IAC9D,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAWD"}
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PRD obstacle clearance predicate engine -- Staged Assembly: PRD Layer.
|
|
3
|
-
*
|
|
4
|
-
* This module lifts the per-delivery verification engine one altitude up to the
|
|
5
|
-
* PRD Prerequisite Tree (PRT) obstacle. Where `verification-engine.ts` answers
|
|
6
|
-
* "is this delivery's injection cleared?", this answers "is this milestone's
|
|
7
|
-
* obstacle cleared?" -- and, in aggregate, "is the whole milestone complete?".
|
|
8
|
-
*
|
|
9
|
-
* The clearance predicate is BOTH the completion signal AND the divergence
|
|
10
|
-
* detector: a PRD (milestone) is done exactly when every obstacle's verifiable
|
|
11
|
-
* clearance predicate passes. (UDE #4 -> desired effect: milestone completion
|
|
12
|
-
* is computable.)
|
|
13
|
-
*
|
|
14
|
-
* Design constraints (delivery C):
|
|
15
|
-
* - PURE. No DB access, no reality-tree writes, no module-level mutable state.
|
|
16
|
-
* The caller fetches obstacles (from `prd_prt_nodes.clearance_predicate`) and
|
|
17
|
-
* passes them in; this module only computes verdicts.
|
|
18
|
-
* - Command execution is INJECTED via `ClearanceContext.runCommand` so tests
|
|
19
|
-
* never shell out. A `defaultRunCommand` is provided for real callers and
|
|
20
|
-
* mirrors `verification-engine.runDeterministicStrategy` (spawn `sh -c`, tail
|
|
21
|
-
* output at 4000 chars, exit 0 = pass) -- but returns the raw triple rather
|
|
22
|
-
* than a StrategyResult, keeping this module side-effect-light.
|
|
23
|
-
* - NO daemon-loop wiring here. Wiring into the focus/verification loop is a
|
|
24
|
-
* later delivery (D).
|
|
25
|
-
*
|
|
26
|
-
* Predicate kinds mirror the verification engine's strategy taxonomy:
|
|
27
|
-
* deterministic -- run shell checks; all exit 0 => cleared.
|
|
28
|
-
* behavioral -- runtime telemetry observation (deferred; no signal source).
|
|
29
|
-
* ai_inspection -- AI reads code/state and decides (deferred; no driver).
|
|
30
|
-
* human -- a human attests clearance (deferred; out of band).
|
|
31
|
-
*
|
|
32
|
-
* @module prd-clearance-engine
|
|
33
|
-
*/
|
|
34
|
-
import { spawn } from 'node:child_process';
|
|
35
|
-
const DEFAULT_CLEARANCE_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
36
|
-
const OUTPUT_TAIL_MAX = 4000;
|
|
37
|
-
// ---------------------------------------------------------------------------
|
|
38
|
-
// Default command runner (mirrors runDeterministicStrategy)
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
/**
|
|
41
|
-
* Real shell runner: spawn `sh -c <cmd>` in `cwd`, capture stdout/stderr tailed
|
|
42
|
-
* to 4000 chars, resolve `{ exitCode, stdoutTail, stderrTail }`. A spawn error
|
|
43
|
-
* resolves with `exitCode: null` (treated as a non-pass by callers). Mirrors
|
|
44
|
-
* `verification-engine.runDeterministicStrategy` but returns the raw triple.
|
|
45
|
-
*/
|
|
46
|
-
export const defaultRunCommand = (cmd, cwd) => {
|
|
47
|
-
return new Promise((resolve) => {
|
|
48
|
-
const child = spawn('sh', ['-c', cmd], {
|
|
49
|
-
cwd,
|
|
50
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
51
|
-
});
|
|
52
|
-
let stdout = '';
|
|
53
|
-
let stderr = '';
|
|
54
|
-
const tail = (buf, max = OUTPUT_TAIL_MAX) => buf.length <= max ? buf : buf.slice(buf.length - max);
|
|
55
|
-
child.stdout?.on('data', (chunk) => {
|
|
56
|
-
stdout += chunk.toString('utf8');
|
|
57
|
-
stdout = tail(stdout);
|
|
58
|
-
});
|
|
59
|
-
child.stderr?.on('data', (chunk) => {
|
|
60
|
-
stderr += chunk.toString('utf8');
|
|
61
|
-
stderr = tail(stderr);
|
|
62
|
-
});
|
|
63
|
-
const timer = setTimeout(() => {
|
|
64
|
-
try {
|
|
65
|
-
child.kill('SIGKILL');
|
|
66
|
-
}
|
|
67
|
-
catch { /* ignore */ }
|
|
68
|
-
}, DEFAULT_CLEARANCE_TIMEOUT_MS);
|
|
69
|
-
child.on('error', (err) => {
|
|
70
|
-
clearTimeout(timer);
|
|
71
|
-
resolve({
|
|
72
|
-
exitCode: null,
|
|
73
|
-
stdoutTail: stdout,
|
|
74
|
-
stderrTail: tail(`${stderr}\n${err.message}`),
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
child.on('close', (code) => {
|
|
78
|
-
clearTimeout(timer);
|
|
79
|
-
resolve({ exitCode: code, stdoutTail: stdout, stderrTail: stderr });
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
};
|
|
83
|
-
// ---------------------------------------------------------------------------
|
|
84
|
-
// Evaluation
|
|
85
|
-
// ---------------------------------------------------------------------------
|
|
86
|
-
const DEFERRAL_REASON = {
|
|
87
|
-
behavioral: 'behavioral clearance deferred -- no runtime telemetry source wired',
|
|
88
|
-
ai_inspection: 'ai_inspection clearance deferred -- no AI inspection driver wired',
|
|
89
|
-
human: 'human clearance deferred -- requires out-of-band human attestation',
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* Evaluate a single obstacle's clearance predicate. PURE.
|
|
93
|
-
*
|
|
94
|
-
* - deterministic: run each check via `ctx.runCommand ?? defaultRunCommand`.
|
|
95
|
-
* exit 0 = passed. All pass => cleared. No checks (undefined/empty) =>
|
|
96
|
-
* not cleared, not deferred (a deterministic predicate with nothing to check
|
|
97
|
-
* cannot assert clearance).
|
|
98
|
-
* - behavioral | ai_inspection | human: deferred (cleared:false, deferred:true);
|
|
99
|
-
* evidence names the deferral reason.
|
|
100
|
-
*/
|
|
101
|
-
export async function evaluateClearance(predicate, ctx) {
|
|
102
|
-
if (predicate.kind !== 'deterministic') {
|
|
103
|
-
return {
|
|
104
|
-
kind: predicate.kind,
|
|
105
|
-
cleared: false,
|
|
106
|
-
deferred: true,
|
|
107
|
-
evidence: DEFERRAL_REASON[predicate.kind],
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
const checks = predicate.checks ?? [];
|
|
111
|
-
if (checks.length === 0) {
|
|
112
|
-
return {
|
|
113
|
-
kind: 'deterministic',
|
|
114
|
-
cleared: false,
|
|
115
|
-
deferred: false,
|
|
116
|
-
evidence: 'no checks defined -- deterministic predicate cannot assert clearance',
|
|
117
|
-
checkResults: [],
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
const run = ctx.runCommand ?? defaultRunCommand;
|
|
121
|
-
const checkResults = [];
|
|
122
|
-
for (const check of checks) {
|
|
123
|
-
const { exitCode } = await run(check.cmd, ctx.worktreeDir);
|
|
124
|
-
checkResults.push({
|
|
125
|
-
cmd: check.cmd,
|
|
126
|
-
exitCode,
|
|
127
|
-
passed: exitCode === 0,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
const passedCount = checkResults.filter(r => r.passed).length;
|
|
131
|
-
const cleared = passedCount === checkResults.length;
|
|
132
|
-
return {
|
|
133
|
-
kind: 'deterministic',
|
|
134
|
-
cleared,
|
|
135
|
-
deferred: false,
|
|
136
|
-
evidence: cleared
|
|
137
|
-
? `deterministic clearance passed (${passedCount}/${checkResults.length} checks exit 0)`
|
|
138
|
-
: `deterministic clearance failed (${passedCount}/${checkResults.length} checks exit 0)`,
|
|
139
|
-
checkResults,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Aggregate clearance across all obstacles of a PRT -- the "milestone
|
|
144
|
-
* completion is computable" primitive. PURE; the caller fetches the obstacles
|
|
145
|
-
* (each carrying its `clearance_predicate`).
|
|
146
|
-
*
|
|
147
|
-
* - `allCleared` is true only when there is at least one obstacle AND every
|
|
148
|
-
* obstacle's verdict is cleared. (An empty obstacle set cannot assert a
|
|
149
|
-
* complete milestone.)
|
|
150
|
-
* - `deferredCount` counts obstacles whose predicate could not be evaluated
|
|
151
|
-
* automatically -- these block `allCleared` and flag where human/AI signal
|
|
152
|
-
* is still required.
|
|
153
|
-
*/
|
|
154
|
-
export async function evaluatePrtClearance(obstacles, ctx) {
|
|
155
|
-
const nodeVerdicts = [];
|
|
156
|
-
for (const obstacle of obstacles) {
|
|
157
|
-
const verdict = await evaluateClearance(obstacle.predicate, ctx);
|
|
158
|
-
nodeVerdicts.push({ nodeId: obstacle.nodeId, verdict });
|
|
159
|
-
}
|
|
160
|
-
const allCleared = obstacles.length > 0 && nodeVerdicts.every(nv => nv.verdict.cleared);
|
|
161
|
-
const deferredCount = nodeVerdicts.filter(nv => nv.verdict.deferred).length;
|
|
162
|
-
return { nodeVerdicts, allCleared, deferredCount };
|
|
163
|
-
}
|
|
164
|
-
//# sourceMappingURL=prd-clearance-engine.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prd-clearance-engine.js","sourceRoot":"","sources":["../src/prd-clearance-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,4BAA4B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;AAChE,MAAM,eAAe,GAAG,IAAI,CAAC;AA0D7B,8EAA8E;AAC9E,4DAA4D;AAC5D,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAe,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACxD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;YACrC,GAAG;YACH,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,GAAG,GAAG,eAAe,EAAU,EAAE,CAC1D,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;QAExD,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACzC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACzC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC;gBAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QACvD,CAAC,EAAE,4BAA4B,CAAC,CAAC;QAEjC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC;gBACN,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,MAAM;gBAClB,UAAU,EAAE,IAAI,CAAC,GAAG,MAAM,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC;aACzD,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,MAAM,eAAe,GAA4D;IAC/E,UAAU,EAAE,oEAAoE;IAChF,aAAa,EAAE,mEAAmE;IAClF,KAAK,EAAE,oEAAoE;CAC5E,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,SAA6B,EAC7B,GAAqB;IAErB,IAAI,SAAS,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QACvC,OAAO;YACL,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC;SAC1C,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC;IACtC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,KAAK;YACf,QAAQ,EAAE,sEAAsE;YAChF,YAAY,EAAE,EAAE;SACjB,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,IAAI,iBAAiB,CAAC;IAChD,MAAM,YAAY,GAA2B,EAAE,CAAC;IAChD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;QAC3D,YAAY,CAAC,IAAI,CAAC;YAChB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,QAAQ;YACR,MAAM,EAAE,QAAQ,KAAK,CAAC;SACvB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IAC9D,MAAM,OAAO,GAAG,WAAW,KAAK,YAAY,CAAC,MAAM,CAAC;IAEpD,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,OAAO;QACP,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,OAAO;YACf,CAAC,CAAC,mCAAmC,WAAW,IAAI,YAAY,CAAC,MAAM,iBAAiB;YACxF,CAAC,CAAC,mCAAmC,WAAW,IAAI,YAAY,CAAC,MAAM,iBAAiB;QAC1F,YAAY;KACb,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,SAA8D,EAC9D,GAAqB;IAMrB,MAAM,YAAY,GAAoD,EAAE,CAAC;IACzE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACjE,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxF,MAAM,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;IAE5E,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;AACrD,CAAC"}
|