@telora/daemon 0.17.56 → 0.17.64
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 +15 -3
- package/dist/cascade-restatement.d.ts +10 -0
- package/dist/cascade-restatement.d.ts.map +1 -1
- package/dist/cascade-restatement.js +107 -37
- package/dist/cascade-restatement.js.map +1 -1
- package/dist/ci-escalation.d.ts.map +1 -1
- package/dist/ci-escalation.js +5 -3
- package/dist/ci-escalation.js.map +1 -1
- package/dist/cli/backfill-frt-prose.d.ts +101 -0
- package/dist/cli/backfill-frt-prose.d.ts.map +1 -0
- package/dist/cli/backfill-frt-prose.js +195 -0
- package/dist/cli/backfill-frt-prose.js.map +1 -0
- package/dist/completion/event-escalations.d.ts +4 -11
- package/dist/completion/event-escalations.d.ts.map +1 -1
- package/dist/completion/event-escalations.js +21 -5
- package/dist/completion/event-escalations.js.map +1 -1
- package/dist/completion/event.d.ts +4 -11
- package/dist/completion/event.d.ts.map +1 -1
- package/dist/completion/event.js.map +1 -1
- package/dist/completion/review-exit-phase.d.ts.map +1 -1
- package/dist/completion/review-exit-phase.js +6 -2
- package/dist/completion/review-exit-phase.js.map +1 -1
- package/dist/crash-recovery-cleanup.d.ts.map +1 -1
- package/dist/crash-recovery-cleanup.js +7 -1
- package/dist/crash-recovery-cleanup.js.map +1 -1
- package/dist/crash-recovery-types.d.ts +4 -9
- package/dist/crash-recovery-types.d.ts.map +1 -1
- package/dist/crash-recovery-types.js.map +1 -1
- package/dist/crash-recovery.d.ts +4 -9
- package/dist/crash-recovery.d.ts.map +1 -1
- package/dist/crash-recovery.js +5 -1
- package/dist/crash-recovery.js.map +1 -1
- package/dist/delivery-advance-block.d.ts +62 -0
- package/dist/delivery-advance-block.d.ts.map +1 -0
- package/dist/delivery-advance-block.js +91 -0
- package/dist/delivery-advance-block.js.map +1 -0
- package/dist/delivery-guards.d.ts.map +1 -1
- package/dist/delivery-guards.js +4 -1
- package/dist/delivery-guards.js.map +1 -1
- package/dist/delivery-lifecycle.d.ts +2 -22
- package/dist/delivery-lifecycle.d.ts.map +1 -1
- package/dist/delivery-lifecycle.js +12 -50
- package/dist/delivery-lifecycle.js.map +1 -1
- package/dist/delivery-merge.d.ts.map +1 -1
- package/dist/delivery-merge.js +5 -1
- package/dist/delivery-merge.js.map +1 -1
- package/dist/directive/directive-dispatch.d.ts.map +1 -1
- package/dist/directive/directive-dispatch.js +4 -1
- package/dist/directive/directive-dispatch.js.map +1 -1
- package/dist/escalation-provenance.d.ts +60 -0
- package/dist/escalation-provenance.d.ts.map +1 -0
- package/dist/escalation-provenance.js +153 -0
- package/dist/escalation-provenance.js.map +1 -0
- package/dist/escalations.d.ts +33 -3
- package/dist/escalations.d.ts.map +1 -1
- package/dist/escalations.js +58 -12
- package/dist/escalations.js.map +1 -1
- package/dist/focus-executor.js +1 -1
- package/dist/focus-executor.js.map +1 -1
- package/dist/focus-merge.d.ts.map +1 -1
- package/dist/focus-merge.js +3 -1
- package/dist/focus-merge.js.map +1 -1
- package/dist/focus-stage-lifecycle.d.ts.map +1 -1
- package/dist/focus-stage-lifecycle.js +5 -2
- package/dist/focus-stage-lifecycle.js.map +1 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/listener-auto-advance.d.ts.map +1 -1
- package/dist/listener-auto-advance.js +8 -3
- package/dist/listener-auto-advance.js.map +1 -1
- package/dist/listener.d.ts.map +1 -1
- package/dist/listener.js +6 -0
- package/dist/listener.js.map +1 -1
- package/dist/merge-back-loop.d.ts.map +1 -1
- package/dist/merge-back-loop.js +7 -2
- package/dist/merge-back-loop.js.map +1 -1
- package/dist/nexus-escalation-bridge.d.ts +92 -0
- package/dist/nexus-escalation-bridge.d.ts.map +1 -0
- package/dist/nexus-escalation-bridge.js +109 -0
- package/dist/nexus-escalation-bridge.js.map +1 -0
- package/dist/nexus-incoming.d.ts +47 -0
- package/dist/nexus-incoming.d.ts.map +1 -0
- package/dist/nexus-incoming.js +93 -0
- package/dist/nexus-incoming.js.map +1 -0
- package/dist/nexus-return.d.ts +79 -0
- package/dist/nexus-return.d.ts.map +1 -0
- package/dist/nexus-return.js +193 -0
- package/dist/nexus-return.js.map +1 -0
- package/dist/queries/deliveries.d.ts +12 -0
- package/dist/queries/deliveries.d.ts.map +1 -1
- package/dist/queries/deliveries.js +17 -0
- package/dist/queries/deliveries.js.map +1 -1
- package/dist/queries/issues.d.ts +69 -5
- package/dist/queries/issues.d.ts.map +1 -1
- package/dist/queries/issues.js +61 -5
- package/dist/queries/issues.js.map +1 -1
- package/dist/resolvers/escalation-answers.d.ts +22 -0
- package/dist/resolvers/escalation-answers.d.ts.map +1 -0
- package/dist/resolvers/escalation-answers.js +98 -0
- package/dist/resolvers/escalation-answers.js.map +1 -0
- package/dist/resolvers/index.d.ts.map +1 -1
- package/dist/resolvers/index.js +2 -0
- package/dist/resolvers/index.js.map +1 -1
- package/dist/scanners/deps.d.ts +16 -0
- package/dist/scanners/deps.d.ts.map +1 -1
- package/dist/scanners/deps.js +39 -0
- package/dist/scanners/deps.js.map +1 -1
- package/dist/staleness.d.ts.map +1 -1
- package/dist/staleness.js +13 -2
- package/dist/staleness.js.map +1 -1
- package/dist/supabase.d.ts +1 -1
- package/dist/supabase.d.ts.map +1 -1
- package/dist/supabase.js +1 -1
- package/dist/supabase.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escalation -> Nexus bridge: the disposition router for cross-product blockers.
|
|
3
|
+
*
|
|
4
|
+
* NOW (without this bridge): when an agent is blocked by ANOTHER product its only
|
|
5
|
+
* in-system outlet is an upward escalation (out_of_scope / blocked_by_external) to
|
|
6
|
+
* a human. There is no lateral product-to-product channel -- a cross-product
|
|
7
|
+
* blocker dead-ends in the human pending inbox even though the right recipient is
|
|
8
|
+
* the OTHER product's team, not a person.
|
|
9
|
+
*
|
|
10
|
+
* TARGET (with this bridge): a cross-product blocker filed as an out_of_scope /
|
|
11
|
+
* blocked_by_external escalation that NAMES a target product is routed into a
|
|
12
|
+
* Nexus request (a lateral product-to-product channel) instead of dead-ending.
|
|
13
|
+
* Disposition is the router:
|
|
14
|
+
* - needs_intent (a human decision) -> human escalation (unchanged)
|
|
15
|
+
* - cross-product blocked_by_external/out_of_scope, target named -> Nexus request
|
|
16
|
+
*
|
|
17
|
+
* Governance choice (auto-route WITH escape): routing is automatic when -- and only
|
|
18
|
+
* when -- the escalation both (a) carries a cross-product reason type and (b) names
|
|
19
|
+
* a resolvable target product AND a source product. If EITHER product is missing
|
|
20
|
+
* (no resolvable target, or no source to attribute the request to) we fall back to
|
|
21
|
+
* the human escalation. The human path is the safe default: an unroutable
|
|
22
|
+
* cross-product blocker is still a real blocker a human must see. We never silently
|
|
23
|
+
* drop a blocker; the worst case degrades to today's behavior.
|
|
24
|
+
*
|
|
25
|
+
* routeEscalation is a PURE function so the disposition rule is unit-tested without
|
|
26
|
+
* any I/O; the request-creation side effect is injected via deps so the wiring is
|
|
27
|
+
* testable with mocks. This mirrors the nexus-incoming.ts callApi-deps + pure-gate
|
|
28
|
+
* pattern.
|
|
29
|
+
*/
|
|
30
|
+
import { callApi } from './queries/shared.js';
|
|
31
|
+
import { ESCALATION_REASONS } from '@telora/daemon-core';
|
|
32
|
+
/** Reason types that represent a cross-product (lateral) blocker, not a human decision. */
|
|
33
|
+
const CROSS_PRODUCT_REASONS = new Set([
|
|
34
|
+
ESCALATION_REASONS.OUT_OF_SCOPE,
|
|
35
|
+
ESCALATION_REASONS.BLOCKED_BY_EXTERNAL,
|
|
36
|
+
]);
|
|
37
|
+
/**
|
|
38
|
+
* Pure disposition router. Returns 'nexus' WHEN the reason type is a cross-product
|
|
39
|
+
* blocker ('out_of_scope' or 'blocked_by_external') AND both a target and a source
|
|
40
|
+
* product are present; otherwise 'human' (the safe default / escape hatch).
|
|
41
|
+
*/
|
|
42
|
+
export function routeEscalation(input) {
|
|
43
|
+
const isCrossProduct = !!input.reasonType && CROSS_PRODUCT_REASONS.has(input.reasonType);
|
|
44
|
+
const hasTarget = !!input.targetProductId;
|
|
45
|
+
const hasSource = !!input.sourceProductId;
|
|
46
|
+
return isCrossProduct && hasTarget && hasSource ? 'nexus' : 'human';
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Production deps backed by the product-api over callApi. Creates the Nexus request
|
|
50
|
+
* via product_request_create (already shipped) and returns its id.
|
|
51
|
+
*/
|
|
52
|
+
export function defaultNexusEscalationBridgeDeps() {
|
|
53
|
+
return {
|
|
54
|
+
createRequest: async (input) => {
|
|
55
|
+
const res = await callApi('product_request_create', {
|
|
56
|
+
sourceProductId: input.sourceProductId,
|
|
57
|
+
targetProductId: input.targetProductId,
|
|
58
|
+
fields: {
|
|
59
|
+
title: input.title,
|
|
60
|
+
description: input.description,
|
|
61
|
+
...(input.acceptanceContract ? { acceptanceContract: input.acceptanceContract } : {}),
|
|
62
|
+
...(input.sourceFocusId ? { sourceFocusId: input.sourceFocusId } : {}),
|
|
63
|
+
...(input.sourceDeliveryId ? { sourceDeliveryId: input.sourceDeliveryId } : {}),
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
const requestId = res.productRequest?.id;
|
|
67
|
+
if (!requestId) {
|
|
68
|
+
throw new Error('product_request_create returned no request id');
|
|
69
|
+
}
|
|
70
|
+
return { requestId };
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Route a cross-product blocker to a Nexus request when the disposition rule says
|
|
76
|
+
* so. Returns { routed: true, requestId } on success, otherwise { routed: false }
|
|
77
|
+
* (the caller then files / keeps the human escalation).
|
|
78
|
+
*
|
|
79
|
+
* Fail-safe: any failure creating the request is logged and degrades to
|
|
80
|
+
* { routed: false } so the blocker still surfaces as a human escalation. We NEVER
|
|
81
|
+
* lose a blocker because the lateral channel hiccupped.
|
|
82
|
+
*/
|
|
83
|
+
export async function maybeRouteToNexus(input, deps = defaultNexusEscalationBridgeDeps()) {
|
|
84
|
+
if (routeEscalation(input) !== 'nexus') {
|
|
85
|
+
return { routed: false };
|
|
86
|
+
}
|
|
87
|
+
const log = deps.log ?? ((msg) => console.log(msg));
|
|
88
|
+
// routeEscalation === 'nexus' guarantees both ids are present; narrow for TS.
|
|
89
|
+
const sourceProductId = input.sourceProductId;
|
|
90
|
+
const targetProductId = input.targetProductId;
|
|
91
|
+
try {
|
|
92
|
+
const { requestId } = await deps.createRequest({
|
|
93
|
+
sourceProductId,
|
|
94
|
+
targetProductId,
|
|
95
|
+
title: input.title,
|
|
96
|
+
description: input.description,
|
|
97
|
+
...(input.acceptanceContract ? { acceptanceContract: input.acceptanceContract } : {}),
|
|
98
|
+
...(input.sourceFocusId ? { sourceFocusId: input.sourceFocusId } : {}),
|
|
99
|
+
...(input.sourceDeliveryId ? { sourceDeliveryId: input.sourceDeliveryId } : {}),
|
|
100
|
+
});
|
|
101
|
+
log(`[nexus] routed cross-product escalation to request ${requestId} (source=${sourceProductId} target=${targetProductId})`);
|
|
102
|
+
return { routed: true, requestId };
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
log(`[nexus] failed to route escalation to Nexus (source=${sourceProductId} target=${targetProductId}): ${err.message}; falling back to human escalation`);
|
|
106
|
+
return { routed: false };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=nexus-escalation-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nexus-escalation-bridge.js","sourceRoot":"","sources":["../src/nexus-escalation-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus incoming-request poll: the receiving side of the cross-product request
|
|
3
|
+
* channel.
|
|
4
|
+
*
|
|
5
|
+
* Each poll cycle, for every configured product, the daemon looks for OPEN
|
|
6
|
+
* incoming requests (product_requests where target_product_id = this product)
|
|
7
|
+
* and applies the product's accept gate:
|
|
8
|
+
*
|
|
9
|
+
* - auto_with_decline (default): auto-accept + materialize the request as a
|
|
10
|
+
* scoped delivery in a per-product "Nexus Inbox" focus, where the target's
|
|
11
|
+
* AI team picks it up via the normal focus spawn path. (The target can still
|
|
12
|
+
* decline/clarify after the fact via MCP -- "accept with decline".)
|
|
13
|
+
* - human_required: leave the request OPEN; a human accepts it via MCP.
|
|
14
|
+
*
|
|
15
|
+
* The decision is a pure function (decideIncoming) so the gate is unit-tested
|
|
16
|
+
* without any I/O; the side effects (list/accept/materialize/policy read) are
|
|
17
|
+
* injected as deps so the poll wiring is testable with mocks.
|
|
18
|
+
*/
|
|
19
|
+
import type { DaemonConfig } from './types.js';
|
|
20
|
+
export type NexusAcceptPolicy = 'auto_with_decline' | 'human_required';
|
|
21
|
+
export type IncomingDecision = 'auto_accept' | 'await_human';
|
|
22
|
+
export interface IncomingRequest {
|
|
23
|
+
id: string;
|
|
24
|
+
targetProductId?: string;
|
|
25
|
+
status?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Pure accept gate. human_required holds the request for a human; everything
|
|
29
|
+
* else (the default auto_with_decline) auto-accepts.
|
|
30
|
+
*/
|
|
31
|
+
export declare function decideIncoming(policy: NexusAcceptPolicy): IncomingDecision;
|
|
32
|
+
export interface NexusIncomingDeps {
|
|
33
|
+
listIncomingOpen: (productId: string) => Promise<IncomingRequest[]>;
|
|
34
|
+
getAcceptPolicy: (productId: string) => Promise<NexusAcceptPolicy>;
|
|
35
|
+
acceptRequest: (requestId: string) => Promise<void>;
|
|
36
|
+
materializeRequest: (requestId: string) => Promise<void>;
|
|
37
|
+
log?: (msg: string) => void;
|
|
38
|
+
}
|
|
39
|
+
/** Production deps backed by the product-api over callApi. */
|
|
40
|
+
export declare function defaultNexusIncomingDeps(): NexusIncomingDeps;
|
|
41
|
+
/**
|
|
42
|
+
* Poll one product for incoming open requests and apply its accept gate.
|
|
43
|
+
* Safe to call every poll cycle: it is a no-op when there is no incoming work,
|
|
44
|
+
* and individual request failures are logged without aborting the batch.
|
|
45
|
+
*/
|
|
46
|
+
export declare function checkIncomingRequests(config: DaemonConfig, deps?: NexusIncomingDeps): Promise<void>;
|
|
47
|
+
//# sourceMappingURL=nexus-incoming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nexus-incoming.d.ts","sourceRoot":"","sources":["../src/nexus-incoming.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,GAAG,gBAAgB,CAAC;AAEvE,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,aAAa,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,gBAAgB,CAE1E;AAED,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACpE,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACnE,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,8DAA8D;AAC9D,wBAAgB,wBAAwB,IAAI,iBAAiB,CAqB5D;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,iBAA8C,GACnD,OAAO,CAAC,IAAI,CAAC,CAoCf"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus incoming-request poll: the receiving side of the cross-product request
|
|
3
|
+
* channel.
|
|
4
|
+
*
|
|
5
|
+
* Each poll cycle, for every configured product, the daemon looks for OPEN
|
|
6
|
+
* incoming requests (product_requests where target_product_id = this product)
|
|
7
|
+
* and applies the product's accept gate:
|
|
8
|
+
*
|
|
9
|
+
* - auto_with_decline (default): auto-accept + materialize the request as a
|
|
10
|
+
* scoped delivery in a per-product "Nexus Inbox" focus, where the target's
|
|
11
|
+
* AI team picks it up via the normal focus spawn path. (The target can still
|
|
12
|
+
* decline/clarify after the fact via MCP -- "accept with decline".)
|
|
13
|
+
* - human_required: leave the request OPEN; a human accepts it via MCP.
|
|
14
|
+
*
|
|
15
|
+
* The decision is a pure function (decideIncoming) so the gate is unit-tested
|
|
16
|
+
* without any I/O; the side effects (list/accept/materialize/policy read) are
|
|
17
|
+
* injected as deps so the poll wiring is testable with mocks.
|
|
18
|
+
*/
|
|
19
|
+
import { callApi } from './queries/shared.js';
|
|
20
|
+
/**
|
|
21
|
+
* Pure accept gate. human_required holds the request for a human; everything
|
|
22
|
+
* else (the default auto_with_decline) auto-accepts.
|
|
23
|
+
*/
|
|
24
|
+
export function decideIncoming(policy) {
|
|
25
|
+
return policy === 'human_required' ? 'await_human' : 'auto_accept';
|
|
26
|
+
}
|
|
27
|
+
/** Production deps backed by the product-api over callApi. */
|
|
28
|
+
export function defaultNexusIncomingDeps() {
|
|
29
|
+
return {
|
|
30
|
+
listIncomingOpen: async (productId) => {
|
|
31
|
+
const res = await callApi('product_request_list', {
|
|
32
|
+
productId,
|
|
33
|
+
direction: 'incoming',
|
|
34
|
+
status: 'open',
|
|
35
|
+
});
|
|
36
|
+
return res.requests ?? [];
|
|
37
|
+
},
|
|
38
|
+
getAcceptPolicy: async (productId) => {
|
|
39
|
+
const res = await callApi('get', { productId });
|
|
40
|
+
return res.product?.nexusAcceptPolicy === 'human_required' ? 'human_required' : 'auto_with_decline';
|
|
41
|
+
},
|
|
42
|
+
acceptRequest: async (requestId) => {
|
|
43
|
+
await callApi('product_request_accept', { requestId });
|
|
44
|
+
},
|
|
45
|
+
materializeRequest: async (requestId) => {
|
|
46
|
+
await callApi('product_request_materialize', { requestId });
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Poll one product for incoming open requests and apply its accept gate.
|
|
52
|
+
* Safe to call every poll cycle: it is a no-op when there is no incoming work,
|
|
53
|
+
* and individual request failures are logged without aborting the batch.
|
|
54
|
+
*/
|
|
55
|
+
export async function checkIncomingRequests(config, deps = defaultNexusIncomingDeps()) {
|
|
56
|
+
const productId = config.productId;
|
|
57
|
+
if (!productId)
|
|
58
|
+
return;
|
|
59
|
+
const log = deps.log ?? ((msg) => console.log(msg));
|
|
60
|
+
let requests;
|
|
61
|
+
try {
|
|
62
|
+
requests = await deps.listIncomingOpen(productId);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
log(`[nexus] failed to list incoming requests for ${productId}: ${err.message}`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (requests.length === 0)
|
|
69
|
+
return;
|
|
70
|
+
let policy;
|
|
71
|
+
try {
|
|
72
|
+
policy = await deps.getAcceptPolicy(productId);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
log(`[nexus] failed to read accept policy for ${productId}: ${err.message}`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (decideIncoming(policy) === 'await_human') {
|
|
79
|
+
log(`[nexus] ${requests.length} incoming request(s) for ${productId} await human approval (policy=human_required)`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
for (const req of requests) {
|
|
83
|
+
try {
|
|
84
|
+
await deps.acceptRequest(req.id);
|
|
85
|
+
await deps.materializeRequest(req.id);
|
|
86
|
+
log(`[nexus] auto-accepted + materialized request ${req.id} for product ${productId}`);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
log(`[nexus] failed to accept/materialize request ${req.id}: ${err.message}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=nexus-incoming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nexus-incoming.js","sourceRoot":"","sources":["../src/nexus-incoming.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus return-path poll: loop closure to the source.
|
|
3
|
+
*
|
|
4
|
+
* This closes the cross-product request differential. Two sides run each poll
|
|
5
|
+
* cycle, both safe to call every tick (no-op when there is no work):
|
|
6
|
+
*
|
|
7
|
+
* TARGET side -- for every incoming request still in_progress with a
|
|
8
|
+
* materialized delivery, ask the server to resolve it. The server gate
|
|
9
|
+
* (product_request_resolve) advances the request to 'closed' ONLY when the
|
|
10
|
+
* materialized delivery's execution_status is 'done' (it passed the verify
|
|
11
|
+
* gate); any other delivery state is a no-op. So merely calling resolve
|
|
12
|
+
* every tick converges the request the moment B's work lands.
|
|
13
|
+
*
|
|
14
|
+
* SOURCE side -- for every outgoing request in a terminal state
|
|
15
|
+
* ('closed' = completed, 'declined' = rejected) that has not yet notified
|
|
16
|
+
* its source (source_notified_at is null), file an escalation on the
|
|
17
|
+
* source's blocked focus so the human/agent there learns the cross-product
|
|
18
|
+
* dependency resolved, then stamp source_notified_at so it is not
|
|
19
|
+
* re-notified. This is the half that unblocks A without a human chasing it.
|
|
20
|
+
*
|
|
21
|
+
* shouldResolve is a pure predicate so the gate is unit-testable with no I/O;
|
|
22
|
+
* the side effects (list/resolve/notify/stamp) are injected as deps so the poll
|
|
23
|
+
* wiring is testable with mocks. Mirrors nexus-incoming.ts.
|
|
24
|
+
*/
|
|
25
|
+
import type { DaemonConfig } from './types.js';
|
|
26
|
+
/**
|
|
27
|
+
* Minimal shape of a product_request list row (camelCase from the edge fn).
|
|
28
|
+
* All fields optional + defensive: the daemon must not assume any are present.
|
|
29
|
+
*/
|
|
30
|
+
export interface Req {
|
|
31
|
+
id: string;
|
|
32
|
+
status?: string;
|
|
33
|
+
materializedDeliveryId?: string | null;
|
|
34
|
+
sourceFocusId?: string | null;
|
|
35
|
+
sourceProductId?: string | null;
|
|
36
|
+
targetProductId?: string | null;
|
|
37
|
+
title?: string | null;
|
|
38
|
+
declineReason?: string | null;
|
|
39
|
+
clarificationMessage?: string | null;
|
|
40
|
+
clarificationNotifiedAt?: string | null;
|
|
41
|
+
sourceNotifiedAt?: string | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Pure resolution gate. The loop closes only once the materialized delivery has
|
|
45
|
+
* passed the verify gate to 'done'. (The authoritative check is server-side in
|
|
46
|
+
* product_request_resolve; this mirror keeps the gate explicit + unit-tested.)
|
|
47
|
+
*/
|
|
48
|
+
export declare function shouldResolve(deliveryStatus: string | undefined): boolean;
|
|
49
|
+
export interface NexusReturnDeps {
|
|
50
|
+
/** Incoming requests still in_progress, filtered to those with a materialized delivery. */
|
|
51
|
+
listIncomingInProgress: (productId: string) => Promise<Req[]>;
|
|
52
|
+
/** Read a delivery's execution_status (org_nodes). Kept for completeness/testing. */
|
|
53
|
+
getDeliveryStatus: (deliveryId: string) => Promise<string | undefined>;
|
|
54
|
+
/** Ask the server to resolve a request; returns true when it closed the loop. */
|
|
55
|
+
resolveRequest: (requestId: string) => Promise<boolean>;
|
|
56
|
+
/** Outgoing requests for the source product (any status). */
|
|
57
|
+
listOutgoing: (productId: string) => Promise<Req[]>;
|
|
58
|
+
/** Notify the source side (escalation on the blocked focus) about a terminal state. */
|
|
59
|
+
notifySource: (req: Req) => Promise<void>;
|
|
60
|
+
/** Stamp source_notified_at so the request is not re-notified. */
|
|
61
|
+
markSourceNotified: (requestId: string) => Promise<void>;
|
|
62
|
+
/** Notify the source side that the target requested clarification. */
|
|
63
|
+
notifyClarification: (req: Req) => Promise<void>;
|
|
64
|
+
/** Stamp clarification_notified_at so the same clarification is not re-notified. */
|
|
65
|
+
markClarificationNotified: (requestId: string) => Promise<void>;
|
|
66
|
+
log?: (msg: string) => void;
|
|
67
|
+
}
|
|
68
|
+
/** Production deps backed by the product-api over callApi + createEscalation. */
|
|
69
|
+
export declare function defaultNexusReturnDeps(config: DaemonConfig): NexusReturnDeps;
|
|
70
|
+
/**
|
|
71
|
+
* Poll one product for return-path loop closure. Runs both sides:
|
|
72
|
+
* TARGET -- resolve materialized in_progress incoming requests (server gates
|
|
73
|
+
* on delivery 'done').
|
|
74
|
+
* SOURCE -- notify + stamp terminal outgoing requests not yet notified.
|
|
75
|
+
* Each request's work is wrapped in try/catch so one failure does not abort the
|
|
76
|
+
* batch (mirrors nexus-incoming).
|
|
77
|
+
*/
|
|
78
|
+
export declare function checkResolvedRequests(config: DaemonConfig, deps?: NexusReturnDeps): Promise<void>;
|
|
79
|
+
//# sourceMappingURL=nexus-return.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nexus-return.d.ts","sourceRoot":"","sources":["../src/nexus-return.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C;;;GAGG;AACH,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEzE;AAED,MAAM,WAAW,eAAe;IAC9B,2FAA2F;IAC3F,sBAAsB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9D,qFAAqF;IACrF,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACvE,iFAAiF;IACjF,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,6DAA6D;IAC7D,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,uFAAuF;IACvF,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,kEAAkE;IAClE,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,sEAAsE;IACtE,mBAAmB,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,oFAAoF;IACpF,yBAAyB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAKD,iFAAiF;AACjF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe,CAwF5E;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,eAAgD,GACrD,OAAO,CAAC,IAAI,CAAC,CA+Df"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus return-path poll: loop closure to the source.
|
|
3
|
+
*
|
|
4
|
+
* This closes the cross-product request differential. Two sides run each poll
|
|
5
|
+
* cycle, both safe to call every tick (no-op when there is no work):
|
|
6
|
+
*
|
|
7
|
+
* TARGET side -- for every incoming request still in_progress with a
|
|
8
|
+
* materialized delivery, ask the server to resolve it. The server gate
|
|
9
|
+
* (product_request_resolve) advances the request to 'closed' ONLY when the
|
|
10
|
+
* materialized delivery's execution_status is 'done' (it passed the verify
|
|
11
|
+
* gate); any other delivery state is a no-op. So merely calling resolve
|
|
12
|
+
* every tick converges the request the moment B's work lands.
|
|
13
|
+
*
|
|
14
|
+
* SOURCE side -- for every outgoing request in a terminal state
|
|
15
|
+
* ('closed' = completed, 'declined' = rejected) that has not yet notified
|
|
16
|
+
* its source (source_notified_at is null), file an escalation on the
|
|
17
|
+
* source's blocked focus so the human/agent there learns the cross-product
|
|
18
|
+
* dependency resolved, then stamp source_notified_at so it is not
|
|
19
|
+
* re-notified. This is the half that unblocks A without a human chasing it.
|
|
20
|
+
*
|
|
21
|
+
* shouldResolve is a pure predicate so the gate is unit-testable with no I/O;
|
|
22
|
+
* the side effects (list/resolve/notify/stamp) are injected as deps so the poll
|
|
23
|
+
* wiring is testable with mocks. Mirrors nexus-incoming.ts.
|
|
24
|
+
*/
|
|
25
|
+
import { callApi } from './queries/shared.js';
|
|
26
|
+
import { createEscalation } from './queries/issues.js';
|
|
27
|
+
import { ESCALATION_REASONS, ESCALATION_DISPOSITIONS, ESCALATION_KINDS } from '@telora/daemon-core';
|
|
28
|
+
/**
|
|
29
|
+
* Pure resolution gate. The loop closes only once the materialized delivery has
|
|
30
|
+
* passed the verify gate to 'done'. (The authoritative check is server-side in
|
|
31
|
+
* product_request_resolve; this mirror keeps the gate explicit + unit-tested.)
|
|
32
|
+
*/
|
|
33
|
+
export function shouldResolve(deliveryStatus) {
|
|
34
|
+
return deliveryStatus === 'done';
|
|
35
|
+
}
|
|
36
|
+
/** Terminal statuses on the source side that warrant a notification. */
|
|
37
|
+
const TERMINAL_SOURCE_STATUSES = new Set(['closed', 'declined']);
|
|
38
|
+
/** Production deps backed by the product-api over callApi + createEscalation. */
|
|
39
|
+
export function defaultNexusReturnDeps(config) {
|
|
40
|
+
return {
|
|
41
|
+
listIncomingInProgress: async (productId) => {
|
|
42
|
+
const res = await callApi('product_request_list', {
|
|
43
|
+
productId,
|
|
44
|
+
direction: 'incoming',
|
|
45
|
+
status: 'in_progress',
|
|
46
|
+
});
|
|
47
|
+
return (res.requests ?? []).filter((r) => !!r.materializedDeliveryId);
|
|
48
|
+
},
|
|
49
|
+
getDeliveryStatus: async (deliveryId) => {
|
|
50
|
+
// The server-side gate already reads delivery status during resolve, so
|
|
51
|
+
// this default is a thin convenience: delivery_list returns org_nodes.
|
|
52
|
+
const res = await callApi('delivery_list', { deliveryId });
|
|
53
|
+
const match = (res.deliveries ?? []).find((d) => d.id === deliveryId);
|
|
54
|
+
return match?.executionStatus;
|
|
55
|
+
},
|
|
56
|
+
resolveRequest: async (requestId) => {
|
|
57
|
+
const res = await callApi('product_request_resolve', { requestId });
|
|
58
|
+
return res.resolved === true;
|
|
59
|
+
},
|
|
60
|
+
listOutgoing: async (productId) => {
|
|
61
|
+
const res = await callApi('product_request_list', {
|
|
62
|
+
productId,
|
|
63
|
+
direction: 'outgoing',
|
|
64
|
+
});
|
|
65
|
+
return res.requests ?? [];
|
|
66
|
+
},
|
|
67
|
+
notifySource: async (req) => {
|
|
68
|
+
const declined = req.status === 'declined';
|
|
69
|
+
const reasonPhrase = declined
|
|
70
|
+
? `declined by the target product${req.declineReason ? `: ${req.declineReason}` : ''}`
|
|
71
|
+
: 'completed by the target product';
|
|
72
|
+
// Use BLOCKED_BY_EXTERNAL for declines (the source is still blocked and needs
|
|
73
|
+
// to decide next steps). Use DECISION_NEEDED for resolved (closed) requests:
|
|
74
|
+
// the dependency cleared and the source team can now unblock their work.
|
|
75
|
+
const reasonType = declined
|
|
76
|
+
? ESCALATION_REASONS.BLOCKED_BY_EXTERNAL
|
|
77
|
+
: ESCALATION_REASONS.DECISION_NEEDED;
|
|
78
|
+
const descriptionPrefix = declined
|
|
79
|
+
? '[Nexus dependency declined]'
|
|
80
|
+
: '[Nexus dependency resolved]';
|
|
81
|
+
await createEscalation({
|
|
82
|
+
organizationId: config.organizationId,
|
|
83
|
+
issueId: null,
|
|
84
|
+
reasonType,
|
|
85
|
+
// Disposition routes resolution: a resolved (closed) dependency clears the
|
|
86
|
+
// blocker so an agent on the source focus can act on it automatically; a
|
|
87
|
+
// decline leaves the source still blocked and needing a human to decide
|
|
88
|
+
// next steps.
|
|
89
|
+
disposition: declined
|
|
90
|
+
? ESCALATION_DISPOSITIONS.NEEDS_INTENT
|
|
91
|
+
: ESCALATION_DISPOSITIONS.AGENT_RESOLVABLE,
|
|
92
|
+
escalationKind: ESCALATION_KINDS.NEXUS_REQUEST_RESOLVED,
|
|
93
|
+
// Provenance: the source focus is the anchor; resolver derives productId.
|
|
94
|
+
anchor: { focusId: req.sourceFocusId ?? undefined },
|
|
95
|
+
...(req.sourceProductId ? { productId: req.sourceProductId } : {}),
|
|
96
|
+
description: `${descriptionPrefix} Nexus request "${req.title ?? '(untitled)'}" was ${reasonPhrase}. ` +
|
|
97
|
+
`${declined ? 'Review the decline reason and decide on next steps.' : 'The cross-product dependency is now clear -- you can unblock your work.'}`,
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
markSourceNotified: async (requestId) => {
|
|
101
|
+
await callApi('product_request_mark_source_notified', { requestId });
|
|
102
|
+
},
|
|
103
|
+
notifyClarification: async (req) => {
|
|
104
|
+
await createEscalation({
|
|
105
|
+
organizationId: config.organizationId,
|
|
106
|
+
issueId: null,
|
|
107
|
+
reasonType: ESCALATION_REASONS.NEEDS_CLARIFICATION,
|
|
108
|
+
// A human on the source side must provide the clarification response.
|
|
109
|
+
disposition: ESCALATION_DISPOSITIONS.NEEDS_INTENT,
|
|
110
|
+
escalationKind: ESCALATION_KINDS.NEXUS_CLARIFICATION_REQUESTED,
|
|
111
|
+
// Provenance: the source focus is the anchor; resolver derives productId.
|
|
112
|
+
anchor: { focusId: req.sourceFocusId ?? undefined },
|
|
113
|
+
...(req.sourceProductId ? { productId: req.sourceProductId } : {}),
|
|
114
|
+
description: `[Nexus clarification requested] Nexus request "${req.title ?? '(untitled)'}" has a question from the target product: ` +
|
|
115
|
+
`${req.clarificationMessage ?? '(no message)'} -- reply or update the request to unblock the cross-product work.`,
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
markClarificationNotified: async (requestId) => {
|
|
119
|
+
await callApi('product_request_mark_clarification_notified', { requestId });
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Poll one product for return-path loop closure. Runs both sides:
|
|
125
|
+
* TARGET -- resolve materialized in_progress incoming requests (server gates
|
|
126
|
+
* on delivery 'done').
|
|
127
|
+
* SOURCE -- notify + stamp terminal outgoing requests not yet notified.
|
|
128
|
+
* Each request's work is wrapped in try/catch so one failure does not abort the
|
|
129
|
+
* batch (mirrors nexus-incoming).
|
|
130
|
+
*/
|
|
131
|
+
export async function checkResolvedRequests(config, deps = defaultNexusReturnDeps(config)) {
|
|
132
|
+
const productId = config.productId;
|
|
133
|
+
if (!productId)
|
|
134
|
+
return;
|
|
135
|
+
const log = deps.log ?? ((msg) => console.log(msg));
|
|
136
|
+
// --- TARGET side: resolve materialized in_progress incoming requests. ---
|
|
137
|
+
let incoming = [];
|
|
138
|
+
try {
|
|
139
|
+
incoming = await deps.listIncomingInProgress(productId);
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
log(`[nexus] failed to list in_progress incoming requests for ${productId}: ${err.message}`);
|
|
143
|
+
}
|
|
144
|
+
for (const req of incoming) {
|
|
145
|
+
try {
|
|
146
|
+
const resolved = await deps.resolveRequest(req.id);
|
|
147
|
+
if (resolved) {
|
|
148
|
+
log(`[nexus] resolved incoming request ${req.id} (materialized delivery done) for ${productId}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
log(`[nexus] failed to resolve incoming request ${req.id}: ${err.message}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// --- SOURCE side: notify + stamp terminal outgoing requests. ---
|
|
156
|
+
let outgoing = [];
|
|
157
|
+
try {
|
|
158
|
+
outgoing = await deps.listOutgoing(productId);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
log(`[nexus] failed to list outgoing requests for ${productId}: ${err.message}`);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const pending = outgoing.filter((r) => r.status !== undefined && TERMINAL_SOURCE_STATUSES.has(r.status) && !r.sourceNotifiedAt);
|
|
165
|
+
for (const req of pending) {
|
|
166
|
+
try {
|
|
167
|
+
await deps.notifySource(req);
|
|
168
|
+
await deps.markSourceNotified(req.id);
|
|
169
|
+
log(`[nexus] notified source of resolved request ${req.id} (status=${req.status}) for ${productId}`);
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
log(`[nexus] failed to notify source for request ${req.id}: ${err.message}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// --- SOURCE side: notify about pending clarifications. ---
|
|
176
|
+
// Exclude terminal requests (closed/declined): the edge handler rejects clarify on
|
|
177
|
+
// terminal requests, but guard here too so any pre-existing stale rows don't fire.
|
|
178
|
+
const pendingClarification = outgoing.filter((r) => !!r.clarificationMessage &&
|
|
179
|
+
!r.clarificationNotifiedAt &&
|
|
180
|
+
r.status !== 'closed' &&
|
|
181
|
+
r.status !== 'declined');
|
|
182
|
+
for (const req of pendingClarification) {
|
|
183
|
+
try {
|
|
184
|
+
await deps.notifyClarification(req);
|
|
185
|
+
await deps.markClarificationNotified(req.id);
|
|
186
|
+
log(`[nexus] notified source of clarification request ${req.id} for ${productId}`);
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
log(`[nexus] failed to notify source about clarification for request ${req.id}: ${err.message}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=nexus-return.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nexus-return.js","sourceRoot":"","sources":["../src/nexus-return.ts"],"names":[],"mappings":"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"}
|
|
@@ -214,4 +214,16 @@ export declare function getMergeConflictDeliveries(_organizationId: string, prod
|
|
|
214
214
|
focus_id: string | null;
|
|
215
215
|
pipeline_config: PipelineConfig | null;
|
|
216
216
|
}>>;
|
|
217
|
+
/**
|
|
218
|
+
* Return the delivery_id (and derived focus_id + product_id) for a single
|
|
219
|
+
* issue, for use by resolveProvenance when only an issueId anchor is available.
|
|
220
|
+
*
|
|
221
|
+
* Returns null when the issue is not found or has no delivery.
|
|
222
|
+
* Best-effort: callers must handle null gracefully.
|
|
223
|
+
*/
|
|
224
|
+
export declare function getIssueDelivery(issueId: string): Promise<{
|
|
225
|
+
deliveryId: string;
|
|
226
|
+
productId: string | null;
|
|
227
|
+
focusId: string | null;
|
|
228
|
+
} | null>;
|
|
217
229
|
//# sourceMappingURL=deliveries.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deliveries.d.ts","sourceRoot":"","sources":["../../src/queries/deliveries.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"deliveries.d.ts","sourceRoot":"","sources":["../../src/queries/deliveries.ts"],"names":[],"mappings":"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"}
|
|
@@ -285,4 +285,21 @@ export async function getMergeConflictDeliveries(_organizationId, productId) {
|
|
|
285
285
|
pipeline_config: d.pipelineConfig ?? null,
|
|
286
286
|
}));
|
|
287
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Return the delivery_id (and derived focus_id + product_id) for a single
|
|
290
|
+
* issue, for use by resolveProvenance when only an issueId anchor is available.
|
|
291
|
+
*
|
|
292
|
+
* Returns null when the issue is not found or has no delivery.
|
|
293
|
+
* Best-effort: callers must handle null gracefully.
|
|
294
|
+
*/
|
|
295
|
+
export async function getIssueDelivery(issueId) {
|
|
296
|
+
const result = await callApi('daemon_get_issue_delivery', { issueId });
|
|
297
|
+
if (!result.deliveryId)
|
|
298
|
+
return null;
|
|
299
|
+
return {
|
|
300
|
+
deliveryId: result.deliveryId,
|
|
301
|
+
productId: result.productId ?? null,
|
|
302
|
+
focusId: result.focusId ?? null,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
288
305
|
//# sourceMappingURL=deliveries.js.map
|