@brainervirus/workit-pi 8.14.1 → 8.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/worker.js CHANGED
@@ -8546,20 +8546,19 @@ var workspaceConfigSchema = object({
8546
8546
  union([boolean2(), literal("verified")]).optional()
8547
8547
  ]))).passthrough().optional(),
8548
8548
  youtrack: object({ baseUrl: nonBlank.optional(), link_issues: boolean2().optional() }).passthrough().optional(),
8549
- issues: object({ provider: literal("github").optional(), link_on_pr: boolean2().optional() }).passthrough().optional(),
8549
+ issues: object({
8550
+ provider: _enum(["github", "gitlab", "youtrack"]).optional(),
8551
+ link: boolean2().optional(),
8552
+ relation: unknown().optional(),
8553
+ backlink: boolean2().optional(),
8554
+ link_on_pr: boolean2().optional()
8555
+ }).passthrough().optional(),
8550
8556
  branchPolicy: workspaceBranchPolicySchema.optional(),
8551
8557
  commitPolicy: workspaceCommitPolicySchema.optional(),
8552
8558
  defaultProfile: nonBlank.optional(),
8553
8559
  profiles: record(nonBlank, workspaceProfileSchema).optional(),
8554
8560
  releaseTracks: record(nonBlank, releaseTrackSchema).optional()
8555
8561
  }).passthrough().superRefine((workspace, context) => {
8556
- if (workspace.issues && workspace.vcs?.provider !== "github") {
8557
- context.addIssue({
8558
- code: "custom",
8559
- path: ["issues"],
8560
- message: `GitHub issue linking requires the github provider, got ${workspace.vcs?.provider ?? "unset"}`
8561
- });
8562
- }
8563
8562
  if (workspace.defaultProfile !== undefined && !Object.hasOwn(workspace.profiles ?? {}, workspace.defaultProfile)) {
8564
8563
  context.addIssue({
8565
8564
  code: "custom",
@@ -8613,11 +8612,19 @@ var KNOWN_FIELDS = new Set([
8613
8612
  ]);
8614
8613
  var memo2 = new Map;
8615
8614
 
8615
+ // packages/workit-core/src/core/vcs-config.ts
8616
+ var TRACKERS = new Set(["github", "gitlab", "youtrack"]);
8617
+
8616
8618
  // packages/workit-core/src/ledger.ts
8617
8619
  var PASSING = new Set(["verified", "tests-verified", "type-check-only"]);
8618
8620
  var FAILING = new Set(["failed", "blocked"]);
8619
8621
  var STRONG_RESULTS = new Set(["verified", "tests-verified"]);
8620
- var PR_ROW_TYPES = new Set(["pr.created", "pr.status", "pr.merged"]);
8622
+ var PR_ROW_TYPES = new Set([
8623
+ "pr.created",
8624
+ "pr.status",
8625
+ "pr.merged",
8626
+ "pr.linked"
8627
+ ]);
8621
8628
  var NETWORK_FS_TYPES = new Set([
8622
8629
  26985,
8623
8630
  20859,
package/dist/workit.js CHANGED
@@ -10034,7 +10034,7 @@ var removeIfEmpty = (dir) => {
10034
10034
  };
10035
10035
  var tokenHash = (token) => createHash3("sha256").update(token).digest("hex");
10036
10036
  function recordIssuedSession(cwd, lead, issued) {
10037
- const token = randomBytes2(18).toString("base64url");
10037
+ const token = randomBytes2(18).toString("hex");
10038
10038
  try {
10039
10039
  migrateRepoIssued(cwd);
10040
10040
  const own = hash(issued);
@@ -13192,20 +13192,19 @@ var workspaceConfigSchema = object({
13192
13192
  union([boolean2(), literal("verified")]).optional()
13193
13193
  ]))).passthrough().optional(),
13194
13194
  youtrack: object({ baseUrl: nonBlank.optional(), link_issues: boolean2().optional() }).passthrough().optional(),
13195
- issues: object({ provider: literal("github").optional(), link_on_pr: boolean2().optional() }).passthrough().optional(),
13195
+ issues: object({
13196
+ provider: _enum(["github", "gitlab", "youtrack"]).optional(),
13197
+ link: boolean2().optional(),
13198
+ relation: unknown().optional(),
13199
+ backlink: boolean2().optional(),
13200
+ link_on_pr: boolean2().optional()
13201
+ }).passthrough().optional(),
13196
13202
  branchPolicy: workspaceBranchPolicySchema.optional(),
13197
13203
  commitPolicy: workspaceCommitPolicySchema.optional(),
13198
13204
  defaultProfile: nonBlank.optional(),
13199
13205
  profiles: record(nonBlank, workspaceProfileSchema).optional(),
13200
13206
  releaseTracks: record(nonBlank, releaseTrackSchema).optional()
13201
13207
  }).passthrough().superRefine((workspace, context) => {
13202
- if (workspace.issues && workspace.vcs?.provider !== "github") {
13203
- context.addIssue({
13204
- code: "custom",
13205
- path: ["issues"],
13206
- message: `GitHub issue linking requires the github provider, got ${workspace.vcs?.provider ?? "unset"}`
13207
- });
13208
- }
13209
13208
  if (workspace.defaultProfile !== undefined && !Object.hasOwn(workspace.profiles ?? {}, workspace.defaultProfile)) {
13210
13209
  context.addIssue({
13211
13210
  code: "custom",
@@ -14080,6 +14079,44 @@ var readVcsConfig = () => {
14080
14079
  }
14081
14080
  return { status: "malformed", path: file, config: {}, error: `${file} is not a JSON object` };
14082
14081
  };
14082
+ var TRACKERS = new Set(["github", "gitlab", "youtrack"]);
14083
+ var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
14084
+ var flag = (value) => typeof value === "boolean" ? value : null;
14085
+ var text2 = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
14086
+ function issueTrackerOf(issues, youtrack) {
14087
+ const iss = asRecord(issues);
14088
+ const yt = asRecord(youtrack);
14089
+ const warnings = [];
14090
+ const named = typeof iss.provider === "string" && TRACKERS.has(iss.provider.toLowerCase()) ? iss.provider.toLowerCase() : null;
14091
+ if (iss.relation !== undefined && iss.relation !== "closes" && iss.relation !== "refs")
14092
+ warnings.push(`issues.relation ${JSON.stringify(iss.relation)} is not closes or refs; read as closes`);
14093
+ for (const key of ["repo", "host"])
14094
+ if (iss[key] !== undefined && text2(iss[key]) === null)
14095
+ warnings.push(`issues.${key} is not a non-empty string; ignored`);
14096
+ const common = {
14097
+ relation: iss.relation === "refs" ? "refs" : "closes",
14098
+ backlink: iss.backlink === true,
14099
+ baseUrl: text2(yt.baseUrl),
14100
+ repo: text2(iss.repo)?.replace(/^\/+|\/+$/gu, "") ?? null,
14101
+ host: text2(iss.host)?.toLowerCase() ?? null,
14102
+ warnings
14103
+ };
14104
+ const legacyGithub = named === "github" && flag(iss.link) === null;
14105
+ if (flag(yt.link_issues) === true && (named === null || legacyGithub))
14106
+ return { provider: "youtrack", link: true, ...common, source: "youtrack.link_issues" };
14107
+ if (named) {
14108
+ const link = flag(iss.link) ?? flag(iss.link_on_pr) ?? (named === "youtrack" ? flag(yt.link_issues) : null) ?? false;
14109
+ return {
14110
+ provider: named,
14111
+ link,
14112
+ ...common,
14113
+ source: flag(iss.link) === null && flag(iss.link_on_pr) !== null ? "issues.link_on_pr" : "issues"
14114
+ };
14115
+ }
14116
+ if (common.baseUrl)
14117
+ return { provider: "youtrack", link: false, ...common, source: "youtrack.baseUrl" };
14118
+ return null;
14119
+ }
14083
14120
  var trackSummary = (resolution) => resolution.status === "resolved" ? {
14084
14121
  name: resolution.track?.name ?? null,
14085
14122
  source: resolution.source,
@@ -14100,6 +14137,7 @@ function vcsConfig(mode, cwd, options = {}) {
14100
14137
  const rawProvider = wsVcs.provider ?? (determinateRoot ? remoteProvider(root) : null) ?? cfg.provider ?? null;
14101
14138
  const provider = rawProvider === null || rawProvider === undefined ? null : String(rawProvider).toLowerCase() || null;
14102
14139
  const workspaceDefault = workspaceDefaultTarget(root, cfg.defaultTargetBranch);
14140
+ const issueTracker = issueTrackerOf(wsIssues, wsYt);
14103
14141
  const linkIssues = typeof wsYt.link_issues === "boolean" ? wsYt.link_issues : null;
14104
14142
  const youtrackBaseUrl = typeof wsYt.baseUrl === "string" ? wsYt.baseUrl : null;
14105
14143
  let issuesProvider = null;
@@ -14132,7 +14170,8 @@ function vcsConfig(mode, cwd, options = {}) {
14132
14170
  link_issues: linkIssues,
14133
14171
  youtrack_base_url: youtrackBaseUrl,
14134
14172
  issues_provider: issuesProvider,
14135
- link_on_pr: linkOnPr
14173
+ link_on_pr: linkOnPr,
14174
+ issue_tracker: issueTracker
14136
14175
  };
14137
14176
  }
14138
14177
  if (cfgStatus === "malformed") {
@@ -14158,7 +14197,8 @@ function vcsConfig(mode, cwd, options = {}) {
14158
14197
  link_issues: linkIssues,
14159
14198
  youtrack_base_url: youtrackBaseUrl,
14160
14199
  issues_provider: issuesProvider,
14161
- link_on_pr: linkOnPr
14200
+ link_on_pr: linkOnPr,
14201
+ issue_tracker: issueTracker
14162
14202
  };
14163
14203
  if (provider === "gitlab") {
14164
14204
  out.gitlab = {
@@ -14262,7 +14302,12 @@ var MAX_LINE_BYTES = 4096;
14262
14302
  var PASSING = new Set(["verified", "tests-verified", "type-check-only"]);
14263
14303
  var FAILING = new Set(["failed", "blocked"]);
14264
14304
  var STRONG_RESULTS = new Set(["verified", "tests-verified"]);
14265
- var PR_ROW_TYPES = new Set(["pr.created", "pr.status", "pr.merged"]);
14305
+ var PR_ROW_TYPES = new Set([
14306
+ "pr.created",
14307
+ "pr.status",
14308
+ "pr.merged",
14309
+ "pr.linked"
14310
+ ]);
14266
14311
  var err = (code, error, unblock) => ({
14267
14312
  ok: false,
14268
14313
  code,
@@ -18590,7 +18635,7 @@ var RISK = {
18590
18635
  };
18591
18636
  var YES = new Set(["true", "yes", "y", "1", "on"]);
18592
18637
  var NO = new Set(["false", "no", "n", "0", "off", "none"]);
18593
- var flag = (value, unknownAs) => {
18638
+ var flag2 = (value, unknownAs) => {
18594
18639
  if (typeof value === "boolean")
18595
18640
  return { ok: true, value };
18596
18641
  if (typeof value === "number" && (value === 0 || value === 1))
@@ -18656,12 +18701,12 @@ function normalizeJudgment(raw, previous) {
18656
18701
  const items = Array.isArray(value) ? value : [value];
18657
18702
  judgment.refs.push(...items.filter((item) => item !== null && item !== "").map(refOf));
18658
18703
  } else {
18659
- if (name === "needsPlan" && typeof value === "string" && !flag(value, false).ok && value.trim()) {
18704
+ if (name === "needsPlan" && typeof value === "string" && !flag2(value, false).ok && value.trim()) {
18660
18705
  judgment.needsPlan = true;
18661
18706
  judgment.refs.push(refOf(value.trim()));
18662
18707
  continue;
18663
18708
  }
18664
- const parsed = flag(value, name === "behaviorChange");
18709
+ const parsed = flag2(value, name === "behaviorChange");
18665
18710
  if (parsed.ok)
18666
18711
  judgment[name] = parsed.value;
18667
18712
  else
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-pi",
3
- "version": "8.14.1",
3
+ "version": "8.15.0",
4
4
  "description": "Workit native extension for Pi — tools, method skills, and session continuity",
5
5
  "keywords": [
6
6
  "agentic-coding",
@@ -33,8 +33,8 @@ that repeats because the base keeps moving, or after 3 failed fix attempts on
33
33
  the same check.
34
34
 
35
35
  1. **Open.** `workit git push`, then `workit pr create --title "<title>"
36
- --body-file <f|->` (idempotent; body: `references/pr-body.md`; edits:
37
- `workit pr edit`). A stack: `workit stack plan <bottom> ... <top>`, one
36
+ --body-file <f|->` plus `--issue <#n|ID>` per issue (`--refs`: no close; idempotent;
37
+ body: `references/pr-body.md`; edits: `workit pr edit`). A stack: `workit stack plan <bottom> ... <top>`, one
38
38
  `workit pr create --base <parent> --fill` per branch, then
39
39
  `workit stack sync`. Finish the whole stack before babysitting any PR.
40
40
  2. **Read state** with `workit pr status --json`. `REVIEW` alone is a pending