@volter/twin-github 0.1.2 → 2.0.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/README.md +88 -36
- package/client/github-mirror.css +277 -319
- package/client/github-mirror.d.ts +418 -0
- package/client/github-mirror.js +485 -0
- package/client/github-mirror.tsx +153 -357
- package/client/pulls-rest.ts +159 -0
- package/client/pulls-workspace.tsx +841 -0
- package/dist/client/github-mirror.bundle.js +239 -0
- package/dist/client/github-mirror.css +916 -0
- package/dist/client/github-mirror.d.ts +418 -0
- package/dist/client/github-mirror.js +485 -0
- package/dist/client/github-mirror.tsx +1315 -0
- package/dist/client/pulls-rest.d.ts +42 -0
- package/dist/client/pulls-rest.js +140 -0
- package/dist/client/pulls-rest.ts +159 -0
- package/dist/client/pulls-workspace.bundle.js +22 -0
- package/dist/client/pulls-workspace.d.ts +114 -0
- package/dist/client/pulls-workspace.js +418 -0
- package/dist/client/pulls-workspace.tsx +841 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +40 -0
- package/dist/src/generated/graphql-sdl.gen.json +1 -0
- package/dist/src/generated/graphql.gen.json +1 -0
- package/dist/src/generated/surface.gen.json +1 -0
- package/dist/src/generated/ui.gen.json +1 -0
- package/dist/src/github-budget.d.ts +69 -0
- package/dist/src/github-budget.js +172 -0
- package/dist/src/github-capabilities.d.ts +5 -0
- package/dist/src/github-capabilities.js +4468 -0
- package/dist/src/github-conformance.d.ts +43 -0
- package/dist/src/github-conformance.js +76 -0
- package/dist/src/github-connector.d.ts +307 -0
- package/dist/src/github-connector.js +1398 -0
- package/dist/src/github-events.d.ts +41 -0
- package/dist/src/github-events.js +230 -0
- package/dist/src/github-git-http.d.ts +49 -0
- package/dist/src/github-git-http.js +185 -0
- package/dist/src/github-git-plane.d.ts +114 -0
- package/dist/src/github-git-plane.js +407 -0
- package/dist/src/github-mirror-state.d.ts +2 -0
- package/dist/src/github-mirror-state.js +335 -0
- package/dist/src/github-mirror-ui.d.ts +20 -0
- package/dist/src/github-mirror-ui.js +101 -0
- package/dist/src/github-server.d.ts +14 -0
- package/dist/src/github-server.js +240 -0
- package/dist/src/github-shared.d.ts +12 -0
- package/dist/src/github-shared.js +21 -0
- package/dist/src/github-twin.d.ts +1411 -0
- package/dist/src/github-twin.js +4084 -0
- package/dist/src/github-ui-conformance.d.ts +4 -0
- package/dist/src/github-ui-conformance.js +105 -0
- package/dist/src/github-ui-structure.d.ts +18 -0
- package/dist/src/github-ui-structure.js +251 -0
- package/dist/src/graphql-wire.d.ts +22 -0
- package/dist/src/graphql-wire.js +89 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/index.js +101 -0
- package/dist/src/manifest.d.ts +8 -0
- package/dist/src/manifest.js +597 -0
- package/dist/src/npm-registry.d.ts +7 -0
- package/dist/src/npm-registry.js +47 -0
- package/dist/src/screens/app-installation.d.ts +3 -0
- package/dist/src/screens/app-installation.js +166 -0
- package/dist/src/screens/app-manifest.d.ts +3 -0
- package/dist/src/screens/app-manifest.js +81 -0
- package/dist/src/screens/oauth.d.ts +15 -0
- package/dist/src/screens/oauth.js +257 -0
- package/dist/src/screens/session.d.ts +8 -0
- package/dist/src/screens/session.js +159 -0
- package/dist/src/semantics/actions.d.ts +2 -0
- package/dist/src/semantics/actions.js +413 -0
- package/dist/src/semantics/activity.d.ts +4 -0
- package/dist/src/semantics/activity.js +161 -0
- package/dist/src/semantics/apps.d.ts +2 -0
- package/dist/src/semantics/apps.js +144 -0
- package/dist/src/semantics/branches.d.ts +2 -0
- package/dist/src/semantics/branches.js +136 -0
- package/dist/src/semantics/checks.d.ts +2 -0
- package/dist/src/semantics/checks.js +176 -0
- package/dist/src/semantics/code-scanning-upload.d.ts +2 -0
- package/dist/src/semantics/code-scanning-upload.js +97 -0
- package/dist/src/semantics/codespaces.d.ts +2 -0
- package/dist/src/semantics/codespaces.js +58 -0
- package/dist/src/semantics/commits.d.ts +2 -0
- package/dist/src/semantics/commits.js +109 -0
- package/dist/src/semantics/contents.d.ts +2 -0
- package/dist/src/semantics/contents.js +131 -0
- package/dist/src/semantics/deployments.d.ts +2 -0
- package/dist/src/semantics/deployments.js +127 -0
- package/dist/src/semantics/gists.d.ts +2 -0
- package/dist/src/semantics/gists.js +86 -0
- package/dist/src/semantics/git.d.ts +2 -0
- package/dist/src/semantics/git.js +235 -0
- package/dist/src/semantics/graphql.d.ts +7 -0
- package/dist/src/semantics/graphql.js +512 -0
- package/dist/src/semantics/index.d.ts +5 -0
- package/dist/src/semantics/index.js +62 -0
- package/dist/src/semantics/issues.d.ts +2 -0
- package/dist/src/semantics/issues.js +456 -0
- package/dist/src/semantics/keys.d.ts +2 -0
- package/dist/src/semantics/keys.js +66 -0
- package/dist/src/semantics/labels.d.ts +2 -0
- package/dist/src/semantics/labels.js +100 -0
- package/dist/src/semantics/meta.d.ts +12 -0
- package/dist/src/semantics/meta.js +144 -0
- package/dist/src/semantics/notifications.d.ts +4 -0
- package/dist/src/semantics/notifications.js +62 -0
- package/dist/src/semantics/orgs.d.ts +2 -0
- package/dist/src/semantics/orgs.js +420 -0
- package/dist/src/semantics/packages.d.ts +2 -0
- package/dist/src/semantics/packages.js +55 -0
- package/dist/src/semantics/pages.d.ts +2 -0
- package/dist/src/semantics/pages.js +176 -0
- package/dist/src/semantics/projects.d.ts +2 -0
- package/dist/src/semantics/projects.js +239 -0
- package/dist/src/semantics/pulls.d.ts +2 -0
- package/dist/src/semantics/pulls.js +462 -0
- package/dist/src/semantics/push-reactions.d.ts +101 -0
- package/dist/src/semantics/push-reactions.js +513 -0
- package/dist/src/semantics/releases.d.ts +19 -0
- package/dist/src/semantics/releases.js +231 -0
- package/dist/src/semantics/repo-invitations.d.ts +2 -0
- package/dist/src/semantics/repo-invitations.js +98 -0
- package/dist/src/semantics/repos.d.ts +17 -0
- package/dist/src/semantics/repos.js +390 -0
- package/dist/src/semantics/rulesets.d.ts +2 -0
- package/dist/src/semantics/rulesets.js +111 -0
- package/dist/src/semantics/search.d.ts +2 -0
- package/dist/src/semantics/search.js +84 -0
- package/dist/src/semantics/security.d.ts +2 -0
- package/dist/src/semantics/security.js +177 -0
- package/dist/src/semantics/shared.d.ts +61 -0
- package/dist/src/semantics/shared.js +151 -0
- package/dist/src/semantics/users.d.ts +2 -0
- package/dist/src/semantics/users.js +255 -0
- package/dist/src/semantics/webhooks.d.ts +2 -0
- package/dist/src/semantics/webhooks.js +107 -0
- package/dist/test-fixtures/github-a11y-reference.pr-list.SOURCE.md +56 -0
- package/dist/test-fixtures/github-a11y-reference.pr-list.json +1447 -0
- package/dist/test-fixtures/github-comment-schema.SOURCE.md +11 -0
- package/dist/test-fixtures/github-comment-schema.json +702 -0
- package/dist/test-fixtures/github-known-deviations.json +94 -0
- package/dist/test-fixtures/github-openapi-operations.SOURCE.md +76 -0
- package/dist/test-fixtures/github-openapi-operations.json +362 -0
- package/dist/test-fixtures/github-pull-schema.SOURCE.md +37 -0
- package/dist/test-fixtures/github-pull-schema.json +3601 -0
- package/dist/test-fixtures/github-review-schema.SOURCE.md +12 -0
- package/dist/test-fixtures/github-review-schema.json +236 -0
- package/package.json +20 -11
- package/src/cli.ts +7 -6
- package/src/generated/graphql-sdl.gen.json +1 -0
- package/src/generated/graphql.gen.json +1 -0
- package/src/generated/surface.gen.json +1 -0
- package/src/generated/ui.gen.json +1 -0
- package/src/github-a11y-snapshot.uitest.ts +5 -5
- package/src/github-budget.ts +4 -4
- package/src/github-capabilities.ts +1993 -556
- package/src/github-conformance.ts +12 -7
- package/src/github-connector.ts +108 -96
- package/src/github-events.ts +223 -95
- package/src/github-git-http.ts +47 -83
- package/src/github-git-plane.ts +247 -385
- package/src/github-journey.uitest.ts +28 -44
- package/src/github-mirror-state.ts +23 -61
- package/src/github-mirror-ui.ts +16 -10
- package/src/github-server.ts +158 -60
- package/src/github-shared.ts +1 -1
- package/src/github-twin.ts +1525 -4494
- package/src/github-ui-conformance.ts +7 -8
- package/src/github-ui-structure.ts +19 -18
- package/src/graphql-wire.ts +115 -0
- package/src/index.ts +47 -7
- package/src/manifest.ts +605 -0
- package/src/npm-registry.ts +43 -0
- package/src/screens/app-installation.tsx +217 -0
- package/src/screens/app-manifest.tsx +97 -0
- package/src/screens/oauth.tsx +258 -0
- package/src/screens/session.tsx +186 -0
- package/src/semantics/actions.ts +395 -0
- package/src/semantics/activity.ts +171 -0
- package/src/semantics/apps.ts +133 -0
- package/src/semantics/branches.ts +133 -0
- package/src/semantics/checks.ts +163 -0
- package/src/semantics/code-scanning-upload.ts +92 -0
- package/src/semantics/codespaces.ts +58 -0
- package/src/semantics/commits.ts +109 -0
- package/src/semantics/contents.ts +112 -0
- package/src/semantics/deployments.ts +116 -0
- package/src/semantics/gists.ts +85 -0
- package/src/semantics/git.ts +226 -0
- package/src/semantics/graphql.ts +505 -0
- package/src/semantics/index.ts +68 -0
- package/src/semantics/issues.ts +434 -0
- package/src/semantics/keys.ts +66 -0
- package/src/semantics/labels.ts +91 -0
- package/src/semantics/meta.ts +139 -0
- package/src/semantics/notifications.ts +58 -0
- package/src/semantics/orgs.ts +383 -0
- package/src/semantics/packages.ts +59 -0
- package/src/semantics/pages.ts +154 -0
- package/src/semantics/projects.ts +246 -0
- package/src/semantics/pulls.ts +421 -0
- package/src/semantics/push-reactions.ts +471 -0
- package/src/semantics/releases.ts +213 -0
- package/src/semantics/repo-invitations.ts +112 -0
- package/src/semantics/repos.ts +373 -0
- package/src/semantics/rulesets.ts +107 -0
- package/src/semantics/search.ts +83 -0
- package/src/semantics/security.ts +153 -0
- package/src/semantics/shared.ts +181 -0
- package/src/semantics/users.ts +252 -0
- package/src/semantics/webhooks.ts +101 -0
- package/test-fixtures/github-known-deviations.json +7 -8
- package/test-fixtures/github-openapi-operations.json +46 -227
- package/src/github-graphql.ts +0 -398
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { specConformance } from '@volter/world-tooling';
|
|
2
|
+
type JsonSchema = specConformance.JsonSchema;
|
|
3
|
+
type KnownDeviation = specConformance.KnownDeviation;
|
|
4
|
+
type SpecViolation = specConformance.SpecViolation;
|
|
5
|
+
export type GithubViolation = SpecViolation & {
|
|
6
|
+
prId: string;
|
|
7
|
+
};
|
|
8
|
+
export type GithubConformanceReport = {
|
|
9
|
+
ok: boolean;
|
|
10
|
+
prsChecked: number;
|
|
11
|
+
fieldsChecked: number;
|
|
12
|
+
violations: GithubViolation[];
|
|
13
|
+
knownIgnored: number;
|
|
14
|
+
};
|
|
15
|
+
/** Load the vendored full GitHub pull-request JSON Schema (dereferenced OpenAPI). */
|
|
16
|
+
export declare function loadGithubPrSchema(): Promise<JsonSchema>;
|
|
17
|
+
/** Load the vendored GitHub pull-request-review JSON Schema. */
|
|
18
|
+
export declare function loadGithubReviewSchema(): Promise<JsonSchema>;
|
|
19
|
+
/** Load the vendored GitHub issue-comment JSON Schema. */
|
|
20
|
+
export declare function loadGithubCommentSchema(): Promise<JsonSchema>;
|
|
21
|
+
/** Load the declared evidence-twin scope (fields deliberately not modeled, + reasons). */
|
|
22
|
+
export declare function loadGithubKnownDeviations(): Promise<KnownDeviation[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Validate every PR the twin serves against the real GitHub PR schema. A wrong
|
|
25
|
+
* type, an undeclared missing-required field, a fabricated field, or an enum
|
|
26
|
+
* violation fails the report.
|
|
27
|
+
*/
|
|
28
|
+
export declare function checkGithubConformance(schema: JsonSchema, opts?: {
|
|
29
|
+
root?: string;
|
|
30
|
+
known?: KnownDeviation[];
|
|
31
|
+
}): GithubConformanceReport;
|
|
32
|
+
export type GithubCoverageReport = specConformance.SpecCoverageReport;
|
|
33
|
+
/**
|
|
34
|
+
* Top-level coverage: of the fields the GitHub PR schema declares, which does the
|
|
35
|
+
* twin emit? The "what we emulate / what we're missing" report — computed from the
|
|
36
|
+
* spec, not probed live. Uses a representative content-bearing PR sample.
|
|
37
|
+
*/
|
|
38
|
+
export declare function githubCoverage(schema: JsonSchema): GithubCoverageReport;
|
|
39
|
+
/** Coverage of the pull-request-review object the twin emits on review submission. */
|
|
40
|
+
export declare function githubReviewCoverage(schema: JsonSchema): GithubCoverageReport;
|
|
41
|
+
/** Coverage of the issue-comment object the twin emits on comment creation. */
|
|
42
|
+
export declare function githubCommentCoverage(schema: JsonSchema): GithubCoverageReport;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// GitHub twin conformance (scorecard R2) — spec-conformance against GitHub's
|
|
2
|
+
// PUBLISHED pull-request schema, not a hand-authored field-name list. Offline, no
|
|
3
|
+
// token: for every PR the twin serves, validate the REST response against the real
|
|
4
|
+
// schema (types, required, enums, fabricated extras) vendored from GitHub's OpenAPI
|
|
5
|
+
// (test-fixtures/github-pull-schema.json). Twin-namespaced extras (keys starting
|
|
6
|
+
// `_`) are skipped. Fields the evidence twin deliberately does not model are DECLARED
|
|
7
|
+
// in github-known-deviations.json with reasons — a missing-required field that is
|
|
8
|
+
// NOT declared fails CI. The companion coverage report says what we emit vs what the
|
|
9
|
+
// vendor declares. Standing gate: wrong types, undeclared omissions, fabricated
|
|
10
|
+
// surface, or enum violations all fail.
|
|
11
|
+
import { readFile } from 'node:fs/promises';
|
|
12
|
+
import { specConformance } from '@volter/world-tooling';
|
|
13
|
+
import { githubState, toGithubComment, toGithubRest, toGithubReview } from "./github-twin.js";
|
|
14
|
+
const isTwinExtra = (f) => f.startsWith('_');
|
|
15
|
+
const fixturePath = (name) => new URL(`../test-fixtures/${name}`, import.meta.url).pathname;
|
|
16
|
+
/** Load the vendored full GitHub pull-request JSON Schema (dereferenced OpenAPI). */
|
|
17
|
+
export async function loadGithubPrSchema() {
|
|
18
|
+
return JSON.parse(await readFile(fixturePath('github-pull-schema.json'), 'utf8'));
|
|
19
|
+
}
|
|
20
|
+
/** Load the vendored GitHub pull-request-review JSON Schema. */
|
|
21
|
+
export async function loadGithubReviewSchema() {
|
|
22
|
+
return JSON.parse(await readFile(fixturePath('github-review-schema.json'), 'utf8'));
|
|
23
|
+
}
|
|
24
|
+
/** Load the vendored GitHub issue-comment JSON Schema. */
|
|
25
|
+
export async function loadGithubCommentSchema() {
|
|
26
|
+
return JSON.parse(await readFile(fixturePath('github-comment-schema.json'), 'utf8'));
|
|
27
|
+
}
|
|
28
|
+
/** Load the declared evidence-twin scope (fields deliberately not modeled, + reasons). */
|
|
29
|
+
export async function loadGithubKnownDeviations() {
|
|
30
|
+
const doc = JSON.parse(await readFile(fixturePath('github-known-deviations.json'), 'utf8'));
|
|
31
|
+
return doc.deviations;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validate every PR the twin serves against the real GitHub PR schema. A wrong
|
|
35
|
+
* type, an undeclared missing-required field, a fabricated field, or an enum
|
|
36
|
+
* violation fails the report.
|
|
37
|
+
*/
|
|
38
|
+
export function checkGithubConformance(schema, opts = {}) {
|
|
39
|
+
const state = githubState(opts.root);
|
|
40
|
+
const violations = [];
|
|
41
|
+
let fieldsChecked = 0;
|
|
42
|
+
let knownIgnored = 0;
|
|
43
|
+
// "Every PR the twin SERVES" — which is the rows marked as pull-request evidence, not the
|
|
44
|
+
// counter shells `ensure()` materializes for issue numbers. Checking a shell measures an
|
|
45
|
+
// object no door answers with, and its emptiness would read as the twin's conformance.
|
|
46
|
+
const served = state.prs.filter((p) => p.is_pull_request);
|
|
47
|
+
for (const pr of served) {
|
|
48
|
+
const rest = toGithubRest(pr);
|
|
49
|
+
const rep = specConformance.checkSpecConformance(rest, schema, { exemptKey: isTwinExtra, known: opts.known ?? [] });
|
|
50
|
+
fieldsChecked += rep.fieldsChecked;
|
|
51
|
+
knownIgnored += rep.knownIgnored;
|
|
52
|
+
for (const v of rep.violations)
|
|
53
|
+
violations.push({ ...v, prId: pr.id });
|
|
54
|
+
}
|
|
55
|
+
return { ok: violations.length === 0, prsChecked: served.length, fieldsChecked, violations, knownIgnored };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Top-level coverage: of the fields the GitHub PR schema declares, which does the
|
|
59
|
+
* twin emit? The "what we emulate / what we're missing" report — computed from the
|
|
60
|
+
* spec, not probed live. Uses a representative content-bearing PR sample.
|
|
61
|
+
*/
|
|
62
|
+
export function githubCoverage(schema) {
|
|
63
|
+
const sample = toGithubRest({
|
|
64
|
+
id: 'o/r#1', number: 1, repository: 'o/r', base_ref: 'main', head_sha: 'abc123',
|
|
65
|
+
changed_files: 3, commits: 2, review_count: 0, comment_count: 0, title: 'Sample', state: 'open',
|
|
66
|
+
});
|
|
67
|
+
return specConformance.specCoverage(schema, sample, { exemptKey: isTwinExtra });
|
|
68
|
+
}
|
|
69
|
+
/** Coverage of the pull-request-review object the twin emits on review submission. */
|
|
70
|
+
export function githubReviewCoverage(schema) {
|
|
71
|
+
return specConformance.specCoverage(schema, toGithubReview({ id: 1, repository: 'o/r', number: 1, state: 'APPROVED', body: 'lgtm' }), { exemptKey: isTwinExtra });
|
|
72
|
+
}
|
|
73
|
+
/** Coverage of the issue-comment object the twin emits on comment creation. */
|
|
74
|
+
export function githubCommentCoverage(schema) {
|
|
75
|
+
return specConformance.specCoverage(schema, toGithubComment({ id: 1, repository: 'o/r', number: 1, body: 'hi', at: '2026-01-01T00:00:00Z' }), { exemptKey: isTwinExtra });
|
|
76
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import type { PerformContext, PushOutcome, RemoteExecute, SyncResource, TwinAction } from '@volter/world-core';
|
|
2
|
+
import { GithubBudget, type GithubBudgetOptions } from './github-budget.js';
|
|
3
|
+
/**
|
|
4
|
+
* The minimal real-GitHub REST surface the connector needs. A real `@octokit/rest`
|
|
5
|
+
* client is structurally adaptable to this (its `request(route, params)` returns
|
|
6
|
+
* `{ status, data }`) — the consumer wires it; this pack never imports it. `request`
|
|
7
|
+
* is the single credentialed boundary: in tests it's a fake, live it's the user's
|
|
8
|
+
* token-bound octokit. It maps a REST `route` ("METHOD /path") + params to a result.
|
|
9
|
+
*/
|
|
10
|
+
export interface GithubExecute {
|
|
11
|
+
request(route: string, params?: Record<string, unknown>): Promise<{
|
|
12
|
+
status: number;
|
|
13
|
+
data: any;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
/** Construction options for the live executor. `budget` cannot be null and cannot be loosened. */
|
|
17
|
+
export type LiveGithubOptions = {
|
|
18
|
+
/** Injected `fetch`, so a test can COUNT the requests the guard did or did not let through. */
|
|
19
|
+
fetchImpl?: typeof fetch;
|
|
20
|
+
/** An existing budget to share across executors. Omit and one is constructed. Cannot be null. */
|
|
21
|
+
budget?: GithubBudget;
|
|
22
|
+
/** Construction options for the default budget (ledger path, clock). Cannot loosen it. */
|
|
23
|
+
budgetOptions?: GithubBudgetOptions;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* A live executor against the real GitHub REST API (token = the user's own PAT).
|
|
27
|
+
* Constructed with the real @octokit/rest in PROD by the CALLER and passed in; this
|
|
28
|
+
* helper shows the shape without importing the SDK. Kept tiny + dependency-free: it
|
|
29
|
+
* uses `fetch`, so the pack pulls in no network client. Live runs may instead pass a
|
|
30
|
+
* real `new Octokit({ auth }).request` bound into a `{ request }` object.
|
|
31
|
+
*
|
|
32
|
+
* THIS IS THE ONE PLACE this pack issues a live `api.github.com` request, and therefore the one
|
|
33
|
+
* place the rate budget has to be enforced. EVERY call is guarded: the budget is charged BEFORE the
|
|
34
|
+
* request goes out (`checkBudget`, which THROWS `GithubBudgetError` instead of returning when the
|
|
35
|
+
* ceiling or a cooldown says stop) and the response is fed back (`recordCall`) so a `Retry-After` /
|
|
36
|
+
* 403-or-429 / `x-ratelimit-remaining: 0` signal becomes a persisted cooldown that makes every
|
|
37
|
+
* later call fail fast WITHOUT touching GitHub. The weights ARE GitHub's own published point costs
|
|
38
|
+
* (1 for a read, 5 for a write) — see `github-budget.ts`. There is deliberately NO option to
|
|
39
|
+
* disable the guard, and no value a caller can pass for `budget` that yields an unguarded client —
|
|
40
|
+
* but NOT immunity from a caller who WANTS one (a fresh `budgetOptions.path` or an injected clock
|
|
41
|
+
* restores the allowance; the kernel header states that limit and this does not upgrade it).
|
|
42
|
+
*/
|
|
43
|
+
export declare function liveGithubExecute(token: string, baseUrl?: string, opts?: LiveGithubOptions): GithubExecute;
|
|
44
|
+
type ObservedReviewComment = {
|
|
45
|
+
id: string;
|
|
46
|
+
/** WHO wrote THIS finding, from the comment's own `user` — the row the vendor sent, not
|
|
47
|
+
* the review that wraps it. A review is a join key, not an authorship claim: a scanner
|
|
48
|
+
* App's finding rides a review a human submitted, a threaded reply rides the root's
|
|
49
|
+
* review, and the phantom bucket has no author at all. The pull BOUGHT this field and
|
|
50
|
+
* used to throw it away, so a bot finding was served under the human reviewer's login —
|
|
51
|
+
* the exact fact a consumer triaging findings reads. Absent when the vendor named nobody
|
|
52
|
+
* (`user: null`, a deleted account); the wrapper's author is then the only evidence
|
|
53
|
+
* there is, and the fold falls back to it rather than inventing one. */
|
|
54
|
+
authorLogin?: string;
|
|
55
|
+
authorType?: 'bot' | 'user';
|
|
56
|
+
path?: string;
|
|
57
|
+
line?: number;
|
|
58
|
+
body?: string;
|
|
59
|
+
inReplyTo?: string;
|
|
60
|
+
createdAt?: string;
|
|
61
|
+
};
|
|
62
|
+
type ObservedReview = {
|
|
63
|
+
id?: string;
|
|
64
|
+
/** True for a review NOBODY SHOWED US — one the reviews page never returned. Two shapes
|
|
65
|
+
* wear it: the PHANTOM bucket (`unattached`), holding inline comments whose review id was
|
|
66
|
+
* missing, and a NAMED orphan, whose id an inline comment gave us but whose row never
|
|
67
|
+
* arrived (a review deleted between the two reads, a page boundary). Both carry comments
|
|
68
|
+
* and NOTHING ELSE — no state, no author, no verdict — and a consumer must be able to tell
|
|
69
|
+
* either from a real review it merely has no state for yet, so both say so. */
|
|
70
|
+
partial?: boolean;
|
|
71
|
+
authorLogin?: string;
|
|
72
|
+
authorType?: 'bot' | 'user';
|
|
73
|
+
state?: string;
|
|
74
|
+
body?: string;
|
|
75
|
+
submittedAt?: string;
|
|
76
|
+
commitId?: string;
|
|
77
|
+
comments: ObservedReviewComment[];
|
|
78
|
+
};
|
|
79
|
+
type ObservedComment = {
|
|
80
|
+
id?: string;
|
|
81
|
+
authorLogin?: string;
|
|
82
|
+
authorType?: 'bot' | 'user';
|
|
83
|
+
body?: string;
|
|
84
|
+
createdAt?: string;
|
|
85
|
+
updatedAt?: string;
|
|
86
|
+
};
|
|
87
|
+
type ObservedPr = {
|
|
88
|
+
id: string;
|
|
89
|
+
number: number;
|
|
90
|
+
repository: string;
|
|
91
|
+
title?: string;
|
|
92
|
+
body?: string;
|
|
93
|
+
state?: string;
|
|
94
|
+
draft?: boolean;
|
|
95
|
+
merged?: boolean;
|
|
96
|
+
mergeCommit?: string;
|
|
97
|
+
baseRef?: string;
|
|
98
|
+
headSha?: string;
|
|
99
|
+
changedFiles?: number;
|
|
100
|
+
commitsCount?: number;
|
|
101
|
+
authorLogin?: string | null;
|
|
102
|
+
authorType?: string;
|
|
103
|
+
/** The PR's own `updated_at` — the provider instant that dates its delta AND the stamp
|
|
104
|
+
* the next pull compares against to decide whether its conversation is worth buying. */
|
|
105
|
+
updatedAt?: string;
|
|
106
|
+
/** False when the budget skipped this PR's reviews/comments (its `updated_at` had not
|
|
107
|
+
* moved). The counts and the conversation subjects are then OMITTED rather than
|
|
108
|
+
* reported as zero — an unbought fact is not an observation of absence. */
|
|
109
|
+
detailsFetched: boolean;
|
|
110
|
+
/** How many reviews this PR has — counted over exactly the set `latestReview` is drawn
|
|
111
|
+
* from (submitted, non-PENDING), so the count and the newest verdict can never disagree. */
|
|
112
|
+
reviewCount?: number;
|
|
113
|
+
/** How many issue comments the conversation read bought. Emitted onto the subject beside
|
|
114
|
+
* `reviewCount` (it used to be computed here and dropped on the floor). */
|
|
115
|
+
commentCount?: number;
|
|
116
|
+
reviews?: ObservedReview[];
|
|
117
|
+
comments?: ObservedComment[];
|
|
118
|
+
};
|
|
119
|
+
type ObservedIssue = {
|
|
120
|
+
id: string;
|
|
121
|
+
number: number;
|
|
122
|
+
repository: string;
|
|
123
|
+
title?: string;
|
|
124
|
+
body?: string;
|
|
125
|
+
state?: string;
|
|
126
|
+
created_at?: string;
|
|
127
|
+
updated_at?: string;
|
|
128
|
+
};
|
|
129
|
+
export declare function pullGithubPrs(execute: GithubExecute, opts: {
|
|
130
|
+
owner: string;
|
|
131
|
+
repo: string;
|
|
132
|
+
state?: 'open' | 'closed' | 'all';
|
|
133
|
+
perPage?: number;
|
|
134
|
+
/** How many recently-updated CLOSED PRs an open-only pull also sweeps (default 20). */
|
|
135
|
+
closedPerPage?: number;
|
|
136
|
+
/** `owner/repo#n` → the `updated_at` last observed for it. */
|
|
137
|
+
lastUpdatedAt?: Record<string, string>;
|
|
138
|
+
}): Promise<ObservedPr[]>;
|
|
139
|
+
/**
|
|
140
|
+
* Pull OBSERVED ISSUES for a repo via the injected executor (GET /repos/:o/:r/issues),
|
|
141
|
+
* EXCLUDING pull requests — the issues endpoint returns PRs too (each PR is an issue),
|
|
142
|
+
* distinguished by a `pull_request` field, which we filter out so PRs only flow through
|
|
143
|
+
* pullGithubPrs. Folds each issue's content (title/body/state). Numbers share the
|
|
144
|
+
* per-repo PR/issue space (real GitHub).
|
|
145
|
+
*/
|
|
146
|
+
export declare function pullGithubIssues(execute: GithubExecute, opts: {
|
|
147
|
+
owner: string;
|
|
148
|
+
repo: string;
|
|
149
|
+
state?: 'open' | 'closed' | 'all';
|
|
150
|
+
perPage?: number;
|
|
151
|
+
}): Promise<ObservedIssue[]>;
|
|
152
|
+
export declare function observedPrsToResources(prs: ObservedPr[]): SyncResource[];
|
|
153
|
+
/**
|
|
154
|
+
* The `updated_at` this world last observed per PR — the budget's memory, read from the
|
|
155
|
+
* SHADOW (the fold of the world's own event log) rather than a cache beside it, so it
|
|
156
|
+
* survives a restart, is per-world like every other pulled fact, and cannot disagree with
|
|
157
|
+
* what was actually folded. A PR nobody has pulled yet is simply absent, and its
|
|
158
|
+
* conversation gets bought.
|
|
159
|
+
*/
|
|
160
|
+
export declare function lastObservedPrUpdates(root?: string): Record<string, string>;
|
|
161
|
+
export declare function observedIssuesToResources(issues: ObservedIssue[]): SyncResource[];
|
|
162
|
+
/**
|
|
163
|
+
* A push this connector DECLINES to make, as opposed to one the vendor rejected. It is
|
|
164
|
+
* raised when enacting the local write faithfully is impossible — the only case today is a
|
|
165
|
+
* threaded reply whose root has no id on the real repo — and the alternative (posting it
|
|
166
|
+
* somewhere else, or forwarding a twin-minted id) would write the wrong thing to a real
|
|
167
|
+
* account. A refusal is ledgered and the sweep continues; the action stays PENDING, so it
|
|
168
|
+
* pushes on a later sweep once the root is known.
|
|
169
|
+
*/
|
|
170
|
+
export declare class GithubPushRefused extends Error {
|
|
171
|
+
constructor(message: string);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* PULL + FOLD: pull a repo's OBSERVED PRs AND issues and fold them into the twin (mirror
|
|
175
|
+
* seeding). Folds CONTENT (PR/issue title/body/state, review state/body, comment body)
|
|
176
|
+
* plus metadata (counts/refs + review/comment existence) — only the Non-goal (repo file
|
|
177
|
+
* CONTENTS) is excluded. Also threads the same resources through `syncPull` so the generic
|
|
178
|
+
* shadow-diff dedup path is exercised (the Linear/Slack-shared contract); the github fold
|
|
179
|
+
* carries the counts/content the generic delta path drops. PRs and issues share ONE
|
|
180
|
+
* per-repo number space (real GitHub). Re-pulling identical observations appends nothing.
|
|
181
|
+
*
|
|
182
|
+
* Per-row conflict tolerance: if a stored event has DIVERGED from what a resource now
|
|
183
|
+
* folds to (a `Conflicting duplicate` — e.g. a post-append line mutation raced the live
|
|
184
|
+
* writer), that ONE row is skipped and its stable id recorded, rather than aborting the
|
|
185
|
+
* whole repo's fold — one row's integrity question must not become a total observation
|
|
186
|
+
* outage for the ~dozens of other resources in the same pull (peak-internal PH-216). The
|
|
187
|
+
* result exposes `conflictsSkipped` + `conflictingIds` so a poller can log the integrity
|
|
188
|
+
* problem loudly instead of it being swallowed. Every OTHER append error stays fatal.
|
|
189
|
+
*/
|
|
190
|
+
export declare function syncGithubFromReal(execute: GithubExecute, opts: {
|
|
191
|
+
owner: string;
|
|
192
|
+
repo: string;
|
|
193
|
+
root?: string;
|
|
194
|
+
occurredAt: string;
|
|
195
|
+
state?: 'open' | 'closed' | 'all';
|
|
196
|
+
perPage?: number;
|
|
197
|
+
}): Promise<{
|
|
198
|
+
observed: number;
|
|
199
|
+
deltasAppended: number;
|
|
200
|
+
eventsAppended: number;
|
|
201
|
+
issues: number;
|
|
202
|
+
conflictsSkipped: number;
|
|
203
|
+
conflictingIds: string[];
|
|
204
|
+
}>;
|
|
205
|
+
/**
|
|
206
|
+
* Push ONE pending GitHub action to the real vendor via the injected executor. Maps
|
|
207
|
+
* the twin's local write (recorded by applyGithubWrite as an action with an
|
|
208
|
+
* `operation` + `fields`) to the matching REST call. The injected `execute.request`
|
|
209
|
+
* is the SOLE credentialed boundary. Returns the real external id when the API gives
|
|
210
|
+
* one (PR/issue/milestone number, review/comment/status/check id, merge sha). Throws
|
|
211
|
+
* on a non-2xx so a failure is never silent.
|
|
212
|
+
*
|
|
213
|
+
* Covers EVERY write operation applyGithubWrite emits, each faithfully mapped to its
|
|
214
|
+
* GitHub REST call (method/path/body):
|
|
215
|
+
* pull_request.create POST .../pulls
|
|
216
|
+
* pull_request.update PATCH .../pulls/:n (+ PATCH .../issues/:n
|
|
217
|
+
* for label/assignee/milestone fields)
|
|
218
|
+
* pull_request.merge PUT .../pulls/:n/merge
|
|
219
|
+
* pull_request.request_reviewers POST .../pulls/:n/requested_reviewers
|
|
220
|
+
* pull_request.remove_requested_reviewers DELETE .../pulls/:n/requested_reviewers
|
|
221
|
+
* pull_request_review.submit POST .../pulls/:n/reviews
|
|
222
|
+
* pull_request_review_comment.create POST .../pulls/:n/comments
|
|
223
|
+
* issue.create POST .../issues
|
|
224
|
+
* issue.update PATCH .../issues/:n
|
|
225
|
+
* issue_comment.create POST .../issues/:n/comments
|
|
226
|
+
* commit_status.create POST .../statuses/:sha
|
|
227
|
+
* check_run.create POST .../check-runs
|
|
228
|
+
* milestone.create POST .../milestones
|
|
229
|
+
* milestone.update PATCH .../milestones/:n
|
|
230
|
+
* Pushing sends the LOCAL content (titles/bodies/diffs the fork authored) — that is
|
|
231
|
+
* legitimate (only PULL must not fabricate content). Unknown ops FAIL LOUDLY (throw).
|
|
232
|
+
*/
|
|
233
|
+
export declare function pushGithubAction(execute: GithubExecute, action: {
|
|
234
|
+
operation?: string;
|
|
235
|
+
subject: {
|
|
236
|
+
type: string;
|
|
237
|
+
id: string;
|
|
238
|
+
};
|
|
239
|
+
fields?: Record<string, unknown>;
|
|
240
|
+
}, opts?: {
|
|
241
|
+
/** Twin comment id → the id that row has on the REAL repo (pulled from GitHub, or
|
|
242
|
+
* returned by an earlier push in this sweep). A reply resolves its root here. */
|
|
243
|
+
externalIds?: Record<string, string>;
|
|
244
|
+
}): Promise<{
|
|
245
|
+
externalId: string;
|
|
246
|
+
}>;
|
|
247
|
+
/**
|
|
248
|
+
* THE R14 PUSH ADAPTER for github (jira's `pushJiraToRemote` is the reference; this
|
|
249
|
+
* transcribes its METHOD): pending local actions cross to the remote through the kernel's
|
|
250
|
+
* ONE RemoteExecute seam under a sealed credential the pack never sees, and each pushed
|
|
251
|
+
* action is confirmed in the local log. Anchored naming: `createGithubTwinFetch` pairs
|
|
252
|
+
* with `syncGithubFromRemote` and `pushGithubToRemote`. Push-plane only — a read refuses
|
|
253
|
+
* loudly. The route grammar is the one `pushGithubAction` speaks (`METHOD /path/{param}`,
|
|
254
|
+
* templated params in the path, the rest as the JSON body).
|
|
255
|
+
*/
|
|
256
|
+
/** This pack's vendor executor over the kernel's ONE RemoteExecute (push plane). */
|
|
257
|
+
export declare function githubPushExecutor(execute: RemoteExecute): GithubExecute;
|
|
258
|
+
/** THE ANCHORED PUSH SEAM (contract "The push arm is the kernel's transaction; a pack performs one
|
|
259
|
+
* action"): perform ONE pending action against GitHub over the kernel executor; the vendor's id comes back. */
|
|
260
|
+
/** The vendor's id in the pack's own subject grammar: a number replaces the trailing number of the
|
|
261
|
+
* local id (`acme/web#issue:1` → `acme/web#issue:57`, `acme/web#3` → `acme/web#9`, `comment:2` →
|
|
262
|
+
* `comment:184`); anything else (a sha, a ref, a path, an owner/name) leaves the address as it is
|
|
263
|
+
* and rides on the receipt as `vendorId`. The kernel rebinds the subject to what comes back
|
|
264
|
+
* (contract "A pushed write adopts the vendor's id"). */
|
|
265
|
+
export declare function adoptGithubId(localId: string, vendorId: string | undefined): string;
|
|
266
|
+
export declare function performGithubAction(execute: RemoteExecute, action: TwinAction, ctx: PerformContext): Promise<PushOutcome>;
|
|
267
|
+
/**
|
|
268
|
+
* THE REPOSITORY AND ITS BRANCHES are observed with the PRs and issues: a working copy's
|
|
269
|
+
* confirmed writes (a branch it cut, the repo it declared) survive only as what reality
|
|
270
|
+
* shows back, so the pull says what reality holds — the repo and every branch head.
|
|
271
|
+
*/
|
|
272
|
+
export declare function observeRepositoryAndBranches(execute: GithubExecute, owner: string, repo: string): Promise<SyncResource[]>;
|
|
273
|
+
/**
|
|
274
|
+
* THE R14 SCHEDULED-PULL ADAPTER (jira is the reference; this transcribes its METHOD):
|
|
275
|
+
* adapts this pack's executor onto the kernel's ONE RemoteExecute seam, so the twins
|
|
276
|
+
* service can schedule pulls with a sealed credential the pack never sees. Anchored
|
|
277
|
+
* naming: `createGithubTwinFetch` pairs with `syncGithubFromRemote`.
|
|
278
|
+
*
|
|
279
|
+
* The link's origin names the REPO, not just the API host — a link is a git remote:
|
|
280
|
+
* https://api.github.com/repos/{owner}/{repo}
|
|
281
|
+
* Egress still anchors at the origin's HOST (the service's RemoteExecute discards the
|
|
282
|
+
* path when routing), so the path here is pure identity. Pull-plane only — every
|
|
283
|
+
* non-read request refuses loudly.
|
|
284
|
+
*
|
|
285
|
+
* Rate note, counted over the routes this pull actually calls: 2 list reads (the repo and
|
|
286
|
+
* its branches) + 1 PR list + 1 issue list, and then, per PR whose `updated_at` MOVED since
|
|
287
|
+
* the last pull, three PAGED conversation reads — the reviews, the issue comments and the
|
|
288
|
+
* inline comments — at 1 request each for a PR under 100 rows and up to 10 each beyond
|
|
289
|
+
* that. So a poll costs 4 + 3·CHANGED at the floor and 4 + 30·CHANGED at the ceiling; an
|
|
290
|
+
* unchanged PR costs nothing beyond the list. The link's sync interval still carries the
|
|
291
|
+
* budget — 60s at the default page floods a PAT's 5000/hr the first time it walks a busy
|
|
292
|
+
* repo; schedule github links at ≥120s.
|
|
293
|
+
*/
|
|
294
|
+
export declare function syncGithubFromRemote(execute: RemoteExecute, opts?: {
|
|
295
|
+
root?: string;
|
|
296
|
+
origin?: string;
|
|
297
|
+
state?: 'open' | 'closed' | 'all';
|
|
298
|
+
perPage?: number;
|
|
299
|
+
}): Promise<{
|
|
300
|
+
observed: number;
|
|
301
|
+
deltasAppended: number;
|
|
302
|
+
eventsAppended: number;
|
|
303
|
+
issues: number;
|
|
304
|
+
conflictsSkipped: number;
|
|
305
|
+
conflictingIds: string[];
|
|
306
|
+
}>;
|
|
307
|
+
export {};
|