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.
- package/dist/commands/pr/pr.d.mts +2 -0
- package/dist/commands/pr/pr.mjs +12 -3
- package/dist/commands/pr/pr.mjs.map +1 -1
- package/docs/architecture.md +1 -1
- package/docs/cli.md +1 -1
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
- package/runtime/python/okstra_ctl/analysis_packet.py +8 -6
- package/runtime/python/okstra_ctl/phases/implementation/spec.md +1 -1
- package/runtime/python/okstra_ctl/phases/release_handoff/entry.py +42 -1
- package/runtime/python/okstra_ctl/phases/release_handoff/operations.py +52 -0
- package/runtime/python/okstra_ctl/phases/release_handoff/profile.md +3 -2
- package/runtime/python/okstra_ctl/phases/release_handoff/report_assets/release-handoff-input.template.md +3 -1
- package/runtime/python/okstra_ctl/phases/release_handoff/spec.md +2 -2
- package/runtime/python/okstra_ctl/report_finalize.py +8 -3
- package/runtime/python/okstra_ctl/report_projections.py +1 -0
- package/runtime/python/okstra_ctl/run.py +4 -0
- package/runtime/python/okstra_ctl/stage_fix_carry.py +118 -16
- package/runtime/python/okstra_ctl/stage_rebase.py +3 -0
- package/runtime/python/okstra_ctl/worktree/decisions.py +42 -5
- package/runtime/python/okstra_ctl/worktree/provision.py +49 -2
- package/runtime/python/okstra_ctl/worktree/rebase.py +11 -1
- package/runtime/schemas/final-report-v2.0.schema.json +7 -2
- package/runtime/schemas/final-report-v3.0.schema.json +7 -2
- package/runtime/skills/okstra-pr-gen/SKILL.md +2 -2
- package/runtime/templates/pr/drafting-rules.md +11 -4
- 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[];
|
package/dist/commands/pr/pr.mjs
CHANGED
|
@@ -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",
|
|
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",
|
|
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,
|
|
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":"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"}
|
|
1
|
+
{"version":3,"file":"pr.mjs","sourceRoot":"","sources":["../../../src/commands/pr/pr.mts"],"names":[],"mappings":"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"}
|
package/docs/architecture.md
CHANGED
|
@@ -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
package/runtime/BUILD.json
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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
|
-
|
|
1217
|
-
help=
|
|
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 에 필수로 찍히면 그 거절과 모순되므로 감춘다.
|
|
@@ -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
|
|
2
|
-
|
|
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
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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`, `
|
|
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 <
|
|
2
|
-
`Head` values above.
|
|
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
|
|
5
|
-
comments; keep the template's sections as
|
|
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
|
-
|
|
4237
|
-
|
|
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})
|
|
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
|
|