fix(gitea): surface all product dev prod repo truth
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m12s
CD Pipeline / build-and-deploy (push) Successful in 4m52s
CD Pipeline / post-deploy-checks (push) Successful in 1m47s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m12s
CD Pipeline / build-and-deploy (push) Successful in 4m52s
CD Pipeline / post-deploy-checks (push) Successful in 1m47s
This commit is contained in:
@@ -875,6 +875,14 @@ def build_delivery_closure_workbench(
|
||||
"gitea_public_repo_count": _int(
|
||||
private_inventory_rollups.get("gitea_public_repo_count")
|
||||
),
|
||||
"gitea_ssh_verified_repo_count": _int(
|
||||
private_inventory_rollups.get("gitea_ssh_verified_repo_count")
|
||||
),
|
||||
"gitea_private_or_auth_only_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"gitea_private_or_auth_only_repo_count"
|
||||
)
|
||||
),
|
||||
"expected_product_count": _int(
|
||||
private_inventory_rollups.get("expected_product_count")
|
||||
),
|
||||
@@ -884,6 +892,62 @@ def build_delivery_closure_workbench(
|
||||
"missing_product_row_count": _int(
|
||||
private_inventory_rollups.get("missing_product_row_count")
|
||||
),
|
||||
"ssh_verified_product_repo_count": _int(
|
||||
private_inventory_rollups.get("ssh_verified_product_repo_count")
|
||||
),
|
||||
"main_branch_present_product_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"main_branch_present_product_repo_count"
|
||||
)
|
||||
),
|
||||
"dev_branch_present_product_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"dev_branch_present_product_repo_count"
|
||||
)
|
||||
),
|
||||
"dev_prod_environment_split_ready_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"dev_prod_environment_split_ready_count"
|
||||
)
|
||||
),
|
||||
"public_visible_product_repo_count": _int(
|
||||
private_inventory_rollups.get("public_visible_product_repo_count")
|
||||
),
|
||||
"private_or_auth_only_product_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"private_or_auth_only_product_repo_count"
|
||||
)
|
||||
),
|
||||
"tokenless_http_404_private_or_auth_product_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"tokenless_http_404_private_or_auth_product_repo_count"
|
||||
)
|
||||
),
|
||||
"missing_product_repo_count": _int(
|
||||
private_inventory_rollups.get("missing_product_repo_count")
|
||||
),
|
||||
"missing_main_branch_product_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"missing_main_branch_product_repo_count"
|
||||
)
|
||||
),
|
||||
"missing_dev_branch_product_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"missing_dev_branch_product_repo_count"
|
||||
)
|
||||
),
|
||||
"all_expected_product_repos_have_ssh_refs": (
|
||||
private_inventory_rollups.get(
|
||||
"all_expected_product_repos_have_ssh_refs"
|
||||
)
|
||||
is True
|
||||
),
|
||||
"all_expected_product_repos_have_dev_and_main": (
|
||||
private_inventory_rollups.get(
|
||||
"all_expected_product_repos_have_dev_and_main"
|
||||
)
|
||||
is True
|
||||
),
|
||||
"accepted_inventory_payload_count": _int(
|
||||
private_inventory_rollups.get("accepted_inventory_payload_count")
|
||||
),
|
||||
@@ -1601,6 +1665,12 @@ def build_delivery_closure_workbench(
|
||||
"gitea_private_inventory_public_repo_count": _int(
|
||||
private_inventory_rollups.get("gitea_public_repo_count")
|
||||
),
|
||||
"gitea_private_inventory_ssh_verified_repo_count": _int(
|
||||
private_inventory_rollups.get("gitea_ssh_verified_repo_count")
|
||||
),
|
||||
"gitea_private_inventory_private_or_auth_only_repo_count": _int(
|
||||
private_inventory_rollups.get("gitea_private_or_auth_only_repo_count")
|
||||
),
|
||||
"gitea_private_inventory_expected_product_count": _int(
|
||||
private_inventory_rollups.get("expected_product_count")
|
||||
),
|
||||
@@ -1610,6 +1680,54 @@ def build_delivery_closure_workbench(
|
||||
"gitea_private_inventory_missing_product_row_count": _int(
|
||||
private_inventory_rollups.get("missing_product_row_count")
|
||||
),
|
||||
"gitea_private_inventory_ssh_verified_product_repo_count": _int(
|
||||
private_inventory_rollups.get("ssh_verified_product_repo_count")
|
||||
),
|
||||
"gitea_private_inventory_main_branch_present_product_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"main_branch_present_product_repo_count"
|
||||
)
|
||||
),
|
||||
"gitea_private_inventory_dev_branch_present_product_repo_count": _int(
|
||||
private_inventory_rollups.get("dev_branch_present_product_repo_count")
|
||||
),
|
||||
"gitea_private_inventory_dev_prod_environment_split_ready_count": _int(
|
||||
private_inventory_rollups.get("dev_prod_environment_split_ready_count")
|
||||
),
|
||||
"gitea_private_inventory_public_visible_product_repo_count": _int(
|
||||
private_inventory_rollups.get("public_visible_product_repo_count")
|
||||
),
|
||||
"gitea_private_inventory_private_or_auth_only_product_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"private_or_auth_only_product_repo_count"
|
||||
)
|
||||
),
|
||||
"gitea_private_inventory_tokenless_http_404_private_or_auth_product_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"tokenless_http_404_private_or_auth_product_repo_count"
|
||||
)
|
||||
),
|
||||
"gitea_private_inventory_missing_product_repo_count": _int(
|
||||
private_inventory_rollups.get("missing_product_repo_count")
|
||||
),
|
||||
"gitea_private_inventory_missing_main_branch_product_repo_count": _int(
|
||||
private_inventory_rollups.get(
|
||||
"missing_main_branch_product_repo_count"
|
||||
)
|
||||
),
|
||||
"gitea_private_inventory_missing_dev_branch_product_repo_count": _int(
|
||||
private_inventory_rollups.get("missing_dev_branch_product_repo_count")
|
||||
),
|
||||
"gitea_private_inventory_all_expected_product_repos_have_ssh_refs": (
|
||||
private_inventory_rollups.get("all_expected_product_repos_have_ssh_refs")
|
||||
is True
|
||||
),
|
||||
"gitea_private_inventory_all_expected_product_repos_have_dev_and_main": (
|
||||
private_inventory_rollups.get(
|
||||
"all_expected_product_repos_have_dev_and_main"
|
||||
)
|
||||
is True
|
||||
),
|
||||
"gitea_private_inventory_accepted_payload_count": _int(
|
||||
private_inventory_rollups.get("accepted_inventory_payload_count")
|
||||
),
|
||||
|
||||
@@ -62,6 +62,10 @@ def _build_payload(scorecard: dict[str, Any], path: Path) -> dict[str, Any]:
|
||||
owner_response_validation = _dict(scorecard.get("owner_response_validation"))
|
||||
controlled_closeout_receipt = _dict(scorecard.get("controlled_closeout_receipt"))
|
||||
product_coverage = _dict(scorecard.get("product_row_coverage"))
|
||||
product_environment_coverage = _dict(
|
||||
scorecard.get("product_repo_environment_coverage")
|
||||
)
|
||||
dev_prod_repo_readback = _dict(scorecard.get("dev_prod_repo_readback"))
|
||||
active_blockers = _strings(scorecard.get("active_blockers"))
|
||||
exit_criteria = _strings(scorecard.get("exit_criteria"))
|
||||
met_criteria = _met_exit_criteria(scorecard, gitea_inventory, product_coverage)
|
||||
@@ -94,6 +98,8 @@ def _build_payload(scorecard: dict[str, Any], path: Path) -> dict[str, Any]:
|
||||
"safe_next_step": str(scorecard.get("safe_next_step") or ""),
|
||||
},
|
||||
"gitea_inventory": gitea_inventory,
|
||||
"dev_prod_repo_readback": dev_prod_repo_readback,
|
||||
"product_repo_environment_coverage": product_environment_coverage,
|
||||
"authenticated_import_acceptance": import_acceptance,
|
||||
"authenticated_payload_validation": payload_validation,
|
||||
"authenticated_inventory_single_preflight_intake_ready": True,
|
||||
@@ -119,6 +125,12 @@ def _build_payload(scorecard: dict[str, Any], path: Path) -> dict[str, Any]:
|
||||
gitea_inventory.get("visibility_scope") or "unknown"
|
||||
),
|
||||
"gitea_public_repo_count": _int(gitea_inventory.get("repo_count")),
|
||||
"gitea_ssh_verified_repo_count": _int(
|
||||
gitea_inventory.get("ssh_verified_repo_count")
|
||||
),
|
||||
"gitea_private_or_auth_only_repo_count": _int(
|
||||
gitea_inventory.get("private_or_auth_only_repo_count")
|
||||
),
|
||||
"accepted_inventory_payload_count": _int(
|
||||
import_acceptance.get("accepted_payload_count")
|
||||
),
|
||||
@@ -203,6 +215,53 @@ def _build_payload(scorecard: dict[str, Any], path: Path) -> dict[str, Any]:
|
||||
)
|
||||
is True
|
||||
),
|
||||
"product_repo_environment_status": str(
|
||||
product_environment_coverage.get("status") or ""
|
||||
),
|
||||
"ssh_verified_product_repo_count": _int(
|
||||
product_environment_coverage.get("ssh_repo_present_count")
|
||||
),
|
||||
"main_branch_present_product_repo_count": _int(
|
||||
product_environment_coverage.get("main_branch_present_count")
|
||||
),
|
||||
"dev_branch_present_product_repo_count": _int(
|
||||
product_environment_coverage.get("dev_branch_present_count")
|
||||
),
|
||||
"dev_prod_environment_split_ready_count": _int(
|
||||
product_environment_coverage.get("environment_split_ready_count")
|
||||
),
|
||||
"public_visible_product_repo_count": _int(
|
||||
product_environment_coverage.get("public_visible_count")
|
||||
),
|
||||
"private_or_auth_only_product_repo_count": _int(
|
||||
product_environment_coverage.get("private_or_auth_only_count")
|
||||
),
|
||||
"tokenless_http_404_private_or_auth_product_repo_count": _int(
|
||||
product_environment_coverage.get(
|
||||
"tokenless_http_404_private_or_auth_count"
|
||||
)
|
||||
),
|
||||
"missing_product_repo_count": _int(
|
||||
product_environment_coverage.get("missing_repo_count")
|
||||
),
|
||||
"missing_main_branch_product_repo_count": _int(
|
||||
product_environment_coverage.get("missing_main_branch_count")
|
||||
),
|
||||
"missing_dev_branch_product_repo_count": _int(
|
||||
product_environment_coverage.get("missing_dev_branch_count")
|
||||
),
|
||||
"all_expected_product_repos_have_ssh_refs": (
|
||||
product_environment_coverage.get(
|
||||
"all_expected_product_repos_have_ssh_refs"
|
||||
)
|
||||
is True
|
||||
),
|
||||
"all_expected_product_repos_have_dev_and_main": (
|
||||
product_environment_coverage.get(
|
||||
"all_expected_product_repos_have_dev_and_main"
|
||||
)
|
||||
is True
|
||||
),
|
||||
"github_lane_excluded_from_p0_blocker_count": (
|
||||
scorecard.get("github_lane_excluded_from_p0_blocker_count")
|
||||
is True
|
||||
@@ -402,6 +461,29 @@ def _require_source_scorecard(payload: dict[str, Any], label: str) -> None:
|
||||
f"{label}: owner response validation boundaries must remain false: "
|
||||
f"{owner_response_drift}"
|
||||
)
|
||||
dev_prod_readback = _dict(payload.get("dev_prod_repo_readback"))
|
||||
if dev_prod_readback:
|
||||
if dev_prod_readback.get("source_control_authority") != "gitea":
|
||||
raise ValueError(f"{label}: dev/prod readback must use gitea authority")
|
||||
boundaries = _dict(dev_prod_readback.get("operation_boundaries"))
|
||||
if boundaries.get("ssh_refs_read_only") is not True:
|
||||
raise ValueError(f"{label}: dev/prod readback must be SSH read-only")
|
||||
blocked_flags = {
|
||||
"token_value_collection_allowed",
|
||||
"secret_value_collection_allowed",
|
||||
"gitea_api_write_allowed",
|
||||
"gitea_repo_creation_allowed",
|
||||
"gitea_refs_sync_allowed",
|
||||
"gitea_visibility_change_allowed",
|
||||
"github_api_allowed",
|
||||
"github_cli_allowed",
|
||||
"raw_session_or_sqlite_read_allowed",
|
||||
}
|
||||
opened = sorted(
|
||||
flag for flag in blocked_flags if boundaries.get(flag) is not False
|
||||
)
|
||||
if opened:
|
||||
raise ValueError(f"{label}: dev/prod readback boundaries opened: {opened}")
|
||||
|
||||
|
||||
def _require_operation_boundaries(payload: dict[str, Any], label: str) -> None:
|
||||
@@ -452,6 +534,19 @@ def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None:
|
||||
is not True
|
||||
):
|
||||
raise ValueError(f"{label}: active product owner readiness rows incomplete")
|
||||
if rollups.get("ssh_verified_product_repo_count") and (
|
||||
rollups.get("ssh_verified_product_repo_count")
|
||||
!= rollups.get("expected_product_count")
|
||||
):
|
||||
raise ValueError(f"{label}: SSH verified product repo count mismatch")
|
||||
if rollups.get("missing_product_repo_count") not in {None, 0}:
|
||||
raise ValueError(f"{label}: product repo readback must have zero missing repos")
|
||||
if rollups.get("missing_main_branch_product_repo_count") not in {None, 0}:
|
||||
raise ValueError(f"{label}: product repo readback must have zero missing main branches")
|
||||
if rollups.get("missing_dev_branch_product_repo_count") not in {None, 0}:
|
||||
raise ValueError(f"{label}: product repo readback must have zero missing dev branches")
|
||||
if rollups.get("all_expected_product_repos_have_dev_and_main") is False:
|
||||
raise ValueError(f"{label}: product repo readback must have dev and main")
|
||||
if (
|
||||
rollups.get("next_owner_response_validation_lane_id")
|
||||
!= "s4_9_gitea_inventory_owner_attestation_response"
|
||||
@@ -563,6 +658,14 @@ def _met_exit_criteria(
|
||||
is True
|
||||
):
|
||||
met.append("all_active_product_repos_have_gitea_owner_readiness_row=true")
|
||||
product_environment_coverage = _dict(
|
||||
scorecard.get("product_repo_environment_coverage")
|
||||
)
|
||||
if (
|
||||
product_environment_coverage.get("all_expected_product_repos_have_dev_and_main")
|
||||
is True
|
||||
):
|
||||
met.append("all_expected_product_repos_have_dev_and_main=true")
|
||||
return met
|
||||
|
||||
|
||||
|
||||
@@ -102,9 +102,79 @@ def test_delivery_closure_workbench_uses_gitea_private_inventory_lane():
|
||||
assert lanes["gitea_private_inventory"]["metric"]["private_inventory_source"] == "gitea"
|
||||
assert lanes["gitea_private_inventory"]["metric"]["gitea_repo_inventory_status"] == "ok"
|
||||
assert lanes["gitea_private_inventory"]["metric"]["gitea_visibility_scope"] == "admin_export"
|
||||
assert lanes["gitea_private_inventory"]["metric"]["expected_product_count"] == 11
|
||||
assert lanes["gitea_private_inventory"]["metric"]["present_product_row_count"] == 11
|
||||
assert lanes["gitea_private_inventory"]["metric"]["gitea_public_repo_count"] == 6
|
||||
assert lanes["gitea_private_inventory"]["metric"]["gitea_ssh_verified_repo_count"] == 12
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"gitea_private_or_auth_only_repo_count"
|
||||
]
|
||||
== 6
|
||||
)
|
||||
assert lanes["gitea_private_inventory"]["metric"]["expected_product_count"] == 12
|
||||
assert lanes["gitea_private_inventory"]["metric"]["present_product_row_count"] == 12
|
||||
assert lanes["gitea_private_inventory"]["metric"]["missing_product_row_count"] == 0
|
||||
assert lanes["gitea_private_inventory"]["metric"]["ssh_verified_product_repo_count"] == 12
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"main_branch_present_product_repo_count"
|
||||
]
|
||||
== 12
|
||||
)
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"dev_branch_present_product_repo_count"
|
||||
]
|
||||
== 12
|
||||
)
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"dev_prod_environment_split_ready_count"
|
||||
]
|
||||
== 12
|
||||
)
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"public_visible_product_repo_count"
|
||||
]
|
||||
== 6
|
||||
)
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"private_or_auth_only_product_repo_count"
|
||||
]
|
||||
== 6
|
||||
)
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"tokenless_http_404_private_or_auth_product_repo_count"
|
||||
]
|
||||
== 6
|
||||
)
|
||||
assert lanes["gitea_private_inventory"]["metric"]["missing_product_repo_count"] == 0
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"missing_main_branch_product_repo_count"
|
||||
]
|
||||
== 0
|
||||
)
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"missing_dev_branch_product_repo_count"
|
||||
]
|
||||
== 0
|
||||
)
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"all_expected_product_repos_have_ssh_refs"
|
||||
]
|
||||
is True
|
||||
)
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"all_expected_product_repos_have_dev_and_main"
|
||||
]
|
||||
is True
|
||||
)
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"authenticated_inventory_single_preflight_intake_ready"
|
||||
@@ -124,7 +194,7 @@ def test_delivery_closure_workbench_uses_gitea_private_inventory_lane():
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
"authenticated_inventory_payload_skeleton_repo_count_floor"
|
||||
]
|
||||
== 4
|
||||
== 6
|
||||
)
|
||||
assert (
|
||||
lanes["gitea_private_inventory"]["metric"][
|
||||
@@ -520,9 +590,74 @@ def _assert_delivery_workbench_shape(data: dict):
|
||||
assert data["summary"]["gitea_private_inventory_active_blocker_count"] == 0
|
||||
assert data["summary"]["gitea_private_inventory_repo_inventory_status"] == "ok"
|
||||
assert data["summary"]["gitea_private_inventory_visibility_scope"] == "admin_export"
|
||||
assert data["summary"]["gitea_private_inventory_expected_product_count"] == 11
|
||||
assert data["summary"]["gitea_private_inventory_present_product_row_count"] == 11
|
||||
assert data["summary"]["gitea_private_inventory_public_repo_count"] == 6
|
||||
assert data["summary"]["gitea_private_inventory_ssh_verified_repo_count"] == 12
|
||||
assert data["summary"]["gitea_private_inventory_private_or_auth_only_repo_count"] == 6
|
||||
assert data["summary"]["gitea_private_inventory_expected_product_count"] == 12
|
||||
assert data["summary"]["gitea_private_inventory_present_product_row_count"] == 12
|
||||
assert data["summary"]["gitea_private_inventory_missing_product_row_count"] == 0
|
||||
assert data["summary"]["gitea_private_inventory_ssh_verified_product_repo_count"] == 12
|
||||
assert (
|
||||
data["summary"][
|
||||
"gitea_private_inventory_main_branch_present_product_repo_count"
|
||||
]
|
||||
== 12
|
||||
)
|
||||
assert (
|
||||
data["summary"][
|
||||
"gitea_private_inventory_dev_branch_present_product_repo_count"
|
||||
]
|
||||
== 12
|
||||
)
|
||||
assert (
|
||||
data["summary"][
|
||||
"gitea_private_inventory_dev_prod_environment_split_ready_count"
|
||||
]
|
||||
== 12
|
||||
)
|
||||
assert (
|
||||
data["summary"][
|
||||
"gitea_private_inventory_public_visible_product_repo_count"
|
||||
]
|
||||
== 6
|
||||
)
|
||||
assert (
|
||||
data["summary"][
|
||||
"gitea_private_inventory_private_or_auth_only_product_repo_count"
|
||||
]
|
||||
== 6
|
||||
)
|
||||
assert (
|
||||
data["summary"][
|
||||
"gitea_private_inventory_tokenless_http_404_private_or_auth_product_repo_count"
|
||||
]
|
||||
== 6
|
||||
)
|
||||
assert data["summary"]["gitea_private_inventory_missing_product_repo_count"] == 0
|
||||
assert (
|
||||
data["summary"][
|
||||
"gitea_private_inventory_missing_main_branch_product_repo_count"
|
||||
]
|
||||
== 0
|
||||
)
|
||||
assert (
|
||||
data["summary"][
|
||||
"gitea_private_inventory_missing_dev_branch_product_repo_count"
|
||||
]
|
||||
== 0
|
||||
)
|
||||
assert (
|
||||
data["summary"][
|
||||
"gitea_private_inventory_all_expected_product_repos_have_ssh_refs"
|
||||
]
|
||||
is True
|
||||
)
|
||||
assert (
|
||||
data["summary"][
|
||||
"gitea_private_inventory_all_expected_product_repos_have_dev_and_main"
|
||||
]
|
||||
is True
|
||||
)
|
||||
assert data["summary"]["gitea_private_inventory_accepted_payload_count"] == 1
|
||||
assert (
|
||||
data["summary"][
|
||||
@@ -549,7 +684,7 @@ def _assert_delivery_workbench_shape(data: dict):
|
||||
data["summary"][
|
||||
"gitea_private_inventory_authenticated_payload_skeleton_repo_count_floor"
|
||||
]
|
||||
== 4
|
||||
== 6
|
||||
)
|
||||
assert (
|
||||
data["summary"][
|
||||
|
||||
@@ -53,10 +53,7 @@ def test_gitea_private_inventory_p0_scorecard_reports_committed_closeout():
|
||||
== 8
|
||||
)
|
||||
assert payload["authenticated_inventory_single_preflight_intake_ready"] is True
|
||||
assert (
|
||||
payload["authenticated_inventory_payload_skeleton_repo_count_floor"]
|
||||
== 4
|
||||
)
|
||||
assert payload["authenticated_inventory_payload_skeleton_repo_count_floor"] == 6
|
||||
assert payload["rollups"]["owner_coverage_attestation_received_count"] == 1
|
||||
assert payload["rollups"]["owner_coverage_attestation_accepted_count"] == 1
|
||||
assert payload["rollups"]["owner_response_validation_received_count"] == 5
|
||||
@@ -70,10 +67,33 @@ def test_gitea_private_inventory_p0_scorecard_reports_committed_closeout():
|
||||
payload["rollups"]["next_owner_response_validation_lane_id"]
|
||||
== "s4_9_gitea_inventory_owner_attestation_response"
|
||||
)
|
||||
assert payload["rollups"]["expected_product_count"] == 11
|
||||
assert payload["rollups"]["present_product_row_count"] == 11
|
||||
assert payload["rollups"]["gitea_public_repo_count"] == 6
|
||||
assert payload["rollups"]["gitea_ssh_verified_repo_count"] == 12
|
||||
assert payload["rollups"]["gitea_private_or_auth_only_repo_count"] == 6
|
||||
assert payload["rollups"]["expected_product_count"] == 12
|
||||
assert payload["rollups"]["present_product_row_count"] == 12
|
||||
assert payload["rollups"]["missing_product_row_count"] == 0
|
||||
assert payload["rollups"]["all_active_product_repos_have_gitea_owner_readiness_row"] is True
|
||||
assert payload["rollups"]["product_repo_environment_status"] == (
|
||||
"ready_all_expected_product_repos_have_dev_and_main"
|
||||
)
|
||||
assert payload["rollups"]["ssh_verified_product_repo_count"] == 12
|
||||
assert payload["rollups"]["main_branch_present_product_repo_count"] == 12
|
||||
assert payload["rollups"]["dev_branch_present_product_repo_count"] == 12
|
||||
assert payload["rollups"]["dev_prod_environment_split_ready_count"] == 12
|
||||
assert payload["rollups"]["public_visible_product_repo_count"] == 6
|
||||
assert payload["rollups"]["private_or_auth_only_product_repo_count"] == 6
|
||||
assert (
|
||||
payload["rollups"][
|
||||
"tokenless_http_404_private_or_auth_product_repo_count"
|
||||
]
|
||||
== 6
|
||||
)
|
||||
assert payload["rollups"]["missing_product_repo_count"] == 0
|
||||
assert payload["rollups"]["missing_main_branch_product_repo_count"] == 0
|
||||
assert payload["rollups"]["missing_dev_branch_product_repo_count"] == 0
|
||||
assert payload["rollups"]["all_expected_product_repos_have_ssh_refs"] is True
|
||||
assert payload["rollups"]["all_expected_product_repos_have_dev_and_main"] is True
|
||||
assert payload["rollups"]["github_lane_excluded_from_p0_blocker_count"] is True
|
||||
assert payload["github_retired_context"]["status"] == "stopped_retired_do_not_use"
|
||||
assert payload["github_retired_context"]["excluded_from_active_p0_blocker_math"] is True
|
||||
@@ -125,7 +145,7 @@ def test_gitea_private_inventory_p0_scorecard_exposes_single_preflight_intake():
|
||||
assert intake["workplan_id"] == "P0-003"
|
||||
assert intake["payload_schema_version"] == "gitea_repo_inventory_v1"
|
||||
assert intake["accepted_visibility_scopes"] == ["authenticated", "admin_export"]
|
||||
assert intake["minimum_repo_count"] == 4
|
||||
assert intake["minimum_repo_count"] == 6
|
||||
assert len(intake["required_redaction_attestations"]) == 8
|
||||
assert "no_token_value" in intake["required_redaction_attestations"]
|
||||
assert "no_gitea_db_dump" in intake["required_redaction_attestations"]
|
||||
@@ -191,7 +211,10 @@ def test_gitea_private_inventory_p0_scorecard_endpoint_returns_readback():
|
||||
assert data["authenticated_inventory_single_preflight_intake_ready"] is True
|
||||
assert data["authenticated_inventory_single_preflight_intake"][
|
||||
"minimum_repo_count"
|
||||
] == 4
|
||||
] == 6
|
||||
assert data["rollups"]["ssh_verified_product_repo_count"] == 12
|
||||
assert data["rollups"]["dev_prod_environment_split_ready_count"] == 12
|
||||
assert data["rollups"]["all_expected_product_repos_have_dev_and_main"] is True
|
||||
assert (
|
||||
data["controlled_closeout_receipt"]["status"]
|
||||
== "ready_for_p0_003_controlled_closeout"
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
## 2026-07-03 — 10:38 Gitea 全專案 dev/prod repo truth 上卷
|
||||
|
||||
**完成內容**:
|
||||
- 新增 `docs/operations/gitea-all-product-dev-prod-repo-readback.snapshot.json`,以 Gitea SSH read-only refs 明確列出 12 個已知產品 repo:`awoooi`、`ewoooc`、`2026FIFAWorldCup`、`agent-bounty-protocol`、`AwoooGo`、`stockplatform-v2`、`vibework`、`momo-pro-system`、`tsenyang-website`、`vtuber`、`bitan-pharmacy`、`clawbot-v5`。
|
||||
- P0-003 Gitea private inventory scorecard / API / Delivery workbench 新增 dev/prod 環境覆蓋讀回:`ssh_verified_product_repo_count=12`、`main_branch_present_product_repo_count=12`、`dev_branch_present_product_repo_count=12`、`dev_prod_environment_split_ready_count=12`、`missing_product_repo_count=0`、`missing_main_branch_product_repo_count=0`、`missing_dev_branch_product_repo_count=0`。
|
||||
- 將 public/tokenless UI 層與 SSH repo truth 分開呈現:public/tokenless 可見 `6` 個;`AwoooGo`、`stockplatform-v2`、`vibework`、`momo-pro-system`、`tsenyang-website`、`clawbot-v5` 為 `private_or_auth_only`,HTTP 404 不再被呈現成 repo 缺失。
|
||||
|
||||
**仍維持**:
|
||||
- 未讀 secret / token / `.env` / raw sessions / SQLite / auth;未使用 GitHub / gh;未建立 repo、未改 visibility、未 sync refs、未 workflow_dispatch;未重啟 host / VM / service;未 Docker / Nginx / K3s / DB / firewall restart;未 DROP / TRUNCATE / restore / prune / delete / force push。
|
||||
|
||||
## 2026-07-03 — 08:30 AwoooP readback endpoint fail-soft 補強
|
||||
|
||||
**完成內容**:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema_version": "awoooi_gitea_private_inventory_p0_scorecard_v1",
|
||||
"generated_at": "2026-06-29T20:27:30+08:00",
|
||||
"generated_at": "2026-07-03T10:38:00+08:00",
|
||||
"workplan_id": "P0-003",
|
||||
"status": "closed_gitea_private_inventory_controlled_closeout",
|
||||
"source_control_authority": "gitea",
|
||||
@@ -14,16 +14,267 @@
|
||||
"schema_version": "gitea_repo_inventory_v1",
|
||||
"status": "ok",
|
||||
"visibility_scope": "admin_export",
|
||||
"repo_count": 4,
|
||||
"repo_count": 6,
|
||||
"ssh_verified_repo_count": 12,
|
||||
"private_or_auth_only_repo_count": 6,
|
||||
"public_repos": [
|
||||
"wooo/awoooi",
|
||||
"wooo/ewoooc",
|
||||
"wooo/2026FIFAWorldCup",
|
||||
"wooo/agent-bounty-protocol",
|
||||
"wooo/2026FIFAWorldCup"
|
||||
"wooo/vtuber",
|
||||
"wooo/bitan-pharmacy"
|
||||
],
|
||||
"token_present": false,
|
||||
"blocking_reason": "redacted_authenticated_inventory_payload_and_owner_attestation_accepted_for_readback"
|
||||
},
|
||||
"dev_prod_repo_readback": {
|
||||
"schema_version": "gitea_all_product_dev_prod_repo_readback_v1",
|
||||
"generated_at": "2026-07-03T10:38:00+08:00",
|
||||
"source_control_authority": "gitea",
|
||||
"scope": "all_known_product_repositories_dev_prod_branch_readback",
|
||||
"status": "ready_all_expected_product_repos_have_dev_and_main",
|
||||
"summary": {
|
||||
"expected_product_count": 12,
|
||||
"ssh_repo_present_count": 12,
|
||||
"main_branch_present_count": 12,
|
||||
"dev_branch_present_count": 12,
|
||||
"environment_split_ready_count": 12,
|
||||
"public_visible_count": 6,
|
||||
"private_or_auth_only_count": 6,
|
||||
"tokenless_http_404_private_or_auth_count": 6,
|
||||
"missing_repo_count": 0,
|
||||
"missing_main_branch_count": 0,
|
||||
"missing_dev_branch_count": 0,
|
||||
"all_expected_product_repos_have_ssh_refs": true,
|
||||
"all_expected_product_repos_have_dev_and_main": true
|
||||
},
|
||||
"environment_contract": {
|
||||
"prod_environment_branch": "main",
|
||||
"dev_environment_branch": "dev",
|
||||
"separate_environment_model": "branch_pair_per_product_repo",
|
||||
"public_http_404_for_private_repo_is_visibility_or_auth_readback": true
|
||||
},
|
||||
"operation_boundaries": {
|
||||
"ssh_refs_read_only": true,
|
||||
"token_value_collection_allowed": false,
|
||||
"secret_value_collection_allowed": false,
|
||||
"gitea_api_write_allowed": false,
|
||||
"gitea_repo_creation_allowed": false,
|
||||
"gitea_refs_sync_allowed": false,
|
||||
"gitea_visibility_change_allowed": false,
|
||||
"github_api_allowed": false,
|
||||
"github_cli_allowed": false,
|
||||
"raw_session_or_sqlite_read_allowed": false
|
||||
},
|
||||
"products": [
|
||||
{
|
||||
"product_id": "awoooi",
|
||||
"gitea_repo": "wooo/awoooi",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b5f895804e38d50e213328b8ab840ecd0d095c6f",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "25889d4b8edcb83b6ec707c5eef3c21ae5d432b0",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "ewoooc",
|
||||
"gitea_repo": "wooo/ewoooc",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "157f0f98be241ec25e7bd12aee293ef062bdbf71",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "157f0f98be241ec25e7bd12aee293ef062bdbf71",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "2026fifa",
|
||||
"gitea_repo": "wooo/2026FIFAWorldCup",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "64cae96d0d7f0f34bfb5d39782063b522983085c",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "64cae96d0d7f0f34bfb5d39782063b522983085c",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "agent-bounty-protocol",
|
||||
"gitea_repo": "wooo/agent-bounty-protocol",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b7a733f44f4f645dd21a9b4a9075b89c4a324f64",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "b7a733f44f4f645dd21a9b4a9075b89c4a324f64",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "awooogo",
|
||||
"gitea_repo": "wooo/AwoooGo",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "6dcfc9acb415cd6203a4f042696d778505c65d1d",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "8471b376d97c1436d4612ece17f51ba0950f114d",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "stockplatform-v2",
|
||||
"gitea_repo": "wooo/stockplatform-v2",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b33624ced355f4fb1c444e153030aa6bf343bb91",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "c89302f7f120fd44c63d48977e489e6cc4a4a482",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "vibework",
|
||||
"gitea_repo": "wooo/vibework",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "ac4df10f4ebebb365a723306440a9c3f80400ae3",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "ac4df10f4ebebb365a723306440a9c3f80400ae3",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "momo-pro-system",
|
||||
"gitea_repo": "wooo/momo-pro-system",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "25120cbf21ba51affc94d0220ec87e607f59a833",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "25120cbf21ba51affc94d0220ec87e607f59a833",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "tsenyang-website",
|
||||
"gitea_repo": "wooo/tsenyang-website",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b369ed8cb6666e8ddaa2d31e1418a02794fdea9d",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "b369ed8cb6666e8ddaa2d31e1418a02794fdea9d",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "vtuber",
|
||||
"gitea_repo": "wooo/vtuber",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "17f0c8c8ff441eba73b59b4872e840adde403bf0",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "17f0c8c8ff441eba73b59b4872e840adde403bf0",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "bitan-pharmacy",
|
||||
"gitea_repo": "wooo/bitan-pharmacy",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "e122c8cbd9522999fd9844c2b63790fadcc89c20",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "e122c8cbd9522999fd9844c2b63790fadcc89c20",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "clawbot-openclaw",
|
||||
"gitea_repo": "wooo/clawbot-v5",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "22074fbe4d6ec6c11c86f76139eea55756d1d160",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "22074fbe4d6ec6c11c86f76139eea55756d1d160",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
}
|
||||
],
|
||||
"visibility_readback_gaps": [
|
||||
"wooo/AwoooGo",
|
||||
"wooo/stockplatform-v2",
|
||||
"wooo/vibework",
|
||||
"wooo/momo-pro-system",
|
||||
"wooo/tsenyang-website",
|
||||
"wooo/clawbot-v5"
|
||||
]
|
||||
},
|
||||
"product_repo_environment_coverage": {
|
||||
"schema_version": "gitea_all_product_dev_prod_repo_readback_v1",
|
||||
"status": "ready_all_expected_product_repos_have_dev_and_main",
|
||||
"expected_product_count": 12,
|
||||
"ssh_repo_present_count": 12,
|
||||
"main_branch_present_count": 12,
|
||||
"dev_branch_present_count": 12,
|
||||
"environment_split_ready_count": 12,
|
||||
"public_visible_count": 6,
|
||||
"private_or_auth_only_count": 6,
|
||||
"tokenless_http_404_private_or_auth_count": 6,
|
||||
"missing_repo_count": 0,
|
||||
"missing_main_branch_count": 0,
|
||||
"missing_dev_branch_count": 0,
|
||||
"all_expected_product_repos_have_ssh_refs": true,
|
||||
"all_expected_product_repos_have_dev_and_main": true
|
||||
},
|
||||
"authenticated_import_acceptance": {
|
||||
"schema_version": "gitea_authenticated_inventory_import_acceptance_v1",
|
||||
"status": "accepted_for_private_inventory_review_only",
|
||||
@@ -114,163 +365,278 @@
|
||||
"safe_next_step": "continue_to_p0_006_source_to_runtime_drift_cleanup"
|
||||
},
|
||||
"product_row_coverage": {
|
||||
"expected_product_count": 11,
|
||||
"present_product_row_count": 11,
|
||||
"expected_product_count": 12,
|
||||
"present_product_row_count": 12,
|
||||
"missing_product_row_count": 0,
|
||||
"ready_product_count": 3,
|
||||
"blocked_product_count": 8,
|
||||
"internal_or_authenticated_inventory_required_count": 3,
|
||||
"all_active_product_repos_have_gitea_owner_readiness_row": true
|
||||
"ready_product_count": 12,
|
||||
"blocked_product_count": 0,
|
||||
"internal_or_authenticated_inventory_required_count": 6,
|
||||
"all_active_product_repos_have_gitea_owner_readiness_row": true,
|
||||
"all_expected_product_repos_have_dev_and_main": true
|
||||
},
|
||||
"product_rows": [
|
||||
{
|
||||
"product_id": "awoooi",
|
||||
"state": "ready",
|
||||
"status": "ready",
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/awoooi",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b5f895804e38d50e213328b8ab840ecd0d095c6f",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "25889d4b8edcb83b6ec707c5eef3c21ae5d432b0",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"next_gate": "use codex-workspaces/awoooi-dev and branch from dev for tasks",
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "momo-pro",
|
||||
"state": "ready",
|
||||
"status": "ready",
|
||||
"product_id": "ewoooc",
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/ewoooc",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "157f0f98be241ec25e7bd12aee293ef062bdbf71",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "157f0f98be241ec25e7bd12aee293ef062bdbf71",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"next_gate": "use this workspace for Codex tasks by branching from dev into codex/*; do not edit dev directly",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "awooogo",
|
||||
"state": "ready",
|
||||
"status": "ready",
|
||||
"gitea_repo": "wooo/AwoooGo",
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"next_gate": "use this workspace for Codex tasks by branching from dev into codex/*; do not edit dev directly",
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "2026fifa",
|
||||
"state": "blocked",
|
||||
"status": "blocked_local_drift_review_required",
|
||||
"gitea_repo": "",
|
||||
"remote_main_present": false,
|
||||
"remote_dev_present": false,
|
||||
"next_gate": "build narrow drift review and owner pick list before any dev branch creation",
|
||||
"blockers": [
|
||||
"local_head_differs_from_gitea_main",
|
||||
"diff_readback_timeout",
|
||||
"production_branch_checked_out"
|
||||
],
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/2026FIFAWorldCup",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "64cae96d0d7f0f34bfb5d39782063b522983085c",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "64cae96d0d7f0f34bfb5d39782063b522983085c",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "agent-bounty-protocol",
|
||||
"state": "blocked",
|
||||
"status": "blocked_local_drift_review_required",
|
||||
"gitea_repo": "",
|
||||
"remote_main_present": false,
|
||||
"remote_dev_present": false,
|
||||
"next_gate": "owner pick list for A2A/traffic/propose changes before dev branch creation",
|
||||
"blockers": [
|
||||
"local_head_differs_from_gitea_main",
|
||||
"tracked_dirty_worktree",
|
||||
"production_branch_checked_out"
|
||||
],
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/agent-bounty-protocol",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b7a733f44f4f645dd21a9b4a9075b89c4a324f64",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "b7a733f44f4f645dd21a9b4a9075b89c4a324f64",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "awooogo",
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/AwoooGo",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "6dcfc9acb415cd6203a4f042696d778505c65d1d",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "8471b376d97c1436d4612ece17f51ba0950f114d",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "stockplatform-v2",
|
||||
"state": "blocked",
|
||||
"status": "blocked_dirty_worktree_review_required",
|
||||
"gitea_repo": "",
|
||||
"remote_main_present": false,
|
||||
"remote_dev_present": false,
|
||||
"next_gate": "review dirty files and owner-selected include/exclude list before dev branch creation",
|
||||
"blockers": [
|
||||
"tracked_dirty_worktree",
|
||||
"production_branch_checked_out"
|
||||
],
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/stockplatform-v2",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b33624ced355f4fb1c444e153030aa6bf343bb91",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "c89302f7f120fd44c63d48977e489e6cc4a4a482",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "vibework",
|
||||
"state": "blocked",
|
||||
"status": "blocked_local_drift_review_required",
|
||||
"gitea_repo": "",
|
||||
"remote_main_present": false,
|
||||
"remote_dev_present": false,
|
||||
"next_gate": "owner pick list for growth/admin/runtime changes before dev branch creation",
|
||||
"blockers": [
|
||||
"local_head_differs_from_gitea_main",
|
||||
"tracked_dirty_worktree",
|
||||
"production_branch_checked_out"
|
||||
],
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/vibework",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "ac4df10f4ebebb365a723306440a9c3f80400ae3",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "ac4df10f4ebebb365a723306440a9c3f80400ae3",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "clawbot-openclaw",
|
||||
"state": "blocked",
|
||||
"status": "blocked_local_drift_review_required",
|
||||
"gitea_repo": "",
|
||||
"remote_main_present": false,
|
||||
"remote_dev_present": false,
|
||||
"next_gate": "review docker-compose and main.py drift before dev branch creation",
|
||||
"blockers": [
|
||||
"local_head_differs_from_gitea_main",
|
||||
"tracked_dirty_worktree",
|
||||
"production_branch_checked_out"
|
||||
],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "bitan-pharmacy",
|
||||
"state": "blocked",
|
||||
"status": "blocked_internal_inventory_and_dirty_review_required",
|
||||
"gitea_repo": "",
|
||||
"remote_main_present": false,
|
||||
"remote_dev_present": false,
|
||||
"next_gate": "owner export or authenticated inventory plus dirty review",
|
||||
"blockers": [
|
||||
"internal_repo_requires_owner_export_or_authenticated_inventory",
|
||||
"dirty_worktree"
|
||||
],
|
||||
"product_id": "momo-pro-system",
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/momo-pro-system",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "25120cbf21ba51affc94d0220ec87e607f59a833",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "25120cbf21ba51affc94d0220ec87e607f59a833",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "tsenyang-website",
|
||||
"state": "blocked",
|
||||
"status": "blocked_internal_inventory_and_dirty_review_required",
|
||||
"gitea_repo": "",
|
||||
"remote_main_present": false,
|
||||
"remote_dev_present": false,
|
||||
"next_gate": "owner export or authenticated inventory plus dirty review",
|
||||
"blockers": [
|
||||
"internal_repo_requires_owner_export_or_authenticated_inventory",
|
||||
"dirty_worktree"
|
||||
],
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/tsenyang-website",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b369ed8cb6666e8ddaa2d31e1418a02794fdea9d",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "b369ed8cb6666e8ddaa2d31e1418a02794fdea9d",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "vtuber",
|
||||
"state": "blocked",
|
||||
"status": "blocked_repository_inventory_repair_required",
|
||||
"gitea_repo": "",
|
||||
"remote_main_present": false,
|
||||
"remote_dev_present": false,
|
||||
"next_gate": "repair local repository inventory before any Gitea action",
|
||||
"blockers": [
|
||||
"remote_repository_not_found_or_unauthenticated",
|
||||
"local_head_readback_abnormal",
|
||||
"dirty_worktree"
|
||||
],
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/vtuber",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "17f0c8c8ff441eba73b59b4872e840adde403bf0",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "17f0c8c8ff441eba73b59b4872e840adde403bf0",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "bitan-pharmacy",
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/bitan-pharmacy",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "e122c8cbd9522999fd9844c2b63790fadcc89c20",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "e122c8cbd9522999fd9844c2b63790fadcc89c20",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
},
|
||||
{
|
||||
"product_id": "clawbot-openclaw",
|
||||
"state": "repo_environment_ready",
|
||||
"status": "ready_dev_prod_branches_present",
|
||||
"gitea_repo": "wooo/clawbot-v5",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "22074fbe4d6ec6c11c86f76139eea55756d1d160",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "22074fbe4d6ec6c11c86f76139eea55756d1d160",
|
||||
"dev_branch_present": true,
|
||||
"remote_main_present": true,
|
||||
"remote_dev_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true,
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": [],
|
||||
"owner_readiness_row_present": true
|
||||
}
|
||||
],
|
||||
@@ -280,7 +646,8 @@
|
||||
"github_lane_excluded_from_p0_blocker_count=true",
|
||||
"gitea_repo_inventory.status=ok",
|
||||
"gitea_repo_inventory.visibility_scope in authenticated/admin_export",
|
||||
"all_active_product_repos_have_gitea_owner_readiness_row=true"
|
||||
"all_active_product_repos_have_gitea_owner_readiness_row=true",
|
||||
"all_expected_product_repos_have_dev_and_main=true"
|
||||
],
|
||||
"safe_next_step": "continue_to_p0_006_source_to_runtime_drift_cleanup"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
{
|
||||
"schema_version": "gitea_all_product_dev_prod_repo_readback_v1",
|
||||
"generated_at": "2026-07-03T10:38:00+08:00",
|
||||
"source_control_authority": "gitea",
|
||||
"scope": "all_known_product_repositories_dev_prod_branch_readback",
|
||||
"status": "ready_all_expected_product_repos_have_dev_and_main",
|
||||
"summary": {
|
||||
"expected_product_count": 12,
|
||||
"ssh_repo_present_count": 12,
|
||||
"main_branch_present_count": 12,
|
||||
"dev_branch_present_count": 12,
|
||||
"environment_split_ready_count": 12,
|
||||
"public_visible_count": 6,
|
||||
"private_or_auth_only_count": 6,
|
||||
"tokenless_http_404_private_or_auth_count": 6,
|
||||
"missing_repo_count": 0,
|
||||
"missing_main_branch_count": 0,
|
||||
"missing_dev_branch_count": 0,
|
||||
"all_expected_product_repos_have_ssh_refs": true,
|
||||
"all_expected_product_repos_have_dev_and_main": true
|
||||
},
|
||||
"environment_contract": {
|
||||
"prod_environment_branch": "main",
|
||||
"dev_environment_branch": "dev",
|
||||
"separate_environment_model": "branch_pair_per_product_repo",
|
||||
"public_http_404_for_private_repo_is_visibility_or_auth_readback": true
|
||||
},
|
||||
"operation_boundaries": {
|
||||
"ssh_refs_read_only": true,
|
||||
"token_value_collection_allowed": false,
|
||||
"secret_value_collection_allowed": false,
|
||||
"gitea_api_write_allowed": false,
|
||||
"gitea_repo_creation_allowed": false,
|
||||
"gitea_refs_sync_allowed": false,
|
||||
"gitea_visibility_change_allowed": false,
|
||||
"github_api_allowed": false,
|
||||
"github_cli_allowed": false,
|
||||
"raw_session_or_sqlite_read_allowed": false
|
||||
},
|
||||
"products": [
|
||||
{
|
||||
"product_id": "awoooi",
|
||||
"gitea_repo": "wooo/awoooi",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b5f895804e38d50e213328b8ab840ecd0d095c6f",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "25889d4b8edcb83b6ec707c5eef3c21ae5d432b0",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "ewoooc",
|
||||
"gitea_repo": "wooo/ewoooc",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "157f0f98be241ec25e7bd12aee293ef062bdbf71",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "157f0f98be241ec25e7bd12aee293ef062bdbf71",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "2026fifa",
|
||||
"gitea_repo": "wooo/2026FIFAWorldCup",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "64cae96d0d7f0f34bfb5d39782063b522983085c",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "64cae96d0d7f0f34bfb5d39782063b522983085c",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "agent-bounty-protocol",
|
||||
"gitea_repo": "wooo/agent-bounty-protocol",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b7a733f44f4f645dd21a9b4a9075b89c4a324f64",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "b7a733f44f4f645dd21a9b4a9075b89c4a324f64",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "awooogo",
|
||||
"gitea_repo": "wooo/AwoooGo",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "6dcfc9acb415cd6203a4f042696d778505c65d1d",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "8471b376d97c1436d4612ece17f51ba0950f114d",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "stockplatform-v2",
|
||||
"gitea_repo": "wooo/stockplatform-v2",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b33624ced355f4fb1c444e153030aa6bf343bb91",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "c89302f7f120fd44c63d48977e489e6cc4a4a482",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "vibework",
|
||||
"gitea_repo": "wooo/vibework",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "ac4df10f4ebebb365a723306440a9c3f80400ae3",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "ac4df10f4ebebb365a723306440a9c3f80400ae3",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "momo-pro-system",
|
||||
"gitea_repo": "wooo/momo-pro-system",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "25120cbf21ba51affc94d0220ec87e607f59a833",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "25120cbf21ba51affc94d0220ec87e607f59a833",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "tsenyang-website",
|
||||
"gitea_repo": "wooo/tsenyang-website",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "b369ed8cb6666e8ddaa2d31e1418a02794fdea9d",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "b369ed8cb6666e8ddaa2d31e1418a02794fdea9d",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "vtuber",
|
||||
"gitea_repo": "wooo/vtuber",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "17f0c8c8ff441eba73b59b4872e840adde403bf0",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "17f0c8c8ff441eba73b59b4872e840adde403bf0",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "bitan-pharmacy",
|
||||
"gitea_repo": "wooo/bitan-pharmacy",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "e122c8cbd9522999fd9844c2b63790fadcc89c20",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "e122c8cbd9522999fd9844c2b63790fadcc89c20",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 200,
|
||||
"public_ui_visible": true,
|
||||
"visibility_readback": "public_tokenless",
|
||||
"environment_split_ready": true
|
||||
},
|
||||
{
|
||||
"product_id": "clawbot-openclaw",
|
||||
"gitea_repo": "wooo/clawbot-v5",
|
||||
"prod_environment_branch": "main",
|
||||
"prod_branch_sha": "22074fbe4d6ec6c11c86f76139eea55756d1d160",
|
||||
"prod_branch_present": true,
|
||||
"dev_environment_branch": "dev",
|
||||
"dev_branch_sha": "22074fbe4d6ec6c11c86f76139eea55756d1d160",
|
||||
"dev_branch_present": true,
|
||||
"ssh_refs_readable": true,
|
||||
"tokenless_http_status": 404,
|
||||
"public_ui_visible": false,
|
||||
"visibility_readback": "private_or_auth_only",
|
||||
"environment_split_ready": true
|
||||
}
|
||||
],
|
||||
"visibility_readback_gaps": [
|
||||
"wooo/AwoooGo",
|
||||
"wooo/stockplatform-v2",
|
||||
"wooo/vibework",
|
||||
"wooo/momo-pro-system",
|
||||
"wooo/tsenyang-website",
|
||||
"wooo/clawbot-v5"
|
||||
]
|
||||
}
|
||||
@@ -54,6 +54,12 @@ def parse_args() -> argparse.Namespace:
|
||||
type=Path,
|
||||
default=ROOT / "docs/operations/codex-gitea-remaining-products-readback.snapshot.json",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dev-prod-repo-readback",
|
||||
type=Path,
|
||||
default=ROOT
|
||||
/ "docs/operations/gitea-all-product-dev-prod-repo-readback.snapshot.json",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--controlled-closeout-receipt",
|
||||
type=Path,
|
||||
@@ -107,6 +113,37 @@ def product_row(row: dict[str, Any], state: str) -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
def dev_prod_product_row(row: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"product_id": str(row.get("product_id", "")),
|
||||
"state": "repo_environment_ready"
|
||||
if row.get("environment_split_ready") is True
|
||||
else "repo_environment_blocked",
|
||||
"status": "ready_dev_prod_branches_present"
|
||||
if row.get("environment_split_ready") is True
|
||||
else "blocked_dev_prod_branch_readback_incomplete",
|
||||
"gitea_repo": str(row.get("gitea_repo", "")),
|
||||
"prod_environment_branch": str(row.get("prod_environment_branch") or "main"),
|
||||
"prod_branch_sha": str(row.get("prod_branch_sha") or ""),
|
||||
"prod_branch_present": bool(row.get("prod_branch_present", False)),
|
||||
"dev_environment_branch": str(row.get("dev_environment_branch") or "dev"),
|
||||
"dev_branch_sha": str(row.get("dev_branch_sha") or ""),
|
||||
"dev_branch_present": bool(row.get("dev_branch_present", False)),
|
||||
"remote_main_present": bool(row.get("prod_branch_present", False)),
|
||||
"remote_dev_present": bool(row.get("dev_branch_present", False)),
|
||||
"ssh_refs_readable": bool(row.get("ssh_refs_readable", False)),
|
||||
"tokenless_http_status": as_int(row.get("tokenless_http_status")),
|
||||
"public_ui_visible": bool(row.get("public_ui_visible", False)),
|
||||
"visibility_readback": str(row.get("visibility_readback") or "unknown"),
|
||||
"environment_split_ready": bool(row.get("environment_split_ready", False)),
|
||||
"next_gate": "branch from dev for controlled development; deploy from main",
|
||||
"blockers": []
|
||||
if row.get("environment_split_ready") is True
|
||||
else ["dev_prod_branch_readback_incomplete"],
|
||||
"owner_readiness_row_present": bool(row.get("product_id")),
|
||||
}
|
||||
|
||||
|
||||
def build_product_rows(remaining: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
rows: list[dict[str, Any]] = []
|
||||
for row in as_list(remaining.get("ready_products")):
|
||||
@@ -118,6 +155,48 @@ def build_product_rows(remaining: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
return rows
|
||||
|
||||
|
||||
def build_dev_prod_product_rows(readback: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
rows: list[dict[str, Any]] = []
|
||||
for row in as_list(readback.get("products")):
|
||||
if isinstance(row, dict):
|
||||
rows.append(dev_prod_product_row(row))
|
||||
return rows
|
||||
|
||||
|
||||
def build_dev_prod_coverage(readback: dict[str, Any]) -> dict[str, Any]:
|
||||
summary = as_dict(readback.get("summary"))
|
||||
expected = as_int(summary.get("expected_product_count"))
|
||||
ssh_present = as_int(summary.get("ssh_repo_present_count"))
|
||||
main_present = as_int(summary.get("main_branch_present_count"))
|
||||
dev_present = as_int(summary.get("dev_branch_present_count"))
|
||||
split_ready = as_int(summary.get("environment_split_ready_count"))
|
||||
public_visible = as_int(summary.get("public_visible_count"))
|
||||
private_or_auth = as_int(summary.get("private_or_auth_only_count"))
|
||||
return {
|
||||
"schema_version": readback.get("schema_version", ""),
|
||||
"status": str(readback.get("status", "not_run")),
|
||||
"expected_product_count": expected,
|
||||
"ssh_repo_present_count": ssh_present,
|
||||
"main_branch_present_count": main_present,
|
||||
"dev_branch_present_count": dev_present,
|
||||
"environment_split_ready_count": split_ready,
|
||||
"public_visible_count": public_visible,
|
||||
"private_or_auth_only_count": private_or_auth,
|
||||
"tokenless_http_404_private_or_auth_count": as_int(
|
||||
summary.get("tokenless_http_404_private_or_auth_count")
|
||||
),
|
||||
"missing_repo_count": as_int(summary.get("missing_repo_count")),
|
||||
"missing_main_branch_count": as_int(summary.get("missing_main_branch_count")),
|
||||
"missing_dev_branch_count": as_int(summary.get("missing_dev_branch_count")),
|
||||
"all_expected_product_repos_have_ssh_refs": bool(
|
||||
summary.get("all_expected_product_repos_have_ssh_refs", False)
|
||||
),
|
||||
"all_expected_product_repos_have_dev_and_main": bool(
|
||||
summary.get("all_expected_product_repos_have_dev_and_main", False)
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def find_validation_lane(rollup: dict[str, Any], lane_id: str) -> dict[str, Any]:
|
||||
for lane in as_list(rollup.get("validation_lanes")):
|
||||
if isinstance(lane, dict) and lane.get("lane_id") == lane_id:
|
||||
@@ -199,17 +278,23 @@ def build_scorecard(args: argparse.Namespace) -> dict[str, Any]:
|
||||
payload_validation = load_optional_json(args.payload_validation)
|
||||
closeout_receipt = load_optional_json(args.controlled_closeout_receipt)
|
||||
remaining_products = load_json(args.remaining_products)
|
||||
dev_prod_readback = load_optional_json(args.dev_prod_repo_readback)
|
||||
dev_prod_rows = build_dev_prod_product_rows(dev_prod_readback)
|
||||
dev_prod_coverage = build_dev_prod_coverage(dev_prod_readback)
|
||||
owner_response_validation = build_owner_response_validation(
|
||||
owner_response_validation_rollup
|
||||
)
|
||||
closeout_ready = controlled_closeout_ready(closeout_receipt)
|
||||
closeout_result = as_dict(closeout_receipt.get("result"))
|
||||
|
||||
rows = build_product_rows(remaining_products)
|
||||
rows = dev_prod_rows or build_product_rows(remaining_products)
|
||||
summary = remaining_products.get("summary", {})
|
||||
if not isinstance(summary, dict):
|
||||
summary = {}
|
||||
expected_product_count = as_int(summary.get("product_count"), len(rows))
|
||||
expected_product_count = as_int(
|
||||
dev_prod_coverage.get("expected_product_count"),
|
||||
as_int(summary.get("product_count"), len(rows)),
|
||||
)
|
||||
missing_row_count = max(expected_product_count - len(rows), 0)
|
||||
|
||||
gitea_status = str(gitea_inventory.get("status", "unknown"))
|
||||
@@ -249,6 +334,12 @@ def build_scorecard(args: argparse.Namespace) -> dict[str, Any]:
|
||||
for repo in as_list(gitea_inventory.get("repos"))
|
||||
if isinstance(repo, dict) and repo.get("gitea_repo")
|
||||
]
|
||||
if dev_prod_rows:
|
||||
public_repos = [
|
||||
str(row.get("gitea_repo", ""))
|
||||
for row in dev_prod_rows
|
||||
if row.get("public_ui_visible") is True and row.get("gitea_repo")
|
||||
]
|
||||
|
||||
blockers: list[str] = []
|
||||
if gitea_status != "ok":
|
||||
@@ -261,8 +352,18 @@ def build_scorecard(args: argparse.Namespace) -> dict[str, Any]:
|
||||
blockers.append("gitea_owner_coverage_attestation_not_received")
|
||||
if missing_row_count:
|
||||
blockers.append("active_product_readiness_rows_missing")
|
||||
if dev_prod_coverage and (
|
||||
dev_prod_coverage.get("all_expected_product_repos_have_dev_and_main")
|
||||
is not True
|
||||
):
|
||||
blockers.append("dev_prod_branch_readback_incomplete")
|
||||
if closeout_ready:
|
||||
blockers = []
|
||||
if dev_prod_coverage and (
|
||||
dev_prod_coverage.get("all_expected_product_repos_have_dev_and_main")
|
||||
is not True
|
||||
):
|
||||
blockers.append("dev_prod_branch_readback_incomplete")
|
||||
|
||||
return {
|
||||
"schema_version": SCHEMA_VERSION,
|
||||
@@ -289,7 +390,16 @@ def build_scorecard(args: argparse.Namespace) -> dict[str, Any]:
|
||||
"schema_version": gitea_inventory.get("schema_version"),
|
||||
"status": gitea_status,
|
||||
"visibility_scope": visibility_scope,
|
||||
"repo_count": as_int(gitea_inventory.get("repo_count")),
|
||||
"repo_count": as_int(
|
||||
dev_prod_coverage.get("public_visible_count"),
|
||||
as_int(gitea_inventory.get("repo_count")),
|
||||
),
|
||||
"ssh_verified_repo_count": as_int(
|
||||
dev_prod_coverage.get("ssh_repo_present_count")
|
||||
),
|
||||
"private_or_auth_only_repo_count": as_int(
|
||||
dev_prod_coverage.get("private_or_auth_only_count")
|
||||
),
|
||||
"public_repos": public_repos,
|
||||
"token_present": bool(gitea_inventory.get("token_present", False)),
|
||||
"blocking_reason": (
|
||||
@@ -298,6 +408,8 @@ def build_scorecard(args: argparse.Namespace) -> dict[str, Any]:
|
||||
else str(gitea_inventory.get("blocking_reason", ""))
|
||||
),
|
||||
},
|
||||
"dev_prod_repo_readback": dev_prod_readback,
|
||||
"product_repo_environment_coverage": dev_prod_coverage,
|
||||
"authenticated_import_acceptance": {
|
||||
"schema_version": import_acceptance.get("schema_version"),
|
||||
"status": (
|
||||
@@ -356,13 +468,29 @@ def build_scorecard(args: argparse.Namespace) -> dict[str, Any]:
|
||||
"expected_product_count": expected_product_count,
|
||||
"present_product_row_count": len(rows),
|
||||
"missing_product_row_count": missing_row_count,
|
||||
"ready_product_count": len([row for row in rows if row["state"] == "ready"]),
|
||||
"blocked_product_count": len([row for row in rows if row["state"] == "blocked"]),
|
||||
"ready_product_count": len(
|
||||
[
|
||||
row
|
||||
for row in rows
|
||||
if row["state"] in {"ready", "repo_environment_ready"}
|
||||
]
|
||||
),
|
||||
"blocked_product_count": len(
|
||||
[
|
||||
row
|
||||
for row in rows
|
||||
if row["state"] in {"blocked", "repo_environment_blocked"}
|
||||
]
|
||||
),
|
||||
"internal_or_authenticated_inventory_required_count": as_int(
|
||||
summary.get("internal_or_authenticated_inventory_required_count")
|
||||
dev_prod_coverage.get("private_or_auth_only_count"),
|
||||
as_int(summary.get("internal_or_authenticated_inventory_required_count")),
|
||||
),
|
||||
"all_active_product_repos_have_gitea_owner_readiness_row": missing_row_count == 0
|
||||
and all(row["owner_readiness_row_present"] for row in rows),
|
||||
"all_expected_product_repos_have_dev_and_main": bool(
|
||||
dev_prod_coverage.get("all_expected_product_repos_have_dev_and_main")
|
||||
),
|
||||
},
|
||||
"product_rows": rows,
|
||||
"active_blockers": blockers,
|
||||
@@ -372,6 +500,7 @@ def build_scorecard(args: argparse.Namespace) -> dict[str, Any]:
|
||||
"gitea_repo_inventory.status=ok",
|
||||
"gitea_repo_inventory.visibility_scope in authenticated/admin_export",
|
||||
"all_active_product_repos_have_gitea_owner_readiness_row=true",
|
||||
"all_expected_product_repos_have_dev_and_main=true",
|
||||
],
|
||||
"safe_next_step": (
|
||||
"continue_to_p0_006_source_to_runtime_drift_cleanup"
|
||||
|
||||
@@ -41,13 +41,30 @@ def test_scorecard_commits_controlled_closeout_receipt() -> None:
|
||||
assert scorecard["status"] == "closed_gitea_private_inventory_controlled_closeout"
|
||||
assert scorecard["gitea_inventory"]["status"] == "ok"
|
||||
assert scorecard["gitea_inventory"]["visibility_scope"] == "admin_export"
|
||||
assert scorecard["gitea_inventory"]["repo_count"] == 4
|
||||
assert scorecard["gitea_inventory"]["repo_count"] == 6
|
||||
assert scorecard["gitea_inventory"]["ssh_verified_repo_count"] == 12
|
||||
assert scorecard["gitea_inventory"]["private_or_auth_only_repo_count"] == 6
|
||||
assert {
|
||||
"wooo/awoooi",
|
||||
"wooo/ewoooc",
|
||||
"wooo/agent-bounty-protocol",
|
||||
"wooo/2026FIFAWorldCup",
|
||||
"wooo/vtuber",
|
||||
"wooo/bitan-pharmacy",
|
||||
} <= set(scorecard["gitea_inventory"]["public_repos"])
|
||||
env_coverage = scorecard["product_repo_environment_coverage"]
|
||||
assert env_coverage["expected_product_count"] == 12
|
||||
assert env_coverage["ssh_repo_present_count"] == 12
|
||||
assert env_coverage["main_branch_present_count"] == 12
|
||||
assert env_coverage["dev_branch_present_count"] == 12
|
||||
assert env_coverage["environment_split_ready_count"] == 12
|
||||
assert env_coverage["public_visible_count"] == 6
|
||||
assert env_coverage["private_or_auth_only_count"] == 6
|
||||
assert env_coverage["missing_repo_count"] == 0
|
||||
assert env_coverage["missing_main_branch_count"] == 0
|
||||
assert env_coverage["missing_dev_branch_count"] == 0
|
||||
assert env_coverage["all_expected_product_repos_have_ssh_refs"] is True
|
||||
assert env_coverage["all_expected_product_repos_have_dev_and_main"] is True
|
||||
assert scorecard["authenticated_import_acceptance"]["accepted_payload_count"] == 1
|
||||
assert (
|
||||
scorecard["authenticated_payload_validation"]["status"]
|
||||
@@ -109,12 +126,22 @@ def test_scorecard_keeps_all_active_product_rows_visible() -> None:
|
||||
scorecard = load_scorecard()
|
||||
coverage = scorecard["product_row_coverage"]
|
||||
|
||||
assert coverage["expected_product_count"] == 11
|
||||
assert coverage["present_product_row_count"] == 11
|
||||
assert coverage["expected_product_count"] == 12
|
||||
assert coverage["present_product_row_count"] == 12
|
||||
assert coverage["missing_product_row_count"] == 0
|
||||
assert coverage["ready_product_count"] == 3
|
||||
assert coverage["blocked_product_count"] == 8
|
||||
assert coverage["ready_product_count"] == 12
|
||||
assert coverage["blocked_product_count"] == 0
|
||||
assert coverage["all_active_product_repos_have_gitea_owner_readiness_row"] is True
|
||||
assert coverage["all_expected_product_repos_have_dev_and_main"] is True
|
||||
|
||||
product_ids = {row["product_id"] for row in scorecard["product_rows"]}
|
||||
assert {"awoooi", "momo-pro", "awooogo", "bitan-pharmacy", "tsenyang-website"} <= product_ids
|
||||
assert {
|
||||
"awoooi",
|
||||
"ewoooc",
|
||||
"awooogo",
|
||||
"momo-pro-system",
|
||||
"bitan-pharmacy",
|
||||
"tsenyang-website",
|
||||
"clawbot-openclaw",
|
||||
} <= product_ids
|
||||
assert all(row["environment_split_ready"] is True for row in scorecard["product_rows"])
|
||||
|
||||
Reference in New Issue
Block a user