Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ REPAIRED_CANDIDATE_PROMOTION_HANDOFF_SESSION_ID_ARG := $(if $(strip $(REPAIRED_C
REPAIRED_CANDIDATE_PROMOTION_HANDOFF_OPERATOR_REF ?= local_operator:unattributed
REPAIRED_CANDIDATE_PROMOTION_HANDOFF_STRICT ?=
REPAIRED_CANDIDATE_PROMOTION_HANDOFF_STRICT_ARG := $(if $(filter 1 true yes,$(strip $(REPAIRED_CANDIDATE_PROMOTION_HANDOFF_STRICT))),--strict,)
# A scoped product flow normally overrides producer outputs. A caller can instead
# supply a direct repaired-handoff input; command-line and environment values win.
product_workspace_repaired_handoff_input = $(if $(filter file,$(origin $(1))),$($(2)),$($(1)))
IDEA_TO_SPEC_REPAIR_SESSION_ACTIVE_CANDIDATE ?= runs/active_idea_to_spec_candidate.json
IDEA_TO_SPEC_REPAIR_SESSION_CLARIFICATION_REQUESTS ?= runs/idea_to_spec_clarification_requests.json
IDEA_TO_SPEC_REPAIR_SESSION_CLARIFICATION_ANSWERS ?= runs/idea_to_spec_clarification_answers.json
Expand Down Expand Up @@ -1170,8 +1173,32 @@ product-workspace-decision-backed-repair-chain:

.PHONY: product-workspace-repaired-promotion-handoff
product-workspace-repaired-promotion-handoff:
@$(MAKE) repaired-candidate-promotion-handoff REPAIRED_CANDIDATE_PROMOTION_HANDOFF_INTAKE="$(IDEA_EVENT_STORMING_INTAKE_OUTPUT)" REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CLARIFICATION_REQUESTS="$(IDEA_TO_SPEC_CLARIFICATION_OUTPUT)" REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CLARIFICATION_ANSWERS="$(IDEA_TO_SPEC_CLARIFICATION_ANSWERS_OUTPUT)" REPAIRED_CANDIDATE_PROMOTION_HANDOFF_ONTOLOGY_DECISIONS="$(PRODUCT_ONTOLOGY_GAP_REVIEW_DECISIONS_OUTPUT)" REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_INPUT="$(IDEA_TO_SPEC_ANSWER_RERUN_INPUT_OUTPUT)" REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_PREVIEW="$(IDEA_TO_SPEC_RERUN_PREVIEW_OUTPUT)" REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_MATERIALIZATION="$(IDEA_TO_SPEC_RERUN_MATERIALIZATION_OUTPUT)"
@$(MAKE) product-workspace-idea-maturity
@$(MAKE) repaired-candidate-promotion-handoff \
REPAIRED_CANDIDATE_PROMOTION_HANDOFF_INTAKE="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_INTAKE,IDEA_EVENT_STORMING_INTAKE_OUTPUT)" \
REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CLARIFICATION_REQUESTS="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CLARIFICATION_REQUESTS,IDEA_TO_SPEC_CLARIFICATION_OUTPUT)" \
REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CLARIFICATION_ANSWERS="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CLARIFICATION_ANSWERS,IDEA_TO_SPEC_CLARIFICATION_ANSWERS_OUTPUT)" \
REPAIRED_CANDIDATE_PROMOTION_HANDOFF_ONTOLOGY_DECISIONS="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_ONTOLOGY_DECISIONS,PRODUCT_ONTOLOGY_GAP_REVIEW_DECISIONS_OUTPUT)" \
REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_INPUT="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_INPUT,IDEA_TO_SPEC_ANSWER_RERUN_INPUT_OUTPUT)" \
REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_PREVIEW="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_PREVIEW,IDEA_TO_SPEC_RERUN_PREVIEW_OUTPUT)" \
REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_MATERIALIZATION="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_MATERIALIZATION,IDEA_TO_SPEC_RERUN_MATERIALIZATION_OUTPUT)"
@$(MAKE) product-workspace-idea-maturity \
IDEA_MATURITY_METRICS_INTAKE="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_INTAKE,IDEA_EVENT_STORMING_INTAKE_OUTPUT)" \
IDEA_MATURITY_METRICS_CANDIDATE_GRAPH="$(CANDIDATE_SPEC_GRAPH_OUTPUT)" \
IDEA_MATURITY_METRICS_PRE_SIB="$(PRE_SIB_COHERENCE_OUTPUT)" \
IDEA_MATURITY_METRICS_CLARIFICATION_REQUESTS="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CLARIFICATION_REQUESTS,IDEA_TO_SPEC_CLARIFICATION_OUTPUT)" \
IDEA_MATURITY_METRICS_CLARIFICATION_ANSWERS="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CLARIFICATION_ANSWERS,IDEA_TO_SPEC_CLARIFICATION_ANSWERS_OUTPUT)" \
IDEA_MATURITY_METRICS_ONTOLOGY_DECISIONS="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_ONTOLOGY_DECISIONS,PRODUCT_ONTOLOGY_GAP_REVIEW_DECISIONS_OUTPUT)" \
IDEA_MATURITY_METRICS_RERUN_INPUT="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_INPUT,IDEA_TO_SPEC_ANSWER_RERUN_INPUT_OUTPUT)" \
IDEA_MATURITY_METRICS_RERUN_PREVIEW="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_PREVIEW,IDEA_TO_SPEC_RERUN_PREVIEW_OUTPUT)" \
IDEA_MATURITY_METRICS_RERUN_MATERIALIZATION="$(call product_workspace_repaired_handoff_input,REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_MATERIALIZATION,IDEA_TO_SPEC_RERUN_MATERIALIZATION_OUTPUT)" \
IDEA_MATURITY_METRICS_PROMOTION_GATE="$(IDEA_TO_SPEC_PROMOTION_GATE_OUTPUT)" \
IDEA_MATURITY_METRICS_REPAIR_SESSION="$(IDEA_TO_SPEC_REPAIR_SESSION_OUTPUT)" \
IDEA_MATURITY_METRICS_REPAIRED_HANDOFF="$(REPAIRED_CANDIDATE_PROMOTION_HANDOFF_OUTPUT)" \
IDEA_MATURITY_METRICS_REPAIRED_CANDIDATE_GRAPH="$(REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CANDIDATE_GRAPH_OUTPUT)" \
IDEA_MATURITY_METRICS_REPAIRED_PRE_SIB="$(REPAIRED_CANDIDATE_PROMOTION_HANDOFF_PRE_SIB_OUTPUT)" \
IDEA_MATURITY_METRICS_REPAIRED_ACTIVE_CANDIDATE="$(REPAIRED_CANDIDATE_PROMOTION_HANDOFF_ACTIVE_CANDIDATE_OUTPUT)" \
IDEA_MATURITY_METRICS_REPAIRED_PROMOTION_GATE="$(REPAIRED_CANDIDATE_PROMOTION_HANDOFF_PROMOTION_GATE_OUTPUT)" \
IDEA_MATURITY_METRICS_REPAIRED_REPAIR_SESSION="$(REPAIRED_CANDIDATE_PROMOTION_HANDOFF_REPAIR_SESSION_OUTPUT)"

.PHONY: metrics-delivery
metrics-delivery:
Expand Down
56 changes: 54 additions & 2 deletions tests/test_idea_maturity_metrics_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -1139,9 +1139,9 @@ def test_idea_maturity_metrics_validate_make_target_invokes_metrics_cli(
assert validation["summary"]["status"] == "ok"


def _make_dry_run_target(target: str) -> str:
def _make_dry_run_target(target: str, *variables: str) -> str:
result = subprocess.run(
["make", "-n", target],
["make", "-n", target, *variables],
cwd=ROOT,
check=False,
capture_output=True,
Expand Down Expand Up @@ -1269,6 +1269,58 @@ def test_repaired_promotion_handoff_emits_validated_idea_maturity() -> None:
assert handoff_index < metrics_index < validation_index


def test_repaired_promotion_handoff_preserves_explicit_scoped_inputs() -> None:
output = _make_dry_run_target(
"product-workspace-repaired-promotion-handoff",
"REPAIRED_CANDIDATE_PROMOTION_HANDOFF_INTAKE=runs/hosted-operation-canary/idea_event_storming_intake.json",
"REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CLARIFICATION_REQUESTS=runs/hosted-operation-canary/idea_to_spec_clarification_requests.json",
"REPAIRED_CANDIDATE_PROMOTION_HANDOFF_CLARIFICATION_ANSWERS=runs/hosted-operation-canary/idea_to_spec_clarification_answers.json",
"REPAIRED_CANDIDATE_PROMOTION_HANDOFF_ONTOLOGY_DECISIONS=runs/hosted-operation-canary/product_ontology_gap_review_decisions.json",
"REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_INPUT=runs/hosted-operation-canary/idea_to_spec_answer_rerun_input.json",
"REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_PREVIEW=runs/hosted-operation-canary/idea_to_spec_rerun_preview.json",
"REPAIRED_CANDIDATE_PROMOTION_HANDOFF_RERUN_MATERIALIZATION=runs/hosted-operation-canary/idea_to_spec_rerun_materialization.json",
"REPAIRED_CANDIDATE_PROMOTION_HANDOFF_OUTPUT=runs/hosted-operation-canary/repaired_candidate_promotion_handoff_report.json",
)

assert '--intake "runs/hosted-operation-canary/idea_event_storming_intake.json"' in output
assert (
"--clarification-requests "
'"runs/hosted-operation-canary/idea_to_spec_clarification_requests.json"' in output
)
assert (
"--rerun-materialization "
'"runs/hosted-operation-canary/idea_to_spec_rerun_materialization.json"' in output
)
assert (
'IDEA_MATURITY_METRICS_REPAIRED_HANDOFF="runs/hosted-operation-canary/repaired_candidate_promotion_handoff_report.json"'
in output
)


def test_repaired_promotion_handoff_threads_scoped_producer_outputs() -> None:
output = _make_dry_run_target(
"product-workspace-repaired-promotion-handoff",
"IDEA_EVENT_STORMING_INTAKE_OUTPUT=runs/hosted-operation-canary/idea_event_storming_intake.json",
"IDEA_TO_SPEC_CLARIFICATION_OUTPUT=runs/hosted-operation-canary/idea_to_spec_clarification_requests.json",
"IDEA_TO_SPEC_CLARIFICATION_ANSWERS_OUTPUT=runs/hosted-operation-canary/idea_to_spec_clarification_answers.json",
"PRODUCT_ONTOLOGY_GAP_REVIEW_DECISIONS_OUTPUT=runs/hosted-operation-canary/product_ontology_gap_review_decisions.json",
"IDEA_TO_SPEC_ANSWER_RERUN_INPUT_OUTPUT=runs/hosted-operation-canary/idea_to_spec_answer_rerun_input.json",
"IDEA_TO_SPEC_RERUN_PREVIEW_OUTPUT=runs/hosted-operation-canary/idea_to_spec_rerun_preview.json",
"IDEA_TO_SPEC_RERUN_MATERIALIZATION_OUTPUT=runs/hosted-operation-canary/idea_to_spec_rerun_materialization.json",
)

assert '--intake "runs/hosted-operation-canary/idea_event_storming_intake.json"' in output
assert (
"--rerun-materialization "
'"runs/hosted-operation-canary/idea_to_spec_rerun_materialization.json"' in output
)
assert (
'IDEA_MATURITY_METRICS_RERUN_MATERIALIZATION="runs/hosted-operation-canary/idea_to_spec_rerun_materialization.json"'
in output
)
assert '--repaired-handoff "runs/repaired_candidate_promotion_handoff_report.json"' in output


def test_idea_maturity_metrics_report_counts_materialized_request_once(
tmp_path: Path,
) -> None:
Expand Down