Dashboard › craft › Session 10K5RWfSz8ej
10K5RWfSz8ejWw2DNRead-only adversarial review of the current uncommitted hotfix in /home/byk/Code/getsentry/publish-root-location-bootstrap. Do not edit files. Review the complete diff and relevant resolver/workflow behavior. Verify: root path '.' cannot be a workspace; only root skips Craft workspace discovery; non-root paths still fail closed when root config discovery cannot run; input validation remains enforced before this function; compatibility/regression tests are sufficient. Run read-only checks only. Return severity-ranked file:line findings and exact verdict MERGE or DO-NOT-MERGE.
<skill_content name="jj-guide"> # Skill: jj-guide # jj Guide for AI Agents Jujutsu (jj) is a Git-compatible VCS with mutable commits, automatic snapshotting, no staging area, and first-class conflicts. This skill teaches you how to use it safely from a non-interactive agent environment. If `.jj/` exists in the repo root, this is a jj repo. **Use `jj` commands, not `git`.** In a colocated repo (`.jj/` *and* `.git/`), git tools can read the state, but mutations should go through `jj` so the operation log stays consistent. ## Critical Rules - **NEVER** use interactive flags (`-i`, `--interactive`). TUI prompts hang in agent environments. This applies to `jj split -i`, `jj squash -i`, `jj commit -i`, `jj resolve`, `jj diffedit`, etc. - **ALWAYS** pass `-m "msg"` when describing/committing. Without `-m`, an editor opens and hangs. - **VERIFY** mutations with `jj st` and `jj log` after `squash`, `abandon`, `rebase`, `restore`, `commit`. ...
Error: There is no jj repo in "."
M src/publish/__tests__/discover-location.js M src/publish/discover-location.js src/publish/__tests__/discover-location.js | 16 ++++++++++++++++ src/publish/discover-location.js | 4 ++++ 2 files changed, 20 insertions(+) src/publish/__tests__/discover-location.js src/publish/discover-location.js 7c60ddb feat: accept workspace publish requests 83d210b build(deps): bump js-yaml from 4.3.0 to 4.3.1 (#9174) 5268a23 feat: Add Vercel creds 92eba3f feat: Add CLOUDFLARE_API_TOKEN (#9122) ada6147 build(deps): bump js-yaml from 4.1.1 to 4.3.0 (#8731) a4f961a fix: Add GITHUB_API_TOKEN for commit-on-git target (#9069) bf10f82 build(deps): bump postcss from 8.5.15 to 8.5.23 (#9017) 837edc0 docs: fix possessive apostrophe placement (#9015) 4da4a25 chore: replace deprecated trimRight() with trimEnd() (#9012) 22fd64d docs: fix typo 'acces' -> 'access' (#9011)
diff --git a/src/publish/__tests__/discover-location.js b/src/publish/__tests__/discover-location.js
index 7b522a6..277bd40 100644
--- a/src/publish/__tests__/discover-location.js
+++ b/src/publish/__tests__/discover-location.js
@@ -16,6 +16,22 @@ test("retains checkout-path behavior when the root config is absent", () => {
).toEqual({ path: "./packages/cli" });
});
+test("does not discover workspaces for the checkout root", () => {
+ const execFile = vi.fn(() => {
+ throw new Error("workspace list is unavailable");
+ });
+
+ expect(
+ discoverLocation({
+ input: { path: "." },
+ repositoryDirectory: "__repo__",
+ exists: () => true,
+ execFile,
+ })
+ ).toEqual({ path: "." });
+ expect(execFile).not.toHaveBeenCalled();
+});
+
test("discovers exact workspace paths using the released Craft image", () => {
const execFile = vi.fn(() => '["packages/CLI"]');
diff --git a/src/publish/discover-location.js b/src/publish/discover-location.js
index ...
<path>/home/byk/Code/getsentry/publish-root-location-bootstrap/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: ...
<path>/home/byk/Code/getsentry/publish-root-location-bootstrap/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("does not discover workspaces for the checkout root", () => {
20: const execFile = vi.fn(() => {
21: throw new Error("workspace list is unavailable");
22: });
23:
24: expect(
25: discoverLocation({
26: input: { path: "." },
27: repositoryDirectory: "__repo__",
28: exists: () => true,
29: ...
<path>/home/byk/Code/getsentry/publish-root-location-bootstrap/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 ...
...output truncated...
Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_0822d7888001GmQAkeNKZ850I9
.github/workflows/publish.yml-296- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
.github/workflows/publish.yml-297- run: node .__publish__/src/publish/update-issue.js
.github/workflows/publish.yml-298-
.github/workflows/publish.yml-299- - name: Inform about cancellation
.github/workflows/publish.yml-300- if: ${{ cancelled() }}
.github/workflows/publish.yml-301- env:
.github/workflows/publish.yml:302: PUBLISH_ARGS: ${{ steps.inputs.outputs.result }}
.github/workflows/publish.yml-303- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
.github/workflows/publish.yml-304- run: node .__publish__/src/publish/post-result.js cancelled
.github/workflows/publish.yml-305-
.github/workflows/publish.yml-306- - name: Inform about failure
.github/workflows/publish.yml-307- if: ${{ failure() ...
<path>/home/byk/Code/getsentry/publish-root-location-bootstrap/.github/workflows/publish.yml</path> <type>file</type> <content> 95: run: | 96: gh workflow run ci-poller.yml -R "$GITHUB_REPOSITORY" 97: 98: publish: 99: runs-on: ubuntu-latest 100: environment: production 101: name: Publish a new version 102: # Publish when ci-ready is present (added by the poller after CI passes). 103: # Fires ONLY on ci-ready label events — not accepted — to avoid racing 104: # with waiting-for-ci on the same event. The poller always adds ci-ready 105: # after checking CI (even if ci-ready was already present, waiting-for-ci 106: # removes it first so a fresh labeled event fires), so this gate is 107: # guaranteed to trigger on the happy path. 108: if: >- 109: github.event.issue.state == 'open' 110: && github.event.label.name == 'ci-ready' 111: && contains(github.event.issue.labels.*.name, 'accepted') 112: && ...
<path>/home/byk/Code/getsentry/publish-root-location-bootstrap/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>
<path>/home/byk/Code/getsentry/publish-root-location-bootstrap/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": ...
yarn run v1.22.22 $ /home/byk/Code/getsentry/publish-root-location-bootstrap/node_modules/.bin/vitest run src/publish/__tests__/discover-location.js src/modules/__tests__/publish-location.js src/modules/__tests__/details-from-context.js src/modules/__tests__/ci-poller-input.js --printConsoleTrace [1m[46m RUN [49m[22m [36mv4.1.0 [39m[90m/home/byk/Code/getsentry/publish-root-location-bootstrap[39m [2m Test Files [22m [1m[32m4 passed[39m[22m[90m (4)[39m [2m Tests [22m [1m[32m53 passed[39m[22m[90m (53)[39m [2m Start at [22m 18:01:03 [2m Duration [22m 643ms[2m (transform 89ms, setup 0ms, import 337ms, tests 84ms, environment 2ms)[22m Done in 1.25s. yarn run v1.22.22 $ eslint src .github --ignore-pattern '!.github' Done in 1.20s.
<path>/home/byk/Code/getsentry/publish-root-location-bootstrap/src/modules/details-from-context.js</path>
<type>file</type>
<content>
1: const { parse: parsePublishIssueTitle } = require("./publish-issue-title");
2: const { getReleaseRevisionDetails } = require("./release-revision");
3: const { isPublishPath } = require("./publish-location");
4: const {
5: isPublishRepository,
6: isReleaseVersion,
7: } = require("./publish-issue-validation");
8:
9: /**
10: * Matches the entire "Targets" section of a github publish issue body.
11: */
12: const TARGETS_SECTION_PARSER_REGEX =
13: /^(?!### Targets$\s)(?: *- \[[ xX]\] \S+\s*$(?:\r?\n)?)+/m;
14:
15: /**
16: * Matches all targets of a github publish issue body in a section that was already matched and extracted with `TARGETS_PARSER_REGEX`.
17: * The "id" of the targets is captured within a capture group. ...
M src/publish/__tests__/discover-location.js
M src/publish/discover-location.js
16 0 src/publish/__tests__/discover-location.js
4 0 src/publish/discover-location.js
diff --git a/src/publish/__tests__/discover-location.js b/src/publish/__tests__/discover-location.js
index 7b522a6..277bd40 100644
--- a/src/publish/__tests__/discover-location.js
+++ b/src/publish/__tests__/discover-location.js
@@ -16,6 +16,22 @@ test("retains checkout-path behavior when the root config is absent", () => {
).toEqual({ path: "./packages/cli" });
});
+test("does not discover workspaces for the checkout root", () => {
+ const execFile = vi.fn(() => {
+ throw new Error("workspace list is unavailable");
+ });
+
+ expect(
+ discoverLocation({
+ input: { path: "." },
+ repositoryDirectory: "__repo__",
+ exists: () => true,
+ execFile,
+ })
+ ).toEqual({ path: "." });
+ expect(execFile).not.toHaveBeenCalled();
+});
+
test("discovers exact workspace paths using the ...
Findings:
src/publish/__tests__/discover-location.js:19 proves root releases skip discovery, but no test proves a non-root path propagates a Docker/workspace-discovery failure. Add a test with path: './packages/cli', root config present, and throwing execFile; it must throw rather than return a checkout path.Verified:
. returns {path: '.'} without a workspace: src/publish/discover-location.js:51.. skips discovery; non-root paths call getWorkspaceNames: src/publish/discover-location.js:55.src/modules/details-from-context.js:49-52, invoked by src/publish/inputs.js:6-9 and passed through the workflow at .github/workflows/publish.yml:134-174.DO-NOT-MERGE
Date: Sep 8, 2026 * 🔴 (18:00) User stated that the CI poller always adds the `ci-ready` label after checking CI; if `ci-ready` was already present, `waiting-for-ci` removes it first so a fresh `labeled` event fires. * 🔴 (18:00) User provided workflow source from `/home/byk/Code/getsentry/publish-root-location-bootstrap/.github/workflows/publish.yml`, lines 95-239. The `publish` job runs on `ubu…
Date: Sep 8, 2026 * 🔴 (18:00) User provided source content from repository path `/home/byk/Code/getsentry/publish-root-location-bootstrap/src/publish/discover-location.js`. * 🔴 (18:00) User provided source content from repository path `/home/byk/Code/getsentry/publish-root-location-bootstrap/src/publish/__tests__/discover-location.js`. * 🔴 (18:00) User provided source content from repository p…
Date: Sep 8, 2026 * 🔴 (17:59) User stated that Jujutsu (`jj`) never fails on conflict; conflicts are recorded in the resulting commit and must be checked with `jj st` and resolved manually rather than using interactive `jj resolve`. * 🔴 (17:59) User stated repository change `4da4a25` is `chore: replace deprecated trimRight() with trimEnd() (#9012)`. * 🟡 (17:59) Read-only environment check foun…
Date: Sep 8, 2026 * 🔴 [requested-code-review] (17:59) User requested a read-only adversarial review of the current uncommitted hotfix in `/home/byk/Code/getsentry/publish-root-location-bootstrap`; instructed not to edit files and to run read-only checks only. * 🟡 (17:59) User requested review of the complete diff and relevant resolver/workflow behavior, verifying: root path `'.'` cannot be a wo…