556 lines
29 KiB
Python
556 lines
29 KiB
Python
from __future__ import annotations
|
|
|
|
from django.db import models
|
|
|
|
from control_plane.common import TimestampedModel
|
|
|
|
|
|
class ProjectStatus(models.TextChoices):
|
|
PLANNING = "PLANNING"
|
|
READY = "READY"
|
|
ARCHAEOLOGY = "ARCHAEOLOGY"
|
|
BUILDING = "BUILDING"
|
|
PAUSING = "PAUSING"
|
|
PAUSED = "PAUSED"
|
|
BLOCKED = "BLOCKED"
|
|
VERIFYING = "VERIFYING"
|
|
FINISHED = "FINISHED"
|
|
FAILED = "FAILED"
|
|
|
|
|
|
class Project(TimestampedModel):
|
|
name = models.CharField(max_length=200)
|
|
project_type = models.CharField(max_length=100, default="WEB_APP")
|
|
goal = models.TextField()
|
|
repository_url = models.TextField(blank=True)
|
|
repository_path = models.TextField(blank=True)
|
|
status = models.CharField(max_length=32, choices=ProjectStatus.choices, default=ProjectStatus.PLANNING)
|
|
current_plan_version = models.PositiveIntegerField(default=0)
|
|
architecture_summary = models.TextField(blank=True)
|
|
constraints = models.JSONField(default=dict, blank=True)
|
|
budget = models.JSONField(default=dict, blank=True)
|
|
|
|
def __str__(self) -> str:
|
|
return self.name
|
|
|
|
|
|
class ProjectPlan(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="plans")
|
|
version = models.PositiveIntegerField()
|
|
goal = models.TextField()
|
|
scope = models.TextField(blank=True)
|
|
stack = models.JSONField(default=dict, blank=True)
|
|
architecture = models.JSONField(default=dict, blank=True)
|
|
constraints = models.JSONField(default=dict, blank=True)
|
|
acceptance_criteria = models.JSONField(default=list, blank=True)
|
|
permissions = models.JSONField(default=dict, blank=True)
|
|
budget = models.JSONField(default=dict, blank=True)
|
|
open_decisions = models.JSONField(default=list, blank=True)
|
|
approved_at = models.DateTimeField(null=True, blank=True)
|
|
|
|
class Meta:
|
|
constraints = [models.UniqueConstraint(fields=["project", "version"], name="unique_plan_version")]
|
|
|
|
|
|
class MilestoneStatus(models.TextChoices):
|
|
QUEUED = "QUEUED"
|
|
READY = "READY"
|
|
RUNNING = "RUNNING"
|
|
VERIFYING = "VERIFYING"
|
|
COMPLETE = "COMPLETE"
|
|
BLOCKED = "BLOCKED"
|
|
FAILED = "FAILED"
|
|
|
|
|
|
class Milestone(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="milestones")
|
|
plan = models.ForeignKey(ProjectPlan, on_delete=models.PROTECT, related_name="milestones")
|
|
key = models.CharField(max_length=50)
|
|
title = models.CharField(max_length=200)
|
|
goal = models.TextField()
|
|
status = models.CharField(max_length=32, choices=MilestoneStatus.choices, default=MilestoneStatus.QUEUED)
|
|
dependencies = models.ManyToManyField("self", symmetrical=False, blank=True)
|
|
verification_contract = models.JSONField(default=dict, blank=True)
|
|
order = models.PositiveIntegerField(default=0)
|
|
|
|
class Meta:
|
|
ordering = ["order", "created_at"]
|
|
constraints = [models.UniqueConstraint(fields=["project", "key"], name="unique_milestone_key")]
|
|
|
|
|
|
class Feature(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="features")
|
|
milestone = models.ForeignKey(Milestone, on_delete=models.CASCADE, related_name="features")
|
|
title = models.CharField(max_length=200)
|
|
description = models.TextField(blank=True)
|
|
acceptance_criteria = models.JSONField(default=list, blank=True)
|
|
status = models.CharField(max_length=32, choices=MilestoneStatus.choices, default=MilestoneStatus.QUEUED)
|
|
|
|
|
|
class TaskStatus(models.TextChoices):
|
|
QUEUED = "QUEUED"
|
|
READY = "READY"
|
|
RUNNING = "RUNNING"
|
|
WAITING_TOOL = "WAITING_TOOL"
|
|
REVIEW = "REVIEW"
|
|
BLOCKED = "BLOCKED"
|
|
FAILED = "FAILED"
|
|
COMPLETE = "COMPLETE"
|
|
|
|
|
|
class TaskPriority(models.IntegerChoices):
|
|
LOW = 10
|
|
NORMAL = 50
|
|
HIGH = 80
|
|
CRITICAL = 100
|
|
|
|
|
|
class Task(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="tasks")
|
|
milestone = models.ForeignKey(Milestone, on_delete=models.PROTECT, related_name="tasks")
|
|
feature = models.ForeignKey(Feature, on_delete=models.PROTECT, related_name="tasks", null=True, blank=True)
|
|
task_type = models.CharField(max_length=80)
|
|
status = models.CharField(max_length=32, choices=TaskStatus.choices, default=TaskStatus.QUEUED)
|
|
priority = models.PositiveSmallIntegerField(choices=TaskPriority.choices, default=TaskPriority.NORMAL)
|
|
goal = models.TextField()
|
|
acceptance_criteria = models.JSONField(default=list, blank=True)
|
|
assigned_agent_version = models.ForeignKey(
|
|
"agents.AgentVersion", on_delete=models.SET_NULL, null=True, blank=True, related_name="tasks"
|
|
)
|
|
retry_count = models.PositiveIntegerField(default=0)
|
|
max_retries = models.PositiveIntegerField(default=2)
|
|
|
|
class Meta:
|
|
indexes = [models.Index(fields=["project", "status", "priority"])]
|
|
|
|
|
|
class TaskDependency(TimestampedModel):
|
|
task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name="dependency_edges")
|
|
depends_on = models.ForeignKey(Task, on_delete=models.CASCADE, related_name="dependent_edges")
|
|
|
|
class Meta:
|
|
constraints = [models.UniqueConstraint(fields=["task", "depends_on"], name="unique_task_dependency")]
|
|
|
|
|
|
class Action(TimestampedModel):
|
|
task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name="actions")
|
|
action_type = models.CharField(max_length=80)
|
|
status = models.CharField(max_length=32, default="PENDING")
|
|
contract = models.JSONField(default=dict, blank=True)
|
|
result = models.JSONField(default=dict, blank=True)
|
|
started_at = models.DateTimeField(null=True, blank=True)
|
|
finished_at = models.DateTimeField(null=True, blank=True)
|
|
|
|
|
|
class Worktree(TimestampedModel):
|
|
task = models.OneToOneField(Task, on_delete=models.CASCADE, related_name="worktree")
|
|
repository_path = models.TextField()
|
|
worktree_path = models.TextField()
|
|
branch_name = models.CharField(max_length=255)
|
|
base_ref = models.CharField(max_length=255, default="main")
|
|
status = models.CharField(max_length=32, default="ACTIVE")
|
|
|
|
|
|
class CommitRecord(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="commits")
|
|
task = models.ForeignKey(Task, on_delete=models.SET_NULL, null=True, blank=True, related_name="commits")
|
|
worktree = models.ForeignKey(Worktree, on_delete=models.SET_NULL, null=True, blank=True, related_name="commits")
|
|
coder = models.ForeignKey(
|
|
"agents.AgentVersion", on_delete=models.SET_NULL, null=True, blank=True, related_name="coded_commits"
|
|
)
|
|
reviewer = models.ForeignKey(
|
|
"agents.AgentVersion", on_delete=models.SET_NULL, null=True, blank=True, related_name="reviewed_commits"
|
|
)
|
|
judge = models.ForeignKey(
|
|
"agents.AgentVersion", on_delete=models.SET_NULL, null=True, blank=True, related_name="judged_commits"
|
|
)
|
|
test_run = models.ForeignKey(
|
|
"verification.TestRun", on_delete=models.SET_NULL, null=True, blank=True, related_name="commits"
|
|
)
|
|
review = models.ForeignKey(
|
|
"verification.Review", on_delete=models.SET_NULL, null=True, blank=True, related_name="commits"
|
|
)
|
|
verification = models.ForeignKey(
|
|
"verification.Verification", on_delete=models.SET_NULL, null=True, blank=True, related_name="commits"
|
|
)
|
|
graph_run = models.ForeignKey(
|
|
"graph.GraphRun", on_delete=models.SET_NULL, null=True, blank=True, related_name="commits"
|
|
)
|
|
steward_finding = models.ForeignKey(
|
|
"projects.StewardFinding", on_delete=models.SET_NULL, null=True, blank=True, related_name="commits"
|
|
)
|
|
extension_candidate = models.ForeignKey(
|
|
"projects.ExtensionCandidate", on_delete=models.SET_NULL, null=True, blank=True, related_name="commits"
|
|
)
|
|
evolution_candidate = models.ForeignKey(
|
|
"projects.EvolutionCandidate", on_delete=models.SET_NULL, null=True, blank=True, related_name="commits"
|
|
)
|
|
sha = models.CharField(max_length=64)
|
|
branch_name = models.CharField(max_length=255)
|
|
message = models.TextField()
|
|
|
|
|
|
class TaskAttempt(TimestampedModel):
|
|
task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name="attempts")
|
|
attempt_number = models.PositiveIntegerField()
|
|
coder = models.ForeignKey("agents.AgentVersion", on_delete=models.PROTECT, related_name="task_attempts")
|
|
status = models.CharField(max_length=32, default="RUNNING")
|
|
context_snapshot = models.JSONField(default=dict, blank=True)
|
|
coder_result = models.JSONField(default=dict, blank=True)
|
|
review_findings = models.JSONField(default=list, blank=True)
|
|
judge_findings = models.JSONField(default=list, blank=True)
|
|
|
|
class Meta:
|
|
constraints = [models.UniqueConstraint(fields=["task", "attempt_number"], name="unique_task_attempt")]
|
|
|
|
|
|
class Decision(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="decisions")
|
|
decision_type = models.CharField(max_length=80)
|
|
decision = models.TextField()
|
|
reason = models.TextField(blank=True)
|
|
evidence = models.JSONField(default=list, blank=True)
|
|
project_plan_version = models.PositiveIntegerField(default=0)
|
|
actor = models.CharField(max_length=120)
|
|
|
|
|
|
class Artifact(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="artifacts")
|
|
task = models.ForeignKey(Task, on_delete=models.SET_NULL, null=True, blank=True, related_name="artifacts")
|
|
artifact_type = models.CharField(max_length=80)
|
|
name = models.CharField(max_length=255)
|
|
uri = models.TextField(blank=True)
|
|
content = models.JSONField(default=dict, blank=True)
|
|
generated_by = models.CharField(max_length=120, blank=True)
|
|
|
|
|
|
class RoadmapStatus(models.TextChoices):
|
|
PROPOSED = "PROPOSED"
|
|
ACCEPTED = "ACCEPTED"
|
|
PLANNING = "PLANNING"
|
|
IN_PROGRESS = "IN_PROGRESS"
|
|
COMPLETE = "COMPLETE"
|
|
DEFERRED = "DEFERRED"
|
|
REJECTED = "REJECTED"
|
|
SUPERSEDED = "SUPERSEDED"
|
|
|
|
|
|
class RoadmapHorizon(models.TextChoices):
|
|
NOW = "NOW"
|
|
NEXT = "NEXT"
|
|
LATER = "LATER"
|
|
EXPLORING = "EXPLORING"
|
|
|
|
|
|
class RoadmapTargetAction(models.TextChoices):
|
|
EXTEND = "EXTEND"
|
|
EVOLVE = "EVOLVE"
|
|
REPAIR = "REPAIR"
|
|
INVESTIGATE = "INVESTIGATE"
|
|
NONE = "NONE"
|
|
|
|
|
|
class RoadmapItem(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="roadmap_items")
|
|
title = models.CharField(max_length=200)
|
|
description = models.TextField(blank=True)
|
|
source = models.CharField(max_length=80, default="USER")
|
|
source_ref = models.JSONField(default=dict, blank=True)
|
|
rationale = models.TextField(blank=True)
|
|
evidence = models.JSONField(default=dict, blank=True)
|
|
horizon = models.CharField(max_length=32, choices=RoadmapHorizon.choices, default=RoadmapHorizon.EXPLORING)
|
|
category = models.CharField(max_length=80, blank=True)
|
|
status = models.CharField(max_length=32, choices=RoadmapStatus.choices, default=RoadmapStatus.PROPOSED)
|
|
target_action = models.CharField(max_length=32, choices=RoadmapTargetAction.choices, default=RoadmapTargetAction.NONE)
|
|
priority = models.PositiveSmallIntegerField(default=50)
|
|
value_score = models.FloatField(default=0.5)
|
|
effort_score = models.FloatField(default=0.5)
|
|
risk_score = models.FloatField(default=0.5)
|
|
confidence = models.FloatField(default=0.5)
|
|
strategic_fit = models.FloatField(default=0.5)
|
|
technical_fit = models.FloatField(default=0.5)
|
|
urgency = models.FloatField(default=0.5)
|
|
composite_score = models.FloatField(default=0.5)
|
|
grouping_key = models.CharField(max_length=240, blank=True)
|
|
dependencies = models.ManyToManyField("self", symmetrical=False, blank=True, related_name="dependent_roadmap_items")
|
|
related_items = models.ManyToManyField("self", symmetrical=True, blank=True)
|
|
converted_extension = models.ForeignKey("projects.ExtensionCandidate", on_delete=models.SET_NULL, null=True, blank=True, related_name="converted_from_roadmap_items")
|
|
converted_evolution = models.ForeignKey("projects.EvolutionCandidate", on_delete=models.SET_NULL, null=True, blank=True, related_name="converted_from_roadmap_items")
|
|
converted_investigation = models.ForeignKey("agents.ProgenyInvestigation", on_delete=models.SET_NULL, null=True, blank=True, related_name="converted_from_roadmap_items")
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class Finding(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="findings")
|
|
source = models.CharField(max_length=80)
|
|
finding_type = models.CharField(max_length=80)
|
|
severity = models.CharField(max_length=32, default="INFO")
|
|
title = models.CharField(max_length=255)
|
|
description = models.TextField(blank=True)
|
|
evidence = models.JSONField(default=list, blank=True)
|
|
status = models.CharField(max_length=32, default="OPEN")
|
|
|
|
|
|
class ScenarioSuite(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="scenario_suites")
|
|
name = models.CharField(max_length=200)
|
|
version = models.PositiveIntegerField(default=1)
|
|
purpose = models.TextField(blank=True)
|
|
status = models.CharField(max_length=32, default="DRAFT")
|
|
frozen_at = models.DateTimeField(null=True, blank=True)
|
|
execution_graph_version = models.ForeignKey("graph.ExecutionGraphVersion", on_delete=models.SET_NULL, null=True, blank=True, related_name="scenario_suites")
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class Scenario(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="scenarios", null=True, blank=True)
|
|
suite = models.ForeignKey(ScenarioSuite, on_delete=models.CASCADE, related_name="scenarios", null=True, blank=True)
|
|
name = models.CharField(max_length=200)
|
|
title = models.CharField(max_length=255, blank=True)
|
|
description = models.TextField(blank=True)
|
|
scenario_type = models.CharField(max_length=80, default="WORKFLOW")
|
|
target_component = models.CharField(max_length=240, blank=True)
|
|
target_type = models.CharField(max_length=80)
|
|
target_id = models.CharField(max_length=120)
|
|
preconditions = models.JSONField(default=list, blank=True)
|
|
injected_condition = models.JSONField(default=dict, blank=True)
|
|
expected_invariants = models.JSONField(default=list, blank=True)
|
|
success_criteria = models.JSONField(default=list, blank=True)
|
|
severity = models.CharField(max_length=32, default="MEDIUM")
|
|
source = models.CharField(max_length=80, default="USER")
|
|
definition = models.JSONField(default=dict, blank=True)
|
|
status = models.CharField(max_length=32, default="DRAFT")
|
|
validated_at = models.DateTimeField(null=True, blank=True)
|
|
rejection_reason = models.TextField(blank=True)
|
|
resource_budget = models.JSONField(default=dict, blank=True)
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class ScenarioRun(TimestampedModel):
|
|
scenario = models.ForeignKey(Scenario, on_delete=models.CASCADE, related_name="runs")
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="scenario_runs")
|
|
repository_baseline = models.CharField(max_length=255, blank=True)
|
|
execution_graph_version = models.ForeignKey("graph.ExecutionGraphVersion", on_delete=models.SET_NULL, null=True, blank=True, related_name="scenario_runs")
|
|
graph_run = models.ForeignKey("graph.GraphRun", on_delete=models.SET_NULL, null=True, blank=True, related_name="scenario_runs")
|
|
status = models.CharField(max_length=32, default="PENDING")
|
|
started_at = models.DateTimeField(null=True, blank=True)
|
|
completed_at = models.DateTimeField(null=True, blank=True)
|
|
environment_metadata = models.JSONField(default=dict, blank=True)
|
|
result = models.CharField(max_length=32, blank=True)
|
|
failure_evidence = models.JSONField(default=dict, blank=True)
|
|
telemetry = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class ScenarioFinding(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="scenario_findings")
|
|
scenario = models.ForeignKey(Scenario, on_delete=models.CASCADE, related_name="findings")
|
|
scenario_run = models.ForeignKey(ScenarioRun, on_delete=models.SET_NULL, null=True, blank=True, related_name="findings")
|
|
title = models.CharField(max_length=255)
|
|
summary = models.TextField(blank=True)
|
|
evidence = models.JSONField(default=dict, blank=True)
|
|
severity = models.CharField(max_length=32, default="MEDIUM")
|
|
confidence = models.FloatField(default=0.5)
|
|
affected_component = models.CharField(max_length=240, blank=True)
|
|
failure_category = models.CharField(max_length=80, blank=True)
|
|
recommended_action = models.CharField(max_length=32, default="INVESTIGATE")
|
|
recommended_route = models.CharField(max_length=120, blank=True)
|
|
grouping_key = models.CharField(max_length=240)
|
|
status = models.CharField(max_length=32, default="OPEN")
|
|
roadmap_item = models.ForeignKey(RoadmapItem, on_delete=models.SET_NULL, null=True, blank=True, related_name="scenario_findings")
|
|
steward_policy_metadata = models.JSONField(default=dict, blank=True)
|
|
progeny_signal = models.ForeignKey("agents.ProgenySignal", on_delete=models.SET_NULL, null=True, blank=True, related_name="scenario_findings")
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class StewardPolicy(TimestampedModel):
|
|
name = models.CharField(max_length=200)
|
|
enabled_checks = models.JSONField(default=list, blank=True)
|
|
severity_thresholds = models.JSONField(default=dict, blank=True)
|
|
auto_route_thresholds = models.JSONField(default=dict, blank=True)
|
|
run_cadence = models.JSONField(default=dict, blank=True)
|
|
allowed_repair_scope = models.JSONField(default=dict, blank=True)
|
|
approval_requirements = models.JSONField(default=dict, blank=True)
|
|
ignored_paths = models.JSONField(default=list, blank=True)
|
|
budget_limits = models.JSONField(default=dict, blank=True)
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class StewardEnrollment(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="steward_enrollments")
|
|
status = models.CharField(max_length=32, default="ACTIVE")
|
|
policy = models.ForeignKey(StewardPolicy, on_delete=models.PROTECT, related_name="enrollments")
|
|
enrolled_at = models.DateTimeField(auto_now_add=True)
|
|
last_run_at = models.DateTimeField(null=True, blank=True)
|
|
next_run_at = models.DateTimeField(null=True, blank=True)
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class StewardRun(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="steward_runs")
|
|
enrollment = models.ForeignKey(StewardEnrollment, on_delete=models.CASCADE, related_name="runs")
|
|
execution_graph_version = models.ForeignKey("graph.ExecutionGraphVersion", on_delete=models.SET_NULL, null=True, blank=True, related_name="steward_runs")
|
|
status = models.CharField(max_length=32, default="PENDING")
|
|
started_at = models.DateTimeField(null=True, blank=True)
|
|
completed_at = models.DateTimeField(null=True, blank=True)
|
|
summary = models.TextField(blank=True)
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class StewardCheck(TimestampedModel):
|
|
steward_run = models.ForeignKey(StewardRun, on_delete=models.CASCADE, related_name="checks")
|
|
check_type = models.CharField(max_length=80)
|
|
status = models.CharField(max_length=32)
|
|
evidence = models.JSONField(default=dict, blank=True)
|
|
severity = models.CharField(max_length=32, default="INFO")
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class StewardFinding(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="steward_findings")
|
|
steward_run = models.ForeignKey(StewardRun, on_delete=models.SET_NULL, null=True, blank=True, related_name="findings")
|
|
source_check = models.ForeignKey(StewardCheck, on_delete=models.SET_NULL, null=True, blank=True, related_name="findings")
|
|
finding_type = models.CharField(max_length=80)
|
|
title = models.CharField(max_length=255)
|
|
summary = models.TextField(blank=True)
|
|
evidence = models.JSONField(default=dict, blank=True)
|
|
severity = models.CharField(max_length=32, default="INFO")
|
|
confidence = models.FloatField(default=0.0)
|
|
status = models.CharField(max_length=32, default="OPEN")
|
|
recommended_action = models.CharField(max_length=32, default="INVESTIGATE")
|
|
recommended_route = models.CharField(max_length=120, blank=True)
|
|
grouping_key = models.CharField(max_length=240)
|
|
first_seen = models.DateTimeField(null=True, blank=True)
|
|
last_seen = models.DateTimeField(null=True, blank=True)
|
|
occurrence_count = models.PositiveIntegerField(default=1)
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class StewardAction(TimestampedModel):
|
|
finding = models.ForeignKey(StewardFinding, on_delete=models.CASCADE, related_name="actions")
|
|
action_type = models.CharField(max_length=32)
|
|
status = models.CharField(max_length=32, default="PENDING")
|
|
task = models.ForeignKey(Task, on_delete=models.SET_NULL, null=True, blank=True, related_name="steward_actions")
|
|
roadmap_item = models.ForeignKey(RoadmapItem, on_delete=models.SET_NULL, null=True, blank=True, related_name="steward_actions")
|
|
investigation = models.ForeignKey("agents.ProgenyInvestigation", on_delete=models.SET_NULL, null=True, blank=True, related_name="steward_actions")
|
|
improvement_candidate = models.ForeignKey("agents.ImprovementCandidate", on_delete=models.SET_NULL, null=True, blank=True, related_name="steward_actions")
|
|
extension_candidate = models.ForeignKey("projects.ExtensionCandidate", on_delete=models.SET_NULL, null=True, blank=True, related_name="steward_actions")
|
|
evolution_candidate = models.ForeignKey("projects.EvolutionCandidate", on_delete=models.SET_NULL, null=True, blank=True, related_name="steward_actions")
|
|
requires_approval = models.BooleanField(default=False)
|
|
approved_at = models.DateTimeField(null=True, blank=True)
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class ExtensionCandidate(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="extension_candidates")
|
|
title = models.CharField(max_length=255)
|
|
description = models.TextField(blank=True)
|
|
rationale = models.TextField(blank=True)
|
|
source = models.CharField(max_length=80, default="user")
|
|
expected_value = models.TextField(blank=True)
|
|
affected_areas = models.JSONField(default=list, blank=True)
|
|
estimated_complexity = models.CharField(max_length=80, blank=True)
|
|
risk = models.CharField(max_length=80, default="MEDIUM")
|
|
confidence = models.FloatField(default=0.0)
|
|
status = models.CharField(max_length=32, default="PROPOSED")
|
|
evidence = models.JSONField(default=dict, blank=True)
|
|
source_steward_finding = models.ForeignKey(StewardFinding, on_delete=models.SET_NULL, null=True, blank=True, related_name="extension_candidates")
|
|
source_investigation = models.ForeignKey("agents.ProgenyInvestigation", on_delete=models.SET_NULL, null=True, blank=True, related_name="extension_candidates")
|
|
source_roadmap_item = models.ForeignKey(RoadmapItem, on_delete=models.SET_NULL, null=True, blank=True, related_name="extension_candidates")
|
|
source_opportunity = models.ForeignKey("projects.ExplorationOpportunity", on_delete=models.SET_NULL, null=True, blank=True, related_name="extension_candidates")
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class ExtensionPlan(TimestampedModel):
|
|
candidate = models.ForeignKey(ExtensionCandidate, on_delete=models.CASCADE, related_name="plans")
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="extension_plans")
|
|
status = models.CharField(max_length=32, default="DRAFT")
|
|
strategy = models.TextField(blank=True)
|
|
plan = models.JSONField(default=dict, blank=True)
|
|
acceptance_criteria = models.JSONField(default=list, blank=True)
|
|
context_snapshot = models.JSONField(default=dict, blank=True)
|
|
project_plan = models.ForeignKey(ProjectPlan, on_delete=models.SET_NULL, null=True, blank=True, related_name="extension_plans")
|
|
verification = models.ForeignKey("verification.Verification", on_delete=models.SET_NULL, null=True, blank=True, related_name="extension_plans")
|
|
approved_at = models.DateTimeField(null=True, blank=True)
|
|
completed_at = models.DateTimeField(null=True, blank=True)
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class EvolutionCandidate(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="evolution_candidates")
|
|
target = models.CharField(max_length=240)
|
|
objective = models.TextField()
|
|
baseline_measurement = models.JSONField(default=dict, blank=True)
|
|
desired_direction = models.CharField(max_length=32)
|
|
target_measurement = models.JSONField(default=dict, blank=True)
|
|
rationale = models.TextField(blank=True)
|
|
source = models.CharField(max_length=80, default="user")
|
|
evidence = models.JSONField(default=dict, blank=True)
|
|
status = models.CharField(max_length=32, default="PROPOSED")
|
|
risk = models.CharField(max_length=80, default="MEDIUM")
|
|
confidence = models.FloatField(default=0.0)
|
|
source_steward_finding = models.ForeignKey(StewardFinding, on_delete=models.SET_NULL, null=True, blank=True, related_name="evolution_candidates")
|
|
source_investigation = models.ForeignKey("agents.ProgenyInvestigation", on_delete=models.SET_NULL, null=True, blank=True, related_name="evolution_candidates")
|
|
source_roadmap_item = models.ForeignKey(RoadmapItem, on_delete=models.SET_NULL, null=True, blank=True, related_name="evolution_candidates")
|
|
source_opportunity = models.ForeignKey("projects.ExplorationOpportunity", on_delete=models.SET_NULL, null=True, blank=True, related_name="evolution_candidates")
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class EvolutionPlan(TimestampedModel):
|
|
candidate = models.ForeignKey(EvolutionCandidate, on_delete=models.CASCADE, related_name="plans")
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="evolution_plans")
|
|
status = models.CharField(max_length=32, default="DRAFT")
|
|
baseline = models.JSONField(default=dict, blank=True)
|
|
hypothesis = models.TextField(blank=True)
|
|
intervention = models.TextField(blank=True)
|
|
measurement_method = models.JSONField(default=dict, blank=True)
|
|
success_threshold = models.JSONField(default=dict, blank=True)
|
|
regression_constraints = models.JSONField(default=list, blank=True)
|
|
affected_components = models.JSONField(default=list, blank=True)
|
|
task_plan = models.JSONField(default=dict, blank=True)
|
|
experiment_requirements = models.JSONField(default=dict, blank=True)
|
|
candidate_measurement = models.JSONField(default=dict, blank=True)
|
|
delta = models.JSONField(default=dict, blank=True)
|
|
verdict = models.CharField(max_length=32, blank=True)
|
|
context_snapshot = models.JSONField(default=dict, blank=True)
|
|
project_plan = models.ForeignKey(ProjectPlan, on_delete=models.SET_NULL, null=True, blank=True, related_name="evolution_plans")
|
|
verification = models.ForeignKey("verification.Verification", on_delete=models.SET_NULL, null=True, blank=True, related_name="evolution_plans")
|
|
approved_at = models.DateTimeField(null=True, blank=True)
|
|
completed_at = models.DateTimeField(null=True, blank=True)
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class Exploration(TimestampedModel):
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="explorations")
|
|
source = models.CharField(max_length=80, default="Explorer")
|
|
status = models.CharField(max_length=32, default="RUNNING")
|
|
prompt = models.TextField(blank=True)
|
|
context_snapshot = models.JSONField(default=dict, blank=True)
|
|
execution_graph_version = models.ForeignKey("graph.ExecutionGraphVersion", on_delete=models.SET_NULL, null=True, blank=True, related_name="explorations")
|
|
completed_at = models.DateTimeField(null=True, blank=True)
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
|
|
class ExplorationOpportunity(TimestampedModel):
|
|
exploration = models.ForeignKey(Exploration, on_delete=models.CASCADE, related_name="opportunities")
|
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="exploration_opportunities")
|
|
title = models.CharField(max_length=255)
|
|
description = models.TextField(blank=True)
|
|
opportunity_type = models.CharField(max_length=80)
|
|
evidence = models.JSONField(default=dict, blank=True)
|
|
rationale = models.TextField(blank=True)
|
|
expected_value = models.TextField(blank=True)
|
|
effort_estimate = models.CharField(max_length=80, blank=True)
|
|
risk = models.CharField(max_length=80, default="MEDIUM")
|
|
confidence = models.FloatField(default=0.0)
|
|
technical_fit = models.FloatField(default=0.0)
|
|
strategic_fit = models.FloatField(default=0.0)
|
|
value_score = models.FloatField(default=0.0)
|
|
effort_score = models.FloatField(default=0.0)
|
|
risk_score = models.FloatField(default=0.0)
|
|
composite_score = models.FloatField(default=0.0)
|
|
recommended_action = models.CharField(max_length=32, default="DEFER")
|
|
status = models.CharField(max_length=32, default="DISCOVERED")
|
|
grouping_key = models.CharField(max_length=240)
|
|
converted_extension = models.ForeignKey(ExtensionCandidate, on_delete=models.SET_NULL, null=True, blank=True, related_name="converted_from_opportunities")
|
|
converted_evolution = models.ForeignKey(EvolutionCandidate, on_delete=models.SET_NULL, null=True, blank=True, related_name="converted_from_opportunities")
|
|
metadata = models.JSONField(default=dict, blank=True)
|