DashboardcraftSession 0052pO1BGKrk

Session 0052pO1BGKrk

Full ID: 0052pO1BGKrkditf3
Messages: 59
Distillations: 4
Time range: 2026-09-04 20:08:04 — 2026-09-04 20:22:20

Conversation (59 messages)

Perform a strict final READ-ONLY adversarial audit of the complete CURRENT uncommitted diff and relevant source in BOTH worktrees. Do not edit files, format, generate, run mutating commands, or change git state.

Worktrees:

  • /home/byk/Code/getsentry/craft-workspace-action-propagation
  • /home/byk/Code/getsentry/publish-workspace-acceptance

IMPORTANT CONTRACT: getsentry/craft:latest in Publish is intentional and REQUIRED. It must remain floating so the controller always uses the latest released Craft workspace behavior; the CI-approved revision passed to checkout and craft publish --rev binds all repository operations. Do not report latest as a concern or recommend pinning it.

Audit these invariants with exact current file:line citations:

  1. CI poller validates repository, Craft-compatible version, and canonical title path before getReleaseRevision or any API-oriented work; root allowed; traversal/dot/prototype/option-like segments rejected.
  2. Craft getPublishStateFilename and Publish workflow’s Set targets use identical, lossless state-version encoding. Safe lowercase existing names remain unchanged; altered valid versions encode raw bytes base64url; case/punctuation variants cannot collide.
  3. Craft safe brace workspace globs such as packages/{cli,mcp} expand. Unsafe brace alternatives (relative traversal, absolute path, malformed syntax) fail before globSync. Verify safe character/negated classes, globstar, concrete literals, POSIX / paths, overlap failure, and physical symlink containment. Ensure schema/runtime checks are equivalent or safely layered.
  4. Action validates untrusted path/workspace before all side effects, clears ambient CRAFT_WORKSPACE, preserves full exact workspace titles and mutual exclusion.
  5. Publish checks out CI-approved SHA before discovery, does exact case-sensitive full-path matching, defaults missing root .craft.yml to checkout-path behavior, validates discovery output, gates only on fresh accepted ci-ready, ...
gateway · 2026-09-04 20:08:04
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation</path>
<type>directory</type>
<entries>
.craft.yml
.dockerignore
.eslintcache
.git
.github/
.gitignore
.lore.md
.nojekyll
.npmignore
.prettierignore
.prettierrc.yml
.tsbuildinfo
.vscode/
action.yml
AGENTS.md
blog-post-draft.md
build.mjs
CHANGELOG.md
CONTRIBUTING.md
dist/
Dockerfile
docs/
eslint.config.mjs
img/
LICENSE
node_modules/
package.json
pnpm-lock.yaml
README.md
src/
tsconfig.build.json
tsconfig.json
vitest.config.mts

(33 entries)
</entries>
gateway · 2026-09-04 20:09:13
result
 M action.yml
 M docs/src/content/docs/targets/github.md
 M src/__tests__/action.test.ts
 M src/__tests__/config.test.ts
 M src/commands/prepare.ts
 M src/config.ts
 M src/schemas/project_config.ts
 M src/utils/__tests__/publishState.test.ts
 M src/utils/publishState.ts
 action.yml                               |  11 +-
 docs/src/content/docs/targets/github.md  |  20 ++-
 src/__tests__/action.test.ts             | 101 +++++++++---
 src/__tests__/config.test.ts             | 176 ++++++++++++++++++++-
 src/commands/prepare.ts                  |   3 +-
 src/config.ts                            | 255 +++++++++++++++++++++++++++++--
 src/schemas/project_config.ts            |  90 +++++++++++
 src/utils/__tests__/publishState.test.ts |  15 ++
 src/utils/publishState.ts                |   9 +-
 9 files changed, 636 insertions(+), 44 ...
gateway · 2026-09-04 20:09:19
result
 M .github/workflows/publish.yml
 M docs/publish-issue-format.md
 M src/modules/__tests__/ci-poller-input.js
 M src/modules/__tests__/details-from-context.js
 M src/modules/__tests__/publish-location.js
 M src/modules/__tests__/publish-workflow.js
 M src/modules/ci-poller-input.js
 M src/modules/details-from-context.js
 M src/modules/publish-issue-title.js
 M src/modules/publish-issue-title.peggy
 M src/modules/publish-location.js
 M src/publish/resolve-location.js
?? src/modules/publish-issue-validation.js
 .github/workflows/publish.yml                 |  14 +-
 docs/publish-issue-format.md                  |  56 +++----
 src/modules/__tests__/ci-poller-input.js      |  48 +++++-
 src/modules/__tests__/details-from-context.js | 219 ++++++-------------------
 src/modules/__tests__/publish-location.js     |  94 +++++------
 src/modules/__tests__/publish-workflow.js     |  35 +++-
 src/modules/ci-poller-input.js                |  15 ++
 src/modules/details-from-context.js           |  ...
gateway · 2026-09-04 20:09:37
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-validation.js</path>
<type>file</type>
<content>
1: function isPublishRepository(name) {
2:   return (
3:     /^[A-Za-z0-9_.-]+$/.test(name) &&
4:     name !== "." &&
5:     name !== ".." &&
6:     name !== "__proto__" &&
7:     !name.startsWith("-")
8:   );
9: }
10: 
11: function isReleaseVersion(version) {
12:   return /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-?([0-9a-z-]+(?:\.[0-9a-z-]+)*))?(?:\+([0-9a-z-]+(?:\.[0-9a-z-]+)*))?$/i.test(
13:     version
14:   );
15: }
16: 
17: module.exports = { isPublishRepository, isReleaseVersion };

(End of file - total 17 lines)
</content>
gateway · 2026-09-04 20:09:45
result
Found 73 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/workspaces.ts:
  Line 317:   // If version is the default regex pattern, use it as-is; otherwise escape it


/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/version.ts:
  Line 42:  * SemVer is a parsed semantic version.

  Line 44: export interface SemVer {

  Line 63: export function parseVersion(text: string): SemVer | null {

  Line 81: export function versionGreaterOrEqualThan(v1: SemVer, v2: SemVer): boolean {

  Line 164:  * Returns the stringified version of the passed SemVer object.

  Line 166: export function semVerToString(s: SemVer) {


/home/byk/Code/getsentry/craft-workspace-action-propagation/src/targets/brew.ts:
  Line 13: import { isPreviewRelease, parseVersion } from '../utils/version';

  Line 144:     const parsedVersion = parseVersion(version);


/home/byk/Code/getsentry/craft-workspace-action-propagation/src/targets/awsLambdaLayer.ts:
  Line 26: import { ...
gateway · 2026-09-04 20:09:50
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/version.ts</path>
<type>file</type>
<content>
1: import { getGitTagPrefix } from '../config';
2: 
3: /**
4:  * Regular expression for matching semver versions.
5:  *
6:  * Modified to match version components
7:  * Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
8:  * @see https://github.com/sindresorhus/semver-regex
9:  */
10: const semverRegex = () =>
11:   /\bv?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-?([\da-z-]+(?:\.[\da-z-]+)*))?(?:\+([\da-z-]+(?:\.[\da-z-]+)*))?\b/gi;
12: 
13: /**
14:  * Extracts a version number from the given text.
15:  *
16:  * In case the version contains a leading "v", it is stripped from the result.
17:  * All semantic versions are supported. See {@link http://semver.org/} for
18:  * more information. ...
gateway · 2026-09-04 20:09:57
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-04 20:10:03
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-04 20:10:09
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-04 20:10:15
result
Found 4 matches
/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/publish.yml:
  Line 96:           gh workflow run ci-poller.yml -R "$GITHUB_REPOSITORY"


/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 146:                 node .__publish__/src/publish/resolve-ci-poller-input.js | jq -r '.issueBody')

  Line 308:           gh workflow run ci-poller.yml -R "$GITHUB_REPOSITORY" -f attempt="${attempt}"
gateway · 2026-09-04 20:10:18
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-04 20:10:31
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-04 20:10:35
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', result);
10: }
11: 
12: 
13: inputs();

(End of file - total 13 lines)
</content>
gateway · 2026-09-04 20:10:44
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/resolve-release-revision.js</path>
<type>file</type>
<content>
1: const core = require("@actions/core");
2: const { getReleaseRevision } = require("../modules/release-revision");
3: 
4: function resolveReleaseRevision() {
5:   const { repo } = JSON.parse(process.env.PUBLISH_ARGS || "");
6:   core.setOutput(
7:     "revision",
8:     getReleaseRevision({
9:       issueBody: process.env.PUBLISH_ISSUE_BODY || "",
10:       repo,
11:     })
12:   );
13: }
14: 
15: resolveReleaseRevision();

(End of file - total 15 lines)
</content>
gateway · 2026-09-04 20:10:53
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/release-revision.js</path>
<type>file</type>
<content>
1: const CHECK_RUNS_LINK =
2:   /^Requested by: @[^\r\n]+\r?\n(?:[ \t]*\r?\n)?[ \t]*Merge target: [^\r\n]+\r?\n(?:[ \t]*\r?\n)?[ \t]*Quick links:\r?\n(?:[ \t]*\r?\n)?[ \t]*- \[View changes\]\([^\r\n]+\)\r?\n[ \t]*- \[View check runs\]\(https:\/\/github\.com\/getsentry\/(?<repo>[A-Za-z0-9_.-]+)\/commit\/(?<revision>[0-9a-f]{40})\/checks\/?\)(?=\r?\n|$)/;
3: const CHECK_RUNS_LINK_COUNT = /^[ \t]*- \[View check runs\]\(/gm;
4: 
5: function getReleaseRevision({ issueBody, repo }) {
6:   if ((issueBody.match(CHECK_RUNS_LINK_COUNT) || []).length !== 1) {
7:     throw new Error(
8:       `Expected exactly one View check runs link in Quick links for getsentry/${repo}.`
9:     );
10:   }
11: 
12:   const match = issueBody.match(CHECK_RUNS_LINK);
13:   if (!match?.groups || match.groups.repo !== repo) {
14:     throw new Error(
15:       `Expected a View check runs link ...
gateway · 2026-09-04 20:11:03
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/publishState.ts</path>
<type>file</type>
<content>
1: /**
2:  * Helpers for locating Craft's publish-state file in a path that is NOT
3:  * writable by the repository being published.
4:  *
5:  * Background: `craft publish` writes a small JSON file listing targets
6:  * that have completed so a resumed run can skip them. Before this module
7:  * existed, the file lived at `.craft-publish-<version>.json` in the
8:  * project's cwd. That path is inside the repository checkout, so any
9:  * committed file at the same path (or any earlier CI step) could
10:  * pre-populate the "published" set and trick Craft into silently
11:  * skipping targets.
12:  *
13:  * The file now lives under `$XDG_STATE_HOME/craft/` (falling back to
14:  * `$HOME/.local/state/craft/`). The filename is keyed on
15:  * owner, repo, a hash of cwd (to disambiguate monorepo subpaths), and
16:  * the version being published. ...
gateway · 2026-09-04 20:11:31
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/config.ts</path>
<type>file</type>
<content>
150:       };
151:       // Only adopt the merged github if it is complete (has owner + repo).
152:       // Otherwise leave `github` unset so getGlobalGitHubConfig() can still
153:       // fall back to git-remote detection instead of seeing a truthy-but-
154:       // incomplete object and skipping the fallback.
155:       if (mergedGithub.owner && mergedGithub.repo) {
156:         resolved.github = mergedGithub as GitHubGlobalConfig;
157:       } else {
158:         delete (resolved as { github?: unknown }).github;
159:       }
160:     } else {
161:       (resolved as Record<string, unknown>)[key] = value;
162:     }
163:   }
164: 
165:   return resolved;
166: }
167: 
168: function getWorkspaceConfig(
169:   workspaces: NonNullable<CraftProjectConfig['workspaces']>,
170:   workspaceName: string,
171:   workspaceDirectory: string,
172: ): Workspace | undefined {
173:   ...
gateway · 2026-09-04 20:11:54
result
No files found
gateway · 2026-09-04 20:12:01
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/glob</path>
<type>directory</type>
<entries>
dist/
LICENSE.md
package.json
README.md

(4 entries)
</entries>
gateway · 2026-09-04 20:12:05
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/glob/dist</path>
<type>directory</type>
<entries>
commonjs/
esm/

(2 entries)
</entries>
gateway · 2026-09-04 20:12:10
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/glob/dist/commonjs</path>
<type>directory</type>
<entries>
glob.d.ts
glob.d.ts.map
glob.js
glob.js.map
has-magic.d.ts
has-magic.d.ts.map
has-magic.js
has-magic.js.map
ignore.d.ts
ignore.d.ts.map
ignore.js
ignore.js.map
index.d.ts
index.d.ts.map
index.js
index.js.map
package.json
pattern.d.ts
pattern.d.ts.map
pattern.js
pattern.js.map
processor.d.ts
processor.d.ts.map
processor.js
processor.js.map
walker.d.ts
walker.d.ts.map
walker.js
walker.js.map

(29 entries)
</entries>
gateway · 2026-09-04 20:12:14
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/glob/dist/commonjs/has-magic.js</path>
<type>file</type>
<content>
1: "use strict";
2: Object.defineProperty(exports, "__esModule", { value: true });
3: exports.hasMagic = void 0;
4: const minimatch_1 = require("minimatch");
5: /**
6:  * Return true if the patterns provided contain any magic glob characters,
7:  * given the options provided.
8:  *
9:  * Brace expansion is not considered "magic" unless the `magicalBraces` option
10:  * is set, as brace expansion just turns one string into an array of strings.
11:  * So a pattern like `'x{a,b}y'` would return `false`, because `'xay'` and
12:  * `'xby'` both do not contain any magic glob characters, and it's treated the
13:  * same as if you had called it on `['xay', 'xby']`. When `magicalBraces:true`
14:  * is in the options, brace expansion _is_ treated as a pattern having magic.
15:  */
16: const hasMagic = (pattern, options = {}) => {
17:     if ...
gateway · 2026-09-04 20:12:19
result
No files found
gateway · 2026-09-04 20:12:29
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/glob/package.json</path>
<type>file</type>
<content>
1: {
2:   "author": "Isaac Z. Schlueter <i@izs.me> (https://blog.izs.me/)",
3:   "name": "glob",
4:   "description": "the most correct and second fastest glob implementation in JavaScript",
5:   "version": "11.1.0",
6:   "type": "module",
7:   "tshy": {
8:     "main": true,
9:     "exports": {
10:       "./package.json": "./package.json",
11:       ".": "./src/index.ts"
12:     }
13:   },
14:   "bin": "./dist/esm/bin.mjs",
15:   "main": "./dist/commonjs/index.js",
16:   "types": "./dist/commonjs/index.d.ts",
17:   "exports": {
18:     "./package.json": "./package.json",
19:     ".": {
20:       "import": {
21:         "types": "./dist/esm/index.d.ts",
22:         "default": "./dist/esm/index.js"
23:       },
24:       "require": {
25:         "types": "./dist/commonjs/index.d.ts",
26:         "default": "./dist/commonjs/index.js"
27:       }
28:     }
29: ...
gateway · 2026-09-04 20:12:34
result
No files found
gateway · 2026-09-04 20:12:39
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/.pnpm</path>
<type>directory</type>
<entries>
@apm-js-collab+code-transformer@0.8.2/
@apm-js-collab+tracing-hooks@0.3.1/
@aws-crypto+crc32@5.2.0/
@aws-crypto+sha256-browser@5.2.0/
@aws-crypto+sha256-js@5.2.0/
@aws-crypto+supports-web-crypto@5.2.0/
@aws-crypto+util@5.2.0/
@aws-sdk+client-lambda@3.984.0/
@aws-sdk+client-sso@3.982.0/
@aws-sdk+core@3.973.6/
@aws-sdk+credential-provider-env@3.972.4/
@aws-sdk+credential-provider-http@3.972.6/
@aws-sdk+credential-provider-ini@3.972.4/
@aws-sdk+credential-provider-login@3.972.4/
@aws-sdk+credential-provider-node@3.972.5/
@aws-sdk+credential-provider-process@3.972.4/
@aws-sdk+credential-provider-sso@3.972.4/
@aws-sdk+credential-provider-web-identity@3.972.4/
@aws-sdk+middleware-host-header@3.972.3/
@aws-sdk+middleware-logger@3.972.3/
@aws-sdk+middleware-recursion-detection@3.972.3/
@aws-sdk+middleware-user-agent@3.972.6/
@aws-sdk+nested-clients@3.982.0/
@aws-sdk+regi...
gateway · 2026-09-04 20:12:56
result
File not found: /home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/.pnpm/minimatch@10.1.1/node_modules/minimatch/dist/commonjs/index.js
gateway · 2026-09-04 20:13:05
result
No files found
gateway · 2026-09-04 20:13:09
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/.pnpm</path>
<type>directory</type>
<entries>
callsites@3.1.0/
caniuse-lite@1.0.30001763/
chai@6.2.2/
chalk@4.1.1/
chokidar@3.6.0/
chownr@1.1.4/
chownr@3.0.0/
ci-info@2.0.0/
ci-info@4.3.1/
cjs-module-lexer@1.2.3/
cjs-module-lexer@1.4.3/
cli-cursor@3.1.0/
cli-spinners@2.9.2/
cli-table@0.3.1/
cliui@9.0.1/
clone@1.0.4/
color-convert@2.0.1/
color-name@1.1.4/
colors@1.0.3/
combined-stream@1.0.8/
commander@12.1.0/
consola@2.15.3/
convert-source-map@2.0.0/
cookie@0.7.2/
core-util-is@1.0.3/
cross-spawn@7.0.6/
debug@4.4.3/
deep-is@0.1.4/
defaults@1.0.4/
define-data-property@1.1.4/
delayed-stream@1.0.0/
dotenv@16.6.1/
dunder-proto@1.0.1/
duplexify@4.1.3/
eastasianwidth@0.2.0/
ecdsa-sig-formatter@1.0.11/
electron-to-chromium@1.5.267/
emoji-regex@10.6.0/
emoji-regex@8.0.0/
emoji-regex@9.2.2/
end-of-stream@1.4.5/
es-define-property@1.0.1/
es-errors@1.3.0/
es-module-lexer@1.5.0/
es-module-lexer@2.1.0/
es-object-atoms@1.1....
gateway · 2026-09-04 20:13:13
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/.pnpm</path>
<type>directory</type>
<entries>
get-tsconfig@4.14.0/
git-up@8.1.1/
git-url-parse@16.1.0/
glob-parent@5.1.2/
glob-parent@6.0.2/
glob@11.1.0/
glob@9.3.5/
globals@14.0.0/
google-auth-library@9.15.1/
google-logging-utils@0.0.2/
gopd@1.2.0/
graceful-fs@4.2.11/
gtoken@7.1.0/
has-flag@4.0.0/
has-property-descriptors@1.0.2/
has-symbols@1.1.0/
has-tostringtag@1.0.2/
hasown@2.0.4/
html-entities@2.6.0/
http-proxy-agent@5.0.0/
http-proxy@1.18.1/
https-proxy-agent@5.0.1/
https-proxy-agent@7.0.6/
ieee754@1.2.1/
ignore@4.0.6/
ignore@5.3.2/
ignore@7.0.5/
import-fresh@3.3.1/
import-in-the-middle@2.0.0/
imurmurhash@0.1.4/
inherits@2.0.4/
is-binary-path@2.1.0/
is-callable@1.2.7/
is-ci@2.0.0/
is-extglob@2.1.1/
is-fullwidth-code-point@3.0.0/
is-glob@4.0.3/
is-interactive@1.0.0/
is-number@7.0.0/
is-ssh@1.4.1/
is-stream@2.0.1/
is-typed-array@1.1.15/
is-unicode-supported@0.1.0/
isarray@1.0.0/
isarray@2.0.5/
isexe@2.0....
gateway · 2026-09-04 20:13:18
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/dist/commonjs/index.js</path>
<type>file</type>
<content>
1: "use strict";
2: Object.defineProperty(exports, "__esModule", { value: true });
3: exports.unescape = exports.escape = exports.AST = exports.Minimatch = exports.match = exports.makeRe = exports.braceExpand = exports.defaults = exports.filter = exports.GLOBSTAR = exports.sep = exports.minimatch = void 0;
4: const brace_expansion_1 = require("brace-expansion");
5: const assert_valid_pattern_js_1 = require("./assert-valid-pattern.js");
6: const ast_js_1 = require("./ast.js");
7: const escape_js_1 = require("./escape.js");
8: const unescape_js_1 = require("./unescape.js");
9: const minimatch = (p, pattern, options = {}) => {
10:     (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
11:     // shortcut: comments match nothing.
12:     if (!options.nocomment && pattern.charAt(0) === '#') {
13:      ...
gateway · 2026-09-04 20:13:25
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/dist/commonjs/index.js</path>
<type>file</type>
<content>
250:         return false;
251:     }
252:     debug(..._) { }
253:     make() {
254:         const pattern = this.pattern;
255:         const options = this.options;
256:         // empty patterns and comments match nothing.
257:         if (!options.nocomment && pattern.charAt(0) === '#') {
258:             this.comment = true;
259:             return;
260:         }
261:         if (!pattern) {
262:             this.empty = true;
263:             return;
264:         }
265:         // step 1: figure out negation, etc.
266:         this.parseNegate();
267:         // step 2: expand braces
268:         this.globSet = [...new Set(this.braceExpand())];
269:         if (options.debug) {
270:             //oxlint-disable-next-line no-console
271:             this.debug = (...args) => ...
gateway · 2026-09-04 20:13:29
result
Found 2 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/dist/commonjs/index.js:
  Line 266:         this.parseNegate();

  Line 601:     parseNegate() {
gateway · 2026-09-04 20:13:39
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/dist/commonjs/index.js</path>
<type>file</type>
<content>
580:                 bi++;
581:             }
582:             else if (b[bi] === '*' &&
583:                 a[ai] &&
584:                 (this.options.dot || !a[ai].startsWith('.')) &&
585:                 a[ai] !== '**') {
586:                 if (which === 'a')
587:                     return false;
588:                 which = 'b';
589:                 result.push(b[bi]);
590:                 ai++;
591:                 bi++;
592:             }
593:             else {
594:                 return false;
595:             }
596:         }
597:         // if we fall out of the loop, it means they two are identical
598:         // as long as their lengths match
599:         return a.length === b.length && result;
600:     }
601:     parseNegate() {
602:         if (this.nonegate)
603:             ...
gateway · 2026-09-04 20:13:59
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/action.yml</path>
<type>file</type>
<content>
1: name: 'Craft Prepare Release'
2: description: 'Prepare a new release using Craft'
3: 
4: inputs:
5:   version:
6:     description: >
7:       Version to release. Can be a semver string (e.g., "1.2.3"),
8:       a bump type ("major", "minor", "patch"), or "auto" for automatic detection.
9:     required: false
10:   merge_target:
11:     description: Target branch to merge into. Uses the default branch as a fallback. ...
gateway · 2026-09-04 20:14:13
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: // Canonical grammar for publish issue titles. A path suffix is syntactic only:
8: // the controller resolves the complete suffix as a workspace after checking
9: // out the CI-approved revision.
10: PublishIssueTitle
11:   = "publish: " "getsentry/"? repo:Repository path:Path? "@" version:Version !. {
12:       return {
13:         repo,
14:         path: path || "",
15:         version,
16:       };
17:     }
18: 
19: Repository
20:   = characters:RepositoryCharacter+ { return join(characters); }
21: 
22: RepositoryCharacter
23:   = [A-Za-z0-9_.-]
24: 
25: Path
26:   = segments:("/" segment:PathSegment { return `/${segment}`; })+ { return join(segments); }
27: 
28: PathSegment
29:   = characters:RepositoryCharacter+ { return join(characters); }
30: 
31: ...
gateway · 2026-09-04 20:14:21
result
/home/byk/Code/getsentry/publish-workspace-acceptance/scripts/generate-publish-issue-title-parser.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-title.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-title.peggy
gateway · 2026-09-04 20:14:29
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-04 20:14:36
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 grammar = fs.readFileSync(grammarPath, "utf8");
21: const parser = peggy.generate(grammar, {
22:   format: "commonjs",
23:   grammarSource: "publish-issue-title.peggy",
24:   output: "source",
25: });
26: 
27: const generatedParser = prettier.format(`/* eslint-disable */\n${parser}`, {
28:   filepath: outputPath,
29: });
30: 
31: if (process.argv.includes("--check")) {
32:   const currentParser = fs.readFileSync(outputPath, "utf8");
33:   ...
gateway · 2026-09-04 20:15:46
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-04 20:15:56
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/__tests__/config.test.ts</path>
<type>file</type>
<content>
350:   test('a different workspace resolves independently', () => {
351:     setActiveWorkspace('mcp');
352:     const config = loadConfigurationFromString(WS_CONFIG);
353:     expect(config.releaseBranchPrefix).toBe('release/mcp');
354:     expect(getGitTagPrefix()).toBe('mcp@');
355:     expect(getVersioningPolicy()).toBe('calver');
356:     expect(config.github).toEqual({ owner: 'getsentry', repo: 'toolkit' });
357:   });
358: 
359:   test('errors when workspaces are defined but none is selected', () => {
360:     setActiveWorkspace(undefined);
361:     expect(() => loadConfigurationFromString(WS_CONFIG)).toThrow(
362:       /defines workspaces; select one/,
363:     );
364:   });
365: 
366:   test('lists concrete workspace names without requiring a selection', () => {
367:     setActiveWorkspace(undefined);
368:     const directory = ...
gateway · 2026-09-04 20:16:07
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/__tests__/action.test.ts</path>
<type>file</type>
<content>
1: import {
2:   chmodSync,
3:   mkdtempSync,
4:   mkdirSync,
5:   readFileSync,
6:   rmSync,
7:   writeFileSync,
8: } from 'fs';
9: import { tmpdir } from 'os';
10: import { join } from 'path';
11: import { spawnSync } from 'child_process';
12: 
13: import { load } from 'js-yaml';
14: import { afterEach, expect, test } from 'vitest';
15: 
16: interface ActionStep {
17:   env?: Record<string, string>;
18:   name?: string;
19:   run?: string;
20: }
21: 
22: function getActionSteps(): ActionStep[] {
23:   const action = load(
24:     readFileSync(join(__dirname, '../../action.yml'), 'utf8'),
25:   ) as {
26:     runs?: { steps?: ActionStep[] };
27:   };
28:   return action.runs?.steps || [];
29: }
30: 
31: function getActionStep(name: string): ActionStep {
32:   const step = getActionSteps().find(step => step.name === name);
33:   if (!step?.run) {
34:     ...
gateway · 2026-09-04 20:16:17
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-04 20:16:23
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-location.js</path>
<type>file</type>
<content>
1: import { expect, test } from "vitest";
2: 
3: const { resolvePublishLocation } = require("../publish-location.js");
4: 
5: test("classifies an exact full workspace path without normalizing it", () => {
6:   expect(
7:     resolvePublishLocation({
8:       path: "./packages/CLI",
9:       workspaceNames: ["packages/cli", "packages/CLI"],
10:     })
11:   ).toStrictEqual({ path: ".", workspace: "packages/CLI" });
12: });
13: 
14: test("keeps a non-workspace suffix as a checkout path", () => {
15:   expect(
16:     resolvePublishLocation({
17:       path: "./packages",
18:       workspaceNames: ["cli"],
19:     })
20:   ).toStrictEqual({ path: "./packages" });
21: });
22: 
23: test("keeps a multi-segment suffix that is not an exact workspace path", () => {
24:   expect(
25:     resolvePublishLocation({
26:       path: "./packages/cli",
27:       ...
gateway · 2026-09-04 20:16:29
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: `. This EBNF is canonical:
10: 
11: ```text
12: title             = "publish: ", [ "getsentry/" ], repository, [ path ],
13:                     "@", version ;
14: repository        = token, { token } ;
15: path              = "/", path-segment, { "/", path-segment } ;
16: path-segment      = token, { token } ;
17: version           = version-character, { version-character } ;
18: token             = ? ASCII letter, digit, ".", "_", or "-" ? ...
gateway · 2026-09-04 20:16:45
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/schemas/project_config.ts</path>
<type>file</type>
<content>
170:  *
171:  * These are shared between the top-level config (the implicit/default release
172:  * unit) and each entry under the top-level `workspaces` map (an explicit,
173:  * independently-versioned release unit). A workspace inherits the top-level
174:  * values as defaults and overrides the fields it declares.
175:  *
176:  * NOTE: this "workspace" (a named, independently-versioned release unit) is a
177:  * different concept from the `npm` target's `workspaces: true` field, which
178:  * discovers npm packages *within* a single target and publishes them all at the
179:  * same version. See docs for the disambiguation.
180:  */
181: const releaseUnitFields = {
182:   github: GitHubGlobalConfigSchema.optional(),
183:   targets: z.array(TargetConfigSchema).optional(),
184:   preReleaseCommand: z.string().optional(),
185:   postReleaseCommand: ...
gateway · 2026-09-04 20:17:22
result
yarn run v1.22.22
$ node scripts/generate-publish-issue-title-parser.js --check
Done in 0.52s.
gateway · 2026-09-04 20:17:39
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-title.js</path>
<type>file</type>
<content>
195:   const peg$source = options.grammarSource;
196: 
197:   const peg$startRuleFunctions = {
198:     PublishIssueTitle: peg$parsePublishIssueTitle,
199:   };
200:   let peg$startRuleFunction = peg$parsePublishIssueTitle;
201: 
202:   const peg$c0 = "publish: ";
203:   const peg$c1 = "getsentry/";
204:   const peg$c2 = "@";
205:   const peg$c3 = "/";
206: 
207:   const peg$r0 = /^[A-Za-z0-9_.\-]/;
208:   const peg$r1 = /^[A-Za-z0-9_.+\-]/;
209: 
210:   const peg$e0 = peg$literalExpectation("publish: ", false);
211:   const peg$e1 = peg$literalExpectation("getsentry/", false);
212:   const peg$e2 = peg$literalExpectation("@", false);
213:   const peg$e3 = peg$anyExpectation();
214:   const peg$e4 = peg$classExpectation(
215:     [["A", "Z"], ["a", "z"], ["0", "9"], "_", ".", "-"],
216:     false,
217:     false,
218:     false
219:   );
220:   const peg$e5 ...
gateway · 2026-09-04 20:18:01
result
 M action.yml
 M docs/src/content/docs/targets/github.md
 M src/__tests__/action.test.ts
 M src/__tests__/config.test.ts
 M src/commands/prepare.ts
 M src/config.ts
 M src/schemas/project_config.ts
 M src/utils/__tests__/publishState.test.ts
 M src/utils/publishState.ts
gateway · 2026-09-04 20:18:08
result
 M .github/workflows/publish.yml
 M docs/publish-issue-format.md
 M src/modules/__tests__/ci-poller-input.js
 M src/modules/__tests__/details-from-context.js
 M src/modules/__tests__/publish-location.js
 M src/modules/__tests__/publish-workflow.js
 M src/modules/ci-poller-input.js
 M src/modules/details-from-context.js
 M src/modules/publish-issue-title.js
 M src/modules/publish-issue-title.peggy
 M src/modules/publish-location.js
 M src/publish/resolve-location.js
?? src/modules/publish-issue-validation.js
gateway · 2026-09-04 20:18:24
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-04 20:19:39
result
Found 2 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts:
  Line 629:   const rev = argv.rev;

  Line 680:   const revision = await git.revparse('HEAD');
gateway · 2026-09-04 20:19:47
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts</path>
<type>file</type>
<content>
590:   logger.info(`Running the post-release command...`);
591:   await spawnProcess(sysCommand as string, args as string[], {
592:     env: buildReleaseCommandEnv({ CRAFT_RELEASED_VERSION: newVersion }),
593:   });
594:   return true;
595: }
596: 
597: /**
598:  * Body of 'publish' command
599:  *
600:  * @param argv Command-line arguments
601:  */
602: export async function publishMain(argv: PublishOptions): Promise<any> {
603:   // Get publishing configuration
604:   const config = getConfiguration() || {};
605: 
606:   const newVersion = argv.newVersion;
607: 
608:   logger.info(`Publishing version: "${newVersion}"`);
609: 
610:   const git = await getGitClient();
611: 
612:   // Check for dirty repository state before any git operations
613:   if (argv.noGitChecks) {
614:     logger.info('Not checking the status of the local repository');
615:   } else ...
gateway · 2026-09-04 20:20:01
result
Found 6 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts:
  Line 634:     branchName = await getRevisionBranchName(git, rev);

  Line 933: export async function getRevisionBranchName(


/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/__tests__/publish.test.ts:
  Line 6:   getRevisionBranchName,

  Line 213: describe('getRevisionBranchName', () => {

  Line 219:     await expect(getRevisionBranchName(git, 'abc123')).resolves.toBe(

  Line 235:     await expect(getRevisionBranchName(git, 'abc123')).resolves.toBe('');
gateway · 2026-09-04 20:20:17
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts</path>
<type>file</type>
<content>
900:       }
901:       lines.push(
902:         ``,
903:         `Error: ${mergeError instanceof Error ? mergeError.message : String(mergeError)}`,
904:       );
905:       logger.warn(lines.join('\n'));
906:     }
907: 
908:     // XXX(BYK): intentionally DO NOT await unlinking as we do not want
909:     // to block (both in terms of waiting for IO and the success of the
910:     // operation) finishing the publish flow on the removal of a temporary
911:     // file. If unlinking fails, we honestly don't care, at least to fail
912:     // the final steps. And it doesn't make sense to wait until this op
913:     // finishes then as nothing relies on the removal of this file.
914:     safeFs
915:       .unlink(publishStateFile)
916:       .catch((err: unknown) =>
917:         logger.trace("Couldn't remove publish state file: ", err),
918:       );
919:     ...
gateway · 2026-09-04 20:20:57
result
Found 3 matches
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-location.js:
  Line 11:   ).toStrictEqual({ path: ".", workspace: "packages/CLI" });


/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-workflow.js:
  Line 90:     "CRAFT_PUBLISH_WORKSPACE: ${{ fromJSON(steps.location.outputs.result).workspace || '' }}"

  Line 129:     workspace: location.workspace,
gateway · 2026-09-04 20:21:32
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/__tests__/publishState.test.ts</path>
<type>file</type>
<content>
70:     test('disambiguates release workspaces at the same repo, cwd, and version', () => {
71:       const cli = getPublishStateFilename(
72:         '1.2.3',
73:         { owner: 'o', repo: 'r' },
74:         cwd,
75:         'cli',
76:       );
77:       const mcp = getPublishStateFilename(
78:         '1.2.3',
79:         { owner: 'o', repo: 'r' },
80:         cwd,
81:         'mcp',
82:       );
83:       expect(cli).not.toBe(mcp);
84:       expect(cli).toMatch(/-workspace-Y2xp-1\.2\.3\.json$/);
85:       expect(mcp).toMatch(/-workspace-bWNw-1\.2\.3\.json$/);
86:     });
87: 
88:     test('does not collide when workspace names only differ by case or punctuation', () => {
89:       const names = ['CLI', 'cli', 'cli/workspace', 'cli_workspace'];
90:       const filenames = names.map(workspace =>
91:         getPublishStateFilename(
92:        ...
gateway · 2026-09-04 20:22:18
  1. MUST-FIX — High: Malformed brace syntax passes validation. Both implementations return [] for unclosed or non-alternative braces, then accept it through vacuous .every() success: Craft runtime src/config.ts:287-294,327-349; schema src/schemas/project_config.ts:249-285,305-317. Thus keys such as packages/{cli and packages/{cli} are accepted rather than rejected before glob handling. Existing tests cover balanced alternatives but not malformed braces: src/__tests__/config.test.ts:451-515.

  2. PASS: CI input validates repository, Craft-compatible version, and canonical path before getReleaseRevision: publish/src/modules/ci-poller-input.js:12-30. Root . is allowed; unsafe segments are rejected in publish-location.js:19-44. Target-repository API calls occur only after parsed input is consumed: .github/workflows/ci-poller.yml:100-115.

  3. PASS: Craft and Publish use matching version encoding: craft/src/utils/publishState.ts:58-63,95-102; publish/.github/workflows/publish.yml:217-233. Both preserve already-safe lowercase versions and base64url-encode altered values. Regression coverage checks case-distinct encoded names: craft/src/utils/__tests__/publishState.test.ts:101-123; publish/src/modules/__tests__/publish-workflow.js:138-152.

  4. PASS: The action validates path/workspace before later steps, enforces exclusivity, and rejects unsafe segments: craft/action.yml:74-92. It clears inherited CRAFT_WORKSPACE before both Craft invocations: action.yml:180-225; full workspace paths remain intact in titles: action.yml:245-275. Tests cover unsafe inputs, full paths, and ambient-variable clearing: src/__tests__/action.test.ts:204-312.

  5. PASS: Publish resolves the release revision, checks out that SHA before discovery, then performs exact case-sensitive workspace matching: publish.yml:138-182; src/modules/publish-location.js:1-44. It gates on a fresh accepted ci-ready event: publish.yml:102-114, isolates ...

gpt-5.6-terra · 2026-09-04 20:22:20 · ~617 tokens

Distillations (4)

Gen 0 2026-09-04 20:24:36 · 2195 tokens

Date: Sep 4, 2026 * 🔴 (20:09) User stated package-management policy for `craft-workspace-action-propagation`: always use `pnpm`; never use `npm` or `yarn`. * 🟡 (20:09) Read-only `AGENTS.md` output for `/home/byk/Code/getsentry/craft-workspace-action-propagation` specifies Node.js v22.12.0 managed by Volta; dependency installation command `pnpm install --frozen-lockfile`; development commands `p…

Gen 0 2026-09-04 20:17:44 · 754 tokens

Date: Sep 4, 2026 * 🔴 (20:09) User stated that new Craft publish requests always include the checkout repository identity. * 🔴 (20:09) User stated that a missing root `.craft.yml` always means checkout-path behavior. * 🔴 (20:09) User stated that the controller never normalizes publish-location names. * 🟡 (20:09) Read-only diff output for `/home/byk/Code/getsentry/publish-workspace-acceptance`…

Gen 0 2026-09-04 20:13:42 · 534 tokens

Date: Sep 4, 2026 * 🔴 (20:09) User stated that Action publish titles always carry the full concrete workspace path; `craft workspace list` outputs concrete workspace paths as a JSON array for automation. * 🟡 (20:09) Read-only tool output enumerated `/home/byk/Code/getsentry/craft-workspace-action-propagation` (33 entries), including `.craft.yml`, `action.yml`, `Dockerfile`, `README.md`, `docs/`…

Gen 0 2026-09-04 20:09:59 · 680 tokens

Date: Sep 4, 2026 * 🔴 (20:08) User directive: never return empty. * 🔴 [requested-read-only-audit] (20:08) User requested a strict final READ-ONLY adversarial audit of the complete CURRENT uncommitted diff and relevant source in both worktrees: `/home/byk/Code/getsentry/craft-workspace-action-propagation` and `/home/byk/Code/getsentry/publish-workspace-acceptance`. * 🔴 (20:08) User required the…