@humanbased/crosscheck 1.2.0-beta.80 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +388 -149
- package/README.zh.md +1 -1
- package/crosscheck.config.example.yml +2 -63
- package/dist/__tests__/codex.test.js +27 -14
- package/dist/__tests__/codex.test.js.map +1 -1
- package/dist/__tests__/comment-bodies.test.js +1 -49
- package/dist/__tests__/comment-bodies.test.js.map +1 -1
- package/dist/__tests__/conflict-resolve.test.js +1 -44
- package/dist/__tests__/conflict-resolve.test.js.map +1 -1
- package/dist/__tests__/fix.test.js +0 -33
- package/dist/__tests__/fix.test.js.map +1 -1
- package/dist/__tests__/onboard-preservation.test.js +0 -5
- package/dist/__tests__/onboard-preservation.test.js.map +1 -1
- package/dist/__tests__/optimize.test.js +0 -2
- package/dist/__tests__/optimize.test.js.map +1 -1
- package/dist/__tests__/repo-picker.test.js +1 -7
- package/dist/__tests__/repo-picker.test.js.map +1 -1
- package/dist/__tests__/review-comment-body.test.js +0 -35
- package/dist/__tests__/review-comment-body.test.js.map +1 -1
- package/dist/__tests__/review-models.test.js +3 -19
- package/dist/__tests__/review-models.test.js.map +1 -1
- package/dist/__tests__/runner.test.js +1 -29
- package/dist/__tests__/runner.test.js.map +1 -1
- package/dist/cli.js +0 -29
- package/dist/cli.js.map +1 -1
- package/dist/commands/onboard.d.ts +0 -11
- package/dist/commands/onboard.d.ts.map +1 -1
- package/dist/commands/onboard.js +2 -88
- package/dist/commands/onboard.js.map +1 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +6 -65
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +3 -23
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +1 -53
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +6 -52
- package/dist/commands/watch.js.map +1 -1
- package/dist/config/loader.d.ts +1 -3
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +0 -13
- package/dist/config/loader.js.map +1 -1
- package/dist/config/review-model-tiers.json +3 -3
- package/dist/config/schema.d.ts +10 -254
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +2 -62
- package/dist/config/schema.js.map +1 -1
- package/dist/github/client.d.ts +1 -6
- package/dist/github/client.d.ts.map +1 -1
- package/dist/github/client.js +7 -15
- package/dist/github/client.js.map +1 -1
- package/dist/issues/ticket-ref.d.ts.map +1 -1
- package/dist/issues/ticket-ref.js +5 -6
- package/dist/issues/ticket-ref.js.map +1 -1
- package/dist/lib/clone.d.ts +0 -1
- package/dist/lib/clone.d.ts.map +1 -1
- package/dist/lib/clone.js +10 -32
- package/dist/lib/clone.js.map +1 -1
- package/dist/lib/comment-bodies.d.ts +0 -35
- package/dist/lib/comment-bodies.d.ts.map +1 -1
- package/dist/lib/comment-bodies.js +9 -43
- package/dist/lib/comment-bodies.js.map +1 -1
- package/dist/lib/repo-picker.d.ts +0 -3
- package/dist/lib/repo-picker.d.ts.map +1 -1
- package/dist/lib/repo-picker.js +9 -45
- package/dist/lib/repo-picker.js.map +1 -1
- package/dist/lib/review-models.d.ts +2 -15
- package/dist/lib/review-models.d.ts.map +1 -1
- package/dist/lib/review-models.js +6 -26
- package/dist/lib/review-models.js.map +1 -1
- package/dist/lib/runner.d.ts +0 -12
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/runner.js +42 -186
- package/dist/lib/runner.js.map +1 -1
- package/dist/lib/workflow.d.ts +0 -9
- package/dist/lib/workflow.d.ts.map +1 -1
- package/dist/lib/workflow.js +0 -20
- package/dist/lib/workflow.js.map +1 -1
- package/dist/reviewers/claude.d.ts +1 -4
- package/dist/reviewers/claude.d.ts.map +1 -1
- package/dist/reviewers/claude.js +7 -39
- package/dist/reviewers/claude.js.map +1 -1
- package/dist/reviewers/codex.d.ts +1 -3
- package/dist/reviewers/codex.d.ts.map +1 -1
- package/dist/reviewers/codex.js +70 -76
- package/dist/reviewers/codex.js.map +1 -1
- package/dist/reviewers/conflict-resolve.d.ts +1 -3
- package/dist/reviewers/conflict-resolve.d.ts.map +1 -1
- package/dist/reviewers/conflict-resolve.js +6 -21
- package/dist/reviewers/conflict-resolve.js.map +1 -1
- package/dist/reviewers/fix.d.ts +2 -5
- package/dist/reviewers/fix.d.ts.map +1 -1
- package/dist/reviewers/fix.js +10 -26
- package/dist/reviewers/fix.js.map +1 -1
- package/get-started.md +4 -139
- package/package.json +3 -4
- package/assets/icon-256.png +0 -0
- package/assets/linear-comment.svg +0 -18
- package/assets/linear-onboard.svg +0 -30
- package/assets/linear-status.svg +0 -23
- package/assets/linear-test.svg +0 -34
- package/assets/skills/code-review/.crosscheck-skill.json +0 -9
- package/assets/skills/code-review/LICENSE +0 -21
- package/assets/skills/code-review/SKILL.md +0 -89
- package/assets/skills/code-review/agents/openai.yaml +0 -3
- package/assets/skills/code-review-skill/.crosscheck-skill.json +0 -9
- package/assets/skills/code-review-skill/LICENSE +0 -21
- package/assets/skills/code-review-skill/SKILL.md +0 -231
- package/assets/skills/code-review-skill/assets/pr-review-template.md +0 -137
- package/assets/skills/code-review-skill/assets/review-checklist.md +0 -123
- package/assets/skills/code-review-skill/reference/angular.md +0 -768
- package/assets/skills/code-review-skill/reference/architecture-review-guide.md +0 -472
- package/assets/skills/code-review-skill/reference/c.md +0 -890
- package/assets/skills/code-review-skill/reference/code-quality-universal.md +0 -488
- package/assets/skills/code-review-skill/reference/code-review-best-practices.md +0 -136
- package/assets/skills/code-review-skill/reference/common-bugs-checklist.md +0 -286
- package/assets/skills/code-review-skill/reference/cpp.md +0 -893
- package/assets/skills/code-review-skill/reference/cross-cutting/async-concurrency-patterns.md +0 -515
- package/assets/skills/code-review-skill/reference/cross-cutting/error-handling-principles.md +0 -492
- package/assets/skills/code-review-skill/reference/cross-cutting/n-plus-one-queries.md +0 -309
- package/assets/skills/code-review-skill/reference/cross-cutting/sql-injection-prevention.md +0 -308
- package/assets/skills/code-review-skill/reference/cross-cutting/xss-prevention.md +0 -264
- package/assets/skills/code-review-skill/reference/csharp.md +0 -525
- package/assets/skills/code-review-skill/reference/css-less-sass.md +0 -661
- package/assets/skills/code-review-skill/reference/django.md +0 -985
- package/assets/skills/code-review-skill/reference/fastapi.md +0 -580
- package/assets/skills/code-review-skill/reference/go.md +0 -993
- package/assets/skills/code-review-skill/reference/java.md +0 -409
- package/assets/skills/code-review-skill/reference/java8.md +0 -586
- package/assets/skills/code-review-skill/reference/kotlin.md +0 -1018
- package/assets/skills/code-review-skill/reference/nestjs.md +0 -593
- package/assets/skills/code-review-skill/reference/performance-review-guide.md +0 -816
- package/assets/skills/code-review-skill/reference/php.md +0 -684
- package/assets/skills/code-review-skill/reference/python.md +0 -1073
- package/assets/skills/code-review-skill/reference/qt.md +0 -757
- package/assets/skills/code-review-skill/reference/react.md +0 -871
- package/assets/skills/code-review-skill/reference/ruby.md +0 -964
- package/assets/skills/code-review-skill/reference/rust.md +0 -846
- package/assets/skills/code-review-skill/reference/security-review-guide.md +0 -494
- package/assets/skills/code-review-skill/reference/svelte.md +0 -1064
- package/assets/skills/code-review-skill/reference/swift.md +0 -936
- package/assets/skills/code-review-skill/reference/typescript.md +0 -1016
- package/assets/skills/code-review-skill/reference/vue.md +0 -924
- package/assets/skills/code-review-skill/reference/zig.md +0 -440
- package/assets/skills/code-review-skill/scripts/pr-analyzer.py +0 -435
- package/assets/skills/code-review-skill/scripts/test_pr_analyzer.py +0 -380
- package/assets/skills/codebase-design/.crosscheck-skill.json +0 -9
- package/assets/skills/codebase-design/DEEPENING.md +0 -37
- package/assets/skills/codebase-design/DESIGN-IT-TWICE.md +0 -44
- package/assets/skills/codebase-design/LICENSE +0 -21
- package/assets/skills/codebase-design/SKILL.md +0 -114
- package/assets/skills/codebase-design/agents/openai.yaml +0 -3
- package/assets/skills/diagnosing-bugs/.crosscheck-skill.json +0 -9
- package/assets/skills/diagnosing-bugs/LICENSE +0 -21
- package/assets/skills/diagnosing-bugs/SKILL.md +0 -134
- package/assets/skills/diagnosing-bugs/agents/openai.yaml +0 -3
- package/assets/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +0 -41
- package/dist/__tests__/can-write-verdict.test.d.ts +0 -2
- package/dist/__tests__/can-write-verdict.test.d.ts.map +0 -1
- package/dist/__tests__/can-write-verdict.test.js +0 -31
- package/dist/__tests__/can-write-verdict.test.js.map +0 -1
- package/dist/__tests__/linear-branding.test.d.ts +0 -2
- package/dist/__tests__/linear-branding.test.d.ts.map +0 -1
- package/dist/__tests__/linear-branding.test.js +0 -156
- package/dist/__tests__/linear-branding.test.js.map +0 -1
- package/dist/__tests__/linear-client.test.d.ts +0 -2
- package/dist/__tests__/linear-client.test.d.ts.map +0 -1
- package/dist/__tests__/linear-client.test.js +0 -120
- package/dist/__tests__/linear-client.test.js.map +0 -1
- package/dist/__tests__/linear-comment.test.d.ts +0 -2
- package/dist/__tests__/linear-comment.test.d.ts.map +0 -1
- package/dist/__tests__/linear-comment.test.js +0 -151
- package/dist/__tests__/linear-comment.test.js.map +0 -1
- package/dist/__tests__/linear-identity.test.d.ts +0 -2
- package/dist/__tests__/linear-identity.test.d.ts.map +0 -1
- package/dist/__tests__/linear-identity.test.js +0 -253
- package/dist/__tests__/linear-identity.test.js.map +0 -1
- package/dist/__tests__/linear-notify.test.d.ts +0 -2
- package/dist/__tests__/linear-notify.test.d.ts.map +0 -1
- package/dist/__tests__/linear-notify.test.js +0 -144
- package/dist/__tests__/linear-notify.test.js.map +0 -1
- package/dist/__tests__/linear-ref.test.d.ts +0 -2
- package/dist/__tests__/linear-ref.test.d.ts.map +0 -1
- package/dist/__tests__/linear-ref.test.js +0 -261
- package/dist/__tests__/linear-ref.test.js.map +0 -1
- package/dist/__tests__/linear-test-ref.test.d.ts +0 -2
- package/dist/__tests__/linear-test-ref.test.d.ts.map +0 -1
- package/dist/__tests__/linear-test-ref.test.js +0 -81
- package/dist/__tests__/linear-test-ref.test.js.map +0 -1
- package/dist/__tests__/linear-verify.test.d.ts +0 -2
- package/dist/__tests__/linear-verify.test.d.ts.map +0 -1
- package/dist/__tests__/linear-verify.test.js +0 -132
- package/dist/__tests__/linear-verify.test.js.map +0 -1
- package/dist/__tests__/linear-worker.test.d.ts +0 -2
- package/dist/__tests__/linear-worker.test.d.ts.map +0 -1
- package/dist/__tests__/linear-worker.test.js +0 -83
- package/dist/__tests__/linear-worker.test.js.map +0 -1
- package/dist/__tests__/linear-write-possible.test.d.ts +0 -2
- package/dist/__tests__/linear-write-possible.test.d.ts.map +0 -1
- package/dist/__tests__/linear-write-possible.test.js +0 -30
- package/dist/__tests__/linear-write-possible.test.js.map +0 -1
- package/dist/__tests__/repository-guidance.test.d.ts +0 -2
- package/dist/__tests__/repository-guidance.test.d.ts.map +0 -1
- package/dist/__tests__/repository-guidance.test.js +0 -107
- package/dist/__tests__/repository-guidance.test.js.map +0 -1
- package/dist/__tests__/review-strategy.test.d.ts +0 -2
- package/dist/__tests__/review-strategy.test.d.ts.map +0 -1
- package/dist/__tests__/review-strategy.test.js +0 -195
- package/dist/__tests__/review-strategy.test.js.map +0 -1
- package/dist/__tests__/skill-attribution.test.d.ts +0 -2
- package/dist/__tests__/skill-attribution.test.d.ts.map +0 -1
- package/dist/__tests__/skill-attribution.test.js +0 -53
- package/dist/__tests__/skill-attribution.test.js.map +0 -1
- package/dist/__tests__/skill-broker.test.d.ts +0 -2
- package/dist/__tests__/skill-broker.test.d.ts.map +0 -1
- package/dist/__tests__/skill-broker.test.js +0 -144
- package/dist/__tests__/skill-broker.test.js.map +0 -1
- package/dist/__tests__/skill-catalog.test.d.ts +0 -2
- package/dist/__tests__/skill-catalog.test.d.ts.map +0 -1
- package/dist/__tests__/skill-catalog.test.js +0 -40
- package/dist/__tests__/skill-catalog.test.js.map +0 -1
- package/dist/__tests__/skill-installer.test.d.ts +0 -2
- package/dist/__tests__/skill-installer.test.d.ts.map +0 -1
- package/dist/__tests__/skill-installer.test.js +0 -96
- package/dist/__tests__/skill-installer.test.js.map +0 -1
- package/dist/__tests__/skills-config.test.d.ts +0 -2
- package/dist/__tests__/skills-config.test.d.ts.map +0 -1
- package/dist/__tests__/skills-config.test.js +0 -12
- package/dist/__tests__/skills-config.test.js.map +0 -1
- package/dist/commands/linear-test.d.ts +0 -18
- package/dist/commands/linear-test.d.ts.map +0 -1
- package/dist/commands/linear-test.js +0 -130
- package/dist/commands/linear-test.js.map +0 -1
- package/dist/commands/skill.d.ts +0 -2
- package/dist/commands/skill.d.ts.map +0 -1
- package/dist/commands/skill.js +0 -16
- package/dist/commands/skill.js.map +0 -1
- package/dist/config/review-strategy.json +0 -202
- package/dist/lib/repository-guidance.d.ts +0 -2
- package/dist/lib/repository-guidance.d.ts.map +0 -1
- package/dist/lib/repository-guidance.js +0 -55
- package/dist/lib/repository-guidance.js.map +0 -1
- package/dist/lib/review-strategy.d.ts +0 -62
- package/dist/lib/review-strategy.d.ts.map +0 -1
- package/dist/lib/review-strategy.js +0 -235
- package/dist/lib/review-strategy.js.map +0 -1
- package/dist/linear/client.d.ts +0 -18
- package/dist/linear/client.d.ts.map +0 -1
- package/dist/linear/client.js +0 -67
- package/dist/linear/client.js.map +0 -1
- package/dist/linear/comment.d.ts +0 -20
- package/dist/linear/comment.d.ts.map +0 -1
- package/dist/linear/comment.js +0 -57
- package/dist/linear/comment.js.map +0 -1
- package/dist/linear/identity.d.ts +0 -59
- package/dist/linear/identity.d.ts.map +0 -1
- package/dist/linear/identity.js +0 -187
- package/dist/linear/identity.js.map +0 -1
- package/dist/linear/notify.d.ts +0 -35
- package/dist/linear/notify.d.ts.map +0 -1
- package/dist/linear/notify.js +0 -76
- package/dist/linear/notify.js.map +0 -1
- package/dist/linear/ref.d.ts +0 -13
- package/dist/linear/ref.d.ts.map +0 -1
- package/dist/linear/ref.js +0 -90
- package/dist/linear/ref.js.map +0 -1
- package/dist/linear/verify.d.ts +0 -26
- package/dist/linear/verify.d.ts.map +0 -1
- package/dist/linear/verify.js +0 -67
- package/dist/linear/verify.js.map +0 -1
- package/dist/skills/attribution.d.ts +0 -4
- package/dist/skills/attribution.d.ts.map +0 -1
- package/dist/skills/attribution.js +0 -14
- package/dist/skills/attribution.js.map +0 -1
- package/dist/skills/broker-server.d.ts +0 -2
- package/dist/skills/broker-server.d.ts.map +0 -1
- package/dist/skills/broker-server.js +0 -17
- package/dist/skills/broker-server.js.map +0 -1
- package/dist/skills/broker.d.ts +0 -42
- package/dist/skills/broker.d.ts.map +0 -1
- package/dist/skills/broker.js +0 -285
- package/dist/skills/broker.js.map +0 -1
- package/dist/skills/catalog.d.ts +0 -28
- package/dist/skills/catalog.d.ts.map +0 -1
- package/dist/skills/catalog.js +0 -104
- package/dist/skills/catalog.js.map +0 -1
- package/dist/skills/installer.d.ts +0 -10
- package/dist/skills/installer.d.ts.map +0 -1
- package/dist/skills/installer.js +0 -138
- package/dist/skills/installer.js.map +0 -1
- package/dist/skills/integrity.d.ts +0 -4
- package/dist/skills/integrity.d.ts.map +0 -1
- package/dist/skills/integrity.js +0 -36
- package/dist/skills/integrity.js.map +0 -1
- package/docs/dynamic-thoroughness.md +0 -286
- package/docs/linear-identity-contract.md +0 -139
- package/docs/linear-identity.md +0 -293
package/dist/linear/client.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
// All Linear API traffic goes through this module — mirrors the rule that GitHub
|
|
2
|
-
// calls go through src/github/client.ts. No raw fetch to api.linear.app elsewhere.
|
|
3
|
-
const GRAPHQL_ENDPOINT = 'https://api.linear.app/graphql';
|
|
4
|
-
const IDENTIFIER_PATTERN = /^([A-Za-z][A-Za-z0-9]{0,9})-(\d+)$/;
|
|
5
|
-
function authHeader(auth) {
|
|
6
|
-
return auth.bearer ? `Bearer ${auth.token}` : auth.token;
|
|
7
|
-
}
|
|
8
|
-
export async function linearGraphQL(auth, query, variables, opts = {}) {
|
|
9
|
-
const doFetch = opts.fetchImpl ?? globalThis.fetch;
|
|
10
|
-
const endpoint = opts.endpoint ?? GRAPHQL_ENDPOINT;
|
|
11
|
-
// The token rides in a header, never in the URL or on argv.
|
|
12
|
-
const response = await doFetch(endpoint, {
|
|
13
|
-
method: 'POST',
|
|
14
|
-
headers: { 'Content-Type': 'application/json', Authorization: authHeader(auth) },
|
|
15
|
-
body: JSON.stringify({ query, variables }),
|
|
16
|
-
});
|
|
17
|
-
const text = await response.text();
|
|
18
|
-
if (!response.ok) {
|
|
19
|
-
throw new Error(`Linear API request failed (HTTP ${response.status})`);
|
|
20
|
-
}
|
|
21
|
-
let parsed;
|
|
22
|
-
try {
|
|
23
|
-
parsed = JSON.parse(text);
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
throw new Error(`Linear API returned a non-JSON response (HTTP ${response.status})`);
|
|
27
|
-
}
|
|
28
|
-
if (parsed.errors && parsed.errors.length > 0) {
|
|
29
|
-
const detail = parsed.errors.map(e => e.message ?? 'unknown error').join('; ');
|
|
30
|
-
throw new Error(`Linear API error: ${detail}`);
|
|
31
|
-
}
|
|
32
|
-
if (parsed.data === undefined) {
|
|
33
|
-
throw new Error('Linear API returned no data');
|
|
34
|
-
}
|
|
35
|
-
return parsed.data;
|
|
36
|
-
}
|
|
37
|
-
const FIND_ISSUE = `query($teamKey: String!, $number: Float!) {
|
|
38
|
-
issues(first: 1, filter: { team: { key: { eq: $teamKey } }, number: { eq: $number } }) {
|
|
39
|
-
nodes { id identifier url }
|
|
40
|
-
}
|
|
41
|
-
}`;
|
|
42
|
-
export async function findIssueByIdentifier(auth, identifier, opts = {}) {
|
|
43
|
-
const match = identifier.match(IDENTIFIER_PATTERN);
|
|
44
|
-
if (!match) {
|
|
45
|
-
throw new Error(`Malformed Linear issue identifier: "${identifier}" (expected e.g. IN-2269)`);
|
|
46
|
-
}
|
|
47
|
-
const data = await linearGraphQL(auth, FIND_ISSUE, { teamKey: match[1].toUpperCase(), number: Number.parseInt(match[2], 10) }, opts);
|
|
48
|
-
return data.issues.nodes[0] ?? null;
|
|
49
|
-
}
|
|
50
|
-
const CREATE_COMMENT = `mutation($issueId: String!, $body: String!, $createAsUser: String) {
|
|
51
|
-
commentCreate(input: { issueId: $issueId, body: $body, createAsUser: $createAsUser }) {
|
|
52
|
-
success
|
|
53
|
-
comment { id url }
|
|
54
|
-
}
|
|
55
|
-
}`;
|
|
56
|
-
export async function postLinearComment(auth, issueId, body, opts = {}) {
|
|
57
|
-
const variables = { issueId, body };
|
|
58
|
-
// Only T1 can attribute the write to the app actor.
|
|
59
|
-
if (auth.createAsUser)
|
|
60
|
-
variables.createAsUser = auth.createAsUser;
|
|
61
|
-
const data = await linearGraphQL(auth, CREATE_COMMENT, variables, opts);
|
|
62
|
-
if (!data.commentCreate.success || !data.commentCreate.comment) {
|
|
63
|
-
throw new Error('Linear rejected the comment mutation');
|
|
64
|
-
}
|
|
65
|
-
return data.commentCreate.comment;
|
|
66
|
-
}
|
|
67
|
-
//# sourceMappingURL=client.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/linear/client.ts"],"names":[],"mappings":"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"}
|
package/dist/linear/comment.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export interface LinearCommentInput {
|
|
2
|
-
/** `🤖 {actor} · {product}` — must lead the comment (IN-2260 step 3). */
|
|
3
|
-
signature: string;
|
|
4
|
-
verdict: string | null;
|
|
5
|
-
reviewer: string;
|
|
6
|
-
origin: string;
|
|
7
|
-
model: string;
|
|
8
|
-
prUrl: string;
|
|
9
|
-
prTitle: string;
|
|
10
|
-
sha?: string;
|
|
11
|
-
summary?: string;
|
|
12
|
-
service?: string;
|
|
13
|
-
/** Workflow step this verdict came from — a recheck must not read as a review. */
|
|
14
|
-
stepType?: string;
|
|
15
|
-
round?: number;
|
|
16
|
-
}
|
|
17
|
-
export declare function buildLinearCommentBody(input: LinearCommentInput): string;
|
|
18
|
-
export declare function normalizeVerdict(verdict: string | null): string;
|
|
19
|
-
export declare function shouldPostToLinear(verdict: string | null, commentOn: readonly string[]): boolean;
|
|
20
|
-
//# sourceMappingURL=comment.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["../../src/linear/comment.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAsBD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CA6BxE;AAKD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE/D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAGhG"}
|
package/dist/linear/comment.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
// Body construction for the comment crosscheck posts back to a PR's Linear issue.
|
|
2
|
-
import { buildAnnotation } from '../lib/annotation.js';
|
|
3
|
-
const DEFAULT_SERVICE = 'crosscheck';
|
|
4
|
-
// The visible line must agree with the annotation. Saying "review" on a recheck
|
|
5
|
-
// made the human-readable text contradict the type=recheck sitting right below it.
|
|
6
|
-
// Returns the whole connective phrase, including the preposition — "fix of" is
|
|
7
|
-
// not English, so the label owns it rather than the template appending one.
|
|
8
|
-
function stepLabel(stepType) {
|
|
9
|
-
switch (stepType) {
|
|
10
|
-
case 'recheck': return 'recheck of';
|
|
11
|
-
case 'fix': return 'fix for';
|
|
12
|
-
case 'conflict-resolve': return 'conflict resolution for';
|
|
13
|
-
default: return 'review of';
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
// A `]` in the PR title would terminate the markdown link label early.
|
|
17
|
-
function escapeLinkLabel(text) {
|
|
18
|
-
return text.replace(/([[\]])/g, '\\$1');
|
|
19
|
-
}
|
|
20
|
-
export function buildLinearCommentBody(input) {
|
|
21
|
-
const verdict = input.verdict ?? 'UNKNOWN';
|
|
22
|
-
const service = input.service ?? DEFAULT_SERVICE;
|
|
23
|
-
const sections = [
|
|
24
|
-
input.signature,
|
|
25
|
-
'',
|
|
26
|
-
// Both halves: the model when the vendor reported one — `default` means it
|
|
27
|
-
// chose without saying which, and naming it would be a guess — and the step
|
|
28
|
-
// label, so a recheck does not read as a review.
|
|
29
|
-
`**${verdict}** — ${input.reviewer}${input.model && input.model !== 'default' ? ` (${input.model})` : ''}` +
|
|
30
|
-
` ${stepLabel(input.stepType)} [${escapeLinkLabel(input.prTitle)}](${input.prUrl})`,
|
|
31
|
-
];
|
|
32
|
-
if (input.summary)
|
|
33
|
-
sections.push('', input.summary);
|
|
34
|
-
// Same annotation schema as the GitHub comment, so one parser reads both.
|
|
35
|
-
sections.push('', buildAnnotation({
|
|
36
|
-
origin: input.origin,
|
|
37
|
-
reviewer: input.reviewer,
|
|
38
|
-
model: input.model,
|
|
39
|
-
type: input.stepType ?? 'review',
|
|
40
|
-
round: input.round ?? 1,
|
|
41
|
-
verdict,
|
|
42
|
-
service,
|
|
43
|
-
...(input.sha && { sha: input.sha }),
|
|
44
|
-
}));
|
|
45
|
-
return sections.join('\n');
|
|
46
|
-
}
|
|
47
|
-
// parseVerdict yields the human spelling `NEEDS WORK`, while config and the
|
|
48
|
-
// annotation schema both use `NEEDS_WORK`. Comparing them raw silently dropped
|
|
49
|
-
// every NEEDS WORK verdict — the most common actionable one.
|
|
50
|
-
export function normalizeVerdict(verdict) {
|
|
51
|
-
return (verdict ?? 'UNKNOWN').trim().toUpperCase().replace(/\s+/g, '_');
|
|
52
|
-
}
|
|
53
|
-
export function shouldPostToLinear(verdict, commentOn) {
|
|
54
|
-
const wanted = normalizeVerdict(verdict);
|
|
55
|
-
return commentOn.some(v => normalizeVerdict(v) === wanted);
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=comment.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"comment.js","sourceRoot":"","sources":["../../src/linear/comment.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAElF,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAoBtD,MAAM,eAAe,GAAG,YAAY,CAAA;AAEpC,gFAAgF;AAChF,mFAAmF;AACnF,+EAA+E;AAC/E,4EAA4E;AAC5E,SAAS,SAAS,CAAC,QAA4B;IAC7C,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,SAAS,CAAC,CAAC,OAAO,YAAY,CAAA;QACnC,KAAK,KAAK,CAAC,CAAC,OAAO,SAAS,CAAA;QAC5B,KAAK,kBAAkB,CAAC,CAAC,OAAO,yBAAyB,CAAA;QACzD,OAAO,CAAC,CAAC,OAAO,WAAW,CAAA;IAC7B,CAAC;AACH,CAAC;AAED,uEAAuE;AACvE,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;AACzC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAyB;IAC9D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,SAAS,CAAA;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,eAAe,CAAA;IAEhD,MAAM,QAAQ,GAAG;QACf,KAAK,CAAC,SAAS;QACf,EAAE;QACF,2EAA2E;QAC3E,4EAA4E;QAC5E,iDAAiD;QACjD,KAAK,OAAO,QAAQ,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACxG,IAAI,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,KAAK,CAAC,KAAK,GAAG;KACtF,CAAA;IAED,IAAI,KAAK,CAAC,OAAO;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IAEnD,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,eAAe,CAAC;QAChC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,QAAQ,IAAI,QAAQ;QAChC,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC;QACvB,OAAO;QACP,OAAO;QACP,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;KACrC,CAAC,CAAC,CAAA;IAEH,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC5B,CAAC;AAED,4EAA4E;AAC5E,+EAA+E;AAC/E,6DAA6D;AAC7D,MAAM,UAAU,gBAAgB,CAAC,OAAsB;IACrD,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AACzE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAsB,EAAE,SAA4B;IACrF,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAA;AAC5D,CAAC"}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { LinearConfig } from '../config/schema.js';
|
|
2
|
-
/** Injectable fetch, so tests never touch the network. */
|
|
3
|
-
export type FetchLike = (url: string, init: RequestInit) => Promise<Response>;
|
|
4
|
-
export type LinearAuthMode = 'api_key' | 'client_credentials';
|
|
5
|
-
/** Credentials read from the environment. Resolved in config/loader.ts — never here. */
|
|
6
|
-
export interface LinearCredentials {
|
|
7
|
-
apiKey?: string;
|
|
8
|
-
clientId?: string;
|
|
9
|
-
clientSecret?: string;
|
|
10
|
-
}
|
|
11
|
-
export interface ResolvedLinearAuth {
|
|
12
|
-
mode: LinearAuthMode;
|
|
13
|
-
/** Bare API key (T0) or minted app token (T1). Never log this. */
|
|
14
|
-
token: string;
|
|
15
|
-
/** T1 tokens need an `Authorization: Bearer` prefix; T0 keys are sent bare. */
|
|
16
|
-
bearer: boolean;
|
|
17
|
-
actor: string;
|
|
18
|
-
/** Rendered `🤖 {actor} · {product}` line. Leads every write in both tiers. */
|
|
19
|
-
signature: string;
|
|
20
|
-
/** Set in T1 only — Linear attributes the write to this display name. */
|
|
21
|
-
createAsUser?: string;
|
|
22
|
-
/** Retained so withWorker() can re-render the signature for a derived actor. */
|
|
23
|
-
signatureTemplate: string;
|
|
24
|
-
product: string;
|
|
25
|
-
}
|
|
26
|
-
export interface MintOptions {
|
|
27
|
-
fetchImpl?: FetchLike;
|
|
28
|
-
}
|
|
29
|
-
export interface ResolveOptions extends MintOptions {
|
|
30
|
-
/** Product name used in the signature template. */
|
|
31
|
-
product?: string;
|
|
32
|
-
}
|
|
33
|
-
export declare class LinearConfigError extends Error {
|
|
34
|
-
readonly userError = true;
|
|
35
|
-
constructor(message: string);
|
|
36
|
-
}
|
|
37
|
-
export declare function isLinearConfigError(err: unknown): boolean;
|
|
38
|
-
export interface SignatureVars {
|
|
39
|
-
actor: string;
|
|
40
|
-
product: string;
|
|
41
|
-
/** Reviewer model, e.g. `claude-opus-4.5`. Absent at auth-resolution time. */
|
|
42
|
-
model?: string;
|
|
43
|
-
/** Reviewing vendor, e.g. `codex`. */
|
|
44
|
-
reviewer?: string;
|
|
45
|
-
/** Pre-rendered markdown image, or '' when no icon is configured. */
|
|
46
|
-
icon?: string;
|
|
47
|
-
}
|
|
48
|
-
export declare function renderSignature(template: string, vars: SignatureVars): string;
|
|
49
|
-
/** Wraps a configured icon URL as inline markdown, or '' when unset. */
|
|
50
|
-
export declare function renderIcon(iconUrl: string): string;
|
|
51
|
-
export declare function normalizeScopes(scopes: string): string;
|
|
52
|
-
export declare function mintAppToken(creds: {
|
|
53
|
-
clientId: string;
|
|
54
|
-
clientSecret: string;
|
|
55
|
-
scopes: string;
|
|
56
|
-
}, opts?: MintOptions): Promise<string>;
|
|
57
|
-
export declare function resolveLinearAuth(config: LinearConfig, creds: LinearCredentials, opts?: ResolveOptions): Promise<ResolvedLinearAuth>;
|
|
58
|
-
export declare function withWorker(auth: ResolvedLinearAuth, worker: string): ResolvedLinearAuth;
|
|
59
|
-
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/linear/identity.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAIvD,0DAA0D;AAC1D,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAE7E,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,oBAAoB,CAAA;AAE7D,wFAAwF;AACxF,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAA;IACpB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gFAAgF;IAChF,iBAAiB,EAAE,MAAM,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW;IACjD,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAOD,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,SAAS,QAAO;gBACb,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAEzD;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAMD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,CAgB7E;AAmBD,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGlD;AAKD,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACjE,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,MAAM,CAAC,CA8CjB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,iBAAiB,EACxB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,kBAAkB,CAAC,CAwD7B;AAWD,wBAAgB,UAAU,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAWvF"}
|
package/dist/linear/identity.js
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
// Tiered Linear identity (IN-2267 / IN-2269).
|
|
2
|
-
//
|
|
3
|
-
// T0 api_key — operator supplies a personal/workspace key. Writes carry a
|
|
4
|
-
// `🤖 {actor} · {product}` signature line. Works everywhere,
|
|
5
|
-
// weakest attribution.
|
|
6
|
-
// T1 client_credentials — operator creates an OAuth app in their own workspace and
|
|
7
|
-
// enables the Client credentials toggle. We mint a Bearer app
|
|
8
|
-
// token per run and pass `createAsUser` on every write, so
|
|
9
|
-
// Linear renders them as the app (botActor), not a human.
|
|
10
|
-
//
|
|
11
|
-
// Hard requirements this module enforces:
|
|
12
|
-
// * Secrets travel in a POST body — never on argv, never in a URL, never logged.
|
|
13
|
-
// * A configured-but-failing T1 mint ABORTS. It must never silently downgrade to
|
|
14
|
-
// api_key, because that would re-attribute agent writes to a human account.
|
|
15
|
-
const TOKEN_ENDPOINT = 'https://api.linear.app/oauth/token';
|
|
16
|
-
const DEFAULT_PRODUCT = 'crosscheck';
|
|
17
|
-
// Misconfiguration (missing env var, rejected credentials) is a user error, so it
|
|
18
|
-
// must surface as exit 1 — the CLI contract reserves 2 for unexpected failures.
|
|
19
|
-
// commands/review.ts already exits 1 here; the workflow path has to agree.
|
|
20
|
-
export class LinearConfigError extends Error {
|
|
21
|
-
userError = true;
|
|
22
|
-
constructor(message) {
|
|
23
|
-
super(message);
|
|
24
|
-
this.name = 'LinearConfigError';
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
export function isLinearConfigError(err) {
|
|
28
|
-
return err instanceof LinearConfigError;
|
|
29
|
-
}
|
|
30
|
-
// Renders the signature template. Unknown placeholders are left alone; known ones
|
|
31
|
-
// with no value resolve to empty, and the leftover punctuation is tidied so a
|
|
32
|
-
// template like `🤖 {icon} {actor} · {product} · {model}` still reads correctly
|
|
33
|
-
// when icon and model are unset.
|
|
34
|
-
export function renderSignature(template, vars) {
|
|
35
|
-
const values = {
|
|
36
|
-
actor: vars.actor,
|
|
37
|
-
product: vars.product,
|
|
38
|
-
model: vars.model ?? '',
|
|
39
|
-
reviewer: vars.reviewer ?? '',
|
|
40
|
-
icon: vars.icon ?? '',
|
|
41
|
-
};
|
|
42
|
-
// Mark where an empty placeholder stood so tidying can target exactly those gaps
|
|
43
|
-
// and leave separators the operator wrote deliberately alone.
|
|
44
|
-
const HOLE = '\u0000';
|
|
45
|
-
const substituted = template.replace(/\{(actor|product|model|reviewer|icon)\}/g, (_match, key) => values[key] === '' ? HOLE : values[key]);
|
|
46
|
-
return tidyHoles(substituted, HOLE);
|
|
47
|
-
}
|
|
48
|
-
// Removes each empty-placeholder hole together with ONE adjacent separator, so
|
|
49
|
-
// `{a} · {model} · {b}` with no model yields `a · b` rather than `a · · b`.
|
|
50
|
-
// Separators the operator wrote between two present values are never touched.
|
|
51
|
-
function tidyHoles(text, hole) {
|
|
52
|
-
const SEP = '(?:\\s*[·—|]\\s*|\\s+)';
|
|
53
|
-
return text
|
|
54
|
-
// hole with a separator on either side — drop the hole and one separator
|
|
55
|
-
.replace(new RegExp(`${SEP}${hole}(?=${SEP})`, 'g'), '')
|
|
56
|
-
// hole at the end of the string, with its leading separator
|
|
57
|
-
.replace(new RegExp(`${SEP}${hole}\\s*$`, 'g'), '')
|
|
58
|
-
// hole at the start, with its trailing separator
|
|
59
|
-
.replace(new RegExp(`^\\s*${hole}${SEP}`, 'g'), '')
|
|
60
|
-
// any hole left over (no adjacent separator)
|
|
61
|
-
.split(hole).join('')
|
|
62
|
-
.trim();
|
|
63
|
-
}
|
|
64
|
-
/** Wraps a configured icon URL as inline markdown, or '' when unset. */
|
|
65
|
-
export function renderIcon(iconUrl) {
|
|
66
|
-
const trimmed = iconUrl.trim();
|
|
67
|
-
return trimmed ? `` : '';
|
|
68
|
-
}
|
|
69
|
-
// Linear's token endpoint documents scope as a COMMA-separated list, but OAuth 2.0
|
|
70
|
-
// itself specifies space-separated, so operators write it both ways. Accept either
|
|
71
|
-
// and always send commas.
|
|
72
|
-
export function normalizeScopes(scopes) {
|
|
73
|
-
return scopes.split(/[\s,]+/).filter(Boolean).join(',');
|
|
74
|
-
}
|
|
75
|
-
export async function mintAppToken(creds, opts = {}) {
|
|
76
|
-
const doFetch = opts.fetchImpl ?? globalThis.fetch;
|
|
77
|
-
// URLSearchParams keeps the secret in the request body. Nothing here reaches argv.
|
|
78
|
-
const body = new URLSearchParams({
|
|
79
|
-
grant_type: 'client_credentials',
|
|
80
|
-
client_id: creds.clientId,
|
|
81
|
-
client_secret: creds.clientSecret,
|
|
82
|
-
scope: normalizeScopes(creds.scopes),
|
|
83
|
-
});
|
|
84
|
-
let response;
|
|
85
|
-
try {
|
|
86
|
-
response = await doFetch(TOKEN_ENDPOINT, {
|
|
87
|
-
method: 'POST',
|
|
88
|
-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
89
|
-
body: body.toString(),
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
catch (err) {
|
|
93
|
-
// Transport failure — Linear is unreachable. Not a configuration problem, so
|
|
94
|
-
// this stays a plain Error and classifies as an unexpected failure (exit 2).
|
|
95
|
-
throw new Error(`Linear token mint failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
96
|
-
}
|
|
97
|
-
const text = await response.text();
|
|
98
|
-
if (!response.ok) {
|
|
99
|
-
// 4xx means Linear rejected these credentials or scopes — the operator can fix
|
|
100
|
-
// that. 5xx is an outage, and 429 is rate limiting: both are transient and must
|
|
101
|
-
// not be blamed on the config.
|
|
102
|
-
const message = `Linear token mint rejected (HTTP ${response.status})`;
|
|
103
|
-
const transient = response.status >= 500 || response.status === 429;
|
|
104
|
-
throw transient ? new Error(message) : new LinearConfigError(message);
|
|
105
|
-
}
|
|
106
|
-
let parsed;
|
|
107
|
-
try {
|
|
108
|
-
parsed = JSON.parse(text);
|
|
109
|
-
}
|
|
110
|
-
catch {
|
|
111
|
-
throw new Error(`Linear token mint returned a non-JSON response (HTTP ${response.status})`);
|
|
112
|
-
}
|
|
113
|
-
const token = parsed.access_token;
|
|
114
|
-
if (typeof token !== 'string' || token.length === 0) {
|
|
115
|
-
throw new Error('Linear token mint returned no access_token');
|
|
116
|
-
}
|
|
117
|
-
return token;
|
|
118
|
-
}
|
|
119
|
-
export async function resolveLinearAuth(config, creds, opts = {}) {
|
|
120
|
-
const product = opts.product ?? DEFAULT_PRODUCT;
|
|
121
|
-
const { actor, signature: template } = config.identity;
|
|
122
|
-
const signature = renderSignature(template, { actor, product });
|
|
123
|
-
if (config.auth.mode === 'client_credentials') {
|
|
124
|
-
const missing = [];
|
|
125
|
-
if (!creds.clientId)
|
|
126
|
-
missing.push(config.auth.client_id_env);
|
|
127
|
-
if (!creds.clientSecret)
|
|
128
|
-
missing.push(config.auth.client_secret_env);
|
|
129
|
-
if (missing.length > 0) {
|
|
130
|
-
// Abort rather than fall back — see the module header.
|
|
131
|
-
throw new LinearConfigError(`Linear auth mode is client_credentials but ${missing.join(' and ')} ` +
|
|
132
|
-
`${missing.length > 1 ? 'are' : 'is'} not set. ` +
|
|
133
|
-
'Set them, or switch linear.auth.mode to api_key.');
|
|
134
|
-
}
|
|
135
|
-
let token;
|
|
136
|
-
try {
|
|
137
|
-
token = await mintAppToken({ clientId: creds.clientId, clientSecret: creds.clientSecret, scopes: config.auth.scopes }, opts);
|
|
138
|
-
}
|
|
139
|
-
catch (err) {
|
|
140
|
-
// Preserve the classification the mint chose: a rejected credential stays a
|
|
141
|
-
// config error (exit 1), an outage stays unexpected (exit 2). Both abort —
|
|
142
|
-
// neither falls back to api_key.
|
|
143
|
-
// Name the variables to check. A bare "HTTP 401" leaves an operator with
|
|
144
|
-
// custom env names guessing which credential to rotate. Names only — never
|
|
145
|
-
// the values.
|
|
146
|
-
const message = `Linear client_credentials token mint failed — aborting rather than falling back ` +
|
|
147
|
-
`to an API key (that would attribute agent writes to a human). ` +
|
|
148
|
-
`Check ${config.auth.client_id_env} and ${config.auth.client_secret_env}. ` +
|
|
149
|
-
`${err instanceof Error ? err.message : String(err)}`;
|
|
150
|
-
throw isLinearConfigError(err) ? new LinearConfigError(message) : new Error(message);
|
|
151
|
-
}
|
|
152
|
-
return {
|
|
153
|
-
mode: 'client_credentials', token, bearer: true, actor, signature,
|
|
154
|
-
createAsUser: actor, signatureTemplate: template, product,
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
if (!creds.apiKey) {
|
|
158
|
-
throw new LinearConfigError(`Linear is enabled but ${config.auth.api_key_env} is not set. ` +
|
|
159
|
-
`Set it, or disable the linear block in your config.`);
|
|
160
|
-
}
|
|
161
|
-
return {
|
|
162
|
-
mode: 'api_key', token: creds.apiKey, bearer: false, actor, signature,
|
|
163
|
-
signatureTemplate: template, product,
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
// Derives a step-scoped identity: `crosscheck` → `crosscheck/review`.
|
|
167
|
-
//
|
|
168
|
-
// The epic calls for per-worker display names (its example is `symphony/worker-3`)
|
|
169
|
-
// so a fleet of agents does not collapse into one indistinguishable bot. crosscheck's
|
|
170
|
-
// natural axis is the workflow step that produced the write.
|
|
171
|
-
//
|
|
172
|
-
// T1 re-points createAsUser, which is what Linear actually renders. T0 has no
|
|
173
|
-
// createAsUser, so the suffix only reaches the signature line — still an improvement,
|
|
174
|
-
// since that is T0's whole attribution mechanism.
|
|
175
|
-
export function withWorker(auth, worker) {
|
|
176
|
-
const trimmed = worker.trim();
|
|
177
|
-
if (!trimmed)
|
|
178
|
-
return auth;
|
|
179
|
-
const actor = `${auth.actor}/${trimmed}`;
|
|
180
|
-
return {
|
|
181
|
-
...auth,
|
|
182
|
-
actor,
|
|
183
|
-
signature: renderSignature(auth.signatureTemplate, { actor, product: auth.product }),
|
|
184
|
-
...(auth.createAsUser !== undefined && { createAsUser: actor }),
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
//# sourceMappingURL=identity.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/linear/identity.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,EAAE;AACF,uFAAuF;AACvF,uFAAuF;AACvF,iDAAiD;AACjD,qFAAqF;AACrF,wFAAwF;AACxF,qFAAqF;AACrF,oFAAoF;AACpF,EAAE;AACF,0CAA0C;AAC1C,mFAAmF;AACnF,mFAAmF;AACnF,gFAAgF;AAIhF,MAAM,cAAc,GAAG,oCAAoC,CAAA;AAuC3D,MAAM,eAAe,GAAG,YAAY,CAAA;AAEpC,kFAAkF;AAClF,gFAAgF;AAChF,2EAA2E;AAC3E,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,SAAS,GAAG,IAAI,CAAA;IACzB,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAA;IACjC,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,OAAO,GAAG,YAAY,iBAAiB,CAAA;AACzC,CAAC;AAaD,kFAAkF;AAClF,8EAA8E;AAC9E,gFAAgF;AAChF,iCAAiC;AACjC,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,IAAmB;IACnE,MAAM,MAAM,GAA2B;QACrC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;QACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;QAC7B,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;KACtB,CAAA;IACD,iFAAiF;IACjF,8DAA8D;IAC9D,MAAM,IAAI,GAAG,QAAQ,CAAA;IACrB,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAClC,0CAA0C,EAC1C,CAAC,MAAM,EAAE,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjE,CAAA;IACD,OAAO,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;AACrC,CAAC;AAED,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,SAAS,SAAS,CAAC,IAAY,EAAE,IAAY;IAC3C,MAAM,GAAG,GAAG,wBAAwB,CAAA;IACpC,OAAO,IAAI;QACT,yEAAyE;SACxE,OAAO,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;QACxD,4DAA4D;SAC3D,OAAO,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,GAAG,IAAI,OAAO,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;QACnD,iDAAiD;SAChD,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,IAAI,GAAG,GAAG,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;QACnD,6CAA6C;SAC5C,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;SACpB,IAAI,EAAE,CAAA;AACX,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;IAC9B,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;AACzC,CAAC;AAED,mFAAmF;AACnF,mFAAmF;AACnF,0BAA0B;AAC1B,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAiE,EACjE,OAAoB,EAAE;IAEtB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAK,UAAU,CAAC,KAAmB,CAAA;IAEjE,mFAAmF;IACnF,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC;QAC/B,UAAU,EAAE,oBAAoB;QAChC,SAAS,EAAE,KAAK,CAAC,QAAQ;QACzB,aAAa,EAAE,KAAK,CAAC,YAAY;QACjC,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC;KACrC,CAAC,CAAA;IAEF,IAAI,QAAkB,CAAA;IACtB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,OAAO,CAAC,cAAc,EAAE;YACvC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;YAChE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE;SACtB,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,6EAA6E;QAC7E,6EAA6E;QAC7E,MAAM,IAAI,KAAK,CAAC,6BAA6B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAClG,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IAClC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,+EAA+E;QAC/E,gFAAgF;QAChF,+BAA+B;QAC/B,MAAM,OAAO,GAAG,oCAAoC,QAAQ,CAAC,MAAM,GAAG,CAAA;QACtE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAA;QACnE,MAAM,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAA;IACvE,CAAC;IAED,IAAI,MAAe,CAAA;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,wDAAwD,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7F,CAAC;IAED,MAAM,KAAK,GAAI,MAAqC,CAAC,YAAY,CAAA;IACjE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAoB,EACpB,KAAwB,EACxB,OAAuB,EAAE;IAEzB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,eAAe,CAAA;IAC/C,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAA;IACtD,MAAM,SAAS,GAAG,eAAe,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;IAE/D,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAa,EAAE,CAAA;QAC5B,IAAI,CAAC,KAAK,CAAC,QAAQ;YAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC5D,IAAI,CAAC,KAAK,CAAC,YAAY;YAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QACpE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,uDAAuD;YACvD,MAAM,IAAI,iBAAiB,CACzB,8CAA8C,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG;gBACtE,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,YAAY;gBAChD,kDAAkD,CACnD,CAAA;QACH,CAAC;QAED,IAAI,KAAa,CAAA;QACjB,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,YAAY,CACxB,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAS,EAAE,YAAY,EAAE,KAAK,CAAC,YAAa,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAC5F,IAAI,CACL,CAAA;QACH,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,4EAA4E;YAC5E,2EAA2E;YAC3E,iCAAiC;YACjC,yEAAyE;YACzE,2EAA2E;YAC3E,cAAc;YACd,MAAM,OAAO,GACX,kFAAkF;gBAClF,gEAAgE;gBAChE,SAAS,MAAM,CAAC,IAAI,CAAC,aAAa,QAAQ,MAAM,CAAC,IAAI,CAAC,iBAAiB,IAAI;gBAC3E,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAA;YACvD,MAAM,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;QACtF,CAAC;QAED,OAAO;YACL,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS;YACjE,YAAY,EAAE,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,OAAO;SAC1D,CAAA;IACH,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,IAAI,iBAAiB,CACzB,yBAAyB,MAAM,CAAC,IAAI,CAAC,WAAW,eAAe;YAC/D,qDAAqD,CACtD,CAAA;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS;QACrE,iBAAiB,EAAE,QAAQ,EAAE,OAAO;KACrC,CAAA;AACH,CAAC;AAED,sEAAsE;AACtE,EAAE;AACF,mFAAmF;AACnF,sFAAsF;AACtF,6DAA6D;AAC7D,EAAE;AACF,8EAA8E;AAC9E,sFAAsF;AACtF,kDAAkD;AAClD,MAAM,UAAU,UAAU,CAAC,IAAwB,EAAE,MAAc;IACjE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAEzB,MAAM,KAAK,GAAG,GAAG,IAAI,CAAC,KAAK,IAAI,OAAO,EAAE,CAAA;IACxC,OAAO;QACL,GAAG,IAAI;QACP,KAAK;QACL,SAAS,EAAE,eAAe,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACpF,GAAG,CAAC,IAAI,CAAC,YAAY,KAAK,SAAS,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;KAChE,CAAA;AACH,CAAC"}
|
package/dist/linear/notify.d.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { type LinearRequestOptions } from './client.js';
|
|
2
|
-
import { type ResolvedLinearAuth } from './identity.js';
|
|
3
|
-
import type { LinearConfig } from '../config/schema.js';
|
|
4
|
-
export type LinearNotifyStatus = 'posted' | 'skipped' | 'failed';
|
|
5
|
-
export interface LinearNotifyResult {
|
|
6
|
-
status: LinearNotifyStatus;
|
|
7
|
-
/** Machine-readable reason for skipped/failed. */
|
|
8
|
-
reason?: string;
|
|
9
|
-
identifier?: string;
|
|
10
|
-
url?: string;
|
|
11
|
-
}
|
|
12
|
-
export interface LinearNotifyParams {
|
|
13
|
-
auth: ResolvedLinearAuth;
|
|
14
|
-
config: LinearConfig;
|
|
15
|
-
pr: {
|
|
16
|
-
branch?: string;
|
|
17
|
-
title: string;
|
|
18
|
-
body?: string;
|
|
19
|
-
url: string;
|
|
20
|
-
sha?: string;
|
|
21
|
-
};
|
|
22
|
-
verdict: string | null;
|
|
23
|
-
reviewer: string;
|
|
24
|
-
origin: string;
|
|
25
|
-
model: string;
|
|
26
|
-
summary?: string;
|
|
27
|
-
service?: string;
|
|
28
|
-
/** Workflow step that produced this verdict. Defaults to 'review'. */
|
|
29
|
-
stepType?: string;
|
|
30
|
-
/** 1-based workflow round. Defaults to 1. */
|
|
31
|
-
round?: number;
|
|
32
|
-
}
|
|
33
|
-
export declare function issueBelongsToWorkspace(issueUrl: string, workspace: string): boolean;
|
|
34
|
-
export declare function notifyLinear(params: LinearNotifyParams, opts?: LinearRequestOptions): Promise<LinearNotifyResult>;
|
|
35
|
-
//# sourceMappingURL=notify.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/linear/notify.ts"],"names":[],"mappings":"AASA,OAAO,EAA4C,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAEjG,OAAO,EAA+B,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEhE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,kBAAkB,CAAA;IAC1B,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,kBAAkB,CAAA;IACxB,MAAM,EAAE,YAAY,CAAA;IACpB,EAAE,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAGD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAQpF;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,EAC1B,IAAI,GAAE,oBAAyB,GAC9B,OAAO,CAAC,kBAAkB,CAAC,CAwD7B"}
|
package/dist/linear/notify.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
// Orchestrates the one Linear write crosscheck makes: mirroring a review verdict
|
|
2
|
-
// onto the Linear issue the PR belongs to.
|
|
3
|
-
//
|
|
4
|
-
// This never throws. Auth is resolved up front (fail-fast, before the expensive
|
|
5
|
-
// review runs), so anything that goes wrong here is a per-write problem on a review
|
|
6
|
-
// that already succeeded and already posted to GitHub. The caller logs the returned
|
|
7
|
-
// status — failures are reported, never swallowed.
|
|
8
|
-
import { buildLinearCommentBody, shouldPostToLinear } from './comment.js';
|
|
9
|
-
import { findIssueByIdentifier, postLinearComment } from './client.js';
|
|
10
|
-
import { extractLinearRef } from './ref.js';
|
|
11
|
-
import { renderIcon, renderSignature } from './identity.js';
|
|
12
|
-
// Linear issue URLs are https://linear.app/<workspace>/issue/<ID>/<slug>.
|
|
13
|
-
export function issueBelongsToWorkspace(issueUrl, workspace) {
|
|
14
|
-
try {
|
|
15
|
-
const segments = new URL(issueUrl).pathname.split('/').filter(Boolean);
|
|
16
|
-
return segments[0]?.toLowerCase() === workspace.toLowerCase();
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
// Unparseable URL from the API — fail closed rather than post to the wrong place.
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
export async function notifyLinear(params, opts = {}) {
|
|
24
|
-
const { auth, config, pr } = params;
|
|
25
|
-
if (!shouldPostToLinear(params.verdict, config.comment_on)) {
|
|
26
|
-
return { status: 'skipped', reason: 'verdict-not-configured' };
|
|
27
|
-
}
|
|
28
|
-
const ref = extractLinearRef({ branch: pr.branch, title: pr.title, body: pr.body }, config.team_keys);
|
|
29
|
-
if (!ref)
|
|
30
|
-
return { status: 'skipped', reason: 'no-issue-ref' };
|
|
31
|
-
try {
|
|
32
|
-
const issue = await findIssueByIdentifier(auth, ref.id, opts);
|
|
33
|
-
if (!issue)
|
|
34
|
-
return { status: 'skipped', reason: 'issue-not-found', identifier: ref.id };
|
|
35
|
-
// An explicit URL names a workspace, and identifiers repeat across workspaces.
|
|
36
|
-
// If the credentials resolve a different workspace, this is a same-numbered
|
|
37
|
-
// issue somewhere else — never the one the PR pointed at. Checked before any
|
|
38
|
-
// body is built, so a mismatch costs nothing.
|
|
39
|
-
if (ref.workspace && !issueBelongsToWorkspace(issue.url, ref.workspace)) {
|
|
40
|
-
return { status: 'skipped', reason: 'workspace-mismatch', identifier: ref.id };
|
|
41
|
-
}
|
|
42
|
-
// Re-render here rather than reusing auth.signature: this is the first point
|
|
43
|
-
// that knows the model and reviewer, which the template may reference.
|
|
44
|
-
const signature = renderSignature(auth.signatureTemplate, {
|
|
45
|
-
actor: auth.actor,
|
|
46
|
-
product: auth.product,
|
|
47
|
-
model: params.model === 'default' ? undefined : params.model,
|
|
48
|
-
reviewer: params.reviewer,
|
|
49
|
-
icon: renderIcon(config.identity.icon_url),
|
|
50
|
-
});
|
|
51
|
-
const body = buildLinearCommentBody({
|
|
52
|
-
signature,
|
|
53
|
-
verdict: params.verdict,
|
|
54
|
-
reviewer: params.reviewer,
|
|
55
|
-
origin: params.origin,
|
|
56
|
-
model: params.model,
|
|
57
|
-
prUrl: pr.url,
|
|
58
|
-
prTitle: pr.title,
|
|
59
|
-
...(pr.sha && { sha: pr.sha }),
|
|
60
|
-
...(params.stepType && { stepType: params.stepType }),
|
|
61
|
-
...(params.round !== undefined && { round: params.round }),
|
|
62
|
-
...(params.summary && { summary: params.summary }),
|
|
63
|
-
...(params.service && { service: params.service }),
|
|
64
|
-
});
|
|
65
|
-
const comment = await postLinearComment(auth, issue.id, body, opts);
|
|
66
|
-
return { status: 'posted', identifier: issue.identifier, url: comment.url };
|
|
67
|
-
}
|
|
68
|
-
catch (err) {
|
|
69
|
-
return {
|
|
70
|
-
status: 'failed',
|
|
71
|
-
reason: err instanceof Error ? err.message : String(err),
|
|
72
|
-
identifier: ref.id,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
//# sourceMappingURL=notify.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/linear/notify.ts"],"names":[],"mappings":"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"}
|
package/dist/linear/ref.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { type TicketRef } from '../issues/ticket-ref.js';
|
|
2
|
-
export interface LinearIssueRef extends TicketRef {
|
|
3
|
-
source: 'branch' | 'title' | 'body';
|
|
4
|
-
/** Workspace slug, when the ref came from an explicit URL. Bare refs have none. */
|
|
5
|
-
workspace?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface PRMetadata {
|
|
8
|
-
branch?: string | null;
|
|
9
|
-
title?: string | null;
|
|
10
|
-
body?: string | null;
|
|
11
|
-
}
|
|
12
|
-
export declare function extractLinearRef(pr: PRMetadata, teamKeys: readonly string[]): LinearIssueRef | null;
|
|
13
|
-
//# sourceMappingURL=ref.d.ts.map
|
package/dist/linear/ref.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../../src/linear/ref.ts"],"names":[],"mappings":"AAYA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAE1F,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C,MAAM,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAA;IACnC,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAiED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,GAAG,IAAI,CAanG"}
|