Skip to content

Cortex — Task and Decision Effect Lifecycle

This spec adds lifecycle semantics, template governance, and completion validation to Tasks, and pack-level implementation guidance to Decision Effects. The Task (WorkflowTask) schema is documented in §task.fields below; the Effect schema is authoritative in component.cortex.decision-evidence#effect.fields.

The Three Layers

Layer When Objects What Happens Who Acts
A. Deliberation During investigation Blocks, Events, Tasks Evidence gathered, work routed, decisions drafted Analysts, Agents, Reviewers
B. Decision Artifact At sealing Edition (manifest + narrative + attestation) Immutable record created, hash chain locked Author + Attester
C. Execution After attestation Decision Effects Sealed decision dispatched to external systems System, Human Process

Tasks live in Layer A — they produce evidence. Effects live in Layer C — they execute sealed decisions. The Edition (Layer B) is the firewall: nothing crosses from A to C without attestation.

Task Object Model

A Task IS a governance-bound unit of work created from a TaskTemplate; attached to an Investigation (insight_id required); assigned to a role, not a user (workers pull, not push); logged in the append-only Event ledger; optionally producing new Blocks or Editions.

A Task IS NOT a workflow engine (no branching, no conditional routing), a state machine that orchestrates (transitions are validated, not orchestrated), auto-advancing logic (no system-driven changes except SLA timeout), or a replacement for Effects. Architecture guardrail: "Tasks are PUBLISHED → Workers PULL → No SEQUENCE."

Task Schema and Extensions

The WorkflowTask key fields: task_id, task_type, status, assigned_to (OR-logic: roles_any, groups_any, user_id), insight_id, edition_id, summary, priority, due_by, created_by, outcome. The DES core Task object also models schema_version, assignee (type/value), result (outcome, notes, produced_block_ids — required when completed), and created_at.

Task invariants (DES core): tasks are optional (DES requires no task for any lifecycle transition); tasks are non-deterministic (no prescribed ordering/routing/sequencing); task outputs are blocks; attestation requires a human, not a task (a attest-type task is a coordination request — the attestation itself is an event with actor.type = user); agent execution is opaque; task status is descriptive, not gating.

Cortex extensions stored via additionalProperties:

  • template_id — links the task to its governing template for completion validation
  • sla_hours — from template, used to compute due_by
  • origin_event_id — traceability: what event caused this task
  • attached_block_ids — which evidence blocks are provided as context

Task Types and Assignee Types

Task types: review (review an edition before attestation), attest (formally attest a reviewed edition), gather_evidence (collect additional evidence), acknowledge (acknowledge a signal/finding), refresh (re-execute stale evidence blocks). Assignee types: user, role, group, agent.

Task Lifecycle

OPEN ──accept──> IN_PROGRESS ──complete──> COMPLETED
  │                    │
  │                    └──reject──> REJECTED
  └──expire──> EXPIRED ──(generates Signal)
Status Meaning Who Transitions
open Published to queue, awaiting claim System (on create)
in_progress Worker has claimed and started User (explicit accept)
completed Work done, outcome recorded User (after validation)
rejected Worker declined or returned User
expired SLA deadline passed without completion System (SLA engine)

Transition rules: open → in_progress (any user whose roles match assigned_to.roles_any); open/in_progress → expired (system, when now > due_by); in_progress → completed (user, after completion_requirements validation); in_progress → rejected (user, with reason). expired is a system-generated terminal state; implementations without SLA engines skip it. Task state machines are descriptive, not prescriptive — DES does not gate investigation/edition lifecycle on task status; implementations MAY enforce task-gating via accountability constraints.

Event Ledger Integration

Every transition appends an event to the investigation's ledger (event taxonomy in component.cortex.decision-evidence#event):

Event Type Status Transition Payload
task_created open {task_id, task_type, template_id, assigned_to, attached_block_ids}
task_accepted open → in_progress {task_id, accepted_by}
task_completed in_progress → completed {task_id, outcome, completion_note}
task_rejected in_progress → rejected {task_id, rejection_reason}
task_expired → expired {task_id, sla_hours, due_by}

task_created and task_completed are DES Level 2 core events. task_accepted, task_rejected, task_expired are Level 3 (full audit trail). All task events are append-only via _append_event().

Task Outputs Are Blocks

When a task produces meaningful work, that work MUST be captured as Blocks. An agent assigned gather_evidence executes queries, produces Blocks, and completes with result.produced_block_ids referencing them. The blocks are the evidence; the task is the coordination record. Agent execution is opaque — DES records what blocks were produced, not agent reasoning.

Task Templates

Task templates are pack-level configuration owned by the Governance Manager. They define runtime validation rules, not workflow logic. They inherit defaults from _base/task_templates.yaml. Schema in component.cortex.pack-reference; template defaults in component.cortex.domain-loading.

templates:
  - template_id: tmpl_task_risk_review_v1
    name: Risk Review Request
    task_type: review
    routing_rules: { assignee_role: role-risk, priority_default: high, sla_hours: 48, escalation_after_hours: 72 }
    required_context: { minimum_pinned_blocks: 1 }
    completion_requirements: { must_create_edition: true, minimum_new_blocks: 1 }

Template Fields

Field Purpose
template_id Unique id, referenced by accountability pack
task_type Coarse task category (routing + Inbox UI)
routing_rules.assignee_role Default role assignment
routing_rules.priority_default Default priority
routing_rules.sla_hours SLA deadline (hours from creation), used for due_by
routing_rules.escalation_after_hours When to escalate if not completed
required_context.insight_id Task must be linked to an investigation
required_context.edition_id Task must reference an edition
required_context.minimum_pinned_blocks Minimum evidence before task creation
required_context.description_required Summary field mandatory
completion_requirements.must_add_evidence Worker must pin ≥1 new block
completion_requirements.must_create_edition Worker must create an edition
completion_requirements.minimum_new_blocks Minimum new blocks during task
completion_requirements.must_attest Edition must be attested to close task
completion_requirements.minimum_attesters Minimum attestation count

Resolution Chain

User creates task → Cortex loads Profile → Profile references accountability_id
  → Accountability pack has task_template_ids: { review: tmpl_task_risk_review_v1 }
  → Cortex loads template from ES/Redis cache → routing_rules + required_context + completion_requirements
  → Task enriched with template defaults → required_context checked before creation
  → completion_requirements checked before close

TheBank Task Templates

Template Task Type Routes To SLA Completion Requires
tmpl_task_risk_review_v1 review RISK_MANAGER 48h 1 new block + edition
tmpl_task_treasury_review_v1 review TREASURY_ANALYST 72h 1 new block
tmpl_task_committee_review_v1 committee_review COMMITTEE 120h Attestation (2 attesters)

Task Creation Triggers

Explicit User Action (Primary)

User clicks "Request Review" in Beacon → Beacon reads accountability pack → shows task type picker → Cortex create_task(). Accountability gate: the pack must contain task_template_ids for the requested task_type, else 403 TASK_TEMPLATE_NOT_AUTHORIZED. Routing gate: assignee_role must match the pack's review_routing.default_reviewers.roles_any, else 403 ROUTING_NOT_AUTHORIZED.

Decision Template Effect (Post-Attestation)

A decision template may declare an effect of type task_creation:

effects:
  - type: task_creation
    template_id: tmpl_task_committee_review_v1
    condition: "decision_type == 'escalation'"

This bridges Tasks (Layer A) and Effects (Layer C): the attested edition triggers a new task via create_task() with actor.type: system and origin_event_id pointing to the attested event.

SLA Breach Escalation (System-Generated)

When a task expires, the system MAY generate a task_sla_breach Signal (source.type: system, system_id: cortex-sla-engine, severity: high, subject: {type: task, id: ...}). This signal enters the standard OODA flow, creating a self-healing governance loop: Signal → Task → Signal. System signals carry no source_model (see component.cortex.signal-lifecycle#sources.system).

Task Completion Validation

When complete_task() is called, Cortex MUST validate against the governing template before accepting completion.

Validation rules (against template.completion_requirements): must_add_evidence → count blocks added since origin_event_id ≥ 1, else COMPLETION_REQUIRES_EVIDENCE; minimum_new_blocks → blocks added ≥ N, else COMPLETION_REQUIRES_{N}_BLOCKS; must_create_edition → insight has ≥1 edition, else COMPLETION_REQUIRES_EDITION; must_attest → at least one edition attested, else COMPLETION_REQUIRES_ATTESTATION; minimum_attesters → attester count ≥ N, else COMPLETION_REQUIRES_{N}_ATTESTERS.

On failure → 409 with structured error {error: TASK_COMPLETION_REQUIREMENTS_NOT_MET, message, unmet_requirements[], template_id}. No silent success, no partial completion — the worker must fulfill all requirements or the task stays in_progress.

Task ↔ Accountability Pack Interaction

Accountability Field Task Behavior
task_template_ids Which task types this role can create
review_routing.default_reviewers Who tasks route to
review_routing.escalation_path Escalation chain
guardrails.minimum_evidence_count Minimum evidence before task creation
attestation.separation_of_duties Attester ≠ author on editions produced by tasks

Tasks cannot bypass governance: minimum-evidence requirements apply before task creation; editions created during a task still pass separation-of-duties at attestation; the worker's pack constrains which decision_type they can produce.

Task ↔ Evidence Interaction

Key rule: Tasks NEVER freeze evidence. Tasks may create blocks (block_created), pin blocks (block_pinned), draft editions (edition_created), and request review (review_requested). Tasks cannot freeze blocks (only edition submission/attestation freezes), attest editions (attestation is role-gated, not task-gated), or modify frozen blocks.

Task ↔ Investigation Lifecycle

Tasks do NOT change investigation lifecycle automatically. RM creates task / Risk Manager claims / adds blocks / creates edition — the investigation stays ACTIVE throughout. Only attesting an edition may close the investigation (if the last signal resolves). Tasks support decisions; they do not define them. Investigation status is driven by edition and signal lifecycle, not task lifecycle (see component.cortex.investigation-lifecycle#states.drivers).

Decision Effects

Decision Effects are Layer C — post-attestation execution. The Effect object model, types, lifecycle, timeout/escalation, and federated verification are authoritative in component.cortex.decision-evidence#effect. This section adds pack-level declaration syntax and implementation guidance.

Effect Declaration in Decision Templates

Effects are declared in decision template YAML (schema in component.cortex.pack-reference#decision-template):

templates:
  - template_id: tmpl_credit_review_action_v1
    effects:
      - type: external_routing
        target: credit_committee_queue
        condition: "exposure > 5000000"
      - type: notification
        channel: email
        recipients: { roles_any: [RISK_MANAGER] }
      - type: task_creation
        template_id: tmpl_task_committee_review_v1
        condition: "decision_type == 'escalation'"

Pack type → DES effect_type Mapping

DES Effect Type Pack Equivalent Description
external_dispatch external_routing, webhook Route to external system
notification notification Email, webhook, or message — no completion expected
human_process task_creation Create a new task for human action

Effects CREATE Tasks (One-Way)

Attested Edition
    ├── Effect: external_routing → Core Banking System
    ├── Effect: notification → Email to Risk Manager
    └── Effect: task_creation → Committee Review Task → New Task (Layer A)

One-way rule: Effects can create tasks. Tasks cannot create effects. The Edition is the firewall.

SLA Engine (Future — Not Yet Implemented)

A periodic process (cron or background worker) queries tasks with status IN (open, in_progress) and due_by < now; for each overdue task sets status = expired, appends task_expired, and optionally generates a task_sla_breach Signal. The governance loop: Signal → Investigation → Task → (SLA breach) → Signal → new Investigation. Self-healing governance with no human intervention to escalate overdue work. Recommended deployment: background worker in the Cortex process.

Pack Author Guide

Adding a task template: define it in <domain>/task_templates.yaml; reference it in <domain>/accountability.yaml under insights.task_template_ids; cross-validate every task_template_ids value exists. Adding a decision effect: add an effects: array to the decision template in <domain>/decision_templates.yaml; each effect needs type, target (or template_id for task_creation), optional condition; effects are evaluated post-attestation and don't block edition creation. Task templates inherit _base defaults (required_context.insight_id: true, required_context.description_required: true, completion_requirements.must_add_evidence: true); domain templates override only what differs; explicit null removes a base value.

Implementation Status

What exists today: WorkflowTask model; create_task() (partially template-aware); complete_task() (NO completion validation); list_tasks_for_user(); update_task_status() (no transition validation); task template resolution (accountability → template_id → ES); template enrichment (routing + SLA applied; context/completion NOT validated); _TaskTemplateClient. NOT implemented: completion validation, SLA engine, Decision Effects (Effect event types are defined in the DES schema but not wired in Cortex).

What's missing (priority order):

ID Gap Priority
T1 Completion validation in complete_task() P1 — demo correctness
T2 Task creation precondition validation (minimum_pinned_blocks, etc.) P1 — demo correctness
T3 Status transition validation (prevent open→completed skip) P2 — correctness
T4 task_accepted event type on status change P2 — audit trail
T5 task_expired status + SLA engine P3 — production
T6 task_sla_breach signal generation P3 — production
E1 Effect object model (DecisionEffect model) P4
E2 Effect creation from decision template effects[] P4
E3 Effect lifecycle events (effect_created, etc.) P4
E4 Effect timeout → Signal generation P4

Depends on: component.cortex.decision-evidence, component.cortex.pack-reference

Realizes: product.task

Required by: component.conduit.effect-engine