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
2 changes: 1 addition & 1 deletion scripts/generate_spreadsheet_programme_workflow_seed.py
Original file line number Diff line number Diff line change
Expand Up @@ -1594,7 +1594,7 @@ def build_bundle() -> dict[str, object]:
return {
"family_id": "spreadsheet_programme_representation_workflow_seed_bundle",
"schema_version": "repo_seed_workflow_bundle.v1",
"seed_version": "19",
"seed_version": "20",
"source_tag": "JVNAUTOSCI-2592",
"managed_by": "spreadsheet_programme_workflow_vontology_service",
"processing_authority_fingerprint": authority_fingerprint,
Expand Down
1 change: 1 addition & 0 deletions src/backend/services/workflow_repo_seed_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,7 @@ def _stable_state_metadata_subset(state: Any) -> dict[str, Any]:
"writes_context_keys",
"tool_output_context_mappings",
"subworkflow_contract",
"retry_policy",
"mutation_authority",
):
value = metadata.get(key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
"family_id": "#V#kr_design_materialisation_workflow_family",
"managed_by": "kr_materialisation_workflow_vontology_service",
"schema_version": "repo_seed_workflow_bundle.v1",
"seed_version": "6",
"seed_version": "7",
"known_legacy_authority_payload_sha256_by_seed_version": {
"#V#kr_design_concept_materialisation_item_workflow": {
"6": [
"c027e848fe7860016bdc91fd1efa5809c3cfb57e667eb021bc638d1cfb34d8d8"
]
}
},
"source_tag": "JVNAUTOSCI-2271",
"supported_action_ids": [
"llm.action",
Expand Down Expand Up @@ -746,27 +753,16 @@
"on_failure_state": "summarise_blocker",
"retry_policy": {
"backoff_policy": "fixed",
"delay_ms": 1000,
"initial_delay_ms": 1000,
"max_attempts": 2,
"max_delay_ms": 1000,
"retry_on_outcomes": [
"failure"
],
"schema_version": "workflow_step_retry_policy.v1"
},
"state_id": "read_back_concept",
"static_input_bindings": [
[
"include_relations_any_arg",
true
],
[
"include_text_relations_arg1",
true
],
[
"limit",
40
],
[
"tool_name",
"fetch_concept"
Expand Down Expand Up @@ -804,8 +800,9 @@
"on_failure_state": "summarise_blocker",
"retry_policy": {
"backoff_policy": "fixed",
"delay_ms": 1000,
"initial_delay_ms": 1000,
"max_attempts": 2,
"max_delay_ms": 1000,
"retry_on_outcomes": [
"failure"
],
Expand Down Expand Up @@ -1211,16 +1208,18 @@
"execution_mode": "deterministic",
"next_state": "read_back_target",
"on_failure_state": "summarise_blocker",
"retry_policy": {
"backoff_policy": "fixed",
"initial_delay_ms": 1000,
"max_attempts": 2,
"max_delay_ms": 1000,
"retry_on_outcomes": [
"failure"
],
"schema_version": "workflow_step_retry_policy.v1"
},
"state_id": "read_back_source",
"static_input_bindings": [
[
"include_relations_any_arg",
true
],
[
"limit",
40
],
[
"tool_name",
"fetch_concept"
Expand Down Expand Up @@ -1256,16 +1255,18 @@
"execution_mode": "deterministic",
"next_state": "emit_relationship_payload",
"on_failure_state": "summarise_blocker",
"retry_policy": {
"backoff_policy": "fixed",
"initial_delay_ms": 1000,
"max_attempts": 2,
"max_delay_ms": 1000,
"retry_on_outcomes": [
"failure"
],
"schema_version": "workflow_step_retry_policy.v1"
},
"state_id": "read_back_target",
"static_input_bindings": [
[
"include_relations_any_arg",
true
],
[
"limit",
40
],
[
"tool_name",
"fetch_concept"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
"managed_by": "spreadsheet_programme_workflow_vontology_service",
"processing_authority_dependencies": {
"kr_materialisation_workflow_seed_bundle": {
"canonical_payload_sha256": "sha256:330476eb8e85bc0ea4aeca0c7bf844968495c8c1018f52b5097a96cd68fd8c0a",
"canonical_payload_sha256": "sha256:9b476fe39cd6595890adb83ab80480ada00329bbd2461b693b453cdf10e90536",
"family_id": "#V#kr_design_materialisation_workflow_family",
"seed_version": "6"
"seed_version": "7"
}
},
"processing_authority_fingerprint": "sha256:7ecf13bbdfa9a9a95f28eefc3634fad91cc5c7498aa0aa84b6763ab965c46267",
"processing_authority_fingerprint": "sha256:3f7d250eec0d520b2658d63493285776c21c123ccec3676e4eb561217a1c4f60",
"schema_version": "repo_seed_workflow_bundle.v1",
"seed_version": "19",
"seed_version": "20",
"source_tag": "JVNAUTOSCI-2592",
"support_concepts": [
{
Expand Down Expand Up @@ -306,7 +306,7 @@
},
{
"key": "processing_authority_fingerprint",
"value": "sha256:7ecf13bbdfa9a9a95f28eefc3634fad91cc5c7498aa0aa84b6763ab965c46267"
"value": "sha256:3f7d250eec0d520b2658d63493285776c21c123ccec3676e4eb561217a1c4f60"
}
],
"tool_output_mapping_specs": [
Expand Down Expand Up @@ -702,7 +702,7 @@
},
{
"key": "processing_authority_fingerprint",
"value": "sha256:7ecf13bbdfa9a9a95f28eefc3634fad91cc5c7498aa0aa84b6763ab965c46267"
"value": "sha256:3f7d250eec0d520b2658d63493285776c21c123ccec3676e4eb561217a1c4f60"
}
],
"tool_output_mapping_specs": [
Expand Down Expand Up @@ -776,7 +776,7 @@
},
{
"key": "processing_authority_fingerprint",
"value": "sha256:7ecf13bbdfa9a9a95f28eefc3634fad91cc5c7498aa0aa84b6763ab965c46267"
"value": "sha256:3f7d250eec0d520b2658d63493285776c21c123ccec3676e4eb561217a1c4f60"
}
],
"tool_output_mapping_specs": [
Expand Down Expand Up @@ -1234,7 +1234,7 @@
},
{
"key": "processing_authority_fingerprint",
"value": "sha256:7ecf13bbdfa9a9a95f28eefc3634fad91cc5c7498aa0aa84b6763ab965c46267"
"value": "sha256:3f7d250eec0d520b2658d63493285776c21c123ccec3676e4eb561217a1c4f60"
}
],
"tool_output_mapping_specs": [
Expand Down Expand Up @@ -1557,7 +1557,7 @@
},
{
"key": "processing_authority_fingerprint",
"value": "sha256:7ecf13bbdfa9a9a95f28eefc3634fad91cc5c7498aa0aa84b6763ab965c46267"
"value": "sha256:3f7d250eec0d520b2658d63493285776c21c123ccec3676e4eb561217a1c4f60"
}
],
"tool_output_mapping_specs": [
Expand Down Expand Up @@ -1625,7 +1625,7 @@
},
{
"key": "processing_authority_fingerprint",
"value": "sha256:7ecf13bbdfa9a9a95f28eefc3634fad91cc5c7498aa0aa84b6763ab965c46267"
"value": "sha256:3f7d250eec0d520b2658d63493285776c21c123ccec3676e4eb561217a1c4f60"
}
],
"tool_output_mapping_specs": [
Expand Down
3 changes: 3 additions & 0 deletions src/backend/workflows/workflow_repo_seed_export_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,9 @@ def _build_publication_spec_payload_from_definition(
"on_true_state": on_true_state,
"on_unknown_state": on_unknown_state,
"prompt_concept_ids": prompt_concept_ids,
"retry_policy": _stable_json_like(
runtime_details.retry_policy
),
"state_id": state_id,
"static_input_bindings": static_input_bindings,
"tool_output_context_mappings": [],
Expand Down
115 changes: 113 additions & 2 deletions tests/backend/test_kr_materialisation_workflow_vontology_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
from src.backend.workflows.durable.control_flow_actions import (
register_control_flow_actions,
)
from src.backend.workflows.engine import _normalise_retry_policy_spec
from src.backend.workflows.execution_contracts import (
WORKFLOW_CONTROL_ACTION_CONTEXT_SET_ID,
)
from src.backend.workflows.metadata_validation import (
validate_state_metadata_post_action,
)
from src.backend.workflows import (
workflow_concept_authority_service as authority_service,
)
from src.backend.workflows import workflow_repo_seed_export_service as export_service

_PROJECT_ROOT = Path(__file__).resolve().parents[2]
_SEED_BUNDLE_PATH = (
Expand Down Expand Up @@ -161,7 +166,14 @@ def test_kr_prompt_seed_assets_hold_operational_prompt_content() -> None:

def test_kr_seed_applies_optional_guard_before_each_write_phase() -> None:
bundle = json.loads(_SEED_BUNDLE_PATH.read_text(encoding="utf-8"))
assert bundle["seed_version"] == "6"
assert bundle["seed_version"] == "7"
assert bundle["known_legacy_authority_payload_sha256_by_seed_version"] == {
mod.KR_DESIGN_CONCEPT_MATERIALISATION_ITEM_WORKFLOW_ID: {
"6": [
"c027e848fe7860016bdc91fd1efa5809c3cfb57e667eb021bc638d1cfb34d8d8"
]
}
}
workflow = next(
row
for row in bundle["workflows"]
Expand Down Expand Up @@ -241,8 +253,9 @@ def test_kr_seed_applies_optional_guard_before_each_write_phase() -> None:
assert description_outputs["kr_description_text_value_id"] == "text_value_id"
expected_readback_retry = {
"backoff_policy": "fixed",
"delay_ms": 1000,
"initial_delay_ms": 1000,
"max_attempts": 2,
"max_delay_ms": 1000,
"retry_on_outcomes": ["failure"],
"schema_version": "workflow_step_retry_policy.v1",
}
Expand All @@ -254,6 +267,23 @@ def test_kr_seed_applies_optional_guard_before_each_write_phase() -> None:
concept_item_states["read_back_text_relations"]["retry_policy"]
== expected_readback_retry
)
relationship_item = next(
row
for row in bundle["workflows"]
if row["workflow_id"] == mod.KR_DESIGN_RELATIONSHIP_ASSERTION_ITEM_WORKFLOW_ID
)
relationship_item_states = {
row["state_id"]: row
for row in relationship_item["publication_spec"]["steps"]
}
assert (
relationship_item_states["read_back_source"]["retry_policy"]
== expected_readback_retry
)
assert (
relationship_item_states["read_back_target"]["retry_policy"]
== expected_readback_retry
)
concept_iteration_bindings = dict(
states["materialise_concepts"]["static_input_bindings"]
)
Expand Down Expand Up @@ -307,6 +337,87 @@ def test_kr_seed_suppresses_event_fan_out_only_for_owned_mutations() -> None:
}


def test_kr_readbacks_avoid_expensive_relation_expansion() -> None:
bundle = json.loads(_SEED_BUNDLE_PATH.read_text(encoding="utf-8"))
concept_readback = _publication_step(
bundle,
workflow_id=mod.KR_DESIGN_CONCEPT_MATERIALISATION_ITEM_WORKFLOW_ID,
state_id="read_back_concept",
)
text_readback = _publication_step(
bundle,
workflow_id=mod.KR_DESIGN_CONCEPT_MATERIALISATION_ITEM_WORKFLOW_ID,
state_id="read_back_text_relations",
)

assert dict(concept_readback["static_input_bindings"]) == {
"tool_name": "fetch_concept"
}
assert {
mapping["tool_output_field"]
for mapping in concept_readback["tool_output_mapping_specs"]
} == {"concept_id", "relationships"}
assert concept_readback["next_state"] == "read_back_text_relations"
assert dict(text_readback["static_input_bindings"]) == {
"language": "en-NZ",
"limit": 10,
"predicate": "hasDescription",
"tool_name": "get_text_relations",
}
for state_id in ("read_back_source", "read_back_target"):
relationship_readback = _publication_step(
bundle,
workflow_id=mod.KR_DESIGN_RELATIONSHIP_ASSERTION_ITEM_WORKFLOW_ID,
state_id=state_id,
)
assert dict(relationship_readback["static_input_bindings"]) == {
"tool_name": "fetch_concept"
}
assert {
mapping["tool_output_field"]
for mapping in relationship_readback["tool_output_mapping_specs"]
} == {"concept_id", "relationships"}


def test_kr_retry_policy_round_trips_in_canonical_loader_shape() -> None:
raw_bundle = json.loads(_SEED_BUNDLE_PATH.read_text(encoding="utf-8"))
bundle = authority_service.load_repo_seed_workflow_bundle(_SEED_BUNDLE_PATH)
readback_states_by_workflow = {
mod.KR_DESIGN_CONCEPT_MATERIALISATION_ITEM_WORKFLOW_ID: (
"read_back_concept",
"read_back_text_relations",
),
mod.KR_DESIGN_RELATIONSHIP_ASSERTION_ITEM_WORKFLOW_ID: (
"read_back_source",
"read_back_target",
),
}

for workflow_id, state_ids in readback_states_by_workflow.items():
publication_spec = bundle["publication_specs"][workflow_id]
definition = authority_service._build_definition_from_publication_spec(
workflow_id=workflow_id,
spec=publication_spec,
)
exported = export_service._build_publication_spec_payload_from_definition(
workflow_id=workflow_id,
definition=definition,
)
exported_steps = {step["state_id"]: step for step in exported["steps"]}

for state_id in state_ids:
raw_policy = _publication_step(
raw_bundle,
workflow_id=workflow_id,
state_id=state_id,
)["retry_policy"]
parsed_policy = definition.states[state_id].metadata["retry_policy"]
canonical_policy = _normalise_retry_policy_spec(parsed_policy)
assert raw_policy == canonical_policy
assert parsed_policy == canonical_policy
assert exported_steps[state_id]["retry_policy"] == canonical_policy


def test_kr_seed_bundle_validates_as_workflow_contracts() -> None:
report = mod.validate_kr_materialisation_seed_bundle()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ def test_processing_authority_fingerprint_tracks_exact_kr_dependency(
from scripts import generate_spreadsheet_programme_workflow_seed as generator

baseline = generator.build_bundle()
assert baseline["seed_version"] == "19"
assert baseline["seed_version"] == "20"
baseline_dependency = baseline["processing_authority_dependencies"][
"kr_materialisation_workflow_seed_bundle"
]
Expand All @@ -352,7 +352,7 @@ def test_processing_authority_fingerprint_tracks_exact_kr_dependency(
)
assert baseline_dependency["family_id"] == source_payload["family_id"]
assert baseline_dependency["seed_version"] == source_payload["seed_version"]
assert baseline_dependency["seed_version"] == "6"
assert baseline_dependency["seed_version"] == "7"
assert baseline_dependency["canonical_payload_sha256"].startswith("sha256:")

changed_payload = dict(source_payload)
Expand Down
Loading
Loading