okstra 0.205.1 → 0.206.1
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/README.md +2 -2
- package/dist/commands/lifecycle/install.mjs +2 -1
- package/dist/commands/lifecycle/install.mjs.map +1 -1
- package/docs/architecture.md +16 -16
- package/docs/cli.md +4 -4
- package/docs/contributor-change-matrix.md +3 -2
- package/docs/performance-improvement-plan-v2.md +1 -1
- package/docs/project-structure-overview.md +45 -21
- package/package.json +2 -3
- package/runtime/BUILD.json +2 -2
- package/runtime/bin/okstra-spawn-followups.py +2 -2
- package/runtime/prompts/launch.template.md +1 -1
- package/runtime/prompts/lead/context-loader.md +1 -1
- package/runtime/prompts/lead/convergence.md +3 -3
- package/runtime/prompts/lead/okstra-lead-contract.md +14 -55
- package/runtime/prompts/lead/phase-routing.md +82 -0
- package/runtime/prompts/lead/report-writer.md +2 -2
- package/runtime/prompts/lead/team-contract.md +1 -1
- package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +1 -1
- package/runtime/prompts/profiles/_coverage-critic.md +1 -1
- package/runtime/prompts/profiles/forbidden-actions.json +0 -94
- package/runtime/python/okstra_ctl/agent/prompt_cli/corrections.py +1 -1
- package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +10 -1
- package/runtime/python/okstra_ctl/analysis_inputs.py +0 -39
- package/runtime/python/okstra_ctl/analysis_scope.py +31 -0
- package/runtime/python/okstra_ctl/asset_roots.py +19 -0
- package/runtime/python/okstra_ctl/consumers.py +12 -0
- package/runtime/python/okstra_ctl/contract_graph.py +75 -10
- package/runtime/python/okstra_ctl/dispatch_state.py +22 -0
- package/runtime/python/okstra_ctl/doctor.py +15 -4
- package/runtime/python/okstra_ctl/execution_mutation_audit.py +27 -1
- package/runtime/python/okstra_ctl/handoff.py +11 -466
- package/runtime/python/okstra_ctl/handoff_error.py +5 -0
- package/runtime/python/okstra_ctl/implementation_direction.py +9 -485
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +8 -1
- package/runtime/python/okstra_ctl/next_phase.py +2 -2
- package/runtime/python/okstra_ctl/option_comparison.py +3 -165
- package/runtime/python/okstra_ctl/option_votes.py +3 -191
- package/runtime/python/okstra_ctl/paths.py +22 -6
- package/runtime/python/okstra_ctl/phases/__init__.py +4 -0
- package/runtime/python/okstra_ctl/phases/catalog.py +260 -0
- package/runtime/python/okstra_ctl/phases/change_impact_analysis/boundary.json +11 -0
- package/runtime/python/okstra_ctl/phases/change_impact_analysis/entry.py +39 -0
- package/runtime/python/okstra_ctl/{report_html/view_models/change_impact_analysis.py → phases/change_impact_analysis/report.py} +3 -3
- package/runtime/python/okstra_ctl/phases/change_impact_analysis/spec.md +26 -0
- package/runtime/python/okstra_ctl/phases/change_impact_analysis/validation.py +23 -0
- package/runtime/python/okstra_ctl/phases/error_analysis/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/error_analysis/boundary.json +9 -0
- package/runtime/{prompts/profiles/error-analysis.md → python/okstra_ctl/phases/error_analysis/profile.md} +2 -2
- package/runtime/python/okstra_ctl/{report_html/view_models/error_analysis.py → phases/error_analysis/report.py} +9 -8
- package/runtime/{templates/reports → python/okstra_ctl/phases/error_analysis/report_assets}/error-analysis-input.template.md +1 -1
- package/{docs/task-process/error-analysis.md → runtime/python/okstra_ctl/phases/error_analysis/spec.md} +22 -7
- package/runtime/python/okstra_ctl/phases/error_analysis/validation.py +241 -0
- package/runtime/python/okstra_ctl/phases/feature_analysis/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/feature_analysis/boundary.json +8 -0
- package/runtime/python/okstra_ctl/phases/feature_analysis/entry.py +63 -0
- package/runtime/python/okstra_ctl/{report_html/view_models/feature_analysis.py → phases/feature_analysis/report.py} +12 -5
- package/runtime/python/okstra_ctl/phases/feature_analysis/spec.md +22 -0
- package/runtime/python/okstra_ctl/phases/feature_analysis/validation.py +27 -0
- package/runtime/python/okstra_ctl/phases/feature_analysis/wizard.py +95 -0
- package/runtime/python/okstra_ctl/phases/final_verification/__init__.py +4 -0
- package/runtime/python/okstra_ctl/phases/final_verification/boundary.json +8 -0
- package/runtime/python/okstra_ctl/phases/final_verification/entry.py +166 -0
- package/runtime/{prompts/profiles/final-verification.md → python/okstra_ctl/phases/final_verification/profile.md} +5 -5
- package/runtime/python/okstra_ctl/{report_html/view_models/final_verification.py → phases/final_verification/report.py} +12 -3
- package/runtime/{templates/reports → python/okstra_ctl/phases/final_verification/report_assets}/final-verification-input.template.md +1 -1
- package/{docs/task-process/final-verification.md → runtime/python/okstra_ctl/phases/final_verification/spec.md} +42 -25
- package/runtime/python/okstra_ctl/phases/final_verification/target.py +296 -0
- package/runtime/python/okstra_ctl/phases/final_verification/validation.py +190 -0
- package/runtime/python/okstra_ctl/phases/final_verification/wizard.py +38 -0
- package/runtime/python/okstra_ctl/phases/implementation/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/implementation/boundary.json +17 -0
- package/runtime/python/okstra_ctl/{implementation_stage.py → phases/implementation/entry.py} +22 -10
- package/runtime/{prompts/host-orchestration/implementation.md → python/okstra_ctl/phases/implementation/host-rules.md} +1 -1
- package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-deliverable.md +1 -1
- package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-executor.md +4 -3
- package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-verifier.md +4 -4
- package/runtime/{prompts/profiles/implementation.md → python/okstra_ctl/phases/implementation/profile.md} +5 -5
- package/runtime/python/okstra_ctl/{report_html/view_models/implementation.py → phases/implementation/report.py} +3 -3
- package/runtime/{templates/reports → python/okstra_ctl/phases/implementation/report_assets}/implementation-input.template.md +1 -1
- package/{docs/task-process/implementation.md → runtime/python/okstra_ctl/phases/implementation/spec.md} +20 -8
- package/runtime/python/okstra_ctl/phases/implementation/validation.py +205 -0
- package/runtime/python/okstra_ctl/phases/implementation/wizard.py +39 -0
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/authoring.py +80 -0
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/boundary.json +10 -0
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/comparison.py +168 -0
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/entry.py +27 -0
- package/runtime/{prompts/profiles/implementation-option-selection.md → python/okstra_ctl/phases/implementation_option_selection/profile.md} +2 -2
- package/runtime/python/okstra_ctl/{report_html/view_models/implementation_option_selection.py → phases/implementation_option_selection/report.py} +2 -2
- package/{docs/task-process/implementation-option-selection.md → runtime/python/okstra_ctl/phases/implementation_option_selection/spec.md} +20 -7
- package/runtime/python/okstra_ctl/{implementation_options.py → phases/implementation_option_selection/validation.py} +3 -3
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/votes.py +194 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/authoring.py +2345 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/boundary.json +12 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/entry.py +161 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/guidance.py +178 -0
- package/runtime/{prompts/lead → python/okstra_ctl/phases/implementation_planning/instructions}/plan-body-verification.md +61 -51
- package/runtime/python/okstra_ctl/phases/implementation_planning/plan_body.py +3295 -0
- package/runtime/{prompts/profiles/implementation-planning.md → python/okstra_ctl/phases/implementation_planning/profile.md} +74 -25
- package/runtime/python/okstra_ctl/phases/implementation_planning/report.py +237 -0
- package/runtime/{templates/reports → python/okstra_ctl/phases/implementation_planning/report_assets}/implementation-planning-input.template.md +2 -2
- package/{docs/task-process/implementation-planning.md → runtime/python/okstra_ctl/phases/implementation_planning/spec.md} +30 -6
- package/runtime/python/okstra_ctl/phases/implementation_planning/validation.py +597 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/wizard.py +166 -0
- package/runtime/python/okstra_ctl/phases/improvement_discovery/boundary.json +12 -0
- package/runtime/python/okstra_ctl/{improvement_lenses.py → phases/improvement_discovery/lenses.py} +1 -6
- package/runtime/{prompts/profiles/improvement-discovery.md → python/okstra_ctl/phases/improvement_discovery/profile.md} +5 -5
- package/runtime/python/okstra_ctl/{report_html/view_models/improvement_discovery.py → phases/improvement_discovery/report.py} +3 -3
- package/runtime/{templates/reports → python/okstra_ctl/phases/improvement_discovery/report_assets}/improvement-discovery-input.template.md +1 -2
- package/runtime/python/okstra_ctl/phases/improvement_discovery/spec.md +29 -0
- package/runtime/{validators/validate_improvement_report.py → python/okstra_ctl/phases/improvement_discovery/validation.py} +5 -14
- package/runtime/python/okstra_ctl/phases/project_analysis/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/project_analysis/boundary.json +8 -0
- package/runtime/python/okstra_ctl/phases/project_analysis/entry.py +11 -0
- package/runtime/python/okstra_ctl/{report_html/view_models/project_analysis.py → phases/project_analysis/report.py} +3 -3
- package/runtime/python/okstra_ctl/phases/project_analysis/spec.md +33 -0
- package/runtime/python/okstra_ctl/phases/project_analysis/validation.py +55 -0
- package/runtime/python/okstra_ctl/phases/release_handoff/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/release_handoff/boundary.json +17 -0
- package/runtime/python/okstra_ctl/phases/release_handoff/entry.py +147 -0
- package/runtime/python/okstra_ctl/phases/release_handoff/operations.py +446 -0
- package/runtime/{prompts/profiles/release-handoff.md → python/okstra_ctl/phases/release_handoff/profile.md} +3 -3
- package/runtime/python/okstra_ctl/{report_html/view_models/release_handoff.py → phases/release_handoff/report.py} +3 -3
- package/runtime/{templates/reports → python/okstra_ctl/phases/release_handoff/report_assets}/release-handoff-input.template.md +1 -1
- package/{docs/task-process/release-handoff.md → runtime/python/okstra_ctl/phases/release_handoff/spec.md} +22 -9
- package/runtime/python/okstra_ctl/phases/release_handoff/wizard.py +84 -0
- package/runtime/python/okstra_ctl/phases/requirements_discovery/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/requirements_discovery/boundary.json +9 -0
- package/runtime/{prompts/profiles/requirements-discovery.md → python/okstra_ctl/phases/requirements_discovery/profile.md} +2 -3
- package/runtime/python/okstra_ctl/{report_html/view_models/requirements_discovery.py → phases/requirements_discovery/report.py} +3 -3
- package/{docs/task-process/requirements-discovery.md → runtime/python/okstra_ctl/phases/requirements_discovery/spec.md} +25 -6
- package/runtime/{validators/validate_fanout.py → python/okstra_ctl/phases/requirements_discovery/validation.py} +11 -12
- package/runtime/python/okstra_ctl/phases/technical_verification/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/technical_verification/boundary.json +9 -0
- package/runtime/python/okstra_ctl/phases/technical_verification/entry.py +100 -0
- package/runtime/{prompts/profiles/technical-verification.md → python/okstra_ctl/phases/technical_verification/profile.md} +1 -1
- package/runtime/python/okstra_ctl/{report_html/view_models/technical_verification.py → phases/technical_verification/report.py} +2 -2
- package/runtime/python/okstra_ctl/phases/technical_verification/spec.md +37 -0
- package/runtime/python/okstra_ctl/phases/technical_verification/validation.py +90 -0
- package/runtime/python/okstra_ctl/plan_approval.py +70 -0
- package/runtime/python/okstra_ctl/plan_items_cli.py +2 -2130
- package/runtime/python/okstra_ctl/profile_show.py +9 -3
- package/runtime/python/okstra_ctl/render.py +9 -2
- package/runtime/python/okstra_ctl/render_final_report.py +3 -2
- package/runtime/python/okstra_ctl/report_assembly.py +14 -93
- package/runtime/python/okstra_ctl/report_html/context_links.py +1 -1
- package/runtime/python/okstra_ctl/report_html/render.py +3 -2
- package/runtime/python/okstra_ctl/report_html/router.py +9 -33
- package/runtime/python/okstra_ctl/report_projections.py +1 -36
- package/runtime/python/okstra_ctl/report_routing.py +23 -0
- package/runtime/python/okstra_ctl/report_synthesis_packet.py +4 -73
- package/runtime/python/okstra_ctl/report_template_loader.py +35 -0
- package/runtime/python/okstra_ctl/report_validation_identity.py +38 -0
- package/runtime/python/okstra_ctl/report_views.py +18 -2
- package/runtime/python/okstra_ctl/run.py +113 -503
- package/runtime/python/okstra_ctl/stage_map.py +13 -0
- package/runtime/python/okstra_ctl/stage_targets.py +9 -286
- package/runtime/python/okstra_ctl/technical_verification_facts.py +52 -0
- package/runtime/python/okstra_ctl/user_response.py +199 -4
- package/runtime/python/okstra_ctl/verification_target.py +1 -1
- package/runtime/python/okstra_ctl/wizard/__init__.py +31 -31
- package/runtime/python/okstra_ctl/wizard/api.py +18 -0
- package/runtime/python/okstra_ctl/wizard/outcome.py +3 -12
- package/runtime/python/okstra_ctl/wizard/registry.py +20 -12
- package/runtime/python/okstra_ctl/wizard/state.py +6 -2
- package/runtime/python/okstra_ctl/wizard/steps_analysis.py +0 -97
- package/runtime/python/okstra_ctl/wizard/steps_plan.py +27 -278
- package/runtime/python/okstra_ctl/wizard/steps_roles.py +2 -1
- package/runtime/python/okstra_ctl/work_categories.py +1 -1
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +36 -0
- package/runtime/python/okstra_ctl/workflow.py +26 -143
- package/runtime/skills/okstra-brief-gen/SKILL.md +3 -3
- package/runtime/skills/okstra-run/SKILL.md +1 -1
- package/runtime/skills/okstra-user-response/SKILL.md +23 -4
- package/runtime/templates/reports/quick-input.template.md +1 -1
- package/runtime/templates/reports/task-brief.template.md +1 -1
- package/runtime/validators/validate-brief.py +2 -2
- package/runtime/validators/validate-run.py +287 -4091
- package/runtime/validators/validate_analysis_report.py +14 -126
- package/docs/task-process/README.md +0 -82
- package/docs/task-process/common-flow.md +0 -173
- package/runtime/python/okstra_ctl/report_html/view_models/implementation_planning.py +0 -147
- package/runtime/python/okstra_ctl/technical_verification.py +0 -195
- /package/runtime/{prompts/profiles/change-impact-analysis.json → python/okstra_ctl/phases/change_impact_analysis/profile.json} +0 -0
- /package/runtime/{prompts/profiles/change-impact-analysis.md → python/okstra_ctl/phases/change_impact_analysis/profile.md} +0 -0
- /package/runtime/{templates/reports → python/okstra_ctl/phases/change_impact_analysis/report_assets}/change-impact-analysis-input.template.md +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/change_impact_analysis/report_assets}/change-impact-analysis.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/change_impact_analysis/report_assets}/change-impact-analysis.template.md +0 -0
- /package/runtime/{prompts/profiles/error-analysis.json → python/okstra_ctl/phases/error_analysis/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/error_analysis/report_assets}/error-analysis.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/error_analysis/report_assets}/error-analysis.template.md +0 -0
- /package/runtime/{prompts/profiles/feature-analysis.json → python/okstra_ctl/phases/feature_analysis/profile.json} +0 -0
- /package/runtime/{prompts/profiles/feature-analysis.md → python/okstra_ctl/phases/feature_analysis/profile.md} +0 -0
- /package/runtime/{templates/reports → python/okstra_ctl/phases/feature_analysis/report_assets}/feature-analysis-input.template.md +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/feature_analysis/report_assets}/feature-analysis.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/feature_analysis/report_assets}/feature-analysis.template.md +0 -0
- /package/runtime/{prompts/profiles/final-verification.json → python/okstra_ctl/phases/final_verification/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/final_verification/report_assets}/final-verification.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/final_verification/report_assets}/final-verification.template.md +0 -0
- /package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-diff-review.md +0 -0
- /package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-self-check.md +0 -0
- /package/runtime/{prompts/profiles/implementation.json → python/okstra_ctl/phases/implementation/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/implementation/report_assets}/implementation.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/implementation/report_assets}/implementation.template.md +0 -0
- /package/runtime/{prompts/profiles/implementation-option-selection.json → python/okstra_ctl/phases/implementation_option_selection/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/implementation_option_selection/report_assets}/implementation-option-selection.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/implementation_option_selection/report_assets}/implementation-option-selection.template.md +0 -0
- /package/runtime/{prompts/host-orchestration/implementation-planning.md → python/okstra_ctl/phases/implementation_planning/host-rules.md} +0 -0
- /package/runtime/{prompts/profiles/implementation-planning.json → python/okstra_ctl/phases/implementation_planning/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/implementation_planning/report_assets}/implementation-planning.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/implementation_planning/report_assets}/implementation-planning.template.md +0 -0
- /package/runtime/{prompts/profiles/improvement-discovery.json → python/okstra_ctl/phases/improvement_discovery/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/improvement_discovery/report_assets}/improvement-discovery.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/improvement_discovery/report_assets}/improvement-discovery.template.md +0 -0
- /package/runtime/{prompts/profiles/project-analysis.json → python/okstra_ctl/phases/project_analysis/profile.json} +0 -0
- /package/runtime/{prompts/profiles/project-analysis.md → python/okstra_ctl/phases/project_analysis/profile.md} +0 -0
- /package/runtime/{templates/reports → python/okstra_ctl/phases/project_analysis/report_assets}/project-analysis-input.template.md +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/project_analysis/report_assets}/project-analysis.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/project_analysis/report_assets}/project-analysis.template.md +0 -0
- /package/runtime/{prompts/profiles/release-handoff.json → python/okstra_ctl/phases/release_handoff/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/release_handoff/report_assets}/release-handoff.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/release_handoff/report_assets}/release-handoff.template.md +0 -0
- /package/runtime/python/okstra_ctl/{fanout.py → phases/requirements_discovery/fanout.py} +0 -0
- /package/runtime/{prompts/profiles/requirements-discovery.json → python/okstra_ctl/phases/requirements_discovery/profile.json} +0 -0
- /package/runtime/{templates/reports → python/okstra_ctl/phases/requirements_discovery/report_assets}/fan-out-unit.template.md +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/requirements_discovery/report_assets}/requirements-discovery.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/requirements_discovery/report_assets}/requirements-discovery.template.md +0 -0
- /package/runtime/{prompts/profiles/technical-verification.json → python/okstra_ctl/phases/technical_verification/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/technical_verification/report_assets}/technical-verification.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/technical_verification/report_assets}/technical-verification.template.md +0 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""final-verification 준비 중 이 단계가 소유하는 대상 고정.
|
|
2
|
+
|
|
3
|
+
공통 조립부는 CLI 값과 diff 요약을 넘긴다. 대상 요청, 렌더 문맥 기록,
|
|
4
|
+
스냅샷 다이제스트는 여기서 계산한다. 이 모듈은 공통 실행 조립부를 import
|
|
5
|
+
하지 않는다.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import hashlib
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from okstra_ctl.phases.final_verification.target import (
|
|
13
|
+
FinalVerificationTargetAcquisition,
|
|
14
|
+
FinalVerificationTargetRequest,
|
|
15
|
+
)
|
|
16
|
+
from okstra_ctl.prepare_error import PrepareError
|
|
17
|
+
from okstra_ctl.stage_targets import FinalVerificationTarget
|
|
18
|
+
from okstra_ctl.worktree import WorktreeProvision
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def reject_prepare_flags(*, approve_plan_ack: bool, implementation_option: str) -> None:
|
|
22
|
+
"""승인과 구현 방향 적용은 implementation 준비의 일이다."""
|
|
23
|
+
if approve_plan_ack:
|
|
24
|
+
raise PrepareError(
|
|
25
|
+
"--approve is only meaningful with --task-type implementation "
|
|
26
|
+
"and --approved-plan <path>"
|
|
27
|
+
)
|
|
28
|
+
if implementation_option:
|
|
29
|
+
raise PrepareError(
|
|
30
|
+
"--implementation-option is only meaningful with --task-type "
|
|
31
|
+
"implementation and --approved-plan <path>"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def single_stage_worktree() -> WorktreeProvision:
|
|
36
|
+
"""선택한 stage 원장 행이 정해지기 전까지 두는 자리."""
|
|
37
|
+
return WorktreeProvision(
|
|
38
|
+
status="deferred-final-verification",
|
|
39
|
+
note=(
|
|
40
|
+
"final-verification single-stage uses the selected implementation "
|
|
41
|
+
"stage worktree from the registry"
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def verification_target_request(
|
|
47
|
+
*,
|
|
48
|
+
project_root: str,
|
|
49
|
+
project_id: str,
|
|
50
|
+
task_group: str,
|
|
51
|
+
task_id: str,
|
|
52
|
+
work_category: str,
|
|
53
|
+
approved_plan_path: str,
|
|
54
|
+
stage: str,
|
|
55
|
+
stage_map: list[dict],
|
|
56
|
+
) -> FinalVerificationTargetRequest:
|
|
57
|
+
"""``stage`` 가 ``auto`` 이면 대상 선택을 비운다. 호출부가 기본값을 고르지 않는다."""
|
|
58
|
+
selected = int(stage) if stage and stage != "auto" else None
|
|
59
|
+
return FinalVerificationTargetRequest(
|
|
60
|
+
project_root=Path(project_root),
|
|
61
|
+
project_id=project_id,
|
|
62
|
+
task_group=task_group,
|
|
63
|
+
task_id=task_id,
|
|
64
|
+
work_category=work_category,
|
|
65
|
+
approved_plan_path=Path(approved_plan_path),
|
|
66
|
+
stage=selected,
|
|
67
|
+
stage_map=tuple(stage_map),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def apply_verification_target(
|
|
72
|
+
ctx: dict,
|
|
73
|
+
acquisition: FinalVerificationTargetAcquisition,
|
|
74
|
+
diff_stat: str,
|
|
75
|
+
) -> None:
|
|
76
|
+
"""획득한 검증 대상을 렌더 문맥에 적는다. diff 요약은 호출부가 계산한다."""
|
|
77
|
+
target = acquisition.target
|
|
78
|
+
if target.scope == "single-stage":
|
|
79
|
+
stage = target.stages[0]
|
|
80
|
+
ctx["EXECUTOR_WORKTREE_PATH"] = target.worktree_path
|
|
81
|
+
ctx["EXECUTOR_WORKTREE_BRANCH"] = acquisition.worktree_branch
|
|
82
|
+
ctx["EXECUTOR_WORKTREE_BASE_REF"] = target.base
|
|
83
|
+
ctx["EXECUTOR_WORKTREE_STATUS"] = "reused-stage"
|
|
84
|
+
ctx["EXECUTOR_WORKTREE_NOTE"] = (
|
|
85
|
+
f"final-verification uses implementation stage {stage} worktree"
|
|
86
|
+
)
|
|
87
|
+
if acquisition.integration_result is not None:
|
|
88
|
+
ctx["STAGE_INTEGRATION"] = _format_integration(acquisition.integration_result)
|
|
89
|
+
if acquisition.relocations:
|
|
90
|
+
moved = "\n".join(
|
|
91
|
+
f"- stage {row['stage']}: `{row['from']}` → `{row['to']}`"
|
|
92
|
+
for row in acquisition.relocations
|
|
93
|
+
)
|
|
94
|
+
ctx["STAGE_INTEGRATION"] = (
|
|
95
|
+
f"{ctx.get('STAGE_INTEGRATION', '')}\n"
|
|
96
|
+
"Nested stage worktrees moved out of the verification worktree "
|
|
97
|
+
"(registry updated; contents and branches unchanged):\n"
|
|
98
|
+
f"{moved}"
|
|
99
|
+
).strip()
|
|
100
|
+
ctx["VERIFICATION_SCOPE"] = target.scope
|
|
101
|
+
ctx["VERIFICATION_WORKTREE_PATH"] = target.worktree_path
|
|
102
|
+
ctx["VERIFICATION_BASE_REF"] = target.base
|
|
103
|
+
ctx["VERIFICATION_HEAD_REF"] = target.head
|
|
104
|
+
ctx["VERIFICATION_TARGET"] = _format_verification_target(target, diff_stat)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def write_verification_target_snapshot(
|
|
108
|
+
instruction_set: Path,
|
|
109
|
+
target_markdown: str,
|
|
110
|
+
) -> tuple[Path, str]:
|
|
111
|
+
"""정규화한 검증 대상 스냅샷을 쓰고 그 다이제스트를 돌려준다."""
|
|
112
|
+
normalized = target_markdown.replace("\r\n", "\n").replace("\r", "\n")
|
|
113
|
+
normalized = normalized.rstrip() + "\n"
|
|
114
|
+
digest = "sha256:" + hashlib.sha256(normalized.encode("utf-8")).hexdigest()
|
|
115
|
+
path = instruction_set / "verification-target.md"
|
|
116
|
+
# 계산 규칙을 값과 함께 적는다. 워커는 이 다이제스트를 프롬프트 앵커로도
|
|
117
|
+
# 받는데, 규칙을 모르면 파일 전체 바이트로 재고 반드시 불일치를 본다 —
|
|
118
|
+
# 실측(2026-08-26): 그렇게 잰 검증자가 스냅샷이 변조됐다고 보고했다.
|
|
119
|
+
# 다이제스트 줄은 줄머리 앵커로 잘리므로(`_TARGET_DIGEST_RE`) 그 뒤에
|
|
120
|
+
# 붙는 이 줄은 본문에 들어가지 않는다.
|
|
121
|
+
path.write_text(
|
|
122
|
+
normalized
|
|
123
|
+
+ f"- **Verification target digest:** `{digest}`\n"
|
|
124
|
+
+ "- **Digest rule:** `sha256` of the text above this line, with CRLF "
|
|
125
|
+
"and CR normalized to LF, trailing whitespace stripped, and exactly "
|
|
126
|
+
"one closing newline. This line and the digest line are not covered.\n",
|
|
127
|
+
encoding="utf-8",
|
|
128
|
+
)
|
|
129
|
+
return path, digest
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _format_verification_target(
|
|
133
|
+
target: FinalVerificationTarget,
|
|
134
|
+
diff_stat: str,
|
|
135
|
+
) -> str:
|
|
136
|
+
reports = "\n".join(
|
|
137
|
+
f" - stage {s}: `{rp or '(report_path unrecorded)'}`"
|
|
138
|
+
for s, rp in zip(target.stages, target.reports)
|
|
139
|
+
)
|
|
140
|
+
return (
|
|
141
|
+
f"- **Verification scope:** `{target.scope}`\n"
|
|
142
|
+
f"- **Worktree:** `{target.worktree_path}`\n"
|
|
143
|
+
f"- **Verification base ref:** `{target.base}`\n"
|
|
144
|
+
f"- **Verification head ref:** `{target.head}`\n"
|
|
145
|
+
f"- **Stages under verification:** {target.stages}\n"
|
|
146
|
+
f"- **Source implementation reports:**\n{reports}\n"
|
|
147
|
+
f"- **Verification diff stat:**\n```\n{diff_stat}\n```"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _format_integration(integ) -> str:
|
|
152
|
+
"""stage 자동 통합 결과를 사람이 읽을 한국어 마크다운 블록으로 만든다."""
|
|
153
|
+
def _csv(xs):
|
|
154
|
+
return ", ".join(str(x) for x in xs) if xs else "없음"
|
|
155
|
+
|
|
156
|
+
skipped = "; ".join(f"stage {n}({why})" for n, why in integ.teardown_skipped)
|
|
157
|
+
lines = [
|
|
158
|
+
"- **Stage 자동 통합 결과** (whole-task final-verification):",
|
|
159
|
+
"- **머지된 stage:** " + _csv(integ.merged),
|
|
160
|
+
"- **이미 머지됨:** " + _csv(integ.already_merged),
|
|
161
|
+
"- **정리(teardown)된 stage:** " + _csv(integ.torn_down),
|
|
162
|
+
"- **정리 보류:** " + (skipped or "없음"),
|
|
163
|
+
]
|
|
164
|
+
for warning in integ.warnings:
|
|
165
|
+
lines.append("- **경고:** " + warning)
|
|
166
|
+
return "\n".join(lines)
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- Primary focus areas (each maps to a deliverable section below):
|
|
14
14
|
- Acceptance-gating — a failure here pushes the verdict toward `blocked` / `conditional-accept`:
|
|
15
15
|
- requirement & acceptance coverage — every must-pass point in the brief's `## Expected Behavior` / `## Preserved Behavior` / `## Expected Outcome` (and the approved plan's requirements) is covered with a cited artifact or raised as an Acceptance Blocker; no silent omissions
|
|
16
|
-
- over-delivery — every surface the merged diff **adds** is traced back to a requirement. Enumerate them: each identifier, module, and configuration entry the diff introduces, searched for its callers across the whole repository (a declaration, its own test, or a commented-out line is not a caller). Record one `addedSurfaceAudit` row per surface with its disposition. `traced` names the brief requirement it serves. `exempt` names one of the legitimate exits and cites it — the approved plan reserves it for a named later stage, or something outside project code calls it (framework entrypoint, implemented interface method, migration hook, published-package API). `over-delivery` is everything else, and it is graded by callers: **no caller anywhere** is an Acceptance Blocker (delete it, or fold an added parameter back into its single call site), while **called but serving no requirement** is a Conditional Acceptance Condition with `blocksReleaseHandoff: false` — the judgement there rests on reading intent, so it travels to the PR body instead of stopping the release. The baseline is the brief, not the approved plan: a surface the plan authorised but no requirement asked for is still over-delivery, and this is the last gate that can see it. **Enforced:** `
|
|
16
|
+
- over-delivery — every surface the merged diff **adds** is traced back to a requirement. Enumerate them: each identifier, module, and configuration entry the diff introduces, searched for its callers across the whole repository (a declaration, its own test, or a commented-out line is not a caller). Record one `addedSurfaceAudit` row per surface with its disposition. `traced` names the brief requirement it serves. `exempt` names one of the legitimate exits and cites it — the approved plan reserves it for a named later stage, or something outside project code calls it (framework entrypoint, implemented interface method, migration hook, published-package API). `over-delivery` is everything else, and it is graded by callers: **no caller anywhere** is an Acceptance Blocker (delete it, or fold an added parameter back into its single call site), while **called but serving no requirement** is a Conditional Acceptance Condition with `blocksReleaseHandoff: false` — the judgement there rests on reading intent, so it travels to the PR body instead of stopping the release. The baseline is the brief, not the approved plan: a surface the plan authorised but no requirement asked for is still over-delivery, and this is the last gate that can see it. **Enforced:** `scripts/okstra_ctl/phases/final_verification/validation.py` `_validate_added_surface_audit` refuses a `traced` row naming no requirement, and an `over-delivery` row whose note does not cite the `AB-NNN` / `CA-NNN` row it became.
|
|
17
17
|
- delivered artifacts match recorded expected values in `reference-expectations` (config files, deployment manifests, other recorded expected states); when reference-expectations are absent, record it as missing information rather than assuming a match
|
|
18
18
|
- test & validation suite pass status — independently re-run the read-only two-tier command set (Tier 1 = brief/approved-plan `validation`, Tier 2 = `project.json` `qaCommands`) and confirm each passes on the verified head, citing exact command + exit code
|
|
19
19
|
- test correctness — delivered tests actually assert the intended behaviour: no gutted/weakened assertions, no tautological or always-passing tests, no tests exercising only mocks; new behaviour has matching coverage. For an `external-interface` / `transformation-mapping` surface specifically, treat a test whose only oracle is a self-authored synthetic fixture (no captured-real-sample provenance) as NOT establishing external correctness — it shows only that the parser agrees with its author's assumed shape, never that the shape matches reality; record that surface's external correctness as a user-owned external advisory gap (a Residual Risk carrying the exact "capture a real sample and confirm" next step, per the Coverage check in the self-review pass below), never as covered — the same non-blocking treatment the External QA advisory policy gives a live external check
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
- **single-stage scope** (`--stage N`): prep verified stage N is `status:done` and its isolated stage worktree exists and is clean. Other stages' state is irrelevant. A single-stage run is a partial verification of one stage, and that is exactly the unit release-handoff ships: an `accepted` verdict here makes the stage PR-eligible, so `release-handoff` is the routing target. It says nothing about any other stage.
|
|
35
35
|
- the lead still captures `git status --short` from the injected worktree to confirm the analysis ran against the delivered work-tree state; an unexpected divergence (dirty tree outside `.okstra/`, missing worktree) is a `tool-failure`, not a silent proceed.
|
|
36
36
|
- Worker verification procedure:
|
|
37
|
-
- **Target confirmation:** analyse the injected target and nothing else. Read `verification-target.md` for the stage/report mapping and the complete diff stat. Prepare fixed that target and `validators/validate-run.py`
|
|
37
|
+
- **Target confirmation:** analyse the injected target and nothing else. Read `verification-target.md` for the stage/report mapping and the complete diff stat. Prepare fixed that target and `phases/final_verification/validation.py` `validate_verification_target_match` (called by `validators/validate-run.py`) re-checks the report against its digest, so the procedure to follow here is simply: if the worktree you can see does not match the injected target, record a `tool-failure` — never reselect a target.
|
|
38
38
|
- **Evidence:** attach file:line, exact command + exit code, log excerpt, or MCP SELECT evidence to every finding. Mark a requirement as covered only when the cited artifact demonstrates it.
|
|
39
|
-
- **Tier 1 and Tier 2 read-only validation:** Tier 1 is the originating brief/approved plan `validation` set. Tier 2 is the `Project QA Commands` section from `okstra model-io project-context --project-root <PROJECT_ROOT> --task-ref <
|
|
39
|
+
- **Tier 1 and Tier 2 read-only validation:** Tier 1 is the originating brief/approved plan `validation` set. Tier 2 is the `Project QA Commands` section from `okstra model-io project-context --project-root <PROJECT_ROOT> --task-ref <TASK_KEY>` (the full `Task key` your dispatch prompt names). Do not auto-detect commands from package manifests. A missing tier is `qa-command not configured: <category>`. Before execution, reject commands containing source/lockfile mutation tokens such as `--fix`, `--write`, ` -w`, ` -u`, `--snapshot-update`, `INSTA_UPDATE=<not-no>`, `cargo update`, or `npm install` without `ci`; record the exact denied token. Tier 2 is already screened by prepare, so this check catches a Tier 1 command the brief or plan named.
|
|
40
40
|
- **External QA outcome policy:** continue to attempt every in-scope Tier 3
|
|
41
41
|
command. For an entry requiring `db`, `http`, or `external`, record non-PASS
|
|
42
42
|
as a Tier 3 `advisory` command, add a user-owned Residual Risk and exact
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
- **Could-not-verify honesty:** use `not-configured`, `env-unavailable`, `rejected`, `gap`, or `blocked` as appropriate. Never convert unavailable evidence into an executed/pass claim.
|
|
58
58
|
- **Source-mutation prohibition:** verification may write only assigned okstra run artifacts. Do not edit source, schema, deployment, lockfile, or configuration files; route detected defects to a later phase.
|
|
59
59
|
- Required deliverable shape (final report, in addition to the standard sections):
|
|
60
|
-
- **Source Implementation Report(s)** (**Enforced:** `validators/validate-run.py`
|
|
60
|
+
- **Source Implementation Report(s)** (**Enforced:** `phases/final_verification/validation.py` `validate_verification_target_match` (called by `validators/validate-run.py`) compares `verificationScope`, `worktreePath`, `implementationBaseRef`, `capturedHeadSha`, and the `stageReports` stage set against the digest-verified `instruction-set/verification-target.md`; a snapshot whose digest no longer checks out is ignored rather than trusted. `verificationScope` in particular gates both stage-group eligibility and release-handoff routing, so it is not the report's to restate): the `VERIFICATION_TARGET` snapshot verbatim — verification scope, worktree path, base/head refs, the list of stages under verification, and one row per stage citing its originating implementation final-report (`report_path` from `consumers.jsonl`; render `(report_path unrecorded)` when absent). Every analyser prompt carries the same compact target identity (`**Verification scope:** / **Worktree:** / **Verification base ref:** / **Verification head ref:** / **Verification target path:** / **Verification target digest:**`) and reads the sidecar on demand for the complete diff stat. A worker that cannot confirm its analysis ran against that worktree's delivered diff MUST record a `tool-failure`.
|
|
61
61
|
- **Verdict vocabulary**: Section 7 (`Final Verdict`) MUST include a `Verdict Token` field whose value is exactly one of `accepted`, `conditional-accept`, or `blocked`. `conditional-accept` requires an explicit, exhaustive list of conditions; ambiguous verdicts ("looks good", "mostly ready") are not allowed. Each condition MUST be recorded as a row in the **Conditional Acceptance Conditions** deliverable (`id` `CA-NNN`, `condition`, `evidenceRequired`, `blocksReleaseHandoff`). `blocksReleaseHandoff` is a gate, not a note: `false` means this condition alone would not stop the release, and a `conditional-accept` whose conditions are all `false` may route to `release-handoff` (the conditions travel into the PR body as unresolved items). Declare `true` for anything that must be settled before release. The validator enforces verdict↔deliverable consistency: `accepted` ⇒ zero acceptance blockers, `blocked` ⇒ at least one, `conditional-accept` ⇒ at least one condition, and a `release-handoff` routing recommendation is allowed only when the verdict is release-ready by `okstra_ctl.release_gate.release_handoff_allowed`. **Any Acceptance Blocker therefore forces the verdict off `accepted` (to `conditional-accept` or `blocked`); the gates below cite this rule instead of restating the arithmetic.**
|
|
62
62
|
- **Added-surface audit** (`finalVerification.addedSurfaceAudit`): the reverse of requirement coverage — one row per surface the merged diff added (`id` `AS-NNN`, `surface` as `path:line` + the added name, `callers`, `requirement`, `disposition`, `note`). Requirement coverage proves every requirement reached the diff; this table proves every addition answers a requirement. An empty array is a claim that the diff added no identifier, module, or configuration entry, not permission to skip the enumeration. Single-stage scope audits its own stage's diff; whole-task audits the merged diff, which is the only place a surface added by one stage and orphaned by another is visible.
|
|
63
63
|
- **Acceptance Blockers block** (under section 4): one row per blocker with `id`, `severity` (`critical` / `major`), evidence (file path, log excerpt, or test output), and the recommended follow-up phase: `error-analysis` for a cause problem, `implementation-option-selection` for a direction problem, or `implementation-planning` for a detailed-plan problem. Empty block is acceptable and preferred — render the single line `- No acceptance blockers found.`
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
- **Validation Evidence**: for every requirement in the originating plan or task brief, cite the artifact (commit SHA, test output, log line, MCP SELECT result) that demonstrates coverage. Paraphrased "verified" claims without an artifact are rejected.
|
|
66
66
|
- **Read-only command log**: any pre-existing test/validation command touched during this run MUST be listed with its exact command line and one honest status — `executed` (ran; carries its exit code) / `advisory` (external Tier 3 did not PASS; carries observed/expected results and remains user-owned) / `env-unavailable` (should run but cannot in this environment — missing replica DB, container, or service; carries the reason, never a faked pass) / `not-configured` (no such qa-command tier) / `rejected` (a mutating/denied token — skipped, carries the denied token). A check that could not run locally is recorded as `env-unavailable` or `advisory` according to the external QA policy — never silently dropped and never reported as `executed` with an invented exit code. Mutating-command prohibition is the shared read-only boundary (see Non-goals); it is not restated per row.
|
|
67
67
|
- **Could-not-verify roll-up (§5.8.9)**: the template mechanically aggregates every not-confirmed check into one scannable list — `gap` requirement-coverage rows, `advisory` / `not-configured` / `env-unavailable` / `rejected` command rows, and `blocked` manual tests. You do not hand-author it, but you MUST give those rows their honest status so nothing unverified hides across sections: a check silently recorded as `executed`/`covered` will not surface in the roll-up. This is okstra's answer to "say what could not be verified this run."
|
|
68
|
-
- **Routing recommendation**:
|
|
68
|
+
- **Routing recommendation**: this phase records the verdict, the blockers, the conditions, and the repair each blocker needs. The lead chooses the next phase from the `## final-verification` section of `prompts/lead/phase-routing.md`, which lists the allowed targets and the shape of `finalVerification.routingRecommendation`. Read that section before writing the field.
|
|
69
69
|
- **Verified-row recording** (both scopes): when the verdict is release-ready, the lead MUST run `okstra handoff record-verified --plan-run-root <plan-run-root> --stage <N> --report-path <final-report data.json path> --data-json <final-report data.json path>` and quote the command + exit code in the report. Pass the record path to both: the Markdown reading copy is rendered on request and does not exist in a finished run (ADR-0014), and the helper normalizes either path to the record anyway. A `whole-task` report clears every stage in its own `stageReports`, so run it **once per those stages** — each run writes that stage's row from this one report. Without those rows the stage is never offered a pull request, and release-handoff opens one PR per stage. The helper checks the latest verification manifest, task/stage identity, report pointer, prepared target, and recorded implementation commit. It records the captured commit and original verdict, including conditional acceptance conditions. A missing target or mismatched commit requires re-verification. Recording happens before final validation; eligibility is granted only after that verification passes validation. **Enforced:** `okstra_ctl.handoff_verification` validates the evidence, and `validators/validate-run.py` `_validate_verified_row_recorded` requires a `verified` row matching this report, captured commit, and verdict.
|
|
70
70
|
- Clarification request policy (phase-specific addendum — shared policy is in `_common-contract.md`):
|
|
71
71
|
- populate `## 1. Clarification Items` only when a blocker hinges on information only the user can supply (deployment intent, intended target environment, business-rule interpretation); use `Blocks=next-phase` for items that gate continuing to release-handoff
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"""Human-first final-verification view model."""
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
-
from
|
|
5
|
-
|
|
6
|
-
from
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from okstra_ctl.release_gate import release_handoff_allowed
|
|
7
|
+
from okstra_ctl.report_html.common import evidence_index
|
|
8
|
+
from okstra_ctl.report_html.models import HumanReportView
|
|
9
|
+
from okstra_ctl.verification_target import read_verification_target
|
|
7
10
|
|
|
8
11
|
# Record fields this template anchors as `id-<row id>` (see
|
|
9
12
|
# `HumanReportView.anchored_fields`); ids elsewhere land in the ledger.
|
|
@@ -16,6 +19,12 @@ ANCHORED_FIELDS = (
|
|
|
16
19
|
)
|
|
17
20
|
|
|
18
21
|
|
|
22
|
+
def verification_scope(project_root: Path, relative: str) -> str:
|
|
23
|
+
"""준비된 검증 대상에서 범위를 읽는다. 파서는 공통 계약이 소유한다."""
|
|
24
|
+
target = read_verification_target(project_root, relative)
|
|
25
|
+
return str((target or {}).get("scope") or "").strip()
|
|
26
|
+
|
|
27
|
+
|
|
19
28
|
def build_final_verification_view(data: dict) -> HumanReportView:
|
|
20
29
|
final = data["finalVerification"]
|
|
21
30
|
verdict_token = data["finalVerdict"]["verdictToken"]
|
|
@@ -85,7 +85,7 @@ taskType: "{{FM_TASK_TYPE}}"
|
|
|
85
85
|
|
|
86
86
|
> Verifiers MUST NOT extend acceptance checks, regression scans, or sign-off recommendations into items listed here. If a verifier believes an excluded item must pass before release, it is reported as a recommended follow-up verification task in the final report — never silently included in the pass/fail decision of this run. If this section is left empty, verifiers treat any check beyond what `Acceptance Criteria` enumerates as out of scope by default.
|
|
87
87
|
|
|
88
|
-
**Enforced (delivery only):** `tests/contract/test_scope_boundary_delivery.py` pins that a filled section reaches every analysis worker through `okstra_ctl.analysis_packet` — drop it from `CANONICAL_BRIEF_SECTIONS` and every run's exclusions vanish silently. The exclusions themselves are prose and are **not** machine-checked: only the codebase-scan `out-of-scope` frontmatter is a path list, and `
|
|
88
|
+
**Enforced (delivery only):** `tests/contract/test_scope_boundary_delivery.py` pins that a filled section reaches every analysis worker through `okstra_ctl.analysis_packet` — drop it from `CANONICAL_BRIEF_SECTIONS` and every run's exclusions vanish silently. The exclusions themselves are prose and are **not** machine-checked: only the codebase-scan `out-of-scope` frontmatter is a path list, and `scripts/okstra_ctl/phases/improvement_discovery/validation.py` checks that one.
|
|
89
89
|
|
|
90
90
|
## Config and Deployment Verification Targets
|
|
91
91
|
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
# final-verification
|
|
1
|
+
# final-verification
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This directory is the canonical home of the final-verification phase. Report field shapes stay in `schemas/final-report-v2.0.schema.json` and `schemas/final-report-v3.0.schema.json` under `finalVerification`. The next phase is chosen in `prompts/lead/phase-routing.md`.
|
|
4
|
+
|
|
5
|
+
## Guarantees
|
|
6
|
+
|
|
7
|
+
| ID | Guarantee | Enforcement |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| FV-1 | A report that does not match the prepared verification target is rejected | `scripts/okstra_ctl/phases/final_verification/validation.py::validate_verification_target_match` |
|
|
10
|
+
| FV-2 | A release-handoff route requires a release-ready verdict | `validators/validate-run.py::_refuse_unsuitable_final_verification_route` |
|
|
11
|
+
| FV-3 | The final-verification destination list matches the report schema | `tests/contract/test_phase_catalog.py::test_final_verification_routing_targets_match_the_report_schema` |
|
|
12
|
+
| FV-4 | The phase profile is not also stored under prompts/profiles | `tests/contract/test_phase_catalog.py::test_migrated_profile_is_absent_from_the_legacy_directory` |
|
|
13
|
+
|
|
14
|
+
## Process
|
|
15
|
+
|
|
16
|
+
### Index
|
|
4
17
|
|
|
5
18
|
- [1. Purpose](#1-purpose)
|
|
6
19
|
- [2. okstra-run wizard flow](#2-okstra-run-wizard-flow)
|
|
@@ -11,11 +24,11 @@
|
|
|
11
24
|
- [7. Forbidden actions](#7-forbidden-actions)
|
|
12
25
|
- [8. Verified code](#8-verified-code)
|
|
13
26
|
|
|
14
|
-
|
|
27
|
+
### 1. Purpose
|
|
15
28
|
|
|
16
29
|
`final-verification` determines whether the committed diff produced by `implementation` can be finally accepted. Without performing any source edit or follow-up fix, it confirms that the implementation report matches the actual checkout, then records acceptance blockers, residual risk, and a release recommendation.
|
|
17
30
|
|
|
18
|
-
|
|
31
|
+
### 2. okstra-run wizard flow
|
|
19
32
|
|
|
20
33
|
```mermaid
|
|
21
34
|
flowchart TD
|
|
@@ -36,7 +49,7 @@ Launch selection uses role slots and model refs only: current-session lead is th
|
|
|
36
49
|
|
|
37
50
|
This phase does not ask for `base-ref` directly. The wizard selects whole-task or a single stage from the approved plan's Stage Map, and prepare resolves `VERIFICATION_TARGET` from the registry / `consumers.jsonl` / git state.
|
|
38
51
|
|
|
39
|
-
|
|
52
|
+
### 3. entry gate
|
|
40
53
|
|
|
41
54
|
```mermaid
|
|
42
55
|
sequenceDiagram
|
|
@@ -69,7 +82,7 @@ prepare fixes the verification target before worker dispatch. If any of the foll
|
|
|
69
82
|
|
|
70
83
|
Once started, the lead treats `VERIFICATION_TARGET` as authoritative. It does not re-pick worktree/base/head/stage/source report from the brief.
|
|
71
84
|
|
|
72
|
-
|
|
85
|
+
### 4. Verification execution flow
|
|
73
86
|
|
|
74
87
|
```mermaid
|
|
75
88
|
flowchart TD
|
|
@@ -104,29 +117,30 @@ flowchart LR
|
|
|
104
117
|
|
|
105
118
|
The runtime validates the `project.json` `qaCommands` deny-list at the prepare stage for both `implementation` and `final-verification` (`okstra_ctl.run.validate_project_qa_commands`), so a Tier 2 declaration carrying a mutating token stops the run before it starts. Tier 1 comes from the brief or the approved plan and is not covered by that gate — the lead self-checks those commands right before execution.
|
|
106
119
|
|
|
107
|
-
|
|
120
|
+
### 5. Verdict and routing
|
|
108
121
|
|
|
109
122
|
```mermaid
|
|
110
123
|
flowchart TD
|
|
111
124
|
Verdict{Verdict Token}
|
|
112
|
-
Verdict -->|accepted|
|
|
125
|
+
Verdict -->|accepted| Ready[release-ready verdict recorded]
|
|
113
126
|
Verdict -->|conditional-accept| Conditions[conditions listed exhaustively]
|
|
114
|
-
Conditions --> Followup[route by cause, direction, or detailed-plan defect]
|
|
115
127
|
Verdict -->|blocked| Blockers[acceptance blockers with evidence]
|
|
116
|
-
|
|
128
|
+
Ready --> Routing[lead reads phase-routing.md]
|
|
129
|
+
Conditions --> Routing
|
|
130
|
+
Blockers --> Routing
|
|
117
131
|
```
|
|
118
132
|
|
|
119
133
|
`## 7. Final Verdict` must contain exactly one `Verdict Token` field, and its value is one of the following three.
|
|
120
134
|
|
|
121
|
-
- `accepted`:
|
|
122
|
-
- `conditional-accept`:
|
|
123
|
-
- `blocked`:
|
|
135
|
+
- `accepted`: the delivered work meets the acceptance gates
|
|
136
|
+
- `conditional-accept`: every condition is stated
|
|
137
|
+
- `blocked`: at least one acceptance blocker is recorded
|
|
124
138
|
|
|
125
|
-
|
|
139
|
+
The lead chooses the destination from `prompts/lead/phase-routing.md` using this verdict and the blocker facts. This phase does not choose it.
|
|
126
140
|
|
|
127
141
|
Vague phrasings such as "looks good" or "mostly ready" are not allowed.
|
|
128
142
|
|
|
129
|
-
|
|
143
|
+
### 6. Deliverables
|
|
130
144
|
|
|
131
145
|
```mermaid
|
|
132
146
|
flowchart TD
|
|
@@ -155,7 +169,7 @@ The final report requires at least the following.
|
|
|
155
169
|
- read-only command log and exit code
|
|
156
170
|
- next safe phase recommendation
|
|
157
171
|
|
|
158
|
-
|
|
172
|
+
### 7. Forbidden actions
|
|
159
173
|
|
|
160
174
|
```mermaid
|
|
161
175
|
flowchart TD
|
|
@@ -168,14 +182,17 @@ flowchart TD
|
|
|
168
182
|
FV -. forbidden .-> Hide[hide verifier dissent]
|
|
169
183
|
```
|
|
170
184
|
|
|
171
|
-
The stage merge of whole-task mode is a runtime-owned integration step that prepare performs; the matching teardown is a runtime-owned step too, but it runs after the verdict (Phase 7 `teardown-stages`) and only when the verdict clears the work for release. After that, lead verification is read-only. Source edit, follow-up fix, and scope expansion are all forbidden. When a defect is found, it is not fixed within the current run.
|
|
185
|
+
The stage merge of whole-task mode is a runtime-owned integration step that prepare performs; the matching teardown is a runtime-owned step too, but it runs after the verdict (Phase 7 `teardown-stages`) and only when the verdict clears the work for release. After that, lead verification is read-only. Source edit, follow-up fix, and scope expansion are all forbidden. When a defect is found, it is not fixed within the current run. The lead chooses the next phase from `prompts/lead/phase-routing.md` using the blocker facts this phase recorded.
|
|
172
186
|
|
|
173
|
-
|
|
187
|
+
### 8. Verified code
|
|
174
188
|
|
|
175
|
-
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
-
|
|
181
|
-
-
|
|
189
|
+
- `scripts/okstra_ctl/phases/final_verification/profile.md`
|
|
190
|
+
- `scripts/okstra_ctl/phases/final_verification/profile.json`
|
|
191
|
+
- `scripts/okstra_ctl/phases/final_verification/entry.py`
|
|
192
|
+
- `scripts/okstra_ctl/phases/final_verification/report.py`
|
|
193
|
+
- `scripts/okstra_ctl/phases/final_verification/validation.py` `_validate_added_surface_audit`
|
|
194
|
+
- `prompts/lead/phase-routing.md`
|
|
195
|
+
- `schemas/final-report-v2.0.schema.json` and `schemas/final-report-v3.0.schema.json` (`finalVerification`, `finalVerdict`, `routingRecommendation.target`)
|
|
196
|
+
- `scripts/okstra_ctl/phases/final_verification/report_assets/final-verification-input.template.md`
|
|
197
|
+
- `validators/validate-run.py`
|
|
198
|
+
- `scripts/okstra_ctl/release_gate.py`
|