DashboardcraftSession 0ZdHwgWRLVf1

Session 0ZdHwgWRLVf1

Full ID: 0ZdHwgWRLVf122BpR
Messages: 40
Distillations: 7
Time range: 2026-09-08 01:31:03 — 2026-09-08 01:37:18

Conversation (40 messages)

Perform a strict READ-ONLY adversarial final audit of the uncommitted changes in /home/byk/Code/getsentry/publish-workspace-acceptance. Do not edit files, format, generate, or run any mutating command. Inspect git status/diff, every changed source/test/workflow/doc file, and relevant unchanged callers. Validate: (1) generated Peggy parser still preserves canonical full-path publish-title syntax; (2) strict release-revision parsing preserves body-start header binding, exact one global check-runs link, requested repo binding, lowercase 40-hex SHA, CRLF, and update-only-canonical behavior; (3) docs grammar comes from parser source and cannot drift; (4) scripts serialize objects for GitHub Action fromJSON consumers and empty/missing JSON handoffs fail contextually rather than raw JSON errors; (5) workflow maintains CI-approved exact-SHA checkout before workspace discovery, root-config absence path fallback, root-config discovery fail-closed, getsentry/craft:latest intentional requirement, correct docker bind/workdir, state/publish ordering; (6) ci-poller checkout upgrade only to v7 and workflow_dispatch retained; (7) test coverage is adequate and no stale assumptions remain; (8) diff hygiene/no unrelated changes. Cite exact file:line findings. End with exactly MERGE or DO-NOT-MERGE. If no findings, explicitly state no findings before the verdict.

gateway · 2026-09-08 01:31:03

I will inspect the exact uncommitted diff and its callers without changing the worktree, then report only evidence-based findings.

gpt-5.6-terra · 2026-09-08 01:31:03 · ~24 tokens
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance</path>
<type>directory</type>
<entries>
.eslintrc.js
.git
.github/
.gitignore
AGENTS.md
auto-approve-repos.txt
docs/
LICENSE
node_modules/
package.json
README.md
scripts/
src/
vitest.config.js
yarn.lock

(15 entries)
</entries>
gateway · 2026-09-08 01:31:43
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/AGENTS.md</path>
<type>file</type>
<content>
1: # AGENTS.md - Coding Agent Guidelines
2: 
3: This document provides guidelines for AI coding agents working in this repository.
4: 
5: ## Project Overview
6: 
7: This is the **Sentry Publish Repository** - a GitHub Actions-based approval system for publishing releases across multiple Sentry projects using [Craft](https://github.com/getsentry/craft). It's a pure JavaScript (Node.js 24.0.0) project using CommonJS modules.
8: 
9: ## Build/Lint/Test Commands
10: 
11: ### Package Manager
12: 
13: - **Yarn 1.22.22** (classic) - Do NOT use npm
14: - Version management via Volta (pinned in package.json)
15: 
16: ### Commands
17: 
18: ```bash
19: # Install dependencies
20: yarn install
21: 
22: # Run all tests
23: yarn test
24: 
25: # Run tests in watch mode
26: yarn test:watch
27: 
28: # Run a single test file
29: yarn test src/modules/__tests__/update-issue.js
30: 
31: # Run tests ...
gateway · 2026-09-08 01:31:47
result
 M .github/workflows/ci-poller.yml
 M .github/workflows/publish.yml
 M docs/publish-issue-format.md
 M scripts/generate-publish-issue-title-parser.js
 M src/modules/__tests__/publish-workflow.js
 M src/modules/publish-issue-title.js
 M src/modules/publish-issue-title.peggy
 M src/modules/release-revision.js
 M src/publish/inputs.js
 M src/publish/resolve-location.js
 M src/publish/resolve-release-revision.js
?? src/publish/__tests__/
?? src/publish/discover-location.js
 .github/workflows/ci-poller.yml                |   2 +-
 .github/workflows/publish.yml                  |  12 +-
 docs/publish-issue-format.md                   |  43 +-
 scripts/generate-publish-issue-title-parser.js |  36 ++
 src/modules/__tests__/publish-workflow.js      |   6 +-
 src/modules/publish-issue-title.js             | 720 ++++++++++++++++++++++++-
 src/modules/publish-issue-title.peggy          |  53 ++
 src/modules/release-revision.js                |  34 +-
 src/publish/inputs.js                         ...
gateway · 2026-09-08 01:31:54
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/__tests__</path>
<type>directory</type>
<entries>
discover-location.js
resolve-location.js
resolve-release-revision.js

(3 entries)
</entries>
gateway · 2026-09-08 01:31:59
result
Found 26 matches
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/__tests__/resolve-release-revision.js:
  Line 4: const script = new URL("../resolve-release-revision.js", import.meta.url).pathname;


/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/resolve-release-revision.js:
  Line 2: const { getReleaseRevision } = require("../modules/release-revision");

  Line 12:     getReleaseRevision({


/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/ci-poller-input.js:
  Line 3:   getReleaseRevision,

  Line 4:   updateReleaseRevision,

  Line 5: } = require("./release-revision");

  Line 30:   const currentRevision = getReleaseRevision({ issueBody, repo });

  Line 34:       ? { issueBody: updateReleaseRevision({ issueBody, repo, revision }) }


/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/release-revision.js:
  Line 3: function getReleaseRevisionDetails({ issueBody, repo }) {

  Line 30: function getReleaseRevision({ ...
gateway · 2026-09-08 01:32:03
result
Found 49 matches
/home/byk/Code/getsentry/publish-workspace-acceptance/scripts/generate-publish-issue-title-parser.js:
  Line 11:   "publish-issue-title.peggy"

  Line 18:   "publish-issue-title.js"

  Line 24:   "publish-issue-format.md"

  Line 34:   grammarSource: "publish-issue-title.peggy",


/home/byk/Code/getsentry/publish-workspace-acceptance/package.json:
  Line 18:     "generate": "node scripts/generate-publish-issue-title-parser.js",

  Line 19:     "check:generated": "node scripts/generate-publish-issue-title-parser.js --check",


/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/discover-location.js:
  Line 7: const { resolvePublishLocation } = require("../modules/publish-location");

  Line 46:   return resolvePublishLocation({


/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/__tests__/discover-location.js:
  Line 3: const { discoverLocation, getWorkspaceNames } = ...
gateway · 2026-09-08 01:32:07
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-title.peggy</path>
<type>file</type>
<content>
1: {
2:   function join(characters) {
3:     return characters.join("");
4:   }
5: }
6: 
7: // BEGIN TITLE GRAMMAR
8: // Canonical grammar for publish issue titles. A path suffix is syntactic only:
9: // the controller resolves the complete suffix as a workspace after checking
10: // out the CI-approved revision.
11: PublishIssueTitle
12:   = "publish: " "getsentry/"? repo:Repository path:Path? "@" version:Version !. {
13:       return {
14:         repo,
15:         path: path || "",
16:         version,
17:       };
18:     }
19: 
20: Repository
21:   = characters:RepositoryCharacter+ { return join(characters); }
22: 
23: RepositoryCharacter
24:   = [A-Za-z0-9_.-]
25: 
26: Path
27:   = segments:("/" segment:PathSegment { return `/${segment}`; })+ { return join(segments); }
28: 
29: PathSegment
30:   = characters:RepositoryCharacter+ { return ...
gateway · 2026-09-08 01:32:10
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/release-revision.js</path>
<type>file</type>
<content>
1: const { parse } = require("./publish-issue-title");
2: 
3: function getReleaseRevisionDetails({ issueBody, repo }) {
4:   if (
5:     parse(issueBody, { startRule: "CheckRunsLinkCount" }) !== 1
6:   ) {
7:     throw new Error(
8:       `Expected exactly one View check runs link in Quick links for getsentry/${repo}.`
9:     );
10:   }
11: 
12:   let details;
13:   try {
14:     details = parse(issueBody, { startRule: "ReleaseRevision" });
15:   } catch {
16:     throw new Error(
17:       `Expected a View check runs link for getsentry/${repo} in the publish issue body.`
18:     );
19:   }
20: 
21:   if (details.repo !== repo) {
22:     throw new Error(
23:       `Expected a View check runs link for getsentry/${repo} in the publish issue body.`
24:     );
25:   }
26: 
27:   return details;
28: }
29: 
30: function getReleaseRevision({ issueBody, repo }) {
31:  ...
gateway · 2026-09-08 01:32:14
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/discover-location.js</path>
<type>file</type>
<content>
1: const { execFileSync } = require("child_process");
2: const { existsSync } = require("fs");
3: const path = require("path");
4: 
5: const core = require("@actions/core");
6: 
7: const { resolvePublishLocation } = require("../modules/publish-location");
8: 
9: function getWorkspaceNames({
10:   repositoryDirectory,
11:   exists = existsSync,
12:   execFile = execFileSync,
13: }) {
14:   if (!exists(path.join(repositoryDirectory, ".craft.yml"))) {
15:     return [];
16:   }
17: 
18:   const output = execFile(
19:     "docker",
20:     [
21:       "run",
22:       "--rm",
23:       "--volume",
24:       `${path.resolve(repositoryDirectory)}:/github/workspace/__repo__`,
25:       "--workdir",
26:       "/github/workspace/__repo__",
27:       "getsentry/craft:latest",
28:       "workspace",
29:       "list",
30:     ],
31:     { encoding: "utf8" }
32:   );
33:  ...
gateway · 2026-09-08 01:32:18
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/__tests__/discover-location.js</path>
<type>file</type>
<content>
1: import { afterEach, expect, test, vi } from "vitest";
2: 
3: const { discoverLocation, getWorkspaceNames } = require("../discover-location.js");
4: 
5: afterEach(() => {
6:   vi.restoreAllMocks();
7: });
8: 
9: test("retains checkout-path behavior when the root config is absent", () => {
10:   expect(
11:     discoverLocation({
12:       input: { path: "./packages/cli" },
13:       repositoryDirectory: "__repo__",
14:       exists: () => false,
15:     })
16:   ).toEqual({ path: "./packages/cli" });
17: });
18: 
19: test("discovers exact workspace paths using the released Craft image", () => {
20:   const execFile = vi.fn(() => '["packages/CLI"]');
21: 
22:   expect(
23:     discoverLocation({
24:       input: { path: "./packages/CLI" },
25:       repositoryDirectory: "__repo__",
26:       exists: () => true,
27:       execFile,
28:     })
29:   ...
gateway · 2026-09-08 01:32:21
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/__tests__/resolve-location.js</path>
<type>file</type>
<content>
1: import { spawnSync } from "child_process";
2: import { expect, test } from "vitest";
3: 
4: const script = new URL("../resolve-location.js", import.meta.url).pathname;
5: 
6: test("rejects missing workflow input through location validation", () => {
7:   const result = spawnSync(process.execPath, [script], {
8:     encoding: "utf8",
9:     env: {
10:       ...process.env,
11:       PUBLISH_ARGS: "",
12:       CRAFT_WORKSPACE_NAMES: "[]",
13:     },
14:   });
15: 
16:   expect(result.status).not.toBe(0);
17:   expect(result.stderr).toContain("Invalid publish path.");
18:   expect(result.stderr).not.toContain("Unexpected end of JSON input");
19: });

(End of file - total 19 lines)
</content>
gateway · 2026-09-08 01:32:25
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/__tests__/resolve-release-revision.js</path>
<type>file</type>
<content>
1: import { spawnSync } from "child_process";
2: import { expect, test } from "vitest";
3: 
4: const script = new URL("../resolve-release-revision.js", import.meta.url).pathname;
5: 
6: test("rejects missing workflow input through release revision validation", () => {
7:   const result = spawnSync(process.execPath, [script], {
8:     encoding: "utf8",
9:     env: {
10:       ...process.env,
11:       PUBLISH_ARGS: "",
12:       PUBLISH_ISSUE_BODY: "",
13:     },
14:   });
15: 
16:   expect(result.status).not.toBe(0);
17:   expect(result.stderr).toContain("Publish input must define a repository.");
18:   expect(result.stderr).not.toContain("Unexpected end of JSON input");
19: });

(End of file - total 19 lines)
</content>
gateway · 2026-09-08 01:32:28
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/publish.yml</path>
<type>file</type>
<content>
1: name: Publish
2: on:
3:   issues:
4:     types: [labeled]
5: 
6: concurrency:
7:   # Use the issue title (e.g. "publish: getsentry/foo@1.2.3") so duplicate
8:   # issues for the same repo@version share a concurrency group.
9:   group: ${{ github.event.issue.title }}
10:   cancel-in-progress: false
11: 
12: permissions:
13:   contents: read
14:   issues: write
15:   packages: write
16: 
17: jobs:
18:   # When accepted is added to a publish issue:
19:   #   - Add ci-pending (and remove ci-failed if retrying)
20:   #   - Enable the poller via CI_POLLER_HAS_PENDING=true
21:   #   - Comment on the issue
22:   #   - Trigger the poller immediately so we don't wait for the next cron tick
23:   # The publish job below requires ci-ready, so it will not fire until the
24:   # poller flips ci-pending → ci-ready (which also prevents publishing without
25:   # CI ...
gateway · 2026-09-08 01:32:44
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/release-revision.js</path>
<type>file</type>
<content>
1: import { expect, test } from "vitest";
2: 
3: const {
4:   getReleaseRevision,
5:   updateReleaseRevision,
6: } = require("../release-revision.js");
7: 
8: const REVISION = "7e5ca7ed5581552de066e2a8bc295b8306be38ac";
9: 
10: function requestBody(quickLinks) {
11:   return `Requested by: @byk
12: 
13: Merge target: (default)
14: 
15: Quick links:
16: ${quickLinks}`;
17: }
18: 
19: function canonicalQuickLinks(revision = REVISION) {
20:   return `- [View changes](https://github.com/getsentry/toolkit/compare/1.2.2...release/1.2.3)
21: - [View check runs](https://github.com/getsentry/toolkit/commit/${revision}/checks/)`;
22: }
23: 
24: test("gets the CI-approved revision from the request header", () => {
25:   expect(
26:     getReleaseRevision({
27:       repo: "toolkit",
28:       issueBody: requestBody(canonicalQuickLinks()),
29:     })
30:   ...
gateway · 2026-09-08 01:33:03
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/ci-poller-input.js</path>
<type>file</type>
<content>
1: const { parse: parsePublishIssueTitle } = require("./publish-issue-title");
2: const {
3:   getReleaseRevision,
4:   updateReleaseRevision,
5: } = require("./release-revision");
6: const {
7:   isPublishRepository,
8:   isReleaseVersion,
9: } = require("./publish-issue-validation");
10: const { isPublishPath } = require("./publish-location");
11: 
12: function getCiPollerInput({ title, issueBody, revision }) {
13:   let parsedTitle;
14:   try {
15:     parsedTitle = parsePublishIssueTitle(title);
16:   } catch {
17:     throw new Error(`Invalid publish issue title: '${title}'`);
18:   }
19:   const { repo, version } = parsedTitle;
20:   if (!isPublishRepository(repo)) {
21:     throw new Error(`Invalid publish issue repository: '${repo}'`);
22:   }
23:   if (!isReleaseVersion(version)) {
24:     throw new Error(`Invalid publish issue version: ...
gateway · 2026-09-08 01:33:07
result
Found 11 matches
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/resolve-ci-poller-input.js:
  Line 1: const { getCiPollerInput } = require("../modules/ci-poller-input");

  Line 5:     getCiPollerInput({


/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/ci-poller-input.js:
  Line 12: function getCiPollerInput({ title, issueBody, revision }) {

  Line 42: module.exports = { getCiPollerInput };


/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/ci-poller-input.js:
  Line 6: const { getCiPollerInput } = require("../ci-poller-input.js");

  Line 19:     getCiPollerInput({

  Line 30:     getCiPollerInput({

  Line 59:       getCiPollerInput({

  Line 71:       getCiPollerInput({

  Line 82:     expect(() => getCiPollerInput({ issueBody, title })).toThrow(

  Line 94:   expect(() => getCiPollerInput({ issueBody, title })).toThrow(
gateway · 2026-09-08 01:33:11
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/resolve-ci-poller-input.js</path>
<type>file</type>
<content>
1: const { getCiPollerInput } = require("../modules/ci-poller-input");
2: 
3: process.stdout.write(
4:   JSON.stringify(
5:     getCiPollerInput({
6:       issueBody: process.env.PUBLISH_ISSUE_BODY || "",
7:       title: process.env.PUBLISH_TITLE || "",
8:       revision: process.env.PUBLISH_REVISION || "",
9:     })
10:   )
11: );

(End of file - total 11 lines)
</content>
gateway · 2026-09-08 01:33:15
result
Found 5 matches
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/resolve-ci-poller-input.js:
  Line 8:       revision: process.env.PUBLISH_REVISION || "",


/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/ci-poller-input.js:
  Line 50:     "node .__publish__/src/publish/resolve-ci-poller-input.js"


/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/ci-poller.yml:
  Line 101:               node .__publish__/src/publish/resolve-ci-poller-input.js); then

  Line 145:               updated_body=$(PUBLISH_ISSUE_BODY="$body" PUBLISH_REVISION="$sha" PUBLISH_TITLE="$title" \

  Line 146:                 node .__publish__/src/publish/resolve-ci-poller-input.js | jq -r '.issueBody')
gateway · 2026-09-08 01:33:19
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/ci-poller.yml</path>
<type>file</type>
<content>
1: name: CI Status Poller
2: 
3: on:
4:   schedule:
5:     - cron: "*/5 * * * *"
6:   workflow_dispatch:
7:     inputs:
8:       attempt:
9:         description: Self-dispatch attempt counter (internal use)
10:         required: false
11:         default: "0"
12: 
13: permissions:
14:   contents: read
15:   issues: read
16: 
17: jobs:
18:   check-ci:
19:     runs-on: ubuntu-latest
20:     environment: production
21:     # Skip entirely (no runner provisioned) when there's nothing to check.
22:     # Set to "true" by ci-pending.yml, reset to "false" here when done.
23:     # Always allow workflow_dispatch for manual recovery.
24:     if: vars.CI_POLLER_HAS_PENDING == 'true' || github.event_name == 'workflow_dispatch'
25:     concurrency:
26:       group: ci-status-poller
27:       cancel-in-progress: false
28:     steps:
29:       # sentry-internal-app token ...
gateway · 2026-09-08 01:33:23
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/inputs.js</path>
<type>file</type>
<content>
1: const github = require('@actions/github');
2: const core = require('@actions/core');
3: const { detailsFromContext } = require('../modules/details-from-context');
4: 
5: async function inputs() {
6:     const result = await detailsFromContext({
7:       context: github.context,
8:     });
9:     core.setOutput('result', JSON.stringify(result));
10: }
11: 
12: 
13: inputs();

(End of file - total 13 lines)
</content>
gateway · 2026-09-08 01:33:31
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/scripts/generate-publish-issue-title-parser.js</path>
<type>file</type>
<content>
1: const fs = require("fs");
2: const path = require("path");
3: const peggy = require("peggy");
4: const prettier = require("prettier");
5: 
6: const grammarPath = path.join(
7:   __dirname,
8:   "..",
9:   "src",
10:   "modules",
11:   "publish-issue-title.peggy"
12: );
13: const outputPath = path.join(
14:   __dirname,
15:   "..",
16:   "src",
17:   "modules",
18:   "publish-issue-title.js"
19: );
20: const documentationPath = path.join(
21:   __dirname,
22:   "..",
23:   "docs",
24:   "publish-issue-format.md"
25: );
26: const grammar = fs.readFileSync(grammarPath, "utf8");
27: const parser = peggy.generate(grammar, {
28:   allowedStartRules: [
29:     "PublishIssueTitle",
30:     "ReleaseRevision",
31:     "CheckRunsLinkCount",
32:   ],
33:   format: "commonjs",
34:   grammarSource: "publish-issue-title.peggy",
35:   output: "source",
36: ...
gateway · 2026-09-08 01:33:44
result
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/__tests__/discover-location.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/__tests__/resolve-release-revision.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/__tests__/resolve-location.js
gateway · 2026-09-08 01:33:49
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-workflow.js</path>
<type>file</type>
<content>
1: import { spawnSync } from "child_process";
2: import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
3: import { tmpdir } from "os";
4: import { join } from "path";
5: 
6: import { afterEach, expect, test } from "vitest";
7: 
8: const { resolvePublishLocation } = require("../publish-location.js");
9: 
10: const temporaryDirectories = [];
11: 
12: function getWorkflow() {
13:   return readFileSync(
14:     join(__dirname, "../../../.github/workflows/publish.yml"),
15:     "utf8"
16:   );
17: }
18: 
19: function getSetTargetsScript() {
20:   const workflow = getWorkflow();
21:   const section = workflow.match(
22:     / {6}- name: Set targets[\s\S]*? {8}run: \|\n(?<script>[\s\S]*?)\n {6}- uses: docker:\/\/getsentry\/craft:latest/
23:   );
24:   if (!section?.groups?.script) {
25:     throw new Error("Missing Set targets workflow ...
gateway · 2026-09-08 01:33:53
result
Found 7 matches
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/ci-poller-input.js:
  Line 17: test("parses root and full-path publish titles", () => {

  Line 83:       "Invalid publish issue title"


/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-location.js:
  Line 8:       path: "./packages/CLI",

  Line 9:       workspaceNames: ["packages/cli", "packages/CLI"],

  Line 11:   ).toStrictEqual({ path: ".", workspace: "packages/CLI" });


/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/details-from-context.js:
  Line 140:   await expect(fn).rejects.toThrow("Invalid publish issue title");

  Line 228:   ).rejects.toThrow("Invalid publish issue title");
gateway · 2026-09-08 01:33:57
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/ci-poller-input.js</path>
<type>file</type>
<content>
1: import { readFileSync } from "fs";
2: import { join } from "path";
3: 
4: import { expect, test } from "vitest";
5: 
6: const { getCiPollerInput } = require("../ci-poller-input.js");
7: 
8: const REVISION = "7e5ca7ed5581552de066e2a8bc295b8306be38ac";
9: const issueBody = `Requested by: @byk
10: 
11: Merge target: (default)
12: 
13: Quick links:
14: - [View changes](https://github.com/getsentry/toolkit/compare/1.2.2...release/1.2.3)
15: - [View check runs](https://github.com/getsentry/toolkit/commit/${REVISION}/checks/)`;
16: 
17: test("parses root and full-path publish titles", () => {
18:   expect(
19:     getCiPollerInput({
20:       issueBody,
21:       title: "publish: getsentry/toolkit/cli@1.2.3",
22:     })
23:   ).toEqual({
24:     repo: "getsentry/toolkit",
25:     revision: REVISION,
26:     version: "1.2.3",
27:   });
28: 
29:   ...
gateway · 2026-09-08 01:34:06
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-location.js</path>
<type>file</type>
<content>
1: function resolvePublishLocation({ path, workspaceNames }) {
2:   if (!isPublishPath(path)) {
3:     throw new Error("Invalid publish path.");
4:   }
5: 
6:   if (!workspaceNames.every(isWorkspaceName)) {
7:     throw new Error(
8:       "Craft workspace discovery returned an invalid workspace list."
9:     );
10:   }
11: 
12:   if (path === ".") {
13:     return { path };
14:   }
15: 
16:   const workspace = path.slice(2);
17:   if (workspaceNames.includes(workspace)) {
18:     return { path: ".", workspace };
19:   }
20: 
21:   return { path };
22: }
23: 
24: function isPublishPath(path) {
25:   return (
26:     typeof path === "string" &&
27:     (path === "." ||
28:       (path.startsWith("./") &&
29:         path
30:           .slice(2)
31:           .split("/")
32:           .every(isSafeWorkspaceSegment)))
33:   );
34: }
35: 
36: function ...
gateway · 2026-09-08 01:34:23
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/docs/publish-issue-format.md</path>
<type>file</type>
<content>
1: # Publish Issue Format
2: 
3: The Publish workflow treats a publish issue as a release request. The title identifies
4: the release; the body supplies the merge target and selected targets. Do not edit the
5: title by hand unless it remains valid under this format.
6: 
7: ## Title
8: 
9: Every title starts with `publish: `. The following canonical Peggy grammar is
10: generated from `src/modules/publish-issue-title.peggy`:
11: 
12: <!-- BEGIN GENERATED TITLE GRAMMAR -->
13: ```peggy
14: // Canonical grammar for publish issue titles. A path suffix is syntactic only:
15: // the controller resolves the complete suffix as a workspace after checking
16: // out the CI-approved revision.
17: PublishIssueTitle
18:   = "publish: " "getsentry/"? repo:Repository path:Path? "@" version:Version !. ...
gateway · 2026-09-08 01:34:28
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/details-from-context.js</path>
<type>file</type>
<content>
1: const { parse: parsePublishIssueTitle } = require("./publish-issue-title");
2: const { isPublishPath } = require("./publish-location");
3: const {
4:   isPublishRepository,
5:   isReleaseVersion,
6: } = require("./publish-issue-validation");
7: 
8: /**
9:  * Matches the entire "Targets" section of a github publish issue body.
10:  */
11: const TARGETS_SECTION_PARSER_REGEX =
12:   /^(?!### Targets$\s)(?: *- \[[ xX]\] \S+\s*$(?:\r?\n)?)+/m;
13: 
14: /**
15:  * Matches all targets of a github publish issue body in a section that was already matched and extracted with `TARGETS_PARSER_REGEX`.
16:  * The "id" of the targets is captured within a capture group. ...
gateway · 2026-09-08 01:34:36
result
Found 59 matches
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/release-revision.js:
  Line 8:       `Expected exactly one View check runs link in Quick links for getsentry/${repo}.`

  Line 17:       `Expected a View check runs link for getsentry/${repo} in the publish issue body.`

  Line 23:       `Expected a View check runs link for getsentry/${repo} in the publish issue body.`


/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-title.js:
  Line 208:   const peg$c4 = "Requested by: @";

  Line 209:   const peg$c5 = "Merge target: ";

  Line 210:   const peg$c6 = "Quick links:";

  Line 213:   const peg$c9 = "- [View check runs](https://github.com/getsentry/";

  Line 243:   const peg$e7 = peg$literalExpectation("Requested by: @", false);

  Line 244:   const peg$e8 = peg$literalExpectation("Merge target: ", false);

  Line 245:   const peg$e9 = peg$literalExpectation("Quick links:", false);

  Line 249:     "- [View check ...
gateway · 2026-09-08 01:34:42
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/package.json</path>
<type>file</type>
<content>
1: {
2:   "name": "publish",
3:   "private": true,
4:   "version": "0.0.1",
5:   "description": "Approval-based publishing system for Sentry",
6:   "main": "index.js",
7:   "repository": "git@github.com:getsentry/publish.git",
8:   "author": "Sentry Open Source <oss@sentry.io>",
9:   "license": "Apache-2.0",
10:   "volta": {
11:     "node": "24.0.0",
12:     "yarn": "1.22.22"
13:   },
14:   "resolutions": {
15:     "undici": "^6.23.0"
16:   },
17:   "scripts": {
18:     "generate": "node scripts/generate-publish-issue-title-parser.js",
19:     "check:generated": "node scripts/generate-publish-issue-title-parser.js --check",
20:     "test": "yarn check:generated && vitest run",
21:     "test:watch": "vitest",
22:     "lint": "eslint src .github --ignore-pattern '!.github'",
23:     "prettier": "prettier --write src"
24:   },
25:   "devDependencies": {
26:     "eslint": ...
gateway · 2026-09-08 01:35:03

I have mapped the changed workflow, parser source, generated output, scripts, documentation, and the new regression tests. I am now verifying generated-artifact consistency and the critical parser paths without writing files.

gpt-5.6-terra · 2026-09-08 01:35:03 · ~40 tokens
result
yarn run v1.22.22
$ node scripts/generate-publish-issue-title-parser.js --check
Done in 0.52s.
Generated parser and LF/CRLF canonical-path checks passed.
gateway · 2026-09-08 01:35:30
result
{"bareAccepted":"7e5ca7ed5581552de066e2a8bc295b8306be38ac","noTrailingChecksAccepted":"Expected a View check runs link for getsentry/toolkit in the publish issue body."}
gateway · 2026-09-08 01:35:38
result
{"revision":"7e5ca7ed5581552de066e2a8bc295b8306be38ac","viewCheckRunsLinks":2}
gateway · 2026-09-08 01:35:50
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-title.js</path>
<type>file</type>
<content>
1: /* eslint-disable */
2: // @generated by Peggy 5.1.0.
3: //
4: // https://peggyjs.org/
5: 
6: "use strict";
7: 
8: class peg$SyntaxError extends SyntaxError {
9:   constructor(message, expected, found, location) {
10:     super(message);
11:     this.expected = expected;
12:     this.found = found;
13:     this.location = location;
14:     this.name = "SyntaxError";
15:   }
16: 
17:   format(sources) {
18:     let str = "Error: " + this.message;
19:     if (this.location) {
20:       let src = null;
21:       const st = sources.find((s) => s.source === this.location.source);
22:       if (st) {
23:         src = st.text.split(/\r\n|\n|\r/g);
24:       }
25:       const s = this.location.start;
26:       const offset_s =
27:         this.location.source &&
28:         typeof this.location.source.offset === "function"
29:           ? ...
gateway · 2026-09-08 01:36:13
result
 M .github/workflows/ci-poller.yml
 M .github/workflows/publish.yml
 M docs/publish-issue-format.md
 M scripts/generate-publish-issue-title-parser.js
 M src/modules/__tests__/publish-workflow.js
 M src/modules/publish-issue-title.js
 M src/modules/publish-issue-title.peggy
 M src/modules/release-revision.js
 M src/publish/inputs.js
 M src/publish/resolve-location.js
 M src/publish/resolve-release-revision.js
?? src/publish/__tests__/
?? src/publish/discover-location.js
.github/workflows/ci-poller.yml
.github/workflows/publish.yml
docs/publish-issue-format.md
scripts/generate-publish-issue-title-parser.js
src/modules/__tests__/publish-workflow.js
src/modules/publish-issue-title.js
src/modules/publish-issue-title.peggy
src/modules/release-revision.js
src/publish/inputs.js
src/publish/resolve-location.js
src/publish/resolve-release-revision.js
gateway · 2026-09-08 01:36:53
result
Unexpected end of JSON input
gateway · 2026-09-08 01:37:18

Findings:

  1. MUST-FIX: "/checks/"? makes the entire checks suffix optional. The parser accepts a bare commit URL and rejects /checks without a trailing slash. This regresses the prior /checks/? contract.
    src/modules/publish-issue-title.peggy:46
    src/modules/publish-issue-title.js:911-924
    Tests cover only /checks/: src/modules/__tests__/release-revision.js:19-22.

  2. MUST-FIX: The “global” link count only recognizes lines whose content starts with - [View check runs](. A second inline or blockquoted check-runs link bypasses the count; a body with two such links was accepted and returned the header SHA.
    src/modules/publish-issue-title.peggy:58-61
    src/modules/publish-issue-title.js:304-307
    src/modules/release-revision.js:3-10
    Existing decoy coverage only tests a line-start duplicate: src/modules/__tests__/release-revision.js:56-71.

  3. MUST-FIX: Documentation-generation validation permits the generated block to be removed entirely. replace() leaves markerless documentation unchanged, then the equality branch skips the marker-presence check. check:generated would pass while the docs no longer contain the canonical grammar.
    scripts/generate-publish-issue-title-parser.js:50-59

  4. MAJOR: Empty Craft workspace output throws raw Unexpected end of JSON input, not the required contextual discovery error. The invalid-list test only covers {}.
    src/publish/discover-location.js:33-36
    src/publish/__tests__/discover-location.js:37-47

  5. MAJOR: Documentation says Merge target is optional, but the canonical release-revision parser requires a non-empty Merge target: line. An issue allowed by the documentation fails later during revision resolution.
    docs/publish-issue-format.md:93-94
    src/modules/publish-issue-title.peggy:42-46
    src/modules/details-from-context.js:54-59

Verified: generated-artifact check passes; canonical full-path parsing and LF/CRLF ...

gpt-5.6-terra · 2026-09-08 01:37:18 · ~542 tokens

Distillations (7)

Gen 0 2026-09-08 01:39:08 · 830 tokens

Date: Sep 8, 2026 * 🟡 (01:36) Working-tree status showed modified files: `.github/workflows/ci-poller.yml`, `.github/workflows/publish.yml`, `docs/publish-issue-format.md`, `scripts/generate-publish-issue-title-parser.js`, `src/modules/__tests__/publish-workflow.js`, `src/modules/publish-issue-title.js`, `src/modules/publish-issue-title.peggy`, `src/modules/release-revision.js`, `src/publish/inp…

Gen 0 2026-09-08 01:37:40 · 862 tokens

Date: Sep 8, 2026 * 🟡 (01:34) `src/modules/details-from-context.js` parses a publish issue title with `parsePublishIssueTitle()`, validates `repo` via `isPublishRepository()`, `version` via `isReleaseVersion()`, and `path` as `"." + titleDetails.path` via `isPublishPath()`. It throws `Issue context is not defined`, `Invalid publish issue title: '${context.payload.issue.title}'`, `Invalid publish…

Gen 0 2026-09-08 01:37:00 · 2558 tokens

Date: Sep 8, 2026 * 🟡 (01:33) `src/modules/__tests__/release-revision.js` defines `REVISION = "7e5ca7ed5581552de066e2a8bc295b8306be38ac"` and helpers `requestBody(quickLinks)` and `canonicalQuickLinks(revision = REVISION)`, whose canonical links are `https://github.com/getsentry/toolkit/compare/1.2.2...release/1.2.3` and `https://github.com/getsentry/toolkit/commit/${revision}/checks/`. * 🟡 (01…

Gen 0 2026-09-08 01:35:37 · 624 tokens

Date: Sep 8, 2026 * 🟡 (01:32) `src/publish/__tests__/resolve-location.js` imports `spawnSync` from `"child_process"` and `expect`, `test` from `"vitest"`; `script` is `new URL("../resolve-location.js", import.meta.url).pathname`. * 🟡 (01:32) `src/publish/__tests__/resolve-location.js` test `"rejects missing workflow input through location validation"` runs `spawnSync(process.execPath, [script],…

Gen 0 2026-09-08 01:33:41 · 392 tokens

Date: Sep 8, 2026 * 🟡 (01:32) `src/publish/__tests__/discover-location.js` imports `afterEach`, `expect`, `test`, and `vi` from `"vitest"` and requires `{ discoverLocation, getWorkspaceNames }` from `"../discover-location.js"`; `afterEach()` calls `vi.restoreAllMocks()`. * 🟡 (01:32) `src/publish/__tests__/discover-location.js` test `"retains checkout-path behavior when the root config is absent…

Gen 0 2026-09-08 01:33:32 · 1698 tokens

Date: Sep 8, 2026 * 🔴 (01:31) User asserted error-handling convention: always throw for unexpected values, including a `default` branch in switch statements that throws descriptive errors such as `Unknown status: '${status}'`. * 🔴 (01:31) User asserted that new Craft requests always include the checkout repository identity; workspace releases use their full concrete path as the publish-title su…

Gen 0 2026-09-08 01:32:33 · 530 tokens

Date: Sep 8, 2026 * 🔴 [requested-read-only-audit] (01:31) User requested a strict READ-ONLY adversarial final audit of uncommitted changes in `/home/byk/Code/getsentry/publish-workspace-acceptance`; instructed not to edit files, format, generate, or run any mutating command. * 🔴 [requested-git-diff-review] (01:31) User required inspection of `git status`/diff, every changed source/test/workflow…