@aligndottech/cli 0.39.0 → 0.40.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/dist/commands/connect.d.ts +11 -13
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +0 -21
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/import/confluence.js +2 -2
- package/dist/commands/import/confluence.js.map +1 -1
- package/dist/commands/import/docs.js +1 -1
- package/dist/commands/import/docs.js.map +1 -1
- package/dist/commands/import/git.js +1 -1
- package/dist/commands/import/git.js.map +1 -1
- package/dist/commands/import/github.js +1 -1
- package/dist/commands/import/github.js.map +1 -1
- package/dist/commands/import/gitlab.js +1 -1
- package/dist/commands/import/gitlab.js.map +1 -1
- package/dist/commands/import/jira.js +2 -2
- package/dist/commands/import/jira.js.map +1 -1
- package/dist/commands/import/linear.js +1 -1
- package/dist/commands/import/linear.js.map +1 -1
- package/dist/commands/import/notion.js +1 -1
- package/dist/commands/import/notion.js.map +1 -1
- package/dist/commands/import/sessions.d.ts +1 -1
- package/dist/commands/import/sessions.js +1 -1
- package/dist/commands/import/sessions.js.map +1 -1
- package/dist/commands/import/slack.js +1 -1
- package/dist/commands/import/slack.js.map +1 -1
- package/dist/commands/import/teams.js +1 -1
- package/dist/commands/import/teams.js.map +1 -1
- package/dist/commands/import/zoom.js +1 -1
- package/dist/commands/import/zoom.js.map +1 -1
- package/dist/commands/import.d.ts +24 -3
- package/dist/commands/import.d.ts.map +1 -1
- package/dist/commands/import.js +38 -21
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/mcp.d.ts +49 -3
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +214 -17
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/ratify.js +1 -1
- package/dist/commands/ratify.js.map +1 -1
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +11 -1
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/search.js +1 -1
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/setup.js +1 -1
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/why.js +3 -3
- package/dist/commands/why.js.map +1 -1
- package/dist/lib/capture-sources.d.ts +1 -1
- package/dist/lib/capture-sources.js +1 -1
- package/dist/lib/command-opts.d.ts +1 -1
- package/dist/lib/command-opts.js +1 -1
- package/dist/lib/commands-doc.d.ts.map +1 -1
- package/dist/lib/commands-doc.js +4 -1
- package/dist/lib/commands-doc.js.map +1 -1
- package/dist/lib/decision-refs.d.ts +1 -1
- package/dist/lib/decision-refs.js +1 -1
- package/dist/lib/errors.d.ts +1 -1
- package/dist/lib/errors.js +2 -2
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/fetchers/git.d.ts +1 -1
- package/dist/lib/fetchers/git.js +1 -1
- package/dist/lib/gateway-client.d.ts +70 -1
- package/dist/lib/gateway-client.d.ts.map +1 -1
- package/dist/lib/gateway-client.js +121 -8
- package/dist/lib/gateway-client.js.map +1 -1
- package/dist/lib/git.js +1 -1
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/import-defaults.d.ts +1 -1
- package/dist/lib/import-defaults.js +1 -1
- package/dist/lib/local-db.js +1 -1
- package/dist/lib/local-gateway-client.d.ts +1 -1
- package/dist/lib/local-gateway-client.d.ts.map +1 -1
- package/dist/lib/local-gateway-client.js +9 -1
- package/dist/lib/local-gateway-client.js.map +1 -1
- package/dist/lib/mcp-timeline-tools.d.ts +128 -0
- package/dist/lib/mcp-timeline-tools.d.ts.map +1 -0
- package/dist/lib/mcp-timeline-tools.js +504 -0
- package/dist/lib/mcp-timeline-tools.js.map +1 -0
- package/dist/lib/personal-oauth.d.ts +1 -1
- package/dist/lib/personal-oauth.js +4 -4
- package/dist/lib/personal-oauth.js.map +1 -1
- package/dist/lib/resolve-env.d.ts +1 -1
- package/dist/lib/resolve-env.js +1 -1
- package/dist/lib/sessions/import-summary.d.ts +2 -2
- package/dist/lib/sessions/import-summary.js +1 -1
- package/dist/lib/sessions/registry.d.ts +1 -1
- package/dist/lib/sessions/registry.js +1 -1
- package/dist/lib/usage-telemetry.d.ts +2 -2
- package/dist/lib/usage-telemetry.js +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
import { citationFor, navigableSourceUrl, repositoryOf } from './decision-links.js';
|
|
2
|
+
/**
|
|
3
|
+
* ALI-1070 slice 1: the "timeline trio", ported from the hosted connector so a customer's
|
|
4
|
+
* agent can reach it through `align mcp`.
|
|
5
|
+
*
|
|
6
|
+
* `align mcp` is the server `align mcp --setup` wires into every customer's agent. It
|
|
7
|
+
* published 8 tools against the hosted endpoint's 24, and the three missing ones ported here
|
|
8
|
+
* are the measured lever on AlignBench's weakest split (`reversed`).
|
|
9
|
+
*
|
|
10
|
+
* THE ENDPOINT IS NOT THE PRODUCT. THE MESSAGE IS.
|
|
11
|
+
*
|
|
12
|
+
* `POST /decisions/topic-timeline` already returns the whole story structure - the chain, the
|
|
13
|
+
* conflicts, the reasons, the open questions. What the hosted connector's topicTimeline.ts
|
|
14
|
+
* adds on top is (a) a projection and (b) a RENDERING CONTRACT in the response message, and
|
|
15
|
+
* the contract is where the measured behaviour lives. A customer handed the rows without the
|
|
16
|
+
* contract gets the data and not the ability to tell a supersession from a correction, which
|
|
17
|
+
* is exactly the split this ticket exists to move. So this module is mostly the message.
|
|
18
|
+
*
|
|
19
|
+
* The contract rides on the response rather than on the server instructions because the
|
|
20
|
+
* message is the one surface guaranteed to be in the calling agent's context at the moment it
|
|
21
|
+
* writes the answer: instructions are truncated around 2KB and some clients never surface
|
|
22
|
+
* them at all.
|
|
23
|
+
*
|
|
24
|
+
* Ported faithfully from connectors/mcp-align/src/tools/topicTimeline.ts with three
|
|
25
|
+
* deliberate differences, each because this server is not that server:
|
|
26
|
+
*
|
|
27
|
+
* 1. TOOL NAMES ARE RENDERED, NOT HARDCODED. The hosted message says "get_decision_rationale";
|
|
28
|
+
* this server's name for that tool is `align_get_decision_rationale`. Porting the text
|
|
29
|
+
* verbatim would instruct a customer's agent to call a tool that is not on this server -
|
|
30
|
+
* the same defect align-stack derives ALIGN_MCP_INSTRUCTIONS_READ_ONLY to prevent, and
|
|
31
|
+
* pinned here by mcp-timeline-trio.test.ts ("names no align_ tool it does not register").
|
|
32
|
+
* 2. NO decision_url. That one genuinely needs the hosted connector's FRONTEND_URL. The
|
|
33
|
+
* contract's link clause is conditional ("with decision_url when present, else
|
|
34
|
+
* source_url") so it stays TRUE here, and the closing full-timeline rule was corrected in
|
|
35
|
+
* the ALI-1070 follow-up to stop demanding it unconditionally.
|
|
36
|
+
*
|
|
37
|
+
* `cite` and `repository` ARE emitted. The first port dropped them claiming they needed
|
|
38
|
+
* FRONTEND_URL too, which was simply false: both derive from `source_url` alone through
|
|
39
|
+
* one regex, so they cost about twenty lines and no configuration. Correcting the claim is
|
|
40
|
+
* the point - a stated reason that is wrong outlives the omission it justified.
|
|
41
|
+
* 3. The result is a plain object. This server's createCallToolHandler serialises it and
|
|
42
|
+
* OMIT_RESULT_KEYS strips the heavy fields, so there is no toolText/framed wrapper. That
|
|
43
|
+
* stripping is also why the rationale tool needs shapeDecisionRationale below rather than
|
|
44
|
+
* returning its gateway row raw.
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* ALI-1070 follow-up, F7 (Copilot, #296 suppressed at mcp.ts:222): project the reasoning OUT
|
|
48
|
+
* of `decision_json` before the serializer strips it.
|
|
49
|
+
*
|
|
50
|
+
* The first port was `return client.getDecision(id)` raw. `serializeMcpResult`'s
|
|
51
|
+
* OMIT_RESULT_KEYS removes `decision_json`, and EVERY field this tool's description promises -
|
|
52
|
+
* rationale, goals, risks, context - lives inside it. Measured against a realistic snapshot
|
|
53
|
+
* row before the fix: the agent received id, title, summary, status, platform, created_at and
|
|
54
|
+
* nothing else. The tool answered with metadata and dropped the rationale it advertises.
|
|
55
|
+
*
|
|
56
|
+
* Worse, the topic-timeline contract's own fallback names this tool ("call
|
|
57
|
+
* align_get_decision_rationale for the decisions whose reasoning the answer needs"), so the
|
|
58
|
+
* one escape hatch the story renderer offers returned no reasoning.
|
|
59
|
+
*
|
|
60
|
+
* Projected rather than un-omitted: `decision_json` is unbounded (ALI-498 measured 43,327
|
|
61
|
+
* characters of it on one 12-row prod component), so the fix is to lift the named fields out,
|
|
62
|
+
* never to let the blob through.
|
|
63
|
+
*
|
|
64
|
+
* Ported from the hosted connector's decisionRationale.ts, including the `.ai` sub-object.
|
|
65
|
+
*
|
|
66
|
+
* ALI-484 is about `alternatives_considered` and `positions_considered` specifically:
|
|
67
|
+
* `rationale` is a 1-2 sentence gloss on the option CHOSEN, while the reasoning an agent needs
|
|
68
|
+
* is the option REJECTED and why, which the scan writes into `suggested_decision_json` and the
|
|
69
|
+
* approve path copies verbatim into `decision_json.ai`. Those two fields therefore read the
|
|
70
|
+
* top level and fall back to `.ai`.
|
|
71
|
+
*
|
|
72
|
+
* `rationale` keeps the HOSTED precedence - top level first, then `.ai`, then the summary.
|
|
73
|
+
* Copilot read the paragraph above as a claim that `.ai.rationale` should win (#298 inline at
|
|
74
|
+
* :134); it is not, and the fix is this wording rather than a re-ranking. A port that silently
|
|
75
|
+
* re-ranks its source stops being verifiable against it, and there is no evidence which order
|
|
76
|
+
* answers better. The both-present case is now pinned by a test so the choice is deliberate.
|
|
77
|
+
*/
|
|
78
|
+
/** A stored decision is free-form JSON, so a field asked for as a list can arrive as anything. */
|
|
79
|
+
function asArray(value) {
|
|
80
|
+
return Array.isArray(value) ? value : [];
|
|
81
|
+
}
|
|
82
|
+
/** ALI-582: the Jira keys and implementing PRs the gateway already sends in this response. */
|
|
83
|
+
const MAX_ARTIFACTS_PER_DECISION = 20;
|
|
84
|
+
function mentionedArtifacts(refs) {
|
|
85
|
+
if (!Array.isArray(refs))
|
|
86
|
+
return {};
|
|
87
|
+
const all = refs
|
|
88
|
+
.map((r) => {
|
|
89
|
+
if (!r || typeof r !== 'object')
|
|
90
|
+
return undefined;
|
|
91
|
+
const ref = r;
|
|
92
|
+
const id = ref['external_id'];
|
|
93
|
+
if (typeof id !== 'string' || id.length === 0)
|
|
94
|
+
return undefined;
|
|
95
|
+
return {
|
|
96
|
+
...(typeof ref['connector'] === 'string' ? { connector: ref['connector'] } : {}),
|
|
97
|
+
external_id: id,
|
|
98
|
+
...(typeof ref['external_url'] === 'string' ? { external_url: ref['external_url'] } : {}),
|
|
99
|
+
...(typeof ref['reference_type'] === 'string'
|
|
100
|
+
? { reference_type: ref['reference_type'] }
|
|
101
|
+
: {}),
|
|
102
|
+
};
|
|
103
|
+
})
|
|
104
|
+
.filter((a) => a !== undefined);
|
|
105
|
+
// Absent rather than [] when there are none: an empty list reads as "we looked and this
|
|
106
|
+
// decision mentions nothing", which is a claim this projection cannot make.
|
|
107
|
+
if (all.length === 0)
|
|
108
|
+
return {};
|
|
109
|
+
return {
|
|
110
|
+
mentioned_artifacts: all.slice(0, MAX_ARTIFACTS_PER_DECISION),
|
|
111
|
+
...(all.length > MAX_ARTIFACTS_PER_DECISION ? { mentioned_artifacts_truncated: true } : {}),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Shape one `GET /snapshots/:id` row into the rationale answer.
|
|
116
|
+
*
|
|
117
|
+
* Tolerant of a row with no `decision_json` at all, which is the LOCAL case: local mode serves
|
|
118
|
+
* this tool for real (the local client implements getDecision) and its rows carry no such
|
|
119
|
+
* column. Thinner, not broken - the summary becomes the rationale, which is the same
|
|
120
|
+
* last-resort fallback the hosted handler uses.
|
|
121
|
+
*/
|
|
122
|
+
export function shapeDecisionRationale(row, decisionId) {
|
|
123
|
+
const dj = row['decision_json'] ?? {};
|
|
124
|
+
const aiSub = dj['ai'] ?? {};
|
|
125
|
+
const summary = typeof row['summary'] === 'string' ? row['summary'] : '';
|
|
126
|
+
return {
|
|
127
|
+
decision_id: decisionId,
|
|
128
|
+
title: row['title'],
|
|
129
|
+
summary: row['summary'],
|
|
130
|
+
status: row['status'],
|
|
131
|
+
platform: row['platform'],
|
|
132
|
+
created_at: row['created_at'],
|
|
133
|
+
rationale: dj['rationale'] ??
|
|
134
|
+
aiSub['rationale'] ??
|
|
135
|
+
summary,
|
|
136
|
+
goals: dj['goals'] ?? [],
|
|
137
|
+
risks: dj['risks'] ?? aiSub['risks'] ?? [],
|
|
138
|
+
context: dj['context'] ?? '',
|
|
139
|
+
alternatives_considered: asArray(dj['alternatives_considered'] ?? aiSub['alternatives_considered']),
|
|
140
|
+
positions_considered: asArray(dj['positions_considered'] ?? aiSub['positions_considered']),
|
|
141
|
+
...mentionedArtifacts(row['external_references']),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/** Names this server publishes for the trio. Imported by mcp.ts, so there is one writer. */
|
|
145
|
+
export const TOPIC_TIMELINE_TOOL = 'align_get_topic_timeline';
|
|
146
|
+
export const DECISION_RATIONALE_TOOL = 'align_get_decision_rationale';
|
|
147
|
+
export const DECISION_TIMELINE_TOOL = 'align_get_decision_timeline';
|
|
148
|
+
/**
|
|
149
|
+
* The one phrase the tool description and the per-result message both use to gate the
|
|
150
|
+
* full-timeline render. Shared so the two surfaces cannot drift: they are two writers of one
|
|
151
|
+
* fact with no reader that sees both, and each surface's test pins only its own copy.
|
|
152
|
+
*/
|
|
153
|
+
export const STORY_GATE = 'asked for the story';
|
|
154
|
+
/**
|
|
155
|
+
* 280, matching the hosted connector's `format.ts` (ALI-297/ALI-498). The first port wrote 500
|
|
156
|
+
* and did not declare it as a difference; on a 50-row timeline that is up to ~11 kB of extra
|
|
157
|
+
* agent context per call, in a module whose stated purpose is bounded output.
|
|
158
|
+
*/
|
|
159
|
+
const MAX_SUMMARY_CHARS = 280;
|
|
160
|
+
function truncate(text, max = MAX_SUMMARY_CHARS) {
|
|
161
|
+
if (text.length <= max)
|
|
162
|
+
return text;
|
|
163
|
+
// max - 3, not max - 1: the hosted original appends a one-character ellipsis and this repo
|
|
164
|
+
// stays ASCII, so the marker costs three. The first port kept the hosted arithmetic with the
|
|
165
|
+
// longer marker and returned max + 2 - inside a cap whose whole job is to bound context.
|
|
166
|
+
return `${text.slice(0, max - 3).trimEnd()}...`;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* The source-url helpers come from decision-links.ts, which already owns all four of them
|
|
170
|
+
* (Copilot, #298 inline at :185 - it named the synthetic list; the follow-up had in fact
|
|
171
|
+
* duplicated FOUR).
|
|
172
|
+
*
|
|
173
|
+
* That module's own docblock says it is already a second writer of the gateway's synthetic
|
|
174
|
+
* namespace list and asks to be kept in sync, so a third copy in this repo is exactly the
|
|
175
|
+
* drift it warns about: the gateway mints a new `align://` namespace, one copy learns it, and
|
|
176
|
+
* the other silently re-exposes a minted identity as a link.
|
|
177
|
+
*
|
|
178
|
+
* Reuse is also a capability gain, not just deduplication: the canonical `citationFor` cites
|
|
179
|
+
* Linear and Jira tickets by their key ("ALI-346", "PROJ-12"), which the deleted local copy
|
|
180
|
+
* could not do at all. `navigableSourceUrl` is the shared refusal to hand back an `align://`
|
|
181
|
+
* identity, and `sourceFields` below is the topic-timeline presentation built on it.
|
|
182
|
+
*/
|
|
183
|
+
function sourceFields(sourceUrl) {
|
|
184
|
+
if (typeof sourceUrl !== 'string' || sourceUrl.length === 0)
|
|
185
|
+
return {};
|
|
186
|
+
const navigable = navigableSourceUrl(sourceUrl);
|
|
187
|
+
if (navigable)
|
|
188
|
+
return { source_url: navigable };
|
|
189
|
+
// A minted identity is not "where this was decided", so it is never emitted as source_url.
|
|
190
|
+
// The agent is told the origin is unverified instead - an `align://` string handed over as
|
|
191
|
+
// an origin gets either fetched or cited, and both are wrong.
|
|
192
|
+
return { source_unverified: true };
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The projection is an ALLOWLIST, not a delete.
|
|
196
|
+
*
|
|
197
|
+
* ALI-498: one 12-row prod component carried 43,327 characters of `decision_json`. A delete
|
|
198
|
+
* list only removes the heavy fields somebody thought of; an allowlist cannot leak a field
|
|
199
|
+
* the gateway adds later. OMIT_RESULT_KEYS in mcp.ts is the belt to this braces.
|
|
200
|
+
*/
|
|
201
|
+
function present(d) {
|
|
202
|
+
return {
|
|
203
|
+
id: d.id,
|
|
204
|
+
title: d.title,
|
|
205
|
+
...(d.summary ? { summary: truncate(d.summary) } : {}),
|
|
206
|
+
...(d.platform ? { platform: d.platform } : {}),
|
|
207
|
+
...(d.status ? { status: d.status } : {}),
|
|
208
|
+
created_at: d.created_at,
|
|
209
|
+
// Key omitted when absent: a missing source date must not render as one.
|
|
210
|
+
...(d.decided_at ? { decided_at: d.decided_at } : {}),
|
|
211
|
+
...(d.source_created_at ? { source_created_at: d.source_created_at } : {}),
|
|
212
|
+
...(d.date_basis ? { date_basis: d.date_basis } : {}),
|
|
213
|
+
...sourceFields(d.source_url),
|
|
214
|
+
...(repositoryOf(d.source_url) ? { repository: repositoryOf(d.source_url) } : {}),
|
|
215
|
+
...(citationFor(d.source_url) ? { cite: citationFor(d.source_url) } : {}),
|
|
216
|
+
...(d.matched_by ? { matched_by: d.matched_by } : {}),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
export function topicTimelineMessage(opts) {
|
|
220
|
+
const { count, semanticRan, topic, backgroundCount, whyState, disagreementCount, stillOpenState, chainCount, chainPlatforms, chainSupersededCount, chainCorrectedCount, } = opts;
|
|
221
|
+
/**
|
|
222
|
+
* F11 (Copilot, #296 suppressed at :170): the early return used to bypass the PARTIAL notice
|
|
223
|
+
* entirely. "No decisions found" plus a silently lexical-only search is the worst pairing in
|
|
224
|
+
* this whole message - the agent concludes the graph has nothing on the topic, when the half
|
|
225
|
+
* of retrieval that finds differently-worded decisions never ran. Declared before the branch
|
|
226
|
+
* so both paths use one writer of the sentence.
|
|
227
|
+
*/
|
|
228
|
+
const partial = semanticRan
|
|
229
|
+
? ''
|
|
230
|
+
: ' PARTIAL: semantic retrieval was unavailable, so this is lexical matches only and may be missing related decisions that use different wording.';
|
|
231
|
+
if (count === 0) {
|
|
232
|
+
return `No decisions found about "${topic}". Try a broader phrase, or search to see what the graph does cover.${partial}`;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* F3 (Copilot, #296 inline at :175): CHAIN-scoped, not retrieval-wide.
|
|
236
|
+
*
|
|
237
|
+
* This used the gateway's `superseded_count`, which covers everything RETRIEVED, while
|
|
238
|
+
* calling it "the history explaining why the current answer is current". A superseded
|
|
239
|
+
* BACKGROUND match is not that history and is not even listed for the agent to inspect, so
|
|
240
|
+
* the sentence named rows nobody can see. The summary line further down was already
|
|
241
|
+
* chain-scoped; these two now agree. `supersededCount` is deliberately no longer read here -
|
|
242
|
+
* it stays in the payload, where it correctly describes the retrieved set.
|
|
243
|
+
*/
|
|
244
|
+
const history = chainSupersededCount > 0
|
|
245
|
+
? ` ${chainSupersededCount} of them are superseded or archived - that is the history explaining why the current answer is current.`
|
|
246
|
+
: '';
|
|
247
|
+
/**
|
|
248
|
+
* ALI-1010. The one clause that stops a correction being told as a reversal, and the single
|
|
249
|
+
* clause most responsible for the `reversed` split this port is measured on.
|
|
250
|
+
*
|
|
251
|
+
* Conditional, like `why` and the Contested slot: on a chain with no corrected decision this
|
|
252
|
+
* would send the agent looking for rows that are not there. And it has to NAME the wrong
|
|
253
|
+
* rendering, because everything else in this message pushes the other way - the compact
|
|
254
|
+
* template asks for "the biggest reversal" and the full-timeline rules say "name which
|
|
255
|
+
* decision replaced them". A model handed those and a status it has never seen will reach
|
|
256
|
+
* for the supersession vocabulary it already has.
|
|
257
|
+
*
|
|
258
|
+
* The status is the only signal the agent gets: `superseded` and `corrected` are both
|
|
259
|
+
* not-active and look alike from the row alone, which is exactly why the difference is
|
|
260
|
+
* spelled out here rather than left to be inferred.
|
|
261
|
+
*/
|
|
262
|
+
const corrections = chainCorrectedCount > 0
|
|
263
|
+
? ` ${chainCorrectedCount} decision(s) in this chain have status \`corrected\`: the record was NEVER TRUE and has been corrected, which is NOT a reversal and NOT a supersession - nothing changed in the world, the graph simply held something wrong. Say "corrected" or "was never true"; never "replaced", "reversed", "superseded" or "changed their mind" about one of these, and never count it as part of the history explaining why the current answer is current. A corrected decision is excluded from the superseded count above for this reason.`
|
|
264
|
+
: '';
|
|
265
|
+
/**
|
|
266
|
+
* ALI-590, the other load-bearing addition. Without it an agent reads every row it is
|
|
267
|
+
* handed, and on a mature graph most rows are adjacent-but-unrelated - a webhook-security
|
|
268
|
+
* topic pulls legal, DPA and pricing tickets over the 0.25 similarity floor. Naming the
|
|
269
|
+
* count and forbidding the enumeration is what turns 50 rows into a story.
|
|
270
|
+
*/
|
|
271
|
+
const background = backgroundCount > 0
|
|
272
|
+
? ` ${backgroundCount} further decision(s) matched this topic loosely and are NOT listed - they are summarised in \`background\`. Say the number in one clause if it is useful ("about a dozen adjacent decisions"); do not ask for them and do not imply the chain is everything.`
|
|
273
|
+
: '';
|
|
274
|
+
/**
|
|
275
|
+
* The `why` clause replaces an explicit instruction to go and call the rationale tool, which
|
|
276
|
+
* produced one follow-up call per interesting decision (five on an observed prod session).
|
|
277
|
+
* The reasons for the arguing decisions are now IN this payload, so the instruction is to
|
|
278
|
+
* use them, and to fall back to the tool only for a decision this payload does not cover.
|
|
279
|
+
*
|
|
280
|
+
* CONDITIONAL on `why` actually being present, because the key is omitted when the gateway
|
|
281
|
+
* sent nothing (an older gateway, or a degraded rationale lookup). Promising a field that is
|
|
282
|
+
* absent is worse than not mentioning it: the agent either hunts for it or decides the
|
|
283
|
+
* reasons are unavailable and does not fall back.
|
|
284
|
+
*/
|
|
285
|
+
const why = whyState === 'present'
|
|
286
|
+
? ` \`why\` carries each arguing decision's reason and logged risks - use it directly and do NOT call ${DECISION_RATIONALE_TOOL} for a decision that appears there; call it only for one that does not appear there${
|
|
287
|
+
// With real questions in the payload the risks synthesis is retired for this
|
|
288
|
+
// response: two stated sources for one section is how the model picks the wrong one
|
|
289
|
+
// (ALI-627).
|
|
290
|
+
stillOpenState === 'present' ? '' : ', and draw the closing open-questions line from its risks'}.`
|
|
291
|
+
: whyState === 'empty'
|
|
292
|
+
? // The gateway looked across this chain and nothing is recorded. Sending the agent to
|
|
293
|
+
// the rationale tool per decision would find the same nothing, one call at a time,
|
|
294
|
+
// so the instruction is to SAY it rather than to go hunting.
|
|
295
|
+
` The gateway looked for recorded reasoning on this chain and found none - say the reasons are not recorded rather than calling ${DECISION_RATIONALE_TOOL} for each decision.`
|
|
296
|
+
: ` This payload carries no \`why\`, so call ${DECISION_RATIONALE_TOOL} for the decisions whose reasoning the answer needs${
|
|
297
|
+
// Only point at `disagreements` when the field is here AND non-empty. Pointing at
|
|
298
|
+
// one absent field from inside the fallback for another is the same defect nested
|
|
299
|
+
// one level down, and pointing at an empty list is a hunt with no quarry.
|
|
300
|
+
(disagreementCount ?? 0) > 0 ? ' - prefer the ones named in `disagreements`' : ''}.`;
|
|
301
|
+
/**
|
|
302
|
+
* Conditional for the same reason as the `why` clause: an instruction naming a field that is
|
|
303
|
+
* not in the payload sends the agent hunting, and on an older gateway neither key exists.
|
|
304
|
+
* Every clause here must be true of THIS response, not of the newest gateway.
|
|
305
|
+
*/
|
|
306
|
+
const disagreements = disagreementCount === undefined
|
|
307
|
+
? ' This payload does not report which decisions conflict, so say the conflict relationships were unavailable rather than implying there are none.'
|
|
308
|
+
: disagreementCount === 0
|
|
309
|
+
? ' The gateway looked for conflicts touching this chain and found none - say so in one clause rather than staying silent.'
|
|
310
|
+
: ' Fill the **Contested** slot naming the ids in `disagreements` and say a later decision argues with them - in both the compact answer and the full timeline, because a hidden conflict is the one thing compaction must never buy.';
|
|
311
|
+
/**
|
|
312
|
+
* A worked TEMPLATE, not adjectives about clarity - in TWO tiers.
|
|
313
|
+
*
|
|
314
|
+
* A live prod run produced a correct answer as seven dense paragraphs: unreadable on a
|
|
315
|
+
* shared screen. "Render this as a story, not a flat list" is an adjective - it names what
|
|
316
|
+
* to avoid and says nothing about shape. A line template fixes ordering, length and where
|
|
317
|
+
* the status goes; "be concise" fixes nothing. The word cap is a number for the same reason:
|
|
318
|
+
* it is checkable, and a model asked to "keep it brief" writes a sentence per entry and
|
|
319
|
+
* rebuilds the wall.
|
|
320
|
+
*/
|
|
321
|
+
// The Contested slot exists only when there is a conflict to put in it: a slot over an empty
|
|
322
|
+
// or absent list sends the model hunting (the same conditionality rule as `why` above).
|
|
323
|
+
const contestedSlot = (disagreementCount ?? 0) > 0
|
|
324
|
+
? '\n\n**Contested:** {which decision argues with which, one line}'
|
|
325
|
+
: '';
|
|
326
|
+
// The offer names only what THIS payload carries: risks ride in `why`, questions in
|
|
327
|
+
// `still_open`, and promising an absent one makes the follow-up a hunt or an invention.
|
|
328
|
+
// Offers only what THIS payload actually carries. An `empty` state is a field that arrived
|
|
329
|
+
// with nothing in it, so offering "the open risks" off the back of it would be a promise the
|
|
330
|
+
// follow-up cannot keep.
|
|
331
|
+
const offerItems = `the full chain${whyState === 'present' ? ', the open risks' : ''}${stillOpenState === 'present' ? ', the open questions' : ''}`;
|
|
332
|
+
const render = ` Answer COMPACTLY by default, never as paragraphs - the user asked a question, not for a history. Link every decision you name (dated row, Now, Contested, supersedes) with decision_url when present, else source_url; do not invent links. Use exactly this shape, with a blank line between sections:` +
|
|
333
|
+
`\n\n**Now:** {current position in one sentence} - {title} ({status})${contestedSlot}` +
|
|
334
|
+
`\n\n{up to three pivotal dated chain steps - the first position, the biggest reversal, the newest - one line each, in the full timeline's line shape}` +
|
|
335
|
+
`\n\n${chainCount} decision(s) across ${chainPlatforms.join(', ') || 'unknown tool(s)'} got it here ({oldest date} - {newest date}, ${chainSupersededCount} superseded or archived).` +
|
|
336
|
+
// C6 (Copilot, #298 suppressed at :523). The stillOpenState fix reached only the
|
|
337
|
+
// full-timeline section; this compact slot is the DEFAULT path and asked for a question
|
|
338
|
+
// unconditionally, so `still_open: []` still invited the invention the empty state exists
|
|
339
|
+
// to prevent - the same defect one level up, on the more-travelled route.
|
|
340
|
+
//
|
|
341
|
+
// An interpolation rather than a bare parenthesised ternary: a conditional dropped into a
|
|
342
|
+
// chain of literals makes the whole concatenation literal-plus-expression, which is what
|
|
343
|
+
// eslint's prefer-template objects to. Identical output.
|
|
344
|
+
`\n\n${stillOpenState === 'empty'
|
|
345
|
+
? '{one line saying the chain leaves no open question}'
|
|
346
|
+
: '{the single sharpest open question, one line}'}` +
|
|
347
|
+
`\n\n{one-line offer of the rest - ${offerItems} - inviting the user to ask for the story}` +
|
|
348
|
+
`\n\nRender the FULL VERTICAL TIMELINE instead ONLY when the user ${STORY_GATE}, the history, or how it got here - or as the follow-up after the compact answer. That shape, also with a blank line between sections:` +
|
|
349
|
+
'\n\nOpen with the same **Now:** line, then:' +
|
|
350
|
+
'\n\n**How it got here**' +
|
|
351
|
+
'\n`DD Mon` `{platform}` **{short title}** - {why, max 15 words} - {cite or id} - {status}' +
|
|
352
|
+
'\n`DD Mon` `{platform}` **{short title}** - ... (one line per decision, oldest first)' +
|
|
353
|
+
'\n\n`{platform}` is the tool the decision was made in - teams, slack, jira, github, linear, confluence. NEVER omit the platform: a Teams meeting contradicting a GitHub pull request is the thing no single tool can show, and it is invisible if every line looks alike. The cite implies it for some rows and not others, so print it explicitly on all of them.' +
|
|
354
|
+
'\n\nThe gutter is the date and NEVER an id: print the row\'s date, not a ticket key, and never the same identifier twice on one line. `date_basis` says which clock it is - `decided` (`decided_at`, the source decided it), `created` (`source_created_at`: RAISED only, never agreed), `recorded` (`created_at`, Align\'s ingest minute, not a source date). Suffix anything not `decided` right after the date - `(raised)` or `(seen)` - or a column of dates all reads as decisions. Where several share a date, normal for an imported backlog, repeat the date. If MOST are `recorded`, add ONE closing note that the graph lacks their source dates.' +
|
|
355
|
+
// C3 (Copilot, #298 inline at :446). Gated on `why`: with no entries there are no risks
|
|
356
|
+
// to line up, so an unconditional section invites exactly the fabrication the empty state
|
|
357
|
+
// exists to prevent. The empty case says so rather than going silent, because silence
|
|
358
|
+
// reads as "there are none" too and only one of those is a measurement.
|
|
359
|
+
`${whyState === 'present'
|
|
360
|
+
? '\n\n**Open risks** - one short line each, naming the decision it came from.'
|
|
361
|
+
: whyState === 'empty'
|
|
362
|
+
? '\n\n**Open risks** - no risks were recorded against this chain; say so in one clause and do not infer any.'
|
|
363
|
+
: ''}`;
|
|
364
|
+
/**
|
|
365
|
+
* Two sources, one section, stated conditionally (ALI-627). With `still_open` present the
|
|
366
|
+
* section closes on the decisions' own stated questions; without it, the synthesis from
|
|
367
|
+
* risks remains - a promise scoped to THIS response, like the `why` clause above.
|
|
368
|
+
*/
|
|
369
|
+
// Both trailing sections are tier-labelled: without a label they read as unconditional
|
|
370
|
+
// rules of the compact default too, which quietly rebuilds the wall.
|
|
371
|
+
const stillOpenSection = stillOpenState === 'present'
|
|
372
|
+
? '\n\n**Still open** (the full timeline closes on this) - one line per question in `still_open`, naming the decision it came from; end with the single sharpest.'
|
|
373
|
+
: stillOpenState === 'empty'
|
|
374
|
+
? // The chain was asked and states none. Asking for "the single sharpest unanswered
|
|
375
|
+
// question" here is what made the model invent one.
|
|
376
|
+
'\n\n**Still open** (the full timeline closes on this) - this chain states no open questions; say so in one clause rather than naming one.'
|
|
377
|
+
: '\n\n**Still open** (the full timeline closes on this) - the single sharpest unanswered question, one line.';
|
|
378
|
+
const renderRules =
|
|
379
|
+
// F4 (Copilot, #296 at :300) then C4 (#298 at :532). The original closed "Cite
|
|
380
|
+
// decision_url and source_url as different links", unconditionally, in a port that never
|
|
381
|
+
// emits decision_url. The first replacement then demanded `source_url` just as
|
|
382
|
+
// unconditionally - and `present()` deliberately omits THAT for a synthetic identity and
|
|
383
|
+
// for a row with no source at all, so it recreated the same defect one field along. The
|
|
384
|
+
// rule is conditional on both sides now, and it names what to do when neither arrived,
|
|
385
|
+
// because "link it" with nothing to link is what produces an invented URL.
|
|
386
|
+
'\n\nRules for the FULL timeline: ONE LINE PER DECISION, never a paragraph. Max 15 words of explanation per line. Mark superseded entries and name which decision replaced them. Link a decision when its row carries a source_url, which is where it was decided; a row marked `source_unverified` has no link anyone can open, so name it without one and never substitute a link you did not receive.';
|
|
387
|
+
return `${count} decision(s) about "${topic}".${history}${corrections}${partial}${background}${render}${stillOpenSection}${renderRules}${disagreements}${why}`;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Shape one gateway topic-timeline response for an agent: project the rows, split the chain
|
|
391
|
+
* from the background, and attach the rendering contract.
|
|
392
|
+
*
|
|
393
|
+
* Pure, and exported, so every clause of the contract is assertable without standing up an
|
|
394
|
+
* MCP server or a gateway.
|
|
395
|
+
*/
|
|
396
|
+
export function shapeTopicTimeline(result, requestedTopic) {
|
|
397
|
+
const rows = Array.isArray(result?.decisions) ? result.decisions : [];
|
|
398
|
+
const semanticRan = result?.retrieval?.semantic !== false;
|
|
399
|
+
/**
|
|
400
|
+
* The chain is what gets narrated; everything else is counted (ALI-590).
|
|
401
|
+
*
|
|
402
|
+
* `chain_ids` is a NEWER gateway field, and this client and the gateway deploy separately -
|
|
403
|
+
* so an older gateway (or one whose edge lookup degraded) sends no ids and every decision
|
|
404
|
+
* stays in the chain, which is the pre-ALI-590 behaviour. Falling back to "narrate
|
|
405
|
+
* everything" is the right direction to fail: a shorter answer that silently dropped
|
|
406
|
+
* history is the one nobody could detect.
|
|
407
|
+
*/
|
|
408
|
+
const chainIds = Array.isArray(result.chain_ids) ? new Set(result.chain_ids) : undefined;
|
|
409
|
+
const chain = chainIds ? rows.filter((d) => chainIds.has(d.id)) : rows;
|
|
410
|
+
const background = chainIds ? rows.filter((d) => !chainIds.has(d.id)) : [];
|
|
411
|
+
const backgroundPlatforms = Array.isArray(result.background_platforms)
|
|
412
|
+
? result.background_platforms
|
|
413
|
+
: [...new Set(background.map((d) => d.platform).filter((p) => Boolean(p)))].sort();
|
|
414
|
+
/**
|
|
415
|
+
* Both shape fields are scoped to the CHAIN, not to the retrieved set.
|
|
416
|
+
*
|
|
417
|
+
* The gateway computes them over everything it retrieved, which is right for a payload that
|
|
418
|
+
* returns everything it retrieved. This tool returns only the chain, so forwarding them
|
|
419
|
+
* unfiltered would name a decision that is not in `decisions` - enumerating background
|
|
420
|
+
* material through the back door and citing titles the agent cannot link.
|
|
421
|
+
*/
|
|
422
|
+
const inChain = chainIds
|
|
423
|
+
? (id) => typeof id === 'string' && chainIds.has(id)
|
|
424
|
+
: () => true;
|
|
425
|
+
/**
|
|
426
|
+
* `undefined` when the gateway did not send the field, `[]` only when it sent an empty one.
|
|
427
|
+
*
|
|
428
|
+
* Those are different answers and collapsing them loses the honest one: an empty array from
|
|
429
|
+
* a gateway that never reports disagreements asserts "we looked and there are none", which
|
|
430
|
+
* is the stronger claim. A gateway that DID look and found nothing keeps its empty array -
|
|
431
|
+
* that is a real result, and it is how the absence gets reported.
|
|
432
|
+
*/
|
|
433
|
+
const disagreements = Array.isArray(result.disagreements)
|
|
434
|
+
? result.disagreements.filter((d) => inChain(d?.from?.id) && inChain(d?.to?.id))
|
|
435
|
+
: undefined;
|
|
436
|
+
const why = (Array.isArray(result.why) ? result.why : []).filter((w) => inChain(w?.id));
|
|
437
|
+
// Chain-scoped like `why`: a question naming a background decision would cite a title the
|
|
438
|
+
// agent has no row for.
|
|
439
|
+
const stillOpen = (Array.isArray(result.still_open) ? result.still_open : []).filter((s) => inChain(s?.id));
|
|
440
|
+
/**
|
|
441
|
+
* Presence and non-emptiness, kept apart (Copilot, #296 inline at :378).
|
|
442
|
+
*
|
|
443
|
+
* `absent` is "the gateway did not send the field" - an older gateway, or a degraded lookup.
|
|
444
|
+
* `empty` is "it sent one with nothing in it", which is a real observation and the stronger
|
|
445
|
+
* claim. Note a field that ARRIVED and was then filtered down to nothing by the chain scope
|
|
446
|
+
* is `empty` and not `absent`: the gateway did look, and what it found does not apply to the
|
|
447
|
+
* rows the agent is being shown. Either way the honest answer is "none here", never "we
|
|
448
|
+
* could not look".
|
|
449
|
+
*/
|
|
450
|
+
const stateOf = (raw, filtered) => !Array.isArray(raw) ? 'absent' : filtered.length > 0 ? 'present' : 'empty';
|
|
451
|
+
const whyState = stateOf(result.why, why);
|
|
452
|
+
const stillOpenState = stateOf(result.still_open, stillOpen);
|
|
453
|
+
return {
|
|
454
|
+
topic: result.topic ?? requestedTopic,
|
|
455
|
+
count: result.count ?? rows.length,
|
|
456
|
+
superseded_count: result.superseded_count ?? 0,
|
|
457
|
+
platforms: result.platforms ?? [],
|
|
458
|
+
spans_platforms: Boolean(result.spans_platforms),
|
|
459
|
+
retrieval: result.retrieval ?? { lexical: true, semantic: semanticRan },
|
|
460
|
+
...(Array.isArray(result.activity) ? { activity: result.activity } : {}),
|
|
461
|
+
...(disagreements ? { disagreements } : {}),
|
|
462
|
+
// Forwarded verbatim: the gateway already clipped every string and never sends
|
|
463
|
+
// decision_json, so there is nothing left for this projection to bound.
|
|
464
|
+
// Emitted whenever the gateway SENT the field, empty included - the same rule
|
|
465
|
+
// `disagreements` above already follows. A key that is present and empty is how the
|
|
466
|
+
// absence gets reported honestly.
|
|
467
|
+
...(whyState !== 'absent' ? { why } : {}),
|
|
468
|
+
...(stillOpenState !== 'absent' ? { still_open: stillOpen } : {}),
|
|
469
|
+
decisions: chain.map(present),
|
|
470
|
+
/**
|
|
471
|
+
* Counted, never enumerated. The whole defect this fixes is an agent reading 50 rows
|
|
472
|
+
* aloud, so handing the tail back in any listable form would reintroduce it - the count
|
|
473
|
+
* and the platforms are enough to say "there is more here" honestly.
|
|
474
|
+
*/
|
|
475
|
+
...(background.length > 0
|
|
476
|
+
? {
|
|
477
|
+
background: {
|
|
478
|
+
count: background.length,
|
|
479
|
+
platforms: backgroundPlatforms,
|
|
480
|
+
note: 'Matched the topic loosely - not part of the decision chain. Not listed on purpose.',
|
|
481
|
+
},
|
|
482
|
+
}
|
|
483
|
+
: {}),
|
|
484
|
+
message: topicTimelineMessage({
|
|
485
|
+
count: result.count ?? rows.length,
|
|
486
|
+
semanticRan,
|
|
487
|
+
topic: result.topic ?? requestedTopic,
|
|
488
|
+
backgroundCount: background.length,
|
|
489
|
+
whyState,
|
|
490
|
+
disagreementCount: disagreements === undefined ? undefined : disagreements.length,
|
|
491
|
+
stillOpenState,
|
|
492
|
+
chainCount: chain.length,
|
|
493
|
+
chainPlatforms: [
|
|
494
|
+
...new Set(chain.map((d) => d.platform).filter((p) => Boolean(p))),
|
|
495
|
+
],
|
|
496
|
+
chainSupersededCount: chain.filter((d) => d.status === 'superseded' || d.status === 'archived')
|
|
497
|
+
.length,
|
|
498
|
+
// Counted separately, never added to the line above: the gateway's RETIRED set draws the
|
|
499
|
+
// same boundary, and the two must agree or the message contradicts the payload.
|
|
500
|
+
chainCorrectedCount: chain.filter((d) => d.status === 'corrected').length,
|
|
501
|
+
}),
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
//# sourceMappingURL=mcp-timeline-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-timeline-tools.js","sourceRoot":"","sources":["../../src/lib/mcp-timeline-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,7 +24,7 @@ export interface PersonalCreds {
|
|
|
24
24
|
siteBase?: string;
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
|
-
* Resolve credentials for `align
|
|
27
|
+
* Resolve credentials for `align connect <src> --personal`: the cached personal OAuth token
|
|
28
28
|
* when one exists, otherwise the browser flow. Throws with a user-readable message when the
|
|
29
29
|
* flow cannot run here - callers print it and exit rather than opening a doomed browser.
|
|
30
30
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// The Align Personal OAuth flow, shared by `align setup` and `align
|
|
1
|
+
// The Align Personal OAuth flow, shared by `align setup` and `align connect <src> --personal`
|
|
2
2
|
// (ALI-388). Lifted verbatim from setup.ts so both entry points use one implementation: the
|
|
3
3
|
// gateway's /oauth/cli-start/:key begins the flow, the browser lands credentials on the
|
|
4
4
|
// localhost listener (cli-oauth.ts), and tokens persist in the local config under the
|
|
@@ -109,7 +109,7 @@ export async function collectTokensViaOAuth(source, client, config, envName, res
|
|
|
109
109
|
return { token: accessToken, ...(cloudId ? { cloudId } : {}), ...(siteBase ? { siteBase } : {}) };
|
|
110
110
|
}
|
|
111
111
|
// Persist a connector's OAuth token plus Atlassian cloudId/site base so future
|
|
112
|
-
// runs (and `align
|
|
112
|
+
// runs (and `align connect`) can reuse the credentials without re-auth.
|
|
113
113
|
export function persistConnectorCreds(config, envName, key, credentials) {
|
|
114
114
|
const accessToken = credentials['access_token'];
|
|
115
115
|
if (!accessToken)
|
|
@@ -123,7 +123,7 @@ export function persistConnectorCreds(config, envName, key, credentials) {
|
|
|
123
123
|
config.setConnectorSiteBase(envName, key, siteBase);
|
|
124
124
|
}
|
|
125
125
|
// ---------------------------------------------------------------------------
|
|
126
|
-
// `align
|
|
126
|
+
// `align connect <src> --personal` (ALI-388)
|
|
127
127
|
// ---------------------------------------------------------------------------
|
|
128
128
|
/**
|
|
129
129
|
* Import source id -> the gateway OAuth key for a personal (non-admin) connection.
|
|
@@ -143,7 +143,7 @@ export const PERSONAL_OAUTH_KEYS = {
|
|
|
143
143
|
zoom: 'zoom',
|
|
144
144
|
};
|
|
145
145
|
/**
|
|
146
|
-
* Resolve credentials for `align
|
|
146
|
+
* Resolve credentials for `align connect <src> --personal`: the cached personal OAuth token
|
|
147
147
|
* when one exists, otherwise the browser flow. Throws with a user-readable message when the
|
|
148
148
|
* flow cannot run here - callers print it and exit rather than opening a doomed browser.
|
|
149
149
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"personal-oauth.js","sourceRoot":"","sources":["../../src/lib/personal-oauth.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"personal-oauth.js","sourceRoot":"","sources":["../../src/lib/personal-oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ export declare function resolveEnv(flagValue?: string, opts?: {
|
|
|
3
3
|
preferLocalEmbedded?: boolean;
|
|
4
4
|
}): EnvName;
|
|
5
5
|
/**
|
|
6
|
-
* Env resolution for `align
|
|
6
|
+
* Env resolution for `align connect <tool>` (ALI-675).
|
|
7
7
|
*
|
|
8
8
|
* Imports were left off the preferLocalEmbedded redirect on the premise that
|
|
9
9
|
* they are cloud-only. They are not: the local-embedded client implements
|
package/dist/lib/resolve-env.js
CHANGED
|
@@ -26,7 +26,7 @@ export function resolveEnv(flagValue, opts = {}) {
|
|
|
26
26
|
return defaultEnv;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
* Env resolution for `align
|
|
29
|
+
* Env resolution for `align connect <tool>` (ALI-675).
|
|
30
30
|
*
|
|
31
31
|
* Imports were left off the preferLocalEmbedded redirect on the premise that
|
|
32
32
|
* they are cloud-only. They are not: the local-embedded client implements
|