okstra 0.222.0 → 0.223.2

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.
Files changed (28) hide show
  1. package/dist/commands/pr/pr.d.mts +2 -0
  2. package/dist/commands/pr/pr.mjs +12 -3
  3. package/dist/commands/pr/pr.mjs.map +1 -1
  4. package/docs/architecture.md +1 -1
  5. package/docs/cli.md +1 -1
  6. package/package.json +1 -1
  7. package/runtime/BUILD.json +2 -2
  8. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  9. package/runtime/python/okstra_ctl/analysis_packet.py +8 -6
  10. package/runtime/python/okstra_ctl/phases/implementation/spec.md +1 -1
  11. package/runtime/python/okstra_ctl/phases/release_handoff/entry.py +42 -1
  12. package/runtime/python/okstra_ctl/phases/release_handoff/operations.py +52 -0
  13. package/runtime/python/okstra_ctl/phases/release_handoff/profile.md +3 -2
  14. package/runtime/python/okstra_ctl/phases/release_handoff/report_assets/release-handoff-input.template.md +3 -1
  15. package/runtime/python/okstra_ctl/phases/release_handoff/spec.md +2 -2
  16. package/runtime/python/okstra_ctl/report_finalize.py +8 -3
  17. package/runtime/python/okstra_ctl/report_projections.py +1 -0
  18. package/runtime/python/okstra_ctl/run.py +4 -0
  19. package/runtime/python/okstra_ctl/stage_fix_carry.py +118 -16
  20. package/runtime/python/okstra_ctl/stage_rebase.py +3 -0
  21. package/runtime/python/okstra_ctl/worktree/decisions.py +42 -5
  22. package/runtime/python/okstra_ctl/worktree/provision.py +49 -2
  23. package/runtime/python/okstra_ctl/worktree/rebase.py +11 -1
  24. package/runtime/schemas/final-report-v2.0.schema.json +7 -2
  25. package/runtime/schemas/final-report-v3.0.schema.json +7 -2
  26. package/runtime/skills/okstra-pr-gen/SKILL.md +2 -2
  27. package/runtime/templates/pr/drafting-rules.md +11 -4
  28. package/runtime/validators/validate-run.py +5 -4
@@ -13,6 +13,8 @@ interface GenerationBundle {
13
13
  readonly base: string;
14
14
  readonly head: string;
15
15
  readonly currentBranch: string | null;
16
+ readonly upstream: string | null;
17
+ readonly mergeBase: string;
16
18
  readonly templateName: string;
17
19
  readonly template: string;
18
20
  readonly commits: readonly CommitSummary[];
@@ -234,8 +234,14 @@ export async function buildGenBundle({ cwd, home, base, head = "HEAD", templateN
234
234
  throw new Error(`head ref not found: ${head}`);
235
235
  }
236
236
  const currentBranch = tryGit(cwd, ["rev-parse", "--abbrev-ref", "HEAD"]);
237
+ // 로컬 base 가 원격보다 뒤처지면 원격에 이미 병합된 변경이 이 브랜치 작업으로 잡힌다.
238
+ const upstream = tryGit(cwd, ["rev-parse", "--abbrev-ref", "--symbolic-full-name", `${base}@{upstream}`]);
239
+ const baseRefs = upstream ? [base, upstream] : [base];
240
+ const mergeBase = tryGit(cwd, ["merge-base", head, ...baseRefs]);
241
+ if (mergeBase === null)
242
+ throw new Error(`no common ancestor with base: ${base}`);
237
243
  const logRaw = tryGit(cwd, [
238
- "log", "--reverse", "--format=%h%x09%s", `${base}..${head}`,
244
+ "log", "--reverse", "--format=%h%x09%s", head, "--not", ...baseRefs,
239
245
  ]) || "";
240
246
  const commits = logRaw
241
247
  .split("\n")
@@ -244,7 +250,7 @@ export async function buildGenBundle({ cwd, home, base, head = "HEAD", templateN
244
250
  const tab = line.indexOf("\t");
245
251
  return { hash: line.slice(0, tab), subject: line.slice(tab + 1) };
246
252
  });
247
- const diffStat = tryGit(cwd, ["diff", "--stat", `${base}...${head}`]) || "";
253
+ const diffStat = tryGit(cwd, ["diff", "--stat", mergeBase, head]) || "";
248
254
  const template = templateFile
249
255
  ? await fs.readFile(resolve(cwd, templateFile), "utf8")
250
256
  : await readTemplate(home, templateName);
@@ -253,7 +259,8 @@ export async function buildGenBundle({ cwd, home, base, head = "HEAD", templateN
253
259
  : templateName && templateName !== "default" ? templateName : "default";
254
260
  const draftingRules = await fs.readFile(DRAFTING_RULES_PATH, "utf8");
255
261
  return {
256
- base, head, currentBranch, templateName: resolvedName, template, commits, diffStat, draftingRules,
262
+ base, head, currentBranch, upstream, mergeBase, templateName: resolvedName, template, commits,
263
+ diffStat, draftingRules,
257
264
  };
258
265
  }
259
266
  export function renderGenerationBundle(bundle) {
@@ -265,6 +272,8 @@ export function renderGenerationBundle(bundle) {
265
272
  `Base: ${bundle.base}`,
266
273
  `Head: ${bundle.head}`,
267
274
  `Current branch: ${bundle.currentBranch ?? "-"}`,
275
+ `Upstream: ${bundle.upstream ?? "-"}`,
276
+ `Merge base: ${bundle.mergeBase}`,
268
277
  `Template name: ${bundle.templateName}`,
269
278
  "Commits:",
270
279
  commits,
@@ -1 +1 @@
1
- {"version":3,"file":"pr.mjs","sourceRoot":"","sources":["../../../src/commands/pr/pr.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,IAAI,KAAK,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAkCvD,MAAM,OAAO,GAAG,mBAAmB,CAAC;AACpC,gGAAgG;AAChG,0DAA0D;AAC1D,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;AAC7E,MAAM,qBAAqB,GAAG,IAAI,CAAC,eAAe,EAAE,qBAAqB,CAAC,CAAC;AAC3E,MAAM,mBAAmB,GAAG,IAAI,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;AAEvE,MAAM,KAAK,GAAG;;;;;;;;;;CAUb,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,CACL,OAAO,IAAI,KAAK,QAAQ;QACxB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAClB,IAAI,KAAK,GAAG;QACZ,IAAI,KAAK,IAAI,CACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACjG,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;SAC1B,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,KAAK,UAAU,kBAAkB;IAC/B,OAAO,EAAE,CAAC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,IAAwB;IACvE,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,kBAAkB,EAAE,CAAC;IAC7D,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;IAClF,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,kBAAkB,EAAE,CAAC;QACnH,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY,EACZ,IAAY,EACZ,OAAe,EACf,IAAI,GAAoB,EAAE;IAE1B,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;IAClF,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,2BAA2B,CAAC,CAAC;QACvE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC;gBAAE,MAAM,GAAG,CAAC;QACtG,CAAC;IACH,CAAC;IACD,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAAC,IAAuB,EAAE,CAAS,EAAE,IAAY;IACjE,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,mBAAmB,CAAC,CAAC;IAC1E,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAwB;IACpD,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC;IAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;IACvE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;AAC/D,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,QAAgB;IACrC,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC9E,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,KAAK,CAAC;IAC5C,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,IAAuB,EAAE,IAAY;IAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,IAAI;YAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;;YAC/D,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;QAC/E,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACvC,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,MAAM,IAAI,GAAuB,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QACvF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,IAAI,KAAK,QAAQ;gBAAE,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;iBACzD,IAAI,IAAI,KAAK,WAAW;gBAAE,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;iBACpE,IAAI,IAAI,KAAK,QAAQ;gBAAE,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;iBAC9D,IAAI,IAAI,KAAK,OAAO;gBAAE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;;gBACtC,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;QAC5C,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC;QACrB,IAAI,CAAC,KAAK,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7C,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACxB,MAAM,GAAG,IAAI,CAAC;YAChB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC;oBAAE,MAAM,GAAG,CAAC;YACtG,CAAC;YACD,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;oBACzB,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,IAAI,2BAA2B,CAAC,CAAC;gBAC5E,CAAC;gBACD,KAAK,GAAG,MAAM,OAAO,CAAC,+BAA+B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;gBACnE,IAAI,CAAC,KAAK,EAAE,CAAC;oBAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;oBAAC,OAAO,CAAC,CAAC;gBAAC,CAAC;YACtD,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3E,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC;QAClC,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,IAAI,QAAQ,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,MAAM,CAAC,GAAW,EAAE,IAAuB;IAClD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IACzE,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IAC5E,MAAM,OAAO,GAAG,EAAE,CAAC;IACnB,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,SAAS,EAAE,0BAA0B,CAAC,CAAC,CAAC;IAC3F,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,KAAK,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAClG,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,aAAa,WAAW,CAAC,CAAC,KAAK,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAChI,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC;QAClF,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,EAAE;QACzB,cAAc,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,YAAY;KACnF,CAAC,CAAC;IACH,IAAI,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,KAAK,aAAa,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,WAAW,CAAC,IAAuB,EAAE,GAAW;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,IAAI;QAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;;QAC5C,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,GAAG,IAAI,CAAC,CAAC;IACxE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EACnC,GAAG,EACH,IAAI,EACJ,IAAI,EACJ,IAAI,GAAG,MAAM,EACb,YAAY,EACZ,YAAY,GAQb;IACC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC;IACvF,IAAI,QAAQ,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACtE,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,EAAE;QACzB,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,GAAG,IAAI,KAAK,IAAI,EAAE;KAC5D,CAAC,IAAI,EAAE,CAAC;IACT,MAAM,OAAO,GAAG,MAAM;SACnB,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;IACpE,CAAC,CAAC,CAAC;IACL,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5E,MAAM,QAAQ,GAAG,YAAY;QAC3B,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QACvD,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,YAAY;QAC/B,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC;QAC5B,CAAC,CAAC,YAAY,IAAI,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;IACrE,OAAO;QACL,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa;KAClG,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAwB;IAC7D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM;QACnC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACjF,CAAC,CAAC,GAAG,CAAC;IACR,OAAO;QACL,sBAAsB;QACtB,SAAS,MAAM,CAAC,IAAI,EAAE;QACtB,SAAS,MAAM,CAAC,IAAI,EAAE;QACtB,mBAAmB,MAAM,CAAC,aAAa,IAAI,GAAG,EAAE;QAChD,kBAAkB,MAAM,CAAC,YAAY,EAAE;QACvC,UAAU;QACV,OAAO;QACP,YAAY;QACZ,MAAM,CAAC,QAAQ,IAAI,GAAG;QACtB,WAAW;QACX,MAAM,CAAC,QAAQ;QACf,iBAAiB;QACjB,MAAM,CAAC,aAAa;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAQD,oFAAoF;AACpF,MAAM,0BAA0B,GAA8D;IAC5F,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,yDAAyD,EAAE;IACzF,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,uBAAuB,EAAE;IACpD,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,8CAA8C,EAAE;IAC5E;QACE,IAAI,EAAE,aAAa;QACnB,EAAE,EAAE,2IAA2I;KAChJ;IACD,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,yCAAyC,EAAE;IACtE,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,6EAA6E,EAAE;CAC5G,CAAC;AAEF,mGAAmG;AACnG,kGAAkG;AAClG,SAAS,gBAAgB,CAAC,GAAW,EAAE,IAAY;IACjD,OAAO,MAAM,CAAC,GAAG,EAAE;QACjB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc;KAChG,CAAC,KAAK,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,IAAY,EACZ,UAAqC;IAErC,MAAM,IAAI,GAAc,EAAE,CAAC;IAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACvC,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,0BAA0B,EAAE,CAAC;YACtD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;gBAClC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpF,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,IAAuB,EAAE,GAAW;IAC1D,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,IAAI,KAAK,aAAa;YAAE,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aAC7D,IAAI,IAAI,KAAK,QAAQ;YAAE,SAAS;;YAChC,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,QAAQ,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,qBAAqB,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAChF,IAAI,IAAI;QAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;SACnD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;;QAC/C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7F,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAuB,EAAE,GAAW,EAAE,IAAY;IACtE,MAAM,IAAI,GAAgG;QACxG,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;KACnB,CAAC;IACF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,IAAI,KAAK,QAAQ;YAAE,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aACzD,IAAI,IAAI,KAAK,QAAQ;YAAE,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aAC9D,IAAI,IAAI,KAAK,YAAY;YAAE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aACtE,IAAI,IAAI,KAAK,iBAAiB;YAAE,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aAC/E,IAAI,IAAI,KAAK,QAAQ;YAAE,SAAS;;YAChC,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC/D,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,GAAG;QACH,IAAI;QACJ,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,YAAY,EAAE,IAAI,CAAC,QAAQ,IAAI,SAAS;QACxC,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,SAAS;KAC7C,CAAC,CAAC;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IACpF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAuB;IAC/C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC;QACH,IAAI,GAAG,KAAK,UAAU;YAAE,OAAO,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC7D,IAAI,GAAG,KAAK,UAAU;YAAE,OAAO,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAChE,IAAI,GAAG,KAAK,KAAK;YAAE,OAAO,MAAM,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;QAClE,IAAI,GAAG,KAAK,OAAO;YAAE,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,OAAO,IAAI,CAAC,CAAC;QAC5C,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"pr.mjs","sourceRoot":"","sources":["../../../src/commands/pr/pr.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,IAAI,KAAK,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAoCvD,MAAM,OAAO,GAAG,mBAAmB,CAAC;AACpC,gGAAgG;AAChG,0DAA0D;AAC1D,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;AAC7E,MAAM,qBAAqB,GAAG,IAAI,CAAC,eAAe,EAAE,qBAAqB,CAAC,CAAC;AAC3E,MAAM,mBAAmB,GAAG,IAAI,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;AAEvE,MAAM,KAAK,GAAG;;;;;;;;;;CAUb,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,CACL,OAAO,IAAI,KAAK,QAAQ;QACxB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAClB,IAAI,KAAK,GAAG;QACZ,IAAI,KAAK,IAAI,CACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACjG,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;SAC1B,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,KAAK,UAAU,kBAAkB;IAC/B,OAAO,EAAE,CAAC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,IAAwB;IACvE,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,kBAAkB,EAAE,CAAC;IAC7D,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;IAClF,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,kBAAkB,EAAE,CAAC;QACnH,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY,EACZ,IAAY,EACZ,OAAe,EACf,IAAI,GAAoB,EAAE;IAE1B,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;IAClF,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,2BAA2B,CAAC,CAAC;QACvE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC;gBAAE,MAAM,GAAG,CAAC;QACtG,CAAC;IACH,CAAC;IACD,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAAC,IAAuB,EAAE,CAAS,EAAE,IAAY;IACjE,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,mBAAmB,CAAC,CAAC;IAC1E,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAwB;IACpD,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC;IAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;IACvE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;AAC/D,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,QAAgB;IACrC,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC9E,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,KAAK,CAAC;IAC5C,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,IAAuB,EAAE,IAAY;IAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,IAAI;YAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;;YAC/D,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;QAC/E,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACvC,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,MAAM,IAAI,GAAuB,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QACvF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,IAAI,KAAK,QAAQ;gBAAE,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;iBACzD,IAAI,IAAI,KAAK,WAAW;gBAAE,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;iBACpE,IAAI,IAAI,KAAK,QAAQ;gBAAE,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;iBAC9D,IAAI,IAAI,KAAK,OAAO;gBAAE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;;gBACtC,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;QAC5C,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC;QACrB,IAAI,CAAC,KAAK,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7C,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACxB,MAAM,GAAG,IAAI,CAAC;YAChB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC;oBAAE,MAAM,GAAG,CAAC;YACtG,CAAC;YACD,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;oBACzB,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,IAAI,2BAA2B,CAAC,CAAC;gBAC5E,CAAC;gBACD,KAAK,GAAG,MAAM,OAAO,CAAC,+BAA+B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;gBACnE,IAAI,CAAC,KAAK,EAAE,CAAC;oBAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;oBAAC,OAAO,CAAC,CAAC;gBAAC,CAAC;YACtD,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3E,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC;QAClC,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,IAAI,QAAQ,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,MAAM,CAAC,GAAW,EAAE,IAAuB;IAClD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IACzE,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IAC5E,MAAM,OAAO,GAAG,EAAE,CAAC;IACnB,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,SAAS,EAAE,0BAA0B,CAAC,CAAC,CAAC;IAC3F,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,KAAK,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAClG,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,aAAa,WAAW,CAAC,CAAC,KAAK,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAChI,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC;QAClF,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,EAAE;QACzB,cAAc,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,YAAY;KACnF,CAAC,CAAC;IACH,IAAI,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,KAAK,aAAa,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,WAAW,CAAC,IAAuB,EAAE,GAAW;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,IAAI;QAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;;QAC5C,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,GAAG,IAAI,CAAC,CAAC;IACxE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EACnC,GAAG,EACH,IAAI,EACJ,IAAI,EACJ,IAAI,GAAG,MAAM,EACb,YAAY,EACZ,YAAY,GAQb;IACC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC;IACvF,IAAI,QAAQ,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACtE,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IACzE,qDAAqD;IACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,sBAAsB,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC,CAAC;IAC1G,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,YAAY,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;IACjE,IAAI,SAAS,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAC;IACjF,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,EAAE;QACzB,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,QAAQ;KACpE,CAAC,IAAI,EAAE,CAAC;IACT,MAAM,OAAO,GAAG,MAAM;SACnB,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;IACpE,CAAC,CAAC,CAAC;IACL,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACxE,MAAM,QAAQ,GAAG,YAAY;QAC3B,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QACvD,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,YAAY;QAC/B,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC;QAC5B,CAAC,CAAC,YAAY,IAAI,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;IACrE,OAAO;QACL,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO;QAC7F,QAAQ,EAAE,aAAa;KACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAwB;IAC7D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM;QACnC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACjF,CAAC,CAAC,GAAG,CAAC;IACR,OAAO;QACL,sBAAsB;QACtB,SAAS,MAAM,CAAC,IAAI,EAAE;QACtB,SAAS,MAAM,CAAC,IAAI,EAAE;QACtB,mBAAmB,MAAM,CAAC,aAAa,IAAI,GAAG,EAAE;QAChD,aAAa,MAAM,CAAC,QAAQ,IAAI,GAAG,EAAE;QACrC,eAAe,MAAM,CAAC,SAAS,EAAE;QACjC,kBAAkB,MAAM,CAAC,YAAY,EAAE;QACvC,UAAU;QACV,OAAO;QACP,YAAY;QACZ,MAAM,CAAC,QAAQ,IAAI,GAAG;QACtB,WAAW;QACX,MAAM,CAAC,QAAQ;QACf,iBAAiB;QACjB,MAAM,CAAC,aAAa;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAQD,oFAAoF;AACpF,MAAM,0BAA0B,GAA8D;IAC5F,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,yDAAyD,EAAE;IACzF,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,uBAAuB,EAAE;IACpD,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,8CAA8C,EAAE;IAC5E;QACE,IAAI,EAAE,aAAa;QACnB,EAAE,EAAE,2IAA2I;KAChJ;IACD,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,yCAAyC,EAAE;IACtE,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,6EAA6E,EAAE;CAC5G,CAAC;AAEF,mGAAmG;AACnG,kGAAkG;AAClG,SAAS,gBAAgB,CAAC,GAAW,EAAE,IAAY;IACjD,OAAO,MAAM,CAAC,GAAG,EAAE;QACjB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc;KAChG,CAAC,KAAK,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,IAAY,EACZ,UAAqC;IAErC,MAAM,IAAI,GAAc,EAAE,CAAC;IAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACvC,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,0BAA0B,EAAE,CAAC;YACtD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;gBAClC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpF,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,IAAuB,EAAE,GAAW;IAC1D,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,IAAI,KAAK,aAAa;YAAE,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aAC7D,IAAI,IAAI,KAAK,QAAQ;YAAE,SAAS;;YAChC,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,QAAQ,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,qBAAqB,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAChF,IAAI,IAAI;QAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;SACnD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;;QAC/C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7F,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAuB,EAAE,GAAW,EAAE,IAAY;IACtE,MAAM,IAAI,GAAgG;QACxG,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;KACnB,CAAC;IACF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,IAAI,KAAK,QAAQ;YAAE,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aACzD,IAAI,IAAI,KAAK,QAAQ;YAAE,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aAC9D,IAAI,IAAI,KAAK,YAAY;YAAE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aACtE,IAAI,IAAI,KAAK,iBAAiB;YAAE,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aAC/E,IAAI,IAAI,KAAK,QAAQ;YAAE,SAAS;;YAChC,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC/D,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,GAAG;QACH,IAAI;QACJ,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,YAAY,EAAE,IAAI,CAAC,QAAQ,IAAI,SAAS;QACxC,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,SAAS;KAC7C,CAAC,CAAC;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IACpF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAuB;IAC/C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC;QACH,IAAI,GAAG,KAAK,UAAU;YAAE,OAAO,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC7D,IAAI,GAAG,KAAK,UAAU;YAAE,OAAO,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAChE,IAAI,GAAG,KAAK,KAAK;YAAE,OAAO,MAAM,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;QAClE,IAAI,GAAG,KAAK,OAAO;YAAE,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,OAAO,IAAI,CAAC,CAAC;QAC5C,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
@@ -517,7 +517,7 @@ The PR base follows the stage's `depends-on`, after dropping predecessors alread
517
517
  | one | that stage's branch — a stacked PR | no |
518
518
  | several | a branch merging their recorded `done.head_commit`s, named `<work-category-namespace>/<task-id-segment>-g<n1>-<n2>` | yes, by `pr-plan` |
519
519
 
520
- A merge-base branch combines independent predecessors and is a base only, never a PR head. When a predecessor advances, `okstra_ctl.stage_rebase` rebases downstream stage branches in dependency order instead of merging the moving base into them. Implementation entry, verification target acquisition, and PR planning share this operation. Old heads are preserved under `refs/okstra/rebase-backups/`; registry bases and completion commits are updated, invalidating previous verification. PR planning stops after a stack change for fresh final-verification. Conflicts abort the current rebase, and dirty or active stages stop synchronization. A published branch that diverges from origin needs explicit delivery instructions; merging old origin history back into it is not recovery. Merge PRs in dependency order with a merge commit or rebase-merge; squashing replaces the commits the next PR's base points at.
520
+ This derivation covers stacking inside one task. The release base must contain the task's implementation anchor base: a task built on another task's unmerged stage branch takes that branch as its release base. Prepare names it as the recommended Q2 option in `release-handoff-input.md`, and `pr-plan` refuses a release base that lacks the anchor, because the PR would also carry the other task's commits. A merge-base branch combines independent predecessors and is a base only, never a PR head. When a predecessor advances, `okstra_ctl.stage_rebase` rebases downstream stage branches in dependency order instead of merging the moving base into them. Implementation entry, verification target acquisition, and PR planning share this operation. Old heads are preserved under `refs/okstra/rebase-backups/`; registry bases and completion commits are updated, invalidating previous verification. PR planning stops after a stack change for fresh final-verification. Conflicts abort the current rebase, and dirty or active stages stop synchronization. A published branch that diverges from origin needs explicit delivery instructions; merging old origin history back into it is not recovery. Merge PRs in dependency order with a merge commit or rebase-merge; squashing replaces the commits the next PR's base points at.
521
521
 
522
522
  Entry is based on **task ID**, without a brief. Briefs are inputs to entry phases; for release-handoff, prepare determines eligibility from the approved plan's Stage Map + Stage Lifecycle Snapshot, then automatically creates an input document (`<task_root>/release-handoff-input.md`) that cites the verification reports. Stage selection comes from the okstra-run wizard's `handoff_stage_pick` multiselect or CLI `--stages <csv>`; an empty selection takes every eligible stage, and the result is exposed to the lead as `HANDOFF_STAGES` in run-context.
523
523
 
package/docs/cli.md CHANGED
@@ -885,7 +885,7 @@ The `okstra` Node CLI (`bin/okstra`) provides both installer/admin commands and
885
885
  | `okstra recap <assemble\|record\|note> (<task-root\|task-key> \| --task-group <group>) …` | Backend for the okstra-inspect `recap` facet. `assemble` is read-only: for a task it prints a JSON summary of phase transitions across its runs; with `--task-group` it prints the group's start order (briefs in ordinal order, each `done` / `in progress` / `not started` from the catalog's task-manifests, memory entries only for tasks the catalog does not know) and every recorded task's latest conclusion from `group-context.md`'s Task Memory. `okstra model-io recap-input --task-group <group>` is the fixed-text projection of the same join. `record --kind <summary\|qa> --mode <artifact\|code> --answer <text> [--question <text>] [--citation <path:line> …]` appends one line to `<task-root>/recap/recap-log.jsonl`, or with `--task-group` to `.okstra/tasks/<group>/.recap/recap-log.jsonl`, and never mutates other artifacts. `note` is task-only. `note --kind <verification-evidence\|decision-draft\|analysis-note> --slug <topic> --purpose <text> --scope-note <text> (--body <markdown>\|--body-file <path>)` writes an agent-authored note to `<task-root>/notes/` and prints its path plus the `--clarification-response` argument for feeding it into a later run |
886
886
  | `okstra user-response <list-view\|show-view\|begin\|answer\|plan-decision\|legacy-report-authoring\|finalize> …` | Backend for the `/okstra-user-response` skill. `list-view` and `show-view --report <md\|data.json> --project-root <dir>` are fixed-text model views; `show-view` validates that the report belongs to the explicit project root and prints each open row's why-asked line, linked plan items, and cited `path:line` artifacts so the skill can read them before asking. The legacy `list` and `show` JSON reads retain their automation-compatible fields. `begin --report <md\|data.json> --task-key <key>` returns an opaque transaction id. A predefined clarification choice uses `answer --transaction <id> --clarification-id <C-NNN> --kind <kind> --option-number <N>`; Python resolves the answer, disposition, reach, and scope effects from the validated report. Direct input instead uses `--disposition <answer\|reframe> --value-file <md> [--rationale-file <md>]`. Every value, rationale, and reason file must be a regular file under `<PROJECT_ROOT>/.okstra/tmp/user-response/`; external paths and symbolic links are rejected. `plan-decision` accepts `approved`, `revision-requested`, or `rejected`, validates any `--implementation-option` against the report candidates, and requires `--reason-file` for the latter two statuses. `legacy-report-authoring` is restricted to report contract 2.0. `finalize` validates the complete existing sidecar before a lossless merge, uses compare-and-swap under a run-local lock, and atomically publishes only the user-owned sidecar; exit 0 ok / 1 error. |
887
887
  | `okstra option-comparison --report <data.json\|md>` | Read-only backend for the okstra-run comparison material. Prints one implementation-option-selection report's comparison facts as JSON: `criteria` (the eight evaluation criteria and their weights), `workers` (voting analysts in first-seen order), and per ranked direction `scores`, `scoreRationales`, the recorded `weightedScore` (publication already checks it against the recalculated value), `coverage` (verdict, counts, requirement ids), `safetyBlockers` and `unresolvedFeasibilityFacts` counts, and `votes` per worker (verdict, rationale, counterevidence); plus the report's `narrative` texts and `nextStep`, which is the next-phase pointer rationale. Exits 2 when the record has no `implementationOptionSelection` block or ranks no direction. |
888
- | `okstra pr <template\|branches\|gen> … [--json]` | Backend for the okstra-pr-gen skill. Git-only—no project registration required. `template list\|show <name\|default>\|add --name <name> (--content <text>\|--file <path>)\|path` manages PR body templates under `~/.okstra/template/pr/` (default `templates/pr/pr-body.template.md`, shared with release-handoff); `branches` recommends a base branch; `gen --base <ref> [--head <ref>] [--template <name\|default> \| --template-file <path>]` emits fixed `Base`, `Head`, `Current branch`, `Template name`, `Commits`, `Diff stat`, `Template`, and `Drafting rules` sections by default. `--head` reads a branch without checking it out. `check --body-file <path>` lists the lines of a drafted PR title/body that carry an okstra identifier (report ids, `.okstra/` paths, run artifact names, phase/stage/worker labels), skipping terms the repository's tracked files use; exit 1 when any is found. `--json` preserves the machine bundle for automation. |
888
+ | `okstra pr <template\|branches\|gen> … [--json]` | Backend for the okstra-pr-gen skill. Git-only—no project registration required. `template list\|show <name\|default>\|add --name <name> (--content <text>\|--file <path>)\|path` manages PR body templates under `~/.okstra/template/pr/` (default `templates/pr/pr-body.template.md`, shared with release-handoff); `branches` recommends a base branch; `gen --base <ref> [--head <ref>] [--template <name\|default> \| --template-file <path>]` emits fixed `Base`, `Head`, `Current branch`, `Upstream`, `Merge base`, `Template name`, `Commits`, `Diff stat`, `Template`, and `Drafting rules` sections by default. `--head` reads a branch without checking it out. Commits and diff stat exclude what the base or its upstream already contains. `check --body-file <path>` lists the lines of a drafted PR title/body that carry an okstra identifier (report ids, `.okstra/` paths, run artifact names, phase/stage/worker labels), skipping terms the repository's tracked files use; exit 1 when any is found. `--json` preserves the machine bundle for automation. |
889
889
  | `okstra migrate [--apply] [--cwd <dir>] [--quiet]` | One-time migration of the project artifact root from `.project-docs/okstra/` to `.okstra/`. It is a dry run by default; `--apply` performs the move with `git mv` in a Git worktree, removes an empty `.project-docs/`, and synchronizes the `<PROJECT>/CLAUDE.md` import line, `.gitignore`, the project's rows in `~/.okstra/{recent,active}.jsonl`, and `~/.okstra/worktrees/registry.json`. It exits 1 if `.okstra/` already exists or the legacy directory is absent. Scheduled for removal by the end of v0.x |
890
890
  | `okstra task-list [--project-root <path>]` | Combine `list_project_tasks` and `read_latest_task` into JSON containing the task catalog and latest task |
891
891
  | `okstra task-show <task-key> [--project-root <path>]` | Summarize workflow, phase, status, and artifacts from the Task Read-Side Snapshot |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.222.0",
3
+ "version": "0.223.2",
4
4
  "description": "Host-aware multi-provider cross-verification orchestrator runtime and agent skills.",
5
5
  "license": "MIT",
6
6
  "author": "devonshin",
@@ -1,5 +1,5 @@
1
1
  {
2
- "package": "0.222.0",
3
- "builtAt": "2026-10-21T15:15:40.772Z",
2
+ "package": "0.223.2",
3
+ "builtAt": "2026-10-22T08:47:32.015Z",
4
4
  "repoRoot": "/home/runner/work/okstra/okstra"
5
5
  }
@@ -178,7 +178,7 @@ Every `okstra` command the lead documents cite, grouped by phase, each spelled w
178
178
 
179
179
  | Command | Use when | Procedure |
180
180
  |---|---|---|
181
- | `okstra report-finalize --project-root <dir> --run-manifest <path> --report <path>` | Run the whole Phase 7 sequence; do not run its steps separately. Without `--only` it records `phase-7-persist` first; emit its `progressLines` | `report-writer` "Phase 6 → Phase 7 execution sequence" |
181
+ | `okstra report-finalize --project-root <dir> --run-manifest <path> [--report <path>]` | Run the whole Phase 7 sequence; do not run its steps separately. `--report` defaults to the manifest's `expectedReportRecordPath`. Without `--only` it records `phase-7-persist` first; emit its `progressLines` | `report-writer` "Phase 6 → Phase 7 execution sequence" |
182
182
  | `okstra handoff record-verified --plan-run-root <dir> --stage <N> --report-path <path> --data-json <path>` | Record an accepted final-verification against its stage. `report-finalize` runs it in its `record-verified` step; run it by hand only to repair a registry after that step failed | `report-writer` "Phase 6 → Phase 7 execution sequence" |
183
183
  | `okstra correction prompt --run-manifest <path> --round <N> --role <executor\|verifier> --base <sha> --stage-base <sha> --finding <F-id>` | Write a correction-round instruction body; materialize it with dispatch kind `correction-r<N>`. `--stage-base` adds the stage's 400-line file-size findings | `_implementation-deliverable.md` "Correction round" |
184
184
  | `okstra stage-done <task-key> --stage <N> --carry <carry.json> --report <path>` | Settle an implementation stage whose synthesised verdict is not FAIL: writes the flat `runs/implementation/carry/stage-<N>.json` sidecar and appends the `done` row — never write either by hand | `_implementation-deliverable.md` "Lead post-stage persistence" |
@@ -622,7 +622,7 @@ The detailed persistence sequence lives in [report-writer](./report-writer.md).
622
622
 
623
623
  Order of operations:
624
624
 
625
- 1. Run `okstra report-finalize ...`. Contract v3 collects usage, assembles the role-owned inputs into `data.json` once, renders views, persists follow-ups, validates the run, records this run's conclusion into the task-group's `group-context.md` for the group's sibling tasks, and performs eligible teardown in order. When the task's pointer is terminal and the group has a task not yet started, the result's `nextInGroup` names it and `nextCommand` closes on starting it from its brief — the group's start order is the brief ordinal; the briefs' Related Task Graph edges are quoted as `waits for` and do not reorder it.
625
+ 1. Run `okstra report-finalize --project-root <dir> --run-manifest <path>`. Contract v3 collects usage, assembles the role-owned inputs into `data.json` once, renders views, persists follow-ups, validates the run, records this run's conclusion into the task-group's `group-context.md` for the group's sibling tasks, and performs eligible teardown in order. When the task's pointer is terminal and the group has a task not yet started, the result's `nextInGroup` names it and `nextCommand` closes on starting it from its brief — the group's start order is the brief ordinal; the briefs' Related Task Graph edges are quoted as `waits for` and do not reorder it.
626
626
 
627
627
  Keep the assigned worker prompt history paths stable in `team-state`, `run-manifest`, and `task-manifest`. Do not rewrite prompt artifacts to `/tmp` or omit prompt metadata for attempted workers.
628
628
 
@@ -117,6 +117,7 @@ def build_analysis_packet(
117
117
  has_selected_direction: bool = False,
118
118
  mcp_servers_text: str = "",
119
119
  technical_evidence_text: str = "",
120
+ verification_target_path: str = "",
120
121
  ) -> str:
121
122
  """Return the primary compact input for Claude/Codex/Antigravity analysers.
122
123
 
@@ -139,6 +140,9 @@ def build_analysis_packet(
139
140
 
140
141
  `technical_evidence_text` 는 carry-in 이 technical-verification 결과일 때
141
142
  `technical_evidence_packet_block` 이 렌더한 증거 위치 절이다.
143
+
144
+ `verification_target_path` 는 final-verification prepare 가 run 별로 기록한
145
+ 검증 대상 스냅샷 경로(매니페스트 `verificationTargetPath` 와 같은 값)다.
142
146
  """
143
147
  brief_text = task_brief_path.read_text(encoding="utf-8")
144
148
  group_context_text = _read_optional(group_context_path) if group_context_path else ""
@@ -152,7 +156,7 @@ def build_analysis_packet(
152
156
  parts.extend(
153
157
  _intro_block(
154
158
  task_key,
155
- task_type,
159
+ verification_target_path,
156
160
  instruction_set_relative_path,
157
161
  bool(clarification_response_path),
158
162
  bool(group_context_text),
@@ -354,7 +358,7 @@ def _packet_frontmatter(brief_text: str, task_key: str) -> str:
354
358
 
355
359
  def _intro_block(
356
360
  task_key: str,
357
- task_type: str,
361
+ verification_target_path: str,
358
362
  instruction_set: str,
359
363
  has_clarification: bool,
360
364
  has_group_context: bool = False,
@@ -376,10 +380,8 @@ def _intro_block(
376
380
  f"- Analysis material: `{instruction_set}/analysis-material.md`",
377
381
  f"- Reference expectations: `{instruction_set}/reference-expectations.md`",
378
382
  ]
379
- if task_type == "final-verification":
380
- lines.append(
381
- f"- Verification target: `{instruction_set}/verification-target.md`"
382
- )
383
+ if verification_target_path:
384
+ lines.append(f"- Verification target: `{verification_target_path}`")
383
385
  if has_clarification:
384
386
  lines.append(
385
387
  f"- Clarification response: `{instruction_set}/clarification-response.md`"
@@ -172,7 +172,7 @@ Stage selection is `auto` or a number. If `--stage` comes from another task-type
172
172
 
173
173
  The stage worktree base is decided by dependency shape. An independent stage uses the task-key worktree HEAD fixed at first implementation entry as its anchor, and a single-dependency stage branches from the predecessor stage's done `head_commit`. A multi-dependency stage branches from a commit holding exactly its predecessors: the predecessor commit that already contains the others, or else an integration branch merging them (`<work-category-namespace>/<task-id-segment>-g<n1>-<n2>`). okstra creates that branch itself, so a predecessor that has not been merged into the task branch no longer blocks the stage; release-handoff later reuses the same branch as that stage's PR base.
174
174
 
175
- When a predecessor advances, implementation entry synchronizes existing completed stage branches in dependency order through `okstra_ctl.stage_rebase.synchronize_stage_stack`. Each downstream stage is rebased with `git rebase --onto <new-base> <recorded-old-base>`; merging a moving predecessor into that stage is not an update strategy. Re-entering an unfinished stage also rebases its existing worktree when the computed base changes. Old heads are preserved under `refs/okstra/rebase-backups/`, registry bases and completion records are updated, and previous verification no longer qualifies. Conflicts abort the current rebase and stop the chain; active runs and dirty worktrees are not rewritten. Tests: `tests/worktree/test_stage_rebase.py`.
175
+ When a predecessor advances, implementation entry synchronizes existing completed stage branches in dependency order through `okstra_ctl.stage_rebase.synchronize_stage_stack`. Each downstream stage is rebased with `git rebase --onto <new-base> <recorded-old-base>`; merging a moving predecessor into that stage is not an update strategy. Re-entering an unfinished stage also rebases its existing worktree when the computed base changes. Old heads are preserved under `refs/okstra/rebase-backups/`, registry bases and completion records are updated, and previous verification no longer qualifies. Conflicts abort the current rebase and stop the chain; active runs and dirty worktrees are not rewritten. A completed stage whose predecessor was reopened, and so has no done row, is left unchanged; the first synchronization after that predecessor is done again rebases it. Tests: `tests/worktree/test_stage_rebase.py`.
176
176
 
177
177
  Successful implementation report finalization automatically removes that stage's clean worktree after its `done` record is persisted. The report's last commit, the completion ledger, and the current branch tip must agree for cleanup (`stage_integrate.reclaim_completed_stage`). Failed, active, dirty, nested, or moved stages are preserved with a reason in the finalization step result. Cleanup retains the branch and registry base; implementation re-entry and final-verification restore the worktree from that branch. The task worktree and other stages are outside this scoped cleanup. Tests: `tests/worktree/test_stage_rebase.py` and `tests/report/test_report_finalize.py`.
178
178
 
@@ -12,7 +12,10 @@ from okstra_ctl.pr_template import PrTemplateError, resolve_pr_template_path
12
12
  from okstra_ctl.stage_map import parse_stage_map_for_prepare
13
13
  from okstra_ctl.phases.catalog import migrated_report_template
14
14
  from okstra_ctl.handoff_error import HandoffError
15
- from .operations import _require_eligible, compute_eligibility, _parse_stages_csv
15
+ from .operations import (
16
+ DEFAULT_RELEASE_BASES, _parse_stages_csv, _require_eligible,
17
+ anchor_base_branches, compute_eligibility,
18
+ )
16
19
 
17
20
 
18
21
  def _collect_handoff_source_report_rows(
@@ -74,6 +77,43 @@ def _select_handoff_stages(stage_map: list, rows: list, selection: str) -> list[
74
77
  return nums
75
78
 
76
79
 
80
+ def _render_anchor_base_candidates(project_root: Path, inp) -> str:
81
+ """구현 기준 커밋을 담은 기본 후보가 없으면, 그 커밋에 있는 origin 브랜치를
82
+ Q2 의 첫 후보로 올린다. 다른 task 의 미병합 stage 위에 쌓인 task 는 기본
83
+ 후보 어느 것을 base 로 잡아도 그 task 의 커밋까지 PR 에 실린다."""
84
+ from okstra_ctl import worktree_registry
85
+ from okstra_ctl.work_categories import resolve_work_category
86
+ from okstra_ctl.worktree import is_ancestor
87
+
88
+ anchor = worktree_registry.get_implementation_base(
89
+ inp.project_id, inp.task_group, inp.task_id) or ""
90
+ if not anchor:
91
+ return ""
92
+ if any(is_ancestor(project_root, anchor, f"refs/remotes/origin/{name}")
93
+ for name in DEFAULT_RELEASE_BASES):
94
+ return ""
95
+ work_category = resolve_work_category(
96
+ inp.work_category, project_root=project_root,
97
+ task_group=inp.task_group, task_id=inp.task_id)
98
+ branches = anchor_base_branches(project_root, anchor,
99
+ work_category=work_category, task_id=inp.task_id)
100
+ held = branches["at"] + branches["containing"]
101
+ defaults = ", ".join(f"`{name}`" for name in DEFAULT_RELEASE_BASES)
102
+ lines = [f"- Implementation anchor base: `{anchor}` — no default candidate "
103
+ f"({defaults}) contains it, so a PR on any of them would also carry "
104
+ "the commits of the work this task was built on."]
105
+ if held:
106
+ lines.append(f"- Recommended release base (offer first in Q2): `{held[0]}`")
107
+ else:
108
+ lines.append("- Recommended release base: none — no origin branch holds the "
109
+ "anchor; push the branch it came from before release-handoff.")
110
+ lines.append("- origin branches at the anchor: "
111
+ + (", ".join(f"`{n}`" for n in branches["at"]) or "none"))
112
+ lines.append("- origin branches containing the anchor: "
113
+ + (", ".join(f"`{n}`" for n in branches["containing"]) or "none"))
114
+ return "\n".join(lines)
115
+
116
+
77
117
  def materialize_handoff_input(
78
118
  workspace_root: Path, project_root: Path, inp, *, install_hint: str,
79
119
  ) -> dict:
@@ -133,6 +173,7 @@ def materialize_handoff_input(
133
173
  "HANDOFF_STAGES": stages_csv,
134
174
  "HANDOFF_SOURCE_REPORTS": source_rows,
135
175
  "HANDOFF_CONDITIONS": source_conditions,
176
+ "HANDOFF_ANCHOR_BASE_CANDIDATES": _render_anchor_base_candidates(project_root, inp),
136
177
  })
137
178
  inp.brief_path = out
138
179
  return {"HANDOFF_STAGES": stages_csv}
@@ -123,6 +123,51 @@ def _merge_base_for(*, project_root, project_id, task_group, task_id,
123
123
  raise HandoffError(str(exc)) from exc
124
124
 
125
125
 
126
+ # 입력 문서 `Candidate Release Base Branches` 의 기본 후보와 같은 목록이다.
127
+ DEFAULT_RELEASE_BASES = ("staging", "preprod", "prod", "main", "dev")
128
+
129
+
130
+ def _origin_branches(project_root, flag: str, commit: str, own_prefix: str) -> List[str]:
131
+ """`git branch -r <flag> <commit>` 중 origin 브랜치 이름. 이 task 자신의 stage
132
+ 브랜치는 릴리스 base 가 될 수 없으므로 뺀다."""
133
+ res = _git(Path(project_root), "branch", "-r", "--format=%(refname)", flag, commit)
134
+ if res.returncode != 0:
135
+ return []
136
+ prefix = "refs/remotes/origin/"
137
+ names = [line.strip()[len(prefix):] for line in res.stdout.splitlines()
138
+ if line.strip().startswith(prefix)]
139
+ return [n for n in names if n != "HEAD"
140
+ and n != own_prefix and not n.startswith(own_prefix + "-")]
141
+
142
+
143
+ def anchor_base_branches(project_root, anchor: str, *, work_category: str,
144
+ task_id: str) -> Dict[str, List[str]]:
145
+ """구현 기준 커밋을 tip 으로 가진 origin 브랜치와 그 커밋을 담은 브랜치."""
146
+ own = compute_branch_name(work_category=work_category, task_id_segment=task_id)
147
+ at = _origin_branches(project_root, "--points-at", anchor, own)
148
+ containing = [n for n in _origin_branches(project_root, "--contains", anchor, own)
149
+ if n not in at]
150
+ return {"at": at, "containing": containing}
151
+
152
+
153
+ def _foreign_anchor_error(*, stage: int, base_branch: str, anchor: str,
154
+ branches: Dict[str, List[str]]) -> HandoffError:
155
+ held = branches["at"] + branches["containing"]
156
+ if held:
157
+ fix = f"re-run pr-plan with --base {held[0]}"
158
+ else:
159
+ fix = ("no origin branch holds that commit — push the branch it came "
160
+ f"from, or wait until it is merged into origin/{base_branch}")
161
+ return HandoffError(
162
+ f"stage {stage} would target origin/{base_branch}, but this task was "
163
+ f"implemented on {anchor}, which origin/{base_branch} does not contain "
164
+ "— the PR would also carry every commit between them, which belong to "
165
+ "other work. pr-plan derives stacking within this task only; a task "
166
+ "built on another task's unmerged branch needs that branch as its "
167
+ f"release base. origin branches at {anchor}: {branches['at'] or 'none'}; "
168
+ f"containing it: {branches['containing'] or 'none'}. {fix}")
169
+
170
+
126
171
  def _resolve_stage_base(
127
172
  *, stage: int, deps: List[int], selected: List[int], pr_covered: set,
128
173
  done: Dict[int, Dict[str, Any]], project_root, base_branch: str,
@@ -135,6 +180,13 @@ def _resolve_stage_base(
135
180
  if not is_ancestor(project_root, _done_head(done, d),
136
181
  f"origin/{base_branch}")]
137
182
  if not live:
183
+ if anchor_base and not is_ancestor(project_root, anchor_base,
184
+ f"origin/{base_branch}"):
185
+ raise _foreign_anchor_error(
186
+ stage=stage, base_branch=base_branch, anchor=anchor_base,
187
+ branches=anchor_base_branches(
188
+ project_root, anchor_base, work_category=work_category,
189
+ task_id=task_id))
138
190
  commit = _run_git(["rev-parse", f"origin/{base_branch}"],
139
191
  project_root).stdout.strip()
140
192
  return {"base_kind": "release-base", "base_branch": base_branch,
@@ -31,13 +31,14 @@
31
31
  `okstra handoff local-checkout --project-root <project root> --project-id <id> --task-group <g> --task-id <t> --stage <N>`
32
32
  Exit 1 means a precondition failed (MAIN worktree dirty, registry entry missing, a run still holds the stage, the target branch already deleted, or checkout failed): show the error verbatim and re-ask the action selection. On success the okstra worktree for that stage no longer exists — if the lead's cwd was inside it, EVERY subsequent step (final-report authoring included) MUST use absolute paths or run from the MAIN worktree. Then route to the final-report self-review pass.
33
33
  2. **Release base branch** (only when the user picked `push + PR`) — present these options and capture exactly one:
34
+ - the `Recommended release base` from the input document's `## Candidate Release Base Branches`, when that section names one — first, marked recommended
34
35
  - `preprod`
35
36
  - `main`
36
37
  - `direct input` (free-form branch name; lead validates the name exists on origin via `git ls-remote --heads origin <name>` and re-asks on failure)
37
- This is the release base for the run, not necessarily each PR's base: a stage that sits on another stage targets that stage's branch. The chosen base MUST NOT be one of the stage branches. If it is, re-ask.
38
+ This is the release base for the run, not necessarily each PR's base: a stage that sits on another stage of this task targets that stage's branch. The release base MUST contain the task's implementation anchor base. `pr-plan` derives stacking inside this task only; when the task was built on another task's unmerged stage branch, the release base is that predecessor task's stage branch, which prepare names as the recommended base. The chosen base MUST NOT be one of this task's stage branches. If it is, re-ask.
38
39
  2p. **PR plan** (only when the user picked `push + PR`) — run
39
40
  `okstra handoff pr-plan --plan-run-root <...> --approved-plan <...> --project-root <project root> --project-id <id> --task-group <g> --task-id <t> --work-category <c> --stages <HANDOFF_STAGES> --base <chosen-base>`.
40
- It returns one row per stage with `head_branch`, `head_commit`, `base_kind` (`release-base` | `stage` | `merge-base`), `base_branch` and `base_commit`. Exit 2 means the predecessors of a multi-dependency stage conflict with each other: show the `conflicts` paths and stop (route: resolve manually, then retry). Exit 1 means an eligibility or dependency violation — most often a stage whose predecessor is neither in this run nor already PR'd nor merged into the release base: show the error verbatim and re-ask the action selection. On success these rows are authoritative for every subsequent step; the lead does not recompute a base by hand.
41
+ It returns one row per stage with `head_branch`, `head_commit`, `base_kind` (`release-base` | `stage` | `merge-base`), `base_branch` and `base_commit`. Exit 2 means the predecessors of a multi-dependency stage conflict with each other: show the `conflicts` paths and stop (route: resolve manually, then retry). Exit 1 means an eligibility or dependency violation — most often a stage whose predecessor is neither in this run nor already PR'd nor merged into the release base: show the error verbatim and re-ask the action selection. When the error says the release base does not contain the implementation anchor, the error names the `--base` that does: show it verbatim and re-ask Q2 with that branch first. **Enforced:** `okstra_ctl.phases.release_handoff.operations._resolve_stage_base` refuses the plan. On success these rows are authoritative for every subsequent step; the lead does not recompute a base by hand.
41
42
  A `merge-base` row means `pr-plan` created a branch merging that stage's predecessors. That branch is a PR base only — it is never a PR head — and it MUST be pushed before the PR that targets it.
42
43
  The output also carries `push_plan` and `warnings`. `push_plan` is every branch the PRs sit on, already in push order (each `merge-base` first, then the stage heads in dependency order), with the `commit` it must reach and an `action` of `create` (origin does not have it), `fast-forward` (origin is behind) or `up-to-date` (origin already has that commit — do not push it). GitHub resolves a PR's head and base by name on origin, so this list, not the local branch set, is what makes the stack real. A `warnings` row means `pr-plan` fast-forwarded a local branch to origin because origin was ahead: the commits origin adds are outside what this run verified. Quote every `warnings` row verbatim in Executed Commands and say so in the branch/PR explanation — the user is deciding whether to release commits this run did not verify. `pr-plan` refuses outright when a branch moved outside okstra or diverged from origin, since only a force push could deliver it.
43
44
  2b. **Pre-merge conflict probe** (only when the user picked `push + PR`) — before pushing, for each planned stage in dependency order:
@@ -48,7 +48,9 @@ taskType: "{{FM_TASK_TYPE}}"
48
48
 
49
49
  ## Candidate Release Base Branches
50
50
 
51
- The user picks ONE release base for the whole run. Each stage's own PR base is then derived from its `depends-on` by `okstra handoff pr-plan`: a stage with no live dependency targets the release base, a stage with one targets that stage's branch (a stacked PR), and a stage with several targets a branch merging them.
51
+ The user picks ONE release base for the whole run. Each stage's own PR base is then derived from its `depends-on` by `okstra handoff pr-plan`: a stage with no live dependency targets the release base, a stage with one targets that stage's branch (a stacked PR), and a stage with several targets a branch merging them. That derivation covers stacking inside this task only. The release base must contain the task's implementation anchor base; when this task was built on another task's unmerged stage branch, the release base is that branch, and `pr-plan` refuses a base that lacks the anchor.
52
+
53
+ {{HANDOFF_ANCHOR_BASE_CANDIDATES}}
52
54
 
53
55
  - Default options offered to the user: `staging` | `preprod` | `prod` | `main` | `dev` | custom input
54
56
  - Repo-specific preference, if known (e.g. `main` is the integration branch):
@@ -29,7 +29,7 @@ Report shapes remain in `schemas/final-report-v2.0.schema.json` and `schemas/fin
29
29
 
30
30
  `release-handoff` is the terminal phase that pushes already-committed implementation stages with a release-ready verdict, or hands them off as pull requests. **One stage is one PR.** The PR head is that stage's stack branch; the base comes from its `depends-on` — the release base for a stage with no live dependency, the predecessor's branch for a stage with one (a stacked PR), and a branch merging the predecessors for a stage with several.
31
31
 
32
- When a predecessor advances, `okstra_ctl.stage_rebase.synchronize_stage_stack` rebases downstream stages in dependency order rather than merging the predecessor into them. It records the new bases and completion commits, preserving prior heads under `refs/okstra/rebase-backups/`. Implementation entry and verification target acquisition use the same operation. PR planning stops after a stack change and requires fresh final-verification; the new completion rows invalidate earlier verification through `consumers.verified_accepted_stages`. Dirty or active stages, rewritten unproven predecessors, and rebase conflicts stop synchronization. The tests in `tests/worktree/test_stage_rebase.py` cover ordering, preservation, and verification invalidation. Origin divergence remains a delivery error, never a reason to merge old origin history into the rebased branch.
32
+ When a predecessor advances, `okstra_ctl.stage_rebase.synchronize_stage_stack` rebases downstream stages in dependency order rather than merging the predecessor into them. It records the new bases and completion commits, preserving prior heads under `refs/okstra/rebase-backups/`. Implementation entry and verification target acquisition use the same operation. PR planning stops after a stack change and requires fresh final-verification; the new completion rows invalidate earlier verification through `consumers.verified_accepted_stages`. Dirty or active stages, rewritten unproven predecessors, and rebase conflicts stop synchronization. A completed stage whose predecessor was reopened, and so has no done row, is left unchanged; the first synchronization after that predecessor is done again rebases it. The tests in `tests/worktree/test_stage_rebase.py` cover ordering, preservation, and verification invalidation. Origin divergence remains a delivery error, never a reason to merge old origin history into the rebased branch.
33
33
 
34
34
  Because the PRs are a stack, they must be merged in dependency order with a merge commit or a rebase-merge. A squash replaces the commits the next PR's base points at, so the stack breaks — every PR body states this, and the lead never merges.
35
35
 
@@ -141,7 +141,7 @@ stateDiagram-v2
141
141
  User interaction is exactly three steps.
142
142
 
143
143
  1. Q1 action: `local checkout`, `push + PR`, `skip`
144
- 2. Q2 release base: a branch from the profile menu such as `staging`, `preprod`, `main`, or Enter directly
144
+ 2. Q2 release base: a branch from the profile menu such as `staging`, `preprod`, `main`, or Enter directly. When no default candidate contains the task's implementation anchor base (the task was built on another task's unmerged stage branch), prepare names the origin branch at the anchor as the recommended first option, and `pr-plan` refuses a release base that lacks the anchor
145
145
  3. Q3 PR title/body: every stage's draft in one question — `use as-is`, `edit then proceed`, `cancel`
146
146
 
147
147
  The merge-conflict probe happens only for `push + PR`, once per stage against that stage's own base.
@@ -1154,7 +1154,9 @@ def _context_from_args(args: argparse.Namespace) -> FinalizeContext:
1154
1154
  team_state_path = resolve_project_path(
1155
1155
  project_root, require_string(manifest, "teamStatePath")
1156
1156
  )
1157
- report_path = resolve_project_path(project_root, args.report)
1157
+ report_path = resolve_project_path(
1158
+ project_root, args.report or require_string(manifest, "expectedReportRecordPath")
1159
+ )
1158
1160
  return FinalizeContext.from_manifest(
1159
1161
  project_root=project_root,
1160
1162
  workspace_root=Path(args.workspace_root).resolve(),
@@ -1213,8 +1215,11 @@ def _parser() -> argparse.ArgumentParser:
1213
1215
  parser.add_argument("--run-manifest", required=True)
1214
1216
  parser.add_argument(
1215
1217
  "--report",
1216
- required=True,
1217
- help="final-report record (.data.json); a leftover markdown path still locates the sibling record",
1218
+ default="",
1219
+ help=(
1220
+ "final-report record (.data.json); defaults to the run manifest's "
1221
+ "expectedReportRecordPath. A leftover markdown path still locates the sibling record"
1222
+ ),
1218
1223
  )
1219
1224
  # `okstra report-finalize` 래퍼(src/lib/python-command.mts)가 넣고, 사용자가
1220
1225
  # 직접 주면 거절한다. usage 에 필수로 찍히면 그 거절과 모순되므로 감춘다.
@@ -325,6 +325,7 @@ def project_convergence(
325
325
  "proposed": critic.get("gapsProposed", 0),
326
326
  "merged": critic.get("gapsMerged", 0),
327
327
  "unverified": critic.get("gapsUnverified", 0),
328
+ "duplicate": critic.get("gapsDuplicate", 0),
328
329
  }
329
330
  return result
330
331
 
@@ -3063,6 +3063,7 @@ def _write_instruction_set_sources(
3063
3063
  )
3064
3064
  if inp.clarification_response_path else ""
3065
3065
  ),
3066
+ verification_target_path=ctx.get("VERIFICATION_TARGET_RELATIVE_PATH", ""),
3066
3067
  )
3067
3068
  if inp.task_type == "technical-verification":
3068
3069
  packet += materialize_technical_input_packet(
@@ -4273,6 +4274,9 @@ def prepare_task_bundle(inp: PrepareInputs) -> PrepareOutputs:
4273
4274
  )
4274
4275
  carry = derive_stage_fix_carry(
4275
4276
  Path(ctx["RUN_DIR"]), ctx.get("EXECUTOR_WORKTREE_PATH", ""),
4277
+ plan_run_root=Path(inp.approved_plan_path).resolve().parents[1],
4278
+ stage=stage_run_claim.stage,
4279
+ project_root=Path(ctx["PROJECT_ROOT"]),
4276
4280
  )
4277
4281
  ctx["FIX_RUN_CONTEXT"] = carry.as_prompt_markdown() if carry else ""
4278
4282
 
@@ -1,8 +1,9 @@
1
- """Derive the fix-run carry for an implementation stage whose previous run
2
- ended with one or more verifier FAIL verdicts.
1
+ """Derive the fix-run carry for an implementation stage that is re-entered to
2
+ fix a defect: either a verifier FAIL in the stage's previous run, or acceptance
3
+ blockers a final-verification found after the stage was settled and reopened.
3
4
 
4
- Pure read-side: scans the stage run directory's assembled final-report data.json
5
- files and the stage worktree HEAD.
5
+ Pure read-side: scans consumers.jsonl, the reopen evidence report, the stage run
6
+ directory's assembled final-report data.json files and the stage worktree HEAD.
6
7
  Returns None when the upcoming run is not a fix run, so callers can treat
7
8
  "no carry" and "first run on this stage" identically.
8
9
  """
@@ -14,10 +15,15 @@ import subprocess
14
15
  from dataclasses import dataclass
15
16
  from pathlib import Path
16
17
 
18
+ from .consumers import read_consumers
17
19
  from .json_boundary import JsonBoundaryError, load_owned_object
18
20
  from .phases.implementation.validation import lead_fixed_verifiers
19
21
 
20
22
  _REPORT_RE = re.compile(r"final-report-implementation-(\d+)\.data\.json$")
23
+ _SEQ_RE = re.compile(r"-(\d+)\.data\.json$")
24
+
25
+ SOURCE_VERIFIER = "verifier"
26
+ SOURCE_FINAL_VERIFICATION = "final-verification"
21
27
 
22
28
 
23
29
  @dataclass(frozen=True)
@@ -28,16 +34,30 @@ class StageFixCarry:
28
34
  failed_verifiers: list[str]
29
35
  blocking_findings: list[str]
30
36
  routing_recommendation: str
37
+ source: str = SOURCE_VERIFIER
38
+ reopen_reason: str = ""
39
+ verification_scope: str = ""
31
40
 
32
41
  def as_prompt_markdown(self) -> str:
33
- lines = [
34
- "## Fix-Run Carry (this run fixes a prior FAIL)",
35
- "",
36
- f"- Previous report (data.json SSOT): `{self.prev_report_path}`",
37
- f"- Previous run HEAD (fix-diff base): `{self.prev_head_commit}`",
38
- f"- Failed verifiers: {', '.join(self.failed_verifiers)}",
39
- "- Carried blocking findings:",
40
- ]
42
+ if self.source == SOURCE_FINAL_VERIFICATION:
43
+ lines = [
44
+ "## Fix-Run Carry (this run fixes final-verification acceptance blockers)",
45
+ "",
46
+ f"- Final-verification report (data.json SSOT): `{self.prev_report_path}`",
47
+ f"- Reopened stage head (fix-diff base): `{self.prev_head_commit}`",
48
+ f"- Reopen reason: {self.reopen_reason}",
49
+ f"- Verification scope: {self.verification_scope or 'unrecorded'}",
50
+ "- Carried acceptance blockers:",
51
+ ]
52
+ else:
53
+ lines = [
54
+ "## Fix-Run Carry (this run fixes a prior FAIL)",
55
+ "",
56
+ f"- Previous report (data.json SSOT): `{self.prev_report_path}`",
57
+ f"- Previous run HEAD (fix-diff base): `{self.prev_head_commit}`",
58
+ f"- Failed verifiers: {', '.join(self.failed_verifiers)}",
59
+ "- Carried blocking findings:",
60
+ ]
41
61
  lines.extend(f" - {finding}" for finding in self.blocking_findings)
42
62
  if self.routing_recommendation:
43
63
  lines.append(
@@ -49,16 +69,39 @@ class StageFixCarry:
49
69
  "(`_implementation-verifier.md` § Fix-run incremental scope, "
50
70
  "`report-writer.md` § Fix-run incremental authoring).",
51
71
  "This block is inlined into the executor and verifier prompts by "
52
- "`initial_prompt_materialization`; do not transcribe it by hand. "
53
- "Lead duties: pass the previous data.json path above as read context "
54
- "to the report-writer dispatch so it updates only changed narrative blocks.",
72
+ "`initial_prompt_materialization`; do not transcribe it by hand.",
55
73
  ])
74
+ if self.source == SOURCE_FINAL_VERIFICATION:
75
+ # 블로커 행에는 stage 필드가 없다(AcceptanceBlockerRow) — whole-task 검증이면 소유 판단을 실행자에게 넘긴다.
76
+ if self.verification_scope != "single-stage":
77
+ lines.append(
78
+ "Blocker rows name no stage: fix the blockers this stage owns, "
79
+ "as the reopen reason states, and cite the others as out of scope."
80
+ )
81
+ else:
82
+ lines.append(
83
+ "Lead duties: pass the previous data.json path above as read context "
84
+ "to the report-writer dispatch so it updates only changed narrative blocks."
85
+ )
56
86
  return "\n".join(lines)
57
87
 
58
88
 
59
89
  def derive_stage_fix_carry(
60
- stage_run_dir: Path, worktree_path: str,
90
+ stage_run_dir: Path, worktree_path: str, *,
91
+ plan_run_root: Path | None = None,
92
+ stage: int | None = None,
93
+ project_root: Path | None = None,
61
94
  ) -> StageFixCarry | None:
95
+ """A stage reopened over a final-verification report carries that report's
96
+ blockers; otherwise the latest implementation report's verifier FAILs.
97
+
98
+ The two never merge: a reopen withdraws a `done` row, and that `done` already
99
+ settled every verdict of the implementation report before it.
100
+ """
101
+ if plan_run_root is not None and stage is not None and project_root is not None:
102
+ carry = _reopen_carry(plan_run_root, stage, project_root, worktree_path)
103
+ if carry is not None:
104
+ return carry
62
105
  report = _latest_report(Path(stage_run_dir))
63
106
  if report is None:
64
107
  return None
@@ -91,6 +134,65 @@ def derive_stage_fix_carry(
91
134
  )
92
135
 
93
136
 
137
+ def _reopen_carry(
138
+ plan_run_root: Path, stage: int, project_root: Path, worktree_path: str,
139
+ ) -> StageFixCarry | None:
140
+ # 이 run 의 claim 이 이미 `started` 행을 붙였으므로 마지막 종결 행(done/failed)을 본다.
141
+ settled = [
142
+ row for row in read_consumers(Path(plan_run_root))
143
+ if row.get("stage") == stage and row.get("status") in ("done", "failed")
144
+ ]
145
+ if not settled:
146
+ return None
147
+ row = settled[-1]
148
+ evidence = str(row.get("evidence_path") or "")
149
+ if row.get("reopened_by") != "stage-reopen" or not evidence:
150
+ return None
151
+ report = Path(evidence)
152
+ if not report.is_absolute():
153
+ report = Path(project_root) / report
154
+ try:
155
+ data = load_owned_object(report, artifact="final-verification final report")
156
+ except (OSError, JsonBoundaryError):
157
+ return None
158
+ if (data.get("header") or {}).get("taskType") != "final-verification":
159
+ return None
160
+ fv = data.get("finalVerification")
161
+ if not isinstance(fv, dict):
162
+ return None
163
+ blockers = [
164
+ _blocker_line(item) for item in fv.get("acceptanceBlockers") or []
165
+ if isinstance(item, dict)
166
+ ]
167
+ if not blockers:
168
+ return None
169
+ # fix-diff 기준은 final-verification 이 판정한 head — reopen 이 철회한 done 행의 head 다.
170
+ head = str(row.get("head_commit") or "") or _git_head(worktree_path)
171
+ if not head:
172
+ return None
173
+ seq = _SEQ_RE.search(report.name)
174
+ return StageFixCarry(
175
+ prev_report_path=str(report),
176
+ prev_report_seq=seq.group(1) if seq else "",
177
+ prev_head_commit=head,
178
+ failed_verifiers=[],
179
+ blocking_findings=blockers,
180
+ routing_recommendation=_routing_line(fv.get("routingRecommendation")),
181
+ source=SOURCE_FINAL_VERIFICATION,
182
+ reopen_reason=str(row.get("reason") or ""),
183
+ verification_scope=str(data.get("verificationScope") or ""),
184
+ )
185
+
186
+
187
+ def _blocker_line(row: dict) -> str:
188
+ return (
189
+ f"{row.get('id') or '<no id>'} ({row.get('severity') or 'unrated'}, "
190
+ f"follow-up phase: {row.get('followUpPhase') or 'unrecorded'}): "
191
+ f"{str(row.get('statement') or '').strip()} — evidence: "
192
+ f"{str(row.get('evidence') or '').strip()}"
193
+ )
194
+
195
+
94
196
  def _blocking_findings(data: dict, failed: list[dict]) -> list[str]:
95
197
  """이전 run 을 FAIL 로 만든 finding 목록.
96
198
 
@@ -118,6 +118,9 @@ def synchronize_stage_stack(
118
118
  stage = by_number[number]
119
119
  if not row or number not in done or stage.get("cancelled"):
120
120
  continue
121
+ # A reopened predecessor has no done row; its dependent waits for the next one.
122
+ if any(dep not in done for dep in stage.get("depends_on") or []):
123
+ continue
121
124
  active = statuses.get(number) == "started" or row.get("status") == "active"
122
125
  if _synchronize_recorded_stage(
123
126
  project_root,
@@ -11,7 +11,12 @@ from dataclasses import dataclass
11
11
  from pathlib import Path
12
12
 
13
13
  from .. import worktree_registry
14
- from .git_ops import _is_inside_non_main_worktree, is_git_work_tree
14
+ from .git_ops import (
15
+ _branch_checkout_path,
16
+ _branch_exists,
17
+ _is_inside_non_main_worktree,
18
+ is_git_work_tree,
19
+ )
15
20
  from .naming import _safe_segment, compute_branch_name, compute_worktree_path
16
21
 
17
22
 
@@ -24,11 +29,19 @@ class WorktreeDecision:
24
29
  - "reused": registry already has this task-key; existing path/branch returned
25
30
  - "skipped-in-worktree": project_root is itself a non-main worktree
26
31
  - "skipped-not-git": project_root has no .git
32
+
33
+ recovery (only when the active registry row no longer matches git):
34
+ - "restore-from-branch": status "reused"; the recorded branch survives but
35
+ is not checked out at the recorded path, so provision re-adds it there
36
+ - "replace-stale-row": status "new"; the recorded branch is gone, so
37
+ provision releases the row and creates a fresh worktree from the
38
+ requested base, or the recorded base when none is requested
27
39
  """
28
40
  status: str
29
41
  path: str # worktree path (new: prospective; reuse: existing; skip: project_root)
30
42
  branch: str = "" # new: prospective branch; reused: existing branch
31
43
  base_ref: str = "" # new: requested base_ref; reused: existing base
44
+ recovery: str = ""
32
45
 
33
46
 
34
47
  def preview_worktree_decision(
@@ -54,11 +67,21 @@ def preview_worktree_decision(
54
67
  safe_group = _safe_segment(task_group_segment)
55
68
  safe_task = _safe_segment(task_id_segment)
56
69
  existing = worktree_registry.lookup(safe_project, safe_group, safe_task)
70
+ recovery = ""
57
71
  if existing is not None and existing.status == "active":
58
- return WorktreeDecision(
59
- status="reused", path=existing.worktree_path,
60
- branch=existing.branch, base_ref=existing.base_ref,
61
- )
72
+ if _is_checked_out_at(project_root, existing.branch, existing.worktree_path):
73
+ return WorktreeDecision(
74
+ status="reused", path=existing.worktree_path,
75
+ branch=existing.branch, base_ref=existing.base_ref,
76
+ )
77
+ if _branch_exists(project_root, existing.branch):
78
+ return WorktreeDecision(
79
+ status="reused", path=existing.worktree_path,
80
+ branch=existing.branch, base_ref=existing.base_ref,
81
+ recovery="restore-from-branch",
82
+ )
83
+ recovery = "replace-stale-row"
84
+ base_ref = base_ref or existing.base_ref
62
85
  return WorktreeDecision(
63
86
  status="new",
64
87
  path=str(compute_worktree_path(
@@ -66,9 +89,23 @@ def preview_worktree_decision(
66
89
  task_id_segment=safe_task)),
67
90
  branch=compute_branch_name(work_category=work_category, task_id_segment=safe_task),
68
91
  base_ref=base_ref,
92
+ recovery=recovery,
69
93
  )
70
94
 
71
95
 
96
+ def _is_checked_out_at(project_root: Path, branch: str, worktree_path: str) -> bool:
97
+ """Whether git itself has `branch` checked out at `worktree_path`.
98
+
99
+ An `active` registry row only records what okstra reserved; the directory
100
+ can be removed by hand and the branch deleted after a merge without the
101
+ registry hearing about it.
102
+ """
103
+ checkout = _branch_checkout_path(project_root, branch)
104
+ if not checkout or not Path(worktree_path).is_dir():
105
+ return False
106
+ return Path(checkout).resolve() == Path(worktree_path).resolve()
107
+
108
+
72
109
  @dataclass
73
110
  class StageWorktreeDecision:
74
111
  """Side-effect-free decision for one concrete implementation stage."""
@@ -141,6 +141,10 @@ def provision_task_worktree(
141
141
  safe_task = _safe_segment(task_id_segment)
142
142
 
143
143
  if decision.status == "reused":
144
+ restored = ""
145
+ if decision.recovery == "restore-from-branch":
146
+ _restore_task_worktree(project_root, Path(decision.path), decision.branch)
147
+ restored = "; restored from its branch (directory was not a worktree)"
144
148
  worktree_registry.touch_phase(safe_project, safe_group, safe_task, task_type)
145
149
  _seed_worktree_settings_symlink(Path(decision.path))
146
150
  drift = _sync_key_drift_note(
@@ -155,7 +159,7 @@ def provision_task_worktree(
155
159
  note=(
156
160
  f"task worktree reused at {decision.path} on branch "
157
161
  f"{decision.branch} (base {decision.base_ref[:12]}); phase {task_type}"
158
- f"{drift}"
162
+ f"{restored}{drift}"
159
163
  ),
160
164
  )
161
165
 
@@ -163,6 +167,8 @@ def provision_task_worktree(
163
167
  worktree_path = Path(decision.path)
164
168
  branch = decision.branch
165
169
 
170
+ if decision.recovery == "replace-stale-row":
171
+ _remove_settings_seed_shell(worktree_path)
166
172
  if worktree_path.exists():
167
173
  raise RuntimeError(
168
174
  f"task worktree path already exists but is not in the registry: "
@@ -173,7 +179,7 @@ def provision_task_worktree(
173
179
  raise RuntimeError(_branch_exists_message(project_root, branch, "task"))
174
180
 
175
181
  main_root = main_worktree_path(project_root)
176
- requested_base = (base_ref or "").strip()
182
+ requested_base = (decision.base_ref or "").strip()
177
183
  if not requested_base and require_base_ref:
178
184
  raise RuntimeError(
179
185
  "first-phase task worktree requires an explicit base ref; "
@@ -221,8 +227,15 @@ def provision_task_worktree(
221
227
  linked_parts.append(f"linked-files {', '.join(linked_files)}")
222
228
  if snapshot_files:
223
229
  linked_parts.append(f"snapshot {', '.join(snapshot_files)}")
230
+ if decision.recovery == "replace-stale-row":
231
+ linked_parts.append(
232
+ "replaced a stale registry row whose recorded branch no longer exists")
224
233
  linked_suffix = ("; " + "; ".join(linked_parts)) if linked_parts else ""
225
234
 
235
+ if decision.recovery == "replace-stale-row":
236
+ # The recorded branch is already deleted, so freeing its slot keeps the
237
+ # registry's "a free branch name is physically deleted" invariant.
238
+ worktree_registry.release(safe_project, safe_group, safe_task)
226
239
  try:
227
240
  worktree_registry.reserve(
228
241
  project_id=safe_project,
@@ -260,6 +273,40 @@ def provision_task_worktree(
260
273
  )
261
274
 
262
275
 
276
+ def _remove_settings_seed_shell(path: Path) -> None:
277
+ """Remove a directory that holds nothing but okstra's settings seed.
278
+
279
+ Earlier prepares re-seeded `.claude/settings.local.json` into the recorded
280
+ path of a stale registry row, which left exactly this shell behind and made
281
+ every later prepare refuse the path. Anything else in the directory is
282
+ left alone.
283
+ """
284
+ seed = path / ".claude" / "settings.local.json"
285
+ if not path.is_dir() or not (seed.is_symlink() or seed.is_file()):
286
+ return
287
+ if [p.name for p in path.iterdir()] != [".claude"]:
288
+ return
289
+ if [p.name for p in (path / ".claude").iterdir()] != ["settings.local.json"]:
290
+ return
291
+ seed.unlink()
292
+ (path / ".claude").rmdir()
293
+ path.rmdir()
294
+
295
+
296
+ def _restore_task_worktree(project_root: Path, path: Path, branch: str) -> None:
297
+ _remove_settings_seed_shell(path)
298
+ if path.exists():
299
+ raise RuntimeError(
300
+ f"task worktree path {path} exists but is not a worktree of branch "
301
+ f"{branch}; move it aside so okstra can re-add the worktree from "
302
+ "that branch."
303
+ )
304
+ # A directory deleted by hand stays registered in git until pruned, and
305
+ # `git worktree add` refuses a missing-but-registered path.
306
+ _git(main_worktree_path(project_root), "worktree", "prune")
307
+ restore_stage_worktree(project_root, str(path), branch)
308
+
309
+
263
310
  def restore_stage_worktree(project_root: Path, path: str, branch: str) -> None:
264
311
  target = Path(path)
265
312
  if target.exists():
@@ -67,6 +67,13 @@ def rebase_stage_branch(
67
67
  raise RuntimeError(
68
68
  f"cannot rebase {branch}: recorded base {old} is not an ancestor"
69
69
  )
70
+ # A branch rebased by hand already sits linearly on the new base; replaying
71
+ # old..head would reapply the new base's own commits and conflict. A merge
72
+ # of the new base still goes through the rebase, which flattens it.
73
+ if is_ancestor(project_root, new, head) and not _checked_git(
74
+ project_root, "rev-list", "--merges", f"{new}..{head}"
75
+ ):
76
+ return head
70
77
  with _stage_worktree(project_root, branch) as holder:
71
78
  for state in ["rebase-merge", "rebase-apply", "MERGE_HEAD", "CHERRY_PICK_HEAD"]:
72
79
  path = Path(_checked_git(holder, "rev-parse", "--git-path", state))
@@ -103,6 +110,9 @@ def _apply_rebase(holder: Path, branch: str, old: str, new: str) -> str:
103
110
  f"rebase failed for {branch}; recovery worktree: {holder}; {detail}; abort: {abort.stderr}"
104
111
  )
105
112
  raise RuntimeError(
106
- f"rebase failed for {branch}; original branch restored: {detail}"
113
+ f"rebase failed for {branch}; original branch restored: {detail}\n"
114
+ f"To resolve: in the worktree holding {branch}, run "
115
+ f"`git rebase --onto {new} {old}`, resolve the conflicts, then re-run "
116
+ "the same prepare command; it records the new base without rebasing again."
107
117
  )
108
118
  return _checked_git(holder, "rev-parse", "HEAD")
@@ -481,11 +481,12 @@
481
481
  },
482
482
  "criticGaps": {
483
483
  "type": "object",
484
- "description": "Coverage-critic gap accounting. `proposed - merged - unverified` is the count the voters judged and rejected, so a gap that vanished shows up as a mismatch instead of as nothing. Every `unverified` gap needs a matching `missingInformation` row with source `critic-unverified` (prompts/lead/convergence.md \"Gap verification\").",
484
+ "description": "Coverage-critic gap accounting. `proposed - merged - unverified - duplicate` is the count the voters judged and rejected, so a gap that vanished shows up as a mismatch instead of as nothing. `duplicate` counts gaps the critic declared duplicates of an existing finding; they are never verified. Every `unverified` gap needs a matching `missingInformation` row with source `critic-unverified` (prompts/lead/convergence.md \"Gap verification\").",
485
485
  "required": [
486
486
  "proposed",
487
487
  "merged",
488
- "unverified"
488
+ "unverified",
489
+ "duplicate"
489
490
  ],
490
491
  "additionalProperties": false,
491
492
  "properties": {
@@ -500,6 +501,10 @@
500
501
  "unverified": {
501
502
  "type": "integer",
502
503
  "minimum": 0
504
+ },
505
+ "duplicate": {
506
+ "type": "integer",
507
+ "minimum": 0
503
508
  }
504
509
  }
505
510
  },
@@ -518,11 +518,12 @@
518
518
  },
519
519
  "criticGaps": {
520
520
  "type": "object",
521
- "description": "Coverage-critic gap accounting. `proposed - merged - unverified` is the count the voters judged and rejected, so a gap that vanished shows up as a mismatch instead of as nothing. Every `unverified` gap needs a matching `missingInformation` row with source `critic-unverified` (prompts/lead/convergence.md \"Gap verification\").",
521
+ "description": "Coverage-critic gap accounting. `proposed - merged - unverified - duplicate` is the count the voters judged and rejected, so a gap that vanished shows up as a mismatch instead of as nothing. `duplicate` counts gaps the critic declared duplicates of an existing finding; they are never verified. Every `unverified` gap needs a matching `missingInformation` row with source `critic-unverified` (prompts/lead/convergence.md \"Gap verification\").",
522
522
  "required": [
523
523
  "proposed",
524
524
  "merged",
525
- "unverified"
525
+ "unverified",
526
+ "duplicate"
526
527
  ],
527
528
  "additionalProperties": false,
528
529
  "properties": {
@@ -537,6 +538,10 @@
537
538
  "unverified": {
538
539
  "type": "integer",
539
540
  "minimum": 0
541
+ },
542
+ "duplicate": {
543
+ "type": "integer",
544
+ "minimum": 0
540
545
  }
541
546
  }
542
547
  },
@@ -87,8 +87,8 @@ okstra pr gen --base <base> --template <template>
87
87
  To describe a branch other than the checkout — a stage branch whose worktree is gone — add
88
88
  `--head <branch>`; nothing is checked out.
89
89
 
90
- Read the fixed `Base`, `Head`, `Current branch`, `Template name`, `Commits`, `Diff stat`,
91
- `Template`, and `Drafting rules` sections. Then fill the template by following every item of
90
+ Read the fixed `Base`, `Head`, `Current branch`, `Upstream`, `Merge base`, `Template name`,
91
+ `Commits`, `Diff stat`, `Template`, and `Drafting rules` sections. Then fill the template by following every item of
92
92
  `Drafting rules`: it says how to read the full diff, when to stop, how to fill sections and
93
93
  checkboxes, how to open the new-behavior section, and which identifiers the title and body may
94
94
  carry. release-handoff drafts its PR bodies from the same rules.
@@ -1,8 +1,15 @@
1
- 1. Read the full diff — it is the source of truth: `git diff <Base>...<Head>`, using the `Base` and
2
- `Head` values above. Read a large diff in sections.
1
+ 1. Read the full diff — it is the source of truth: `git diff <Merge base> <Head>`, pasting the
2
+ `Merge base` and `Head` values above literally. `Merge base` already folds in the base's upstream,
3
+ so changes the remote base has merged are excluded. Read a large diff in sections.
3
4
  2. If `Commits` or `Diff stat` above is `-`, there is nothing to describe: stop and say so.
4
- 3. Fill the template from the diff and the commits. Describe only what actually changed. Strip HTML
5
- comments; keep the template's sections as the structure.
5
+ 3. Fill the template from the diff and the commits. Describe only the net change from the merge base
6
+ to the head, as a reviewer sees it on the PR. Strip HTML comments; keep the template's sections as
7
+ the structure.
8
+ - "Current behavior" is the behavior at the merge base, never at an intermediate commit of the branch.
9
+ - A problem one commit of the branch introduced and a later commit fixed is not a change: leave it
10
+ out, or describe only the final state. Never present it as a pre-existing bug the PR fixes.
11
+ - A commit subject is not evidence of a change the diff does not show.
12
+ - The drafting session's conversation, the last commit alone, and earlier PR drafts are not sources.
6
13
  4. Mark a checklist box `[x]` only when the diff supports it (tests touched → the tests box, docs
7
14
  touched → the docs box).
8
15
  5. Open the new-behavior section — `What is the new behavior` in the default template, or the section
@@ -4233,12 +4233,13 @@ def _validate_unverified_critic_gaps_recorded(data: dict, failures: list[str]) -
4233
4233
 
4234
4234
  proposed = critic.get("proposed")
4235
4235
  merged = critic.get("merged")
4236
- if isinstance(proposed, int) and isinstance(merged, int):
4237
- if merged + unverified > proposed:
4236
+ duplicate = critic.get("duplicate")
4237
+ if isinstance(proposed, int) and isinstance(merged, int) and isinstance(duplicate, int):
4238
+ if merged + unverified + duplicate > proposed:
4238
4239
  failures.append(
4239
4240
  "final-report data.json: crossVerification.criticGaps has "
4240
- f"merged({merged}) + unverified({unverified}) > proposed({proposed}) "
4241
- "— the accounting does not describe a real set of gaps."
4241
+ f"merged({merged}) + unverified({unverified}) + duplicate({duplicate}) "
4242
+ f"> proposed({proposed}) — the accounting does not describe a real set of gaps."
4242
4243
  )
4243
4244
 
4244
4245