@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,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_doc": "Declared evidence-twin scope: GitHub fields the twin does NOT model, each with a reason. Applies to ALL GitHub objects the twin serves (pull_request, pull_request_review, review-comment, pull-file, pull-commit, label, assignee, issue, issue_comment, commit_status, check_run, milestone, requested_reviewer, issue cross-reference event) — PR node_id names the twin GraphQL node; other objects retain the declared node_id gaps. Object-specific gaps are namespaced (label.*, assignee.*, reviewComment.*, pullFile.*, pullCommit.*, status.*, checkRun.*, milestone.*, requestedReviewer.*, issueEvent.*). The spec-conformance gate (github-conformance.ts) treats a missing-required field as a BUG unless it is declared here, so 'what we don't serve' is explicit and reviewable, not silently absent. See github-twin.ts header: the `github` world is an EVIDENCE mirror (metadata), not a content mirror. A trailing `.*` covers a whole unmodeled sub-object. NOTE: issues, commit statuses, check runs, and milestones are LOCAL simulator/fork constructs (no observed evidence fold — observed PR evidence never carries CI/checks/milestones/review-requests) and have no vendored conformance schema yet, so those objects are not run through the spec gate; their simplifications below are recorded for honesty.",
|
|
3
|
+
"deviations": [
|
|
4
|
+
{ "path": "issue.id", "kind": "missing-required", "reason": "issue object: no real GitHub integer id is observed on pull (the issue body carries number/title/body/state); a fabricated id would be invented" },
|
|
5
|
+
{ "path": "issue.node_id", "kind": "missing-required", "reason": "no real GraphQL node id for a local issue" },
|
|
6
|
+
{ "path": "issue.user", "kind": "missing-required", "reason": "issue author not modeled; a synthetic simple-user would fabricate a login/id" },
|
|
7
|
+
{ "path": "issue.reactions", "kind": "missing-required", "reason": "reaction rollup not modeled by the local issue construct" },
|
|
8
|
+
{ "path": "issue.timeline_url", "kind": "missing-required", "reason": "timeline hypermedia not modeled" },
|
|
9
|
+
{ "path": "id", "kind": "missing-required", "reason": "PR object: evidence mirror has no real GitHub id (reviews/comments DO emit an integer id from the local sequence)" },
|
|
10
|
+
{ "path": "node_id", "kind": "missing-required", "reason": "PRs emit the synthetic node ID accepted by the twin GraphQL API. Other objects do not yet model node IDs." },
|
|
11
|
+
{ "path": "created_at", "kind": "missing-required", "reason": "observed PR-evidence events do not carry PR creation timestamps" },
|
|
12
|
+
{ "path": "updated_at", "kind": "missing-required", "reason": "see created_at — no PR timestamps in evidence" },
|
|
13
|
+
{ "path": "title", "kind": "missing-required", "reason": "title IS folded on pull (content mirror) and on local writes; declared only for the edge case of a PR that surfaced solely via a review/comment reference (no PR-list entry), which has no title to emit" },
|
|
14
|
+
{ "path": "user.*", "kind": "missing-required", "reason": "PR author login/type are retained when known. Other simple-user subfields, including vendor numeric id and profile URLs, are not modeled." },
|
|
15
|
+
{ "path": "user", "kind": "missing-required", "reason": "When PR author identity was never observed and no explicit local create proves the modeled caller, user is omitted rather than fabricated." },
|
|
16
|
+
{ "path": "_links.*", "kind": "missing-required", "reason": "hypermedia _links block not modeled by the evidence twin" },
|
|
17
|
+
{ "path": "_links", "kind": "missing-required", "reason": "see _links.*" },
|
|
18
|
+
{ "path": "author_association", "kind": "missing-required", "reason": "author relationship to repo not observed" },
|
|
19
|
+
{ "path": "mergeable_state", "kind": "missing-required", "reason": "mergeability is a live-computed GitHub field, not observable evidence" },
|
|
20
|
+
{ "path": "merged", "kind": "missing-required", "reason": "observed evidence carries no merge outcome, so a not-yet-merged PR emits merged=null (present-and-nullable); a local merge write (PUT .../merge) sets it to a typed boolean" },
|
|
21
|
+
{ "path": "maintainer_can_modify", "kind": "missing-required", "reason": "permission flag not observed" },
|
|
22
|
+
{ "path": "additions", "kind": "missing-required", "reason": "line-addition count is NOT in observed PR evidence (only file/commit counts are), so an observed PR omits it; a LOCAL write that carries a `files` list rolls additions up from the diff and emits a typed integer. Declared for the observed scope only." },
|
|
23
|
+
{ "path": "deletions", "kind": "missing-required", "reason": "line-deletion count is NOT in observed PR evidence; observed PRs omit it, while a LOCAL write with a `files` list rolls deletions up from the diff and emits a typed integer. Declared for the observed scope only." },
|
|
24
|
+
{ "path": "comments", "kind": "missing-required", "reason": "the issue-comment count is not surfaced" },
|
|
25
|
+
{ "path": "review_comments", "kind": "missing-required", "reason": "the review-comment count is not surfaced" },
|
|
26
|
+
{ "path": "commits", "kind": "missing-required", "reason": "emitted as a typed integer when observed; declared only for PRs whose evidence lacked a commit count" },
|
|
27
|
+
{ "path": "changed_files", "kind": "missing-required", "reason": "emitted as a typed integer when observed; declared only for PRs whose evidence lacked a changed-files count" },
|
|
28
|
+
{ "path": "base.label", "kind": "missing-required", "reason": "evidence tracks base ref only, not the owner:ref label" },
|
|
29
|
+
{ "path": "base.sha", "kind": "missing-required", "reason": "evidence tracks head sha only; base sha is not observed" },
|
|
30
|
+
{ "path": "base.user.*", "kind": "missing-required", "reason": "base repo owner not modeled (evidence twin)" },
|
|
31
|
+
{ "path": "base.user", "kind": "missing-required", "reason": "see base.user.*" },
|
|
32
|
+
{ "path": "base.repo.*", "kind": "missing-required", "reason": "full_name is served from the stored PR repository. Other Repository fields, including URL templates and settings, are not modeled here." },
|
|
33
|
+
{ "path": "head.label", "kind": "missing-required", "reason": "evidence tracks head sha only, not the owner:ref label" },
|
|
34
|
+
{ "path": "head.ref", "kind": "missing-required", "reason": "evidence tracks head sha; head branch ref is not observed" },
|
|
35
|
+
{ "path": "head.user.*", "kind": "missing-required", "reason": "head repo owner not modeled (evidence twin)" },
|
|
36
|
+
{ "path": "head.user", "kind": "missing-required", "reason": "see head.user.*" },
|
|
37
|
+
{ "path": "head.repo.*", "kind": "missing-required", "reason": "full head Repository object not modeled by the evidence twin" },
|
|
38
|
+
{ "path": "head.repo", "kind": "missing-required", "reason": "see head.repo.*" },
|
|
39
|
+
{ "path": "submitted_at", "kind": "missing-required", "reason": "review object: OBSERVED reviews carry no submission timestamp (only existence); a LOCAL review write sets submitted_at to the write time. Omitted, not faked, when unknown." },
|
|
40
|
+
{ "path": "label.id", "kind": "missing-required", "reason": "labels are written/read by NAME; the twin stores only the name and emits {name}. id/node_id/url/color/default/description would be fabricated, so the label object carries the name alone." },
|
|
41
|
+
{ "path": "label.node_id", "kind": "missing-required", "reason": "see label.id — no real GraphQL node id for a name-only label" },
|
|
42
|
+
{ "path": "label.url", "kind": "missing-required", "reason": "label url template not modeled (name-only label)" },
|
|
43
|
+
{ "path": "label.color", "kind": "missing-required", "reason": "label color not supplied on write; would be fabricated" },
|
|
44
|
+
{ "path": "label.default", "kind": "missing-required", "reason": "is-default flag not modeled for a name-only label" },
|
|
45
|
+
{ "path": "label.description", "kind": "missing-required", "reason": "label description not modeled for a name-only label" },
|
|
46
|
+
{ "path": "assignee.*", "kind": "missing-required", "reason": "assignees are written/read by LOGIN; the twin stores only the login and emits {login}. The rest of the simple-user object (id, node_id, avatar_url, urls, type) would be fabricated." },
|
|
47
|
+
{ "path": "reviewComment.node_id", "kind": "missing-required", "reason": "PR review-comment object: no real GraphQL node id for a local comment" },
|
|
48
|
+
{ "path": "reviewComment.diff_hunk", "kind": "missing-required", "reason": "OBSERVED review comments carry no diff evidence, so they omit diff_hunk; a LOCAL diff-threaded write (POST /pulls/:n/comments with path) anchors the comment and emits diff_hunk (the supplied hunk or ''). Declared for the observed scope only." },
|
|
49
|
+
{ "path": "reviewComment.path", "kind": "missing-required", "reason": "OBSERVED review comments carry no diff path; a LOCAL diff-threaded write supplies path + line + side (+ optional start_line) and surfaces them on the comment. Declared for the observed scope only." },
|
|
50
|
+
{ "path": "reviewComment.commit_id", "kind": "missing-required", "reason": "commit a review comment pins to is not observed" },
|
|
51
|
+
{ "path": "reviewComment.original_commit_id", "kind": "missing-required", "reason": "original commit not observed" },
|
|
52
|
+
{ "path": "reviewComment.author_association", "kind": "missing-required", "reason": "author relationship to repo not observed" },
|
|
53
|
+
{ "path": "reviewComment._links.*", "kind": "missing-required", "reason": "hypermedia _links block not modeled" },
|
|
54
|
+
{ "path": "pullFile.*", "kind": "behavior", "reason": "GET /pulls/:n/files: OBSERVED PR evidence carries a changed-files COUNT but no per-file detail, so an observed PR returns an EMPTY file list (never fabricated). A LOCAL PR write (POST/PATCH with a `files` list of {filename,status,additions,deletions,changes,patch}) carries real per-file diffs, returned here paginated; the remaining file sub-fields the write didn't supply (blob sha when omitted, contents/raw url templates beyond what's derived) stay unmodeled. The carried files also roll up changed_files/additions/deletions on the PR object." },
|
|
55
|
+
{ "path": "pullCommit.*", "kind": "behavior", "reason": "GET /pulls/:n/commits: OBSERVED PR evidence carries a commit COUNT but no per-commit detail, so an observed PR returns an EMPTY commit list (never fabricated). A LOCAL PR write (POST/PATCH with a `commits` list of {sha, commit.message, commit.author{name,email,date}}) carries real commits, returned here paginated; the author/committer simple-user objects, tree, parents and verification are not modeled (the twin emits the message + commit.author it was given, with author/committer simple-users null). A missing sha is derived deterministically (sha256 of repo+index+message), never random." },
|
|
56
|
+
{ "path": "checksStatus", "kind": "behavior", "reason": "CI status checks (commit statuses + check runs) are NOT in observed PR evidence — observed mirrors carry no CI. They are modeled as LOCAL-write constructs: POST /statuses/:sha + POST /check-runs persist via the action log, and GET .../commits/:ref/status|statuses|check-runs read them back. An observed-only PR therefore reports a 'pending' combined status with total_count 0 (the faithful empty), never a fabricated check." },
|
|
57
|
+
{ "path": "requestedReviewers", "kind": "behavior", "reason": "Review REQUESTS are distinct from submitted reviews and are NOT in observed evidence (the fold sees submitted reviews only). Modeled as a LOCAL write (POST/DELETE /pulls/:n/requested_reviewers, body {reviewers:[login]}) storing bare logins; surfaced on the PR object (requested_reviewers) and GET /pulls/:n/requested_reviewers as {users:[{login}], teams:[]}. Observed-only PRs have none." },
|
|
58
|
+
{ "path": "requestedReviewer.*", "kind": "missing-required", "reason": "requested reviewers are stored by LOGIN; the twin emits {login} and declares the rest of the simple-user object (id, node_id, avatar_url, urls, type) — it would be fabricated. requested_teams is not modeled (always empty)." },
|
|
59
|
+
{ "path": "status.node_id", "kind": "missing-required", "reason": "commit_status object: no real GraphQL node id for a local status" },
|
|
60
|
+
{ "path": "status.creator.*", "kind": "missing-required", "reason": "the user that created a status is not modeled (local CI construct); a synthetic simple-user would fabricate a login/id, so creator is null" },
|
|
61
|
+
{ "path": "status.avatar_url", "kind": "missing-required", "reason": "status avatar_url not modeled (no creator)" },
|
|
62
|
+
{ "path": "checkRun.node_id", "kind": "missing-required", "reason": "check_run object: no real GraphQL node id for a local check run" },
|
|
63
|
+
{ "path": "checkRun.external_id", "kind": "missing-required", "reason": "check run external id not supplied on write" },
|
|
64
|
+
{ "path": "checkRun.output.*", "kind": "missing-required", "reason": "check run output (title/summary/annotations) not modeled — would be fabricated" },
|
|
65
|
+
{ "path": "checkRun.check_suite.*", "kind": "missing-required", "reason": "check run is not grouped into a modeled check suite (no suite evidence)" },
|
|
66
|
+
{ "path": "checkRun.app.*", "kind": "missing-required", "reason": "the GitHub App that produced a check run is not modeled (local construct)" },
|
|
67
|
+
{ "path": "checkRun.pull_requests", "kind": "missing-required", "reason": "the back-link from a check run to its PRs is not modeled (keyed by head_sha only)" },
|
|
68
|
+
{ "path": "milestone.id", "kind": "missing-required", "reason": "milestone object: local construct emits a deterministic sequence id, but the real GitHub integer id / GraphQL node_id are not observed and not fabricated as the canonical id" },
|
|
69
|
+
{ "path": "milestone.node_id", "kind": "missing-required", "reason": "no real GraphQL node id for a local milestone" },
|
|
70
|
+
{ "path": "milestone.creator.*", "kind": "missing-required", "reason": "milestone creator not modeled; a synthetic simple-user would fabricate a login/id, so creator is omitted" },
|
|
71
|
+
{ "path": "milestone.open_issues", "kind": "behavior", "reason": "issue/PR-per-milestone rollup counts are emitted as 0 — the twin does not yet aggregate how many issues/PRs reference a milestone, so it reports 0 rather than fabricating a count" },
|
|
72
|
+
{ "path": "milestone.closed_issues", "kind": "behavior", "reason": "see milestone.open_issues — closed-issue rollup emitted as 0" },
|
|
73
|
+
{ "path": "issueEvent.*", "kind": "behavior", "reason": "GET /issues/:n/events|timeline: real GitHub returns the full timeline (labeled/assigned/referenced/cross-referenced/...). The twin models ONLY the cross-referenced linked-PR/issue relation (set via the twin-extension _twin_linked field — GitHub has no direct link-write endpoint, links are inferred from body text). actor/created_at and the rich source object are emitted null/minimal rather than fabricated; other event types are not modeled." },
|
|
74
|
+
{ "path": "issue.linked", "kind": "behavior", "reason": "linked PRs/issues are a simple LOCAL relation ([{type,number}]) the twin surfaces via the events endpoint as cross-referenced events. Real GitHub infers links from body cross-references / the timeline; the twin lets a simulator declare them explicitly (PATCH issue with _twin_linked) rather than parsing prose." },
|
|
75
|
+
{ "path": "issue.milestone", "kind": "behavior", "reason": "an issue/PR milestone is set by NUMBER via PATCH {milestone:n}; the twin looks up the local milestone object (created via POST /milestones) and surfaces it, or null when none/unknown — it never fabricates a milestone object for an unknown number" },
|
|
76
|
+
{ "path": "release.node_id", "kind": "missing-required", "reason": "release object: local construct emits a deterministic sequence id, but no real GraphQL node id is observed or fabricated" },
|
|
77
|
+
{ "path": "release.author.*", "kind": "missing-required", "reason": "release author not modeled (local construct); a synthetic simple-user would fabricate a login/id, so author is null" },
|
|
78
|
+
{ "path": "release.reactions", "kind": "missing-required", "reason": "reaction rollup not modeled by the local release construct" },
|
|
79
|
+
{ "path": "release.discussion_url", "kind": "missing-required", "reason": "release-discussion hypermedia not modeled (Discussions are a separate todo)" },
|
|
80
|
+
{ "path": "release.published_at", "kind": "behavior", "reason": "a DRAFT release emits published_at=null (real GitHub behavior — a draft has no publish time); a published (draft:false) release stamps published_at to the write time. Omitted/null, never faked." },
|
|
81
|
+
{ "path": "asset.*", "kind": "behavior", "reason": "release ASSETS are MODELED AS METADATA ONLY: the twin carries name/label/content_type/size/state/download_count + derivable url templates (POST /releases/:id/assets persists via the action log; GET .../assets reads them back). The actual asset binary BYTES are a declared Non-goal (large + redundant — the same boundary as repo blob bytes); browser_download_url points at the asset path but the twin serves NO real content. uploader simple-user + node_id are not modeled (would be fabricated)." },
|
|
82
|
+
{ "path": "tag.*", "kind": "behavior", "reason": "GET /tags + GET /git/refs/tags: tags are DERIVED from the LOCAL published (non-draft) releases the twin created — there is no observed git-data evidence, and git commit/blob BYTES are the Non-goal. The commit sha is deterministic (sha256 of repo+tag), the ref is a lightweight 'commit' ref (no annotated-tag object), and the full commit object (author/message/tree) + node_id are not modeled." },
|
|
83
|
+
{ "path": "discussion.*", "kind": "behavior", "reason": "DISCUSSIONS TRANSPORT DEVIATION: on real GitHub, Discussions (and their categories/comments/answers) are served by the GraphQL v4 API, NOT REST — there is no public REST Discussions endpoint. The twin models them over its OWN REST handler (POST/GET/PATCH/DELETE /repos/:o/:r/discussions[/:num][/comments][/categories]) for CONSISTENCY with the rest of the twin's REST surface; the OBJECT shapes mirror the GraphQL node fields projected into a REST-style body (number/title/body/state/category/answer). This is an honest, declared transport+shape deviation, not a fidelity claim about GitHub's REST API. Discussions are LOCAL constructs (no observed evidence fold)." },
|
|
84
|
+
{ "path": "discussion.node_id", "kind": "missing-required", "reason": "discussion object: no real GraphQL node id is observed for a local discussion (Discussions are a GraphQL product; the twin emits node_id=null rather than fabricating one)" },
|
|
85
|
+
{ "path": "discussion.user", "kind": "missing-required", "reason": "discussion author not modeled (local construct); a synthetic simple-user would fabricate a login/id, so user is null" },
|
|
86
|
+
{ "path": "discussion.reactions", "kind": "missing-required", "reason": "reaction rollup not modeled by the local discussion construct" },
|
|
87
|
+
{ "path": "discussion.answer", "kind": "behavior", "reason": "the accepted answer is surfaced as answer_comment_id (the chosen comment's local id, null when none) + answer_chosen_at; the full GraphQL answer node (the embedded comment object) is not duplicated — the comment is fetchable via the comments list. Marking is only valid for an ANSWERABLE (Q&A) category; a mark on a non-answerable discussion 422s." },
|
|
88
|
+
{ "path": "discussionCategory.*", "kind": "behavior", "reason": "discussion CATEGORIES are SEEDED per-repo with GitHub's default set (Announcements/General/Ideas/Q&A/Show and tell), only Q&A answerable; a custom category is a LOCAL construct (POST /discussions/categories). Ids are deterministic (sha256 of repo+slug), repository_id is a deterministic short hash, and node_id is not modeled. The real GraphQL category node carries more (createdAt/updatedAt/repository) that the twin omits." },
|
|
89
|
+
{ "path": "discussionComment.node_id", "kind": "missing-required", "reason": "discussion-comment object: no real GraphQL node id for a local comment" },
|
|
90
|
+
{ "path": "discussionComment.user", "kind": "missing-required", "reason": "discussion-comment author not modeled (local construct); user is null rather than a fabricated simple-user" },
|
|
91
|
+
{ "path": "discussionComment.reactions", "kind": "missing-required", "reason": "reaction rollup not modeled by the local discussion-comment construct" },
|
|
92
|
+
{ "path": "discussionComment.parent_id", "kind": "behavior", "reason": "a threaded REPLY pins to its parent comment via parent_id (set on the create body); a top-level comment has parent_id=null. The twin models a single reply level (parent → reply), matching GitHub's two-level discussion threading; is_answer marks the accepted answer (Q&A only)." }
|
|
93
|
+
]
|
|
94
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# github-openapi-operations.json — provenance
|
|
2
|
+
|
|
3
|
+
The **operation-inventory denominator** for the TWIN-15 spec-census pilot (B5a —
|
|
4
|
+
`docs/COMPLETENESS_PASS.md`): a curated, hand-vendored *subset* of GitHub's published REST
|
|
5
|
+
OpenAPI, used ONLY to enumerate `{method, path}` operations via
|
|
6
|
+
`deriveFromOpenAPI` (`packages/world-tooling/src/derive.ts`) for
|
|
7
|
+
`../github-spec-census.json` to map against. It is deliberately NOT a full spec fetch.
|
|
8
|
+
|
|
9
|
+
- **Upstream:** `github/rest-api-description` (MIT licensed) —
|
|
10
|
+
`https://github.com/github/rest-api-description`, specifically
|
|
11
|
+
`descriptions/api.github.com/api.github.com.json`.
|
|
12
|
+
- **How it was built:** hand-authored path/method entries from the operator's knowledge of
|
|
13
|
+
GitHub's documented REST API — **not fetched over the network**. This repo's completeness
|
|
14
|
+
pass runs offline/deterministic (see `docs/COMPLETENESS_PASS.md` — no live-vendor calls in
|
|
15
|
+
any gated script or test), so this fixture is vendored the same way
|
|
16
|
+
`github-pull-schema.json` et al. are: a real vendor contract, captured by hand instead of by
|
|
17
|
+
a live HTTP fetch.
|
|
18
|
+
- **Curated on:** 2026-07-04.
|
|
19
|
+
- **Scope (38 operations):** the domain `@volter/twin-github` actually models — issues, pull
|
|
20
|
+
requests, repos, git-data refs, commit/review comments (listing them, writing one, and
|
|
21
|
+
replying in a thread) — **plus a deliberate handful of
|
|
22
|
+
adjacent real GitHub operations the pack does NOT model** (repo-wide issue/PR comment and
|
|
23
|
+
event listings, community-profile metrics, fork upstream-merge, vulnerability-alerts toggle,
|
|
24
|
+
matching-refs listing, async-computed repo statistics, repo transfer, and the automated
|
|
25
|
+
security-fixes toggle). Those are real, documented GitHub endpoints — they exist specifically
|
|
26
|
+
so the census's `unmapped` bucket is genuinely exercised instead of a hollow
|
|
27
|
+
1:1 map that proves nothing (see the census's own "why a census where everything maps 1:1
|
|
28
|
+
proves nothing" doctrine note).
|
|
29
|
+
- **Bounded, not exhaustive:** GitHub's real OpenAPI doc is multi-megabyte and covers hundreds
|
|
30
|
+
of operations across many products (Actions, Packages, Codespaces, Projects, …) the pack
|
|
31
|
+
models too (see `github-capabilities.ts`) but that are OUT of this pilot fixture's ~30-40 op
|
|
32
|
+
budget — B5a is explicitly a ONE-VENDOR, ONE-SLICE pilot; B5b (TWIN-16, since built) generalized
|
|
33
|
+
the denominator via the per-vendor spec-source registry `spec-sources.json` (repo root), which
|
|
34
|
+
registers this fixture/census pair as github's entry and rolls the same census format out to the
|
|
35
|
+
other vendors on the manifest-census duty cadence.
|
|
36
|
+
- **TWIN-82 (R-T4) — the curation boundary is now mechanical, not just disclosed here:**
|
|
37
|
+
`../github-spec-census.json` carries a committed `scopePaths: ["/repos/{owner}/{repo}"]` array
|
|
38
|
+
and a `fullSpecEstimateOps` (~850) honest estimate of GitHub's full REST surface.
|
|
39
|
+
`scripts/spec-census.ts --check` fails if any fixture operation falls outside `scopePaths`, and
|
|
40
|
+
prints "census covers N ops within committed scope X; full spec ~M ops" on every run so the
|
|
41
|
+
sampled fraction is visible in gate output — not only in this prose note. `scripts/spec-refresh.ts`
|
|
42
|
+
refuses any `--scope-paths` CLI value that isn't a member of the committed `scopePaths` array (see
|
|
43
|
+
"Refresh" below), so the boundary can't silently drift from what an operator hand-types.
|
|
44
|
+
|
|
45
|
+
## Refresh
|
|
46
|
+
|
|
47
|
+
The fixture also inventories the single `POST /graphql` transport already included in the
|
|
48
|
+
census's committed scope. Its first-party source is
|
|
49
|
+
[GitHub: Forming calls with GraphQL](https://docs.github.com/en/graphql/guides/forming-calls-with-graphql)
|
|
50
|
+
(verified 2026-09-06), not the REST OpenAPI repository: ordinary queries and mutations use
|
|
51
|
+
POST at `https://api.github.com/graphql`. This entry inventories that transport, not every
|
|
52
|
+
GraphQL field or mutation, and does not claim full schema coverage. REST-only fixture refreshes
|
|
53
|
+
must preserve this separately sourced entry and its census mapping.
|
|
54
|
+
|
|
55
|
+
If GitHub's REST API changes a path/method in this subset (or the pack's modeled domain
|
|
56
|
+
grows), update this fixture and `../github-spec-census.json` together — `bun
|
|
57
|
+
scripts/spec-census.ts --check` fails loudly (the completeness/tamper tooth) if the two drift
|
|
58
|
+
out of bijection.
|
|
59
|
+
|
|
60
|
+
**B6 (TWIN-17), built:** the manifest-census duty's refresh tool is `scripts/spec-refresh.ts`.
|
|
61
|
+
Download GitHub's current `descriptions/api.github.com/api.github.com.json` (network happens
|
|
62
|
+
OUTSIDE the tool — this repo's gate runs offline) and run:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
bun scripts/spec-refresh.ts --vendor github --from-file <path-to-the-downloaded-spec> \
|
|
66
|
+
--scope-paths /repos/{owner}/{repo}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`--scope-paths` restricts the diff to this fixture's curated domain — without it, every one of
|
|
70
|
+
GitHub's hundreds of out-of-subset operations (Actions, Packages, Codespaces, Projects, …) would
|
|
71
|
+
be reported as spuriously "removed". The report names every added/removed `{method, path}` and
|
|
72
|
+
exits nonzero if the vendor changed. Add `--apply` to rewrite this fixture and
|
|
73
|
+
`../github-spec-census.json` together (new operations appended as `unmapped` for triage, removed
|
|
74
|
+
operations dropped from both, `unmappedBaseline` left untouched so growth still WARNs); the tool
|
|
75
|
+
then re-runs the bijection check itself before exiting. Once satisfied, record the duty:
|
|
76
|
+
`bun scripts/next-duties.ts --record --duty manifest-census --target github`.
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
{
|
|
2
|
+
"openapi": "3.0.3",
|
|
3
|
+
"info": {
|
|
4
|
+
"title": "GitHub REST API (spec-census pilot subset)",
|
|
5
|
+
"version": "2026-06-14",
|
|
6
|
+
"description": "A curated, hand-vendored SUBSET of GitHub's published REST OpenAPI (github/rest-api-description, https://github.com/github/rest-api-description), used ONLY as the operation-inventory denominator for the TWIN-15 spec census (see ../github-spec-census.json). Domain covered: issues, pull requests, repos, git refs, and commit/review comments -- the surface the @volter/twin-github pack models -- PLUS a deliberate handful of adjacent real GitHub operations the pack does NOT model, so the census genuinely exercises its `unmapped` and `$ruled` buckets instead of mapping 1:1. This is NOT a full GitHub OpenAPI document (GitHub's real spec is multi-megabyte); it is bounded to ~30-40 operations by design, offline and deterministic -- see github-openapi-operations.SOURCE.md for exactly how each path/method was curated. Method + path + operationId + summary ONLY: no schemas and NO STATUS CODES. It used to carry a response code or two per operation, which read as the operation's whole response set -- diff status codes against the freshly fetched spec, never against this file."
|
|
7
|
+
},
|
|
8
|
+
"x-source": {
|
|
9
|
+
"vendor": "github",
|
|
10
|
+
"upstream": "https://github.com/github/rest-api-description",
|
|
11
|
+
"upstreamFile": "descriptions/api.github.com/api.github.com.json",
|
|
12
|
+
"vendored": "hand-authored from the operator's knowledge of GitHub's published REST API paths/methods -- NOT fetched over the network (offline/deterministic build requirement)",
|
|
13
|
+
"curatedOn": "2026-07-04",
|
|
14
|
+
"scope": "issues, pulls, repos, git-data refs, commit/review comments -- the domain the github pack models -- plus adjacent real GitHub operations the pack intentionally leaves unmapped/unmapped"
|
|
15
|
+
},
|
|
16
|
+
"paths": {
|
|
17
|
+
"/graphql": {
|
|
18
|
+
"post": {
|
|
19
|
+
"operationId": "graphql/api",
|
|
20
|
+
"summary": "Execute a GraphQL query or mutation",
|
|
21
|
+
"tags": ["graphql"],
|
|
22
|
+
"responses": { "200": { "description": "GraphQL response with data and/or errors" } }
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"/repos/{owner}/{repo}/issues": {
|
|
26
|
+
"get": {
|
|
27
|
+
"operationId": "issues/list-for-repo",
|
|
28
|
+
"summary": "List repository issues",
|
|
29
|
+
"tags": [
|
|
30
|
+
"issues"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"post": {
|
|
34
|
+
"operationId": "issues/create",
|
|
35
|
+
"summary": "Create an issue",
|
|
36
|
+
"tags": [
|
|
37
|
+
"issues"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"/repos/{owner}/{repo}/issues/{issue_number}": {
|
|
42
|
+
"patch": {
|
|
43
|
+
"operationId": "issues/update",
|
|
44
|
+
"summary": "Update an issue (title/body/state/labels/assignees/milestone)",
|
|
45
|
+
"tags": [
|
|
46
|
+
"issues"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"/repos/{owner}/{repo}/issues/{issue_number}/comments": {
|
|
51
|
+
"get": {
|
|
52
|
+
"operationId": "issues/list-comments",
|
|
53
|
+
"summary": "List issue comments",
|
|
54
|
+
"tags": [
|
|
55
|
+
"issues"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"post": {
|
|
59
|
+
"operationId": "issues/create-comment",
|
|
60
|
+
"summary": "Create an issue comment",
|
|
61
|
+
"tags": [
|
|
62
|
+
"issues"
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"/repos/{owner}/{repo}/issues/{issue_number}/labels": {
|
|
67
|
+
"post": {
|
|
68
|
+
"operationId": "issues/add-labels",
|
|
69
|
+
"summary": "Add labels to an issue",
|
|
70
|
+
"tags": [
|
|
71
|
+
"issues"
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"/repos/{owner}/{repo}/issues/{issue_number}/lock": {
|
|
76
|
+
"put": {
|
|
77
|
+
"operationId": "issues/lock",
|
|
78
|
+
"summary": "Lock an issue conversation",
|
|
79
|
+
"tags": [
|
|
80
|
+
"issues"
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"/repos/{owner}/{repo}/issues/comments": {
|
|
85
|
+
"get": {
|
|
86
|
+
"operationId": "issues/list-comments-for-repo",
|
|
87
|
+
"summary": "List issue comments for a repository (repo-wide, across all issues)",
|
|
88
|
+
"tags": [
|
|
89
|
+
"issues"
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"/repos/{owner}/{repo}/issues/events": {
|
|
94
|
+
"get": {
|
|
95
|
+
"operationId": "issues/list-events-for-repo",
|
|
96
|
+
"summary": "List issue events for a repository (repo-wide, across all issues)",
|
|
97
|
+
"tags": [
|
|
98
|
+
"issues"
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"/repos/{owner}/{repo}/pulls": {
|
|
103
|
+
"get": {
|
|
104
|
+
"operationId": "pulls/list",
|
|
105
|
+
"summary": "List pull requests",
|
|
106
|
+
"tags": [
|
|
107
|
+
"pulls"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
"post": {
|
|
111
|
+
"operationId": "pulls/create",
|
|
112
|
+
"summary": "Create a pull request",
|
|
113
|
+
"tags": [
|
|
114
|
+
"pulls"
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"/repos/{owner}/{repo}/pulls/{pull_number}": {
|
|
119
|
+
"get": {
|
|
120
|
+
"operationId": "pulls/get",
|
|
121
|
+
"summary": "Get a pull request",
|
|
122
|
+
"tags": [
|
|
123
|
+
"pulls"
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
"patch": {
|
|
127
|
+
"operationId": "pulls/update",
|
|
128
|
+
"summary": "Update a pull request",
|
|
129
|
+
"tags": [
|
|
130
|
+
"pulls"
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"/repos/{owner}/{repo}/pulls/{pull_number}/merge": {
|
|
135
|
+
"put": {
|
|
136
|
+
"operationId": "pulls/merge",
|
|
137
|
+
"summary": "Merge a pull request",
|
|
138
|
+
"tags": [
|
|
139
|
+
"pulls"
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"/repos/{owner}/{repo}/pulls/{pull_number}/files": {
|
|
144
|
+
"get": {
|
|
145
|
+
"operationId": "pulls/list-files",
|
|
146
|
+
"summary": "List pull request files",
|
|
147
|
+
"tags": [
|
|
148
|
+
"pulls"
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"/repos/{owner}/{repo}/pulls/{pull_number}/reviews": {
|
|
153
|
+
"get": {
|
|
154
|
+
"operationId": "pulls/list-reviews",
|
|
155
|
+
"summary": "List reviews for a pull request",
|
|
156
|
+
"tags": [
|
|
157
|
+
"pulls"
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
"post": {
|
|
161
|
+
"operationId": "pulls/create-review",
|
|
162
|
+
"summary": "Create a review for a pull request",
|
|
163
|
+
"tags": [
|
|
164
|
+
"pulls"
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"/repos/{owner}/{repo}/pulls/{pull_number}/comments": {
|
|
169
|
+
"get": {
|
|
170
|
+
"operationId": "pulls/list-review-comments",
|
|
171
|
+
"summary": "List review comments on a pull request",
|
|
172
|
+
"tags": [
|
|
173
|
+
"pulls"
|
|
174
|
+
],
|
|
175
|
+
"responses": {
|
|
176
|
+
"200": {
|
|
177
|
+
"description": "list of review comments"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"post": {
|
|
182
|
+
"operationId": "pulls/create-review-comment",
|
|
183
|
+
"summary": "Create a diff-anchored review comment",
|
|
184
|
+
"tags": [
|
|
185
|
+
"pulls"
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"/repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies": {
|
|
190
|
+
"post": {
|
|
191
|
+
"operationId": "pulls/create-reply-for-review-comment",
|
|
192
|
+
"summary": "Create a reply for a review comment",
|
|
193
|
+
"tags": [
|
|
194
|
+
"pulls"
|
|
195
|
+
],
|
|
196
|
+
"responses": {
|
|
197
|
+
"201": {
|
|
198
|
+
"description": "reply created"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
"/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers": {
|
|
204
|
+
"post": {
|
|
205
|
+
"operationId": "pulls/request-reviewers",
|
|
206
|
+
"summary": "Request reviewers for a pull request",
|
|
207
|
+
"tags": [
|
|
208
|
+
"pulls"
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
"/repos/{owner}/{repo}/pulls/comments": {
|
|
213
|
+
"get": {
|
|
214
|
+
"operationId": "pulls/list-review-comments-for-repo",
|
|
215
|
+
"summary": "List review comments in a repository (repo-wide, across all pull requests)",
|
|
216
|
+
"tags": [
|
|
217
|
+
"pulls"
|
|
218
|
+
]
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
"/repos/{owner}/{repo}": {
|
|
222
|
+
"get": {
|
|
223
|
+
"operationId": "repos/get",
|
|
224
|
+
"summary": "Get a repository",
|
|
225
|
+
"tags": [
|
|
226
|
+
"repos"
|
|
227
|
+
]
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
"/repos/{owner}/{repo}/branches": {
|
|
231
|
+
"get": {
|
|
232
|
+
"operationId": "repos/list-branches",
|
|
233
|
+
"summary": "List branches",
|
|
234
|
+
"tags": [
|
|
235
|
+
"repos"
|
|
236
|
+
]
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
"/repos/{owner}/{repo}/contents/{path}": {
|
|
240
|
+
"get": {
|
|
241
|
+
"operationId": "repos/get-content",
|
|
242
|
+
"summary": "Get repository content",
|
|
243
|
+
"tags": [
|
|
244
|
+
"repos"
|
|
245
|
+
]
|
|
246
|
+
},
|
|
247
|
+
"put": {
|
|
248
|
+
"operationId": "repos/create-or-update-file-contents",
|
|
249
|
+
"summary": "Create or update file contents",
|
|
250
|
+
"tags": [
|
|
251
|
+
"repos"
|
|
252
|
+
]
|
|
253
|
+
},
|
|
254
|
+
"delete": {
|
|
255
|
+
"operationId": "repos/delete-file",
|
|
256
|
+
"summary": "Delete a file",
|
|
257
|
+
"tags": [
|
|
258
|
+
"repos"
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
"/repos/{owner}/{repo}/community/profile": {
|
|
263
|
+
"get": {
|
|
264
|
+
"operationId": "repos/get-community-profile-metrics",
|
|
265
|
+
"summary": "Get community profile metrics",
|
|
266
|
+
"tags": [
|
|
267
|
+
"repos"
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
"/repos/{owner}/{repo}/merge-upstream": {
|
|
272
|
+
"post": {
|
|
273
|
+
"operationId": "repos/merge-upstream",
|
|
274
|
+
"summary": "Sync a fork branch with the upstream repository",
|
|
275
|
+
"tags": [
|
|
276
|
+
"repos"
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
"/repos/{owner}/{repo}/vulnerability-alerts": {
|
|
281
|
+
"get": {
|
|
282
|
+
"operationId": "repos/check-vulnerability-alerts",
|
|
283
|
+
"summary": "Check if Dependabot vulnerability alerts are enabled",
|
|
284
|
+
"tags": [
|
|
285
|
+
"repos"
|
|
286
|
+
]
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
"/repos/{owner}/{repo}/git/refs": {
|
|
290
|
+
"post": {
|
|
291
|
+
"operationId": "git/create-ref",
|
|
292
|
+
"summary": "Create a reference",
|
|
293
|
+
"tags": [
|
|
294
|
+
"git"
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
"/repos/{owner}/{repo}/git/ref/{ref}": {
|
|
299
|
+
"get": {
|
|
300
|
+
"operationId": "git/get-ref",
|
|
301
|
+
"summary": "Get a reference",
|
|
302
|
+
"tags": [
|
|
303
|
+
"git"
|
|
304
|
+
]
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
"/repos/{owner}/{repo}/git/matching-refs/{ref}": {
|
|
308
|
+
"get": {
|
|
309
|
+
"operationId": "git/list-matching-refs",
|
|
310
|
+
"summary": "List matching references",
|
|
311
|
+
"tags": [
|
|
312
|
+
"git"
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
"/repos/{owner}/{repo}/commits/{commit_sha}/comments": {
|
|
317
|
+
"get": {
|
|
318
|
+
"operationId": "repos/list-commit-comments",
|
|
319
|
+
"summary": "List commit comments",
|
|
320
|
+
"tags": [
|
|
321
|
+
"repos"
|
|
322
|
+
]
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
"/repos/{owner}/{repo}/stats/contributors": {
|
|
326
|
+
"get": {
|
|
327
|
+
"operationId": "repos/get-contributors-stats",
|
|
328
|
+
"summary": "Get all contributor commit activity (async-computed statistics)",
|
|
329
|
+
"tags": [
|
|
330
|
+
"repos"
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
"/repos/{owner}/{repo}/stats/commit_activity": {
|
|
335
|
+
"get": {
|
|
336
|
+
"operationId": "repos/get-commit-activity-stats",
|
|
337
|
+
"summary": "Get the last year of commit activity (async-computed statistics)",
|
|
338
|
+
"tags": [
|
|
339
|
+
"repos"
|
|
340
|
+
]
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
"/repos/{owner}/{repo}/transfer": {
|
|
344
|
+
"post": {
|
|
345
|
+
"operationId": "repos/transfer",
|
|
346
|
+
"summary": "Transfer a repository to another owner",
|
|
347
|
+
"tags": [
|
|
348
|
+
"repos"
|
|
349
|
+
]
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
"/repos/{owner}/{repo}/automated-security-fixes": {
|
|
353
|
+
"delete": {
|
|
354
|
+
"operationId": "repos/disable-automated-security-fixes",
|
|
355
|
+
"summary": "Disable automated security fixes (Dependabot security updates toggle)",
|
|
356
|
+
"tags": [
|
|
357
|
+
"repos"
|
|
358
|
+
]
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# github-pull-schema.json — provenance
|
|
2
|
+
|
|
3
|
+
The **full** GitHub pull-request response schema (types, required, enums, nested
|
|
4
|
+
`base`/`head`/`repo`/`user`), used by the GitHub twin's spec-conformance gate
|
|
5
|
+
(`src/github-conformance.ts`, `src/github-conformance.test.ts`).
|
|
6
|
+
|
|
7
|
+
- **Source:** `https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/dereferenced/api.github.com.deref.json`
|
|
8
|
+
- **Repo:** `github/rest-api-description` (GitHub's published OpenAPI) — MIT licensed
|
|
9
|
+
- **Fetched:** 2026-06-14
|
|
10
|
+
- **Extraction:** the dereferenced spec inlines all `$ref`s into paths, so the PR
|
|
11
|
+
object is self-contained at
|
|
12
|
+
`paths["/repos/{owner}/{repo}/pulls/{pull_number}"].get.responses["200"].content["application/json"].schema`.
|
|
13
|
+
Vendored verbatim (no projection):
|
|
14
|
+
`jq '.paths["/repos/{owner}/{repo}/pulls/{pull_number}"].get.responses["200"].content["application/json"].schema'`
|
|
15
|
+
|
|
16
|
+
## Why the FULL schema, not a field-name list
|
|
17
|
+
|
|
18
|
+
This **replaces** the old `github-pull-fields.json`, which kept only
|
|
19
|
+
`Object.keys(properties)` — bare field NAMES. A name list can only catch
|
|
20
|
+
*fabrication* (a field GitHub doesn't have). It is structurally blind to:
|
|
21
|
+
- **types** — it could not see that `changed_files` is an `integer` (the twin once
|
|
22
|
+
emitted it as `null`/object and the gate stayed green);
|
|
23
|
+
- **omission** — a subset check never visits required fields the twin *fails* to
|
|
24
|
+
emit (the twin covered 10/48 fields; the old gate reported clean);
|
|
25
|
+
- **enums / required / nullability** — all discarded by the projection.
|
|
26
|
+
|
|
27
|
+
The full schema carries all of it, so the gate validates real types + required
|
|
28
|
+
fields + enums offline, with no token. Fields the **evidence** twin deliberately
|
|
29
|
+
does not model are declared in `github-known-deviations.json` (with reasons), so
|
|
30
|
+
"what we don't serve" is explicit rather than silently absent.
|
|
31
|
+
|
|
32
|
+
## Refresh
|
|
33
|
+
|
|
34
|
+
Re-fetch the dereferenced spec and re-extract the PR schema when GitHub ships
|
|
35
|
+
schema changes; then re-run `bun test src/github-conformance.test.ts`. A new
|
|
36
|
+
failure means either real GitHub drift (update this fixture) or twin drift (fix
|
|
37
|
+
the twin), and the violation report says which fields.
|