feat(awooop): expose ai automation work items
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 18s
CD Pipeline / build-and-deploy (push) Successful in 5m18s
CD Pipeline / post-deploy-checks (push) Successful in 1m5s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 18s
CD Pipeline / build-and-deploy (push) Successful in 5m18s
CD Pipeline / post-deploy-checks (push) Successful in 1m5s
This commit is contained in:
@@ -596,6 +596,153 @@ def _build_log_integration_taxonomy(
|
||||
}
|
||||
|
||||
|
||||
def _build_work_item_progress(
|
||||
*,
|
||||
trace_ledger: Mapping[str, Any],
|
||||
log_integration_taxonomy: Mapping[str, Any],
|
||||
db_read_status: str,
|
||||
) -> dict[str, Any]:
|
||||
"""Build ordered work items that the UI and agent can keep advancing."""
|
||||
|
||||
taxonomy_rollups = log_integration_taxonomy.get("rollups")
|
||||
if not isinstance(taxonomy_rollups, Mapping):
|
||||
taxonomy_rollups = {}
|
||||
source_families = log_integration_taxonomy.get("source_families")
|
||||
if not isinstance(source_families, list):
|
||||
source_families = []
|
||||
inactive_source_count = _int_value(taxonomy_rollups.get("inactive_source_family_count"))
|
||||
missing_required = trace_ledger.get("missing_required_stage_ids")
|
||||
if not isinstance(missing_required, list):
|
||||
missing_required = []
|
||||
deployed_readback_complete = (
|
||||
db_read_status == "ok"
|
||||
and trace_ledger.get("schema_version") == "ai_agent_autonomous_trace_ledger_v1"
|
||||
and log_integration_taxonomy.get("schema_version") == "ai_agent_log_integration_taxonomy_v1"
|
||||
)
|
||||
|
||||
ordered_items = [
|
||||
{
|
||||
"work_item_id": "P0-A-runtime-truth",
|
||||
"priority": "P0-A",
|
||||
"title": "Controlled apply runtime truth readback",
|
||||
"status": "completed",
|
||||
"exit_criteria": "production API reports db_read_status=ok and live executor receipts",
|
||||
},
|
||||
{
|
||||
"work_item_id": "P0-B-trace-ledger",
|
||||
"priority": "P0-B",
|
||||
"title": "Trace ledger for MCP/log/executor/verifier/KM/PlayBook/Telegram",
|
||||
"status": "completed" if not missing_required else "in_progress",
|
||||
"exit_criteria": "trace_ledger exposes required closed-loop stages and missing_required_stage_ids",
|
||||
},
|
||||
{
|
||||
"work_item_id": "P0-C-log-taxonomy",
|
||||
"priority": "P0-C",
|
||||
"title": "Project/product/site/service/package/tool log taxonomy",
|
||||
"status": "completed",
|
||||
"exit_criteria": "log_integration_taxonomy lists source families, labels, and public-safety policy",
|
||||
},
|
||||
{
|
||||
"work_item_id": "P0-D-ui-visibility",
|
||||
"priority": "P0-D",
|
||||
"title": "AwoooP UI shows automation loop and log integration progress",
|
||||
"status": "completed",
|
||||
"exit_criteria": "AwoooP, Approvals, Runs, and Work Items show trace/log taxonomy panel",
|
||||
},
|
||||
{
|
||||
"work_item_id": "P0-E-verification-deploy",
|
||||
"priority": "P0-E",
|
||||
"title": "Focused verification and production deploy marker readback",
|
||||
"status": "completed" if deployed_readback_complete else "in_progress",
|
||||
"exit_criteria": "deploy marker includes this code and production API exposes trace_ledger/log_integration_taxonomy",
|
||||
"blocker": None if deployed_readback_complete else "waiting_for_successful_gitea_cd_deploy_marker",
|
||||
},
|
||||
{
|
||||
"work_item_id": "P1-A-ingestion-coverage",
|
||||
"priority": "P1-A",
|
||||
"title": "Collector and sanitizer coverage for all source families",
|
||||
"status": "completed" if inactive_source_count == 0 else "in_progress",
|
||||
"exit_criteria": "all source families have active sanitized classified events",
|
||||
"remaining_source_family_count": inactive_source_count,
|
||||
},
|
||||
{
|
||||
"work_item_id": "P1-B-agent-decision-wiring",
|
||||
"priority": "P1-B",
|
||||
"title": "RAG retrieval to PlayBook select/repair/check-mode/apply/verifier",
|
||||
"status": "pending",
|
||||
"exit_criteria": "AI Agent consumes labeled evidence and emits target selector, dry-run, apply, verifier, rollback",
|
||||
},
|
||||
{
|
||||
"work_item_id": "P1-C-learning-loop",
|
||||
"priority": "P1-C",
|
||||
"title": "KM / PlayBook trust learning loop",
|
||||
"status": "pending",
|
||||
"exit_criteria": "verified execution updates KM entries, trust delta, similar-case clusters, and repair candidates",
|
||||
},
|
||||
{
|
||||
"work_item_id": "P1-D-alert-noise-reduction",
|
||||
"priority": "P1-D",
|
||||
"title": "Alert grouping and AI controlled workflow routing",
|
||||
"status": "pending",
|
||||
"exit_criteria": "repeated alerts are clustered, deduped, routed to controlled automation, and no longer default to manual handling",
|
||||
},
|
||||
{
|
||||
"work_item_id": "P2-A-ui-ux-productization",
|
||||
"priority": "P2-A",
|
||||
"title": "Professional product UI replacing text-heavy surfaces",
|
||||
"status": "pending",
|
||||
"exit_criteria": "AI automation status is shown as dense dashboard controls, filters, counters, and action rails",
|
||||
},
|
||||
{
|
||||
"work_item_id": "P2-B-multi-product-expansion",
|
||||
"priority": "P2-B",
|
||||
"title": "Reuse taxonomy across AWOOOI products/projects",
|
||||
"status": "pending",
|
||||
"exit_criteria": "StockPlatform, VibeWork, MOMO, AwoooGo, and other products report the same log taxonomy contract",
|
||||
},
|
||||
]
|
||||
source_family_items = []
|
||||
for source in source_families:
|
||||
if not isinstance(source, Mapping):
|
||||
continue
|
||||
total = _int_value(source.get("total"))
|
||||
source_family_items.append({
|
||||
"work_item_id": f"P1-A-source-{source.get('source_family_id')}",
|
||||
"priority": "P1-A",
|
||||
"source_family_id": source.get("source_family_id"),
|
||||
"title": f"Ingest and label {source.get('source_family_id')}",
|
||||
"status": "completed" if total > 0 else "not_started",
|
||||
"label_dimensions": source.get("label_dimensions") or [],
|
||||
"next_controlled_action": (
|
||||
"keep_learning_and_quality_checks"
|
||||
if total > 0
|
||||
else source.get("next_action_if_empty")
|
||||
),
|
||||
})
|
||||
|
||||
all_items = [*ordered_items, *source_family_items]
|
||||
by_status: dict[str, int] = {}
|
||||
for item in all_items:
|
||||
status = str(item.get("status") or "unknown")
|
||||
by_status[status] = by_status.get(status, 0) + 1
|
||||
return {
|
||||
"schema_version": "ai_agent_automation_work_item_progress_v1",
|
||||
"ordered_items": ordered_items,
|
||||
"source_family_items": source_family_items,
|
||||
"rollups": {
|
||||
"work_item_count": len(all_items),
|
||||
"ordered_work_item_count": len(ordered_items),
|
||||
"source_family_work_item_count": len(source_family_items),
|
||||
"completed_count": by_status.get("completed", 0),
|
||||
"in_progress_count": by_status.get("in_progress", 0),
|
||||
"pending_count": by_status.get("pending", 0),
|
||||
"blocked_count": by_status.get("blocked", 0),
|
||||
"not_started_count": by_status.get("not_started", 0),
|
||||
"by_status": by_status,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _first_operation(
|
||||
rows: Iterable[Mapping[str, Any]],
|
||||
operation_type: str,
|
||||
@@ -1396,6 +1543,11 @@ def build_runtime_receipt_readback_from_rows(
|
||||
timeline_summary=timeline_summary,
|
||||
playbook_trust_summary=playbook_trust_summary,
|
||||
)
|
||||
work_item_progress = _build_work_item_progress(
|
||||
trace_ledger=trace_ledger,
|
||||
log_integration_taxonomy=log_integration_taxonomy,
|
||||
db_read_status=db_read_status,
|
||||
)
|
||||
apply_summary = operation_summary.get("ansible_apply_executed") or {}
|
||||
readback = {
|
||||
"schema_version": _LIVE_READBACK_SCHEMA_VERSION,
|
||||
@@ -1515,6 +1667,7 @@ def build_runtime_receipt_readback_from_rows(
|
||||
"autonomous_execution_loop_ledger": loop_ledger,
|
||||
"trace_ledger": trace_ledger,
|
||||
"log_integration_taxonomy": log_integration_taxonomy,
|
||||
"work_item_progress": work_item_progress,
|
||||
}
|
||||
if error_type:
|
||||
readback["error"] = {
|
||||
@@ -1617,6 +1770,31 @@ def _attach_runtime_receipt_readback(
|
||||
"recent_classified_event_total"
|
||||
)
|
||||
),
|
||||
"live_work_item_count": _int_value(
|
||||
((readback.get("work_item_progress") or {}).get("rollups") or {}).get(
|
||||
"work_item_count"
|
||||
)
|
||||
),
|
||||
"live_work_item_completed_count": _int_value(
|
||||
((readback.get("work_item_progress") or {}).get("rollups") or {}).get(
|
||||
"completed_count"
|
||||
)
|
||||
),
|
||||
"live_work_item_in_progress_count": _int_value(
|
||||
((readback.get("work_item_progress") or {}).get("rollups") or {}).get(
|
||||
"in_progress_count"
|
||||
)
|
||||
),
|
||||
"live_work_item_pending_count": _int_value(
|
||||
((readback.get("work_item_progress") or {}).get("rollups") or {}).get(
|
||||
"pending_count"
|
||||
)
|
||||
),
|
||||
"live_work_item_blocked_count": _int_value(
|
||||
((readback.get("work_item_progress") or {}).get("rollups") or {}).get(
|
||||
"blocked_count"
|
||||
)
|
||||
),
|
||||
})
|
||||
return payload
|
||||
|
||||
|
||||
@@ -384,6 +384,28 @@ def test_runtime_receipt_readback_summarizes_live_executor_closure_rows():
|
||||
assert taxonomy["rollups"]["classified_event_total"] > 0
|
||||
assert taxonomy["public_safety"]["raw_secret_collection_allowed"] is False
|
||||
assert taxonomy["public_safety"]["unredacted_payload_storage_allowed"] is False
|
||||
progress = readback["work_item_progress"]
|
||||
assert progress["schema_version"] == "ai_agent_automation_work_item_progress_v1"
|
||||
ordered_ids = [item["work_item_id"] for item in progress["ordered_items"]]
|
||||
assert ordered_ids == [
|
||||
"P0-A-runtime-truth",
|
||||
"P0-B-trace-ledger",
|
||||
"P0-C-log-taxonomy",
|
||||
"P0-D-ui-visibility",
|
||||
"P0-E-verification-deploy",
|
||||
"P1-A-ingestion-coverage",
|
||||
"P1-B-agent-decision-wiring",
|
||||
"P1-C-learning-loop",
|
||||
"P1-D-alert-noise-reduction",
|
||||
"P2-A-ui-ux-productization",
|
||||
"P2-B-multi-product-expansion",
|
||||
]
|
||||
assert progress["ordered_items"][4]["status"] == "completed"
|
||||
assert progress["ordered_items"][5]["status"] == "completed"
|
||||
assert progress["source_family_items"]
|
||||
assert {item["status"] for item in progress["source_family_items"]} == {"completed"}
|
||||
assert progress["rollups"]["source_family_work_item_count"] == 10
|
||||
assert progress["rollups"]["pending_count"] >= 5
|
||||
|
||||
|
||||
def test_runtime_receipt_readback_classifies_closed_failed_apply_as_ai_repair():
|
||||
|
||||
@@ -11355,7 +11355,9 @@
|
||||
"sources": "Log sources",
|
||||
"labels": "Label dimensions",
|
||||
"events": "Classified events",
|
||||
"learning": "Learning sources"
|
||||
"learning": "Learning sources",
|
||||
"workItems": "Work items",
|
||||
"workItemsDetail": "Active {active} / pending {pending} / blocked {blocked}"
|
||||
},
|
||||
"policy": {
|
||||
"label": "Controlled risk tiers",
|
||||
|
||||
@@ -11355,7 +11355,9 @@
|
||||
"sources": "Log 來源",
|
||||
"labels": "貼標維度",
|
||||
"events": "分類事件",
|
||||
"learning": "學習來源"
|
||||
"learning": "學習來源",
|
||||
"workItems": "工作項目",
|
||||
"workItemsDetail": "進行 {active} / 待辦 {pending} / 阻塞 {blocked}"
|
||||
},
|
||||
"policy": {
|
||||
"label": "受控風險層",
|
||||
|
||||
@@ -88,6 +88,15 @@ type RuntimeReceiptReadback = {
|
||||
learning_source_family_count?: number | null;
|
||||
} | null;
|
||||
} | null;
|
||||
work_item_progress?: {
|
||||
rollups?: {
|
||||
work_item_count?: number | null;
|
||||
completed_count?: number | null;
|
||||
in_progress_count?: number | null;
|
||||
pending_count?: number | null;
|
||||
blocked_count?: number | null;
|
||||
} | null;
|
||||
} | null;
|
||||
latest_flow_closure?: {
|
||||
apply_op_id?: string | null;
|
||||
incident_id?: string | null;
|
||||
@@ -208,6 +217,7 @@ export function AutonomousRuntimeReceiptPanel({
|
||||
const traceLedger = readback?.trace_ledger;
|
||||
const logTaxonomy = readback?.log_integration_taxonomy;
|
||||
const logRollups = logTaxonomy?.rollups ?? {};
|
||||
const workItemRollups = readback?.work_item_progress?.rollups ?? {};
|
||||
const latestFlow = readback?.latest_flow_closure;
|
||||
const rollups = payload?.rollups ?? {};
|
||||
const closed = ledger?.closed === true || latestFlow?.closed === true;
|
||||
@@ -400,7 +410,7 @@ export function AutonomousRuntimeReceiptPanel({
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="grid gap-px border-t border-[#e0ddd4] bg-[#e0ddd4] md:grid-cols-4">
|
||||
<div className="grid gap-px border-t border-[#e0ddd4] bg-[#e0ddd4] md:grid-cols-5">
|
||||
<div className="bg-white px-4 py-3">
|
||||
<p className="text-xs font-semibold text-[#77736a]">{t("taxonomy.sources")}</p>
|
||||
<p className="mt-1 text-sm font-semibold text-[#141413]">
|
||||
@@ -427,6 +437,21 @@ export function AutonomousRuntimeReceiptPanel({
|
||||
{numberValue(logRollups.learning_source_family_count)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white px-4 py-3">
|
||||
<p className="text-xs font-semibold text-[#77736a]">{t("taxonomy.workItems")}</p>
|
||||
<p className="mt-1 text-sm font-semibold text-[#141413]">
|
||||
{numberValue(rollups.live_work_item_completed_count ?? workItemRollups.completed_count)}
|
||||
{" / "}
|
||||
{numberValue(rollups.live_work_item_count ?? workItemRollups.work_item_count)}
|
||||
</p>
|
||||
<p className="mt-1 text-xs leading-5 text-[#5f5b52]">
|
||||
{t("taxonomy.workItemsDetail", {
|
||||
active: numberValue(rollups.live_work_item_in_progress_count ?? workItemRollups.in_progress_count),
|
||||
pending: numberValue(rollups.live_work_item_pending_count ?? workItemRollups.pending_count),
|
||||
blocked: numberValue(rollups.live_work_item_blocked_count ?? workItemRollups.blocked_count),
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{mode === "full" ? (
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
**完成內容**:
|
||||
- `agent-autonomous-runtime-control` readback 新增 `trace_ledger`,把 MCP、service/package log evidence、executor log projection、candidate、check-mode、controlled apply、auto-repair receipt、post-apply verifier、KM/RAG、PlayBook trust、timeline projection、Telegram receipt 收斂為 12 個 public-safe 節點。
|
||||
- 新增 `log_integration_taxonomy`,把專案 / 產品 / 網站 / 服務 / 套件 / 工具 / incident / operation / playbook 等 label dimensions 與 10 類 source families 明確列入 API,供 AI Agent 分類、分群、RAG retrieve、PlayBook 選擇與學習回寫。
|
||||
- AwoooP 主頁、Approvals、Runs、Work Items 新增 `AutonomousRuntimeReceiptPanel`,顯示 Loop / Trace / MCP / Logs / Apply / Verifier / KM-RAG / PlayBook / Telegram 與 Log 來源、貼標維度、分類事件、學習來源。
|
||||
- 新增 `work_item_progress`,把 P0-A 到 P2-B 的 ordered work items 與每個 source family 接入狀態列成可計數 readback:completed / in_progress / pending / blocked / not_started。
|
||||
- AwoooP 主頁、Approvals、Runs、Work Items 新增 `AutonomousRuntimeReceiptPanel`,顯示 Loop / Trace / MCP / Logs / Apply / Verifier / KM-RAG / PlayBook / Telegram 與 Log 來源、貼標維度、分類事件、學習來源、工作項目完成度。
|
||||
- 補 `sidebar.iwooos` / `sidebar.iwooosSecurityCompliance` i18n,避免 IwoooS 導航入口在 runtime console 出現 missing message。
|
||||
|
||||
**驗證結果**:
|
||||
|
||||
Reference in New Issue
Block a user