init: company-haness 설계

This commit is contained in:
DongHyeonka
2026-07-23 17:49:00 +09:00
parent 57d1bab894
commit f668d6a158
962 changed files with 98989 additions and 1 deletions
+2
View File
@@ -0,0 +1,2 @@
"""Reusable state-kernel services behind the compatibility ``state_engine.py`` CLI."""
+94
View File
@@ -0,0 +1,94 @@
"""Append-only JSONL primitives for the Org OS state kernel."""
from __future__ import annotations
import json
import os
from contextlib import nullcontext
from typing import Any, Callable, ContextManager, Iterable
def read_jsonl(path: str | None, on_error: Callable[[str], None] | None = None) -> list[dict[str, Any]]:
if not path or not os.path.exists(path):
return []
rows: list[dict[str, Any]] = []
try:
with open(path, encoding="utf-8") as handle:
for line in handle:
try:
value = json.loads(line)
except Exception:
continue
if isinstance(value, dict):
rows.append(value)
except Exception as exc:
if on_error:
on_error(f"event 원장 읽기 실패({path}): {exc}")
return rows
def append_jsonl(
path: str | None,
event: dict[str, Any],
*,
file_lock: bool = False,
on_error: Callable[[str], None] | None = None,
) -> bool:
if not path:
return False
try:
with open(path, "a", encoding="utf-8") as handle:
if file_lock:
try:
import fcntl
fcntl.flock(handle.fileno(), fcntl.LOCK_EX)
except Exception:
pass
handle.write(json.dumps(event, ensure_ascii=False) + "\n")
handle.flush()
os.fsync(handle.fileno())
return True
except Exception as exc:
if on_error:
on_error(f"event append 실패({path}): {exc}")
return False
def atomic_append(
entries: Iterable[tuple[str | None, dict[str, Any]]],
*,
transaction_lock: ContextManager[Any] | None = None,
) -> None:
"""Append a group of events and truncate every participating tail on failure."""
normalized = list(entries)
handles: list[tuple[Any, int]] = []
with (transaction_lock or nullcontext()):
try:
for path, _event in normalized:
if not path:
raise OSError("event path 해석 실패")
handle = open(path, "a+", encoding="utf-8")
try:
import fcntl
fcntl.flock(handle.fileno(), fcntl.LOCK_EX)
except Exception:
pass
handle.seek(0, os.SEEK_END)
handles.append((handle, handle.tell()))
try:
for (handle, _offset), (_path, event) in zip(handles, normalized):
handle.write(json.dumps(event, ensure_ascii=False) + "\n")
handle.flush()
os.fsync(handle.fileno())
except Exception:
for handle, offset in handles:
handle.seek(offset)
handle.truncate()
handle.flush()
raise
finally:
for handle, _offset in handles:
try:
handle.close()
except Exception:
pass
+172
View File
@@ -0,0 +1,172 @@
"""Deterministic workflow materialized-view projection from canonical events."""
from __future__ import annotations
from typing import Any, Callable
PROTECTED_FIELDS = (
"quality_gate_status", "quality-gate-status",
"release_acceptance_status", "release-acceptance-status",
"unresolved_critical_risks", "unresolved-critical-risks",
"blocker-open", "blocker_open", "resume-condition",
"resume_condition_present", "resume-condition-satisfied",
"resume_condition_satisfied", "evidence-grade", "evidence_grade",
"human_gate_approved", "human-gate-approved",
"current-quality-event-id", "current-quality-event-ids",
"current-quality-artifact-id", "current-quality-artifact-sha256",
"current-completion-artifact-id", "current-completion-artifact-sha256",
"quality-panel-unmet",
)
def _latest_artifact_of_kind(artifacts: list[dict[str, Any]], kind: str) -> dict[str, Any] | None:
return next((artifact for artifact in reversed(artifacts or [])
if isinstance(artifact, dict) and artifact.get("artifact-kind") == kind), None)
def project_workflow(
ledger: dict[str, Any],
*,
trusted_artifacts: list[dict[str, Any]],
workflow_events: list[dict[str, Any]],
initial_stage: Callable[[str], str],
quality_panel_unmet: Callable[[str, list[dict[str, Any]], list[dict[str, Any]]], list[str]],
default_plan: str,
) -> dict[str, Any]:
"""Rebuild protected fields; caller-owned data is never accepted as runtime truth."""
projected = dict(ledger)
for key in PROTECTED_FIELDS:
projected.pop(key, None)
projected["artifacts"] = trusted_artifacts
quality_events: list[dict[str, Any]] = []
release_events: list[dict[str, Any]] = []
for event in workflow_events:
event_type = event.get("event-type")
if event_type == "workflow-initialized":
projected["stage"] = event.get("stage") or initial_stage(event.get("plan", default_plan))
projected["stage-status"] = "running"
projected["last-completed-stage"] = None
projected["completed-for-next-stage"] = None
projected.pop("blocked-from", None)
projected.pop("design-direction-approval", None)
projected.pop("experience-foundation-approval", None)
for key in (
"plan", "tier", "mode", "evidence-contract-version",
"parent-workflow-id", "product-decision-id",
"direction-input-brief-ref", "direction-input-brief-sha256",
):
if event.get(key) is not None:
projected[key] = event.get(key)
elif event_type == "state-transition":
projected["stage"] = event.get("to") or projected.get("stage")
projected["stage-status"] = "running"
projected["last-completed-stage"] = event.get("from")
projected["completed-for-next-stage"] = None
if event.get("to") == "blocked":
projected["blocked-from"] = event.get("from")
elif event.get("from") == "blocked":
projected.pop("blocked-from", None)
elif event_type == "stage-completed":
if event.get("stage") == projected.get("stage"):
projected["stage-status"] = "completed"
projected["last-completed-stage"] = event.get("stage")
projected["completed-for-next-stage"] = event.get("intended-next-stage")
elif event_type == "quality-gate-recorded":
quality_events.append(event)
elif event_type == "release-decision-recorded":
release_events.append(event)
elif event_type == "tier-escalated":
projected["tier"] = event.get("to-tier") or projected.get("tier")
elif event_type == "workflow-blocked":
projected["blocked-from"] = event.get("blocked-from") or projected.get("stage")
projected["stage"] = "blocked"
projected["stage-status"] = "running"
projected["completed-for-next-stage"] = None
projected["blocker-open"] = True
projected["resume-condition"] = event.get("resume-condition")
projected.pop("resume-condition-satisfied", None)
elif event_type == "workflow-resumed":
projected["stage"] = event.get("to") or projected.get("blocked-from") or projected.get("stage")
projected["stage-status"] = "running"
projected["completed-for-next-stage"] = None
projected.pop("blocked-from", None)
projected["blocker-open"] = False
projected["resume-condition-satisfied"] = True
elif event_type == "direction-approval-registered":
projected["design-direction-approval"] = {
"report-ref": event.get("report-ref"),
"report-sha256": event.get("report-sha256"),
"child-workflow-id": event.get("child-workflow-id"),
}
elif event_type == "experience-foundation-registered":
projected["experience-foundation-approval"] = {
"child-workflow-id": event.get("child-workflow-id"),
"product-decision-id": event.get("product-decision-id"),
"benchmark-id": event.get("benchmark-id"),
"benchmark-ref": event.get("benchmark-ref"),
"benchmark-sha256": event.get("benchmark-sha256"),
"strategy-id": event.get("strategy-id"),
"strategy-ref": event.get("strategy-ref"),
"strategy-sha256": event.get("strategy-sha256"),
"technical-id": event.get("technical-id"),
"technical-ref": event.get("technical-ref"),
"technical-sha256": event.get("technical-sha256"),
"operational-id": event.get("operational-id"),
"operational-ref": event.get("operational-ref"),
"operational-sha256": event.get("operational-sha256"),
"blueprint-id": event.get("blueprint-id"),
"blueprint-ref": event.get("blueprint-ref"),
"blueprint-sha256": event.get("blueprint-sha256"),
"wireframe-id": event.get("wireframe-id"),
"wireframe-ref": event.get("wireframe-ref"),
"wireframe-sha256": event.get("wireframe-sha256"),
}
completion = _latest_artifact_of_kind(trusted_artifacts, "completion-record")
if not completion:
return projected
completion_id = completion.get("artifact-id")
completion_sha = completion.get("artifact-sha256")
projected["current-completion-artifact-id"] = completion_id
projected["current-completion-artifact-sha256"] = completion_sha
current_quality = [
event for event in quality_events
if event.get("reviewed-artifact-id") == completion_id
and event.get("reviewed-artifact-sha256") == completion_sha
and any(
artifact.get("artifact-id") == event.get("review-artifact-id")
and artifact.get("artifact-sha256") == event.get("review-artifact-sha256")
for artifact in trusted_artifacts
)
]
latest_by_actor = {event.get("actor"): event for event in current_quality}
active_quality = list(latest_by_actor.values())
if active_quality:
failed = any(event.get("status") != "Passed" or event.get("blocker-open")
for event in active_quality)
projected["quality_gate_status"] = "Failed" if failed else "Passed"
projected["blocker-open"] = bool(projected.get("blocker-open")) or any(
bool(event.get("blocker-open")) for event in active_quality)
last_quality = active_quality[-1]
projected["current-quality-event-id"] = last_quality.get("workflow-event-id")
projected["current-quality-event-ids"] = sorted(
event.get("workflow-event-id") for event in active_quality if event.get("workflow-event-id")
)
projected["current-quality-artifact-id"] = last_quality.get("review-artifact-id")
projected["current-quality-artifact-sha256"] = last_quality.get("review-artifact-sha256")
panel_unmet = quality_panel_unmet(projected.get("tier"), trusted_artifacts, active_quality)
if panel_unmet:
projected["quality-panel-unmet"] = panel_unmet
projected.pop("quality_gate_status", None)
active_event_ids = projected.get("current-quality-event-ids") or []
for event in release_events:
if (event.get("reviewed-completion-artifact-id") != completion_id
or event.get("reviewed-completion-artifact-sha256") != completion_sha
or sorted(event.get("quality-event-set") or []) != active_event_ids):
continue
if event.get("status") == "Approved" and (
projected.get("quality_gate_status") != "Passed" or projected.get("blocker-open")):
continue
projected["release_acceptance_status"] = event.get("status")
projected["unresolved_critical_risks"] = bool(event.get("unresolved-critical-risks"))
return projected
@@ -0,0 +1,93 @@
"""Pure workflow transition evaluation; state I/O remains outside this module."""
from __future__ import annotations
from typing import Any, Callable
def structural_next(
current: str,
plan_stages: list[str],
transitions: list[dict[str, Any]],
blocked_from: str | None = None,
) -> list[str]:
destinations: set[str] = set()
if current in plan_stages:
index = plan_stages.index(current)
if index + 1 < len(plan_stages):
destinations.add(plan_stages[index + 1])
for transition in transitions:
source = transition.get("from")
destination = transition.get("to")
if source == current:
if destination == "<resume>":
if blocked_from:
destinations.add(blocked_from)
elif destination:
destinations.add(destination)
elif source == "*" and current not in ("blocked", "closed") and destination:
destinations.add(destination)
destinations.discard("<resume>")
destinations.discard("*")
return sorted(destinations)
def actor_allowed(
transition: dict[str, Any],
actor: str | None,
role_registry: dict[str, Any],
) -> tuple[bool, str | None]:
allowed = transition.get("allowed-by") or []
if not str(actor or "").strip():
return False, "전이 주체(--actor) 미지정 — 누가 전이하는지 명시해야 한다(권한/감사)."
if not allowed:
return True, None
normalized = str(actor).strip()
if normalized not in role_registry:
return False, f"actor '{normalized}'는 role registry에 없는 역할이다"
if isinstance(allowed, dict):
concrete = allowed.get("executor") or allowed.get("concrete-roles") or []
else:
concrete = [value for value in allowed
if isinstance(value, str) and not value.endswith("-role-agent")]
if normalized in concrete:
return True, None
if not concrete:
return False, f"allowed-by가 placeholder만 포함해 runtime 권한을 결정할 수 없다: {allowed}"
return False, f"actor '{actor}' 는 transition executor {concrete} 에 없다(권한 없음)."
def evaluate_transition(
transition: dict[str, Any],
*,
current: str,
destination: str,
plan: str,
plan_stages: set[str],
blocked_from: str | None,
facts: dict[str, Any],
condition_evaluator: Callable[[Any, dict[str, Any]], tuple[bool, str | None]],
actor: str | None = None,
role_registry: dict[str, Any] | None = None,
) -> list[str]:
universal = (destination == "blocked" or current == "blocked"
or destination == current or transition.get("from") == "*")
if plan_stages and not universal and destination not in plan_stages:
return [f"plan '{plan}' 시퀀스에 없는 stage 전이 금지: {current} -> {destination} "
f"(plan stages: {sorted(plan_stages)})"]
if actor:
permitted, reason = actor_allowed(transition, actor, role_registry or {})
if not permitted:
return [reason or "transition actor 권한 없음"]
if current == "blocked" and blocked_from and destination != blocked_from:
return [f"blocked 재개 대상은 {blocked_from} 여야 합니다(요청: {destination})"]
reasons: list[str] = []
for condition in transition.get("required-conditions") or []:
passed, reason = condition_evaluator(condition, facts)
if not passed:
reasons.append(reason or f"조건 미충족: {condition}")
for condition in transition.get("forbidden-if") or []:
passed, _reason = condition_evaluator(condition, facts)
if passed:
reasons.append(f"금지조건 충족: {condition}")
return reasons